clean sync class
This commit is contained in:
parent
da1feef746
commit
1b11162522
|
@ -30,13 +30,6 @@ DEVICES_ALLOW_DUPLICITY = [
|
|||
'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:
|
||||
"""Synchronizes the device and components with the database."""
|
||||
|
@ -74,18 +67,10 @@ class Sync:
|
|||
of the passed-in components.
|
||||
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)
|
||||
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()
|
||||
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
|
||||
# non-computers with components
|
||||
raise ValidationError('Only computers can have components.')
|
||||
blacklist = set() # type: Set[int]
|
||||
not_new_components = set()
|
||||
for component in components:
|
||||
db_component, is_new = self.execute_register_component(
|
||||
component, blacklist, parent=db_device
|
||||
)
|
||||
db_component, is_new = self.execute_register_component(component)
|
||||
db_components.add(db_component)
|
||||
if not is_new:
|
||||
not_new_components.add(db_component)
|
||||
|
@ -109,9 +91,7 @@ class Sync:
|
|||
self.create_placeholder(db_device)
|
||||
return db_device, actions
|
||||
|
||||
def execute_register_component(
|
||||
self, component: Component, blacklist: Set[int], parent: Computer
|
||||
):
|
||||
def execute_register_component(self, component: Component):
|
||||
"""Synchronizes one component to the DB.
|
||||
|
||||
This method is a specialization of :meth:`.execute_register`
|
||||
|
@ -141,30 +121,18 @@ class Sync:
|
|||
is_new = True
|
||||
return component, is_new
|
||||
|
||||
# if not, then continue with the traditional behaviour
|
||||
try:
|
||||
if component.hid:
|
||||
db_component = Device.query.filter_by(
|
||||
hid=component.hid, owner_id=g.user.id, placeholder=None
|
||||
).one()
|
||||
assert isinstance(
|
||||
db_component, Device
|
||||
), '{} must be a component'.format(db_component)
|
||||
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:
|
||||
if component.hid:
|
||||
db_component = Device.query.filter_by(
|
||||
hid=component.hid, owner_id=g.user.id, placeholder=None
|
||||
).first()
|
||||
assert isinstance(db_component, Device), '{} must be a component'.format(
|
||||
db_component
|
||||
)
|
||||
is_new = False
|
||||
else:
|
||||
db.session.add(component)
|
||||
# db.session.flush()
|
||||
db_component = component
|
||||
is_new = True
|
||||
else:
|
||||
self.merge(component, db_component)
|
||||
is_new = False
|
||||
return db_component, is_new
|
||||
|
||||
def execute_register(self, device: Device) -> Device:
|
||||
|
@ -194,53 +162,15 @@ class Sync:
|
|||
:raise DatabaseError: Any other error from the DB.
|
||||
: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()
|
||||
|
||||
if db_device and db_device.allocated:
|
||||
raise ResourceNotFound('device is actually allocated {}'.format(device))
|
||||
|
||||
try:
|
||||
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
|
||||
if not db_device:
|
||||
device.tags.clear() # We don't want to add the transient dummy tags
|
||||
db.session.add(device)
|
||||
db_device = device
|
||||
db_device.tags |= (
|
||||
tags # Union of tags the device had plus the (potentially) new ones
|
||||
)
|
||||
try:
|
||||
db.session.flush()
|
||||
except IntegrityError as e:
|
||||
|
@ -258,29 +188,6 @@ class Sync:
|
|||
assert db_device is not None
|
||||
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
|
||||
def create_placeholder(device: Device):
|
||||
"""If the device is new, we need create automaticaly a new placeholder"""
|
||||
|
|
Reference in a new issue