Fullstack case for metadata path
This case has following workflow: 1. start a neutron environment with 1 neutron-server and 1 ovs-agent 2. boot 2 fake VMs (namespace) to install and verify the installed flows. Change-Id: Id55deca434f82976a58944146e4d756e52868a33
This commit is contained in:
@@ -824,6 +824,22 @@ class OVSBridgeFixture(fixtures.Fixture):
|
||||
self.addCleanup(self.bridge.destroy)
|
||||
|
||||
|
||||
class OVSMetaBridgeFixture(fixtures.Fixture):
|
||||
"""Create an OVS bridge.
|
||||
|
||||
:ivar bridge: created bridge
|
||||
:type bridge: OVSBridge
|
||||
"""
|
||||
def __init__(self, name):
|
||||
super().__init__()
|
||||
self.name = name
|
||||
|
||||
def _setUp(self):
|
||||
ovs = ovs_lib.BaseOVS()
|
||||
self.bridge = ovs.add_bridge(self.name)
|
||||
self.addCleanup(self.bridge.destroy)
|
||||
|
||||
|
||||
class OVSTrunkBridgeFixture(OVSBridgeFixture):
|
||||
"""This bridge doesn't generate the name."""
|
||||
def _setUp(self):
|
||||
|
@@ -216,18 +216,21 @@ class OVSConfigFixture(ConfigFixture):
|
||||
base_filename='openvswitch_agent.ini')
|
||||
|
||||
self.tunneling_enabled = self.env_desc.tunneling_enabled
|
||||
ext_dev = utils.get_rand_device_name(prefix='br-eth')
|
||||
|
||||
if host_desc.segmented_physnet:
|
||||
physnet = PHYSICAL_NETWORK_SEGMENTS_NAME
|
||||
else:
|
||||
physnet = PHYSICAL_NETWORK_NAME
|
||||
|
||||
self.phy_br_name = utils.get_rand_device_name(prefix='br-eth')
|
||||
self.meta_br_name = self._generate_meta_bridge()
|
||||
bridge_mappings = '{}:{}'.format(physnet, self.phy_br_name)
|
||||
if env_desc.has_metadata:
|
||||
bridge_mappings += ',{}:{}'.format('meta', self.meta_br_name)
|
||||
self.config.update({
|
||||
'ovs': {
|
||||
'local_ip': local_ip,
|
||||
'integration_bridge': self._generate_integration_bridge(),
|
||||
'bridge_mappings': '{}:{}'.format(physnet, ext_dev),
|
||||
'bridge_mappings': bridge_mappings,
|
||||
'of_inactivity_probe': '0',
|
||||
'ovsdb_debug': 'True',
|
||||
'qos_meter_bandwidth': str(
|
||||
@@ -254,7 +257,8 @@ class OVSConfigFixture(ConfigFixture):
|
||||
else:
|
||||
if env_desc.report_bandwidths:
|
||||
self.config['ovs'][constants.RP_BANDWIDTHS] = \
|
||||
'{}:{}:{}'.format(ext_dev, MINIMUM_BANDWIDTH_EGRESS_KBPS,
|
||||
'{}:{}:{}'.format(self.phy_br_name,
|
||||
MINIMUM_BANDWIDTH_EGRESS_KBPS,
|
||||
MINIMUM_BANDWIDTH_INGRESS_KBPS)
|
||||
|
||||
if env_desc.qos:
|
||||
@@ -281,6 +285,17 @@ class OVSConfigFixture(ConfigFixture):
|
||||
if host_desc.firewall_driver == 'openvswitch':
|
||||
self.config['local_ip'] = {'static_nat': 'True'}
|
||||
|
||||
if env_desc.has_metadata:
|
||||
self.config['agent']['extensions'] = 'metadata_path'
|
||||
self.config.update({
|
||||
'METADATA': {
|
||||
'metadata_proxy_shared_secret': 'secret',
|
||||
'nova_metadata_host': env_desc.metadata_host,
|
||||
'nova_metadata_port': str(env_desc.metadata_port),
|
||||
'host_proxy_listen_port': str(env_desc.hp_listen_port),
|
||||
}
|
||||
})
|
||||
|
||||
def _setUp(self):
|
||||
self.config['ovs'].update({
|
||||
'of_listen_port': self.useFixture(
|
||||
@@ -296,6 +311,9 @@ class OVSConfigFixture(ConfigFixture):
|
||||
def _generate_tunnel_bridge(self):
|
||||
return utils.get_rand_device_name(prefix='br-tun')
|
||||
|
||||
def _generate_meta_bridge(self):
|
||||
return utils.get_rand_device_name(prefix='br-meta')
|
||||
|
||||
def _generate_int_peer(self):
|
||||
return utils.get_rand_device_name(prefix='patch-tun')
|
||||
|
||||
@@ -313,7 +331,10 @@ class OVSConfigFixture(ConfigFixture):
|
||||
return self.config.ovs.integration_bridge
|
||||
|
||||
def get_br_phys_name(self):
|
||||
return self.config.ovs.bridge_mappings.split(':')[1]
|
||||
return self.phy_br_name
|
||||
|
||||
def get_br_meta_name(self):
|
||||
return self.meta_br_name
|
||||
|
||||
def get_br_tun_name(self):
|
||||
return self.config.ovs.tunnel_bridge
|
||||
@@ -355,6 +376,20 @@ class PlacementConfigFixture(ConfigFixture):
|
||||
})
|
||||
|
||||
|
||||
class MetadataConfigFixture(ConfigFixture):
|
||||
|
||||
def __init__(self, env_desc, host_desc, temp_dir):
|
||||
super().__init__(
|
||||
env_desc, host_desc, temp_dir, base_filename='metadata.ini')
|
||||
self.config.update({
|
||||
'DEFAULT': {
|
||||
'debug': 'True',
|
||||
'metadata_host': self.env_desc.metadata_host,
|
||||
'metadata_port': str(self.env_desc.metadata_port)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
class L3ConfigFixture(ConfigFixture):
|
||||
|
||||
def __init__(self, env_desc, host_desc, temp_dir, integration_bridge=None):
|
||||
|
@@ -46,7 +46,9 @@ class EnvironmentDescription:
|
||||
api_workers=1,
|
||||
enable_traditional_dhcp=True, local_ip_ext=False,
|
||||
quota_driver=quota_conf.QUOTA_DB_DRIVER,
|
||||
use_meter_bandwidth_limit=False):
|
||||
use_meter_bandwidth_limit=False,
|
||||
has_metadata=False, metadata_host=None, metadata_port=None,
|
||||
host_proxy_listen_port=None):
|
||||
self.network_type = network_type
|
||||
self.l2_pop = l2_pop
|
||||
self.qos = qos
|
||||
@@ -75,6 +77,10 @@ class EnvironmentDescription:
|
||||
self.service_plugins += ',local_ip'
|
||||
self.quota_driver = quota_driver
|
||||
self.use_meter_bandwidth_limit = use_meter_bandwidth_limit
|
||||
self.has_metadata = has_metadata
|
||||
self.metadata_host = metadata_host
|
||||
self.metadata_port = metadata_port
|
||||
self.hp_listen_port = host_proxy_listen_port
|
||||
|
||||
@property
|
||||
def tunneling_enabled(self):
|
||||
@@ -183,6 +189,12 @@ class Host(fixtures.Fixture):
|
||||
self.env_desc, self.host_desc,
|
||||
self.test_name, self.neutron_config, agent_cfg_fixture))
|
||||
|
||||
if self.env_desc.has_metadata:
|
||||
self.br_meta = self.useFixture(
|
||||
net_helpers.OVSMetaBridgeFixture(
|
||||
self.ovs_agent.agent_cfg_fixture.get_br_meta_name())
|
||||
).bridge
|
||||
|
||||
if self.host_desc.l3_agent:
|
||||
self.l3_agent_cfg_fixture = self.useFixture(
|
||||
config.L3ConfigFixture(
|
||||
@@ -415,6 +427,17 @@ class Environment(fixtures.Fixture):
|
||||
placement_cfg_fixture)
|
||||
)
|
||||
|
||||
if self.env_desc.has_metadata:
|
||||
metadata_cfg_fixture = self.useFixture(
|
||||
config.MetadataConfigFixture(self.env_desc, self.hosts_desc,
|
||||
self.temp_dir)
|
||||
)
|
||||
self.metadata = self.useFixture(
|
||||
process.MetadataFixture(
|
||||
self.env_desc, self.hosts_desc, self.test_name,
|
||||
metadata_cfg_fixture)
|
||||
)
|
||||
|
||||
self.hosts = [self._create_host(desc) for desc in self.hosts_desc]
|
||||
|
||||
self.wait_until_env_is_up()
|
||||
|
@@ -314,6 +314,27 @@ class PlacementFixture(ServiceFixture):
|
||||
config_filenames=[self.placement_cfg_fixture.filename]))
|
||||
|
||||
|
||||
class MetadataFixture(ServiceFixture):
|
||||
|
||||
def __init__(self, env_desc, host_desc, test_name, metadata_cfg_fixture):
|
||||
super().__init__()
|
||||
self.env_desc = env_desc
|
||||
self.host_desc = host_desc
|
||||
self.test_name = test_name
|
||||
self.metadata_cfg_fixture = metadata_cfg_fixture
|
||||
self.metadata_config = self.metadata_cfg_fixture.config
|
||||
|
||||
def _setUp(self):
|
||||
self.process_fixture = self.useFixture(ProcessFixture(
|
||||
test_name=self.test_name,
|
||||
process_name='metadata',
|
||||
exec_name=shutil.which(
|
||||
'metadata.py', path=os.path.join(fullstack_base.ROOTDIR,
|
||||
'servers')
|
||||
),
|
||||
config_filenames=[self.metadata_cfg_fixture.filename]))
|
||||
|
||||
|
||||
class SRIOVAgentFixture(ServiceFixture):
|
||||
|
||||
def __init__(self, env_desc, host_desc,
|
||||
|
65
neutron/tests/fullstack/servers/metadata.py
Executable file
65
neutron/tests/fullstack/servers/metadata.py
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import sys
|
||||
from wsgiref import simple_server as wsgi_simple_server
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from neutron.common import config as common_config
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
metadata_opts = [
|
||||
cfg.StrOpt('metadata_host', default='127.0.0.1'),
|
||||
cfg.IntOpt('metadata_port', default=8775)
|
||||
]
|
||||
cfg.CONF.register_opts(metadata_opts)
|
||||
|
||||
|
||||
class FakeMetadata():
|
||||
|
||||
def wsgi_app(self, env, start_response):
|
||||
response_headers = [('Content-Type', 'application/json')]
|
||||
http_status = '200 OK'
|
||||
LOG.info("HTTP_X_INSTANCE_ID: %s", env.get('HTTP_X_INSTANCE_ID'))
|
||||
LOG.info("HTTP_X_TENANT_ID: %s", env.get('HTTP_X_TENANT_ID'))
|
||||
LOG.info("HTTP_X_INSTANCE_ID_SIGNATURE: %s",
|
||||
env.get('HTTP_X_INSTANCE_ID_SIGNATURE'))
|
||||
|
||||
# Send the headers back for verify the path
|
||||
response_headers += [
|
||||
('RESP_INSTANCE_ID', env.get('HTTP_X_INSTANCE_ID')),
|
||||
('RESP_TENANT_ID', env.get('HTTP_X_TENANT_ID')),
|
||||
('RESP_INSTANCE_ID_SIGNATURE',
|
||||
env.get('HTTP_X_INSTANCE_ID_SIGNATURE'))]
|
||||
|
||||
start_response(http_status, response_headers)
|
||||
return [b"Metadata OK"]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
common_config.register_common_config_options()
|
||||
common_config.init(sys.argv[1:])
|
||||
common_config.setup_logging()
|
||||
metadata_host = cfg.CONF.metadata_host
|
||||
metadata_port = cfg.CONF.metadata_port
|
||||
|
||||
LOG.info("Metadata fixture started on port: %s", metadata_port)
|
||||
|
||||
mock_metadata = FakeMetadata()
|
||||
wsgi_simple_server.make_server(
|
||||
metadata_host, metadata_port, mock_metadata.wsgi_app).serve_forever()
|
279
neutron/tests/fullstack/test_ovs_metadata_extension.py
Normal file
279
neutron/tests/fullstack/test_ovs_metadata_extension.py
Normal file
@@ -0,0 +1,279 @@
|
||||
# Copyright (c) 2023 China Unicom Cloud Data Co.,Ltd.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import re
|
||||
|
||||
import netaddr
|
||||
from neutron_lib import constants
|
||||
from neutron_lib.plugins.ml2 import ovs_constants as p_const
|
||||
from neutron_lib.plugins import utils as p_utils
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from neutron.common import utils as common_utils
|
||||
from neutron.tests.common.exclusive_resources import ip_network
|
||||
from neutron.tests.fullstack import base
|
||||
from neutron.tests.fullstack.resources import environment
|
||||
from neutron.tests.fullstack.resources import machine
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
METADATA_REQUEST_TIMEOUT = 60
|
||||
METADATA_REQUEST_SLEEP = 5
|
||||
TOO_MANY_REQUESTS_CODE = '429'
|
||||
|
||||
|
||||
class OvsMetadataExtensionTestCase(base.BaseFullStackTestCase):
|
||||
number_of_hosts = 1
|
||||
|
||||
def setUp(self):
|
||||
host_desc = [
|
||||
environment.HostDescription(
|
||||
l2_agent_type=constants.AGENT_TYPE_OVS,
|
||||
firewall_driver='openvswitch',
|
||||
l3_agent=True,
|
||||
dhcp_agent=False) for _ in range(self.number_of_hosts)]
|
||||
env_desc = environment.EnvironmentDescription(
|
||||
mech_drivers='openvswitch',
|
||||
has_metadata=True, metadata_host='127.0.0.1',
|
||||
metadata_port=58775,
|
||||
host_proxy_listen_port=55555,
|
||||
enable_traditional_dhcp=False)
|
||||
env = environment.Environment(env_desc, host_desc)
|
||||
super().setUp(env)
|
||||
self.tenant_id = uuidutils.generate_uuid()
|
||||
self.vm_id_1 = uuidutils.generate_uuid()
|
||||
self.vm_id_2 = uuidutils.generate_uuid()
|
||||
|
||||
network = self.safe_client.create_network(
|
||||
self.tenant_id, name='public', external=True)
|
||||
cidr = self.useFixture(
|
||||
ip_network.ExclusiveIPNetwork(
|
||||
"240.0.0.0", "240.255.255.255", "24")).network
|
||||
self.safe_client.create_subnet(
|
||||
self.tenant_id, network['id'], cidr)
|
||||
|
||||
router = self.safe_client.create_router(
|
||||
self.tenant_id, external_network=network['id'])
|
||||
|
||||
self.network = self.safe_client.create_network(
|
||||
self.tenant_id, 'network-test')
|
||||
subnet_routes_v4 = [
|
||||
{"destination": "1.1.1.0/24", "nexthop": "10.0.0.100"},
|
||||
{"destination": "2.2.2.2/32", "nexthop": "10.0.0.101"}]
|
||||
self.subnet_v4 = self.safe_client.create_subnet(
|
||||
self.tenant_id, self.network['id'],
|
||||
cidr='10.0.0.0/24',
|
||||
gateway_ip='10.0.0.1',
|
||||
enable_dhcp=False,
|
||||
name='subnet-v4-test',
|
||||
host_routes=subnet_routes_v4)
|
||||
|
||||
router_interface_info = self.safe_client.add_router_interface(
|
||||
router['id'], self.subnet_v4['id'])
|
||||
self.block_until_port_status_active(
|
||||
router_interface_info['port_id'])
|
||||
|
||||
subnet_routes_v6 = [
|
||||
{"destination": "2001:4860:4860::8888/128",
|
||||
"nexthop": "fda7:a5cc:3460:1::1"},
|
||||
{"destination": "1234:5678:abcd::/64",
|
||||
"nexthop": "fda7:a5cc:3460:1::fff"}]
|
||||
self.subnet_v6 = self.safe_client.create_subnet(
|
||||
self.tenant_id, self.network['id'],
|
||||
cidr='fda7:a5cc:3460:1::/64',
|
||||
gateway_ip='fda7:a5cc:3460:1::1',
|
||||
enable_dhcp=True,
|
||||
ipv6_address_mode="dhcpv6-stateful",
|
||||
ipv6_ra_mode="dhcpv6-stateful",
|
||||
ip_version=6,
|
||||
name='subnet-v6-test',
|
||||
host_routes=subnet_routes_v6)
|
||||
|
||||
# Need router radvd to send IPv6 address prefix to make the default
|
||||
# route work.
|
||||
router_interface_info = self.safe_client.add_router_interface(
|
||||
router['id'], self.subnet_v6['id'])
|
||||
self.block_until_port_status_active(
|
||||
router_interface_info['port_id'])
|
||||
|
||||
def block_until_port_status_active(self, port_id):
|
||||
def is_port_status_active():
|
||||
port = self.client.show_port(port_id)
|
||||
return port['port']['status'] == 'ACTIVE'
|
||||
common_utils.wait_until_true(lambda: is_port_status_active(), sleep=1)
|
||||
|
||||
def _prepare_vms(self):
|
||||
sgs = [self.safe_client.create_security_group(self.tenant_id)
|
||||
for _ in range(2)]
|
||||
|
||||
port1 = self.safe_client.create_port(
|
||||
self.tenant_id, self.network['id'],
|
||||
self.environment.hosts[0].hostname,
|
||||
device_owner="compute:test_ovs_meta_1",
|
||||
device_id=self.vm_id_1,
|
||||
security_groups=[sgs[0]['id']])
|
||||
|
||||
port2 = self.safe_client.create_port(
|
||||
self.tenant_id, self.network['id'],
|
||||
self.environment.hosts[0].hostname,
|
||||
device_owner="compute:test_ovs_meta_2",
|
||||
device_id=self.vm_id_2,
|
||||
security_groups=[sgs[1]['id']])
|
||||
|
||||
# insert security-group-rules allow icmp
|
||||
self.safe_client.create_security_group_rule(
|
||||
self.tenant_id, sgs[0]['id'],
|
||||
direction=constants.INGRESS_DIRECTION,
|
||||
ethertype=constants.IPv4,
|
||||
protocol=constants.PROTO_NAME_ICMP)
|
||||
self.safe_client.create_security_group_rule(
|
||||
self.tenant_id, sgs[0]['id'],
|
||||
direction=constants.INGRESS_DIRECTION,
|
||||
ethertype=constants.IPv6,
|
||||
protocol=constants.PROTO_NAME_ICMP)
|
||||
|
||||
# insert security-group-rules allow icmp
|
||||
self.safe_client.create_security_group_rule(
|
||||
self.tenant_id, sgs[1]['id'],
|
||||
direction=constants.INGRESS_DIRECTION,
|
||||
ethertype=constants.IPv4,
|
||||
protocol=constants.PROTO_NAME_ICMP)
|
||||
self.safe_client.create_security_group_rule(
|
||||
self.tenant_id, sgs[1]['id'],
|
||||
direction=constants.INGRESS_DIRECTION,
|
||||
ethertype=constants.IPv6,
|
||||
protocol=constants.PROTO_NAME_ICMP)
|
||||
|
||||
vm1 = self.useFixture(
|
||||
machine.FakeFullstackMachine(
|
||||
self.environment.hosts[0],
|
||||
self.network['id'],
|
||||
self.tenant_id,
|
||||
self.safe_client,
|
||||
neutron_port=port1,
|
||||
use_dhcp=False,
|
||||
use_dhcp6=False))
|
||||
|
||||
vm2 = self.useFixture(
|
||||
machine.FakeFullstackMachine(
|
||||
self.environment.hosts[0],
|
||||
self.network['id'],
|
||||
self.tenant_id,
|
||||
self.safe_client,
|
||||
neutron_port=port2,
|
||||
use_dhcp=False,
|
||||
use_dhcp6=False))
|
||||
return machine.FakeFullstackMachinesList([vm1, vm2])
|
||||
|
||||
def _wait_for_metadata_flows_applied(self, vm, table, actions):
|
||||
|
||||
def _is_metadata_flow_set(vm, table, actions):
|
||||
LOG.info("Metadata bridge verify actions: %s", actions)
|
||||
flows = vm.host.br_meta.dump_flows_for_table(table)
|
||||
flows_list = flows.splitlines()
|
||||
LOG.info("Metadata bridge flows_list: %s", flows_list)
|
||||
pattern = re.compile(
|
||||
r"^.* table=%s,.* actions=%s" % (table, re.escape(actions)))
|
||||
for flow in flows_list:
|
||||
if pattern.match(flow.strip()):
|
||||
return True
|
||||
return False
|
||||
common_utils.wait_until_true(lambda: _is_metadata_flow_set(
|
||||
vm, table, actions))
|
||||
|
||||
def test_ovs_meta_agent_extension_verify_ovs_flows(self):
|
||||
vms = self._prepare_vms()
|
||||
vms.block_until_all_boot()
|
||||
|
||||
# Check ovs flows
|
||||
vm_0_provider_ip = vms[0].bridge.get_value_from_other_config(
|
||||
vms[0].port.name, "provider_ip", value_type=str)
|
||||
vm_0_provider_mac = vms[0].bridge.get_value_from_other_config(
|
||||
vms[0].port.name, "provider_mac", value_type=str)
|
||||
|
||||
actions_0 = ("strip_vlan,mod_dl_src:%s,"
|
||||
"mod_nw_src:%s,resubmit(,87)") % (vm_0_provider_mac,
|
||||
vm_0_provider_ip)
|
||||
self._wait_for_metadata_flows_applied(vms[0], 80, actions_0)
|
||||
|
||||
vm_1_provider_ip = vms[1].bridge.get_value_from_other_config(
|
||||
vms[1].port.name, "provider_ip", value_type=str)
|
||||
vm_1_provider_mac = vms[1].bridge.get_value_from_other_config(
|
||||
vms[1].port.name, "provider_mac", value_type=str)
|
||||
actions_1 = ("strip_vlan,mod_dl_src:%s,"
|
||||
"mod_nw_src:%s,resubmit(,87)") % (vm_1_provider_mac,
|
||||
vm_1_provider_ip)
|
||||
self._wait_for_metadata_flows_applied(vms[1], 80, actions_1)
|
||||
|
||||
tap_meta_ofport = vms[0].host.br_meta.get_port_ofport("tap-meta")
|
||||
self._wait_for_metadata_flows_applied(
|
||||
vms[0], 87,
|
||||
("mod_dl_dst:fa:16:ee:00:00:01,mod_nw_dst:240.0.0.1,"
|
||||
"mod_tp_dst:55555,output:%s" % tap_meta_ofport))
|
||||
|
||||
vm_0_provider_mac_hex = "0x%s" % (
|
||||
vm_0_provider_mac.replace(":", ""))
|
||||
vm_0_provider_ip_hex = "%x" % netaddr.IPAddress(vm_0_provider_ip)
|
||||
vm_0_arp_res_actions = (
|
||||
"load:0x2->NXM_OF_ARP_OP[],"
|
||||
"move:NXM_NX_ARP_SHA[]->NXM_NX_ARP_THA[],"
|
||||
"move:NXM_OF_ARP_SPA[]->NXM_OF_ARP_TPA[],"
|
||||
"load:%s->NXM_NX_ARP_SHA[],"
|
||||
"load:0x%s->NXM_OF_ARP_SPA[],"
|
||||
"move:NXM_OF_ETH_SRC[]->NXM_OF_ETH_DST[],"
|
||||
"mod_dl_src:%s,IN_PORT") % (vm_0_provider_mac_hex,
|
||||
vm_0_provider_ip_hex,
|
||||
vm_0_provider_mac)
|
||||
self._wait_for_metadata_flows_applied(
|
||||
vms[0], 90, vm_0_arp_res_actions)
|
||||
|
||||
vm_1_provider_mac_hex = "0x%s" % (vm_1_provider_mac.replace(":", ""))
|
||||
vm_1_provider_ip_hex = "%x" % netaddr.IPAddress(vm_1_provider_ip)
|
||||
vm_1_arp_res_actions = (
|
||||
"load:0x2->NXM_OF_ARP_OP[],"
|
||||
"move:NXM_NX_ARP_SHA[]->NXM_NX_ARP_THA[],"
|
||||
"move:NXM_OF_ARP_SPA[]->NXM_OF_ARP_TPA[],"
|
||||
"load:%s->NXM_NX_ARP_SHA[],"
|
||||
"load:0x%s->NXM_OF_ARP_SPA[],"
|
||||
"move:NXM_OF_ETH_SRC[]->NXM_OF_ETH_DST[],"
|
||||
"mod_dl_src:%s,IN_PORT") % (vm_1_provider_mac_hex,
|
||||
vm_1_provider_ip_hex,
|
||||
vm_1_provider_mac)
|
||||
self._wait_for_metadata_flows_applied(
|
||||
vms[1], 90, vm_1_arp_res_actions)
|
||||
|
||||
local_vlan = vms[0].bridge.get_port_tag_by_name(vms[0].port.name)
|
||||
|
||||
patch_name = p_utils.get_interface_name(
|
||||
vms[0].host.br_meta.br_name,
|
||||
prefix=p_const.PEER_PHYSICAL_PREFIX)
|
||||
patch_ofport = vms[0].host.br_meta.get_port_ofport(patch_name)
|
||||
self._wait_for_metadata_flows_applied(
|
||||
vms[0], 91,
|
||||
("mod_vlan_vid:%s,mod_dl_dst:%s,"
|
||||
"mod_nw_src:169.254.169.254,mod_nw_dst:%s,mod_tp_src:80,"
|
||||
"output:%s" % (local_vlan, vms[0].neutron_port['mac_address'],
|
||||
vms[0].ip, patch_ofport)))
|
||||
local_vlan = vms[1].bridge.get_port_tag_by_name(vms[1].port.name)
|
||||
patch_name = p_utils.get_interface_name(
|
||||
vms[1].host.br_meta.br_name,
|
||||
prefix=p_const.PEER_PHYSICAL_PREFIX)
|
||||
patch_ofport = vms[1].host.br_meta.get_port_ofport(patch_name)
|
||||
self._wait_for_metadata_flows_applied(
|
||||
vms[1], 91,
|
||||
("mod_vlan_vid:%s,mod_dl_dst:%s,"
|
||||
"mod_nw_src:169.254.169.254,mod_nw_dst:%s,mod_tp_src:80,"
|
||||
"output:%s" % (local_vlan, vms[1].neutron_port['mac_address'],
|
||||
vms[1].ip, patch_ofport)))
|
Reference in New Issue
Block a user