class MyObj(base.CyborgPersistentObject, base.CyborgObject, base.CyborgObjectDictCompat): VERSION = '1.6' fields = { 'foo': fields.IntegerField(default=1), 'bar': fields.StringField(), 'missing': fields.StringField(), 'readonly': fields.IntegerField(read_only=True), 'rel_object': fields.ObjectField('MyOwnedObject', nullable=True), 'rel_objects': fields.ListOfObjectsField('MyOwnedObject', nullable=True), 'mutable_default': fields.ListOfStringsField(default=[]), } @staticmethod def _from_db_object(context, obj, db_obj): self = MyObj() self.foo = db_obj['foo'] self.bar = db_obj['bar'] self.missing = db_obj['missing'] self.readonly = 1 self._context = context return self def obj_load_attr(self, attrname): setattr(self, attrname, 'loaded!') def query(cls, context): obj = cls(context=context, foo=1, bar='bar') obj.obj_reset_changes() return obj def marco(self): return 'polo' def _update_test(self): self.bar = 'updated' def save(self): self.obj_reset_changes() def refresh(self): self.foo = 321 self.bar = 'refreshed' self.obj_reset_changes() def modify_save_modify(self): self.bar = 'meow' self.save() self.foo = 42 self.rel_object = MyOwnedObject(baz=42) def obj_make_compatible(self, primitive, target_version): super(MyObj, self).obj_make_compatible(primitive, target_version) # NOTE(danms): Simulate an older version that had a different # format for the 'bar' attribute if target_version == '1.1' and 'bar' in primitive: primitive['bar'] = 'old%s' % primitive['bar']
class DriverDevice(base.DriverObjectBase, object_base.VersionedObjectDictCompat): # Version 1.0: Initial version VERSION = '1.0' fields = { 'vendor': object_fields.StringField(nullable=False), 'model': object_fields.StringField(nullable=False), 'type': object_fields.DeviceTypeField(nullable=False), 'std_board_info': object_fields.StringField(nullable=True), # vendor board info should be a dict for driver-specific resource # provider. 'vendor_board_info': object_fields.StringField(nullable=True), # hostname will be set by the agent, so driver don't need to report. # Each controlpath_id corresponds to a different PF. For now # we are sticking with a single cpid. 'controlpath_id': object_fields.ObjectField('DriverControlPathID', nullable=False), 'deployable_list': object_fields.ListOfObjectsField('DriverDeployable', default=[], nullable=False) } def create(self, context, host): """Create a driver-side Device Object into DB. This object will be stored in many db tables: device, deployable, attach_handle, controlpath_id etc. by calling related Object.""" # first store in device table through Device Object. device_obj = Device(context=context, type=self.type, vendor=self.vendor, model=self.model, hostname=host ) if hasattr(self, 'std_board_info'): device_obj.std_board_info = self.std_board_info if hasattr(self, 'vendor_board_info'): device_obj.vendor_board_info = self.vendor_board_info device_obj.create(context) # for the controlpath_id, call driver_controlpath_id to create. cpid_obj = self.controlpath_id.create(context, device_obj.id) # for deployable_list, call internal layer object: driver_deployable # to create. for driver_deployable in self.deployable_list: driver_deployable.create(context, device_obj.id, cpid_obj.id) def destroy(self, context, host): """Delete a driver-side Device Object from db. This should delete the internal layer objects.""" # get dev_obj_list from hostname device_obj = self.get_device_obj(context, host) if hasattr(self.controlpath_id, 'cpid_info'): cpid_obj = ControlpathID.get_by_device_id_cpidinfo( context, device_obj.id, self.controlpath_id.cpid_info) # delete controlpath_id cpid_obj.destroy(context) # delete deployable_list first. for driver_deployable in self.deployable_list: driver_deployable.destroy(context, device_obj.id) # delete the device device_obj.destroy(context) def get_device_obj(self, context, host): """ :param context: requested context. :param host: hostname of the node. :return: a device object of current driver device object. It will return on value because it has controlpath_id. """ # get dev_obj_list from hostname device_obj_list = Device.get_list_by_hostname(context, host) # use controlpath_id.cpid_info to identiy one Device. for device_obj in device_obj_list: # get cpid_obj, could be empty or only one value. cpid_obj = ControlpathID.get_by_device_id_cpidinfo( context, device_obj.id, self.controlpath_id.cpid_info) # find the one cpid_obj with cpid_info if cpid_obj is not None: return device_obj @classmethod def list(cls, context, host): """Form driver-side device object list from DB for one host. A list may contains driver_device_object without controlpath_id.(In the case some of controlpath_id can't store successfully but its devices stores successfully. )""" # get dev_obj_list from hostname dev_obj_list = Device.get_list_by_hostname(context, host) driver_dev_obj_list = [] for dev_obj in dev_obj_list: cpid = DriverControlPathID.get(context, dev_obj.id) # NOTE: will not return device without controlpath_id. if cpid is not None: driver_dev_obj = \ cls(context=context, vendor=dev_obj.vendor, model=dev_obj.model, type=dev_obj.type, std_board_info=dev_obj.std_board_info, vendor_board_info=dev_obj.vendor_board_info, controlpath_id=cpid, deployable_list=DriverDeployable.list(context, dev_obj.id) ) driver_dev_obj_list.append(driver_dev_obj) return driver_dev_obj_list
class MyList(base.ObjectListBase, base.CyborgObject): fields = {'objects': fields.ListOfObjectsField('MyObj')}
class DriverDeployable(base.DriverObjectBase, object_base.VersionedObjectDictCompat): # Version 1.0: Initial version VERSION = '1.0' fields = { 'name': object_fields.StringField(nullable=False), 'num_accelerators': object_fields.IntegerField(nullable=False), 'attribute_list': object_fields.ListOfObjectsField( 'DriverAttribute', default=[], nullable=True), # TODO() add field related to local_memory or just store in the # attribute list? 'attach_handle_list': object_fields.ListOfObjectsField( 'DriverAttachHandle', default=[], nullable=True), 'driver_name': object_fields.StringField(nullable=True) } def create(self, context, device_id, cpid_id): """Create a driver-side Deployable object into DB. This object will be stored in separate db tables: deployable & attach_handle & attribute table. """ # first store in deployable table through Deployable Object. deployable_obj = Deployable(context=context, name=self.name, num_accelerators=self.num_accelerators, device_id=device_id, driver_name=self.driver_name ) deployable_obj.create(context) # create attribute_list for this deployable if hasattr(self, 'attribute_list'): for driver_attr in self.attribute_list: driver_attr.create(context, deployable_obj.id) # create attach_handle_list for this deployable if hasattr(self, 'attach_handle_list'): for driver_attach_handle in self.attach_handle_list: driver_attach_handle.create(context, deployable_obj.id, cpid_id) def destroy(self, context, device_id): """delete one driver-side deployable by calling existing Deployable and AttachHandle Object. Use name&host to identify Deployable and attach_info to identify the AttachHandle """ # get deployable_id by name, get only one value. dep_obj = Deployable.get_by_name_deviceid(context, self.name, device_id) # delete attach_handle if hasattr(self, 'attach_handle_list'): for driver_ah_obj in self.attach_handle_list: # get attach_handle_obj, exist and only one. driver_ah_obj.destroy(context, dep_obj.id) # delete attribute_list if hasattr(self, 'attribute_list'): DriverAttribute.destroy(context, dep_obj.id) # delete dep_obj if dep_obj is not None: dep_obj.destroy(context) @classmethod def list(cls, context, device_id): """Form driver-side Deployable object list from DB for one device.""" # get deployable_obj_list for one device_id dep_obj_list = Deployable.get_list_by_device_id(context, device_id) driver_dep_obj_list = [] for dep_obj in dep_obj_list: # get driver_ah_obj_list for this dep_obj driver_ah_obj_list = DriverAttachHandle.list(context, dep_obj.id) # get driver_attr_obj_list fro this dep_obj driver_attr_obj_list = DriverAttribute.list(context, dep_obj.id) driver_dep_obj = cls(context=context, name=dep_obj.name, num_accelerators=dep_obj.num_accelerators, attribute_list=driver_attr_obj_list, attach_handle_list=driver_ah_obj_list) driver_dep_obj_list.append(driver_dep_obj) return driver_dep_obj_list @classmethod def get_by_name(cls, context, name): """Form driver-side Deployable object list from DB for one device.""" # get deployable_obj_list for one device_id dep_obj = Deployable.get_by_name(context, name) driver_ah_obj_list = DriverAttachHandle.list(context, dep_obj.id) # get driver_attr_obj_list fro this dep_obj driver_attr_obj_list = DriverAttribute.list(context, dep_obj.id) driver_dep_obj = cls(context=context, name=dep_obj.name, num_accelerators=dep_obj.num_accelerators, attribute_list=driver_attr_obj_list, attach_handle_list=driver_ah_obj_list) return driver_dep_obj