From 1c50ceed0bc78b862fe711db7592af91c998cedc Mon Sep 17 00:00:00 2001 From: Zhenguo Niu Date: Fri, 8 Sep 2017 11:52:20 +0800 Subject: [PATCH] Add preserve_on_delete to server nic object This field will indicate whether we should delete or unbind the port during server deletion or detaching interfaces. Change-Id: I25834a82b83806bf87b4c7006a8d33d56e2ce976 Closes-Bug: #1715040 --- mogan/db/api.py | 7 ++++ .../91941bf1ebc9_initial_migration.py | 1 + mogan/db/sqlalchemy/api.py | 8 +++++ mogan/db/sqlalchemy/models.py | 1 + mogan/engine/flows/create_server.py | 3 ++ mogan/engine/manager.py | 33 +++++++++++++------ mogan/objects/server_nic.py | 5 +++ mogan/tests/unit/db/utils.py | 1 + mogan/tests/unit/objects/test_objects.py | 2 +- 9 files changed, 50 insertions(+), 11 deletions(-) diff --git a/mogan/db/api.py b/mogan/db/api.py index 03e20852..33af7204 100644 --- a/mogan/db/api.py +++ b/mogan/db/api.py @@ -117,6 +117,13 @@ class Connection(object): This delete a nic db entry. """ + @abc.abstractmethod + def server_nic_get(self, context, port_id): + """Get a nic db entry. + + This gets a nic db entry. + """ + # Servers Faults @abc.abstractmethod def server_fault_create(self, context, values): diff --git a/mogan/db/sqlalchemy/alembic/versions/91941bf1ebc9_initial_migration.py b/mogan/db/sqlalchemy/alembic/versions/91941bf1ebc9_initial_migration.py index 09c407f0..2eb82fb4 100644 --- a/mogan/db/sqlalchemy/alembic/versions/91941bf1ebc9_initial_migration.py +++ b/mogan/db/sqlalchemy/alembic/versions/91941bf1ebc9_initial_migration.py @@ -102,6 +102,7 @@ def upgrade(): sa.Column('network_id', sa.String(length=36), nullable=True), sa.Column('floating_ip', sa.String(length=64), nullable=True), sa.Column('fixed_ips', sa.Text(), nullable=True), + sa.Column('preserve_on_delete', sa.Boolean(), nullable=True), sa.PrimaryKeyConstraint('port_id'), sa.Index('server_nics_server_uuid_idx', 'server_uuid'), mysql_ENGINE='InnoDB', diff --git a/mogan/db/sqlalchemy/api.py b/mogan/db/sqlalchemy/api.py index b96d2940..1399ffcd 100644 --- a/mogan/db/sqlalchemy/api.py +++ b/mogan/db/sqlalchemy/api.py @@ -344,6 +344,14 @@ class Connection(api.Connection): if count != 1: raise exception.PortNotFound(port_id=port_id) + def server_nic_get(self, context, port_id): + query = model_query(context, models.ServerNic).filter_by( + port_id=port_id) + try: + return query.one() + except NoResultFound: + raise exception.PortNotFound(port_id=port_id) + @oslo_db_api.retry_on_deadlock def server_nic_update_or_create(self, context, port_id, values): with _session_for_write() as session: diff --git a/mogan/db/sqlalchemy/models.py b/mogan/db/sqlalchemy/models.py index d2c186c8..e1215098 100644 --- a/mogan/db/sqlalchemy/models.py +++ b/mogan/db/sqlalchemy/models.py @@ -110,6 +110,7 @@ class ServerNic(Base): network_id = Column(String(36), nullable=True) fixed_ips = Column(db_types.JsonEncodedList) floating_ip = Column(String(64), nullable=True) + preserve_on_delete = Column(Boolean) _server = orm.relationship( Server, backref=orm.backref('server_nics', uselist=False), diff --git a/mogan/engine/flows/create_server.py b/mogan/engine/flows/create_server.py index accb52ea..9c65bff8 100644 --- a/mogan/engine/flows/create_server.py +++ b/mogan/engine/flows/create_server.py @@ -154,6 +154,7 @@ class BuildNetworkTask(flow_utils.MoganTask): if vif.get('net_id'): port = self.manager.network_api.create_port( context, vif['net_id'], server.uuid) + preserve_on_delete = False elif vif.get('port_id'): port = self.manager.network_api.show_port( context, vif.get('port_id')) @@ -161,11 +162,13 @@ class BuildNetworkTask(flow_utils.MoganTask): self.manager.network_api.bind_port(context, port['id'], server) + preserve_on_delete = True nic_dict = {'port_id': port['id'], 'network_id': port['network_id'], 'mac_address': port['mac_address'], 'fixed_ips': port['fixed_ips'], + 'preserve_on_delete': preserve_on_delete, 'server_uuid': server.uuid} server_nic = objects.ServerNic(context, **nic_dict) diff --git a/mogan/engine/manager.py b/mogan/engine/manager.py index fe3725ad..91e19f65 100644 --- a/mogan/engine/manager.py +++ b/mogan/engine/manager.py @@ -289,9 +289,9 @@ class EngineManager(base_manager.BaseEngineManager): server.save() def destroy_networks(self, context, server): - ports = server.nics.get_port_ids() - for port in ports: - self._detach_interface(context, server, port) + for nic in server.nics: + self._detach_interface(context, server, nic.port_id, + nic.preserve_on_delete) def _rollback_servers_quota(self, context, number): reserve_opts = {'servers': number} @@ -582,24 +582,28 @@ class EngineManager(base_manager.BaseEngineManager): vif_port = self.network_api.show_port(context, port_id) except Exception: raise exception.PortNotFound(port_id=port_id) - - self.network_api.check_port_availability(vif_port) + try: + self.network_api.check_port_availability(vif_port) + self.network_api.bind_port(context, port_id, server) + except Exception as e: + raise exception.InterfaceAttachFailed(message=six.text_type(e)) + preserve_on_delete = True else: LOG.debug("Attaching network interface %(net_id) to server " "%(server)s", {'net_id': net_id, 'server': server}) vif_port = self.network_api.create_port(context, net_id, server.uuid) + preserve_on_delete = False try: - vif = self.network_api.bind_port(context, vif_port['id'], server) - vif_port = vif['port'] self.driver.plug_vif(server.node_uuid, vif_port['id']) nics_obj = objects.ServerNics(context) nic_dict = {'port_id': vif_port['id'], 'network_id': vif_port['network_id'], 'mac_address': vif_port['mac_address'], 'fixed_ips': vif_port['fixed_ips'], + 'preserve_on_delete': preserve_on_delete, 'server_uuid': server.uuid} nics_obj.objects.append(objects.ServerNic( context, **nic_dict)) @@ -614,7 +618,7 @@ class EngineManager(base_manager.BaseEngineManager): raise exception.InterfaceAttachFailed(message=six.text_type(e)) LOG.info('Attaching interface successfully') - def _detach_interface(self, context, server, port_id): + def _detach_interface(self, context, server, port_id, preserve=False): try: self.driver.unplug_vif(context, server, port_id) except exception.MoganException as e: @@ -624,7 +628,11 @@ class EngineManager(base_manager.BaseEngineManager): raise exception.InterfaceDetachFailed(server_uuid=server.uuid) else: try: - self.network_api.delete_port(context, port_id, server.uuid) + if preserve: + vif_port = self.network_api.show_port(context, port_id) + self.network_api.unbind_port(context, vif_port) + else: + self.network_api.delete_port(context, port_id, server.uuid) except Exception as e: raise exception.InterfaceDetachFailed(server_uuid=server.uuid) @@ -637,7 +645,12 @@ class EngineManager(base_manager.BaseEngineManager): def detach_interface(self, context, server, port_id): LOG.debug("Detaching interface %(port_id) from server %(server)s", {'port_id': port_id, 'server': server.uuid}) - self._detach_interface(context, server, port_id) + try: + db_nic = objects.ServerNic.get_by_port_id(context, port_id) + preserve = db_nic['preserve_on_delete'] + except exception.PortNotFound: + preserve = False + self._detach_interface(context, server, port_id, preserve) LOG.info('Interface was successfully detached') diff --git a/mogan/objects/server_nic.py b/mogan/objects/server_nic.py index 2954de4a..34cbb062 100644 --- a/mogan/objects/server_nic.py +++ b/mogan/objects/server_nic.py @@ -42,6 +42,7 @@ class ServerNic(base.MoganObject, object_base.VersionedObjectDictCompat): 'fixed_ips': object_fields.ListOfDictOfNullableStringsField( nullable=True), 'floating_ip': object_fields.StringField(nullable=True), + 'preserve_on_delete': object_fields.BooleanField(), } @staticmethod @@ -62,6 +63,10 @@ class ServerNic(base.MoganObject, object_base.VersionedObjectDictCompat): def delete_by_port_id(cls, context, port_id): cls.dbapi.server_nic_delete(context, port_id) + @classmethod + def get_by_port_id(cls, context, port_id): + return cls.dbapi.server_nic_get(context, port_id) + def save(self, context): updates = self.obj_get_changes() self.dbapi.server_nic_update_or_create( diff --git a/mogan/tests/unit/db/utils.py b/mogan/tests/unit/db/utils.py index 2cb16a7d..2e799f6d 100644 --- a/mogan/tests/unit/db/utils.py +++ b/mogan/tests/unit/db/utils.py @@ -37,6 +37,7 @@ def get_test_server(**kw): } ], 'floating_ip': '', + 'preserve_on_delete': False, }, ] return { diff --git a/mogan/tests/unit/objects/test_objects.py b/mogan/tests/unit/objects/test_objects.py index 337317ed..9daab2d0 100644 --- a/mogan/tests/unit/objects/test_objects.py +++ b/mogan/tests/unit/objects/test_objects.py @@ -387,7 +387,7 @@ expected_object_fingerprints = { 'ServerFaultList': '1.0-43e8aad0258652921f929934e9e048fd', 'Flavor': '1.0-9f7166aa387d89ec40cd699019d0c9a9', 'MyObj': '1.1-aad62eedc5a5cc8bcaf2982c285e753f', - 'ServerNic': '1.0-0494306157ef437802260ff8b51cf5cf', + 'ServerNic': '1.0-fb405af29a68a9a60a495962a11579cc', 'ServerNics': '1.0-33a2e1bb91ad4082f9f63429b77c1244', 'Quota': '1.0-c8caa082f4d726cb63fdc5943f7cd186', 'KeyPair': '1.0-1a1ea1f9b4d03503f5c13b52d1432fa9',