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
This commit is contained in:
Zhenguo Niu 2017-09-08 11:52:20 +08:00
parent ba2aeab9dd
commit 1c50ceed0b
9 changed files with 50 additions and 11 deletions

View File

@ -117,6 +117,13 @@ class Connection(object):
This delete a nic db entry. 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 # Servers Faults
@abc.abstractmethod @abc.abstractmethod
def server_fault_create(self, context, values): def server_fault_create(self, context, values):

View File

@ -102,6 +102,7 @@ def upgrade():
sa.Column('network_id', sa.String(length=36), nullable=True), sa.Column('network_id', sa.String(length=36), nullable=True),
sa.Column('floating_ip', sa.String(length=64), nullable=True), sa.Column('floating_ip', sa.String(length=64), nullable=True),
sa.Column('fixed_ips', sa.Text(), nullable=True), sa.Column('fixed_ips', sa.Text(), nullable=True),
sa.Column('preserve_on_delete', sa.Boolean(), nullable=True),
sa.PrimaryKeyConstraint('port_id'), sa.PrimaryKeyConstraint('port_id'),
sa.Index('server_nics_server_uuid_idx', 'server_uuid'), sa.Index('server_nics_server_uuid_idx', 'server_uuid'),
mysql_ENGINE='InnoDB', mysql_ENGINE='InnoDB',

View File

@ -344,6 +344,14 @@ class Connection(api.Connection):
if count != 1: if count != 1:
raise exception.PortNotFound(port_id=port_id) 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 @oslo_db_api.retry_on_deadlock
def server_nic_update_or_create(self, context, port_id, values): def server_nic_update_or_create(self, context, port_id, values):
with _session_for_write() as session: with _session_for_write() as session:

View File

@ -110,6 +110,7 @@ class ServerNic(Base):
network_id = Column(String(36), nullable=True) network_id = Column(String(36), nullable=True)
fixed_ips = Column(db_types.JsonEncodedList) fixed_ips = Column(db_types.JsonEncodedList)
floating_ip = Column(String(64), nullable=True) floating_ip = Column(String(64), nullable=True)
preserve_on_delete = Column(Boolean)
_server = orm.relationship( _server = orm.relationship(
Server, Server,
backref=orm.backref('server_nics', uselist=False), backref=orm.backref('server_nics', uselist=False),

View File

@ -154,6 +154,7 @@ class BuildNetworkTask(flow_utils.MoganTask):
if vif.get('net_id'): if vif.get('net_id'):
port = self.manager.network_api.create_port( port = self.manager.network_api.create_port(
context, vif['net_id'], server.uuid) context, vif['net_id'], server.uuid)
preserve_on_delete = False
elif vif.get('port_id'): elif vif.get('port_id'):
port = self.manager.network_api.show_port( port = self.manager.network_api.show_port(
context, vif.get('port_id')) context, vif.get('port_id'))
@ -161,11 +162,13 @@ class BuildNetworkTask(flow_utils.MoganTask):
self.manager.network_api.bind_port(context, self.manager.network_api.bind_port(context,
port['id'], port['id'],
server) server)
preserve_on_delete = True
nic_dict = {'port_id': port['id'], nic_dict = {'port_id': port['id'],
'network_id': port['network_id'], 'network_id': port['network_id'],
'mac_address': port['mac_address'], 'mac_address': port['mac_address'],
'fixed_ips': port['fixed_ips'], 'fixed_ips': port['fixed_ips'],
'preserve_on_delete': preserve_on_delete,
'server_uuid': server.uuid} 'server_uuid': server.uuid}
server_nic = objects.ServerNic(context, **nic_dict) server_nic = objects.ServerNic(context, **nic_dict)

View File

@ -289,9 +289,9 @@ class EngineManager(base_manager.BaseEngineManager):
server.save() server.save()
def destroy_networks(self, context, server): def destroy_networks(self, context, server):
ports = server.nics.get_port_ids() for nic in server.nics:
for port in ports: self._detach_interface(context, server, nic.port_id,
self._detach_interface(context, server, port) nic.preserve_on_delete)
def _rollback_servers_quota(self, context, number): def _rollback_servers_quota(self, context, number):
reserve_opts = {'servers': number} reserve_opts = {'servers': number}
@ -582,24 +582,28 @@ class EngineManager(base_manager.BaseEngineManager):
vif_port = self.network_api.show_port(context, port_id) vif_port = self.network_api.show_port(context, port_id)
except Exception: except Exception:
raise exception.PortNotFound(port_id=port_id) raise exception.PortNotFound(port_id=port_id)
try:
self.network_api.check_port_availability(vif_port) 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: else:
LOG.debug("Attaching network interface %(net_id) to server " LOG.debug("Attaching network interface %(net_id) to server "
"%(server)s", {'net_id': net_id, 'server': server}) "%(server)s", {'net_id': net_id, 'server': server})
vif_port = self.network_api.create_port(context, net_id, vif_port = self.network_api.create_port(context, net_id,
server.uuid) server.uuid)
preserve_on_delete = False
try: 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']) self.driver.plug_vif(server.node_uuid, vif_port['id'])
nics_obj = objects.ServerNics(context) nics_obj = objects.ServerNics(context)
nic_dict = {'port_id': vif_port['id'], nic_dict = {'port_id': vif_port['id'],
'network_id': vif_port['network_id'], 'network_id': vif_port['network_id'],
'mac_address': vif_port['mac_address'], 'mac_address': vif_port['mac_address'],
'fixed_ips': vif_port['fixed_ips'], 'fixed_ips': vif_port['fixed_ips'],
'preserve_on_delete': preserve_on_delete,
'server_uuid': server.uuid} 'server_uuid': server.uuid}
nics_obj.objects.append(objects.ServerNic( nics_obj.objects.append(objects.ServerNic(
context, **nic_dict)) context, **nic_dict))
@ -614,7 +618,7 @@ class EngineManager(base_manager.BaseEngineManager):
raise exception.InterfaceAttachFailed(message=six.text_type(e)) raise exception.InterfaceAttachFailed(message=six.text_type(e))
LOG.info('Attaching interface successfully') LOG.info('Attaching interface successfully')
def _detach_interface(self, context, server, port_id): def _detach_interface(self, context, server, port_id, preserve=False):
try: try:
self.driver.unplug_vif(context, server, port_id) self.driver.unplug_vif(context, server, port_id)
except exception.MoganException as e: except exception.MoganException as e:
@ -624,7 +628,11 @@ class EngineManager(base_manager.BaseEngineManager):
raise exception.InterfaceDetachFailed(server_uuid=server.uuid) raise exception.InterfaceDetachFailed(server_uuid=server.uuid)
else: else:
try: 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: except Exception as e:
raise exception.InterfaceDetachFailed(server_uuid=server.uuid) raise exception.InterfaceDetachFailed(server_uuid=server.uuid)
@ -637,7 +645,12 @@ class EngineManager(base_manager.BaseEngineManager):
def detach_interface(self, context, server, port_id): def detach_interface(self, context, server, port_id):
LOG.debug("Detaching interface %(port_id) from server %(server)s", LOG.debug("Detaching interface %(port_id) from server %(server)s",
{'port_id': port_id, 'server': server.uuid}) {'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') LOG.info('Interface was successfully detached')

View File

@ -42,6 +42,7 @@ class ServerNic(base.MoganObject, object_base.VersionedObjectDictCompat):
'fixed_ips': object_fields.ListOfDictOfNullableStringsField( 'fixed_ips': object_fields.ListOfDictOfNullableStringsField(
nullable=True), nullable=True),
'floating_ip': object_fields.StringField(nullable=True), 'floating_ip': object_fields.StringField(nullable=True),
'preserve_on_delete': object_fields.BooleanField(),
} }
@staticmethod @staticmethod
@ -62,6 +63,10 @@ class ServerNic(base.MoganObject, object_base.VersionedObjectDictCompat):
def delete_by_port_id(cls, context, port_id): def delete_by_port_id(cls, context, port_id):
cls.dbapi.server_nic_delete(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): def save(self, context):
updates = self.obj_get_changes() updates = self.obj_get_changes()
self.dbapi.server_nic_update_or_create( self.dbapi.server_nic_update_or_create(

View File

@ -37,6 +37,7 @@ def get_test_server(**kw):
} }
], ],
'floating_ip': '', 'floating_ip': '',
'preserve_on_delete': False,
}, ] }, ]
return { return {

View File

@ -387,7 +387,7 @@ expected_object_fingerprints = {
'ServerFaultList': '1.0-43e8aad0258652921f929934e9e048fd', 'ServerFaultList': '1.0-43e8aad0258652921f929934e9e048fd',
'Flavor': '1.0-9f7166aa387d89ec40cd699019d0c9a9', 'Flavor': '1.0-9f7166aa387d89ec40cd699019d0c9a9',
'MyObj': '1.1-aad62eedc5a5cc8bcaf2982c285e753f', 'MyObj': '1.1-aad62eedc5a5cc8bcaf2982c285e753f',
'ServerNic': '1.0-0494306157ef437802260ff8b51cf5cf', 'ServerNic': '1.0-fb405af29a68a9a60a495962a11579cc',
'ServerNics': '1.0-33a2e1bb91ad4082f9f63429b77c1244', 'ServerNics': '1.0-33a2e1bb91ad4082f9f63429b77c1244',
'Quota': '1.0-c8caa082f4d726cb63fdc5943f7cd186', 'Quota': '1.0-c8caa082f4d726cb63fdc5943f7cd186',
'KeyPair': '1.0-1a1ea1f9b4d03503f5c13b52d1432fa9', 'KeyPair': '1.0-1a1ea1f9b4d03503f5c13b52d1432fa9',