Exemple #1
0
class Chassis(base.APIBase):
    """API representation of a chassis.

    This class enforces type checking and value constraints, and converts
    between the internal object model and the API representation of
    a chassis.
    """

    uuid = types.uuid
    "The UUID of the chassis"

    description = wtypes.text
    "The description of the chassis"

    extra = {wtypes.text: types.MultiType(wtypes.text, six.integer_types)}
    "The metadata of the chassis"

    links = wsme.wsattr([link.Link], readonly=True)
    "A list containing a self link and associated chassis links"

    nodes = wsme.wsattr([link.Link], readonly=True)
    "Links to the collection of nodes contained in this chassis"

    def __init__(self, **kwargs):
        self.fields = objects.Chassis.fields.keys()
        for k in self.fields:
            setattr(self, k, kwargs.get(k))

    @classmethod
    def convert_with_links(cls, rpc_chassis, expand=True):
        chassis = Chassis(**rpc_chassis.as_dict())
        if not expand:
            chassis.unset_fields_except(['uuid', 'description'])
        else:
            chassis.nodes = [
                link.Link.make_link('self', pecan.request.host_url, 'chassis',
                                    chassis.uuid + "/nodes"),
                link.Link.make_link('bookmark',
                                    pecan.request.host_url,
                                    'chassis',
                                    chassis.uuid + "/nodes",
                                    bookmark=True)
            ]
        chassis.links = [
            link.Link.make_link('self', pecan.request.host_url, 'chassis',
                                chassis.uuid),
            link.Link.make_link('bookmark', pecan.request.host_url, 'chassis',
                                chassis.uuid)
        ]
        return chassis
Exemple #2
0
class ConsoleInfo(base.APIBase):
    """API representation of the console information for a node."""

    console_enabled = types.boolean
    """The console state: if the console is enabled or not."""

    console_info = {
        wtypes.text: types.MultiType(wtypes.text, six.integer_types)
    }
    """The console information. It typically includes the url to access the
    console and the type of the application that hosts the console."""
    @classmethod
    def sample(cls):
        console = {'type': 'shellinabox', 'url': 'http://<hostname>:4201'}
        return cls(console_enabled=True, console_info=console)
Exemple #3
0
class Chassis(base.APIBase):
    """API representation of a chassis.

    This class enforces type checking and value constraints, and converts
    between the internal object model and the API representation of
    a chassis.
    """

    uuid = types.uuid
    "The UUID of the chassis"

    description = wtypes.text
    "The description of the chassis"

    extra = {wtypes.text: types.MultiType(wtypes.text, six.integer_types)}
    "The metadata of the chassis"

    links = wsme.wsattr([link.Link], readonly=True)
    "A list containing a self link and associated chassis links"

    nodes = wsme.wsattr([link.Link], readonly=True)
    "Links to the collection of nodes contained in this chassis"

    def __init__(self, **kwargs):
        self.fields = []
        for field in objects.Chassis.fields:
            # Skip fields we do not expose.
            if not hasattr(self, field):
                continue
            self.fields.append(field)
            setattr(self, field, kwargs.get(field))

    @classmethod
    def _convert_with_links(cls, chassis, url, expand=True):
        if not expand:
            chassis.unset_fields_except(['uuid', 'description'])
        else:
            chassis.nodes = [
                link.Link.make_link('self', url, 'chassis',
                                    chassis.uuid + "/nodes"),
                link.Link.make_link('bookmark',
                                    url,
                                    'chassis',
                                    chassis.uuid + "/nodes",
                                    bookmark=True)
            ]
        chassis.links = [
            link.Link.make_link('self', url, 'chassis', chassis.uuid),
            link.Link.make_link('bookmark',
                                url,
                                'chassis',
                                chassis.uuid,
                                bookmark=True)
        ]
        return chassis

    @classmethod
    def convert_with_links(cls, rpc_chassis, expand=True):
        chassis = Chassis(**rpc_chassis.as_dict())
        return cls._convert_with_links(chassis, pecan.request.host_url, expand)

    @classmethod
    def sample(cls, expand=True):
        time = datetime.datetime(2000, 1, 1, 12, 0, 0)
        sample = cls(uuid='eaaca217-e7d8-47b4-bb41-3f99f20eed89',
                     extra={},
                     description='Sample chassis',
                     created_at=time)
        return cls._convert_with_links(sample, 'http://localhost:6385', expand)
Exemple #4
0
class Node(base.APIBase):
    """API representation of a bare metal node.

    This class enforces type checking and value constraints, and converts
    between the internal object model and the API representation of a node.
    """

    _chassis_uuid = None

    def _get_chassis_uuid(self):
        return self._chassis_uuid

    def _set_chassis_uuid(self, value):
        if value and self._chassis_uuid != value:
            try:
                chassis = objects.Chassis.get(pecan.request.context, value)
                self._chassis_uuid = chassis.uuid
                # NOTE(lucasagomes): Create the chassis_id attribute on-the-fly
                #                    to satisfy the api -> rpc object
                #                    conversion.
                self.chassis_id = chassis.id
            except exception.ChassisNotFound as e:
                # Change error code because 404 (NotFound) is inappropriate
                # response for a POST request to create a Port
                e.code = 400  # BadRequest
                raise e
        elif value == wtypes.Unset:
            self._chassis_uuid = wtypes.Unset

    uuid = types.uuid
    "Unique UUID for this node"

    instance_uuid = types.uuid
    "The UUID of the instance in nova-compute"

    power_state = wsme.wsattr(wtypes.text, readonly=True)
    "Represent the current (not transition) power state of the node"

    target_power_state = wsme.wsattr(wtypes.text, readonly=True)
    "The user modified desired power state of the node."

    last_error = wsme.wsattr(wtypes.text, readonly=True)
    "Any error from the most recent (last) asynchronous transaction that"
    "started but failed to finish."

    provision_state = wsme.wsattr(wtypes.text, readonly=True)
    "Represent the current (not transition) provision state of the node"

    reservation = wsme.wsattr(wtypes.text, readonly=True)
    "The hostname of the conductor that holds an exclusive lock on the node."

    provision_updated_at = datetime.datetime
    "The UTC date and time of the last provision state change"

    maintenance = types.boolean
    "Indicates whether the node is in maintenance mode."

    target_provision_state = wsme.wsattr(wtypes.text, readonly=True)
    "The user modified desired provision state of the node."

    console_enabled = types.boolean
    "Indicates whether the console access is enabled or disabled on the node."

    instance_info = {
        wtypes.text: types.MultiType(wtypes.text, six.integer_types)
    }
    "This node's instance info."

    driver = wsme.wsattr(wtypes.text, mandatory=True)
    "The driver responsible for controlling the node"

    driver_info = {
        wtypes.text: types.MultiType(wtypes.text, six.integer_types)
    }
    "This node's driver configuration"

    extra = {wtypes.text: types.MultiType(wtypes.text, six.integer_types)}
    "This node's meta data"

    # NOTE: properties should use a class to enforce required properties
    #       current list: arch, cpus, disk, ram, image
    properties = {wtypes.text: types.MultiType(wtypes.text, six.integer_types)}
    "The physical characteristics of this node"

    chassis_uuid = wsme.wsproperty(types.uuid, _get_chassis_uuid,
                                   _set_chassis_uuid)
    "The UUID of the chassis this node belongs"

    links = wsme.wsattr([link.Link], readonly=True)
    "A list containing a self link and associated node links"

    ports = wsme.wsattr([link.Link], readonly=True)
    "Links to the collection of ports on this node"

    def __init__(self, **kwargs):
        self.fields = []
        fields = objects.Node.fields.keys()
        # NOTE(lucasagomes): chassis_uuid is not part of objects.Node.fields
        # because it's an API-only attribute.
        fields.append('chassis_uuid')
        for k in fields:
            # Skip fields we do not expose.
            if not hasattr(self, k):
                continue
            self.fields.append(k)
            setattr(self, k, kwargs.get(k))

        # NOTE(lucasagomes): chassis_id is an attribute created on-the-fly
        # by _set_chassis_uuid(), it needs to be present in the fields so
        # that as_dict() will contain chassis_id field when converting it
        # before saving it in the database.
        self.fields.append('chassis_id')
        setattr(self, 'chassis_uuid', kwargs.get('chassis_id'))

    @classmethod
    def _convert_with_links(cls, node, url, expand=True):
        if not expand:
            except_list = [
                'instance_uuid', 'maintenance', 'power_state',
                'provision_state', 'uuid'
            ]
            node.unset_fields_except(except_list)
        else:
            node.ports = [
                link.Link.make_link('self', url, 'nodes',
                                    node.uuid + "/ports"),
                link.Link.make_link('bookmark',
                                    url,
                                    'nodes',
                                    node.uuid + "/ports",
                                    bookmark=True)
            ]

        # NOTE(lucasagomes): The numeric ID should not be exposed to
        #                    the user, it's internal only.
        node.chassis_id = wtypes.Unset

        node.links = [
            link.Link.make_link('self', url, 'nodes', node.uuid),
            link.Link.make_link('bookmark',
                                url,
                                'nodes',
                                node.uuid,
                                bookmark=True)
        ]
        return node

    @classmethod
    def convert_with_links(cls, rpc_node, expand=True):
        node = Node(**rpc_node.as_dict())
        return cls._convert_with_links(node, pecan.request.host_url, expand)

    @classmethod
    def sample(cls, expand=True):
        time = datetime.datetime(2000, 1, 1, 12, 0, 0)
        node_uuid = '1be26c0b-03f2-4d2e-ae87-c02d7f33c123'
        instance_uuid = 'dcf1fbc5-93fc-4596-9395-b80572f6267b'
        sample = cls(uuid=node_uuid,
                     instance_uuid=instance_uuid,
                     power_state=ir_states.POWER_ON,
                     target_power_state=ir_states.NOSTATE,
                     last_error=None,
                     provision_state=ir_states.ACTIVE,
                     target_provision_state=ir_states.NOSTATE,
                     reservation=None,
                     driver='fake',
                     driver_info={},
                     extra={},
                     properties={
                         'memory_mb': '1024',
                         'local_gb': '10',
                         'cpus': '1'
                     },
                     updated_at=time,
                     created_at=time,
                     provision_updated_at=time,
                     instance_info={})
        # NOTE(matty_dubs): The chassis_uuid getter() is based on the
        # _chassis_uuid variable:
        sample._chassis_uuid = 'edcad704-b2da-41d5-96d9-afd580ecfa12'
        return cls._convert_with_links(sample, 'http://localhost:6385', expand)
Exemple #5
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

    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(pecan.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 = 400  # BadRequest
                raise e
        elif value == wtypes.Unset:
            self._node_uuid = wtypes.Unset

    uuid = types.uuid
    "Unique UUID for this port"

    address = wsme.wsattr(types.macaddress, mandatory=True)
    "MAC Address for this port"

    extra = {wtypes.text: types.MultiType(wtypes.text, six.integer_types)}
    "This port's meta data"

    node_uuid = wsme.wsproperty(types.uuid,
                                _get_node_uuid,
                                _set_node_uuid,
                                mandatory=True)
    "The UUID of the node this port belongs to"

    links = wsme.wsattr([link.Link], readonly=True)
    "A list containing a self link and associated port links"

    def __init__(self, **kwargs):
        self.fields = []
        fields = list(objects.Port.fields.keys())
        # NOTE(lucasagomes): node_uuid is not part of objects.Port.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))

        # 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'))

    @classmethod
    def convert_with_links(cls, rpc_port, expand=True):
        port = Port(**rpc_port.as_dict())
        if not expand:
            port.unset_fields_except(['uuid', 'address'])

        # never expose the node_id attribute
        port.node_id = wtypes.Unset

        port.links = [
            link.Link.make_link('self', pecan.request.host_url, 'ports',
                                port.uuid),
            link.Link.make_link('bookmark',
                                pecan.request.host_url,
                                'ports',
                                port.uuid,
                                bookmark=True)
        ]
        return port

    @classmethod
    def sample(cls):
        sample = cls(uuid='27e3153e-d5bf-4b7e-b517-fb518e17f34c',
                     address='fe:54:00:77:07:d9',
                     extra={'foo': 'bar'},
                     created_at=datetime.datetime.utcnow(),
                     updated_at=datetime.datetime.utcnow())
        # NOTE(lucasagomes): node_uuid getter() method look at the
        # _node_uuid variable
        sample._node_uuid = '7ae81bb3-dec3-4289-8d6c-da80bd8001ae'
        return sample
Exemple #6
0
 def test_multitype_tostring(self):
     vt = types.MultiType(str, int)
     vts = str(vt)
     self.assertIn(str(str), vts)
     self.assertIn(str(int), vts)
Exemple #7
0
 def test_invalid_values(self):
     vt = types.MultiType(wsme.types.text, six.integer_types)
     self.assertRaises(ValueError, vt.validate, 0.10)
     self.assertRaises(ValueError, vt.validate, object())
Exemple #8
0
 def test_valid_values(self):
     vt = types.MultiType(wsme.types.text, six.integer_types)
     value = vt.validate("hello")
     self.assertEqual("hello", value)
     value = vt.validate(10)
     self.assertEqual(10, value)