예제 #1
0
파일: bay.py 프로젝트: openstack/magnum
    def _patch(self, bay_ident, patch):
        context = pecan.request.context
        bay = api_utils.get_resource('Cluster', bay_ident)
        policy.enforce(context, 'bay:update', bay.as_dict(),
                       action='bay:update')

        bay_to_cluster_attrs = {
            'baymodel_id': 'cluster_template_id',
            'bay_create_timeout': 'create_timeout'
        }
        try:
            bay_dict = bay.as_dict()
            new_bay = Bay(**api_utils.apply_jsonpatch(bay_dict, patch))
        except api_utils.JSONPATCH_EXCEPTIONS as e:
            raise exception.PatchError(patch=patch, reason=e)

        # NOTE(ttsiouts): magnum.objects.Cluster.node_count will be a
        # property so we won't be able to store it in the object. So
        # instead of object_what_changed compare the new and the old
        # clusters.
        delta = set()
        for field in new_bay.fields:
            cluster_field = field
            if cluster_field in bay_to_cluster_attrs:
                cluster_field = bay_to_cluster_attrs[field]
            if cluster_field not in bay_dict:
                continue
            if getattr(new_bay, field) != bay_dict[cluster_field]:
                delta.add(cluster_field)

        validate_cluster_properties(delta)
        return bay, new_bay.node_count
예제 #2
0
파일: cluster.py 프로젝트: ragnaray/magnum
    def get_one(self, cluster_ident):
        """Retrieve information about the given Cluster.

        :param cluster_ident: UUID or logical name of the Cluster.
        """
        context = pecan.request.context
        if context.is_admin:
            policy.enforce(context, "cluster:get_one_all_projects",
                           action="cluster:get_one_all_projects")
            # TODO(flwang): Instead of asking an extra 'all_project's
            # parameter, currently the design is allowing admin user to list
            # all clusters from all projects. But the all_tenants is one of
            # the condition to do project filter in DB API. And it's also used
            # by periodic tasks. So the could be removed in the future and
            # a new parameter 'project_id' would be added so that admin user
            # can list clusters for a particular project.
            context.all_tenants = True

        cluster = api_utils.get_resource('Cluster', cluster_ident)
        policy.enforce(context, 'cluster:get', cluster.as_dict(),
                       action='cluster:get')

        cluster = Cluster.convert_with_links(cluster)

        if cluster.status in fields.ClusterStatus.STATUS_FAILED:
            cluster.faults = self._collect_fault_info(context, cluster)

        return cluster
예제 #3
0
파일: cluster.py 프로젝트: ragnaray/magnum
    def _patch(self, cluster_ident, patch):
        context = pecan.request.context
        cluster = api_utils.get_resource('Cluster', cluster_ident)
        policy.enforce(context, 'cluster:update', cluster.as_dict(),
                       action='cluster:update')
        try:
            cluster_dict = cluster.as_dict()
            new_cluster = Cluster(**api_utils.apply_jsonpatch(cluster_dict,
                                                              patch))
        except api_utils.JSONPATCH_EXCEPTIONS as e:
            raise exception.PatchError(patch=patch, reason=e)

        # Update only the fields that have changed
        for field in objects.Cluster.fields:
            try:
                patch_val = getattr(new_cluster, field)
            except AttributeError:
                # Ignore fields that aren't exposed in the API
                continue
            if patch_val == wtypes.Unset:
                patch_val = None
            if cluster[field] != patch_val:
                cluster[field] = patch_val

        delta = cluster.obj_what_changed()

        validation.validate_cluster_properties(delta)
        return cluster
예제 #4
0
    def post(self, cluster):
        """Create a new cluster.

        :param cluster: a cluster within the request body.
        """
        context = pecan.request.context
        policy.enforce(context, 'cluster:create',
                       action='cluster:create')
        temp_id = cluster.cluster_template_id
        cluster_template = objects.BayModel.get_by_uuid(context, temp_id)
        cluster_dict = cluster.as_dict()

        attr_validator.validate_os_resources(context,
                                             cluster_template.as_dict())
        attr_validator.validate_master_count(cluster_dict,
                                             cluster_template.as_dict())

        cluster_dict['project_id'] = context.project_id
        cluster_dict['user_id'] = context.user_id
        # NOTE(yuywz): We will generate a random human-readable name for
        # cluster if the name is not specified by user.
        name = cluster_dict.get('name') or \
            self._generate_name_for_cluster(context)
        cluster_dict['name'] = name

        new_cluster = objects.Bay(context, **cluster_dict)
        new_cluster.uuid = uuid.uuid4()
        pecan.request.rpcapi.bay_create_async(new_cluster,
                                              cluster.create_timeout)

        return ClusterID(new_cluster.uuid)
예제 #5
0
파일: baymodel.py 프로젝트: bigsurge/magnum
    def post(self, baymodel):
        """Create a new baymodel.

        :param baymodel: a baymodel within the request body.
        """
        context = pecan.request.context
        policy.enforce(context, 'baymodel:create',
                       action='baymodel:create')
        baymodel_dict = baymodel.as_dict()
        context = pecan.request.context
        cli = clients.OpenStackClients(context)
        attr_validator.validate_os_resources(context, baymodel_dict)
        image_data = attr_validator.validate_image(cli,
                                                   baymodel_dict['image_id'])
        baymodel_dict['cluster_distro'] = image_data['os_distro']
        baymodel_dict['project_id'] = context.project_id
        baymodel_dict['user_id'] = context.user_id
        # check permissions for making baymodel public
        if baymodel_dict['public']:
            if not policy.enforce(context, "baymodel:publish", None,
                                  do_raise=False):
                raise exception.BaymodelPublishDenied()

        new_baymodel = objects.BayModel(context, **baymodel_dict)
        new_baymodel.create()
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('baymodels',
                                                 new_baymodel.uuid)
        return BayModel.convert_with_links(new_baymodel)
예제 #6
0
    def post(self, baymodel):
        """Create a new baymodel.

        :param baymodel: a baymodel within the request body.
        """
        context = pecan.request.context
        policy.enforce(context, 'baymodel:create',
                       action='baymodel:create')
        baymodel_dict = baymodel.as_dict()
        cli = clients.OpenStackClients(context)
        attr_validator.validate_os_resources(context, baymodel_dict)
        image_data = attr_validator.validate_image(cli,
                                                   baymodel_dict['image_id'])
        baymodel_dict['cluster_distro'] = image_data['os_distro']
        baymodel_dict['project_id'] = context.project_id
        baymodel_dict['user_id'] = context.user_id
        # check permissions for making baymodel public
        if baymodel_dict['public']:
            if not policy.enforce(context, "baymodel:publish", None,
                                  do_raise=False):
                raise exception.ClusterTemplatePublishDenied()

        # NOTE(yuywz): We will generate a random human-readable name for
        # baymodel if the name is not spcified by user.
        arg_name = baymodel_dict.get('name')
        name = arg_name or self._generate_name_for_baymodel(context)
        baymodel_dict['name'] = name

        new_baymodel = objects.BayModel(context, **baymodel_dict)
        new_baymodel.create()
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('baymodels',
                                                 new_baymodel.uuid)
        return BayModel.convert_with_links(new_baymodel)
예제 #7
0
파일: bay.py 프로젝트: larsbutler/magnum
    def _patch(self, bay_ident, patch):
        context = pecan.request.context
        bay = api_utils.get_resource('Bay', bay_ident)
        policy.enforce(context, 'bay:update', bay,
                       action='bay:update')
        try:
            bay_dict = bay.as_dict()
            new_bay = Bay(**api_utils.apply_jsonpatch(bay_dict, patch))
        except api_utils.JSONPATCH_EXCEPTIONS as e:
            raise exception.PatchError(patch=patch, reason=e)

        # Update only the fields that have changed
        for field in objects.Bay.fields:
            try:
                patch_val = getattr(new_bay, field)
            except AttributeError:
                # Ignore fields that aren't exposed in the API
                continue
            if patch_val == wtypes.Unset:
                patch_val = None
            if bay[field] != patch_val:
                bay[field] = patch_val

        delta = bay.obj_what_changed()

        validate_bay_properties(delta)
        return bay
예제 #8
0
    def _patch(self, federation_ident, patch):
        context = pecan.request.context
        federation = api_utils.get_resource('Federation', federation_ident)
        policy.enforce(context, 'federation:update', federation.as_dict(),
                       action='federation:update')

        # NOTE(clenimar): Magnum does not allow one to append items to existing
        # fields through an `add` operation using HTTP PATCH (please check
        # `magnum.api.utils.apply_jsonpatch`). In order to perform the join
        # and unjoin operations, intercept the original JSON PATCH document
        # and change the operation from either `add` or `remove` to `replace`.
        patch_path = patch[0].get('path')
        patch_value = patch[0].get('value')
        patch_op = patch[0].get('op')

        if patch_path == '/member_ids':
            if patch_op == 'add' and patch_value is not None:
                patch = self._join_wrapper(federation_ident, patch)
            elif patch_op == 'remove' and patch_value is not None:
                patch = self._unjoin_wrapper(federation_ident, patch)

        try:
            federation_dict = federation.as_dict()
            new_federation = Federation(
                **api_utils.apply_jsonpatch(federation_dict, patch))
        except api_utils.JSONPATCH_EXCEPTIONS as e:
            raise exception.PatchError(patch=patch, reason=e)

        # Retrieve only what changed after the patch.
        delta = self._update_changed_fields(federation, new_federation)
        validation.validate_federation_properties(delta)

        return federation
예제 #9
0
    def get_one(self, cluster_template_ident):
        """Retrieve information about the given ClusterTemplate.

        :param cluster_template_ident: UUID or logical name of a
        ClusterTemplate.
        """
        context = pecan.request.context

        if context.is_admin:
            policy.enforce(context, "clustertemplate:get_one_all_projects",
                           action="clustertemplate:get_one_all_projects")
            # TODO(flwang): Instead of asking an extra 'all_project's
            # parameter, currently the design is allowing admin user to list
            # all clusters from all projects. But the all_tenants is one of
            # the condition to do project filter in DB API. And it's also used
            # by periodic tasks. So the could be removed in the future and
            # a new parameter 'project_id' would be added so that admin user
            # can list clusters for a particular project.
            context.all_tenants = True

        cluster_template = api_utils.get_resource('ClusterTemplate',
                                                  cluster_template_ident)

        if not cluster_template.public:
            policy.enforce(context, 'clustertemplate:get',
                           cluster_template.as_dict(),
                           action='clustertemplate:get')

        return ClusterTemplate.convert_with_links(cluster_template)
예제 #10
0
    def post(self, federation):
        """Create a new federation.

        :param federation: a federation within the request body.
        """
        context = pecan.request.context
        policy.enforce(context, 'federation:create',
                       action='federation:create')

        federation_dict = federation.as_dict()

        # Validate `hostcluster_id`
        hostcluster_id = federation_dict.get('hostcluster_id')
        attr_validator.validate_federation_hostcluster(hostcluster_id)

        # Validate `properties` dict.
        properties_dict = federation_dict.get('properties')
        attr_validator.validate_federation_properties(properties_dict)

        federation_dict['project_id'] = context.project_id

        # If no name is specified, generate a random human-readable name
        name = (federation_dict.get('name') or
                self._generate_name_for_federation(context))
        federation_dict['name'] = name

        new_federation = objects.Federation(context, **federation_dict)
        new_federation.uuid = uuid.uuid4()

        # TODO(clenimar): remove hard-coded `create_timeout`.
        pecan.request.rpcapi.federation_create_async(new_federation,
                                                     create_timeout=15)

        return FederationID(new_federation.uuid)
예제 #11
0
    def patch(self, bay_ident, patch):
        """Update an existing bay.

        :param bay_ident: UUID or logical name of a bay.
        :param patch: a json PATCH document to apply to this bay.
        """
        context = pecan.request.context
        bay = api_utils.get_resource('Bay', bay_ident)
        policy.enforce(context, 'bay:update', bay,
                       action='bay:update')
        try:
            bay_dict = bay.as_dict()
            new_bay = Bay(**api_utils.apply_jsonpatch(bay_dict, patch))
        except api_utils.JSONPATCH_EXCEPTIONS as e:
            raise exception.PatchError(patch=patch, reason=e)

        # Update only the fields that have changed
        for field in objects.Bay.fields:
            try:
                patch_val = getattr(new_bay, field)
            except AttributeError:
                # Ignore fields that aren't exposed in the API
                continue
            if patch_val == wtypes.Unset:
                patch_val = None
            if bay[field] != patch_val:
                bay[field] = patch_val

        delta = bay.obj_what_changed()

        validate_bay_properties(delta)

        res_bay = pecan.request.rpcapi.bay_update(bay)
        return Bay.convert_with_links(res_bay)
예제 #12
0
    def patch(self, cluster_ident, patch):
        """Update an existing bay.

        :param cluster_ident: UUID or logical name of a bay.
        :param patch: a json PATCH document to apply to this bay.
        """
        context = pecan.request.context
        cluster = api_utils.get_resource('Bay', cluster_ident)
        policy.enforce(context, 'cluster:update', cluster,
                       action='cluster:update')
        try:
            cluster_dict = cluster.as_dict()
            new_cluster = Cluster(**api_utils.apply_jsonpatch(cluster_dict,
                                                              patch))
        except api_utils.JSONPATCH_EXCEPTIONS as e:
            raise exception.PatchError(patch=patch, reason=e)

        # Update only the fields that have changed
        for field in objects.Bay.fields:
            try:
                patch_val = getattr(new_cluster, field)
            except AttributeError:
                # Ignore fields that aren't exposed in the API
                continue
            if patch_val == wtypes.Unset:
                patch_val = None
            if cluster[field] != patch_val:
                cluster[field] = patch_val

        delta = cluster.obj_what_changed()

        validate_bay_properties(delta)

        pecan.request.rpcapi.bay_update_async(cluster)
        return ClusterID(cluster.uuid)
예제 #13
0
파일: bay.py 프로젝트: voa808/magnum
    def post(self, bay):
        """Create a new bay.

        :param bay: a bay within the request body.
        """
        context = pecan.request.context
        policy.enforce(context, 'bay:create',
                       action='bay:create')
        baymodel = objects.BayModel.get_by_uuid(context, bay.baymodel_id)
        attr_validator.validate_os_resources(context, baymodel.as_dict())
        attr_validator.validate_master_count(bay.as_dict(), baymodel.as_dict())
        bay_dict = bay.as_dict()
        bay_dict['project_id'] = context.project_id
        bay_dict['user_id'] = context.user_id
        # NOTE(yuywz): We will generate a random human-readable name for
        # bay if the name is not spcified by user.
        name = bay_dict.get('name') or self._generate_name_for_bay(context)
        bay_dict['name'] = name

        new_bay = objects.Bay(context, **bay_dict)
        res_bay = pecan.request.rpcapi.bay_create(new_bay,
                                                  bay.bay_create_timeout)

        # Set the HTTP Location Header
        pecan.response.location = link.build_url('bays', res_bay.uuid)
        return Bay.convert_with_links(res_bay)
예제 #14
0
파일: cluster.py 프로젝트: ragnaray/magnum
    def post(self, cluster):
        """Create a new cluster.

        :param cluster: a cluster within the request body.
        """
        context = pecan.request.context
        policy.enforce(context, 'cluster:create',
                       action='cluster:create')

        self._check_cluster_quota_limit(context)

        temp_id = cluster.cluster_template_id
        cluster_template = objects.ClusterTemplate.get_by_uuid(context,
                                                               temp_id)
        # If keypair not present, use cluster_template value
        if cluster.keypair is None:
            cluster.keypair = cluster_template.keypair_id

        # If docker_volume_size is not present, use cluster_template value
        if cluster.docker_volume_size == wtypes.Unset:
            cluster.docker_volume_size = cluster_template.docker_volume_size

        # If labels is not present, use cluster_template value
        if cluster.labels == wtypes.Unset:
            cluster.labels = cluster_template.labels

        # If master_flavor_id is not present, use cluster_template value
        if (cluster.master_flavor_id == wtypes.Unset or
                not cluster.master_flavor_id):
            cluster.master_flavor_id = cluster_template.master_flavor_id

        # If flavor_id is not present, use cluster_template value
        if cluster.flavor_id == wtypes.Unset or not cluster.flavor_id:
            cluster.flavor_id = cluster_template.flavor_id

        cluster_dict = cluster.as_dict()

        attr_validator.validate_os_resources(context,
                                             cluster_template.as_dict(),
                                             cluster_dict)
        attr_validator.validate_master_count(cluster_dict,
                                             cluster_template.as_dict())

        cluster_dict['project_id'] = context.project_id
        cluster_dict['user_id'] = context.user_id
        # NOTE(yuywz): We will generate a random human-readable name for
        # cluster if the name is not specified by user.
        name = cluster_dict.get('name') or \
            self._generate_name_for_cluster(context)
        cluster_dict['name'] = name
        cluster_dict['coe_version'] = None
        cluster_dict['container_version'] = None

        new_cluster = objects.Cluster(context, **cluster_dict)
        new_cluster.uuid = uuid.uuid4()
        pecan.request.rpcapi.cluster_create_async(new_cluster,
                                                  cluster.create_timeout)

        return ClusterID(new_cluster.uuid)
예제 #15
0
 def patch(self, cluster_ident):
     context = pecan.request.context
     cluster = api_utils.get_resource('Cluster', cluster_ident)
     policy.enforce(context, 'certificate:rotate_ca', cluster.as_dict(),
                    action='certificate:rotate_ca')
     if cluster.cluster_template.tls_disabled:
         raise exception.NotSupported("Rotating the CA certificate on a "
                                      "non-TLS cluster is not supported")
     pecan.request.rpcapi.rotate_ca_certificate(cluster)
예제 #16
0
    def delete(self, baymodel_ident):
        """Delete a Baymodel.

        :param baymodel_ident: UUID or logical name of a Baymodel.
        """
        context = pecan.request.context
        baymodel = api_utils.get_resource('ClusterTemplate', baymodel_ident)
        policy.enforce(context, 'baymodel:delete', baymodel.as_dict(),
                       action='baymodel:delete')
        baymodel.destroy()
예제 #17
0
    def delete(self, baymodel_ident):
        """Delete a baymodel.

        :param baymodel_ident: UUID or logical name of a baymodel.
        """
        context = pecan.request.context
        baymodel = api_utils.get_resource('BayModel', baymodel_ident)
        policy.enforce(context, 'baymodel:delete', baymodel,
                       action='baymodel:delete')
        baymodel.destroy()
예제 #18
0
    def get_one(self, bay_ident):
        """Retrieve information about the given bay.

        :param bay_ident: UUID of a bay or logical name of the bay.
        """
        context = pecan.request.context
        bay = api_utils.get_resource('Bay', bay_ident)
        policy.enforce(context, 'bay:get', bay,
                       action='bay:get')

        return Bay.convert_with_links(bay)
예제 #19
0
    def delete(self, bay_ident):
        """Delete a bay.

        :param bay_ident: UUID of a bay or logical name of the bay.
        """
        context = pecan.request.context
        bay = api_utils.get_resource('Bay', bay_ident)
        policy.enforce(context, 'bay:delete', bay,
                       action='bay:delete')

        pecan.request.rpcapi.bay_delete(bay.uuid)
예제 #20
0
    def delete(self, cluster_ident):
        """Delete a cluster.

        :param cluster_ident: UUID of cluster or logical name of the cluster.
        """
        context = pecan.request.context
        cluster = api_utils.get_resource('Cluster', cluster_ident)
        policy.enforce(context, 'cluster:delete', cluster,
                       action='cluster:delete')

        pecan.request.rpcapi.cluster_delete_async(cluster.uuid)
예제 #21
0
    def get_one(self, baymodel_ident):
        """Retrieve information about the given baymodel.

        :param baymodel_ident: UUID or logical name of a baymodel.
        """
        context = pecan.request.context
        baymodel = api_utils.get_resource('BayModel', baymodel_ident)
        if not baymodel.public:
            policy.enforce(context, 'baymodel:get', baymodel,
                           action='baymodel:get')

        return BayModel.convert_with_links(baymodel)
예제 #22
0
    def delete(self, federation_ident):
        """Delete a federation.

        :param federation_ident: UUID of federation or logical name
                                 of the federation.
        """
        context = pecan.request.context
        federation = api_utils.get_resource('Federation', federation_ident)
        policy.enforce(context, 'federation:delete', federation.as_dict(),
                       action='federation:delete')

        pecan.request.rpcapi.federation_delete_async(federation.uuid)
예제 #23
0
파일: quota.py 프로젝트: charliekang/magnum
    def delete(self, project_id,  resource):
        """Delete Quota for a given project_id and resource.

        :param project_id: project id.
        :param resource: resource name.
        """

        context = pecan.request.context
        policy.enforce(context, 'quota:delete', action='quota:delete')
        quota_dict = {"project_id": project_id, "resource": resource}
        quota = objects.Quota(context, **quota_dict)
        quota.delete()
예제 #24
0
파일: certificate.py 프로젝트: gwdg/magnum
    def get_one(self, bay_ident):
        """Retrieve CA information about the given bay.

        :param bay_ident: UUID of a bay or
        logical name of the bay.
        """
        context = pecan.request.context
        bay = api_utils.get_resource('Bay', bay_ident)
        policy.enforce(context, 'certificate:get', bay,
                       action='certificate:get')
        certificate = pecan.request.rpcapi.get_ca_certificate(bay)
        return Certificate.convert_with_links(certificate)
예제 #25
0
    def get_one(self, cluster_ident):
        """Retrieve CA information about the given cluster.

        :param cluster_ident: UUID of a cluster or
        logical name of the cluster.
        """
        context = pecan.request.context
        cluster = api_utils.get_resource('Cluster', cluster_ident)
        policy.enforce(context, 'certificate:get', cluster.as_dict(),
                       action='certificate:get')
        certificate = pecan.request.rpcapi.get_ca_certificate(cluster)
        return Certificate.convert_with_links(certificate)
예제 #26
0
    def delete(self, cluster_template_ident):
        """Delete a cluster_template.

        :param cluster_template_ident: UUID or logical name of a
         cluster_template.
        """
        context = pecan.request.context
        cluster_template = api_utils.get_resource('BayModel',
                                                  cluster_template_ident)
        policy.enforce(context, 'clustertemplate:delete', cluster_template,
                       action='clustertemplate:delete')
        cluster_template.destroy()
예제 #27
0
    def get_one(self, federation_ident):
        """Retrieve information about a given Federation.

        :param federation_ident: UUID or logical name of the Federation.
        """
        context = pecan.request.context
        federation = api_utils.get_resource('Federation', federation_ident)
        policy.enforce(context, 'federation:get', federation.as_dict(),
                       action='federation:get')

        federation = Federation.convert_with_links(federation)

        return federation
예제 #28
0
    def get_one(self, cluster_template_ident):
        """Retrieve information about the given clustertemplate.

        :param cluster_template_ident: UUID or logical name of a
        clustertemplate.
        """
        context = pecan.request.context
        cluster_template = api_utils.get_resource('BayModel',
                                                  cluster_template_ident)
        if not cluster_template.public:
            policy.enforce(context, 'clustertemplate:get', cluster_template,
                           action='clustertemplate:get')

        return ClusterTemplate.convert_with_links(cluster_template)
예제 #29
0
    def patch(self, cluster_template_ident, patch):
        """Update an existing ClusterTemplate.

        :param cluster_template_ident: UUID or logic name of a
        ClusterTemplate.
        :param patch: a json PATCH document to apply to this
        ClusterTemplate.
        """
        context = pecan.request.context
        if context.is_admin:
            policy.enforce(context, 'clustertemplate:update_all_projects',
                           action='clustertemplate:update_all_projects')
            context.all_tenants = True
        cluster_template = api_utils.get_resource('ClusterTemplate',
                                                  cluster_template_ident)
        policy.enforce(context, 'clustertemplate:update',
                       cluster_template.as_dict(),
                       action='clustertemplate:update')
        try:
            cluster_template_dict = cluster_template.as_dict()
            new_cluster_template = ClusterTemplate(**api_utils.apply_jsonpatch(
                cluster_template_dict,
                patch))
        except api_utils.JSONPATCH_EXCEPTIONS as e:
            raise exception.PatchError(patch=patch, reason=e)

        new_cluster_template_dict = new_cluster_template.as_dict()
        attr_validator.validate_os_resources(context,
                                             new_cluster_template_dict)
        # check permissions when updating ClusterTemplate public or hidden flag
        if (cluster_template.public != new_cluster_template.public or
                cluster_template.hidden != new_cluster_template.hidden):
            if not policy.enforce(context, "clustertemplate:publish", None,
                                  do_raise=False):
                raise exception.ClusterTemplatePublishDenied()

        # Update only the fields that have changed
        for field in objects.ClusterTemplate.fields:
            try:
                patch_val = getattr(new_cluster_template, field)
            except AttributeError:
                # Ignore fields that aren't exposed in the API
                continue
            if patch_val == wtypes.Unset:
                patch_val = None
            if cluster_template[field] != patch_val:
                cluster_template[field] = patch_val

        cluster_template.save()
        return ClusterTemplate.convert_with_links(cluster_template)
예제 #30
0
    def get_all(self, marker=None, limit=None, sort_key='id',
                sort_dir='asc'):
        """Retrieve a list of bays.

        :param marker: pagination marker for large data sets.
        :param limit: maximum number of resources to return in a single result.
        :param sort_key: column to sort results by. Default: id.
        :param sort_dir: direction to sort. "asc" or "desc". Default: asc.
        """
        context = pecan.request.context
        policy.enforce(context, 'bay:get_all',
                       action='bay:get_all')
        return self._get_bays_collection(marker, limit, sort_key,
                                         sort_dir)
예제 #31
0
    def detail(self, marker=None, limit=None, sort_key='id', sort_dir='asc'):
        """Retrieve a list of clusters with detail.

        :param marker: pagination marker for large data sets.
        :param limit: maximum number of resources to return in a single result.
        :param sort_key: column to sort results by. Default: id.
        :param sort_dir: direction to sort. "asc" or "desc". Default: asc.
        """
        context = pecan.request.context
        policy.enforce(context, 'cluster:detail', action='cluster:detail')

        # NOTE(lucasagomes): /detail should only work against collections
        parent = pecan.request.path.split('/')[:-1][-1]
        if parent != "clusters":
            raise exception.HTTPNotFound

        expand = True
        resource_url = '/'.join(['clusters', 'detail'])
        return self._get_clusters_collection(marker, limit, sort_key, sort_dir,
                                             expand, resource_url)
예제 #32
0
    def upgrade(self, cluster_ident, cluster_upgrade_req):
        """Upgrade a cluster.

        :param cluster_ident: UUID of a cluster or logical name of the cluster.
        """
        context = pecan.request.context
        if context.is_admin:
            policy.enforce(context,
                           "cluster:upgrade_all_projects",
                           action="cluster:upgrade_all_projects")
            context.all_tenants = True

        cluster = api_utils.get_resource('Cluster', cluster_ident)
        policy.enforce(context,
                       'cluster:upgrade',
                       cluster,
                       action='cluster:upgrade')

        new_cluster_template = api_utils.get_resource(
            'ClusterTemplate', cluster_upgrade_req.cluster_template)

        if (cluster_upgrade_req.nodegroup == wtypes.Unset
                or not cluster_upgrade_req.nodegroup):
            # NOTE(ttsiouts): If the nodegroup is not specified
            # reflect the change to the default worker nodegroup
            nodegroup = cluster.default_ng_worker
        else:
            nodegroup = objects.NodeGroup.get(context, cluster.uuid,
                                              cluster_upgrade_req.nodegroup)
            if (new_cluster_template.uuid != cluster.cluster_template_id
                    and not nodegroup.is_default):
                reason = ("Nodegroup %s can be upgraded only to "
                          "match cluster's template (%s).")
                reason = reason % (nodegroup.name,
                                   cluster.cluster_template.name)
                raise exception.InvalidClusterTemplateForUpgrade(reason=reason)

        pecan.request.rpcapi.cluster_upgrade(
            cluster, new_cluster_template, cluster_upgrade_req.max_batch_size,
            nodegroup)
        return ClusterID(cluster.uuid)
예제 #33
0
    def patch(self, baymodel_ident, patch):
        """Update an existing Baymodel.

        :param baymodel_ident: UUID or logic name of a Baymodel.
        :param patch: a json PATCH document to apply to this Baymodel.
        """
        context = pecan.request.context
        baymodel = api_utils.get_resource('ClusterTemplate', baymodel_ident)
        policy.enforce(context,
                       'baymodel:update',
                       baymodel.as_dict(),
                       action='baymodel:update')
        try:
            baymodel_dict = baymodel.as_dict()
            new_baymodel = BayModel(
                **api_utils.apply_jsonpatch(baymodel_dict, patch))
        except api_utils.JSONPATCH_EXCEPTIONS as e:
            raise exception.PatchError(patch=patch, reason=e)

        new_baymodel_dict = new_baymodel.as_dict()
        attr_validator.validate_os_resources(context, new_baymodel_dict)
        # check permissions when updating baymodel public flag
        if baymodel.public != new_baymodel.public:
            if not policy.enforce(
                    context, "baymodel:publish", None, do_raise=False):
                raise exception.ClusterTemplatePublishDenied()

        # Update only the fields that have changed
        for field in objects.ClusterTemplate.fields:
            try:
                patch_val = getattr(new_baymodel, field)
            except AttributeError:
                # Ignore fields that aren't exposed in the API
                continue
            if patch_val == wtypes.Unset:
                patch_val = None
            if baymodel[field] != patch_val:
                baymodel[field] = patch_val

        baymodel.save()
        return BayModel.convert_with_links(baymodel)
예제 #34
0
    def resize(self, cluster_ident, cluster_resize_req):
        """Resize a cluster.

        :param cluster_ident: UUID of a cluster or logical name of the cluster.
        """
        context = pecan.request.context
        cluster = api_utils.get_resource('Cluster', cluster_ident)
        policy.enforce(context,
                       'cluster:resize',
                       cluster,
                       action='cluster:resize')

        if (cluster_resize_req.nodegroup == wtypes.Unset
                or not cluster_resize_req.nodegroup):
            # NOTE(ttsiouts): If the nodegroup is not specified
            # reflect the change to the default worker nodegroup
            nodegroup = cluster.default_ng_worker
        else:
            nodegroup = objects.NodeGroup.get(context, cluster.uuid,
                                              cluster_resize_req.nodegroup)

        if nodegroup.role == 'master':
            # NOTE(ttsiouts): Restrict the resize to worker nodegroups
            raise exception.MasterNGResizeNotSupported()

        # NOTE(ttsiouts): Make sure that the new node count is within
        # the configured boundaries of the selected nodegroup.
        if nodegroup.min_node_count > cluster_resize_req.node_count:
            raise exception.NGResizeOutBounds(nodegroup=nodegroup.name,
                                              min_nc=nodegroup.min_node_count,
                                              max_nc=nodegroup.max_node_count)
        if (nodegroup.max_node_count
                and nodegroup.max_node_count < cluster_resize_req.node_count):
            raise exception.NGResizeOutBounds(nodegroup=nodegroup.name,
                                              min_nc=nodegroup.min_node_count,
                                              max_nc=nodegroup.max_node_count)

        pecan.request.rpcapi.cluster_resize_async(
            cluster, cluster_resize_req.node_count,
            cluster_resize_req.nodes_to_remove, nodegroup)
        return ClusterID(cluster.uuid)
예제 #35
0
    def post(self, cluster):
        """Create a new cluster.

        :param cluster: a cluster within the request body.
        """
        context = pecan.request.context
        policy.enforce(context, 'cluster:create', action='cluster:create')

        self._check_cluster_quota_limit(context)

        temp_id = cluster.cluster_template_id
        cluster_template = objects.ClusterTemplate.get_by_uuid(
            context, temp_id)
        # If keypair not present, use cluster_template value
        if cluster.keypair is None:
            cluster.keypair = cluster_template.keypair_id

        cluster_dict = cluster.as_dict()

        attr_validator.validate_os_resources(context,
                                             cluster_template.as_dict(),
                                             cluster_dict)
        attr_validator.validate_master_count(cluster_dict,
                                             cluster_template.as_dict())

        cluster_dict['project_id'] = context.project_id
        cluster_dict['user_id'] = context.user_id
        # NOTE(yuywz): We will generate a random human-readable name for
        # cluster if the name is not specified by user.
        name = cluster_dict.get('name') or \
            self._generate_name_for_cluster(context)
        cluster_dict['name'] = name
        cluster_dict['coe_version'] = None
        cluster_dict['container_version'] = None

        new_cluster = objects.Cluster(context, **cluster_dict)
        new_cluster.uuid = uuid.uuid4()
        pecan.request.rpcapi.cluster_create_async(new_cluster,
                                                  cluster.create_timeout)

        return ClusterID(new_cluster.uuid)
예제 #36
0
    def get_one(self, project_id, resource):
        """Retrieve Quota information for the given project_id.

        :param id: project id.
        :param resource: resource name.
        """
        context = pecan.request.context
        policy.enforce(context, 'quota:get', action='quota:get')

        if not context.is_admin and project_id != context.project_id:
            raise exception.NotAuthorized()

        try:
            quota = objects.Quota.get_quota_by_project_id_resource(
                context, project_id, resource)
            quota = Quota.convert(quota)
        except exception.QuotaNotFound:
            # If explicit quota was not set for the project, use default limit
            quota = Quota(project_id=project_id,
                          hard_limit=CONF.quotas.max_clusters_per_project)
        return quota
예제 #37
0
    def _post(self, bay):
        context = pecan.request.context
        policy.enforce(context, 'bay:create',
                       action='bay:create')
        baymodel = objects.ClusterTemplate.get_by_uuid(context,
                                                       bay.baymodel_id)

        # If docker_volume_size is not present, use baymodel value
        if bay.docker_volume_size == wtypes.Unset:
            bay.docker_volume_size = baymodel.docker_volume_size

        # If labels is not present, use baymodel value
        if bay.labels is None:
            bay.labels = baymodel.labels

        # If master_flavor_id is not present, use baymodel value
        if bay.master_flavor_id == wtypes.Unset or not bay.master_flavor_id:
            bay.master_flavor_id = baymodel.master_flavor_id

        # If flavor_id is not present, use baymodel value
        if bay.flavor_id == wtypes.Unset or not bay.flavor_id:
            bay.flavor_id = baymodel.flavor_id

        bay_dict = bay.as_dict()
        bay_dict['keypair'] = baymodel.keypair_id
        attr_validator.validate_os_resources(context, baymodel.as_dict(),
                                             bay_dict)
        attr_validator.validate_master_count(bay.as_dict(), baymodel.as_dict())

        bay_dict['project_id'] = context.project_id
        bay_dict['user_id'] = context.user_id
        # NOTE(yuywz): We will generate a random human-readable name for
        # bay if the name is not specified by user.
        name = bay_dict.get('name') or self._generate_name_for_bay(context)
        bay_dict['name'] = name
        bay_dict['coe_version'] = None
        bay_dict['container_version'] = None
        new_bay = objects.Cluster(context, **bay_dict)
        new_bay.uuid = uuid.uuid4()
        return new_bay
예제 #38
0
    def _patch(self, cluster_ident, patch):
        context = pecan.request.context
        if context.is_admin:
            policy.enforce(context,
                           "cluster:update_all_projects",
                           action="cluster:update_all_projects")
            context.all_tenants = True

        cluster = api_utils.get_resource('Cluster', cluster_ident)
        policy.enforce(context,
                       'cluster:update',
                       cluster.as_dict(),
                       action='cluster:update')
        policy.enforce(context,
                       "cluster:update_health_status",
                       action="cluster:update_health_status")
        try:
            cluster_dict = cluster.as_dict()
            new_cluster = Cluster(
                **api_utils.apply_jsonpatch(cluster_dict, patch))
        except api_utils.JSONPATCH_EXCEPTIONS as e:
            raise exception.PatchError(patch=patch, reason=e)

        # NOTE(ttsiouts): magnum.objects.Cluster.node_count will be a
        # property so we won't be able to store it in the object. So
        # instead of object_what_changed compare the new and the old
        # clusters.
        delta = set()
        for field in new_cluster.fields:
            if getattr(cluster, field) != getattr(new_cluster, field):
                delta.add(field)

        validation.validate_cluster_properties(delta)
        return (cluster, new_cluster.node_count, new_cluster.health_status,
                new_cluster.health_status_reason)
예제 #39
0
    def post(self, cluster_id, nodegroup):
        """Create NodeGroup.

        :param nodegroup: a json document to create this NodeGroup.
        """

        context = pecan.request.context
        policy.enforce(context, 'nodegroup:create', action='nodegroup:create')

        cluster = api_utils.get_resource('Cluster', cluster_id)
        # Before we start, we need to check that the cluster has an
        # api_address. If not, just fail.
        if 'api_address' not in cluster or not cluster.api_address:
            raise exception.ClusterAPIAddressUnavailable()
        cluster_ngs = [ng.name for ng in cluster.nodegroups]
        if nodegroup.name in cluster_ngs:
            raise exception.NodeGroupAlreadyExists(name=nodegroup.name,
                                                   cluster_id=cluster.name)
        _validate_node_count(nodegroup)

        if nodegroup.role == "master":
            # Currently we don't support adding master nodegroups.
            # Keep this until we start supporting it.
            raise exception.CreateMasterNodeGroup()
        if nodegroup.image_id is None or nodegroup.image_id == wtypes.Unset:
            nodegroup.image_id = cluster.cluster_template.image_id
        if nodegroup.flavor_id is None or nodegroup.flavor_id == wtypes.Unset:
            nodegroup.flavor_id = cluster.flavor_id
        if nodegroup.labels is None or nodegroup.labels == wtypes.Unset:
            nodegroup.labels = cluster.labels

        nodegroup_dict = nodegroup.as_dict()
        nodegroup_dict['cluster_id'] = cluster.uuid
        nodegroup_dict['project_id'] = context.project_id

        new_obj = objects.NodeGroup(context, **nodegroup_dict)
        new_obj.uuid = uuid.uuid4()
        pecan.request.rpcapi.nodegroup_create_async(cluster, new_obj)
        return NodeGroup.convert(new_obj)
예제 #40
0
    def post(self, bay):
        """Create a new bay.

        :param bay: a bay within the request body.
        """
        context = pecan.request.context
        policy.enforce(context, 'bay:create', action='bay:create')
        baymodel = objects.BayModel.get_by_uuid(context, bay.baymodel_id)
        attr_validator.validate_os_resources(context, baymodel.as_dict())
        bay_dict = bay.as_dict()
        bay_dict['project_id'] = context.project_id
        bay_dict['user_id'] = context.user_id
        if bay_dict.get('name') is None:
            bay_dict['name'] = None

        new_bay = objects.Bay(context, **bay_dict)
        res_bay = pecan.request.rpcapi.bay_create(new_bay,
                                                  bay.bay_create_timeout)

        # Set the HTTP Location Header
        pecan.response.location = link.build_url('bays', res_bay.uuid)
        return Bay.convert_with_links(res_bay)
예제 #41
0
    def _get_clusters_collection(self, marker, limit,
                                 sort_key, sort_dir, expand=False,
                                 resource_url=None):

        context = pecan.request.context
        if context.is_admin:
            if expand:
                policy.enforce(context, "cluster:detail_all_projects",
                               action="cluster:detail_all_projects")
            else:
                policy.enforce(context, "cluster:get_all_all_projects",
                               action="cluster:get_all_all_projects")
            # TODO(flwang): Instead of asking an extra 'all_project's
            # parameter, currently the design is allowing admin user to list
            # all clusters from all projects. But the all_tenants is one of
            # the condition to do project filter in DB API. And it's also used
            # by periodic tasks. So the could be removed in the future and
            # a new parameter 'project_id' would be added so that admin user
            # can list clusters for a particular project.
            context.all_tenants = True

        limit = api_utils.validate_limit(limit)
        sort_dir = api_utils.validate_sort_dir(sort_dir)

        marker_obj = None
        if marker:
            marker_obj = objects.Cluster.get_by_uuid(pecan.request.context,
                                                     marker)

        clusters = objects.Cluster.list(pecan.request.context, limit,
                                        marker_obj, sort_key=sort_key,
                                        sort_dir=sort_dir)

        return ClusterCollection.convert_with_links(clusters, limit,
                                                    url=resource_url,
                                                    expand=expand,
                                                    sort_key=sort_key,
                                                    sort_dir=sort_dir)
예제 #42
0
    def get_all(self,
                marker=None,
                limit=None,
                sort_key='id',
                sort_dir='asc',
                bay_ident=None):
        """Retrieve a list of containers.

        :param marker: pagination marker for large data sets.
        :param limit: maximum number of resources to return in a single result.
        :param sort_key: column to sort results by. Default: id.
        :param sort_dir: direction to sort. "asc" or "desc". Default: asc.
        :param bay_indent: UUID or logical name of bay.
        """
        context = pecan.request.context
        policy.enforce(context,
                       "container:get_all",
                       action="container:get_all")
        return self._get_containers_collection(marker,
                                               limit,
                                               sort_key,
                                               sort_dir,
                                               bay_ident=bay_ident)
예제 #43
0
파일: bay.py 프로젝트: yangkf1985/magnum
    def _post(self, bay):
        context = pecan.request.context
        policy.enforce(context, 'bay:create', action='bay:create')
        baymodel = objects.ClusterTemplate.get_by_uuid(context,
                                                       bay.baymodel_id)

        bay_dict = bay.as_dict()
        bay_dict['keypair'] = baymodel.keypair_id
        attr_validator.validate_os_resources(context, baymodel.as_dict(),
                                             bay_dict)
        attr_validator.validate_master_count(bay.as_dict(), baymodel.as_dict())

        bay_dict['project_id'] = context.project_id
        bay_dict['user_id'] = context.user_id
        # NOTE(yuywz): We will generate a random human-readable name for
        # bay if the name is not spcified by user.
        name = bay_dict.get('name') or self._generate_name_for_bay(context)
        bay_dict['name'] = name
        bay_dict['coe_version'] = None
        bay_dict['container_version'] = None
        new_bay = objects.Cluster(context, **bay_dict)
        new_bay.uuid = uuid.uuid4()
        return new_bay
예제 #44
0
    def get_all(self,
                marker=None,
                limit=None,
                sort_key='id',
                sort_dir='asc',
                all_tenants=False):
        """Retrieve a list of quotas.

        :param marker: pagination marker for large data sets.
        :param limit: maximum number of resources to return in a single result.
        :param sort_key: column to sort results by. Default: id.
        :param sort_dir: direction to sort. "asc" or "desc". Default: asc.
        :param all_tenants: a flag to indicate all or current tenant.
        """
        context = pecan.request.context
        policy.enforce(context, 'quota:get_all', action='quota:get_all')

        filters = {}
        if not context.is_admin or not all_tenants:
            filters = {"project_id": context.project_id}

        return self._get_quota_collection(marker, limit, sort_key, sort_dir,
                                          filters)
예제 #45
0
    def resize(self, cluster_ident, cluster_resize_req):
        """Resize a cluster.

        :param cluster_ident: UUID of a cluster or logical name of the cluster.
        """
        context = pecan.request.context
        cluster = api_utils.get_resource('Cluster', cluster_ident)
        policy.enforce(context,
                       'cluster:resize',
                       cluster,
                       action='cluster:resize')

        if (cluster_resize_req.nodegroup == wtypes.Unset
                or not cluster_resize_req.nodegroup):
            # TODO(flwang): The default node group of current cluster could be
            # extracted by objects.NodeGroups.get_by_uuid or something like
            # that as long as we have node group support.
            cluster_resize_req.nodegroup = None

        pecan.request.rpcapi.cluster_resize_async(
            cluster, cluster_resize_req.node_count,
            cluster_resize_req.nodes_to_remove, cluster_resize_req.nodegroup)
        return ClusterID(cluster.uuid)
예제 #46
0
    def patch(self, cluster_ident, patch):
        """Update an existing bay.

        :param cluster_ident: UUID or logical name of a bay.
        :param patch: a json PATCH document to apply to this bay.
        """
        context = pecan.request.context
        cluster = api_utils.get_resource('Bay', cluster_ident)
        policy.enforce(context,
                       'cluster:update',
                       cluster,
                       action='cluster:update')
        try:
            cluster_dict = cluster.as_dict()
            new_cluster = Cluster(
                **api_utils.apply_jsonpatch(cluster_dict, patch))
        except api_utils.JSONPATCH_EXCEPTIONS as e:
            raise exception.PatchError(patch=patch, reason=e)

        # Update only the fields that have changed
        for field in objects.Bay.fields:
            try:
                patch_val = getattr(new_cluster, field)
            except AttributeError:
                # Ignore fields that aren't exposed in the API
                continue
            if patch_val == wtypes.Unset:
                patch_val = None
            if cluster[field] != patch_val:
                cluster[field] = patch_val

        delta = cluster.obj_what_changed()

        validate_bay_properties(delta)

        pecan.request.rpcapi.bay_update_async(cluster)
        return ClusterID(cluster.uuid)
예제 #47
0
    def post(self, bay):
        """Create a new bay.

        :param bay: a bay within the request body.
        """
        context = pecan.request.context
        policy.enforce(context, 'bay:create', action='bay:create')
        baymodel = objects.BayModel.get_by_uuid(context, bay.baymodel_id)
        attr_validator.validate_os_resources(context, baymodel.as_dict())
        bay_dict = bay.as_dict()
        bay_dict['project_id'] = context.project_id
        bay_dict['user_id'] = context.user_id
        # NOTE(yuywz): We will generate a random human-readable name for
        # bay if the name is not spcified by user.
        name = bay_dict.get('name') or self._generate_name_for_bay(context)
        bay_dict['name'] = name

        new_bay = objects.Bay(context, **bay_dict)
        res_bay = pecan.request.rpcapi.bay_create(new_bay,
                                                  bay.bay_create_timeout)

        # Set the HTTP Location Header
        pecan.response.location = link.build_url('bays', res_bay.uuid)
        return Bay.convert_with_links(res_bay)
예제 #48
0
    def get_all(self, project_id=None, type="cluster"):
        """Retrieve magnum stats.

        """
        context = pecan.request.context
        policy.enforce(context, 'stats:get_all', action='stats:get_all')
        allowed_stats = ["cluster"]

        if type.lower() not in allowed_stats:
            msg = _("Invalid stats type. Allowed values are '%s'")
            allowed_str = ','.join(allowed_stats)
            raise exception.InvalidParameterValue(err=msg % allowed_str)

        # 1.If the requester is not an admin and trying to request stats for
        # different tenant, then reject the request
        # 2.If the requester is not an admin and project_id was not provided,
        # then return self stats
        if not context.is_admin:
            project_id = project_id if project_id else context.project_id
            if project_id != context.project_id:
                raise exception.NotAuthorized()

        stats = objects.Stats.get_cluster_stats(context, project_id)
        return Stats.convert(stats)
예제 #49
0
    def post(self, cluster_template):
        """Create a new ClusterTemplate.

        :param cluster_template: a ClusterTemplate within the request body.
        """
        context = pecan.request.context
        policy.enforce(context,
                       'clustertemplate:create',
                       action='clustertemplate:create')
        cluster_template_dict = cluster_template.as_dict()
        cli = clients.OpenStackClients(context)
        attr_validator.validate_os_resources(context, cluster_template_dict)
        image_data = attr_validator.validate_image(
            cli, cluster_template_dict['image_id'])
        cluster_template_dict['cluster_distro'] = image_data['os_distro']
        cluster_template_dict['project_id'] = context.project_id
        cluster_template_dict['user_id'] = context.user_id
        # check permissions for making cluster_template public or hidden
        if cluster_template_dict['public'] or cluster_template_dict['hidden']:
            if not policy.enforce(
                    context, "clustertemplate:publish", None, do_raise=False):
                raise exception.ClusterTemplatePublishDenied()

        # NOTE(yuywz): We will generate a random human-readable name for
        # cluster_template if the name is not specified by user.
        arg_name = cluster_template_dict.get('name')
        name = arg_name or self._generate_name_for_cluster_template(context)
        cluster_template_dict['name'] = name

        new_cluster_template = objects.ClusterTemplate(context,
                                                       **cluster_template_dict)
        new_cluster_template.create()
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('clustertemplates',
                                                 new_cluster_template.uuid)
        return ClusterTemplate.convert_with_links(new_cluster_template)
예제 #50
0
파일: cluster.py 프로젝트: sangtq-vn/magnum
    def _patch(self, cluster_ident, patch):
        context = pecan.request.context
        if context.is_admin:
            policy.enforce(context,
                           "cluster:update_all_projects",
                           action="cluster:update_all_projects")
            context.all_tenants = True

        cluster = api_utils.get_resource('Cluster', cluster_ident)
        policy.enforce(context,
                       'cluster:update',
                       cluster.as_dict(),
                       action='cluster:update')
        policy.enforce(context,
                       "cluster:update_health_status",
                       action="cluster:update_health_status")
        try:
            cluster_dict = cluster.as_dict()
            new_cluster = Cluster(
                **api_utils.apply_jsonpatch(cluster_dict, patch))
        except api_utils.JSONPATCH_EXCEPTIONS as e:
            raise exception.PatchError(patch=patch, reason=e)

        # NOTE(ttsiouts): magnum.objects.Cluster.node_count will be a
        # property so we won't be able to store it in the object. So
        # instead of object_what_changed compare the new and the old
        # clusters.
        delta = set()
        for field in new_cluster.fields:
            if getattr(cluster, field) != getattr(new_cluster, field):
                delta.add(field)

        validation.validate_cluster_properties(delta)

        # NOTE(brtknr): cluster.node_count is the size of the whole cluster
        # which includes non-default nodegroups. However cluster_update expects
        # node_count to be the size of the default_ng_worker therefore return
        # this value unless the patch object says otherwise.
        node_count = cluster.default_ng_worker.node_count
        for p in patch:
            if p['path'] == '/node_count':
                node_count = p.get('value') or new_cluster.node_count

        return (cluster, node_count, new_cluster.health_status,
                new_cluster.health_status_reason)
예제 #51
0
def check_policy_on_container(container, action):
    context = pecan.request.context
    policy.enforce(context, action, container, action=action)
예제 #52
0
    def post(self, cluster):
        """Create a new cluster.

        :param cluster: a cluster within the request body.
        """
        context = pecan.request.context
        policy.enforce(context, 'cluster:create',
                       action='cluster:create')

        self._check_cluster_quota_limit(context)

        temp_id = cluster.cluster_template_id
        cluster_template = objects.ClusterTemplate.get_by_uuid(context,
                                                               temp_id)
        # If keypair not present, use cluster_template value
        if cluster.keypair is None:
            cluster.keypair = cluster_template.keypair_id

        # If labels is not present, use cluster_template value
        if cluster.labels == wtypes.Unset or not cluster.labels:
            cluster.labels = cluster_template.labels
        else:
            # If labels are provided check if the user wishes to merge
            # them with the values from the cluster template.
            if cluster.merge_labels:
                labels = cluster_template.labels
                labels.update(cluster.labels)
                cluster.labels = labels

        cinder_csi_enabled = cluster.labels.get('cinder_csi_enabled', True)
        if (cluster_template.volume_driver == 'cinder' and
                not strutils.bool_from_string(cinder_csi_enabled)):
            warnings.warn(self._in_tree_cinder_volume_driver_deprecation_note,
                          DeprecationWarning)
            LOG.warning(self._in_tree_cinder_volume_driver_deprecation_note)

        # If floating_ip_enabled is not present, use cluster_template value
        if cluster.floating_ip_enabled == wtypes.Unset:
            cluster.floating_ip_enabled = cluster_template.floating_ip_enabled

        # If master_lb_enabled is not present, use cluster_template value
        if cluster.master_lb_enabled == wtypes.Unset:
            cluster.master_lb_enabled = cluster_template.master_lb_enabled

        attributes = ["docker_volume_size", "master_flavor_id", "flavor_id",
                      "fixed_network", "fixed_subnet"]
        for attr in attributes:
            if (getattr(cluster, attr) == wtypes.Unset or
                    not getattr(cluster, attr)):
                setattr(cluster, attr, getattr(cluster_template, attr))

        cluster_dict = cluster.as_dict()

        attr_validator.validate_os_resources(context,
                                             cluster_template.as_dict(),
                                             cluster_dict)
        attr_validator.validate_master_count(cluster_dict,
                                             cluster_template.as_dict())

        cluster_dict['project_id'] = context.project_id
        cluster_dict['user_id'] = context.user_id
        # NOTE(yuywz): We will generate a random human-readable name for
        # cluster if the name is not specified by user.
        name = cluster_dict.get('name') or \
            self._generate_name_for_cluster(context)
        cluster_dict['name'] = name
        cluster_dict['coe_version'] = None
        cluster_dict['container_version'] = None

        node_count = cluster_dict.pop('node_count')
        master_count = cluster_dict.pop('master_count')
        new_cluster = objects.Cluster(context, **cluster_dict)
        new_cluster.uuid = uuid.uuid4()
        pecan.request.rpcapi.cluster_create_async(new_cluster,
                                                  master_count, node_count,
                                                  cluster.create_timeout)

        return ClusterID(new_cluster.uuid)
예제 #53
0
파일: bay.py 프로젝트: wirespecter/magnum
 def _delete(self, bay_ident):
     context = pecan.request.context
     bay = api_utils.get_resource('Cluster', bay_ident)
     policy.enforce(context, 'bay:delete', bay.as_dict(),
                    action='bay:delete')
     return bay
예제 #54
0
def check_policy_on_bay(bay_id, action):
    context = pecan.request.context
    bay = api_utils.get_resource('Bay', bay_id)
    policy.enforce(context, action, bay, action=action)
예제 #55
0
    def post(self, cluster):
        """Create a new cluster.

        :param cluster: a cluster within the request body.
        """
        context = pecan.request.context
        policy.enforce(context, 'cluster:create', action='cluster:create')

        self._check_cluster_quota_limit(context)

        temp_id = cluster.cluster_template_id
        cluster_template = objects.ClusterTemplate.get_by_uuid(
            context, temp_id)
        # If keypair not present, use cluster_template value
        if cluster.keypair is None:
            cluster.keypair = cluster_template.keypair_id

        # If labels is not present, use cluster_template value
        if cluster.labels == wtypes.Unset:
            cluster.labels = cluster_template.labels

        # If floating_ip_enabled is not present, use cluster_template value
        if cluster.floating_ip_enabled == wtypes.Unset:
            cluster.floating_ip_enabled = cluster_template.floating_ip_enabled

        attributes = [
            "docker_volume_size", "master_flavor_id", "flavor_id",
            "fixed_network", "fixed_subnet"
        ]
        for attr in attributes:
            if (getattr(cluster, attr) == wtypes.Unset
                    or not getattr(cluster, attr)):
                setattr(cluster, attr, getattr(cluster_template, attr))

        cluster_dict = cluster.as_dict()

        attr_validator.validate_os_resources(context,
                                             cluster_template.as_dict(),
                                             cluster_dict)
        attr_validator.validate_master_count(cluster_dict,
                                             cluster_template.as_dict())

        cluster_dict['project_id'] = context.project_id
        cluster_dict['user_id'] = context.user_id
        # NOTE(yuywz): We will generate a random human-readable name for
        # cluster if the name is not specified by user.
        name = cluster_dict.get('name') or \
            self._generate_name_for_cluster(context)
        cluster_dict['name'] = name
        cluster_dict['coe_version'] = None
        cluster_dict['container_version'] = None

        node_count = cluster_dict.pop('node_count')
        master_count = cluster_dict.pop('master_count')
        new_cluster = objects.Cluster(context, **cluster_dict)
        new_cluster.uuid = uuid.uuid4()
        pecan.request.rpcapi.cluster_create_async(new_cluster, master_count,
                                                  node_count,
                                                  cluster.create_timeout)

        return ClusterID(new_cluster.uuid)