From 282a099e236604964512ec4d384537399f0a2b3e Mon Sep 17 00:00:00 2001 From: gong yong sheng Date: Tue, 2 Aug 2016 09:54:39 +0800 Subject: [PATCH] Device refactor Part1: Rename device db name This patch changes the table name into single format. Later we will change all the table names into single format in tacker. Next patches will refactor plugin codes. Change-Id: I7052bc7557998b087f8e32a5d6823feaa55d5e40 Partial-bug: #1589018 --- tacker/db/migration/__init__.py | 21 +++ .../versions/22f5385a3d50_rename_devicedb.py | 52 ++++++ .../alembic_migrations/versions/HEAD | 2 +- tacker/db/nfvo/nfvo_db.py | 2 +- tacker/db/vm/vm_db.py | 171 +++++++++--------- tacker/tests/unit/vm/test_plugin.py | 6 +- tacker/vm/plugin.py | 2 +- 7 files changed, 168 insertions(+), 88 deletions(-) create mode 100644 tacker/db/migration/alembic_migrations/versions/22f5385a3d50_rename_devicedb.py diff --git a/tacker/db/migration/__init__.py b/tacker/db/migration/__init__.py index 80de7f4cb..4617f2956 100644 --- a/tacker/db/migration/__init__.py +++ b/tacker/db/migration/__init__.py @@ -72,3 +72,24 @@ def modify_foreign_keys_constraint(table_names): for table in table_names: fk_constraints = inspector.get_foreign_keys(table) create_foreign_key_constraint(table, fk_constraints) + + +def modify_foreign_keys_constraint_with_col_change( + table_name, old_local_col, new_local_col, existing_type, + nullable=False): + inspector = reflection.Inspector.from_engine(op.get_bind()) + fk_constraints = inspector.get_foreign_keys(table_name) + for fk in fk_constraints: + if old_local_col in fk['constrained_columns']: + drop_foreign_key_constraint(table_name, [fk]) + op.alter_column(table_name, old_local_col, + new_column_name=new_local_col, + existing_type=existing_type, + nullable=nullable) + fk_constraints = inspector.get_foreign_keys(table_name) + for fk in fk_constraints: + for i in range(len(fk['constrained_columns'])): + if old_local_col == fk['constrained_columns'][i]: + fk['constrained_columns'][i] = new_local_col + create_foreign_key_constraint(table_name, [fk]) + break diff --git a/tacker/db/migration/alembic_migrations/versions/22f5385a3d50_rename_devicedb.py b/tacker/db/migration/alembic_migrations/versions/22f5385a3d50_rename_devicedb.py new file mode 100644 index 000000000..6e85e30ae --- /dev/null +++ b/tacker/db/migration/alembic_migrations/versions/22f5385a3d50_rename_devicedb.py @@ -0,0 +1,52 @@ +# Copyright 2016 OpenStack Foundation +# +# 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. +# + +"""rename device db tables + +Revision ID: 22f5385a3d50 +Revises: 22f5385a3d4f +Create Date: 2016-08-01 15:47:51.161749 + +""" + +# revision identifiers, used by Alembic. +revision = '22f5385a3d50' +down_revision = '22f5385a3d4f' + +from alembic import op +import sqlalchemy as sa + +from tacker.db import migration + + +def upgrade(active_plugins=None, options=None): + # commands auto generated by Alembic - please adjust! # + op.rename_table('devicetemplates', 'vnfd') + op.rename_table('devicetemplateattributes', 'vnfd_attribute') + op.rename_table('devices', 'vnf') + op.rename_table('deviceattributes', 'vnf_attribute') + migration.modify_foreign_keys_constraint_with_col_change( + 'vnfd_attribute', 'template_id', 'vnfd_id', + sa.String(length=36)) + migration.modify_foreign_keys_constraint_with_col_change( + 'servicetypes', 'template_id', 'vnfd_id', + sa.String(length=36)) + migration.modify_foreign_keys_constraint_with_col_change( + 'vnf', 'template_id', 'vnfd_id', + sa.String(length=36)) + migration.modify_foreign_keys_constraint_with_col_change( + 'vnf_attribute', 'device_id', 'vnf_id', + sa.String(length=36)) + # end Alembic commands # diff --git a/tacker/db/migration/alembic_migrations/versions/HEAD b/tacker/db/migration/alembic_migrations/versions/HEAD index ba9c47217..acd364f08 100644 --- a/tacker/db/migration/alembic_migrations/versions/HEAD +++ b/tacker/db/migration/alembic_migrations/versions/HEAD @@ -1 +1 @@ -22f5385a3d4f +22f5385a3d50 diff --git a/tacker/db/nfvo/nfvo_db.py b/tacker/db/nfvo/nfvo_db.py index e44659dbf..7da96edec 100644 --- a/tacker/db/nfvo/nfvo_db.py +++ b/tacker/db/nfvo/nfvo_db.py @@ -131,7 +131,7 @@ class NfvoPluginDb(nfvo.NFVOPluginBase, db_base.CommonDbMixin): def is_vim_still_in_use(self, context, vim_id): with context.session.begin(subtransactions=True): - devices_db = context.session.query(vm_db.Device).filter_by( + devices_db = context.session.query(vm_db.VNF).filter_by( vim_id=vim_id).first() if devices_db is not None: raise nfvo.VimInUseException(vim_id=vim_id) diff --git a/tacker/db/vm/vm_db.py b/tacker/db/vm/vm_db.py index 06b03678b..ae11f0d0d 100644 --- a/tacker/db/vm/vm_db.py +++ b/tacker/db/vm/vm_db.py @@ -42,9 +42,10 @@ CREATE_STATES = (constants.PENDING_CREATE, constants.DEAD) ########################################################################### # db tables -class DeviceTemplate(model_base.BASE, models_v1.HasId, models_v1.HasTenant): - """Represents template to create hosting device.""" +class VNFD(model_base.BASE, models_v1.HasId, models_v1.HasTenant): + """Represents VNFD to create VNF.""" + __tablename__ = 'vnfd' # Descriptive name name = sa.Column(sa.String(255), nullable=False) description = sa.Column(sa.Text) @@ -61,7 +62,7 @@ class DeviceTemplate(model_base.BASE, models_v1.HasId, models_v1.HasTenant): mgmt_driver = sa.Column(sa.String(255)) # (key, value) pair to spin up - attributes = orm.relationship('DeviceTemplateAttribute', + attributes = orm.relationship('VNFDAttribute', backref='template') @@ -71,32 +72,36 @@ class ServiceType(model_base.BASE, models_v1.HasId, models_v1.HasTenant): Since a device may provide many services, This is one-to-many relationship. """ - template_id = sa.Column(types.Uuid, sa.ForeignKey('devicetemplates.id'), - nullable=False) + vnfd_id = sa.Column(types.Uuid, sa.ForeignKey('vnfd.id'), + nullable=False) service_type = sa.Column(sa.String(64), nullable=False) -class DeviceTemplateAttribute(model_base.BASE, models_v1.HasId): +class VNFDAttribute(model_base.BASE, models_v1.HasId): """Represents attributes necessary for spinning up VM in (key, value) pair key value pair is adopted for being agnostic to actuall manager of VMs like nova, heat or others. e.g. image-id, flavor-id for Nova. The interpretation is up to actual driver of hosting device. """ - template_id = sa.Column(types.Uuid, sa.ForeignKey('devicetemplates.id'), - nullable=False) + + __tablename__ = 'vnfd_attribute' + vnfd_id = sa.Column(types.Uuid, sa.ForeignKey('vnfd.id'), + nullable=False) key = sa.Column(sa.String(255), nullable=False) value = sa.Column(sa.TEXT(65535), nullable=True) -class Device(model_base.BASE, models_v1.HasId, models_v1.HasTenant): +class VNF(model_base.BASE, models_v1.HasId, models_v1.HasTenant): """Represents devices that hosts services. Here the term, 'VM', is intentionally avoided because it can be VM or other container. """ - template_id = sa.Column(types.Uuid, sa.ForeignKey('devicetemplates.id')) - template = orm.relationship('DeviceTemplate') + + __tablename__ = 'vnf' + vnfd_id = sa.Column(types.Uuid, sa.ForeignKey('vnfd.id')) + vnfd = orm.relationship('VNFD') name = sa.Column(sa.String(255), nullable=False) description = sa.Column(sa.Text, nullable=True) @@ -109,7 +114,7 @@ class Device(model_base.BASE, models_v1.HasId, models_v1.HasTenant): # opaque string. # e.g. (driver, mgmt_url) = (ssh, ip address), ... mgmt_url = sa.Column(sa.String(255), nullable=True) - attributes = orm.relationship("DeviceAttribute", backref="device") + attributes = orm.relationship("VNFAttribute", backref="device") status = sa.Column(sa.String(64), nullable=False) vim_id = sa.Column(types.Uuid, sa.ForeignKey('vims.id'), nullable=False) @@ -118,15 +123,17 @@ class Device(model_base.BASE, models_v1.HasId, models_v1.HasTenant): error_reason = sa.Column(sa.Text, nullable=True) -class DeviceAttribute(model_base.BASE, models_v1.HasId): +class VNFAttribute(model_base.BASE, models_v1.HasId): """Represents kwargs necessary for spinning up VM in (key, value) pair. key value pair is adopted for being agnostic to actuall manager of VMs like nova, heat or others. e.g. image-id, flavor-id for Nova. The interpretation is up to actual driver of hosting device. """ - device_id = sa.Column(types.Uuid, sa.ForeignKey('devices.id'), - nullable=False) + + __tablename__ = 'vnf_attribute' + vnf_id = sa.Column(types.Uuid, sa.ForeignKey('vnf.id'), + nullable=False) key = sa.Column(sa.String(255), nullable=False) # json encoded value. example # "nic": [{"net-id": }, {"port-id": }] @@ -150,11 +157,11 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin): try: return self._get_by_id(context, model, id) except orm_exc.NoResultFound: - if issubclass(model, DeviceTemplate): + if issubclass(model, VNFD): raise vnfm.DeviceTemplateNotFound(device_template_id=id) elif issubclass(model, ServiceType): raise vnfm.ServiceTypeNotFound(service_type_id=id) - if issubclass(model, Device): + if issubclass(model, VNF): raise vnfm.DeviceNotFound(device_id=id) else: raise @@ -186,11 +193,11 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin): LOG.debug(_('device_db attributes %s'), device_db.attributes) res = { 'device_template': - self._make_template_dict(device_db.template), + self._make_template_dict(device_db.vnfd), 'attributes': self._make_dev_attrs_dict(device_db.attributes), } key_list = ('id', 'tenant_id', 'name', 'description', 'instance_id', - 'vim_id', 'placement_attr', 'template_id', 'status', + 'vim_id', 'placement_attr', 'vnfd_id', 'status', 'mgmt_url', 'error_reason') res.update((key, device_db[key]) for key in key_list) return self._fields(res, fields) @@ -227,7 +234,7 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin): with context.session.begin(subtransactions=True): template_id = str(uuid.uuid4()) - template_db = DeviceTemplate( + template_db = VNFD( id=template_id, tenant_id=tenant_id, name=template.get('name'), @@ -236,9 +243,9 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin): mgmt_driver=mgmt_driver) context.session.add(template_db) for (key, value) in template.get('attributes', {}).items(): - attribute_db = DeviceTemplateAttribute( + attribute_db = VNFDAttribute( id=str(uuid.uuid4()), - template_id=template_id, + vnfd_id=template_id, key=key, value=value) context.session.add(attribute_db) @@ -247,7 +254,7 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin): service_type_db = ServiceType( id=str(uuid.uuid4()), tenant_id=tenant_id, - template_id=template_id, + vnfd_id=template_id, service_type=service_type) context.session.add(service_type_db) @@ -259,7 +266,7 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin): def update_device_template(self, context, device_template_id, device_template): with context.session.begin(subtransactions=True): - template_db = self._get_resource(context, DeviceTemplate, + template_db = self._get_resource(context, VNFD, device_template_id) template_db.update(device_template['device_template']) return self._make_template_dict(template_db) @@ -268,27 +275,27 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin): with context.session.begin(subtransactions=True): # TODO(yamahata): race. prevent from newly inserting hosting device # that refers to this template - devices_db = context.session.query(Device).filter_by( - template_id=device_template_id).first() + devices_db = context.session.query(VNF).filter_by( + vnfd_id=device_template_id).first() if devices_db is not None: raise vnfm.DeviceTemplateInUse( device_template_id=device_template_id) context.session.query(ServiceType).filter_by( - template_id=device_template_id).delete() - context.session.query(DeviceTemplateAttribute).filter_by( - template_id=device_template_id).delete() - template_db = self._get_resource(context, DeviceTemplate, + vnfd_id=device_template_id).delete() + context.session.query(VNFDAttribute).filter_by( + vnfd_id=device_template_id).delete() + template_db = self._get_resource(context, VNFD, device_template_id) context.session.delete(template_db) def get_device_template(self, context, device_template_id, fields=None): - template_db = self._get_resource(context, DeviceTemplate, + template_db = self._get_resource(context, VNFD, device_template_id) return self._make_template_dict(template_db) def get_device_templates(self, context, filters, fields=None): - return self._get_collection(context, DeviceTemplate, + return self._get_collection(context, VNFD, self._make_template_dict, filters=filters, fields=fields) @@ -298,19 +305,19 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin): LOG.debug(_('required_attributes %s'), required_attributes) with context.session.begin(subtransactions=True): query = ( - context.session.query(DeviceTemplate). + context.session.query(VNFD). filter( sa.exists(). where(sa.and_( - DeviceTemplate.id == ServiceType.template_id, + VNFD.id == ServiceType.vnfd_id, ServiceType.service_type == service_type)))) for key in required_attributes: query = query.filter( sa.exists(). where(sa.and_( - DeviceTemplate.id == - DeviceTemplateAttribute.template_id, - DeviceTemplateAttribute.key == key))) + VNFD.id == + VNFDAttribute.vnfd_id, + VNFDAttribute.key == key))) LOG.debug(_('statements %s'), query) template_db = query.first() if template_db: @@ -318,14 +325,14 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin): def _device_attribute_update_or_create( self, context, device_id, key, value): - arg = (self._model_query(context, DeviceAttribute). - filter(DeviceAttribute.device_id == device_id). - filter(DeviceAttribute.key == key).first()) + arg = (self._model_query(context, VNFAttribute). + filter(VNFAttribute.vnf_id == device_id). + filter(VNFAttribute.key == key).first()) if arg: arg.value = value else: - arg = DeviceAttribute( - id=str(uuid.uuid4()), device_id=device_id, + arg = VNFAttribute( + id=str(uuid.uuid4()), vnf_id=device_id, key=key, value=value) context.session.add(arg) @@ -340,22 +347,22 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin): vim_id = device.get('vim_id') placement_attr = device.get('placement_attr', {}) with context.session.begin(subtransactions=True): - template_db = self._get_resource(context, DeviceTemplate, + template_db = self._get_resource(context, VNFD, template_id) - device_db = Device(id=device_id, - tenant_id=tenant_id, - name=name, - description=template_db.description, - instance_id=None, - template_id=template_id, - vim_id=vim_id, - placement_attr=placement_attr, - status=constants.PENDING_CREATE, - error_reason=None) + device_db = VNF(id=device_id, + tenant_id=tenant_id, + name=name, + description=template_db.description, + instance_id=None, + vnfd_id=template_id, + vim_id=vim_id, + placement_attr=placement_attr, + status=constants.PENDING_CREATE, + error_reason=None) context.session.add(device_db) for key, value in attributes.items(): - arg = DeviceAttribute( - id=str(uuid.uuid4()), device_id=device_id, + arg = VNFAttribute( + id=str(uuid.uuid4()), vnf_id=device_id, key=key, value=value) context.session.add(arg) @@ -367,9 +374,9 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin): mgmt_url, device_dict): LOG.debug(_('device_dict %s'), device_dict) with context.session.begin(subtransactions=True): - query = (self._model_query(context, Device). - filter(Device.id == device_id). - filter(Device.status.in_(CREATE_STATES)). + query = (self._model_query(context, VNF). + filter(VNF.id == device_id). + filter(VNF.status.in_(CREATE_STATES)). one()) query.update({'instance_id': instance_id, 'mgmt_url': mgmt_url}) if instance_id is None or device_dict['status'] == constants.ERROR: @@ -383,17 +390,17 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin): def _create_device_status(self, context, device_id, new_status): with context.session.begin(subtransactions=True): - query = (self._model_query(context, Device). - filter(Device.id == device_id). - filter(Device.status.in_(CREATE_STATES)).one()) + query = (self._model_query(context, VNF). + filter(VNF.id == device_id). + filter(VNF.status.in_(CREATE_STATES)).one()) query.update({'status': new_status}) def _get_device_db(self, context, device_id, current_statuses, new_status): try: device_db = ( - self._model_query(context, Device). - filter(Device.id == device_id). - filter(Device.status.in_(current_statuses)). + self._model_query(context, VNF). + filter(VNF.id == device_id). + filter(VNF.status.in_(current_statuses)). with_lockmode('update').one()) except orm_exc.NoResultFound: raise vnfm.DeviceNotFound(device_id=device_id) @@ -424,15 +431,15 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin): def _update_device_post(self, context, device_id, new_status, new_device_dict=None): with context.session.begin(subtransactions=True): - (self._model_query(context, Device). - filter(Device.id == device_id). - filter(Device.status == constants.PENDING_UPDATE). + (self._model_query(context, VNF). + filter(VNF.id == device_id). + filter(VNF.status == constants.PENDING_UPDATE). update({'status': new_status})) dev_attrs = new_device_dict.get('attributes', {}) - (context.session.query(DeviceAttribute). - filter(DeviceAttribute.device_id == device_id). - filter(~DeviceAttribute.key.in_(dev_attrs.keys())). + (context.session.query(VNFAttribute). + filter(VNFAttribute.vnf_id == device_id). + filter(~VNFAttribute.key.in_(dev_attrs.keys())). delete(synchronize_session='fetch')) for (key, value) in dev_attrs.items(): @@ -451,14 +458,14 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin): def _delete_device_post(self, context, device_id, error): with context.session.begin(subtransactions=True): query = ( - self._model_query(context, Device). - filter(Device.id == device_id). - filter(Device.status == constants.PENDING_DELETE)) + self._model_query(context, VNF). + filter(VNF.id == device_id). + filter(VNF.status == constants.PENDING_DELETE)) if error: query.update({'status': constants.ERROR}) else: - (self._model_query(context, DeviceAttribute). - filter(DeviceAttribute.device_id == device_id).delete()) + (self._model_query(context, VNFAttribute). + filter(VNFAttribute.vnf_id == device_id).delete()) query.delete() # reference implementation. needs to be overrided by subclass @@ -493,17 +500,17 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin): self._delete_device_post(context, device_id, False) def get_device(self, context, device_id, fields=None): - device_db = self._get_resource(context, Device, device_id) + device_db = self._get_resource(context, VNF, device_id) return self._make_device_dict(device_db, fields) def get_devices(self, context, filters=None, fields=None): - return self._get_collection(context, Device, self._make_device_dict, + return self._get_collection(context, VNF, self._make_device_dict, filters=filters, fields=fields) def set_device_error_status_reason(self, context, device_id, new_reason): with context.session.begin(subtransactions=True): - (self._model_query(context, Device). - filter(Device.id == device_id). + (self._model_query(context, VNF). + filter(VNF.id == device_id). update({'error_reason': new_reason})) def _mark_device_status(self, device_id, exclude_status, new_status): @@ -511,9 +518,9 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin): with context.session.begin(subtransactions=True): try: device_db = ( - self._model_query(context, Device). - filter(Device.id == device_id). - filter(~Device.status.in_(exclude_status)). + self._model_query(context, VNF). + filter(VNF.id == device_id). + filter(~VNF.status.in_(exclude_status)). with_lockmode('update').one()) except orm_exc.NoResultFound: LOG.warning(_('no device found %s'), device_id) diff --git a/tacker/tests/unit/vm/test_plugin.py b/tacker/tests/unit/vm/test_plugin.py index 103d08558..6ee743b0a 100644 --- a/tacker/tests/unit/vm/test_plugin.py +++ b/tacker/tests/unit/vm/test_plugin.py @@ -97,7 +97,7 @@ class TestVNFMPlugin(db_base.SqlTestCase): def _insert_dummy_device_template(self): session = self.context.session - device_template = vm_db.DeviceTemplate( + device_template = vm_db.VNFD( id='eb094833-995e-49f0-a047-dfb56aaf7c4e', tenant_id='ad7ebc56538745a08ef7c5e97f8bd437', name='fake_template', @@ -110,13 +110,13 @@ class TestVNFMPlugin(db_base.SqlTestCase): def _insert_dummy_device(self): session = self.context.session - device_db = vm_db.Device( + device_db = vm_db.VNF( id='6261579e-d6f3-49ad-8bc3-a9cb974778ff', tenant_id='ad7ebc56538745a08ef7c5e97f8bd437', name='fake_device', description='fake_device_description', instance_id='da85ea1a-4ec4-4201-bbb2-8d9249eca7ec', - template_id='eb094833-995e-49f0-a047-dfb56aaf7c4e', + vnfd_id='eb094833-995e-49f0-a047-dfb56aaf7c4e', vim_id='6261579e-d6f3-49ad-8bc3-a9cb974778ff', placement_attr={'region': 'RegionOne'}, status='ACTIVE') diff --git a/tacker/vm/plugin.py b/tacker/vm/plugin.py index c2f86c12e..1c7d5cee5 100644 --- a/tacker/vm/plugin.py +++ b/tacker/vm/plugin.py @@ -543,7 +543,7 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin): vnf_attributes['template_id'] = vnf_attributes.pop('vnfd_id') vnf_dict = self.create_device(context, vnf) vnf_response = copy.deepcopy(vnf_dict) - vnf_response['vnfd_id'] = vnf_response.pop('template_id') + vnf_response['vnfd_id'] = vnf_response.pop('vnfd_id') return vnf_response def update_vnf(