clean sync class
This commit is contained in:
parent
da1feef746
commit
1b11162522
|
@ -30,13 +30,6 @@ DEVICES_ALLOW_DUPLICITY = [
|
||||||
'GraphicCard',
|
'GraphicCard',
|
||||||
]
|
]
|
||||||
|
|
||||||
err_motherboard = "Error: We have detected that a there is a device"
|
|
||||||
err_motherboard += " in your inventory with this system UUID. "
|
|
||||||
err_motherboard += "We proceed to block this snapshot to prevent its"
|
|
||||||
err_motherboard += " information from being updated incorrectly."
|
|
||||||
err_motherboard += " The solution we offer you to inventory this device "
|
|
||||||
err_motherboard += "is to do it by creating a placeholder."
|
|
||||||
|
|
||||||
|
|
||||||
class Sync:
|
class Sync:
|
||||||
"""Synchronizes the device and components with the database."""
|
"""Synchronizes the device and components with the database."""
|
||||||
|
@ -74,18 +67,10 @@ class Sync:
|
||||||
of the passed-in components.
|
of the passed-in components.
|
||||||
2. A list of Add / Remove (not yet added to session).
|
2. A list of Add / Remove (not yet added to session).
|
||||||
"""
|
"""
|
||||||
|
device.components = OrderedSet(components)
|
||||||
|
device.set_hid()
|
||||||
|
device.components = OrderedSet()
|
||||||
db_device = self.execute_register(device)
|
db_device = self.execute_register(device)
|
||||||
motherboard = None
|
|
||||||
if components:
|
|
||||||
for c in components:
|
|
||||||
if c.type == "Motherboard":
|
|
||||||
motherboard = c
|
|
||||||
|
|
||||||
if motherboard:
|
|
||||||
for c in db_device.components:
|
|
||||||
if c.type == "Motherboard" and motherboard.hid != c.hid:
|
|
||||||
# import pdb; pdb.set_trace()
|
|
||||||
raise ValidationError(err_motherboard)
|
|
||||||
|
|
||||||
db_components, actions = OrderedSet(), OrderedSet()
|
db_components, actions = OrderedSet(), OrderedSet()
|
||||||
if components is not None: # We have component info (see above)
|
if components is not None: # We have component info (see above)
|
||||||
|
@ -93,12 +78,9 @@ class Sync:
|
||||||
# Until a good reason is given, we synthetically forbid
|
# Until a good reason is given, we synthetically forbid
|
||||||
# non-computers with components
|
# non-computers with components
|
||||||
raise ValidationError('Only computers can have components.')
|
raise ValidationError('Only computers can have components.')
|
||||||
blacklist = set() # type: Set[int]
|
|
||||||
not_new_components = set()
|
not_new_components = set()
|
||||||
for component in components:
|
for component in components:
|
||||||
db_component, is_new = self.execute_register_component(
|
db_component, is_new = self.execute_register_component(component)
|
||||||
component, blacklist, parent=db_device
|
|
||||||
)
|
|
||||||
db_components.add(db_component)
|
db_components.add(db_component)
|
||||||
if not is_new:
|
if not is_new:
|
||||||
not_new_components.add(db_component)
|
not_new_components.add(db_component)
|
||||||
|
@ -109,9 +91,7 @@ class Sync:
|
||||||
self.create_placeholder(db_device)
|
self.create_placeholder(db_device)
|
||||||
return db_device, actions
|
return db_device, actions
|
||||||
|
|
||||||
def execute_register_component(
|
def execute_register_component(self, component: Component):
|
||||||
self, component: Component, blacklist: Set[int], parent: Computer
|
|
||||||
):
|
|
||||||
"""Synchronizes one component to the DB.
|
"""Synchronizes one component to the DB.
|
||||||
|
|
||||||
This method is a specialization of :meth:`.execute_register`
|
This method is a specialization of :meth:`.execute_register`
|
||||||
|
@ -141,30 +121,18 @@ class Sync:
|
||||||
is_new = True
|
is_new = True
|
||||||
return component, is_new
|
return component, is_new
|
||||||
|
|
||||||
# if not, then continue with the traditional behaviour
|
|
||||||
try:
|
|
||||||
if component.hid:
|
if component.hid:
|
||||||
db_component = Device.query.filter_by(
|
db_component = Device.query.filter_by(
|
||||||
hid=component.hid, owner_id=g.user.id, placeholder=None
|
hid=component.hid, owner_id=g.user.id, placeholder=None
|
||||||
).one()
|
).first()
|
||||||
assert isinstance(
|
assert isinstance(db_component, Device), '{} must be a component'.format(
|
||||||
db_component, Device
|
db_component
|
||||||
), '{} must be a component'.format(db_component)
|
)
|
||||||
|
is_new = False
|
||||||
else:
|
else:
|
||||||
# Is there a component similar to ours?
|
|
||||||
db_component = component.similar_one(parent, blacklist)
|
|
||||||
# We blacklist this component so we
|
|
||||||
# ensure we don't get it again for another component
|
|
||||||
# with the same physical properties
|
|
||||||
blacklist.add(db_component.id)
|
|
||||||
except ResourceNotFound:
|
|
||||||
db.session.add(component)
|
db.session.add(component)
|
||||||
# db.session.flush()
|
|
||||||
db_component = component
|
db_component = component
|
||||||
is_new = True
|
is_new = True
|
||||||
else:
|
|
||||||
self.merge(component, db_component)
|
|
||||||
is_new = False
|
|
||||||
return db_component, is_new
|
return db_component, is_new
|
||||||
|
|
||||||
def execute_register(self, device: Device) -> Device:
|
def execute_register(self, device: Device) -> Device:
|
||||||
|
@ -194,53 +162,15 @@ class Sync:
|
||||||
:raise DatabaseError: Any other error from the DB.
|
:raise DatabaseError: Any other error from the DB.
|
||||||
:return: The synced device from the db with the tags linked.
|
:return: The synced device from the db with the tags linked.
|
||||||
"""
|
"""
|
||||||
assert inspect(device).transient, 'Device cannot be already synced from DB'
|
|
||||||
assert all(
|
|
||||||
inspect(tag).transient for tag in device.tags
|
|
||||||
), 'Tags cannot be synced from DB'
|
|
||||||
db_device = device.get_from_db()
|
db_device = device.get_from_db()
|
||||||
|
|
||||||
if db_device and db_device.allocated:
|
if db_device and db_device.allocated:
|
||||||
raise ResourceNotFound('device is actually allocated {}'.format(device))
|
raise ResourceNotFound('device is actually allocated {}'.format(device))
|
||||||
|
|
||||||
try:
|
if not db_device:
|
||||||
tags = {
|
|
||||||
Tag.from_an_id(tag.id).one() for tag in device.tags
|
|
||||||
} # type: Set[Tag]
|
|
||||||
except ResourceNotFound:
|
|
||||||
raise ResourceNotFound('tag you are linking to device {}'.format(device))
|
|
||||||
linked_tags = {tag for tag in tags if tag.device_id} # type: Set[Tag]
|
|
||||||
if linked_tags:
|
|
||||||
sample_tag = next(iter(linked_tags))
|
|
||||||
for tag in linked_tags:
|
|
||||||
if tag.device_id != sample_tag.device_id:
|
|
||||||
raise MismatchBetweenTags(
|
|
||||||
tag, sample_tag
|
|
||||||
) # Tags linked to different devices
|
|
||||||
if db_device: # Device from hid
|
|
||||||
if (
|
|
||||||
sample_tag.device_id != db_device.id
|
|
||||||
): # Device from hid != device from tags
|
|
||||||
raise MismatchBetweenTagsAndHid(db_device.id, db_device.hid)
|
|
||||||
else: # There was no device from hid
|
|
||||||
if sample_tag.device.physical_properties != device.physical_properties:
|
|
||||||
# Incoming physical props of device != props from tag's device
|
|
||||||
# which means that the devices are not the same
|
|
||||||
raise MismatchBetweenProperties(
|
|
||||||
sample_tag.device.physical_properties,
|
|
||||||
device.physical_properties,
|
|
||||||
)
|
|
||||||
db_device = sample_tag.device
|
|
||||||
|
|
||||||
if db_device: # Device from hid or tags
|
|
||||||
self.merge(device, db_device)
|
|
||||||
else: # Device is new and tags are not linked to a device
|
|
||||||
device.tags.clear() # We don't want to add the transient dummy tags
|
device.tags.clear() # We don't want to add the transient dummy tags
|
||||||
db.session.add(device)
|
db.session.add(device)
|
||||||
db_device = device
|
db_device = device
|
||||||
db_device.tags |= (
|
|
||||||
tags # Union of tags the device had plus the (potentially) new ones
|
|
||||||
)
|
|
||||||
try:
|
try:
|
||||||
db.session.flush()
|
db.session.flush()
|
||||||
except IntegrityError as e:
|
except IntegrityError as e:
|
||||||
|
@ -258,29 +188,6 @@ class Sync:
|
||||||
assert db_device is not None
|
assert db_device is not None
|
||||||
return db_device
|
return db_device
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def merge(device: Device, db_device: Device):
|
|
||||||
"""Copies the physical properties of the device to the db_device.
|
|
||||||
|
|
||||||
This method mutates db_device.
|
|
||||||
"""
|
|
||||||
if db_device.owner_id != g.user.id:
|
|
||||||
return
|
|
||||||
|
|
||||||
if device.placeholder and not db_device.placeholder:
|
|
||||||
return
|
|
||||||
|
|
||||||
for field_name, value in device.physical_properties.items():
|
|
||||||
if value is not None:
|
|
||||||
setattr(db_device, field_name, value)
|
|
||||||
|
|
||||||
# if device.system_uuid and db_device.system_uuid and device.system_uuid != db_device.system_uuid:
|
|
||||||
# TODO @cayop send error to sentry.io
|
|
||||||
# there are 2 computers duplicate get db_device for hid
|
|
||||||
|
|
||||||
if hasattr(device, 'system_uuid') and device.system_uuid:
|
|
||||||
db_device.system_uuid = device.system_uuid
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_placeholder(device: Device):
|
def create_placeholder(device: Device):
|
||||||
"""If the device is new, we need create automaticaly a new placeholder"""
|
"""If the device is new, we need create automaticaly a new placeholder"""
|
||||||
|
|
Reference in New Issue