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
1 changed files with 57 additions and 17 deletions

View File

@ -29,7 +29,6 @@ import base64
import contextlib
import datetime
import functools
import os
import socket
import sys
import time
@ -87,21 +86,16 @@ from nova.openstack.common import strutils
from nova.openstack.common import timeutils
from nova import paths
from nova import rpc
from nova import safe_utils
from nova.scheduler import rpcapi as scheduler_rpcapi
from nova import utils
from nova.virt import block_device as driver_block_device
from nova.virt import driver
from nova.virt import event as virtevent
from nova.virt import storage_users
from nova.virt import virtapi
from nova import volume
from nova.volume import encryptors
#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 novaclient.exceptions import Unauthorized as Client_Unauthorized
from neutronclient.common.exceptions import NeutronClientException
compute_opts = [
@ -690,6 +684,11 @@ class ComputeManager(manager.Manager):
INSTANCE_UUID_LENGTH = 36
NEUTRON_UUID_LENGTH = 36
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):
"""Load configuration options and connect to the hypervisor."""
@ -808,7 +807,9 @@ class ComputeManager(manager.Manager):
if not csg_net_id:
#todo(jd) Add exception log.
continue
csg_net_name = ComputeManager._extract_nets_csg_name(csd_net['name'])
self._network_mapping[csg_net_id] = {'mapping_id': csd_net['id'],
'name': csg_net_name,
'subnets': []}
for subnet in csd_subnets['subnets']:
network_id = subnet['network_id']
@ -849,8 +850,7 @@ class ComputeManager(manager.Manager):
@staticmethod
def _gen_csd_instance_name(name, instance):
max_len = (ComputeManager.NAME_FIELD_MAX_LENGTH
- ComputeManager.NEUTRON_UUID_LENGTH -1)
max_len = ComputeManager.CSG_INSTANCE_NAME_MAX_LEN
save_name = name[:(max_len-len(name))] if max_len < len(name) else name
return save_name + '@' + instance['uuid']
@ -858,14 +858,21 @@ class ComputeManager(manager.Manager):
def _extract_nets_csg_uuid(neutron_obj_name):
uuid_len = ComputeManager.NEUTRON_UUID_LENGTH
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 ''
@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
def _gen_csd_nets_name(csg_name, csg_uuid):
max_len = (ComputeManager.NAME_FIELD_MAX_LENGTH
- ComputeManager.NEUTRON_UUID_LENGTH -1)
max_len = ComputeManager.CSG_NET_NAME_MAX_LEN
save_name = (csg_name[:(max_len-len(csg_name))]
if max_len < len(csg_name) else csg_name)
return save_name + '_' + csg_uuid
@ -1356,27 +1363,60 @@ class ComputeManager(manager.Manager):
LOG.debug(_('Physical network not exist.'
'need to create,logicalNetId:%s'),
net_id)
self._network_mapping[net_id] = {'mapping_id': '', 'subnets': []}
self._network_mapping[net_id] = {'mapping_id': '',
'name': '',
'subnets': []}
search_opts = {'id': [net_id]}
logical_nets = neutron_client.list_networks(**search_opts).get('networks', [])
# create cascaded network and add the mapping relationship.
req_network = self._get_network_req(logical_nets[0], instance)
csd_net_name = ComputeManager._gen_csd_nets_name(net_name, net_id)
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,'
'net_response %s'), req_network)
csd_net_id = net_response['network']['id']
#Actually, only one subnet item in net_obj
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]['name'] = net_name
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
#we have to compare the cidr.
csd_net_id = self._network_mapping[net_id]['mapping_id']
mapping_subnets = self._network_mapping[net_id]['subnets']
cidr_list = [sn['cidr'] for sn in net_obj['network']['subnets']
if sn['cidr'] not in [m_sn['cidr']