class WithWSProp(object): def __init__(self): self._aint = 0 def get_aint(self): return self._aint def set_aint(self, value): self._aint = value aint = types.wsproperty(int, get_aint, set_aint, mandatory=True)
class VolumeConnector(base.APIBase): """API representation of a volume connector. This class enforces type checking and value constraints, and converts between the internal object model and the API representation of a volume connector. """ _node_uuid = None def _get_node_uuid(self): return self._node_uuid def _set_node_identifiers(self, value): """Set both UUID and ID of a node for VolumeConnector object :param value: UUID, ID of a node, or atypes.Unset """ if value == atypes.Unset: self._node_uuid = atypes.Unset elif value and self._node_uuid != value: try: node = objects.Node.get(api.request.context, value) self._node_uuid = node.uuid # NOTE(smoriya): Create the node_id attribute on-the-fly # to satisfy the api -> rpc object conversion. self.node_id = node.id except exception.NodeNotFound as e: # Change error code because 404 (NotFound) is inappropriate # response for a POST request to create a VolumeConnector e.code = http_client.BAD_REQUEST # BadRequest raise uuid = types.uuid """Unique UUID for this volume connector""" type = atypes.wsattr(str, mandatory=True) """The type of volume connector""" connector_id = atypes.wsattr(str, mandatory=True) """The connector_id for this volume connector""" extra = {str: types.jsontype} """The metadata for this volume connector""" node_uuid = atypes.wsproperty(types.uuid, _get_node_uuid, _set_node_identifiers, mandatory=True) """The UUID of the node this volume connector belongs to""" links = atypes.wsattr([link.Link], readonly=True) """A list containing a self link and associated volume connector links""" def __init__(self, **kwargs): self.fields = [] fields = list(objects.VolumeConnector.fields) for field in fields: # Skip fields we do not expose. if not hasattr(self, field): continue self.fields.append(field) setattr(self, field, kwargs.get(field, atypes.Unset)) # NOTE(smoriya): node_id is an attribute created on-the-fly # by _set_node_uuid(), it needs to be present in the fields so # that as_dict() will contain node_id field when converting it # before saving it in the database. self.fields.append('node_id') # NOTE(smoriya): node_uuid is not part of objects.VolumeConnector.- # fields because it's an API-only attribute self.fields.append('node_uuid') # NOTE(jtaryma): Additionally to node_uuid, node_id is handled as a # secondary identifier in case RPC volume connector object dictionary # was passed to the constructor. self.node_uuid = kwargs.get('node_uuid') or kwargs.get( 'node_id', atypes.Unset) @staticmethod def _convert_with_links(connector, url): connector.links = [ link.Link.make_link('self', url, 'volume/connectors', connector.uuid), link.Link.make_link('bookmark', url, 'volume/connectors', connector.uuid, bookmark=True) ] return connector @classmethod def convert_with_links(cls, rpc_connector, fields=None, sanitize=True): connector = VolumeConnector(**rpc_connector.as_dict()) if fields is not None: api_utils.check_for_invalid_fields(fields, connector.as_dict()) connector = cls._convert_with_links(connector, api.request.public_url) if not sanitize: return connector connector.sanitize(fields) return connector def sanitize(self, fields=None): """Removes sensitive and unrequested data. Will only keep the fields specified in the ``fields`` parameter. :param fields: list of fields to preserve, or ``None`` to preserve them all :type fields: list of str """ if fields is not None: self.unset_fields_except(fields) # never expose the node_id attribute self.node_id = atypes.Unset @classmethod def sample(cls, expand=True): time = datetime.datetime(2000, 1, 1, 12, 0, 0) sample = cls(uuid='86cfd480-0842-4abb-8386-e46149beb82f', type='iqn', connector_id='iqn.2010-10.org.openstack:51332b70524', extra={'foo': 'bar'}, created_at=time, updated_at=time) sample._node_uuid = '7ae81bb3-dec3-4289-8d6c-da80bd8001ae' fields = None if expand else _DEFAULT_RETURN_FIELDS return cls._convert_with_links(sample, 'http://localhost:6385', fields=fields)
class VolumeTarget(base.APIBase): """API representation of a volume target. This class enforces type checking and value constraints, and converts between the internal object model and the API representation of a volume target. """ _node_uuid = None def _get_node_uuid(self): return self._node_uuid def _set_node_identifiers(self, value): """Set both UUID and ID of a node for VolumeTarget object :param value: UUID, ID of a node, or atypes.Unset """ if value == atypes.Unset: self._node_uuid = atypes.Unset elif value and self._node_uuid != value: try: node = objects.Node.get(api.request.context, value) self._node_uuid = node.uuid # NOTE(smoriya): Create the node_id attribute on-the-fly # to satisfy the api -> rpc object conversion. self.node_id = node.id except exception.NodeNotFound as e: # Change error code because 404 (NotFound) is inappropriate # response for a POST request to create a VolumeTarget e.code = http_client.BAD_REQUEST # BadRequest raise uuid = types.uuid """Unique UUID for this volume target""" volume_type = atypes.wsattr(str, mandatory=True) """The volume_type of volume target""" properties = {str: types.jsontype} """The properties for this volume target""" boot_index = atypes.wsattr(int, mandatory=True) """The boot_index of volume target""" volume_id = atypes.wsattr(str, mandatory=True) """The volume_id for this volume target""" extra = {str: types.jsontype} """The metadata for this volume target""" node_uuid = atypes.wsproperty(types.uuid, _get_node_uuid, _set_node_identifiers, mandatory=True) """The UUID of the node this volume target belongs to""" links = atypes.wsattr([link.Link], readonly=True) """A list containing a self link and associated volume target links""" def __init__(self, **kwargs): self.fields = [] fields = list(objects.VolumeTarget.fields) for field in fields: # Skip fields we do not expose. if not hasattr(self, field): continue self.fields.append(field) setattr(self, field, kwargs.get(field, atypes.Unset)) # NOTE(smoriya): node_id is an attribute created on-the-fly # by _set_node_uuid(), it needs to be present in the fields so # that as_dict() will contain node_id field when converting it # before saving it in the database. self.fields.append('node_id') # NOTE(smoriya): node_uuid is not part of objects.VolumeTarget.- # fields because it's an API-only attribute self.fields.append('node_uuid') # NOTE(jtaryma): Additionally to node_uuid, node_id is handled as a # secondary identifier in case RPC volume target object dictionary # was passed to the constructor. self.node_uuid = kwargs.get('node_uuid') or kwargs.get('node_id', atypes.Unset) @staticmethod def _convert_with_links(target, url): target.links = [link.Link.make_link('self', url, 'volume/targets', target.uuid), link.Link.make_link('bookmark', url, 'volume/targets', target.uuid, bookmark=True) ] return target @classmethod def convert_with_links(cls, rpc_target, fields=None, sanitize=True): target = VolumeTarget(**rpc_target.as_dict()) if fields is not None: api_utils.check_for_invalid_fields(fields, target.as_dict()) target = cls._convert_with_links(target, api.request.public_url) if not sanitize: return target target.sanitize(fields) return target def sanitize(self, fields=None): """Removes sensitive and unrequested data. Will only keep the fields specified in the ``fields`` parameter. :param fields: list of fields to preserve, or ``None`` to preserve them all :type fields: list of str """ if fields is not None: self.unset_fields_except(fields) # never expose the node_id attribute self.node_id = atypes.Unset @classmethod def sample(cls, expand=True): time = datetime.datetime(2000, 1, 1, 12, 0, 0) properties = {"auth_method": "CHAP", "auth_username": "******", "auth_password": "******", "target_iqn": "iqn.2010-10.com.example:vol-X", "target_portal": "192.168.0.123:3260", "volume_id": "a2f3ff15-b3ea-4656-ab90-acbaa1a07607", "target_lun": 0, "access_mode": "rw"} sample = cls(uuid='667808d4-622f-4629-b629-07753a19e633', volume_type='iscsi', boot_index=0, volume_id='a2f3ff15-b3ea-4656-ab90-acbaa1a07607', properties=properties, extra={'foo': 'bar'}, created_at=time, updated_at=time) sample._node_uuid = '7ae81bb3-dec3-4289-8d6c-da80bd8001ae' fields = None if expand else _DEFAULT_RETURN_FIELDS return cls._convert_with_links(sample, 'http://localhost:6385', fields=fields)
class Port(base.APIBase): """API representation of a port. This class enforces type checking and value constraints, and converts between the internal object model and the API representation of a port. """ _node_uuid = None _portgroup_uuid = None def _get_node_uuid(self): return self._node_uuid def _set_node_uuid(self, value): if value and self._node_uuid != value: try: # FIXME(comstud): One should only allow UUID here, but # there seems to be a bug in that tests are passing an # ID. See bug #1301046 for more details. node = objects.Node.get(api.request.context, value) self._node_uuid = node.uuid # NOTE(lucasagomes): Create the node_id attribute on-the-fly # to satisfy the api -> rpc object # conversion. self.node_id = node.id except exception.NodeNotFound as e: # Change error code because 404 (NotFound) is inappropriate # response for a POST request to create a Port e.code = http_client.BAD_REQUEST # BadRequest raise elif value == atypes.Unset: self._node_uuid = atypes.Unset def _get_portgroup_uuid(self): return self._portgroup_uuid def _set_portgroup_uuid(self, value): if value and self._portgroup_uuid != value: if not api_utils.allow_portgroups_subcontrollers(): self._portgroup_uuid = atypes.Unset return try: portgroup = objects.Portgroup.get(api.request.context, value) if portgroup.node_id != self.node_id: raise exception.BadRequest( _('Port can not be added to a ' 'portgroup belonging to a ' 'different node.')) self._portgroup_uuid = portgroup.uuid # NOTE(lucasagomes): Create the portgroup_id attribute # on-the-fly to satisfy the api -> # rpc object conversion. self.portgroup_id = portgroup.id except exception.PortgroupNotFound as e: # Change error code because 404 (NotFound) is inappropriate # response for a POST request to create a Port e.code = http_client.BAD_REQUEST # BadRequest raise e elif value == atypes.Unset: self._portgroup_uuid = atypes.Unset elif value is None and api_utils.allow_portgroups_subcontrollers(): # This is to output portgroup_uuid field if API version allows this self._portgroup_uuid = None uuid = types.uuid """Unique UUID for this port""" address = atypes.wsattr(types.macaddress, mandatory=True) """MAC Address for this port""" extra = {str: types.jsontype} """This port's meta data""" internal_info = atypes.wsattr({str: types.jsontype}, readonly=True) """This port's internal information maintained by ironic""" node_uuid = atypes.wsproperty(types.uuid, _get_node_uuid, _set_node_uuid, mandatory=True) """The UUID of the node this port belongs to""" portgroup_uuid = atypes.wsproperty(types.uuid, _get_portgroup_uuid, _set_portgroup_uuid, mandatory=False) """The UUID of the portgroup this port belongs to""" pxe_enabled = types.boolean """Indicates whether pxe is enabled or disabled on the node.""" local_link_connection = types.locallinkconnectiontype """The port binding profile for the port""" physical_network = atypes.StringType(max_length=64) """The name of the physical network to which this port is connected.""" links = None """A list containing a self link and associated port links""" is_smartnic = types.boolean """Indicates whether this port is a Smart NIC port.""" def __init__(self, **kwargs): self.fields = [] fields = list(objects.Port.fields) # NOTE(lucasagomes): node_uuid is not part of objects.Port.fields # because it's an API-only attribute fields.append('node_uuid') # NOTE: portgroup_uuid is not part of objects.Port.fields # because it's an API-only attribute fields.append('portgroup_uuid') for field in fields: # Add fields we expose. if hasattr(self, field): self.fields.append(field) setattr(self, field, kwargs.get(field, atypes.Unset)) # NOTE(lucasagomes): node_id is an attribute created on-the-fly # by _set_node_uuid(), it needs to be present in the fields so # that as_dict() will contain node_id field when converting it # before saving it in the database. self.fields.append('node_id') setattr(self, 'node_uuid', kwargs.get('node_id', atypes.Unset)) # NOTE: portgroup_id is an attribute created on-the-fly # by _set_portgroup_uuid(), it needs to be present in the fields so # that as_dict() will contain portgroup_id field when converting it # before saving it in the database. self.fields.append('portgroup_id') setattr(self, 'portgroup_uuid', kwargs.get('portgroup_id', atypes.Unset)) @classmethod def convert_with_links(cls, rpc_port, fields=None, sanitize=True): port = Port(**rpc_port.as_dict()) port._validate_fields(fields) url = api.request.public_url port.links = [ link.make_link('self', url, 'ports', port.uuid), link.make_link('bookmark', url, 'ports', port.uuid, bookmark=True) ] if not sanitize: return port port.sanitize(fields=fields) return port def _validate_fields(self, fields=None): if fields is not None: api_utils.check_for_invalid_fields(fields, self.as_dict()) def sanitize(self, fields=None): """Removes sensitive and unrequested data. Will only keep the fields specified in the ``fields`` parameter. :param fields: list of fields to preserve, or ``None`` to preserve them all :type fields: list of str """ hide_fields_in_newer_versions(self) if fields is not None: self.unset_fields_except(fields) # never expose the node_id attribute self.node_id = atypes.Unset # never expose the portgroup_id attribute self.portgroup_id = atypes.Unset @classmethod def sample(cls, expand=True): time = datetime.datetime(2000, 1, 1, 12, 0, 0) sample = cls(uuid='27e3153e-d5bf-4b7e-b517-fb518e17f34c', address='fe:54:00:77:07:d9', extra={'foo': 'bar'}, internal_info={}, created_at=time, updated_at=time, pxe_enabled=True, local_link_connection={ 'switch_info': 'host', 'port_id': 'Gig0/1', 'switch_id': 'aa:bb:cc:dd:ee:ff' }, physical_network='physnet1', is_smartnic=False) # NOTE(lucasagomes): node_uuid getter() method look at the # _node_uuid variable sample._node_uuid = '7ae81bb3-dec3-4289-8d6c-da80bd8001ae' sample._portgroup_uuid = '037d9a52-af89-4560-b5a3-a33283295ba2' fields = None if expand else _DEFAULT_RETURN_FIELDS return cls._convert_with_links(sample, 'http://localhost:6385', fields=fields)
class Portgroup(base.APIBase): """API representation of a portgroup. This class enforces type checking and value constraints, and converts between the internal object model and the API representation of a portgroup. """ _node_uuid = None def _get_node_uuid(self): return self._node_uuid def _set_node_uuid(self, value): if value and self._node_uuid != value: if not api_utils.allow_portgroups(): self._node_uuid = atypes.Unset return try: node = objects.Node.get(api.request.context, value) self._node_uuid = node.uuid # NOTE: Create the node_id attribute on-the-fly # to satisfy the api -> rpc object # conversion. self.node_id = node.id except exception.NodeNotFound as e: # Change error code because 404 (NotFound) is inappropriate # response for a POST request to create a Portgroup e.code = http_client.BAD_REQUEST raise e elif value == atypes.Unset: self._node_uuid = atypes.Unset uuid = types.uuid """Unique UUID for this portgroup""" address = atypes.wsattr(types.macaddress) """MAC Address for this portgroup""" extra = {str: types.jsontype} """This portgroup's meta data""" internal_info = atypes.wsattr({str: types.jsontype}, readonly=True) """This portgroup's internal info""" node_uuid = atypes.wsproperty(types.uuid, _get_node_uuid, _set_node_uuid, mandatory=True) """The UUID of the node this portgroup belongs to""" name = atypes.wsattr(str) """The logical name for this portgroup""" links = None """A list containing a self link and associated portgroup links""" standalone_ports_supported = types.boolean """Indicates whether ports of this portgroup may be used as single NIC ports""" mode = atypes.wsattr(str) """The mode for this portgroup. See linux bonding documentation for details: https://www.kernel.org/doc/Documentation/networking/bonding.txt""" properties = {str: types.jsontype} """This portgroup's properties""" ports = None """Links to the collection of ports of this portgroup""" def __init__(self, **kwargs): self.fields = [] fields = list(objects.Portgroup.fields) # NOTE: node_uuid is not part of objects.Portgroup.fields # because it's an API-only attribute fields.append('node_uuid') for field in fields: # Skip fields we do not expose. if not hasattr(self, field): continue self.fields.append(field) setattr(self, field, kwargs.get(field, atypes.Unset)) # NOTE: node_id is an attribute created on-the-fly # by _set_node_uuid(), it needs to be present in the fields so # that as_dict() will contain node_id field when converting it # before saving it in the database. self.fields.append('node_id') setattr(self, 'node_uuid', kwargs.get('node_id', atypes.Unset)) @staticmethod def _convert_with_links(portgroup, url, fields=None): """Add links to the portgroup.""" if fields is None: portgroup.ports = [ link.make_link('self', url, 'portgroups', portgroup.uuid + "/ports"), link.make_link('bookmark', url, 'portgroups', portgroup.uuid + "/ports", bookmark=True) ] # never expose the node_id attribute portgroup.node_id = atypes.Unset portgroup.links = [ link.make_link('self', url, 'portgroups', portgroup.uuid), link.make_link('bookmark', url, 'portgroups', portgroup.uuid, bookmark=True) ] return portgroup @classmethod def convert_with_links(cls, rpc_portgroup, fields=None, sanitize=True): """Add links to the portgroup.""" portgroup = Portgroup(**rpc_portgroup.as_dict()) if fields is not None: api_utils.check_for_invalid_fields(fields, portgroup.as_dict()) portgroup = cls._convert_with_links(portgroup, api.request.host_url, fields=fields) if not sanitize: return portgroup portgroup.sanitize(fields) return portgroup def sanitize(self, fields=None): """Removes sensitive and unrequested data. Will only keep the fields specified in the ``fields`` parameter. :param fields: list of fields to preserve, or ``None`` to preserve them all :type fields: list of str """ if fields is not None: self.unset_fields_except(fields) # never expose the node_id attribute self.node_id = atypes.Unset @classmethod def sample(cls, expand=True): """Return a sample of the portgroup.""" sample = cls(uuid='a594544a-2daf-420c-8775-17a8c3e0852f', address='fe:54:00:77:07:d9', name='node1-portgroup-01', extra={'foo': 'bar'}, internal_info={'baz': 'boo'}, standalone_ports_supported=True, mode='active-backup', properties={}, created_at=datetime.datetime(2000, 1, 1, 12, 0, 0), updated_at=datetime.datetime(2000, 1, 1, 12, 0, 0)) # NOTE(lucasagomes): node_uuid getter() method look at the # _node_uuid variable sample._node_uuid = '7ae81bb3-dec3-4289-8d6c-da80bd8001ae' fields = None if expand else _DEFAULT_RETURN_FIELDS return cls._convert_with_links(sample, 'http://localhost:6385', fields=fields)