Пример #1
0
        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)
Пример #2
0
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)
Пример #3
0
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)
Пример #4
0
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)
Пример #5
0
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)