Commit ebe865a5 by Xinran WANG Committed by Yumeng Bao

Add AttachHandle and ControlpathID objects

Add AttachHandle and ControlpathID objects and related DB APIs.

Change-Id: I9f5a0d63ca1a181c4a328881951a93b5356e1d3a
Stroy: 2004248
parent c17b4280
......@@ -86,6 +86,14 @@ class CyborgException(Exception):
return unicode(self.args[0])
class AttachHandleAlreadyExists(CyborgException):
_msg_fmt = _("AttachHandle with uuid %(uuid)s already exists.")
class ControlpathIDAlreadyExists(CyborgException):
_msg_fmt = _("ControlpathID with uuid %(uuid)s already exists.")
class ConfigInvalid(CyborgException):
_msg_fmt = _("Invalid configuration file. %(error_msg)s")
......@@ -147,6 +155,14 @@ class ServiceNotFound(NotFound):
msg_fmt = _("Service %(service_id)s could not be found.")
class AttachHandleNotFound(NotFound):
_msg_fmt = _("AttachHandle %(uuid)s could not be found.")
class ControlpathIDNotFound(NotFound):
_msg_fmt = _("ControlpathID %(uuid)s could not be found.")
class ConfGroupForServiceTypeNotFound(ServiceNotFound):
msg_fmt = _("No conf group name could be found for service type "
"%(stype)s.")
......
......@@ -123,6 +123,7 @@ class Connection(object):
def attribute_delete(self, context, uuid):
"""Delete an attribute."""
# quota
@abc.abstractmethod
def quota_reserve(self, context, resources, deltas, expire,
until_refresh, max_age, project_id=None,
......@@ -153,3 +154,63 @@ class Connection(object):
@abc.abstractmethod
def extarq_get(self, context, uuid):
"""Get requested extarq."""
# attach_handle
@abc.abstractmethod
def attach_handle_create(self, context, values):
"""Create a new attach_handle"""
@abc.abstractmethod
def attach_handle_get_by_uuid(self, context, uuid):
"""Get requested attach_handle"""
@abc.abstractmethod
def attach_handle_get_by_id(self, context, id):
"""Get requested attach_handle"""
@abc.abstractmethod
def attach_handle_get_by_filters(self, context,
filters, sort_key='created_at',
sort_dir='desc', limit=None,
marker=None, columns_to_join=None):
"""Get requested deployable by filters."""
@abc.abstractmethod
def attach_handle_list(self, context):
"""Get requested list of attach_handles"""
@abc.abstractmethod
def attach_handle_delete(self, context, uuid):
"""Delete an attach_handle"""
@abc.abstractmethod
def attach_handle_update(self, context, uuid, values):
"""Update an attach_handle"""
# control_path_id
@abc.abstractmethod
def control_path_create(self, context, values):
"""Create a new control path id"""
@abc.abstractmethod
def control_path_get_by_uuid(self, context, uuid):
"""Get requested control path id"""
@abc.abstractmethod
def control_path_get_by_filters(self, context,
filters, sort_key='created_at',
sort_dir='desc', limit=None,
marker=None, columns_to_join=None):
"""Get requested deployable by filters."""
@abc.abstractmethod
def control_path_list(self, context):
"""Get requested list of control path ids"""
@abc.abstractmethod
def control_path_delete(self, context, uuid):
"""Delete a control path id"""
@abc.abstractmethod
def control_path_update(self, context, uuid, values):
"""Update a control path id"""
......@@ -30,3 +30,5 @@ def register_all():
__import__('cyborg.objects.attribute')
__import__('cyborg.objects.arq')
__import__('cyborg.objects.ext_arq')
__import__('cyborg.objects.attach_handle')
__import__('cyborg.objects.control_path')
# Copyright 2019 Intel, Inc.
# 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_log import log as logging
from oslo_versionedobjects import base as object_base
from cyborg.db import api as dbapi
from cyborg.objects import base
from cyborg.objects import fields as object_fields
LOG = logging.getLogger(__name__)
ATTACH_TYPE = ["PCI", "MDEV"]
@base.CyborgObjectRegistry.register
class AttachHandle(base.CyborgObject, object_base.VersionedObjectDictCompat):
# Version 1.0: Initial version
VERSION = '1.0'
dbapi = dbapi.get_instance()
fields = {
'id': object_fields.IntegerField(nullable=False),
'uuid': object_fields.UUIDField(nullable=False),
'deployable_id': object_fields.IntegerField(nullable=False),
'attach_type': object_fields.EnumField(valid_values=ATTACH_TYPE,
nullable=False),
# attach_info should be JSON here.
'attach_info': object_fields.StringField(nullable=False)
}
def create(self, context):
"""Create a AttachHandle record in the DB."""
values = self.obj_get_changes()
db_ah = self.dbapi.attach_handle_create(context, values)
self._from_db_object(self, db_ah)
@classmethod
def get(cls, context, uuid):
"""Find a DB AttachHandle and return an Obj AttachHandle."""
db_ah = cls.dbapi.attach_handle_get_by_uuid(context, uuid)
obj_ah = cls._from_db_object(cls(context), db_ah)
return obj_ah
@classmethod
def get_by_id(cls, context, id):
"""Find a DB AttachHandle by ID and return an Obj AttachHandle."""
db_ah = cls.dbapi.attach_handle_get_by_id(context, id)
obj_ah = cls._from_db_object(cls(context), db_ah)
return obj_ah
@classmethod
def list(cls, context, filters={}):
"""Return a list of AttachHandle objects."""
if filters:
sort_dir = filters.pop('sort_dir', 'desc')
sort_key = filters.pop('sort_key', 'create_at')
limit = filters.pop('limit', None)
marker = filters.pop('marker_obj', None)
db_ahs = cls.dbapi.attach_handle_get_by_filters(context, filters,
sort_dir=sort_dir,
sort_key=sort_key,
limit=limit,
marker=marker)
else:
db_ahs = cls.dbapi.attach_handle_list(context)
obj_ah_list = cls._from_db_object_list(db_ahs, context)
return obj_ah_list
def save(self, context):
"""Update an AttachHandle record in the DB"""
updates = self.obj_get_changes()
db_ahs = self.dbapi.attach_handle_update(context, self.uuid, updates)
self._from_db_object(self, db_ahs)
def destroy(self, context):
"""Delete a AttachHandle from the DB."""
self.dbapi.attach_handle_delete(context, self.uuid)
self.obj_reset_changes()
# Copyright 2019 Intel, Inc.
# 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_log import log as logging
from oslo_versionedobjects import base as object_base
from cyborg.db import api as dbapi
from cyborg.objects import base
from cyborg.objects import fields as object_fields
LOG = logging.getLogger(__name__)
CPID_TYPE = ["PCI", "MDEV"]
@base.CyborgObjectRegistry.register
class ControlpathID(base.CyborgObject, object_base.VersionedObjectDictCompat):
# Version 1.0: Initial version
VERSION = '1.0'
dbapi = dbapi.get_instance()
fields = {
'id': object_fields.IntegerField(nullable=False),
'uuid': object_fields.UUIDField(nullable=False),
'deployable_id': object_fields.IntegerField(nullable=False),
'cpid_type': object_fields.EnumField(valid_values=CPID_TYPE,
nullable=False),
'cpid_info': object_fields.StringField(nullable=False)
}
def create(self, context):
"""Create a ControlPathID record in the DB."""
values = self.obj_get_changes()
db_cp = self.dbapi.control_path_create(context, values)
self._from_db_object(self, db_cp)
@classmethod
def get(cls, context, uuid):
"""Find a DB ControlpathID and return an Obj ControlpathID."""
db_cp = cls.dbapi.control_path_get_by_uuid(context, uuid)
obj_cp = cls._from_db_object(cls(context), db_cp)
return obj_cp
@classmethod
def list(cls, context, filters={}):
"""Return a list of ControlpathID objects."""
if filters:
sort_dir = filters.pop('sort_dir', 'desc')
sort_key = filters.pop('sort_key', 'create_at')
limit = filters.pop('limit', None)
marker = filters.pop('marker_obj', None)
db_cps = cls.dbapi.control_path_get_by_filters(context, filters,
sort_dir=sort_dir,
sort_key=sort_key,
limit=limit,
marker=marker)
else:
db_cps = cls.dbapi.control_path_list(context)
obj_cp_list = cls._from_db_object_list(db_cps, context)
return obj_cp_list
def save(self, context):
"""Update an ControlpathID record in the DB"""
updates = self.obj_get_changes()
db_cps = self.dbapi.control_path_update(context, self.uuid, updates)
self._from_db_object(self, db_cps)
def destroy(self, context):
"""Delete a ControlpathID from the DB."""
self.dbapi.control_path_delete(context, self.uuid)
self.obj_reset_changes()
......@@ -18,6 +18,7 @@ from oslo_versionedobjects import fields as object_fields
from cyborg.common import constants
# Import fields from oslo_versionedobjects
EnumField = object_fields.EnumField
IntegerField = object_fields.IntegerField
UUIDField = object_fields.UUIDField
StringField = object_fields.StringField
......
......@@ -86,3 +86,27 @@ def get_test_arq(**kwargs):
'updated_at': kwargs.get('updated_at', None),
'substate': kwargs.get('substate', 'Initial'),
}
def get_test_attach_handle(**kw):
return {
'uuid': kw.get('uuid', '10efe63d-dfea-4a37-ad94-4116fba5098'),
'id': kw.get('id', 1),
'deployable_id': kw.get('deployable_id', 1),
'attach_type': kw.get('attach_type', "PCI"),
'attach_info': kw.get('attach_info', "attach_info"),
'created_at': kw.get('create_at', None),
'updated_at': kw.get('updated_at', None),
}
def get_test_control_path(**kw):
return {
'uuid': kw.get('uuid', '10efe63d-dfea-4a37-ad94-4116fba5098'),
'id': kw.get('id', 1),
'deployable_id': kw.get('deployable_id', 1),
'cpid_type': kw.get('cpid_type', "PCI"),
'cpid_info': kw.get('cpid_info', "cpid_info"),
'created_at': kw.get('create_at', None),
'updated_at': kw.get('updated_at', None),
}
# Copyright 2019 Intel, Inc.
#
# 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.
import mock
from cyborg import objects
from cyborg.tests.unit.db import base
from cyborg.tests.unit.db import utils
class TestAttachHandleObject(base.DbTestCase):
def setUp(self):
super(TestAttachHandleObject, self).setUp()
self.fake_attach_handle = utils.get_test_attach_handle()
def test_get(self):
uuid = self.fake_attach_handle['uuid']
with mock.patch.object(self.dbapi, 'attach_handle_get_by_uuid',
autospec=True) as mock_attach_handle_get:
mock_attach_handle_get.return_value = self.fake_attach_handle
attach_handle = objects.AttachHandle.get(self.context, uuid)
mock_attach_handle_get.assert_called_once_with(self.context, uuid)
self.assertEqual(self.context, attach_handle._context)
def test_get_by_id(self):
id = self.fake_attach_handle['id']
with mock.patch.object(self.dbapi, 'attach_handle_get_by_id',
autospec=True) as mock_attach_handle_get:
mock_attach_handle_get.return_value = self.fake_attach_handle
attach_handle = objects.AttachHandle.get_by_id(self.context, id)
mock_attach_handle_get.assert_called_once_with(self.context, id)
self.assertEqual(self.context, attach_handle._context)
def test_list(self):
with mock.patch.object(self.dbapi, 'attach_handle_list',
autospec=True) as mock_attach_handle_list:
mock_attach_handle_list.return_value = [self.fake_attach_handle]
attach_handles = objects.AttachHandle.list(self.context)
self.assertEqual(1, mock_attach_handle_list.call_count)
self.assertEqual(1, len(attach_handles))
self.assertIsInstance(attach_handles[0], objects.AttachHandle)
self.assertEqual(self.context, attach_handles[0]._context)
def test_create(self):
with mock.patch.object(self.dbapi, 'attach_handle_create',
autospec=True) as mock_attach_handle_create:
mock_attach_handle_create.return_value = self.fake_attach_handle
attach_handle = objects.AttachHandle(self.context,
**self.fake_attach_handle)
attach_handle.create(self.context)
mock_attach_handle_create.assert_called_once_with(
self.context, self.fake_attach_handle)
self.assertEqual(self.context, attach_handle._context)
def test_destroy(self):
uuid = self.fake_attach_handle['uuid']
with mock.patch.object(self.dbapi, 'attach_handle_get_by_uuid',
autospec=True) as mock_attach_handle_get:
mock_attach_handle_get.return_value = self.fake_attach_handle
with mock.patch.object(self.dbapi, 'attach_handle_delete',
autospec=True) as mock_attach_handle_delete:
attach_handle = objects.AttachHandle.get(self.context, uuid)
attach_handle.destroy(self.context)
mock_attach_handle_delete.assert_called_once_with(self.context,
uuid)
self.assertEqual(self.context, attach_handle._context)
def test_update(self):
uuid = self.fake_attach_handle['uuid']
with mock.patch.object(self.dbapi, 'attach_handle_get_by_uuid',
autospec=True) as mock_attach_handle_get:
mock_attach_handle_get.return_value = self.fake_attach_handle
with mock.patch.object(self.dbapi, 'attach_handle_update',
autospec=True) as mock_attach_handle_update:
fake = self.fake_attach_handle
fake["attach_info"] = "new_attach_info"
mock_attach_handle_update.return_value = fake
attach_handle = objects.AttachHandle.get(self.context, uuid)
attach_handle.attach_info = 'new_attach_info'
attach_handle.save(self.context)
mock_attach_handle_get.assert_called_once_with(self.context,
uuid)
mock_attach_handle_update.assert_called_once_with(
self.context, uuid,
{'attach_info': 'new_attach_info'})
self.assertEqual(self.context, attach_handle._context)
# Copyright 2019 Intel, Inc.
#
# 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.
import mock
from cyborg import objects
from cyborg.tests.unit.db import base
from cyborg.tests.unit.db import utils
class TestControlpathIDObject(base.DbTestCase):
def setUp(self):
super(TestControlpathIDObject, self).setUp()
self.fake_control_path = utils.get_test_control_path()
def test_get(self):
uuid = self.fake_control_path['uuid']
with mock.patch.object(self.dbapi, 'control_path_get_by_uuid',
autospec=True) as mock_control_path_get:
mock_control_path_get.return_value = self.fake_control_path
control_path = objects.ControlpathID.get(self.context, uuid)
mock_control_path_get.assert_called_once_with(self.context, uuid)
self.assertEqual(self.context, control_path._context)
def test_list(self):
with mock.patch.object(self.dbapi, 'control_path_list',
autospec=True) as mock_control_path_list:
mock_control_path_list.return_value = [self.fake_control_path]
control_paths = objects.ControlpathID.list(self.context)
self.assertEqual(1, mock_control_path_list.call_count)
self.assertEqual(1, len(control_paths))
self.assertIsInstance(control_paths[0], objects.ControlpathID)
self.assertEqual(self.context, control_paths[0]._context)
def test_create(self):
with mock.patch.object(self.dbapi, 'control_path_create',
autospec=True) as mock_control_path_create:
mock_control_path_create.return_value = self.fake_control_path
control_path = objects.ControlpathID(self.context,
**self.fake_control_path)
control_path.create(self.context)
mock_control_path_create.assert_called_once_with(
self.context, self.fake_control_path)
self.assertEqual(self.context, control_path._context)
def test_destroy(self):
uuid = self.fake_control_path['uuid']
with mock.patch.object(self.dbapi, 'control_path_get_by_uuid',
autospec=True) as mock_control_path_get:
mock_control_path_get.return_value = self.fake_control_path
with mock.patch.object(self.dbapi, 'control_path_delete',
autospec=True) as mock_control_path_delete:
control_path = objects.ControlpathID.get(self.context, uuid)
control_path.destroy(self.context)
mock_control_path_delete.assert_called_once_with(self.context,
uuid)
self.assertEqual(self.context, control_path._context)
def test_update(self):
uuid = self.fake_control_path['uuid']
with mock.patch.object(self.dbapi, 'control_path_get_by_uuid',
autospec=True) as mock_control_path_get:
mock_control_path_get.return_value = self.fake_control_path
with mock.patch.object(self.dbapi, 'control_path_update',
autospec=True) as mock_control_path_update:
fake = self.fake_control_path
fake["cpid_info"] = "new_cpid_info"
mock_control_path_update.return_value = fake
control_path = objects.ControlpathID.get(self.context, uuid)
control_path.cpid_info = 'new_cpid_info'
control_path.save(self.context)
mock_control_path_get.assert_called_once_with(self.context,
uuid)
mock_control_path_update.assert_called_once_with(
self.context, uuid,
{'cpid_info': 'new_cpid_info'})
self.assertEqual(self.context, control_path._context)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment