Merge "Fix multi-nic issue with nexus plugin"

This commit is contained in:
Jenkins 2015-01-15 10:48:40 +00:00 committed by Gerrit Code Review
commit 7cd59d1331
3 changed files with 305 additions and 26 deletions

View File

@ -1682,7 +1682,8 @@ class InstanceTests(helpers.TestCase):
def test_launch_instance_post(self,
disk_config=True,
config_drive=True,
test_with_profile=False):
test_with_profile=False,
test_with_multi_nics=False):
flavor = self.flavors.first()
image = self.images.first()
keypair = self.keypairs.first()
@ -1723,15 +1724,24 @@ class InstanceTests(helpers.TestCase):
if test_with_profile:
policy_profiles = self.policy_profiles.list()
policy_profile_id = self.policy_profiles.first().id
port = self.ports.first()
port_one = self.ports.first()
nics = [{"port-id": port_one.id}]
api.neutron.profile_list(
IsA(http.HttpRequest),
'policy').AndReturn(policy_profiles)
api.neutron.port_create(
IsA(http.HttpRequest),
self.networks.first().id,
policy_profile_id=policy_profile_id).AndReturn(port)
nics = [{"port-id": port.id}]
api.neutron.port_create(IsA(http.HttpRequest),
self.networks.first().id,
policy_profile_id=policy_profile_id) \
.AndReturn(port_one)
if test_with_multi_nics:
port_two = self.ports.get(name="port5")
nics = [{"port-id": port_one.id},
{"port-id": port_two.id}]
# Add a second port to test multiple nics
api.neutron.port_create(IsA(http.HttpRequest),
self.networks.get(name="net4")['id'],
policy_profile_id=policy_profile_id) \
.AndReturn(port_two)
api.nova.extension_supported('DiskConfig',
IsA(http.HttpRequest)) \
.AndReturn(disk_config)
@ -1793,6 +1803,9 @@ class InstanceTests(helpers.TestCase):
form_data['config_drive'] = True
if test_with_profile:
form_data['profile'] = self.policy_profiles.first().id
if test_with_multi_nics:
form_data['network'] = [self.networks.first().id,
self.networks.get(name="net4")['id']]
url = reverse('horizon:project:instances:launch')
res = self.client.post(url, form_data)
@ -1810,6 +1823,158 @@ class InstanceTests(helpers.TestCase):
def test_launch_instance_post_with_profile(self):
self.test_launch_instance_post(test_with_profile=True)
@helpers.update_settings(
OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'})
def test_launch_instance_post_with_profile_and_multi_nics(self):
self.test_launch_instance_post(test_with_profile=True,
test_with_multi_nics=True)
def _test_launch_instance_post_with_profile_and_port_error(
self,
test_with_multi_nics=False,
):
flavor = self.flavors.first()
image = self.images.first()
keypair = self.keypairs.first()
server = self.servers.first()
sec_group = self.security_groups.first()
avail_zone = self.availability_zones.first()
customization_script = 'user data'
quota_usages = self.quota_usages.first()
api.nova.extension_supported('BlockDeviceMappingV2Boot',
IsA(http.HttpRequest)) \
.AndReturn(True)
api.nova.flavor_list(IsA(http.HttpRequest)) \
.AndReturn(self.flavors.list())
api.nova.keypair_list(IsA(http.HttpRequest)) \
.AndReturn(self.keypairs.list())
api.network.security_group_list(IsA(http.HttpRequest)) \
.AndReturn(self.security_groups.list())
api.nova.availability_zone_list(IsA(http.HttpRequest)) \
.AndReturn(self.availability_zones.list())
api.glance.image_list_detailed(IsA(http.HttpRequest),
filters={'is_public': True,
'status': 'active'}) \
.AndReturn([self.images.list(), False, False])
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'property-owner_id': self.tenant.id,
'status': 'active'}) \
.AndReturn([[], False, False])
api.neutron.network_list(IsA(http.HttpRequest),
tenant_id=self.tenant.id,
shared=False) \
.AndReturn(self.networks.list()[:1])
api.neutron.network_list(IsA(http.HttpRequest),
shared=True) \
.AndReturn(self.networks.list()[1:])
policy_profiles = self.policy_profiles.list()
policy_profile_id = self.policy_profiles.first().id
port_one = self.ports.first()
api.neutron.profile_list(
IsA(http.HttpRequest),
'policy').AndReturn(policy_profiles)
if test_with_multi_nics:
api.neutron.port_create(IsA(http.HttpRequest),
self.networks.first().id,
policy_profile_id=policy_profile_id) \
.AndReturn(port_one)
# Add a second port which has the exception to test multiple nics
api.neutron.port_create(IsA(http.HttpRequest),
self.networks.get(name="net4")['id'],
policy_profile_id=policy_profile_id) \
.AndRaise(self.exceptions.neutron)
# Delete the first port
api.neutron.port_delete(IsA(http.HttpRequest),
port_one.id)
else:
api.neutron.port_create(IsA(http.HttpRequest),
self.networks.first().id,
policy_profile_id=policy_profile_id) \
.AndRaise(self.exceptions.neutron)
api.nova.extension_supported('DiskConfig',
IsA(http.HttpRequest)) \
.AndReturn(True)
api.nova.extension_supported('ConfigDrive',
IsA(http.HttpRequest)).AndReturn(True)
cinder.volume_list(IsA(http.HttpRequest),
search_opts=VOLUME_SEARCH_OPTS) \
.AndReturn([])
cinder.volume_snapshot_list(IsA(http.HttpRequest),
search_opts=SNAPSHOT_SEARCH_OPTS) \
.AndReturn([])
quotas.tenant_quota_usages(IsA(http.HttpRequest)) \
.AndReturn(quota_usages)
api.nova.flavor_list(IsA(http.HttpRequest)) \
.AndReturn(self.flavors.list())
self.mox.ReplayAll()
form_data = {'flavor': flavor.id,
'source_type': 'image_id',
'image_id': image.id,
'keypair': keypair.name,
'name': server.name,
'script_source': 'raw',
'script_data': customization_script,
'project_id': self.tenants.first().id,
'user_id': self.user.id,
'groups': sec_group.name,
'availability_zone': avail_zone.zoneName,
'volume_type': '',
'network': self.networks.first().id,
'count': 1,
'disk_config': 'AUTO',
'config_drive': True,
'profile': self.policy_profiles.first().id}
if test_with_multi_nics:
form_data['network'] = [self.networks.first().id,
self.networks.get(name="net4")['id']]
url = reverse('horizon:project:instances:launch')
res = self.client.post(url, form_data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, INDEX_URL)
@helpers.update_settings(
OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'})
@helpers.create_stubs({api.glance: ('image_list_detailed',),
api.neutron: ('network_list',
'profile_list',
'port_create',
'port_delete',),
api.nova: ('extension_supported',
'flavor_list',
'keypair_list',
'availability_zone_list',),
api.network: ('security_group_list',),
cinder: ('volume_list',
'volume_snapshot_list',),
quotas: ('tenant_quota_usages',)})
def test_launch_instance_post_with_profile_and_port_error(self):
self._test_launch_instance_post_with_profile_and_port_error()
@helpers.update_settings(
OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'})
@helpers.create_stubs({api.glance: ('image_list_detailed',),
api.neutron: ('network_list',
'profile_list',
'port_create',
'port_delete',),
api.nova: ('extension_supported',
'flavor_list',
'keypair_list',
'availability_zone_list',),
api.network: ('security_group_list',),
cinder: ('volume_list',
'volume_snapshot_list',),
quotas: ('tenant_quota_usages',)})
def test_lnch_inst_post_w_profile_and_multi_nics_w_port_error(self):
self._test_launch_instance_post_with_profile_and_port_error(
test_with_multi_nics=True)
@helpers.create_stubs({api.glance: ('image_list_detailed',),
api.neutron: ('network_list',
'profile_list',

View File

@ -899,26 +899,10 @@ class LaunchInstance(workflows.Workflow):
avail_zone = context.get('availability_zone', None)
# Create port with Network Name and Port Profile
# for the use with the plugin supporting port profiles.
# neutron port-create <Network name> --n1kv:profile <Port Profile ID>
# for net_id in context['network_id']:
# HACK for now use first network.
if api.neutron.is_port_profiles_supported():
net_id = context['network_id'][0]
LOG.debug("Horizon->Create Port with %(netid)s %(profile_id)s",
{'netid': net_id, 'profile_id': context['profile_id']})
port = None
try:
port = api.neutron.port_create(
request, net_id, policy_profile_id=context['profile_id'])
except Exception:
msg = (_('Port not created for profile-id (%s).') %
context['profile_id'])
exceptions.handle(request, msg)
if port and port.id:
nics = [{"port-id": port.id}]
nics = self.set_network_port_profiles(request,
context['network_id'],
context['profile_id'])
try:
api.nova.server_create(request,
@ -940,3 +924,40 @@ class LaunchInstance(workflows.Workflow):
except Exception:
exceptions.handle(request)
return False
def set_network_port_profiles(self, request, net_ids, profile_id):
# Create port with Network ID and Port Profile
# for the use with the plugin supporting port profiles.
nics = []
for net_id in net_ids:
try:
port = api.neutron.port_create(
request,
net_id,
policy_profile_id=profile_id,
)
except Exception as e:
msg = (_('Unable to create port for profile '
'"%(profile_id)s": %(reason)s'),
{'profile_id': profile_id,
'reason': e})
for nic in nics:
try:
port_id = nic['port-id']
api.neutron.port_delete(request, port_id)
except Exception:
msg = (msg +
_(' Also failed to delete port %s') % port_id)
redirect = self.success_url
exceptions.handle(request, msg, redirect=redirect)
if port:
nics.append({"port-id": port.id})
LOG.debug("Created Port %(portid)s with "
"network %(netid)s "
"policy profile %(profile_id)s",
{'portid': port.id,
'netid': net_id,
'profile_id': profile_id})
return nics

View File

@ -1052,3 +1052,96 @@ def data(TEST):
TEST.api_network_profile_binding.add(network_profile_binding_dict)
TEST.network_profile_binding.add(neutron.Profile(
network_profile_binding_dict))
# Adding a new network and new network and policy profile
# similar to the first to test launching an instance with multiple
# nics and multiple profiles.
# 4th network to use for testing instances with multiple-nics & profiles
network_dict = {'admin_state_up': True,
'id': '7aa23d91-ffff-abab-dcdc-3411ae767e8a',
'name': 'net4',
'status': 'ACTIVE',
'subnets': ['31be4a21-aadd-73da-6422-821ff249a4bb'],
'tenant_id': '1',
'router:external': False,
'shared': False}
subnet_dict = {'allocation_pools': [{'end': '11.10.0.254',
'start': '11.10.0.2'}],
'dns_nameservers': [],
'host_routes': [],
'cidr': '11.10.0.0/24',
'enable_dhcp': True,
'gateway_ip': '11.10.0.1',
'id': network_dict['subnets'][0],
'ip_version': 4,
'name': 'mysubnet4',
'network_id': network_dict['id'],
'tenant_id': network_dict['tenant_id']}
TEST.api_networks.add(network_dict)
TEST.api_subnets.add(subnet_dict)
network = copy.deepcopy(network_dict)
subnet = neutron.Subnet(subnet_dict)
network['subnets'] = [subnet]
TEST.networks.add(neutron.Network(network))
TEST.subnets.add(subnet)
# 5th network profile for network when using the cisco n1k plugin
# Network Profile applied on 4th network
net_profile_dict = {'name': 'net_profile_test5',
'segment_type': 'vlan',
'physical_network': 'phys5',
'segment_range': '400-450',
'id':
'00000000-5555-5555-5555-000000000000',
'project': TEST.networks.get(name="net4")['tenant_id']}
TEST.api_net_profiles.add(net_profile_dict)
TEST.net_profiles.add(neutron.Profile(net_profile_dict))
# 2nd policy profile for port when using the cisco n1k plugin
policy_profile_dict = {'name': 'policy_profile_test2',
'id':
'11111111-9999-9999-9999-111111111111'}
TEST.api_policy_profiles.add(policy_profile_dict)
TEST.policy_profiles.add(neutron.Profile(policy_profile_dict))
# network profile binding
network_profile_binding_dict = {'profile_id':
'00000000-5555-5555-5555-000000000000',
'tenant_id':
TEST.networks.get(name="net4")['tenant_id']
}
TEST.api_network_profile_binding.add(network_profile_binding_dict)
TEST.network_profile_binding.add(neutron.Profile(
network_profile_binding_dict))
# policy profile binding
policy_profile_binding_dict = {'profile_id':
'11111111-9999-9999-9999-111111111111',
'tenant_id':
TEST.networks.get(name="net4")['tenant_id']}
TEST.api_policy_profile_binding.add(policy_profile_binding_dict)
TEST.policy_profile_binding.add(neutron.Profile(
policy_profile_binding_dict))
# ports on 4th network
port_dict = {'admin_state_up': True,
'device_id': '9872faaa-b2b2-eeee-9911-21332eedaa77',
'device_owner': 'network:dhcp',
'fixed_ips': [{'ip_address': '11.10.0.3',
'subnet_id':
TEST.subnets.get(name="mysubnet4")['id']}],
'id': 'a21dcd22-6733-cccc-aa32-22adafaf16a2',
'mac_address': '78:22:ff:1a:ba:23',
'name': 'port5',
'network_id': TEST.networks.get(name="net4")['id'],
'status': 'ACTIVE',
'tenant_id': TEST.networks.get(name="net4")['tenant_id']}
TEST.api_ports.add(port_dict)
TEST.ports.add(neutron.Port(port_dict))