TrunkPort, Horizon workflow: launch instance
Ethernet trunks (network interfaces having a vlan tag) cannot be used as a boot interface. This is a DHCP/PXE limitation. So instead the interface without the vlan tag can be used. In neutron's nomenclature they are the trunk parents. It is also an OpenStack limitation. Subports should not be passed to 'openstack server create --nic ...'. But if you do, there's no clear error message about it. Please see Armando's analysis here why: https://bugs.launchpad.net/neutron/+bug/1636485/comments/9 The server part of this patch signals port kind (i.e. plain, trunkparent, trunksubport) so the launch widget can easily filter out trunksubports, what are not suitable for boot interface. Change-Id: Ie3a6710eeffefcb472c569898d0f1f1554e599f7 Partially-Implements: blueprint neutron-trunk-ui Signed-off-by: Ferenc Cserepkei <ferenc.cserepkei@ericsson.com>
This commit is contained in:
parent
7a2e9aaac6
commit
748d9860bb
openstack_dashboard
api
dashboards/project
instances
static/dashboard/project/workflow/launch-instance
test
@ -148,6 +148,34 @@ class Port(NeutronAPIDictWrapper):
|
||||
super(Port, self).__init__(apidict)
|
||||
|
||||
|
||||
class PortTrunkParent(Port):
|
||||
"""Neutron ports that are trunk parents.
|
||||
|
||||
There's no need to add extra attributes for a trunk parent, because it
|
||||
already has 'trunk_details'. See also class PortTrunkSubport.
|
||||
"""
|
||||
|
||||
|
||||
class PortTrunkSubport(Port):
|
||||
"""Neutron ports that are trunk subports.
|
||||
|
||||
The Neutron API expresses port subtyping information in a surprisingly
|
||||
complex way. When you see a port with attribute 'trunk_details' you know
|
||||
it's a trunk parent. But when you see a port without the 'trunk_details'
|
||||
attribute you can't tell if it's a trunk subport or a regular one without
|
||||
looking beyond the port's attributes. You must go and check if trunks
|
||||
(and/or trunk_details of trunk parent ports) refer to this port.
|
||||
|
||||
Since this behavior is awfully complex we hide this from the rest of
|
||||
horizon by introducing types PortTrunkParent and PortTrunkSubport.
|
||||
"""
|
||||
|
||||
def __init__(self, apidict, trunk_subport_info):
|
||||
for field in ['trunk_id', 'segmentation_type', 'segmentation_id']:
|
||||
apidict[field] = trunk_subport_info[field]
|
||||
super(PortTrunkSubport, self).__init__(apidict)
|
||||
|
||||
|
||||
class PortAllowedAddressPair(NeutronAPIDictWrapper):
|
||||
"""Wrapper for neutron port allowed address pairs."""
|
||||
|
||||
@ -1066,6 +1094,45 @@ def port_list(request, **params):
|
||||
return [Port(p) for p in ports]
|
||||
|
||||
|
||||
@profiler.trace
|
||||
@memoized
|
||||
def port_list_with_trunk_types(request, **params):
|
||||
"""List neutron Ports for this tenant with possible TrunkPort indicated
|
||||
|
||||
:param request: request context
|
||||
|
||||
NOTE Performing two API calls is not atomic, but this is not worse
|
||||
than the original idea when we call port_list repeatedly for
|
||||
each network to perform identification run-time. We should
|
||||
handle the inconsistencies caused by non-atomic API requests
|
||||
gracefully.
|
||||
"""
|
||||
LOG.debug("port_list_with_trunk_types(): params=%s", params)
|
||||
ports = neutronclient(request).list_ports(**params)['ports']
|
||||
trunk_filters = {}
|
||||
if 'tenant_id' in params:
|
||||
trunk_filters['tenant_id'] = params['tenant_id']
|
||||
trunks = neutronclient(request).list_trunks(**trunk_filters)['trunks']
|
||||
parent_ports = set([t['port_id'] for t in trunks])
|
||||
# Create a dict map for child ports (port ID to trunk info)
|
||||
child_ports = dict([(s['port_id'],
|
||||
{'trunk_id': t['id'],
|
||||
'segmentation_type': s['segmentation_type'],
|
||||
'segmentation_id': s['segmentation_id']})
|
||||
for t in trunks
|
||||
for s in t['sub_ports']])
|
||||
|
||||
def _get_port_info(port):
|
||||
if port['id'] in parent_ports:
|
||||
return PortTrunkParent(port)
|
||||
elif port['id'] in child_ports:
|
||||
return PortTrunkSubport(port, child_ports[port['id']])
|
||||
else:
|
||||
return Port(port)
|
||||
|
||||
return [_get_port_info(p) for p in ports]
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def port_get(request, port_id, **params):
|
||||
LOG.debug("port_get(): portid=%(port_id)s, params=%(params)s",
|
||||
|
@ -133,8 +133,9 @@ class Ports(generic.View):
|
||||
"""
|
||||
# see
|
||||
# https://github.com/openstack/neutron/blob/master/neutron/api/v2/attributes.py
|
||||
result = api.neutron.port_list(request, **request.GET.dict())
|
||||
return{'items': [n.to_dict() for n in result]}
|
||||
result = api.neutron.port_list_with_trunk_types(request,
|
||||
**request.GET.dict())
|
||||
return {'items': [n.to_dict() for n in result]}
|
||||
|
||||
|
||||
@urls.register
|
||||
|
@ -91,8 +91,9 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
shared=True) \
|
||||
.AndReturn(self.networks.list()[1:])
|
||||
for net in self.networks.list():
|
||||
api.neutron.port_list(IsA(http.HttpRequest),
|
||||
network_id=net.id) \
|
||||
api.neutron.port_list_with_trunk_types(IsA(http.HttpRequest),
|
||||
network_id=net.id,
|
||||
tenant_id=self.tenant.id) \
|
||||
.AndReturn(self.ports.list())
|
||||
|
||||
def _mock_nova_lists(self):
|
||||
@ -1596,7 +1597,7 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
cinder: ('volume_snapshot_list',
|
||||
'volume_list',),
|
||||
api.neutron: ('network_list',
|
||||
'port_list',
|
||||
'port_list_with_trunk_types',
|
||||
'security_group_list',),
|
||||
api.glance: ('image_list_detailed',),
|
||||
quotas: ('tenant_limit_usages',)})
|
||||
@ -1642,8 +1643,9 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
shared=True) \
|
||||
.AndReturn(self.networks.list()[1:])
|
||||
for net in self.networks.list():
|
||||
api.neutron.port_list(IsA(http.HttpRequest),
|
||||
network_id=net.id) \
|
||||
api.neutron.port_list_with_trunk_types(IsA(http.HttpRequest),
|
||||
network_id=net.id,
|
||||
tenant_id=self.tenant.id) \
|
||||
.AndReturn(self.ports.list())
|
||||
|
||||
api.nova.extension_supported('DiskConfig',
|
||||
@ -1846,7 +1848,7 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
cinder: ('volume_snapshot_list',
|
||||
'volume_list',),
|
||||
api.neutron: ('network_list',
|
||||
'port_list',
|
||||
'port_list_with_trunk_types',
|
||||
'security_group_list',),
|
||||
api.glance: ('image_list_detailed',),
|
||||
quotas: ('tenant_limit_usages',)})
|
||||
@ -1888,8 +1890,9 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
shared=True) \
|
||||
.AndReturn(self.networks.list()[1:])
|
||||
for net in self.networks.list():
|
||||
api.neutron.port_list(IsA(http.HttpRequest),
|
||||
network_id=net.id) \
|
||||
api.neutron.port_list_with_trunk_types(IsA(http.HttpRequest),
|
||||
network_id=net.id,
|
||||
tenant_id=self.tenant.id) \
|
||||
.AndReturn(self.ports.list())
|
||||
api.nova.extension_supported('DiskConfig',
|
||||
IsA(http.HttpRequest)) \
|
||||
@ -1936,7 +1939,7 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
@helpers.create_stubs({api.glance: ('image_list_detailed',),
|
||||
api.neutron: ('network_list',
|
||||
'port_create',
|
||||
'port_list',
|
||||
'port_list_with_trunk_types',
|
||||
'security_group_list',),
|
||||
api.nova: ('extension_supported',
|
||||
'is_feature_available',
|
||||
@ -2050,7 +2053,7 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
@helpers.create_stubs({api.glance: ('image_list_detailed',),
|
||||
api.neutron: ('network_list',
|
||||
'port_create',
|
||||
'port_list',
|
||||
'port_list_with_trunk_types',
|
||||
'security_group_list',),
|
||||
api.nova: ('extension_supported',
|
||||
'is_feature_available',
|
||||
@ -2174,7 +2177,7 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
@helpers.create_stubs({api.glance: ('image_list_detailed',),
|
||||
api.neutron: ('network_list',
|
||||
'port_create',
|
||||
'port_list',
|
||||
'port_list_with_trunk_types',
|
||||
'security_group_list',),
|
||||
api.nova: ('server_create',
|
||||
'extension_supported',
|
||||
@ -2277,7 +2280,7 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
|
||||
@helpers.create_stubs({api.glance: ('image_list_detailed',),
|
||||
api.neutron: ('network_list',
|
||||
'port_list',
|
||||
'port_list_with_trunk_types',
|
||||
'security_group_list',),
|
||||
api.nova: ('extension_supported',
|
||||
'is_feature_available',
|
||||
@ -2356,7 +2359,7 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
api.glance: ('image_list_detailed',),
|
||||
api.neutron: ('network_list',
|
||||
'port_create',
|
||||
'port_list',
|
||||
'port_list_with_trunk_types',
|
||||
'security_group_list',),
|
||||
api.nova: ('extension_supported',
|
||||
'is_feature_available',
|
||||
@ -2484,7 +2487,7 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
api.glance: ('image_list_detailed',),
|
||||
api.neutron: ('network_list',
|
||||
'port_create',
|
||||
'port_list',
|
||||
'port_list_with_trunk_types',
|
||||
'security_group_list',),
|
||||
api.nova: ('extension_supported',
|
||||
'is_feature_available',
|
||||
@ -2555,7 +2558,7 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
|
||||
@helpers.create_stubs({api.glance: ('image_list_detailed',),
|
||||
api.neutron: ('network_list',
|
||||
'port_list',
|
||||
'port_list_with_trunk_types',
|
||||
'security_group_list',),
|
||||
cinder: ('volume_list',
|
||||
'volume_snapshot_list',),
|
||||
@ -2614,7 +2617,7 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
api.neutron: ('network_list',
|
||||
'port_create',
|
||||
'port_delete',
|
||||
'port_list',
|
||||
'port_list_with_trunk_types',
|
||||
'security_group_list',),
|
||||
api.nova: ('extension_supported',
|
||||
'is_feature_available',
|
||||
@ -2724,7 +2727,7 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
|
||||
@helpers.create_stubs({api.glance: ('image_list_detailed',),
|
||||
api.neutron: ('network_list',
|
||||
'port_list',
|
||||
'port_list_with_trunk_types',
|
||||
'security_group_list',),
|
||||
api.nova: ('extension_supported',
|
||||
'is_feature_available',
|
||||
@ -2805,7 +2808,7 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
|
||||
@helpers.create_stubs({api.glance: ('image_list_detailed',),
|
||||
api.neutron: ('network_list',
|
||||
'port_list',
|
||||
'port_list_with_trunk_types',
|
||||
'security_group_list',),
|
||||
api.nova: ('extension_supported',
|
||||
'is_feature_available',
|
||||
@ -2913,7 +2916,7 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
|
||||
@helpers.create_stubs({api.glance: ('image_list_detailed',),
|
||||
api.neutron: ('network_list',
|
||||
'port_list',
|
||||
'port_list_with_trunk_types',
|
||||
'security_group_list',),
|
||||
api.nova: ('extension_supported',
|
||||
'is_feature_available',
|
||||
@ -3022,7 +3025,7 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
|
||||
@helpers.create_stubs({api.glance: ('image_list_detailed',),
|
||||
api.neutron: ('network_list',
|
||||
'port_list',
|
||||
'port_list_with_trunk_types',
|
||||
'security_group_list',),
|
||||
api.nova: ('extension_supported',
|
||||
'is_feature_available',
|
||||
@ -3081,8 +3084,9 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
shared=True) \
|
||||
.AndReturn(self.networks.list()[1:])
|
||||
for net in self.networks.list():
|
||||
api.neutron.port_list(IsA(http.HttpRequest),
|
||||
network_id=net.id) \
|
||||
api.neutron.port_list_with_trunk_types(IsA(http.HttpRequest),
|
||||
network_id=net.id,
|
||||
tenant_id=self.tenant.id) \
|
||||
.AndReturn(self.ports.list())
|
||||
api.nova.extension_supported(
|
||||
'DiskConfig', IsA(http.HttpRequest)).AndReturn(True)
|
||||
@ -3168,7 +3172,7 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
|
||||
@helpers.create_stubs({api.glance: ('image_list_detailed',),
|
||||
api.neutron: ('network_list',
|
||||
'port_list',
|
||||
'port_list_with_trunk_types',
|
||||
'security_group_list',),
|
||||
api.nova: ('extension_supported',
|
||||
'is_feature_available',
|
||||
@ -3383,7 +3387,7 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
|
||||
@helpers.create_stubs({api.glance: ('image_list_detailed',),
|
||||
api.neutron: ('network_list',
|
||||
'port_list',
|
||||
'port_list_with_trunk_types',
|
||||
'security_group_list',),
|
||||
api.nova: ('extension_supported',
|
||||
'is_feature_available',
|
||||
@ -3536,7 +3540,7 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
|
||||
cinder: ('volume_snapshot_list',
|
||||
'volume_list',),
|
||||
api.neutron: ('network_list',
|
||||
'port_list',
|
||||
'port_list_with_trunk_types',
|
||||
'security_group_list',),
|
||||
api.glance: ('image_list_detailed',),
|
||||
quotas: ('tenant_limit_usages',)})
|
||||
|
@ -190,9 +190,11 @@ def port_field_data(request):
|
||||
for network in network_list:
|
||||
ports.extend(
|
||||
[(port.id, add_more_info_port_name(port))
|
||||
for port in api.neutron.port_list(request,
|
||||
network_id=network.id)
|
||||
if port.device_owner == ''])
|
||||
for port in api.neutron.port_list_with_trunk_types(
|
||||
request, network_id=network.id,
|
||||
tenant_id=request.user.tenant_id)
|
||||
if (not port.device_owner and
|
||||
not isinstance(port, api.neutron.PortTrunkSubport))])
|
||||
ports.sort(key=lambda obj: obj[1])
|
||||
return ports
|
||||
|
||||
|
@ -514,7 +514,9 @@
|
||||
if (port.device_owner === "" && port.admin_state === "UP") {
|
||||
port.subnet_names = getPortSubnets(port, network.subnets);
|
||||
port.network_name = network.name;
|
||||
ports.push(port);
|
||||
if (!port.hasOwnProperty("trunk_id")) {
|
||||
ports.push(port);
|
||||
}
|
||||
}
|
||||
});
|
||||
push.apply(model.ports, ports);
|
||||
|
@ -582,6 +582,28 @@
|
||||
expect(model.newInstanceSpec.networks).toEqual(networks);
|
||||
});
|
||||
|
||||
it('getPorts at launch should not return child port', function () {
|
||||
var ports = [ { id: 'parent',
|
||||
trunk_details: { trunk_id: 'trunk1',
|
||||
sub_ports: [ { port_id: 'child' } ] } },
|
||||
{ id: 'child' },
|
||||
{ id : 'plain' } ];
|
||||
var networks = [ { id: 'net-1', subnets: [ { id: 'subnet1' } ] } ];
|
||||
spyOn(neutronApi, 'getNetworks').and.callFake(function () {
|
||||
var deferred = $q.defer();
|
||||
deferred.resolve({ data: { items: networks } });
|
||||
return deferred.promise;
|
||||
});
|
||||
spyOn(neutronApi, 'getPorts').and.callFake(function () {
|
||||
var deferred = $q.defer();
|
||||
deferred.resolve({ data: { items: ports } });
|
||||
return deferred.promise;
|
||||
});
|
||||
neutronEnabled = true;
|
||||
model.initialize(true);
|
||||
scope.$apply();
|
||||
});
|
||||
|
||||
it('should have the proper entries in allowedBootSources', function() {
|
||||
model.initialize(true);
|
||||
scope.$apply();
|
||||
|
@ -155,10 +155,10 @@ class NeutronPortsTestCase(test.TestCase):
|
||||
params = django_request.QueryDict('network_id=%s' %
|
||||
self._networks[0].id)
|
||||
request = self.mock_rest_request(GET=params)
|
||||
client.port_list.return_value = [self._ports[0]]
|
||||
client.port_list_with_trunk_types.return_value = [self._ports[0]]
|
||||
response = neutron.Ports().get(request)
|
||||
self.assertStatusCode(response, 200)
|
||||
client.port_list.assert_called_once_with(
|
||||
client.port_list_with_trunk_types.assert_called_once_with(
|
||||
request, network_id=TEST.api_networks.first().get("id"))
|
||||
|
||||
|
||||
|
@ -389,6 +389,39 @@ class NeutronApiTests(test.APITestCase):
|
||||
for p in ret_val:
|
||||
self.assertIsInstance(p, api.neutron.Port)
|
||||
|
||||
def test_port_list_with_trunk_types(self):
|
||||
ports = self.api_tp_ports.list()
|
||||
trunks = self.api_tp_trunks.list()
|
||||
|
||||
neutronclient = self.stub_neutronclient()
|
||||
neutronclient.list_ports().AndReturn({'ports': ports})
|
||||
neutronclient.list_trunks().AndReturn({'trunks': trunks})
|
||||
self.mox.ReplayAll()
|
||||
|
||||
expected_parent_port_ids = set()
|
||||
expected_subport_ids = set()
|
||||
for trunk in trunks:
|
||||
expected_parent_port_ids.add(trunk['port_id'])
|
||||
expected_subport_ids |= set([p['port_id'] for p
|
||||
in trunk['sub_ports']])
|
||||
expected_normal_port_ids = ({p['id'] for p in ports}
|
||||
- expected_parent_port_ids
|
||||
- expected_subport_ids)
|
||||
|
||||
ret_val = api.neutron.port_list_with_trunk_types(self.request)
|
||||
|
||||
self.assertEqual(len(ports), len(ret_val))
|
||||
|
||||
parent_port_ids = {p.id for p in ret_val
|
||||
if isinstance(p, api.neutron.PortTrunkParent)}
|
||||
subport_ids = {p.id for p in ret_val
|
||||
if isinstance(p, api.neutron.PortTrunkSubport)}
|
||||
normal_port_ids = ({p.id for p in ret_val}
|
||||
- parent_port_ids - subport_ids)
|
||||
self.assertEqual(expected_parent_port_ids, parent_port_ids)
|
||||
self.assertEqual(expected_subport_ids, subport_ids)
|
||||
self.assertEqual(expected_normal_port_ids, normal_port_ids)
|
||||
|
||||
def test_port_get(self):
|
||||
port = {'port': self.api_ports.first()}
|
||||
port_id = self.api_ports.first()['id']
|
||||
|
@ -45,6 +45,7 @@ def data(TEST):
|
||||
TEST.neutron_quota_usages = utils.TestDataContainer()
|
||||
TEST.ip_availability = utils.TestDataContainer()
|
||||
TEST.qos_policies = utils.TestDataContainer()
|
||||
TEST.tp_ports = utils.TestDataContainer()
|
||||
|
||||
# Data return by neutronclient.
|
||||
TEST.api_agents = utils.TestDataContainer()
|
||||
@ -65,6 +66,8 @@ def data(TEST):
|
||||
TEST.api_extensions = utils.TestDataContainer()
|
||||
TEST.api_ip_availability = utils.TestDataContainer()
|
||||
TEST.api_qos_policies = utils.TestDataContainer()
|
||||
TEST.api_tp_trunks = utils.TestDataContainer()
|
||||
TEST.api_tp_ports = utils.TestDataContainer()
|
||||
|
||||
# 1st network.
|
||||
network_dict = {'admin_state_up': True,
|
||||
@ -709,3 +712,170 @@ def data(TEST):
|
||||
'tenant_id': '1'}
|
||||
TEST.api_qos_policies.add(policy_dict1)
|
||||
TEST.qos_policies.add(neutron.QoSPolicy(policy_dict1))
|
||||
|
||||
# TRUNKPORT
|
||||
#
|
||||
# The test setup was created by the following command sequence:
|
||||
# openstack network create tst
|
||||
# openstack subnet create tstsub --network tst\
|
||||
# --subnet-range 10.10.16.128/26
|
||||
# openstack network create tstalt
|
||||
# openstack subnet create tstaltsub --network tstalt\
|
||||
# --subnet-range 10.10.17.128/26
|
||||
# openstack port create --network tst plain
|
||||
# openstack port create --network tst parent
|
||||
# openstack port create --network tst child1
|
||||
# openstack port create --network tstalt child2
|
||||
# openstack network trunk create --parent-port parent trunk
|
||||
# openstack network trunk set\
|
||||
# --subport port=child1,segmentation-type=vlan,segmentation-id=100 trunk
|
||||
# openstack network trunk set\
|
||||
# --subport port=child2,segmentation-type=vlan,segmentation-id=200 trunk
|
||||
# ids/uuids are captured from a live setup.
|
||||
|
||||
# This collection holds the test setup.
|
||||
tdata = {'tenant_id': '19c9123a944644cb9e923497a018d0b7',
|
||||
'trunk_id': '920625a3-13de-46b4-b6c9-8b35f29b3cfe',
|
||||
'security_group': '3fd8c007-9093-4aa3-b475-a0c178d4e1e4',
|
||||
'tag_1': 100,
|
||||
'tag_2': 200,
|
||||
'net': {'tst_id': '5a340332-cc92-42aa-8980-15f47c0d0f3d',
|
||||
'tstalt_id': '0fb41ffd-3933-4da4-8a83-025d328aedf3'},
|
||||
'subnet': {'tst_id': '0b883baf-5a21-4605-ab56-229a24ec585b',
|
||||
'tstalt_id': '0e184cf2-97dc-4738-b4b3-1871faf5d685'},
|
||||
'child1': {'id': '9c151ffb-d7a6-4f15-8eae-d0950999fdfe',
|
||||
'ip': '10.10.16.140',
|
||||
'mac': 'fa:16:3e:22:63:6f',
|
||||
'device_id': '279989f7-54bb-41d9-ba42-0d61f12fda61'},
|
||||
'child2': {'id': 'cedb145f-c163-4630-98a3-e1990744bdef',
|
||||
'ip': '10.10.17.137',
|
||||
'mac': 'fa:16:3e:0d:ca:eb',
|
||||
'device_id': '9872faaa-b2b2-eeee-9911-21332eedaa77'},
|
||||
'parent': {'id': '5b27429d-048b-40fa-88f9-8e2c4ff7d28b',
|
||||
'ip': '10.10.16.141',
|
||||
'mac': 'fa:16:3e:ab:a8:22',
|
||||
'device_id': 'af75c8e5-a1cc-4567-8d04-44fcd6922890'},
|
||||
'plain': {'id': 'bc04da56-d7fc-461e-b95d-a2c66e77ad9a',
|
||||
'ip': '10.10.16.135',
|
||||
'mac': 'fa:16:3e:9c:d5:7f',
|
||||
'device_id': '7180cede-bcd8-4334-b19f-f7ef2f331f53'}}
|
||||
|
||||
# network tst
|
||||
|
||||
# trunk
|
||||
tp_trunk_dict = {
|
||||
'status': 'UP',
|
||||
'sub_ports': [{'segmentation_type': 'vlan',
|
||||
'segmentation_id': tdata['tag_1'],
|
||||
'port_id': tdata['child1']['id']},
|
||||
{'segmentation_type': u'vlan',
|
||||
'segmentation_id': tdata['tag_2'],
|
||||
'port_id': tdata['child2']['id']}],
|
||||
'name': 'trunk',
|
||||
'admin_state_up': True,
|
||||
'tenant_id': tdata['tenant_id'],
|
||||
'project_id': tdata['tenant_id'],
|
||||
'port_id': tdata['parent']['id'],
|
||||
'id': tdata['trunk_id']
|
||||
}
|
||||
TEST.api_tp_trunks.add(tp_trunk_dict)
|
||||
|
||||
# port parent
|
||||
parent_port_dict = {
|
||||
'admin_state_up': True,
|
||||
'device_id': tdata['parent']['device_id'],
|
||||
'device_owner': 'compute:nova',
|
||||
'fixed_ips': [{'ip_address': tdata['parent']['ip'],
|
||||
'subnet_id': tdata['subnet']['tst_id']}],
|
||||
'id': tdata['parent']['id'],
|
||||
'mac_address': tdata['parent']['mac'],
|
||||
'name': 'parent',
|
||||
'network_id': tdata['net']['tst_id'],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': tdata['tenant_id'],
|
||||
'binding:vnic_type': 'normal',
|
||||
'binding:host_id': 'host',
|
||||
'security_groups': [tdata['security_group']],
|
||||
'trunk_details': {
|
||||
'sub_ports': [{'segmentation_type': 'vlan',
|
||||
'mac_address': tdata['child1']['mac'],
|
||||
'segmentation_id': tdata['tag_1'],
|
||||
'port_id': tdata['child1']['id']},
|
||||
{'segmentation_type': 'vlan',
|
||||
'mac_address': tdata['child2']['mac'],
|
||||
'segmentation_id': tdata['tag_2'],
|
||||
'port_id': tdata['child2']['id']}],
|
||||
'trunk_id': tdata['trunk_id']}
|
||||
}
|
||||
TEST.api_tp_ports.add(parent_port_dict)
|
||||
TEST.tp_ports.add(neutron.PortTrunkParent(parent_port_dict))
|
||||
|
||||
# port child1
|
||||
child1_port_dict = {
|
||||
'admin_state_up': True,
|
||||
'device_id': tdata['child1']['device_id'],
|
||||
'device_owner': 'compute:nova',
|
||||
'fixed_ips': [{'ip_address': tdata['child1']['ip'],
|
||||
'subnet_id': tdata['subnet']['tst_id']}],
|
||||
'id': tdata['child1']['id'],
|
||||
'mac_address': tdata['child1']['mac'],
|
||||
'name': 'child1',
|
||||
'network_id': tdata['net']['tst_id'],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': tdata['tenant_id'],
|
||||
'binding:vnic_type': 'normal',
|
||||
'binding:host_id': 'host',
|
||||
'security_groups': [tdata['security_group']]
|
||||
}
|
||||
TEST.api_tp_ports.add(child1_port_dict)
|
||||
TEST.tp_ports.add(neutron.PortTrunkSubport(
|
||||
child1_port_dict,
|
||||
{'trunk_id': tdata['trunk_id'],
|
||||
'segmentation_type': 'vlan',
|
||||
'segmentation_id': tdata['tag_1']}))
|
||||
|
||||
# port plain
|
||||
port_dict = {
|
||||
'admin_state_up': True,
|
||||
'device_id': tdata['plain']['device_id'],
|
||||
'device_owner': 'compute:nova',
|
||||
'fixed_ips': [{'ip_address': tdata['plain']['ip'],
|
||||
'subnet_id': tdata['subnet']['tst_id']}],
|
||||
'id': tdata['plain']['id'],
|
||||
'mac_address': tdata['plain']['mac'],
|
||||
'name': 'plain',
|
||||
'network_id': tdata['net']['tst_id'],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': tdata['tenant_id'],
|
||||
'binding:vnic_type': 'normal',
|
||||
'binding:host_id': 'host',
|
||||
'security_groups': [tdata['security_group']]
|
||||
}
|
||||
TEST.api_tp_ports.add(port_dict)
|
||||
TEST.tp_ports.add(neutron.Port(port_dict))
|
||||
|
||||
# network tstalt
|
||||
|
||||
# port child2
|
||||
child2_port_dict = {
|
||||
'admin_state_up': True,
|
||||
'device_id': tdata['child2']['device_id'],
|
||||
'device_owner': 'compute:nova',
|
||||
'fixed_ips': [{'ip_address': tdata['child2']['ip'],
|
||||
'subnet_id': tdata['subnet']['tstalt_id']}],
|
||||
'id': tdata['child2']['id'],
|
||||
'mac_address': tdata['child2']['mac'],
|
||||
'name': 'child2',
|
||||
'network_id': tdata['net']['tstalt_id'],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': tdata['tenant_id'],
|
||||
'binding:vnic_type': 'normal',
|
||||
'binding:host_id': 'host',
|
||||
'security_groups': [tdata['security_group']]
|
||||
}
|
||||
TEST.api_tp_ports.add(child2_port_dict)
|
||||
TEST.tp_ports.add(neutron.PortTrunkSubport(
|
||||
child2_port_dict,
|
||||
{'trunk_id': tdata['trunk_id'],
|
||||
'segmentation_type': 'vlan',
|
||||
'segmentation_id': tdata['tag_2']}))
|
||||
|
Loading…
x
Reference in New Issue
Block a user