def _get_or_create_model_for_component( model_type, component_data, field_map, forbidden_model_fields=set(), save_priority=SAVE_PRIORITY, ): """ For concrete component type try to save or reuse instance of Component using field_map and list of fields to save. Field_map maps from component fields to database fields. Some of the fields are forbidden to save for given component type, for example field name is forbidden in Storage Component. :param model_type: If provided, a 'model' field will be added :param component_data: list of dicts describing the components :param field_map: mapping from database fields to component_data keys :param forbidden_model_fields: If provided, model will be created without those fields :param save_priority: Save priority """ model_fields = { field: component_data[field_map[field]] for field in field_map if all(( component_data.get(field_map[field]), field != 'type', field not in forbidden_model_fields, )) } if all(( 'model_name' in component_data, 'name' not in forbidden_model_fields, )): model_fields['name'] = component_data['model_name'] if model_type == ComponentType.software: path = model_fields.get('path') family = model_fields.get('family') if path and not family: model_fields['family'] = path if 'family' in model_fields: model_fields['family'] = model_fields.get('family', '')[:128] model, created = ComponentModel.create( model_type, save_priority, **model_fields) return model
def setUp(self): self.client = login_as_su() venture = Venture(name=DEVICE['venture'], symbol=DEVICE['ventureSymbol']) venture.save() self.venture = venture venture_role = VentureRole(name=DEVICE['venture_role'], venture=self.venture) venture_role.save() self.venture_role = venture_role self.device = Device.create( sn=DEVICE['sn'], barcode=DEVICE['barcode'], remarks=DEVICE['remarks'], model_name=DEVICE['model_name'], model_type=DeviceType.unknown, venture=self.venture, venture_role=self.venture_role, rack=DEVICE['rack'], position=DEVICE['position'], dc=DATACENTER, ) self.device.name = DEVICE['name'] self.device.save() self.ip = IPAddress(address=DEVICE['ip'], device=self.device) self.ip.save() self.db_ip = IPAddress.objects.get(address=DEVICE['ip']) self.network_terminator = NetworkTerminator(name='simple_terminator') self.network_terminator.save() self.network_datacenter = DataCenter(name=DATACENTER) self.network_datacenter.save() self.network = Network( name=NETWORK['name'], address=NETWORK['address'], data_center=self.network_datacenter, ) self.diskshare_device = Device.create( sn=DISKSHARE['sn'], barcode=DISKSHARE['barcode'], model_name='xxx', model_type=DeviceType.storage, ) self.diskshare_device.name = DISKSHARE['device'] self.diskshare_device.save() self.cm_generic = ComponentModel(name='GenericModel') self.cm_diskshare = ComponentModel(name='DiskShareModel') self.cm_processor = ComponentModel(name='ProcessorModel') self.cm_memory = ComponentModel(name='MemoryModel') self.cm_storage = ComponentModel(name='ComponentModel') self.cm_fibre = ComponentModel(name='FibreChannalMidel') self.cm_ethernet = ComponentModel(name='EthernetMidel') self.cm_software = ComponentModel(name='SoftwareModel') self.cm_splunkusage = ComponentModel(name='SplunkusageModel') self.cm_operatingsystem = ComponentModel(name='OperatingSystemModel') self.generic_component = GenericComponent( device=self.device, model=self.cm_generic, label=COMPONENT['GenericComponent'], sn=GENERIC['sn'], ) self.generic_component.save() self.diskshare = DiskShare( device=self.device, model=self.cm_diskshare, share_id=self.device.id, size=80, wwn=DISKSHARE['wwn'], ) self.diskshare.save() self.disksharemount = DiskShareMount.concurrent_get_or_create( share=self.diskshare, device=self.device, volume=COMPONENT['DiskShareMount'], ) self.processor = Processor( device=self.device, model=self.cm_processor, label=COMPONENT['Processor'], ) self.processor.save() self.memory = Memory( device=self.device, model=self.cm_memory, label=COMPONENT['Memory'], ) self.memory.save() self.storage = Storage( device=self.device, model=self.cm_storage, label=COMPONENT['Storage'], ) self.storage.save() self.fibrechannel = FibreChannel( device=self.device, model=self.cm_fibre, label=COMPONENT['Fibre'], physical_id='01234', ) self.fibrechannel.save() self.ethernet = Ethernet( model=self.cm_ethernet, device=self.device, mac=DEVICE['mac'], ) self.ethernet.save() self.software = Software( device=self.device, model=self.cm_software, label=COMPONENT['Software'], ) self.software.save() self.splunkusage = SplunkUsage( device=self.device, model=self.cm_splunkusage, ) self.splunkusage.save() self.operatingsystem = OperatingSystem( device=self.device, model=self.cm_operatingsystem, label=COMPONENT['OS'], ) self.operatingsystem.save()
def _update_component_data( device, component_data, Component, field_map, unique_fields, model_type=None, forbidden_model_fields=set(), ): """ Update components of a device based on the data from scan. This function is a little tricky, because we want to reuse the components as much as possible, instead of deleting everything and creating new ones every time. :param component_data: list of dicts describing the components :param Component: model to use to query and create components :param field_map: mapping from database fields to component_data keys :param unique_fields: list of tuples of fields that are unique together :param model_type: If provided, a 'model' field will be added :param forbidden_model_fields: If provided, model will be created without those fields """ component_ids = [] for index, data in enumerate(component_data): data['device'] = device data['index'] = index for group in unique_fields: # First try to find an existing component using unique fields fields = { field: data[field_map[field]] for field in group if data.get(field_map[field]) is not None } if len(group) != len(fields): continue try: component = Component.objects.get(**fields) except Component.DoesNotExist: continue break else: # No matching component found, create a new one if model_type is not None or 'type' in data: # If model_type is provided, create the model model = None if model_type is None: try: model_type = ComponentType.from_name(data['type']) except ValueError: model_type = None if model_type is not None: model_fields = { field: data[field_map[field]] for field in field_map if all(( data.get(field_map[field]), field != 'type', field not in forbidden_model_fields, )) } if all(( 'model_name' in data, 'name' not in forbidden_model_fields, )): model_fields['name'] = data['model_name'] model, created = ComponentModel.create( model_type, 0, **model_fields) if model is None: raise ValueError('Unknown model') component = Component(model=model) else: component = Component() # Fill the component with values from the data dict for field, key in field_map.iteritems(): if key in data: setattr(component, field, data[key]) component.save(priority=100) component_ids.append(component.id) # Delete the components that are no longer current for component in Component.objects.filter( device=device, ).exclude( id__in=component_ids, ): component.delete()