Merge "Fix multi-nic issue with nexus plugin"
This commit is contained in:
commit
7cd59d1331
|
@ -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',
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue