Exemplo n.º 1
0
    def setUp(self):
        super(DbTestCase, self).setUp()

        self.dbapi = dbapi.get_instance()

        global _DB_CACHE
        if not _DB_CACHE:
            _DB_CACHE = Database(sqla_api, migration,
                                 sql_connection=CONF.database.connection)
        self.useFixture(_DB_CACHE)
Exemplo n.º 2
0
def create_test_node(**kw):
    """Create test node entry in DB and return Node DB object.
    Function to be used to create test Node objects in the database.
    :param kw: kwargs with overriding values for node's attributes.
    :returns: Test Node DB object.
    """
    node = get_test_node(**kw)
    # Let DB generate ID if it isn't specified explicitly
    if "id" not in kw:
        del node["id"]
    dbapi = db_api.get_instance()
    return dbapi.create_node(node)
Exemplo n.º 3
0
def create_test_container(**kw):
    """Create test container entry in DB and return Container DB object.
    Function to be used to create test Container objects in the database.
    :param kw: kwargs with overriding values for container's attributes.
    :returns: Test Container DB object.
    """
    container = get_test_container(**kw)
    # Let DB generate ID if it isn't specified explicitly
    if "id" not in kw:
        del container["id"]
    dbapi = db_api.get_instance()
    return dbapi.create_container(container)
Exemplo n.º 4
0
def create_test_x509keypair(**kw):
    """Create test x509keypair entry in DB and return X509KeyPair DB object.
    Function to be used to create test X509KeyPair objects in the database.
    :param kw: kwargs with overriding values for x509keypair's attributes.
    :returns: Test X509KeyPair DB object.
    """
    x509keypair = get_test_x509keypair(**kw)
    # Let DB generate ID if it isn't specified explicitly
    if "id" not in kw:
        del x509keypair["id"]
    dbapi = db_api.get_instance()
    return dbapi.create_x509keypair(x509keypair)
Exemplo n.º 5
0
def create_test_bay(**kw):
    """Create test bay entry in DB and return Bay DB object.
    Function to be used to create test Bay objects in the database.
    :param kw: kwargs with overriding values for bay's attributes.
    :returns: Test Bay DB object.
    """
    bay = get_test_bay(**kw)
    # Let DB generate ID if it isn't specified explicitly
    if "id" not in kw:
        del bay["id"]
    dbapi = db_api.get_instance()
    return dbapi.create_bay(bay)
Exemplo n.º 6
0
def create_test_quotas(**kw):
    """Create test quotas entry in DB and return quotas DB object.

    :param kw: kwargs with overriding values for quota attributes.
    :returns: Test quotas DB object.
    """
    quotas = get_test_quotas(**kw)
    # Let DB generate ID if it isn't specified explicitly
    if 'id' not in kw:
        del quotas['id']
    dbapi = db_api.get_instance()
    return dbapi.create_quota(quotas)
Exemplo n.º 7
0
def create_test_federation(**kw):
    """Create test federation entry in DB and return federation DB object.

    :param kw: kwargs with overriding values for federation attributes.
    :return: Test quotas DB object.
    """
    federation = get_test_federation(**kw)
    # Let DB generate ID if it isn't specified explicitly
    if 'id' not in kw:
        del federation['id']
    dbapi = db_api.get_instance()
    return dbapi.create_federation(federation)
Exemplo n.º 8
0
def create_test_nodegroup(**kw):
    """Create test nodegroup entry in DB and return federation DB object.

    :param kw: kwargs with overriding values for nodegroup attributes.
    :return: Test nodegroup DB object.
    """
    nodegroup = get_test_nodegroup(**kw)
    # Let DB generate ID if it isn't specified explicitly
    if 'id' in nodegroup:
        del nodegroup['id']
    dbapi = db_api.get_instance()
    return dbapi.create_nodegroup(nodegroup)
Exemplo n.º 9
0
def create_test_magnum_service(**kw):
    """Create test magnum_service entry in DB and return magnum_service DB object.

    :param kw: kwargs with overriding values for magnum_service's attributes.
    :returns: Test magnum_service DB object.
    """
    magnum_service = get_test_magnum_service(**kw)
    # Let DB generate ID if it isn't specified explicitly
    if 'id' not in kw:
        del magnum_service['id']
    dbapi = db_api.get_instance()
    return dbapi.create_magnum_service(magnum_service)
Exemplo n.º 10
0
def create_test_pod(**kw):
    """Create test pod entry in DB and return Pod DB object.
    Function to be used to create test Pod objects in the database.
    :param kw: kwargs with overriding values for pod's attributes.
    :returns: Test Pod DB object.
    """
    pod = get_test_pod(**kw)
    # Let DB generate ID if it isn't specified explicitly
    if "id" not in kw:
        del pod["id"]
    dbapi = db_api.get_instance()
    return dbapi.create_pod(pod)
Exemplo n.º 11
0
def create_test_service(**kw):
    """Create test service entry in DB and return Service DB object.
    Function to be used to create test Service objects in the database.
    :param kw: kwargs with overriding values for service's attributes.
    :returns: Test Service DB object.
    """
    service = get_test_service(**kw)
    # Let DB generate ID if it isn't specified explicitly
    if 'id' not in kw:
        del service['id']
    dbapi = db_api.get_instance()
    return dbapi.create_service(service)
Exemplo n.º 12
0
def create_test_quota(**kw):
    """Create test quota entry in DB and return Quota DB object.

    Function to be used to create test Quota objects in the database.
    :param kw: kwargs with overriding values for quota's attributes.
    :returns: Test Quota DB object.
    """
    quota = get_test_quota(**kw)
    # Let DB generate ID if it isn't specified explicitly
    if 'id' not in kw:
        del quota['id']
    dbapi = db_api.get_instance()
    return dbapi.create_quota(quota)
Exemplo n.º 13
0
def create_test_cluster_template(**kw):
    """Create and return test ClusterTemplate DB object.

    Function to be used to create test ClusterTemplate objects in the database.
    :param kw: kwargs with overriding values for ClusterTemplate's attributes.
    :returns: Test ClusterTemplate DB object.
    """
    cluster_template = get_test_cluster_template(**kw)
    # Let DB generate ID if it isn't specified explicitly
    if 'id' not in kw:
        del cluster_template['id']
    dbapi = db_api.get_instance()
    return dbapi.create_cluster_template(cluster_template)
Exemplo n.º 14
0
    def setUp(self):
        cfg.CONF.set_override("enable_authentication", False)
        super(DbTestCase, self).setUp()

        self.dbapi = dbapi.get_instance()

        global _DB_CACHE
        if not _DB_CACHE:
            _DB_CACHE = Database(sqla_api, migration,
                                 sql_connection=CONF.database.connection,
                                 sqlite_db=CONF.database.sqlite_db,
                                 sqlite_clean_db='clean.sqlite')
        self.useFixture(_DB_CACHE)
Exemplo n.º 15
0
    def setUp(self):
        super(FunctionalTest, self).setUp()
        cfg.CONF.set_override("auth_version", "v2.0",
                              group='keystone_authtoken')
        cfg.CONF.set_override("admin_user", "admin",
                              group='keystone_authtoken')
        self.app = self._make_app()
        self.dbapi = dbapi.get_instance()

        def reset_pecan():
            pecan.set_config({}, overwrite=True)

        self.addCleanup(reset_pecan)
Exemplo n.º 16
0
def create_test_rc(**kw):
    """Create test rc entry in DB and return ReplicationController DB object.
    Function to be used to create test ReplicationController objects in the
    database.
    :param kw: kwargs with overriding values for
               replication controller's attributes.
    :returns: Test ReplicationController DB object.
    """
    replication_controller = get_test_rc(**kw)
    # Let DB generate ID if it isn't specified explicitly
    if 'id' not in kw:
        del replication_controller['id']
    dbapi = db_api.get_instance()
    return dbapi.create_rc(replication_controller)
Exemplo n.º 17
0
    def setUp(self):
        super(FunctionalTest, self).setUp()
        cfg.CONF.set_override("auth_version", "v2.0",
                              group='keystone_authtoken')
        cfg.CONF.set_override("admin_user", "admin",
                              group='keystone_authtoken')
        self.app = self._make_app()
        self.dbapi = dbapi.get_instance()

        def reset_pecan():
            pecan.set_config({}, overwrite=True)

        self.addCleanup(reset_pecan)

        p = mock.patch('magnum.api.controllers.v1.Controller._check_version')
        self._check_version = p.start()
        self.addCleanup(p.stop)
Exemplo n.º 18
0
class Service(base.MagnumObject):
    # Version 1.0: Initial version
    VERSION = '1.0'

    dbapi = dbapi.get_instance()

    fields = {
        'id': int,
        'uuid': obj_utils.str_or_none,
        'name': obj_utils.str_or_none,
        'project_id': obj_utils.str_or_none,
        'user_id': obj_utils.str_or_none,
        'bay_uuid': obj_utils.str_or_none,
        'labels': obj_utils.dict_or_none,
        'selector': obj_utils.dict_or_none,
        'ip': obj_utils.str_or_none,
        'port': obj_utils.int_or_none,
        'manifest_url': obj_utils.str_or_none,
        'manifest': obj_utils.str_or_none,
    }

    @staticmethod
    def _from_db_object(service, db_service):
        """Converts a database entity to a formal object."""
        for field in service.fields:
            # ignore manifest_url as it was used for create service
            if field == 'manifest_url':
                continue
            if field == 'manifest':
                continue
            service[field] = db_service[field]

        service.obj_reset_changes()
        return service

    @staticmethod
    def _from_db_object_list(db_objects, cls, context):
        """Converts a list of database entities to a list of formal objects."""
        return [
            Service._from_db_object(cls(context), obj) for obj in db_objects
        ]

    @base.remotable_classmethod
    def get_by_id(cls, context, service_id):
        """Find a service based on its integer id and return a Service object.

        :param service_id: the id of a service.
        :returns: a :class:`Service` object.
        """
        db_service = cls.dbapi.get_service_by_id(context, service_id)
        service = Service._from_db_object(cls(context), db_service)
        return service

    @base.remotable_classmethod
    def get_by_uuid(cls, context, uuid):
        """Find a service based on uuid and return a :class:`Service` object.

        :param uuid: the uuid of a service.
        :param context: Security context
        :returns: a :class:`Service` object.
        """
        db_service = cls.dbapi.get_service_by_uuid(context, uuid)
        service = Service._from_db_object(cls(context), db_service)
        return service

    @base.remotable_classmethod
    def get_by_name(cls, context, name):
        """Find a service based on service name and
        return a :class:`Service` object.

        :param name: the name of a service.
        :param context: Security context
        :returns: a :class:`Service` object.
        """
        db_service = cls.dbapi.get_service_by_name(context, name)
        service = Service._from_db_object(cls(context), db_service)
        return service

    @base.remotable_classmethod
    def list_by_bay_uuid(cls, context, bay_uuid):
        """Return a list of :class:`Service` objects associated with a given bay.

        :param bay_uuid: the uuid of a bay.
        :param context: Security context
        :returns: a list of class:`Service` object.
        """
        db_services = cls.dbapi.get_services_by_bay_uuid(bay_uuid)
        return Service._from_db_object_list(db_services, cls, context)

    @base.remotable_classmethod
    def list(cls,
             context,
             limit=None,
             marker=None,
             sort_key=None,
             sort_dir=None):
        """Return a list of Service objects.

        :param context: Security context.
        :param limit: maximum number of resources to return in a single result.
        :param marker: pagination marker for large data sets.
        :param sort_key: column to sort results by.
        :param sort_dir: direction to sort. "asc" or "desc".
        :returns: a list of :class:`Service` object.

        """
        db_services = cls.dbapi.get_service_list(context,
                                                 limit=limit,
                                                 marker=marker,
                                                 sort_key=sort_key,
                                                 sort_dir=sort_dir)
        return Service._from_db_object_list(db_services, cls, context)

    @base.remotable
    def create(self, context=None):
        """Create a Service record in the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Service(context)

        """
        values = self.obj_get_changes()
        db_service = self.dbapi.create_service(values)
        self._from_db_object(self, db_service)

    @base.remotable
    def destroy(self, context=None):
        """Delete the Service from the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Service(context)
        """
        self.dbapi.destroy_service(self.uuid)
        self.obj_reset_changes()

    @base.remotable
    def save(self, context=None):
        """Save updates to this Service.

        Updates will be made column by column based on the result
        of self.what_changed().

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Service(context)
        """
        updates = self.obj_get_changes()
        self.dbapi.update_service(self.uuid, updates)

        self.obj_reset_changes()

    @base.remotable
    def refresh(self, context=None):
        """Loads updates for this Service.

        Loads a service with the same uuid from the database and
        checks for updated attributes. Updates are applied from
        the loaded service column by column, if there are any updates.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Service(context)
        """
        current = self.__class__.get_by_uuid(self._context, uuid=self.uuid)
        for field in self.fields:
            if (hasattr(self, base.get_attrname(field))
                    and self[field] != current[field]):
                self[field] = current[field]
Exemplo n.º 19
0
class NodeGroup(base.MagnumPersistentObject, base.MagnumObject,
                base.MagnumObjectDictCompat):
    # Version 1.0: Initial version

    VERSION = '1.0'

    dbapi = dbapi.get_instance()

    fields = {
        'id': fields.IntegerField(),
        'uuid': fields.UUIDField(),
        'name': fields.StringField(),
        'cluster_id': fields.StringField(),
        'project_id': fields.StringField(),
        'docker_volume_size': fields.IntegerField(nullable=True),
        'labels': fields.DictOfStringsField(nullable=True),
        'flavor_id': fields.StringField(nullable=True),
        'image_id': fields.StringField(nullable=True),
        'node_addresses': fields.ListOfStringsField(nullable=True),
        'node_count': fields.IntegerField(nullable=False, default=1),
        'role': fields.StringField(),
        'max_node_count': fields.IntegerField(nullable=True),
        'min_node_count': fields.IntegerField(nullable=False, default=1),
        'is_default': fields.BooleanField(default=False)
    }

    @staticmethod
    def _from_db_object(nodegroup, db_nodegroup):
        """Converts a database entity to a formal object."""
        for field in nodegroup.fields:
            nodegroup[field] = db_nodegroup[field]

        nodegroup.obj_reset_changes()
        return nodegroup

    @staticmethod
    def _from_db_object_list(db_objects, cls, context):
        """Converts a list of database entities to a list of formal objects."""
        return [
            NodeGroup._from_db_object(cls(context), obj) for obj in db_objects
        ]

    @base.remotable_classmethod
    def get(cls, context, cluster_id, nodegroup_id):
        """Find a nodegroup based on its id or uuid and return a NodeGroup.

        :param cluster_id: the of id a cluster.
        :param nodegroup_id: the id of a nodegroup.
        :param context: Security context
        :returns: a :class:`NodeGroup` object.
        """
        if strutils.is_int_like(nodegroup_id):
            return cls.get_by_id(context, cluster_id, nodegroup_id)
        elif uuidutils.is_uuid_like(nodegroup_id):
            return cls.get_by_uuid(context, cluster_id, nodegroup_id)
        else:
            return cls.get_by_name(context, cluster_id, nodegroup_id)

    @base.remotable_classmethod
    def get_by_id(cls, context, cluster, id_):
        """Find a nodegroup based on its integer id and return a NodeGroup.

        :param cluster: the id of a cluster.
        :param id_: the id of a nodegroup.
        :param context: Security context
        :returns: a :class:`NodeGroup` object.
        """
        db_nodegroup = cls.dbapi.get_nodegroup_by_id(context, cluster, id_)
        nodegroup = NodeGroup._from_db_object(cls(context), db_nodegroup)
        return nodegroup

    @base.remotable_classmethod
    def get_by_uuid(cls, context, cluster, uuid):
        """Find a nodegroup based on uuid and return a :class:`NodeGroup`.

        :param cluster: the id of a cluster.
        :param uuid: the uuid of a nodegroup.
        :param context: Security context
        :returns: a :class:`NodeGroup` object.
        """
        db_nodegroup = cls.dbapi.get_nodegroup_by_uuid(context, cluster, uuid)
        nodegroup = NodeGroup._from_db_object(cls(context), db_nodegroup)
        return nodegroup

    @base.remotable_classmethod
    def get_by_name(cls, context, cluster, name):
        """Find a nodegroup based on name and return a NodeGroup object.

        :param cluster: the id of a cluster.
        :param name: the logical name of a nodegroup.
        :param context: Security context
        :returns: a :class:`NodeGroup` object.
        """
        db_nodegroup = cls.dbapi.get_nodegroup_by_name(context, cluster, name)
        nodegroup = NodeGroup._from_db_object(cls(context), db_nodegroup)
        return nodegroup

    @base.remotable_classmethod
    def get_count_all(cls, context, cluster_id):
        """Get count of nodegroups in cluster.

        :param context: The security context
        :param cluster_id: The uuid of the cluster
        :returns: Count of nodegroups in the cluster.
        """
        return cls.dbapi.get_cluster_nodegroup_count(context, cluster_id)

    @base.remotable_classmethod
    def list(cls,
             context,
             cluster,
             limit=None,
             marker=None,
             sort_key=None,
             sort_dir=None,
             filters=None):
        """Return a list of NodeGroup objects.

        :param context: Security context.
        :param cluster: The cluster uuid or name
        :param limit: maximum number of resources to return in a single result.
        :param marker: pagination marker for large data sets.
        :param sort_key: column to sort results by.
        :param sort_dir: direction to sort. "asc" or "desc".
        :param filters: filter dict, can includes 'name', 'node_count',
                        'stack_id', 'node_addresses',
                        'status'(should be a status list).
        :returns: a list of :class:`NodeGroup` objects.

        """
        db_nodegroups = cls.dbapi.list_cluster_nodegroups(context,
                                                          cluster,
                                                          limit=limit,
                                                          marker=marker,
                                                          sort_key=sort_key,
                                                          sort_dir=sort_dir,
                                                          filters=filters)
        return NodeGroup._from_db_object_list(db_nodegroups, cls, context)

    @base.remotable
    def create(self, context=None):
        """Create a nodegroup record in the DB.

        :param context: Security context
        """
        values = self.obj_get_changes()
        db_nodegroup = self.dbapi.create_nodegroup(values)
        self._from_db_object(self, db_nodegroup)

    @base.remotable
    def destroy(self, context=None):
        """Delete the NodeGroup from the DB.

        :param context: Security context.
        """
        self.dbapi.destroy_nodegroup(self.cluster_id, self.uuid)
        self.obj_reset_changes()

    @base.remotable
    def save(self, context=None):
        """Save updates to this NodeGroup.

        Updates will be made column by column based on the result
        of self.what_changed().

        :param context: Security context.
        """
        updates = self.obj_get_changes()
        self.dbapi.update_nodegroup(self.cluster_id, self.uuid, updates)

        self.obj_reset_changes()

    @base.remotable
    def refresh(self, context=None):
        """Loads updates for this NodeGroup.

        Loads a NodeGroup with the same uuid from the database and
        checks for updated attributes. Updates are applied from
        the loaded NogeGroup column by column, if there are any updates.

        :param context: Security context.
        """
        current = self.__class__.get_by_uuid(self._context,
                                             cluster=self.cluster_id,
                                             uuid=self.uuid)
        for field in self.fields:
            if self.obj_attr_is_set(field) and self[field] != current[field]:
                self[field] = current[field]

    @base.remotable_classmethod
    def update_nodegroup(cls, context, cluster_id, nodegroup_id, values):
        """Updates a NodeGroup.

        :param context: Security context.
        :param cluster_id:
        :param nodegroup_id:
        :param values: a dictionary with the changed values
        """
        current = cls.get(context, cluster_id, nodegroup_id)
        db_nodegroup = cls.dbapi.update_nodegroup(cluster_id, current.uuid,
                                                  values)
        return NodeGroup._from_db_object(cls(context), db_nodegroup)
Exemplo n.º 20
0
class Service(base.MagnumPersistentObject, base.MagnumObject,
              base.MagnumObjectDictCompat):
    # Version 1.0: Initial version
    VERSION = '1.0'

    dbapi = dbapi.get_instance()

    fields = {
        'id': fields.IntegerField(),
        'uuid': fields.StringField(nullable=True),
        'name': fields.StringField(nullable=True),
        'project_id': fields.StringField(nullable=True),
        'user_id': fields.StringField(nullable=True),
        'bay_uuid': fields.StringField(nullable=True),
        'labels': fields.DictOfStringsField(nullable=True),
        'selector': fields.DictOfStringsField(nullable=True),
        'ip': fields.StringField(nullable=True),
        'ports': magnum_fields.ListOfDictsField(nullable=True),
        'manifest_url': fields.StringField(nullable=True),
        'manifest': fields.StringField(nullable=True),
    }

    @base.remotable_classmethod
    def get_by_uuid(cls, context, uuid, bay_uuid, k8s_api):
        """Find a service based on service uuid and UUID of the Bay

        :param context: Security context
        :param uuid: the uuid of a service.
        :param bay_uuid: the UUID of the Bay
        :param k8s_api: k8s API object

        :returns: a :class:`Service` object.
        """
        try:
            resp = k8s_api.list_namespaced_service(namespace='default')
        except rest.ApiException as err:
            raise exception.KubernetesAPIFailed(err=err)

        if resp is None:
            raise exception.ServiceListNotFound(bay_uuid=bay_uuid)

        service = {}
        for service_entry in resp.items:
            if service_entry.metadata.uid == uuid:
                service['uuid'] = service_entry.metadata.uid
                service['name'] = service_entry.metadata.name
                service['project_id'] = context.project_id
                service['user_id'] = context.user_id
                service['bay_uuid'] = bay_uuid
                service['labels'] = ast.literal_eval(
                    service_entry.metadata.labels)
                if not service_entry.spec.selector:
                    service['selector'] = {}
                else:
                    service['selector'] = ast.literal_eval(
                        service_entry.spec.selector)
                service['ip'] = service_entry.spec.cluster_ip
                service_value = []
                for p in service_entry.spec.ports:
                    ports = p.to_dict()
                    if not ports['name']:
                        ports['name'] = 'k8s-service'
                    service_value.append(ports)

                service['ports'] = service_value

                service_obj = Service(context, **service)
                return service_obj
        raise exception.ServiceNotFound(service=uuid)

    @base.remotable_classmethod
    def get_by_name(cls, context, name, bay_uuid, k8s_api):
        """Find a service based on service name and UUID of the Bay

        :param context: Security context
        :param name: the name of a service.
        :param bay_uuid: the UUID of the Bay
        :param k8s_api: k8s API object

        :returns: a :class:`Service` object.
        """
        try:
            resp = k8s_api.read_namespaced_service(name=name,
                                                   namespace='default')
        except rest.ApiException as err:
            raise exception.KubernetesAPIFailed(err=err)

        if resp is None:
            raise exception.ServiceNotFound(service=name)

        service = {}
        service['uuid'] = resp.metadata.uid
        service['name'] = resp.metadata.name
        service['project_id'] = context.project_id
        service['user_id'] = context.user_id
        service['bay_uuid'] = bay_uuid
        service['labels'] = ast.literal_eval(resp.metadata.labels)
        if not resp.spec.selector:
            service['selector'] = {}
        else:
            service['selector'] = ast.literal_eval(resp.spec.selector)
        service['ip'] = resp.spec.cluster_ip
        service_value = []
        for p in resp.spec.ports:
            ports = p.to_dict()
            if not ports['name']:
                ports['name'] = 'k8s-service'
            service_value.append(ports)

        service['ports'] = service_value

        service_obj = Service(context, **service)
        return service_obj
Exemplo n.º 21
0
class Pod(base.MagnumPersistentObject, base.MagnumObject,
          base.MagnumObjectDictCompat):
    # Version 1.0: Initial version
    # Version 1.1: Remove unused Pod object API 'list_by_bay_uuid'
    VERSION = '1.1'

    dbapi = dbapi.get_instance()

    fields = {
        'id': fields.IntegerField(),
        'uuid': fields.StringField(nullable=True),
        'name': fields.StringField(nullable=True),
        'desc': fields.StringField(nullable=True),
        'project_id': fields.StringField(nullable=True),
        'user_id': fields.StringField(nullable=True),
        'bay_uuid': fields.StringField(nullable=True),
        'images': fields.ListOfStringsField(nullable=True),
        'labels': fields.DictOfStringsField(nullable=True),
        'status': fields.StringField(nullable=True),
        'manifest_url': fields.StringField(nullable=True),
        'manifest': fields.StringField(nullable=True),
        'host': fields.StringField(nullable=True),
    }

    @staticmethod
    def _from_db_object(pod, db_pod):
        """Converts a database entity to a formal object."""
        for field in pod.fields:
            # ignore manifest_url as it was used for create pod
            if field == 'manifest_url':
                continue
            if field == 'manifest':
                continue
            pod[field] = db_pod[field]

        pod.obj_reset_changes()
        return pod

    @staticmethod
    def _from_db_object_list(db_objects, cls, context):
        """Converts a list of database entities to a list of formal objects."""
        return [Pod._from_db_object(cls(context), obj) for obj in db_objects]

    @base.remotable_classmethod
    def get_by_id(cls, context, pod_id):
        """Find a pod based on its integer id and return a Pod object.

        :param pod_id: the id of a pod.
        :returns: a :class:`Pod` object.
        """
        db_pod = cls.dbapi.get_pod_by_id(context, pod_id)
        pod = Pod._from_db_object(cls(context), db_pod)
        return pod

    @base.remotable_classmethod
    def get_by_uuid(cls, context, uuid):
        """Find a pod based on uuid and return a :class:`Pod` object.

        :param uuid: the uuid of a pod.
        :param context: Security context
        :returns: a :class:`Pod` object.
        """
        db_pod = cls.dbapi.get_pod_by_uuid(context, uuid)
        pod = Pod._from_db_object(cls(context), db_pod)
        return pod

    @base.remotable_classmethod
    def get_by_name(cls, context, name):
        """Find a pod based on pod name and return a :class:`Pod` object.

        :param name: the name of a pod.
        :param context: Security context
        :returns: a :class:`Pod` object.
        """
        db_pod = cls.dbapi.get_pod_by_name(name)
        pod = Pod._from_db_object(cls(context), db_pod)
        return pod

    @base.remotable_classmethod
    def list(cls,
             context,
             limit=None,
             marker=None,
             sort_key=None,
             sort_dir=None):
        """Return a list of Pod objects.

        :param context: Security context.
        :param limit: maximum number of resources to return in a single result.
        :param marker: pagination marker for large data sets.
        :param sort_key: column to sort results by.
        :param sort_dir: direction to sort. "asc" or "desc".
        :returns: a list of :class:`Pod` object.

        """
        db_pods = cls.dbapi.get_pod_list(context,
                                         limit=limit,
                                         marker=marker,
                                         sort_key=sort_key,
                                         sort_dir=sort_dir)
        return Pod._from_db_object_list(db_pods, cls, context)

    @base.remotable
    def create(self, context=None):
        """Create a Pod record in the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Pod(context)

        """
        values = self.obj_get_changes()
        db_pod = self.dbapi.create_pod(values)
        self._from_db_object(self, db_pod)

    @base.remotable
    def destroy(self, context=None):
        """Delete the Pod from the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Pod(context)
        """
        self.dbapi.destroy_pod(self.uuid)
        self.obj_reset_changes()

    @base.remotable
    def save(self, context=None):
        """Save updates to this Pod.

        Updates will be made column by column based on the result
        of self.what_changed().

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Pod(context)
        """
        updates = self.obj_get_changes()
        self.dbapi.update_pod(self.uuid, updates)

        self.obj_reset_changes()

    @base.remotable
    def refresh(self, context=None):
        """Loads updates for this Pod.

        Loads a pod with the same uuid from the database and
        checks for updated attributes. Updates are applied from
        the loaded pod column by column, if there are any updates.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Pod(context)
        """
        current = self.__class__.get_by_uuid(self._context, uuid=self.uuid)
        for field in self.fields:
            if field == 'manifest_url':
                continue
            if field == 'manifest':
                continue
            if self.obj_attr_is_set(field) and self[field] != current[field]:
                self[field] = current[field]
Exemplo n.º 22
0
class BayModel(base.MagnumObject):
    # Version 1.0: Initial version
    VERSION = '1.0'

    dbapi = dbapi.get_instance()

    fields = {
        'id': int,
        'uuid': obj_utils.str_or_none,
        'project_id': obj_utils.str_or_none,
        'user_id': obj_utils.str_or_none,
        'name': obj_utils.str_or_none,
        'image_id': obj_utils.str_or_none,
        'flavor_id': obj_utils.str_or_none,
        'master_flavor_id': obj_utils.str_or_none,
        'keypair_id': obj_utils.str_or_none,
        'dns_nameserver': obj_utils.str_or_none,
        'external_network_id': obj_utils.str_or_none,
        'fixed_network': obj_utils.str_or_none,
        'apiserver_port': obj_utils.int_or_none,
        'docker_volume_size': obj_utils.int_or_none,
        'ssh_authorized_key': obj_utils.str_or_none,
    }

    @staticmethod
    def _from_db_object(baymodel, db_baymodel):
        """Converts a database entity to a formal object."""
        for field in baymodel.fields:
            baymodel[field] = db_baymodel[field]

        baymodel.obj_reset_changes()
        return baymodel

    @staticmethod
    def _from_db_object_list(db_objects, cls, context):
        """Converts a list of database entities to a list of formal objects."""
        return [
            BayModel._from_db_object(cls(context), obj) for obj in db_objects
        ]

    @base.remotable_classmethod
    def get(cls, context, baymodel_id):
        """Find a baymodel based on its id or uuid and return a BayModel object.

        :param baymodel_id: the id *or* uuid of a baymodel.
        :returns: a :class:`BayModel` object.
        """
        if utils.is_int_like(baymodel_id):
            return cls.get_by_id(context, baymodel_id)
        elif utils.is_uuid_like(baymodel_id):
            return cls.get_by_uuid(context, baymodel_id)
        else:
            raise exception.InvalidIdentity(identity=baymodel_id)

    @base.remotable_classmethod
    def get_by_id(cls, context, baymodel_id):
        """Find a baymodel based on its integer id and return a BayModel object.

        :param baymodel_id: the id of a baymodel.
        :returns: a :class:`BayModel` object.
        """
        db_baymodel = cls.dbapi.get_baymodel_by_id(context, baymodel_id)
        baymodel = BayModel._from_db_object(cls(context), db_baymodel)
        return baymodel

    @base.remotable_classmethod
    def get_by_uuid(cls, context, uuid):
        """Find a baymodel based on uuid and return a :class:`BayModel` object.

        :param uuid: the uuid of a baymodel.
        :param context: Security context
        :returns: a :class:`BayModel` object.
        """
        db_baymodel = cls.dbapi.get_baymodel_by_uuid(context, uuid)
        baymodel = BayModel._from_db_object(cls(context), db_baymodel)
        return baymodel

    @base.remotable_classmethod
    def get_by_name(cls, context, name):
        """Find a baymodel based on name and return a :class:`BayModel` object.

        :param name: the name of a baymodel.
        :param context: Security context
        :returns: a :class:`BayModel` object.
        """
        db_baymodel = cls.dbapi.get_baymodel_by_name(context, name)
        baymodel = BayModel._from_db_object(cls(context), db_baymodel)
        return baymodel

    @base.remotable_classmethod
    def list(cls,
             context,
             limit=None,
             marker=None,
             sort_key=None,
             sort_dir=None):
        """Return a list of BayModel objects.

        :param context: Security context.
        :param limit: maximum number of resources to return in a single result.
        :param marker: pagination marker for large data sets.
        :param sort_key: column to sort results by.
        :param sort_dir: direction to sort. "asc" or "desc".
        :returns: a list of :class:`BayModel` object.

        """
        db_baymodels = cls.dbapi.get_baymodel_list(context,
                                                   limit=limit,
                                                   marker=marker,
                                                   sort_key=sort_key,
                                                   sort_dir=sort_dir)
        return BayModel._from_db_object_list(db_baymodels, cls, context)

    @base.remotable
    def create(self, context=None):
        """Create a BayModel record in the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: BayModel(context)

        """
        values = self.obj_get_changes()
        db_baymodel = self.dbapi.create_baymodel(values)
        self._from_db_object(self, db_baymodel)

    @base.remotable
    def destroy(self, context=None):
        """Delete the BayModel from the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: BayModel(context)
        """
        self.dbapi.destroy_baymodel(self.uuid)
        self.obj_reset_changes()

    @base.remotable
    def save(self, context=None):
        """Save updates to this BayModel.

        Updates will be made column by column based on the result
        of self.what_changed().

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: BayModel(context)
        """
        updates = self.obj_get_changes()
        self.dbapi.update_baymodel(self.uuid, updates)

        self.obj_reset_changes()

    @base.remotable
    def refresh(self, context=None):
        """Loads updates for this BayModel.

        Loads a baymodel with the same uuid from the database and
        checks for updated attributes. Updates are applied from
        the loaded baymodel column by column, if there are any updates.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: BayModel(context)
        """
        current = self.__class__.get_by_uuid(self._context, uuid=self.uuid)
        for field in self.fields:
            if (hasattr(self, base.get_attrname(field))
                    and self[field] != current[field]):
                self[field] = current[field]
Exemplo n.º 23
0
class Cluster(base.MagnumPersistentObject, base.MagnumObject,
              base.MagnumObjectDictCompat):
    # Version 1.0: Initial version
    # Version 1.1: Added 'bay_create_timeout' field
    # Version 1.2: Add 'registry_trust_id' field
    # Version 1.3: Added 'baymodel' field
    # Version 1.4: Added more types of status to bay's status field
    # Version 1.5: Rename 'registry_trust_id' to 'trust_id'
    #              Add 'trustee_user_name', 'trustee_password',
    #              'trustee_user_id' field
    # Version 1.6: Add rollback support for Bay
    # Version 1.7: Added 'coe_version'  and 'container_version' fields
    # Version 1.8: Rename 'baymodel' to 'cluster_template'
    # Version 1.9: Rename table name from 'bay' to 'cluster'
    #              Rename 'baymodel_id' to 'cluster_template_id'
    #              Rename 'bay_create_timeout' to 'create_timeout'
    # Version 1.10: Added 'keypair' field
    # Version 1.11: Added 'RESUME_FAILED' in status field
    # Version 1.12: Added 'get_stats' method
    # Version 1.13: Added get_count_all method
    # Version 1.14: Added 'docker_volume_size' field
    # Version 1.15: Added 'labels' field
    # Version 1.16: Added 'master_flavor_id' field
    # Version 1.17: Added 'flavor_id' field
    # Version 1.18: Added 'health_status' and 'health_status_reason' field

    VERSION = '1.18'

    dbapi = dbapi.get_instance()

    fields = {
        'id': fields.IntegerField(),
        'uuid': fields.UUIDField(nullable=True),
        'name': fields.StringField(nullable=True),
        'project_id': fields.StringField(nullable=True),
        'user_id': fields.StringField(nullable=True),
        'cluster_template_id': fields.StringField(nullable=True),
        'keypair': fields.StringField(nullable=True),
        'docker_volume_size': fields.IntegerField(nullable=True),
        'labels': fields.DictOfStringsField(nullable=True),
        'master_flavor_id': fields.StringField(nullable=True),
        'flavor_id': fields.StringField(nullable=True),
        'stack_id': fields.StringField(nullable=True),
        'status': m_fields.ClusterStatusField(nullable=True),
        'status_reason': fields.StringField(nullable=True),
        'health_status': m_fields.ClusterHealthStatusField(nullable=True),
        'health_status_reason': fields.DictOfStringsField(nullable=True),
        'create_timeout': fields.IntegerField(nullable=True),
        'api_address': fields.StringField(nullable=True),
        'node_addresses': fields.ListOfStringsField(nullable=True),
        'node_count': fields.IntegerField(nullable=True),
        'master_count': fields.IntegerField(nullable=True),
        'discovery_url': fields.StringField(nullable=True),
        'master_addresses': fields.ListOfStringsField(nullable=True),
        'ca_cert_ref': fields.StringField(nullable=True),
        'magnum_cert_ref': fields.StringField(nullable=True),
        'cluster_template': fields.ObjectField('ClusterTemplate'),
        'trust_id': fields.StringField(nullable=True),
        'trustee_username': fields.StringField(nullable=True),
        'trustee_password': fields.StringField(nullable=True),
        'trustee_user_id': fields.StringField(nullable=True),
        'coe_version': fields.StringField(nullable=True),
        'container_version': fields.StringField(nullable=True)
    }

    @staticmethod
    def _from_db_object(cluster, db_cluster):
        """Converts a database entity to a formal object."""
        for field in cluster.fields:
            if field != 'cluster_template':
                cluster[field] = db_cluster[field]

        # Note(eliqiao): The following line needs to be placed outside the
        # loop because there is a dependency from cluster_template to
        # cluster_template_id. The cluster_template_id must be populated
        # first in the loop before it can be used to find the cluster_template.
        cluster['cluster_template'] = ClusterTemplate.get_by_uuid(
            cluster._context, cluster.cluster_template_id)

        cluster.obj_reset_changes()
        return cluster

    @staticmethod
    def _from_db_object_list(db_objects, cls, context):
        """Converts a list of database entities to a list of formal objects."""
        return [
            Cluster._from_db_object(cls(context), obj) for obj in db_objects
        ]

    @base.remotable_classmethod
    def get(cls, context, cluster_id):
        """Find a cluster based on its id or uuid and return a Cluster object.

        :param cluster_id: the id *or* uuid of a cluster.
        :param context: Security context
        :returns: a :class:`Cluster` object.
        """
        if strutils.is_int_like(cluster_id):
            return cls.get_by_id(context, cluster_id)
        elif uuidutils.is_uuid_like(cluster_id):
            return cls.get_by_uuid(context, cluster_id)
        else:
            raise exception.InvalidIdentity(identity=cluster_id)

    @base.remotable_classmethod
    def get_by_id(cls, context, cluster_id):
        """Find a cluster based on its integer id and return a Cluster object.

        :param cluster_id: the id of a cluster.
        :param context: Security context
        :returns: a :class:`Cluster` object.
        """
        db_cluster = cls.dbapi.get_cluster_by_id(context, cluster_id)
        cluster = Cluster._from_db_object(cls(context), db_cluster)
        return cluster

    @base.remotable_classmethod
    def get_by_uuid(cls, context, uuid):
        """Find a cluster based on uuid and return a :class:`Cluster` object.

        :param uuid: the uuid of a cluster.
        :param context: Security context
        :returns: a :class:`Cluster` object.
        """
        db_cluster = cls.dbapi.get_cluster_by_uuid(context, uuid)
        cluster = Cluster._from_db_object(cls(context), db_cluster)
        return cluster

    @base.remotable_classmethod
    def get_count_all(cls, context, filters=None):
        """Get count of matching clusters.

        :param context: The security context
        :param filters: filter dict, can includes 'cluster_template_id',
                        'name', 'node_count', 'stack_id', 'api_address',
                        'node_addresses', 'project_id', 'user_id',
                        'status'(should be a status list), 'master_count'.
        :returns: Count of matching clusters.
        """
        return cls.dbapi.get_cluster_count_all(context, filters=filters)

    @base.remotable_classmethod
    def get_by_name(cls, context, name):
        """Find a cluster based on name and return a Cluster object.

        :param name: the logical name of a cluster.
        :param context: Security context
        :returns: a :class:`Cluster` object.
        """
        db_cluster = cls.dbapi.get_cluster_by_name(context, name)
        cluster = Cluster._from_db_object(cls(context), db_cluster)
        return cluster

    @base.remotable_classmethod
    def list(cls,
             context,
             limit=None,
             marker=None,
             sort_key=None,
             sort_dir=None,
             filters=None):
        """Return a list of Cluster objects.

        :param context: Security context.
        :param limit: maximum number of resources to return in a single result.
        :param marker: pagination marker for large data sets.
        :param sort_key: column to sort results by.
        :param sort_dir: direction to sort. "asc" or "desc".
        :param filters: filter dict, can includes 'cluster_template_id',
                        'name', 'node_count', 'stack_id', 'api_address',
                        'node_addresses', 'project_id', 'user_id',
                        'status'(should be a status list), 'master_count'.
        :returns: a list of :class:`Cluster` object.

        """
        db_clusters = cls.dbapi.get_cluster_list(context,
                                                 limit=limit,
                                                 marker=marker,
                                                 sort_key=sort_key,
                                                 sort_dir=sort_dir,
                                                 filters=filters)
        return Cluster._from_db_object_list(db_clusters, cls, context)

    @base.remotable_classmethod
    def get_stats(cls, context, project_id=None):
        """Return a list of Cluster objects.

        :param context: Security context.
        :param project_id: project id
        """
        return cls.dbapi.get_cluster_stats(project_id)

    @base.remotable
    def create(self, context=None):
        """Create a Cluster record in the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Cluster(context)

        """
        values = self.obj_get_changes()
        db_cluster = self.dbapi.create_cluster(values)
        self._from_db_object(self, db_cluster)

    @base.remotable
    def destroy(self, context=None):
        """Delete the Cluster from the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Cluster(context)
        """
        self.dbapi.destroy_cluster(self.uuid)
        self.obj_reset_changes()

    @base.remotable
    def save(self, context=None):
        """Save updates to this Cluster.

        Updates will be made column by column based on the result
        of self.what_changed().

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Cluster(context)
        """
        updates = self.obj_get_changes()
        self.dbapi.update_cluster(self.uuid, updates)

        self.obj_reset_changes()

    @base.remotable
    def refresh(self, context=None):
        """Loads updates for this Cluster.

        Loads a Cluster with the same uuid from the database and
        checks for updated attributes. Updates are applied from
        the loaded Cluster column by column, if there are any updates.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Cluster(context)
        """
        current = self.__class__.get_by_uuid(self._context, uuid=self.uuid)
        for field in self.fields:
            if self.obj_attr_is_set(field) and self[field] != current[field]:
                self[field] = current[field]
Exemplo n.º 24
0
 def setUp(self):
     super(SqlAlchemyCustomTypesTestCase, self).setUp()
     self.dbapi = dbapi.get_instance()
Exemplo n.º 25
0
class MagnumService(base.MagnumPersistentObject, base.MagnumObject,
                    base.MagnumObjectDictCompat):
    # Version 1.0: Initial version
    VERSION = '1.0'

    dbapi = dbapi.get_instance()

    fields = {
        'id': fields.IntegerField(),
        'host': fields.StringField(nullable=True),
        'binary': fields.StringField(nullable=True),
        'disabled': fields.BooleanField(),
        'disabled_reason': fields.StringField(nullable=True),
        'last_seen_up': fields.DateTimeField(nullable=True),
        'forced_down': fields.BooleanField(),
        'report_count': fields.IntegerField(),
    }

    @staticmethod
    def _from_db_object(magnum_service, db_magnum_service):
        """Converts a database entity to a formal object."""
        for field in magnum_service.fields:
            magnum_service[field] = db_magnum_service[field]

        magnum_service.obj_reset_changes()
        return magnum_service

    @staticmethod
    def _from_db_object_list(db_objects, cls, context):
        """Converts a list of database entities to a list of formal objects."""
        return [
            MagnumService._from_db_object(cls(context), obj)
            for obj in db_objects
        ]

    @base.remotable_classmethod
    def get_by_host_and_binary(cls, context, host, binary):
        """Find a magnum_service based on its hostname and binary.

        :param host: The host on which the binary is running.
        :param binary: The name of the binary.
        :returns: a :class:`MagnumService` object.
        """
        db_magnum_service = cls.dbapi.get_magnum_service_by_host_and_binary(
            context, host, binary)
        if db_magnum_service is None:
            return None
        magnum_service = MagnumService._from_db_object(cls(context),
                                                       db_magnum_service)
        return magnum_service

    @base.remotable_classmethod
    def list(cls,
             context,
             limit=None,
             marker=None,
             sort_key=None,
             sort_dir=None):
        """Return a list of MagnumService objects.

        :param context: Security context.
        :param limit: maximum number of resources to return in a single result.
        :param marker: pagination marker for large data sets.
        :param sort_key: column to sort results by.
        :param sort_dir: direction to sort. "asc" or "desc".
        :returns: a list of :class:`MagnumService` object.

        """
        db_magnum_services = cls.dbapi.get_magnum_service_list(
            context,
            limit=limit,
            marker=marker,
            sort_key=sort_key,
            sort_dir=sort_dir)
        return MagnumService._from_db_object_list(db_magnum_services, cls,
                                                  context)

    @base.remotable
    def create(self, context=None):
        """Create a MagnumService record in the DB.

        :param context: Security context.
        """
        values = self.obj_get_changes()
        db_magnum_service = self.dbapi.create_magnum_service(values)
        self._from_db_object(self, db_magnum_service)

    @base.remotable
    def destroy(self, context=None):
        """Delete the MagnumService from the DB.

        :param context: Security context.
        """
        self.dbapi.destroy_magnum_service(self.id)
        self.obj_reset_changes()

    @base.remotable
    def save(self, context=None):
        """Save updates to this MagnumService.

        Updates will be made column by column based on the result
        of self.what_changed().

        :param context: Security context.
        """
        updates = self.obj_get_changes()
        self.dbapi.update_magnum_service(self.id, updates)
        self.obj_reset_changes()

    @base.remotable
    def report_state_up(self, context=None):
        """Touching the magnum_service record to show aliveness.

        :param context: Security context.
        """
        self.report_count += 1
        self.save(context)
Exemplo n.º 26
0
class BayModel(base.MagnumPersistentObject, base.MagnumObject,
               base.MagnumObjectDictCompat):
    # Version 1.0: Initial version
    # Version 1.1: Add 'registry_enabled' field
    # Version 1.2: Added 'network_driver' field
    # Version 1.3: Added 'labels' attribute
    # Version 1.4: Added 'insecure' attribute
    # Version 1.5: Changed type of 'coe' from StringField to BayTypeField
    # Version 1.6: Change 'insecure' to 'tls_disabled'
    # Version 1.7: Added 'public' field
    # Version 1.8: Added 'server_type' field
    # Version 1.9: Added 'volume_driver' field
    # Version 1.10: Removed 'ssh_authorized_key' field
    # Version 1.11: Added 'insecure_registry' field
    # Version 1.12: Added 'docker_storage_driver' field
    # Version 1.13: Added 'master_lb_enabled' field
    # Version 1.14: Added 'fixed_subnet' field
    # Version 1.15: Added 'floating_ip_enabled' field
    VERSION = '1.15'

    dbapi = dbapi.get_instance()

    fields = {
        'id': fields.IntegerField(),
        'uuid': fields.StringField(nullable=True),
        'project_id': fields.StringField(nullable=True),
        'user_id': fields.StringField(nullable=True),
        'name': fields.StringField(nullable=True),
        'image_id': fields.StringField(nullable=True),
        'flavor_id': fields.StringField(nullable=True),
        'master_flavor_id': fields.StringField(nullable=True),
        'keypair_id': fields.StringField(nullable=True),
        'dns_nameserver': fields.StringField(nullable=True),
        'external_network_id': fields.StringField(nullable=True),
        'fixed_network': fields.StringField(nullable=True),
        'fixed_subnet': fields.StringField(nullable=True),
        'network_driver': fields.StringField(nullable=True),
        'volume_driver': fields.StringField(nullable=True),
        'apiserver_port': fields.IntegerField(nullable=True),
        'docker_volume_size': fields.IntegerField(nullable=True),
        'docker_storage_driver':
        m_fields.DockerStorageDriverField(nullable=True),
        'cluster_distro': fields.StringField(nullable=True),
        'coe': m_fields.BayTypeField(nullable=True),
        'http_proxy': fields.StringField(nullable=True),
        'https_proxy': fields.StringField(nullable=True),
        'no_proxy': fields.StringField(nullable=True),
        'registry_enabled': fields.BooleanField(default=False),
        'labels': fields.DictOfStringsField(nullable=True),
        'tls_disabled': fields.BooleanField(default=False),
        'public': fields.BooleanField(default=False),
        'server_type': fields.StringField(nullable=True),
        'insecure_registry': fields.StringField(nullable=True),
        'master_lb_enabled': fields.BooleanField(default=False),
        'floating_ip_enabled': fields.BooleanField(default=True),
    }

    @staticmethod
    def _from_db_object(baymodel, db_baymodel):
        """Converts a database entity to a formal object."""
        for field in baymodel.fields:
            baymodel[field] = db_baymodel[field]

        baymodel.obj_reset_changes()
        return baymodel

    @staticmethod
    def _from_db_object_list(db_objects, cls, context):
        """Converts a list of database entities to a list of formal objects."""
        return [
            BayModel._from_db_object(cls(context), obj) for obj in db_objects
        ]

    @base.remotable_classmethod
    def get(cls, context, baymodel_id):
        """Find a baymodel based on its id or uuid and return a BayModel object.

        :param baymodel_id: the id *or* uuid of a baymodel.
        :param context: Security context
        :returns: a :class:`BayModel` object.
        """
        if strutils.is_int_like(baymodel_id):
            return cls.get_by_id(context, baymodel_id)
        elif uuidutils.is_uuid_like(baymodel_id):
            return cls.get_by_uuid(context, baymodel_id)
        else:
            raise exception.InvalidIdentity(identity=baymodel_id)

    @base.remotable_classmethod
    def get_by_id(cls, context, baymodel_id):
        """Find a baymodel based on its integer id and return a BayModel object.

        :param baymodel_id: the id of a baymodel.
        :param context: Security context
        :returns: a :class:`BayModel` object.
        """
        db_baymodel = cls.dbapi.get_baymodel_by_id(context, baymodel_id)
        baymodel = BayModel._from_db_object(cls(context), db_baymodel)
        return baymodel

    @base.remotable_classmethod
    def get_by_uuid(cls, context, uuid):
        """Find a baymodel based on uuid and return a :class:`BayModel` object.

        :param uuid: the uuid of a baymodel.
        :param context: Security context
        :returns: a :class:`BayModel` object.
        """
        db_baymodel = cls.dbapi.get_baymodel_by_uuid(context, uuid)
        baymodel = BayModel._from_db_object(cls(context), db_baymodel)
        return baymodel

    @base.remotable_classmethod
    def get_by_name(cls, context, name):
        """Find a baymodel based on name and return a :class:`BayModel` object.

        :param name: the name of a baymodel.
        :param context: Security context
        :returns: a :class:`BayModel` object.
        """
        db_baymodel = cls.dbapi.get_baymodel_by_name(context, name)
        baymodel = BayModel._from_db_object(cls(context), db_baymodel)
        return baymodel

    @base.remotable_classmethod
    def list(cls,
             context,
             limit=None,
             marker=None,
             sort_key=None,
             sort_dir=None):
        """Return a list of BayModel objects.

        :param context: Security context.
        :param limit: maximum number of resources to return in a single result.
        :param marker: pagination marker for large data sets.
        :param sort_key: column to sort results by.
        :param sort_dir: direction to sort. "asc" or "desc".
        :returns: a list of :class:`BayModel` object.

        """
        db_baymodels = cls.dbapi.get_baymodel_list(context,
                                                   limit=limit,
                                                   marker=marker,
                                                   sort_key=sort_key,
                                                   sort_dir=sort_dir)
        return BayModel._from_db_object_list(db_baymodels, cls, context)

    @base.remotable
    def create(self, context=None):
        """Create a BayModel record in the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: BayModel(context)

        """
        values = self.obj_get_changes()
        db_baymodel = self.dbapi.create_baymodel(values)
        self._from_db_object(self, db_baymodel)

    @base.remotable
    def destroy(self, context=None):
        """Delete the BayModel from the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: BayModel(context)
        """
        self.dbapi.destroy_baymodel(self.uuid)
        self.obj_reset_changes()

    @base.remotable
    def save(self, context=None):
        """Save updates to this BayModel.

        Updates will be made column by column based on the result
        of self.what_changed().

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: BayModel(context)
        """
        updates = self.obj_get_changes()
        self.dbapi.update_baymodel(self.uuid, updates)

        self.obj_reset_changes()

    @base.remotable
    def refresh(self, context=None):
        """Loads updates for this BayModel.

        Loads a baymodel with the same uuid from the database and
        checks for updated attributes. Updates are applied from
        the loaded baymodel column by column, if there are any updates.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: BayModel(context)
        """
        current = self.__class__.get_by_uuid(self._context, uuid=self.uuid)
        for field in self.fields:
            if self.obj_attr_is_set(field) and self[field] != current[field]:
                self[field] = current[field]
Exemplo n.º 27
0
class Container(base.MagnumPersistentObject, base.MagnumObject,
                base.MagnumObjectDictCompat):
    # Version 1.0: Initial version
    # Version 1.1: Add memory field
    VERSION = '1.1'

    dbapi = dbapi.get_instance()

    fields = {
        'id': fields.IntegerField(),
        'uuid': fields.StringField(nullable=True),
        'name': fields.StringField(nullable=True),
        'project_id': fields.StringField(nullable=True),
        'user_id': fields.StringField(nullable=True),
        'image': fields.StringField(nullable=True),
        'command': fields.StringField(nullable=True),
        'bay_uuid': fields.StringField(nullable=True),
        'status': m_fields.ContainerStatusField(nullable=True),
        'memory': fields.StringField(nullable=True),
    }

    @staticmethod
    def _from_db_object(container, db_container):
        """Converts a database entity to a formal object."""
        for field in container.fields:
            container[field] = db_container[field]

        container.obj_reset_changes()
        return container

    @staticmethod
    def _from_db_object_list(db_objects, cls, context):
        """Converts a list of database entities to a list of formal objects."""
        return [
            Container._from_db_object(cls(context), obj) for obj in db_objects
        ]

    @base.remotable_classmethod
    def get_by_id(cls, context, container_id):
        """Find a container based on its integer id and return a Container object.

        :param container_id: the id of a container.
        :returns: a :class:`Container` object.
        """
        db_container = cls.dbapi.get_container_by_id(context, container_id)
        container = Container._from_db_object(cls(context), db_container)
        return container

    @base.remotable_classmethod
    def get_by_uuid(cls, context, uuid):
        """Find a container based on uuid and return a :class:`Container` object.

        :param uuid: the uuid of a container.
        :param context: Security context
        :returns: a :class:`Container` object.
        """
        db_container = cls.dbapi.get_container_by_uuid(context, uuid)
        container = Container._from_db_object(cls(context), db_container)
        return container

    @base.remotable_classmethod
    def get_by_name(cls, context, name):
        """Find a bay based on name and return a Bay object.

        :param name: the logical name of a bay.
        :param context: Security context
        :returns: a :class:`Bay` object.
        """
        db_bay = cls.dbapi.get_container_by_name(context, name)
        bay = Container._from_db_object(cls(context), db_bay)
        return bay

    @base.remotable_classmethod
    def list(cls,
             context,
             limit=None,
             marker=None,
             sort_key=None,
             sort_dir=None):
        """Return a list of Container objects.

        :param context: Security context.
        :param limit: maximum number of resources to return in a single result.
        :param marker: pagination marker for large data sets.
        :param sort_key: column to sort results by.
        :param sort_dir: direction to sort. "asc" or "desc".
        :returns: a list of :class:`Container` object.

        """
        db_containers = cls.dbapi.get_container_list(context,
                                                     limit=limit,
                                                     marker=marker,
                                                     sort_key=sort_key,
                                                     sort_dir=sort_dir)
        return Container._from_db_object_list(db_containers, cls, context)

    @base.remotable
    def create(self, context=None):
        """Create a Container record in the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Container(context)

        """
        values = self.obj_get_changes()
        db_container = self.dbapi.create_container(values)
        self._from_db_object(self, db_container)

    @base.remotable
    def destroy(self, context=None):
        """Delete the Container from the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Container(context)
        """
        self.dbapi.destroy_container(self.uuid)
        self.obj_reset_changes()

    @base.remotable
    def save(self, context=None):
        """Save updates to this Container.

        Updates will be made column by column based on the result
        of self.what_changed().

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Container(context)
        """
        updates = self.obj_get_changes()
        self.dbapi.update_container(self.uuid, updates)

        self.obj_reset_changes()

    @base.remotable
    def refresh(self, context=None):
        """Loads updates for this Container.

        Loads a container with the same uuid from the database and
        checks for updated attributes. Updates are applied from
        the loaded container column by column, if there are any updates.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Container(context)
        """
        current = self.__class__.get_by_uuid(self._context, uuid=self.uuid)
        for field in self.fields:
            if self.obj_attr_is_set(field) and self[field] != current[field]:
                self[field] = current[field]
Exemplo n.º 28
0
class Bay(base.MagnumPersistentObject, base.MagnumObject,
          base.MagnumObjectDictCompat):
    # Version 1.0: Initial version
    # Version 1.1: Added 'bay_create_timeout' field
    # Version 1.2: Add 'registry_trust_id' field
    # Version 1.3: Added 'baymodel' field
    # Version 1.4: Added more types of status to bay's status field
    # Version 1.5: Reanme 'registry_trust_id' to 'trust_id'
    #              Add 'trustee_user_name', 'trustee_password',
    #              'trustee_user_id' field
    VERSION = '1.5'

    dbapi = dbapi.get_instance()

    fields = {
        'id': fields.IntegerField(),
        'uuid': fields.UUIDField(nullable=True),
        'name': fields.StringField(nullable=True),
        'project_id': fields.StringField(nullable=True),
        'user_id': fields.StringField(nullable=True),
        'baymodel_id': fields.StringField(nullable=True),
        'stack_id': fields.StringField(nullable=True),
        'status': m_fields.BayStatusField(nullable=True),
        'status_reason': fields.StringField(nullable=True),
        'bay_create_timeout': fields.IntegerField(nullable=True),
        'api_address': fields.StringField(nullable=True),
        'node_addresses': fields.ListOfStringsField(nullable=True),
        'node_count': fields.IntegerField(nullable=True),
        'master_count': fields.IntegerField(nullable=True),
        'discovery_url': fields.StringField(nullable=True),
        'master_addresses': fields.ListOfStringsField(nullable=True),
        'ca_cert_ref': fields.StringField(nullable=True),
        'magnum_cert_ref': fields.StringField(nullable=True),
        'baymodel': fields.ObjectField('BayModel'),
        'trust_id': fields.StringField(nullable=True),
        'trustee_username': fields.StringField(nullable=True),
        'trustee_password': fields.StringField(nullable=True),
        'trustee_user_id': fields.StringField(nullable=True)
    }

    @staticmethod
    def _from_db_object(bay, db_bay):
        """Converts a database entity to a formal object."""
        for field in bay.fields:
            if field != 'baymodel':
                bay[field] = db_bay[field]

        # Note(eliqiao): The following line needs to be placed outside the
        # loop because there is a dependency from baymodel to baymodel_id.
        # The baymodel_id must be populated first in the loop before it can be
        # used to find the baymodel.
        bay['baymodel'] = baymodel.BayModel.get_by_uuid(
            bay._context, bay.baymodel_id)

        bay.obj_reset_changes()
        return bay

    @staticmethod
    def _from_db_object_list(db_objects, cls, context):
        """Converts a list of database entities to a list of formal objects."""
        return [Bay._from_db_object(cls(context), obj) for obj in db_objects]

    @base.remotable_classmethod
    def get(cls, context, bay_id):
        """Find a bay based on its id or uuid and return a Bay object.

        :param bay_id: the id *or* uuid of a bay.
        :param context: Security context
        :returns: a :class:`Bay` object.
        """
        if utils.is_int_like(bay_id):
            return cls.get_by_id(context, bay_id)
        elif utils.is_uuid_like(bay_id):
            return cls.get_by_uuid(context, bay_id)
        else:
            raise exception.InvalidIdentity(identity=bay_id)

    @base.remotable_classmethod
    def get_by_id(cls, context, bay_id):
        """Find a bay based on its integer id and return a Bay object.

        :param bay_id: the id of a bay.
        :param context: Security context
        :returns: a :class:`Bay` object.
        """
        db_bay = cls.dbapi.get_bay_by_id(context, bay_id)
        bay = Bay._from_db_object(cls(context), db_bay)
        return bay

    @base.remotable_classmethod
    def get_by_uuid(cls, context, uuid):
        """Find a bay based on uuid and return a :class:`Bay` object.

        :param uuid: the uuid of a bay.
        :param context: Security context
        :returns: a :class:`Bay` object.
        """
        db_bay = cls.dbapi.get_bay_by_uuid(context, uuid)
        bay = Bay._from_db_object(cls(context), db_bay)
        return bay

    @base.remotable_classmethod
    def get_by_name(cls, context, name):
        """Find a bay based on name and return a Bay object.

        :param name: the logical name of a bay.
        :param context: Security context
        :returns: a :class:`Bay` object.
        """
        db_bay = cls.dbapi.get_bay_by_name(context, name)
        bay = Bay._from_db_object(cls(context), db_bay)
        return bay

    @base.remotable_classmethod
    def list(cls,
             context,
             limit=None,
             marker=None,
             sort_key=None,
             sort_dir=None,
             filters=None):
        """Return a list of Bay objects.

        :param context: Security context.
        :param limit: maximum number of resources to return in a single result.
        :param marker: pagination marker for large data sets.
        :param sort_key: column to sort results by.
        :param sort_dir: direction to sort. "asc" or "desc".
        :param filters: filter dict, can includes 'baymodel_id', 'name',
                        'node_count', 'stack_id', 'api_address',
                        'node_addresses', 'project_id', 'user_id',
                        'status'(should be a status list), 'master_count'.
        :returns: a list of :class:`Bay` object.

        """
        db_bays = cls.dbapi.get_bay_list(context,
                                         limit=limit,
                                         marker=marker,
                                         sort_key=sort_key,
                                         sort_dir=sort_dir,
                                         filters=filters)
        return Bay._from_db_object_list(db_bays, cls, context)

    @base.remotable
    def create(self, context=None):
        """Create a Bay record in the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Bay(context)

        """
        values = self.obj_get_changes()
        db_bay = self.dbapi.create_bay(values)
        self._from_db_object(self, db_bay)

    @base.remotable
    def destroy(self, context=None):
        """Delete the Bay from the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Bay(context)
        """
        self.dbapi.destroy_bay(self.uuid)
        self.obj_reset_changes()

    @base.remotable
    def save(self, context=None):
        """Save updates to this Bay.

        Updates will be made column by column based on the result
        of self.what_changed().

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Bay(context)
        """
        updates = self.obj_get_changes()
        self.dbapi.update_bay(self.uuid, updates)

        self.obj_reset_changes()

    @base.remotable
    def refresh(self, context=None):
        """Loads updates for this Bay.

        Loads a bay with the same uuid from the database and
        checks for updated attributes. Updates are applied from
        the loaded bay column by column, if there are any updates.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Bay(context)
        """
        current = self.__class__.get_by_uuid(self._context, uuid=self.uuid)
        for field in self.fields:
            if self.obj_attr_is_set(field) and self[field] != current[field]:
                self[field] = current[field]
Exemplo n.º 29
0
class Node(base.MagnumObject):
    # Version 1.0: Initial version
    VERSION = '1.0'

    dbapi = dbapi.get_instance()

    fields = {
        'id': int,
        'uuid': obj_utils.str_or_none,
        'project_id': obj_utils.str_or_none,
        'user_id': obj_utils.str_or_none,
        'type': obj_utils.str_or_none,
        'image_id': obj_utils.str_or_none,
        'ironic_node_id': obj_utils.str_or_none
    }

    @staticmethod
    def _from_db_object(node, db_node):
        """Converts a database entity to a formal object."""
        for field in node.fields:
            node[field] = db_node[field]

        node.obj_reset_changes()
        return node

    @staticmethod
    def _from_db_object_list(db_objects, cls, context):
        """Converts a list of database entities to a list of formal objects."""
        return [Node._from_db_object(cls(context), obj) for obj in db_objects]

    @base.remotable_classmethod
    def get_by_id(cls, context, node_id):
        """Find a node based on its integer id and return a Node object.

        :param node_id: the id of a node.
        :returns: a :class:`Node` object.
        """
        db_node = cls.dbapi.get_node_by_id(context, node_id)
        node = Node._from_db_object(cls(context), db_node)
        return node

    @base.remotable_classmethod
    def get_by_uuid(cls, context, uuid):
        """Find a node based on uuid and return a :class:`Node` object.

        :param uuid: the uuid of a node.
        :param context: Security context
        :returns: a :class:`Node` object.
        """
        db_node = cls.dbapi.get_node_by_uuid(context, uuid)
        node = Node._from_db_object(cls(context), db_node)
        return node

    @base.remotable_classmethod
    def list(cls,
             context,
             limit=None,
             marker=None,
             sort_key=None,
             sort_dir=None):
        """Return a list of Node objects.

        :param context: Security context.
        :param limit: maximum number of resources to return in a single result.
        :param marker: pagination marker for large data sets.
        :param sort_key: column to sort results by.
        :param sort_dir: direction to sort. "asc" or "desc".
        :returns: a list of :class:`Node` object.

        """
        db_nodes = cls.dbapi.get_node_list(context,
                                           limit=limit,
                                           marker=marker,
                                           sort_key=sort_key,
                                           sort_dir=sort_dir)
        return Node._from_db_object_list(db_nodes, cls, context)

    @base.remotable
    def create(self, context=None):
        """Create a Node record in the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Node(context)

        """
        values = self.obj_get_changes()
        db_node = self.dbapi.create_node(values)
        self._from_db_object(self, db_node)

    @base.remotable
    def destroy(self, context=None):
        """Delete the Node from the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Node(context)
        """
        self.dbapi.destroy_node(self.uuid)
        self.obj_reset_changes()

    @base.remotable
    def save(self, context=None):
        """Save updates to this Node.

        Updates will be made column by column based on the result
        of self.what_changed().

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Node(context)
        """
        updates = self.obj_get_changes()
        self.dbapi.update_node(self.uuid, updates)

        self.obj_reset_changes()

    @base.remotable
    def refresh(self, context=None):
        """Loads updates for this Node.

        Loads a node with the same uuid from the database and
        checks for updated attributes. Updates are applied from
        the loaded node column by column, if there are any updates.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Node(context)
        """
        current = self.__class__.get_by_uuid(self._context, uuid=self.uuid)
        for field in self.fields:
            if (hasattr(self, base.get_attrname(field))
                    and self[field] != current[field]):
                self[field] = current[field]
Exemplo n.º 30
0
class X509KeyPair(base.MagnumPersistentObject, base.MagnumObject,
                  base.MagnumObjectDictCompat):
    # Version 1.0: Initial version
    # Version 1.1: Added new method get_x509keypair_by_bay_uuid
    VERSION = '1.1'

    dbapi = dbapi.get_instance()

    fields = {
        'id': fields.IntegerField(),
        'uuid': fields.UUIDField(nullable=True),
        'name': fields.StringField(nullable=True),
        'bay_uuid': fields.StringField(nullable=True),
        'ca_cert': fields.StringField(nullable=True),
        'certificate': fields.StringField(nullable=True),
        'private_key': fields.StringField(nullable=True),
        'project_id': fields.StringField(nullable=True),
        'user_id': fields.StringField(nullable=True),
    }

    @staticmethod
    def _from_db_object(x509keypair, db_x509keypair):
        """Converts a database entity to a formal object."""
        for field in x509keypair.fields:
            x509keypair[field] = db_x509keypair[field]

        x509keypair.obj_reset_changes()
        return x509keypair

    @staticmethod
    def _from_db_object_list(db_objects, cls, context):
        """Converts a list of database entities to a list of formal objects."""
        return [
            X509KeyPair._from_db_object(cls(context), obj)
            for obj in db_objects
        ]

    @base.remotable_classmethod
    def get(cls, context, x509keypair_id):
        """Find a X509KeyPair based on its id or uuid.

        Find X509KeyPair by id or uuid and return a X509KeyPair object.

        :param x509keypair_id: the id *or* uuid of a x509keypair.
        :returns: a :class:`X509KeyPair` object.
        """
        if utils.is_int_like(x509keypair_id):
            return cls.get_by_id(context, x509keypair_id)
        elif utils.is_uuid_like(x509keypair_id):
            return cls.get_by_uuid(context, x509keypair_id)
        else:
            raise exception.InvalidIdentity(identity=x509keypair_id)

    @base.remotable_classmethod
    def get_by_id(cls, context, x509keypair_id):
        """Find a X509KeyPair based on its integer id.

        Find X509KeyPair by id and return a X509KeyPair object.

        :param x509keypair_id: the id of a x509keypair.
        :returns: a :class:`X509KeyPair` object.
        """
        db_x509keypair = cls.dbapi.get_x509keypair_by_id(
            context, x509keypair_id)
        x509keypair = X509KeyPair._from_db_object(cls(context), db_x509keypair)
        return x509keypair

    @base.remotable_classmethod
    def get_by_uuid(cls, context, uuid):
        """Find a x509keypair based on uuid and return a :class:`X509KeyPair` object.

        :param uuid: the uuid of a x509keypair.
        :param context: Security context
        :returns: a :class:`X509KeyPair` object.
        """
        db_x509keypair = cls.dbapi.get_x509keypair_by_uuid(context, uuid)
        x509keypair = X509KeyPair._from_db_object(cls(context), db_x509keypair)
        return x509keypair

    @base.remotable_classmethod
    def get_by_name(cls, context, name):
        """Find a x509keypair based on name and return a X509KeyPair object.

        :param name: the logical name of a x509keypair.
        :param context: Security context
        :returns: a :class:`X509KeyPair` object.
        """
        db_x509keypair = cls.dbapi.get_x509keypair_by_name(context, name)
        x509keypair = X509KeyPair._from_db_object(cls(context), db_x509keypair)
        return x509keypair

    @base.remotable_classmethod
    def list(cls,
             context,
             limit=None,
             marker=None,
             sort_key=None,
             sort_dir=None,
             filters=None):
        """Return a list of X509KeyPair objects.

        :param context: Security context.
        :param limit: maximum number of resources to return in a single result.
        :param marker: pagination marker for large data sets.
        :param sort_key: column to sort results by.
        :param sort_dir: direction to sort. "asc" or "desc".
        :param filters: filter dict, can include 'x509keypairmodel_id', 'name',
                        'node_count', 'stack_id', 'api_address',
                        'node_addresses', 'project_id', 'user_id',
                        'status'(should be a status list).
        :returns: a list of :class:`X509KeyPair` object.

        """
        db_x509keypairs = cls.dbapi.get_x509keypair_list(context,
                                                         limit=limit,
                                                         marker=marker,
                                                         sort_key=sort_key,
                                                         sort_dir=sort_dir,
                                                         filters=filters)
        return X509KeyPair._from_db_object_list(db_x509keypairs, cls, context)

    @base.remotable
    def create(self, context=None):
        """Create a X509KeyPair record in the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: X509KeyPair(context)

        """
        values = self.obj_get_changes()
        db_x509keypair = self.dbapi.create_x509keypair(values)
        self._from_db_object(self, db_x509keypair)

    @base.remotable
    def destroy(self, context=None):
        """Delete the X509KeyPair from the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: X509KeyPair(context)
        """
        self.dbapi.destroy_x509keypair(self.uuid)
        self.obj_reset_changes()

    @base.remotable
    def save(self, context=None):
        """Save updates to this X509KeyPair.

        Updates will be made column by column based on the result
        of self.what_changed().

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: X509KeyPair(context)
        """
        updates = self.obj_get_changes()
        self.dbapi.update_x509keypair(self.uuid, updates)

        self.obj_reset_changes()

    @base.remotable
    def refresh(self, context=None):
        """Loads updates for this X509KeyPair.

        Loads a x509keypair with the same uuid from the database and
        checks for updated attributes. Updates are applied from
        the loaded x509keypair column by column, if there are any updates.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: X509KeyPair(context)
        """
        current = self.__class__.get_by_uuid(self._context, uuid=self.uuid)
        for field in self.fields:
            if self.obj_attr_is_set(field) and self[field] != current[field]:
                self[field] = current[field]

    @base.remotable_classmethod
    def get_by_bay_uuid(cls, context, bay_uuid):
        """Return a :class:`Cert` object associated with a given bay.

        :param bay_uuid: the uuid of a bay.
        :param context: Security context
        :returns: a class:`Cert` object.
        """
        db_cert = cls.dbapi.get_x509keypair_by_bay_uuid(context, bay_uuid)
        return X509KeyPair._from_db_object(cls(context), db_cert)
Exemplo n.º 31
0
class Bay(base.MagnumPersistentObject, base.MagnumObject,
          base.MagnumObjectDictCompat):
    # Version 1.0: Initial version
    VERSION = '1.0'

    dbapi = dbapi.get_instance()

    fields = {
        'id': fields.IntegerField(),
        'uuid': fields.UUIDField(nullable=True),
        'name': fields.StringField(nullable=True),
        'project_id': fields.StringField(nullable=True),
        'user_id': fields.StringField(nullable=True),
        'baymodel_id': fields.StringField(nullable=True),
        'stack_id': fields.StringField(nullable=True),
        # One of CREATE_IN_PROGRESS|CREATE_FAILED|CREATED
        #        UPDATE_IN_PROGRESS|UPDATE_FAILED|UPDATED
        #        DELETE_IN_PROGRESS|DELETE_FAILED|DELETED
        'status': fields.StringField(nullable=True),
        'status_reason': fields.StringField(nullable=True),
        'api_address': fields.StringField(nullable=True),
        'node_addresses': fields.ListOfStringsField(nullable=True),
        'node_count': fields.IntegerField(nullable=True),
        'discovery_url': fields.StringField(nullable=True),
    }

    @staticmethod
    def _from_db_object(bay, db_bay):
        """Converts a database entity to a formal object."""
        for field in bay.fields:
            bay[field] = db_bay[field]

        bay.obj_reset_changes()
        return bay

    @staticmethod
    def _from_db_object_list(db_objects, cls, context):
        """Converts a list of database entities to a list of formal objects."""
        return [Bay._from_db_object(cls(context), obj) for obj in db_objects]

    @base.remotable_classmethod
    def get(cls, context, bay_id):
        """Find a bay based on its id or uuid and return a Bay object.

        :param bay_id: the id *or* uuid of a bay.
        :returns: a :class:`Bay` object.
        """
        if utils.is_int_like(bay_id):
            return cls.get_by_id(context, bay_id)
        elif utils.is_uuid_like(bay_id):
            return cls.get_by_uuid(context, bay_id)
        else:
            raise exception.InvalidIdentity(identity=bay_id)

    @base.remotable_classmethod
    def get_by_id(cls, context, bay_id):
        """Find a bay based on its integer id and return a Bay object.

        :param bay_id: the id of a bay.
        :returns: a :class:`Bay` object.
        """
        db_bay = cls.dbapi.get_bay_by_id(context, bay_id)
        bay = Bay._from_db_object(cls(context), db_bay)
        return bay

    @base.remotable_classmethod
    def get_by_uuid(cls, context, uuid):
        """Find a bay based on uuid and return a :class:`Bay` object.

        :param uuid: the uuid of a bay.
        :param context: Security context
        :returns: a :class:`Bay` object.
        """
        db_bay = cls.dbapi.get_bay_by_uuid(context, uuid)
        bay = Bay._from_db_object(cls(context), db_bay)
        return bay

    @base.remotable_classmethod
    def get_by_name(cls, context, name):
        """Find a bay based on name and return a Bay object.

        :param name: the logical name of a bay.
        :param context: Security context
        :returns: a :class:`Bay` object.
        """
        db_bay = cls.dbapi.get_bay_by_name(context, name)
        bay = Bay._from_db_object(cls(context), db_bay)
        return bay

    @base.remotable_classmethod
    def list(cls,
             context,
             limit=None,
             marker=None,
             sort_key=None,
             sort_dir=None,
             filters=None):
        """Return a list of Bay objects.

        :param context: Security context.
        :param limit: maximum number of resources to return in a single result.
        :param marker: pagination marker for large data sets.
        :param sort_key: column to sort results by.
        :param sort_dir: direction to sort. "asc" or "desc".
        :param filters: filter dict, can includes 'baymodel_id', 'name',
                        'node_count', 'stack_id', 'api_address',
                        'node_addresses', 'project_id', 'user_id',
                        'status'(should be a status list).
        :returns: a list of :class:`Bay` object.

        """
        db_bays = cls.dbapi.get_bay_list(context,
                                         limit=limit,
                                         marker=marker,
                                         sort_key=sort_key,
                                         sort_dir=sort_dir,
                                         filters=filters)
        return Bay._from_db_object_list(db_bays, cls, context)

    @base.remotable_classmethod
    def list_all(cls,
                 context,
                 limit=None,
                 marker=None,
                 sort_key=None,
                 sort_dir=None,
                 filters=None):
        """Return all tenants of Bay objects.

        :param context: Security context, should be an admin context.
        :param limit: maximum number of resources to return in a single result.
        :param marker: pagination marker for large data sets.
        :param sort_key: column to sort results by.
        :param sort_dir: direction to sort. "asc" or "desc".
        :param filters: filter dict, can includes 'baymodel_id', 'name',
                        'node_count', 'stack_id', 'api_address',
                        'node_addresses', 'project_id', 'user_id',
                        'status'(should be a status list).
        :returns: a list of :class:`Bay` object.

        """
        db_bays = cls.dbapi.get_bay_list(context,
                                         limit=limit,
                                         marker=marker,
                                         sort_key=sort_key,
                                         sort_dir=sort_dir,
                                         filters=filters,
                                         opts={'get_all_tenants': True})
        return Bay._from_db_object_list(db_bays, cls, context)

    @base.remotable
    def create(self, context=None):
        """Create a Bay record in the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Bay(context)

        """
        values = self.obj_get_changes()
        db_bay = self.dbapi.create_bay(values)
        self._from_db_object(self, db_bay)

    @base.remotable
    def destroy(self, context=None):
        """Delete the Bay from the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Bay(context)
        """
        self.dbapi.destroy_bay(self.uuid)
        self.obj_reset_changes()

    @base.remotable
    def save(self, context=None):
        """Save updates to this Bay.

        Updates will be made column by column based on the result
        of self.what_changed().

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Bay(context)
        """
        updates = self.obj_get_changes()
        self.dbapi.update_bay(self.uuid, updates)

        self.obj_reset_changes()

    @base.remotable
    def refresh(self, context=None):
        """Loads updates for this Bay.

        Loads a bay with the same uuid from the database and
        checks for updated attributes. Updates are applied from
        the loaded bay column by column, if there are any updates.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Bay(context)
        """
        current = self.__class__.get_by_uuid(self._context, uuid=self.uuid)
        for field in self.fields:
            if self.obj_attr_is_set(field) and self[field] != current[field]:
                self[field] = current[field]
Exemplo n.º 32
0
class Quota(base.MagnumPersistentObject, base.MagnumObject,
            base.MagnumObjectDictCompat):
    # Version 1.0: Initial version
    VERSION = '1.0'

    dbapi = dbapi.get_instance()

    fields = {
        'id': fields.IntegerField(),
        'project_id': fields.StringField(nullable=False),
        'resource': fields.StringField(nullable=False),
        'hard_limit': fields.IntegerField(nullable=False),
    }

    @base.remotable_classmethod
    def get_quota_by_project_id_resource(cls, context, project_id, resource):
        """Find a quota based on its integer id and return a Quota object.

        :param project_id: the id of a project.
        :param resource: resource name.
        :param context: Security context
        :returns: a :class:`Quota` object.
        """
        db_quota = cls.dbapi.get_quota_by_project_id_resource(
            project_id, resource)
        quota = Quota._from_db_object(cls(context), db_quota)
        return quota

    @staticmethod
    def _from_db_object(quota, db_quota):
        """Converts a database entity to a formal object."""
        for field in quota.fields:
            setattr(quota, field, db_quota[field])

        quota.obj_reset_changes()
        return quota

    @staticmethod
    def _from_db_object_list(db_objects, cls, context):
        """Converts a list of database entities to a list of formal objects."""
        return [Quota._from_db_object(cls(context), obj) for obj in db_objects]

    @base.remotable_classmethod
    def get_by_id(cls, context, quota_id):
        """Find a quota based on its integer id and return a Quota object.

        :param quota_id: the id of a quota.
        :param context: Security context
        :returns: a :class:`Quota` object.
        """
        db_quota = cls.dbapi.get_quota_by_id(context, quota_id)
        quota = Quota._from_db_object(cls(context), db_quota)
        return quota

    @base.remotable_classmethod
    def list(cls,
             context,
             limit=None,
             marker=None,
             sort_key=None,
             sort_dir=None,
             filters=None):
        """Return a list of Quota objects.

        :param context: Security context.
        :param limit: maximum number of resources to return in a single result.
        :param marker: pagination marker for large data sets.
        :param sort_key: column to sort results by.
        :param sort_dir: direction to sort. "asc" or "desc".
        :param filters: filter dict, can includes 'project_id',
                        'resource'.
        :returns: a list of :class:`Quota` object.

        """
        db_quotas = cls.dbapi.get_quota_list(context,
                                             limit=limit,
                                             marker=marker,
                                             sort_key=sort_key,
                                             sort_dir=sort_dir,
                                             filters=filters)
        return Quota._from_db_object_list(db_quotas, cls, context)

    @base.remotable_classmethod
    def quota_get_all_by_project_id(cls, context, project_id):
        """Find a quota based on project id.

        :param project_id: the project id.
        :param context: Security context
        :returns: a :class:`Quota` object.
        """
        quotas = cls.dbapi.get_quota_by_project_id(context, project_id)
        return Quota._from_db_object_list(quotas, cls, context)

    @base.remotable
    def create(self, context=None):
        """Save a quota based on project id.

        :param context: security context.
        :returns: a :class:`Quota` object.
        """
        values = self.obj_get_changes()
        db_quota = self.dbapi.create_quota(values)
        self._from_db_object(self, db_quota)

    @base.remotable
    def delete(self, context=None):
        """Delete the quota from the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Quota(context)
        """
        self.dbapi.delete_quota(self.project_id, self.resource)
        self.obj_reset_changes()

    @base.remotable_classmethod
    def update_quota(cls, context, project_id, quota):
        """Save a quota based on project id.

        :param quota: quota.
        :returns: a :class:`Quota` object.
        """
        db_quota = cls.dbapi.update_quota(project_id, quota)
        return Quota._from_db_object(cls(context), db_quota)
Exemplo n.º 33
0
class ReplicationController(base.MagnumPersistentObject, base.MagnumObject,
                            base.MagnumObjectDictCompat):
    # Version 1.0: Initial version
    VERSION = '1.0'

    dbapi = dbapi.get_instance()

    fields = {
        'id': fields.IntegerField(),
        'uuid': fields.StringField(nullable=True),
        'name': fields.StringField(nullable=True),
        'project_id': fields.StringField(nullable=True),
        'user_id': fields.StringField(nullable=True),
        'images': fields.ListOfStringsField(nullable=True),
        'bay_uuid': fields.StringField(nullable=True),
        'labels': fields.DictOfStringsField(nullable=True),
        'replicas': fields.IntegerField(nullable=True),
        'manifest_url': fields.StringField(nullable=True),
        'manifest': fields.StringField(nullable=True),
    }

    @base.remotable_classmethod
    def get_by_uuid(cls, context, uuid, bay_uuid, k8s_api):
        """Return a :class:`ReplicationController` object based on uuid.

        :param context: Security context
        :param uuid: the uuid of a ReplicationController.
        :param bay_uuid: the UUID of the Bay.

        :returns: a :class:`ReplicationController` object.
        """
        try:
            resp = k8s_api.list_namespaced_replication_controller(
                namespace='default')
        except rest.ApiException as err:
            raise exception.KubernetesAPIFailed(err=err)

        if resp is None:
            raise exception.ReplicationControllerListNotFound(
                bay_uuid=bay_uuid)

        rc = {}
        for entry in resp.items:
            if entry.metadata.uid == uuid:
                rc['uuid'] = entry.metadata.uid
                rc['name'] = entry.metadata.name
                rc['project_id'] = context.project_id
                rc['user_id'] = context.user_id
                rc['images'] = [
                    c.image for c in entry.spec.template.spec.containers]
                rc['bay_uuid'] = bay_uuid
                # Convert string to dictionary
                rc['labels'] = ast.literal_eval(entry.metadata.labels)
                rc['replicas'] = entry.status.replicas

                rc_obj = ReplicationController(context, **rc)
                return rc_obj

        raise exception.ReplicationControllerNotFound(rc=uuid)

    @base.remotable_classmethod
    def get_by_name(cls, context, name, bay_uuid, k8s_api):
        """Return a :class:`ReplicationController` object based on name.

        :param context: Security context
        :param name: the name of a ReplicationController.
        :param bay_uuid: the UUID of the Bay.

        :returns: a :class:`ReplicationController` object.
        """
        try:
            resp = k8s_api.read_namespaced_replication_controller(
                name=name,
                namespace='default')
        except rest.ApiException as err:
            raise exception.KubernetesAPIFailed(err=err)

        if resp is None:
            raise exception.ReplicationControllerNotFound(rc=name)

        rc = {}
        rc['uuid'] = resp.metadata.uid
        rc['name'] = resp.metadata.name
        rc['project_id'] = context.project_id
        rc['user_id'] = context.user_id
        rc['images'] = [c.image for c in resp.spec.template.spec.containers]
        rc['bay_uuid'] = bay_uuid
        # Convert string to dictionary
        rc['labels'] = ast.literal_eval(resp.metadata.labels)
        rc['replicas'] = resp.status.replicas

        rc_obj = ReplicationController(context, **rc)
        return rc_obj
Exemplo n.º 34
0
class Federation(base.MagnumPersistentObject, base.MagnumObject,
                 base.MagnumObjectDictCompat):
    """Represents a Federation object.

    Version 1.0: Initial Version
    """

    VERSION = '1.0'

    dbapi = dbapi.get_instance()

    fields = {
        'id': fields.IntegerField(),
        'uuid': fields.UUIDField(nullable=True),
        'name': fields.StringField(nullable=True),
        'project_id': fields.StringField(nullable=True),
        'hostcluster_id': fields.StringField(nullable=True),
        'member_ids': fields.ListOfStringsField(nullable=True),
        'status': m_fields.FederationStatusField(nullable=True),
        'status_reason': fields.StringField(nullable=True),
        'properties': fields.DictOfStringsField(nullable=True)
    }

    @staticmethod
    def _from_db_object(federation, db_federation):
        """Converts a database entity to a formal object."""
        for field in federation.fields:
            federation[field] = db_federation[field]

        federation.obj_reset_changes()
        return federation

    @staticmethod
    def _from_db_object_list(db_objects, cls, context):
        """Converts a list of database entities to a list of formal objects."""
        return [Federation._from_db_object(cls(context), obj)
                for obj in db_objects]

    @base.remotable_classmethod
    def get(cls, context, federation_id):
        """Find a federation based on its id or uuid and return it.

        :param federation_id: the id *or* uuid of a federation.
        :param context: Security context
        :returns: a :class:`Federation` object.
        """
        if strutils.is_int_like(federation_id):
            return cls.get_by_id(context, federation_id)
        elif uuidutils.is_uuid_like(federation_id):
            return cls.get_by_uuid(context, federation_id)
        else:
            raise exception.InvalidIdentity(identity=federation_id)

    @base.remotable_classmethod
    def get_by_id(cls, context, federation_id):
        """Find a federation based on its integer id and return it.

        :param federation_id: the id of a federation.
        :param context: Security context
        :returns: a :class:`Federation` object.
        """
        db_federation = cls.dbapi.get_federation_by_id(context, federation_id)
        federation = Federation._from_db_object(cls(context), db_federation)
        return federation

    @base.remotable_classmethod
    def get_by_uuid(cls, context, uuid):
        """Find a federation based on uuid and return it.

        :param uuid: the uuid of a federation.
        :param context: Security context
        :returns: a :class:`Federation` object.
        """
        db_federation = cls.dbapi.get_federation_by_uuid(context, uuid)
        federation = Federation._from_db_object(cls(context), db_federation)
        return federation

    @base.remotable_classmethod
    def get_count_all(cls, context, filters=None):
        """Get count of matching federation.

        :param context: The security context
        :param filters: filter dict, can includes 'name', 'project_id',
                        'hostcluster_id', 'member_ids', 'status' (should be a
                        status list).
        :returns: Count of matching federation.
        """
        return cls.dbapi.get_federation_count_all(context, filters=filters)

    @base.remotable_classmethod
    def get_by_name(cls, context, name):
        """Find a federation based on name and return a Federation object.

        :param name: the logical name of a federation.
        :param context: Security context
        :returns: a :class:`Federation` object.
        """
        db_federation = cls.dbapi.get_federation_by_name(context, name)
        federation = Federation._from_db_object(cls(context), db_federation)
        return federation

    @base.remotable_classmethod
    def list(cls, context, limit=None, marker=None,
             sort_key=None, sort_dir=None, filters=None):
        """Return a list of Federation objects.

        :param context: Security context.
        :param limit: maximum number of resources to return in a single result.
        :param marker: pagination marker for large data sets.
        :param sort_key: column to sort results by.
        :param sort_dir: direction to sort. "asc" or "desc".
        :param filters: filter dict, can includes 'name', 'project_id',
                        'hostcluster_id', 'member_ids', 'status' (should be a
                        status list).
        :returns: a list of :class:`Federation` object.

        """
        db_federation = cls.dbapi.get_federation_list(context, limit=limit,
                                                      marker=marker,
                                                      sort_key=sort_key,
                                                      sort_dir=sort_dir,
                                                      filters=filters)
        return Federation._from_db_object_list(db_federation, cls, context)

    @base.remotable
    def create(self, context=None):
        """Create a Federation record in the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Federation(context)

        """
        values = self.obj_get_changes()
        db_federation = self.dbapi.create_federation(values)
        self._from_db_object(self, db_federation)

    @base.remotable
    def destroy(self, context=None):
        """Delete the Federation from the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Federation(context)
        """
        self.dbapi.destroy_federation(self.uuid)
        self.obj_reset_changes()

    @base.remotable
    def save(self, context=None):
        """Save updates to this Federation.

        Updates will be made column by column based on the result
        of self.what_changed().

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Federation(context)
        """
        updates = self.obj_get_changes()
        self.dbapi.update_federation(self.uuid, updates)

        self.obj_reset_changes()

    @base.remotable
    def refresh(self, context=None):
        """Load updates for this Federation.

        Loads a Federation with the same uuid from the database and
        checks for updated attributes. Updates are applied from
        the loaded Federation column by column, if there are any updates.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Federation(context)
        """
        current = self.__class__.get_by_uuid(self._context, uuid=self.uuid)
        for field in self.fields:
            if self.obj_attr_is_set(field) and self[field] != current[field]:
                self[field] = current[field]
Exemplo n.º 35
0
class Cluster(base.MagnumPersistentObject, base.MagnumObject,
              base.MagnumObjectDictCompat):
    # Version 1.0: Initial version
    # Version 1.1: Added 'bay_create_timeout' field
    # Version 1.2: Add 'registry_trust_id' field
    # Version 1.3: Added 'baymodel' field
    # Version 1.4: Added more types of status to bay's status field
    # Version 1.5: Rename 'registry_trust_id' to 'trust_id'
    #              Add 'trustee_user_name', 'trustee_password',
    #              'trustee_user_id' field
    # Version 1.6: Add rollback support for Bay
    # Version 1.7: Added 'coe_version'  and 'container_version' fields
    # Version 1.8: Rename 'baymodel' to 'cluster_template'
    # Version 1.9: Rename table name from 'bay' to 'cluster'
    #              Rename 'baymodel_id' to 'cluster_template_id'
    #              Rename 'bay_create_timeout' to 'create_timeout'
    # Version 1.10: Added 'keypair' field
    # Version 1.11: Added 'RESUME_FAILED' in status field
    # Version 1.12: Added 'get_stats' method
    # Version 1.13: Added get_count_all method
    # Version 1.14: Added 'docker_volume_size' field
    # Version 1.15: Added 'labels' field
    # Version 1.16: Added 'master_flavor_id' field
    # Version 1.17: Added 'flavor_id' field
    # Version 1.18: Added 'health_status' and 'health_status_reason' field
    # Version 1.19: Added nodegroups, default_ng_worker, default_ng_master
    # Version 1.20: Fields node_count, master_count, node_addresses,
    #               master_addresses are now properties.
    # Version 1.21  Added fixed_network, fixed_subnet, floating_ip_enabled
    # Version 1.22  Added master_lb_enabled
    # Version 1.23  Added etcd_ca_cert_ref and front_proxy_ca_cert_ref

    VERSION = '1.23'

    dbapi = dbapi.get_instance()

    fields = {
        'id': fields.IntegerField(),
        'uuid': fields.UUIDField(nullable=True),
        'name': fields.StringField(nullable=True),
        'project_id': fields.StringField(nullable=True),
        'user_id': fields.StringField(nullable=True),
        'cluster_template_id': fields.StringField(nullable=True),
        'keypair': fields.StringField(nullable=True),
        'docker_volume_size': fields.IntegerField(nullable=True),
        'labels': fields.DictOfStringsField(nullable=True),
        'master_flavor_id': fields.StringField(nullable=True),
        'flavor_id': fields.StringField(nullable=True),
        'stack_id': fields.StringField(nullable=True),
        'status': m_fields.ClusterStatusField(nullable=True),
        'status_reason': fields.StringField(nullable=True),
        'health_status': m_fields.ClusterHealthStatusField(nullable=True),
        'health_status_reason': fields.DictOfStringsField(nullable=True),
        'create_timeout': fields.IntegerField(nullable=True),
        'api_address': fields.StringField(nullable=True),
        'discovery_url': fields.StringField(nullable=True),
        'ca_cert_ref': fields.StringField(nullable=True),
        'magnum_cert_ref': fields.StringField(nullable=True),
        'etcd_ca_cert_ref': fields.StringField(nullable=True),
        'front_proxy_ca_cert_ref': fields.StringField(nullable=True),
        'cluster_template': fields.ObjectField('ClusterTemplate'),
        'trust_id': fields.StringField(nullable=True),
        'trustee_username': fields.StringField(nullable=True),
        'trustee_password': fields.StringField(nullable=True),
        'trustee_user_id': fields.StringField(nullable=True),
        'coe_version': fields.StringField(nullable=True),
        'container_version': fields.StringField(nullable=True),
        'fixed_network': fields.StringField(nullable=True),
        'fixed_subnet': fields.StringField(nullable=True),
        'floating_ip_enabled': fields.BooleanField(default=True),
        'master_lb_enabled': fields.BooleanField(default=False),
    }

    @staticmethod
    def _from_db_object(cluster, db_cluster):
        """Converts a database entity to a formal object."""
        for field in cluster.fields:
            # cluster_template will be loaded lazily when it is needed
            # by obj_load_attr.
            if field != 'cluster_template':
                cluster[field] = db_cluster[field]

        cluster.obj_reset_changes()
        return cluster

    @property
    def nodegroups(self):
        # Returns all nodegroups that belong to the cluster.
        return NodeGroup.list(self._context, self.uuid)

    @property
    def default_ng_worker(self):
        # Assume that every cluster will have only one default
        # non-master nodegroup. We don't want to limit the roles
        # so each nodegroup that does not have a master role is
        # considered as a worker/minion nodegroup.
        filters = {'is_default': True}
        default_ngs = NodeGroup.list(self._context, self.uuid, filters=filters)
        return [n for n in default_ngs if n.role != 'master'][0]

    @property
    def default_ng_master(self):
        # Assume that every cluster will have only one default
        # master nodegroup.
        filters = {'role': 'master', 'is_default': True}
        return NodeGroup.list(self._context, self.uuid, filters=filters)[0]

    @property
    def node_count(self):
        return sum(n.node_count for n in self.nodegroups if n.role != 'master')

    @property
    def master_count(self):
        return sum(n.node_count for n in self.nodegroups if n.role == 'master')

    @property
    def node_addresses(self):
        node_addresses = []
        for ng in self.nodegroups:
            if ng.role != 'master':
                node_addresses += ng.node_addresses
        return node_addresses

    @property
    def master_addresses(self):
        master_addresses = []
        for ng in self.nodegroups:
            if ng.role == 'master':
                master_addresses += ng.node_addresses
        return master_addresses

    @staticmethod
    def _from_db_object_list(db_objects, cls, context):
        """Converts a list of database entities to a list of formal objects."""
        return [
            Cluster._from_db_object(cls(context), obj) for obj in db_objects
        ]

    @base.remotable_classmethod
    def get(cls, context, cluster_id):
        """Find a cluster based on its id or uuid and return a Cluster object.

        :param cluster_id: the id *or* uuid of a cluster.
        :param context: Security context
        :returns: a :class:`Cluster` object.
        """
        if strutils.is_int_like(cluster_id):
            return cls.get_by_id(context, cluster_id)
        elif uuidutils.is_uuid_like(cluster_id):
            return cls.get_by_uuid(context, cluster_id)
        else:
            raise exception.InvalidIdentity(identity=cluster_id)

    @base.remotable_classmethod
    def get_by_id(cls, context, cluster_id):
        """Find a cluster based on its integer id and return a Cluster object.

        :param cluster_id: the id of a cluster.
        :param context: Security context
        :returns: a :class:`Cluster` object.
        """
        db_cluster = cls.dbapi.get_cluster_by_id(context, cluster_id)
        cluster = Cluster._from_db_object(cls(context), db_cluster)
        return cluster

    @base.remotable_classmethod
    def get_by_uuid(cls, context, uuid):
        """Find a cluster based on uuid and return a :class:`Cluster` object.

        :param uuid: the uuid of a cluster.
        :param context: Security context
        :returns: a :class:`Cluster` object.
        """
        db_cluster = cls.dbapi.get_cluster_by_uuid(context, uuid)
        cluster = Cluster._from_db_object(cls(context), db_cluster)
        return cluster

    @base.remotable_classmethod
    def get_count_all(cls, context, filters=None):
        """Get count of matching clusters.

        :param context: The security context
        :param filters: filter dict, can includes 'cluster_template_id',
                        'name', 'node_count', 'stack_id', 'api_address',
                        'node_addresses', 'project_id', 'user_id',
                        'status'(should be a status list), 'master_count'.
        :returns: Count of matching clusters.
        """
        return cls.dbapi.get_cluster_count_all(context, filters=filters)

    @base.remotable_classmethod
    def get_by_name(cls, context, name):
        """Find a cluster based on name and return a Cluster object.

        :param name: the logical name of a cluster.
        :param context: Security context
        :returns: a :class:`Cluster` object.
        """
        db_cluster = cls.dbapi.get_cluster_by_name(context, name)
        cluster = Cluster._from_db_object(cls(context), db_cluster)
        return cluster

    @base.remotable_classmethod
    def list(cls,
             context,
             limit=None,
             marker=None,
             sort_key=None,
             sort_dir=None,
             filters=None):
        """Return a list of Cluster objects.

        :param context: Security context.
        :param limit: maximum number of resources to return in a single result.
        :param marker: pagination marker for large data sets.
        :param sort_key: column to sort results by.
        :param sort_dir: direction to sort. "asc" or "desc".
        :param filters: filter dict, can includes 'cluster_template_id',
                        'name', 'node_count', 'stack_id', 'api_address',
                        'node_addresses', 'project_id', 'user_id',
                        'status'(should be a status list), 'master_count'.
        :returns: a list of :class:`Cluster` object.

        """
        db_clusters = cls.dbapi.get_cluster_list(context,
                                                 limit=limit,
                                                 marker=marker,
                                                 sort_key=sort_key,
                                                 sort_dir=sort_dir,
                                                 filters=filters)
        return Cluster._from_db_object_list(db_clusters, cls, context)

    @base.remotable_classmethod
    def get_stats(cls, context, project_id=None):
        """Return a list of Cluster objects.

        :param context: Security context.
        :param project_id: project id
        """
        return cls.dbapi.get_cluster_stats(project_id)

    @base.remotable
    def create(self, context=None):
        """Create a Cluster record in the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Cluster(context)

        """
        values = self.obj_get_changes()
        db_cluster = self.dbapi.create_cluster(values)
        self._from_db_object(self, db_cluster)

    @base.remotable
    def destroy(self, context=None):
        """Delete the Cluster from the DB.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Cluster(context)
        """
        self.dbapi.destroy_cluster(self.uuid)
        self.obj_reset_changes()

    @base.remotable
    def save(self, context=None):
        """Save updates to this Cluster.

        Updates will be made column by column based on the result
        of self.what_changed().

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Cluster(context)
        """
        updates = self.obj_get_changes()
        self.dbapi.update_cluster(self.uuid, updates)

        self.obj_reset_changes()

    @base.remotable
    def refresh(self, context=None):
        """Loads updates for this Cluster.

        Loads a Cluster with the same uuid from the database and
        checks for updated attributes. Updates are applied from
        the loaded Cluster column by column, if there are any updates.

        :param context: Security context. NOTE: This should only
                        be used internally by the indirection_api.
                        Unfortunately, RPC requires context as the first
                        argument, even though we don't use it.
                        A context should be set when instantiating the
                        object, e.g.: Cluster(context)
        """
        current = self.__class__.get_by_uuid(self._context, uuid=self.uuid)
        for field in self.fields:
            if self.obj_attr_is_set(field) and self[field] != current[field]:
                self[field] = current[field]

    def obj_load_attr(self, attrname):
        if attrname not in LAZY_LOADED_ATTRS:
            raise exception.ObjectError(action='obj_load_attr',
                                        obj_name=self.name,
                                        obj_id=self.uuid,
                                        reason='unable to lazy-load %s' %
                                        attrname)

        self['cluster_template'] = ClusterTemplate.get_by_uuid(
            self._context, self.cluster_template_id)

        self.obj_reset_changes(['cluster_template'])

    def as_dict(self):
        dict_ = super(Cluster, self).as_dict()
        # Update the dict with the attributes coming form
        # the cluster's nodegroups.
        dict_.update({
            'node_count': self.node_count,
            'master_count': self.master_count,
            'node_addresses': self.node_addresses,
            'master_addresses': self.master_addresses
        })
        return dict_