mogan/mogan/objects/flavor.py

154 lines
5.5 KiB
Python

# Copyright 2016 Huawei Technologies Co.,LTD.
# All Rights Reserved.
#
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_versionedobjects import base as object_base
from mogan.db import api as dbapi
from mogan.objects import base
from mogan.objects import fields as object_fields
OPTIONAL_FIELDS = ['projects']
@base.MoganObjectRegistry.register
class Flavor(base.MoganObject, object_base.VersionedObjectDictCompat):
# Version 1.0: Initial version
VERSION = '1.0'
dbapi = dbapi.get_instance()
fields = {
'uuid': object_fields.UUIDField(nullable=True),
'name': object_fields.StringField(nullable=True),
'description': object_fields.StringField(nullable=True),
'is_public': object_fields.BooleanField(),
'disabled': object_fields.BooleanField(),
'resources': object_fields.FlexibleDictField(nullable=True),
'resource_traits': object_fields.FlexibleDictField(nullable=True),
'resource_aggregates': object_fields.FlexibleDictField(nullable=True),
'projects': object_fields.ListOfStringsField(),
}
def __init__(self, *args, **kwargs):
super(Flavor, self).__init__(*args, **kwargs)
self._orig_projects = {}
@staticmethod
def _from_db_object(context, flavor, db_flavor, expected_attrs=None):
if expected_attrs is None:
expected_attrs = []
for name, field in flavor.fields.items():
if name in OPTIONAL_FIELDS:
continue
value = db_flavor[name]
if isinstance(field, object_fields.IntegerField):
value = value if value is not None else 0
flavor[name] = value
if 'projects' in expected_attrs:
flavor._load_projects(context)
flavor.obj_reset_changes()
return flavor
def _load_projects(self, context):
self.projects = [x['project_id'] for x in
self.dbapi.flavor_access_get(context, self.uuid)]
self.obj_reset_changes(['projects'])
def obj_reset_changes(self, fields=None, recursive=False):
super(Flavor, self).obj_reset_changes(fields=fields,
recursive=recursive)
if fields is None or 'projects' in fields:
self._orig_projects = (list(self.projects)
if self.obj_attr_is_set('projects')
else [])
def obj_what_changed(self):
changes = super(Flavor, self).obj_what_changed()
if 'projects' in self and self.projects != self._orig_projects:
changes.add('projects')
return changes
@staticmethod
def _from_db_object_list(db_objects, cls, context):
"""Converts a list of database entities to a list of formal objects."""
return [Flavor._from_db_object(context, cls(context), obj)
for obj in db_objects]
@classmethod
def list(cls, context):
"""Return a list of Flavor objects."""
db_flavors = cls.dbapi.flavor_get_all(context)
return Flavor._from_db_object_list(db_flavors, cls, context)
@classmethod
def get(cls, context, flavor_uuid):
"""Find a Flavor and return a Flavor object."""
db_flavor = cls.dbapi.flavor_get(context, flavor_uuid)
flavor = Flavor._from_db_object(
context, cls(context), db_flavor,
expected_attrs=['projects'])
return flavor
def create(self, context=None):
"""Create a Flavor record in the DB."""
values = self.obj_get_changes()
db_flavor = self.dbapi.flavor_create(context, values)
self._from_db_object(context, self, db_flavor)
def destroy(self, context=None):
"""Delete the Flavor from the DB."""
self.dbapi.flavor_destroy(context, self.uuid)
self.obj_reset_changes()
def save(self, context=None):
updates = self.obj_get_changes()
projects = updates.pop('projects', None)
# access projects
if projects is not None:
deleted_projects = set(self._orig_projects) - set(projects)
added_projects = set(projects) - set(self._orig_projects)
else:
added_projects = deleted_projects = None
if added_projects or deleted_projects:
self.save_projects(context, added_projects, deleted_projects)
if updates:
self.dbapi.flavor_update(context, self.uuid, updates)
def save_projects(self, context, to_add=None, to_delete=None):
"""Add or delete projects.
:param:to_add: A list of projects to add
:param:to_delete: A list of projects to remove
"""
ident = self.uuid
to_add = to_add if to_add is not None else []
to_delete = to_delete if to_delete is not None else []
for project_id in to_add:
self.dbapi.flavor_access_add(context, ident, project_id)
for project_id in to_delete:
self.dbapi.flavor_access_remove(context, ident, project_id)
self.obj_reset_changes(['projects'])