Add re-check logic when create network failed with conflict

Add re-check logic when create network faild with the Conflict Exception
whose status_code is 409, it's means another task of creating the same
network is happend and done. So there is no need to create it again, instead
we query if the network exists(by name). If we can not find the network,
then the exception raised.

Change-Id: I44a6909b3119be748d4445a0f560454c19687276
This commit is contained in:
joey5678
2015-01-12 16:41:24 +08:00
parent 8796babed2
commit 8fb4429a1e

View File

@@ -29,7 +29,6 @@ import base64
import contextlib import contextlib
import datetime import datetime
import functools import functools
import os
import socket import socket
import sys import sys
import time import time
@@ -87,21 +86,16 @@ from nova.openstack.common import strutils
from nova.openstack.common import timeutils from nova.openstack.common import timeutils
from nova import paths from nova import paths
from nova import rpc from nova import rpc
from nova import safe_utils
from nova.scheduler import rpcapi as scheduler_rpcapi from nova.scheduler import rpcapi as scheduler_rpcapi
from nova import utils from nova import utils
from nova.virt import block_device as driver_block_device from nova.virt import block_device as driver_block_device
from nova.virt import driver from nova.virt import driver
from nova.virt import event as virtevent from nova.virt import event as virtevent
from nova.virt import storage_users
from nova.virt import virtapi from nova.virt import virtapi
from nova import volume from nova import volume
from nova.volume import encryptors
#extra import #extra import
from nova.virt.libvirt import utils as libvirt_utils
from nova.network import neutronv2
from neutronclient.v2_0 import client as clientv20 from neutronclient.v2_0 import client as clientv20
from novaclient.exceptions import Unauthorized as Client_Unauthorized from neutronclient.common.exceptions import NeutronClientException
compute_opts = [ compute_opts = [
@@ -690,6 +684,11 @@ class ComputeManager(manager.Manager):
INSTANCE_UUID_LENGTH = 36 INSTANCE_UUID_LENGTH = 36
NEUTRON_UUID_LENGTH = 36 NEUTRON_UUID_LENGTH = 36
NAME_FIELD_MAX_LENGTH = 255 NAME_FIELD_MAX_LENGTH = 255
NAME_SPLIT_MARK_LENGTH = 1
CSG_INSTANCE_NAME_MAX_LEN = (NAME_FIELD_MAX_LENGTH - INSTANCE_UUID_LENGTH
- NAME_SPLIT_MARK_LENGTH)
CSG_NET_NAME_MAX_LEN = (NAME_FIELD_MAX_LENGTH - NEUTRON_UUID_LENGTH
- NAME_SPLIT_MARK_LENGTH)
def __init__(self, compute_driver=None, *args, **kwargs): def __init__(self, compute_driver=None, *args, **kwargs):
"""Load configuration options and connect to the hypervisor.""" """Load configuration options and connect to the hypervisor."""
@@ -808,7 +807,9 @@ class ComputeManager(manager.Manager):
if not csg_net_id: if not csg_net_id:
#todo(jd) Add exception log. #todo(jd) Add exception log.
continue continue
csg_net_name = ComputeManager._extract_nets_csg_name(csd_net['name'])
self._network_mapping[csg_net_id] = {'mapping_id': csd_net['id'], self._network_mapping[csg_net_id] = {'mapping_id': csd_net['id'],
'name': csg_net_name,
'subnets': []} 'subnets': []}
for subnet in csd_subnets['subnets']: for subnet in csd_subnets['subnets']:
network_id = subnet['network_id'] network_id = subnet['network_id']
@@ -849,8 +850,7 @@ class ComputeManager(manager.Manager):
@staticmethod @staticmethod
def _gen_csd_instance_name(name, instance): def _gen_csd_instance_name(name, instance):
max_len = (ComputeManager.NAME_FIELD_MAX_LENGTH max_len = ComputeManager.CSG_INSTANCE_NAME_MAX_LEN
- ComputeManager.NEUTRON_UUID_LENGTH -1)
save_name = name[:(max_len-len(name))] if max_len < len(name) else name save_name = name[:(max_len-len(name))] if max_len < len(name) else name
return save_name + '@' + instance['uuid'] return save_name + '@' + instance['uuid']
@@ -858,14 +858,21 @@ class ComputeManager(manager.Manager):
def _extract_nets_csg_uuid(neutron_obj_name): def _extract_nets_csg_uuid(neutron_obj_name):
uuid_len = ComputeManager.NEUTRON_UUID_LENGTH uuid_len = ComputeManager.NEUTRON_UUID_LENGTH
if (len(neutron_obj_name) > (uuid_len+1) if (len(neutron_obj_name) > (uuid_len+1)
and neutron_obj_name[-(uuid_len+1)] == '_'): and neutron_obj_name[-(uuid_len+1)] == '_'):
return neutron_obj_name[-uuid_len:] return neutron_obj_name[-uuid_len:]
return '' return ''
@staticmethod
def _extract_nets_csg_name(neutron_obj_name):
uuid_len = ComputeManager.NEUTRON_UUID_LENGTH
if (len(neutron_obj_name) > (uuid_len+1)
and neutron_obj_name[-(uuid_len+1)] == '_'):
return neutron_obj_name[:(len(neutron_obj_name)-uuid_len-1)]
return ''
@staticmethod @staticmethod
def _gen_csd_nets_name(csg_name, csg_uuid): def _gen_csd_nets_name(csg_name, csg_uuid):
max_len = (ComputeManager.NAME_FIELD_MAX_LENGTH max_len = ComputeManager.CSG_NET_NAME_MAX_LEN
- ComputeManager.NEUTRON_UUID_LENGTH -1)
save_name = (csg_name[:(max_len-len(csg_name))] save_name = (csg_name[:(max_len-len(csg_name))]
if max_len < len(csg_name) else csg_name) if max_len < len(csg_name) else csg_name)
return save_name + '_' + csg_uuid return save_name + '_' + csg_uuid
@@ -1356,27 +1363,60 @@ class ComputeManager(manager.Manager):
LOG.debug(_('Physical network not exist.' LOG.debug(_('Physical network not exist.'
'need to create,logicalNetId:%s'), 'need to create,logicalNetId:%s'),
net_id) net_id)
self._network_mapping[net_id] = {'mapping_id': '', 'subnets': []} self._network_mapping[net_id] = {'mapping_id': '',
'name': '',
'subnets': []}
search_opts = {'id': [net_id]} search_opts = {'id': [net_id]}
logical_nets = neutron_client.list_networks(**search_opts).get('networks', []) logical_nets = neutron_client.list_networks(**search_opts).get('networks', [])
# create cascaded network and add the mapping relationship. # create cascaded network and add the mapping relationship.
req_network = self._get_network_req(logical_nets[0], instance) req_network = self._get_network_req(logical_nets[0], instance)
csd_net_name = ComputeManager._gen_csd_nets_name(net_name, net_id) csd_net_name = ComputeManager._gen_csd_nets_name(net_name, net_id)
req_network['network']['name'] = csd_net_name req_network['network']['name'] = csd_net_name
net_response = csd_neutron_client.create_network(req_network) try:
net_response = csd_neutron_client.create_network(req_network)
csd_net_id = net_response['network']['id']
except NeutronClientException as ne:
if ne.status_code == 409:
_search_opts = {'name': csd_net_name}
_nets = (csd_neutron_client.list_networks(**_search_opts)
.get('networks', []))
if _nets:
net_response = _nets[0]
csd_net_id = net_response['id']
else:
LOG.exception(_('Create cascaded network conflict, but '
'still can not find the cascaded network:'
'%s'), csd_net_name)
raise
except Exception:
LOG.exception(_('Create cascaded network failed, with the '
'req_network: %s'), req_network)
raise
cascaded_network_list.append(net_response['network']['id']) cascaded_network_list.append(csd_net_id)
LOG.debug(_('Finish to create Physical network,' LOG.debug(_('Finish to create Physical network,'
'net_response %s'), req_network) 'net_response %s'), req_network)
csd_net_id = net_response['network']['id']
#Actually, only one subnet item in net_obj #Actually, only one subnet item in net_obj
cidr_list = [sn['cidr'] for sn in net_obj['network']['subnets']] cidr_list = [sn['cidr'] for sn in net_obj['network']['subnets']]
self._network_mapping[net_id]['mapping_id'] = csd_net_id self._network_mapping[net_id]['mapping_id'] = csd_net_id
self._network_mapping[net_id]['name'] = net_name
else: else:
csd_net_id = self._network_mapping[net_id]['mapping_id']
old_csg_net_name = self._network_mapping[net_id]['name']
#Need Check if network name has been changed.
max_len = ComputeManager.CSG_NET_NAME_MAX_LEN
csg_net_name = (net_name if len(net_name) <= max_len
else net_name[:max_len])
if old_csg_net_name != csg_net_name:
csd_net_name = ComputeManager._gen_csd_nets_name(net_name, net_id)
update_req = {'network': {'name': csd_net_name, }}
csd_neutron_client.update_network(csd_net_id, update_req)
self._network_mapping[net_id]['name'] = net_name
#Can not find subnet id in "net_obj['network']['subnets']", so #Can not find subnet id in "net_obj['network']['subnets']", so
#we have to compare the cidr. #we have to compare the cidr.
csd_net_id = self._network_mapping[net_id]['mapping_id']
mapping_subnets = self._network_mapping[net_id]['subnets'] mapping_subnets = self._network_mapping[net_id]['subnets']
cidr_list = [sn['cidr'] for sn in net_obj['network']['subnets'] cidr_list = [sn['cidr'] for sn in net_obj['network']['subnets']
if sn['cidr'] not in [m_sn['cidr'] if sn['cidr'] not in [m_sn['cidr']