neutron/neutron/tests/common/machine_fixtures.py
Jakub Libosvar f0439a04ad fullstack: VLAN aware VMs test
Patch tests basic life-cycle of a trunk associated with a port. Test
creates a trunk with one subport - this tests interaction between
agent and ovsdb handler that calls via RPC to server.
Later a new subport is added which tests RPC interaction between
server and agent. Then deletes the first created subport. Finally trunk
is removed and checked that no patch ports remain on the integration
bridge.

Future work:
 - Run this test with linuxbridge
 - Test re-using port associated with trunk.
 - Test re-using subports.
 - Test with OVS firewall.

Partially-implements: blueprint vlan-aware-vms
Change-Id: Ie79a010e6751c1f1c2be5b1bf52511b9e100ad20
2016-09-29 13:23:39 -04:00

170 lines
4.8 KiB
Python

# Copyright (c) 2015 Thales Services SAS
#
# 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 functools
import fixtures
from neutron.agent.linux import ip_lib
from neutron.common import utils
from neutron.tests.common import net_helpers
class FakeMachineException(Exception):
pass
class FakeMachineBase(fixtures.Fixture):
"""Create a fake machine.
:ivar bridge: bridge on which the fake machine is bound
:ivar ip_cidr: fake machine ip_cidr
:type ip_cidr: str
:ivar ip: fake machine ip
:type ip: str
:ivar gateway_ip: fake machine gateway ip
:type gateway_ip: str
:ivar namespace: namespace emulating the machine
:type namespace: str
:ivar port: port binding the namespace to the bridge
:type port: IPDevice
"""
def __init__(self):
self.port = None
def _setUp(self):
ns_fixture = self.useFixture(
net_helpers.NamespaceFixture())
self.namespace = ns_fixture.name
def execute(self, *args, **kwargs):
ns_ip_wrapper = ip_lib.IPWrapper(self.namespace)
return ns_ip_wrapper.netns.execute(*args, **kwargs)
def ping_predicate(self, dst_ip):
try:
self.assert_ping(dst_ip)
except RuntimeError:
return False
return True
def block_until_ping(self, dst_ip):
predicate = functools.partial(self.ping_predicate, dst_ip)
utils.wait_until_true(
predicate,
exception=FakeMachineException(
"No ICMP reply obtained from IP address %s" % dst_ip)
)
def block_until_no_ping(self, dst_ip):
predicate = functools.partial(
lambda ip: not self.ping_predicate(ip), dst_ip)
utils.wait_until_true(
predicate,
exception=FakeMachineException(
"ICMP packets still pass to %s IP address." % dst_ip)
)
def assert_ping(self, dst_ip):
net_helpers.assert_ping(self.namespace, dst_ip)
def assert_no_ping(self, dst_ip):
net_helpers.assert_no_ping(self.namespace, dst_ip)
@property
def ip(self):
raise NotImplementedError()
@property
def ip_cidr(self):
raise NotImplementedError()
@property
def mac_address(self):
return self.port.link.address
class FakeMachine(FakeMachineBase):
def __init__(self, bridge, ip_cidr, gateway_ip=None):
super(FakeMachine, self).__init__()
self.bridge = bridge
self._ip_cidr = ip_cidr
self.gateway_ip = gateway_ip
def _setUp(self):
super(FakeMachine, self)._setUp()
self.port = self.useFixture(
net_helpers.PortFixture.get(self.bridge, self.namespace)).port
self.port.addr.add(self._ip_cidr)
if self.gateway_ip:
net_helpers.set_namespace_gateway(self.port, self.gateway_ip)
@property
def ip(self):
return self._ip_cidr.partition('/')[0]
@property
def ip_cidr(self):
return self._ip_cidr
@ip_cidr.setter
def ip_cidr(self, ip_cidr):
self.port.addr.add(ip_cidr)
self.port.addr.delete(self._ip_cidr)
self._ip_cidr = ip_cidr
@FakeMachineBase.mac_address.setter
def mac_address(self, mac_address):
self.port.link.set_down()
self.port.link.set_address(mac_address)
self.port.link.set_up()
def set_default_gateway(self, default_gw):
self.port.route.add_gateway(default_gw)
class PeerMachines(fixtures.Fixture):
"""Create 'amount' peered machines on an ip_cidr.
:ivar bridge: bridge on which peer machines are bound
:ivar ip_cidr: ip_cidr on which peer machines have ips
:type ip_cidr: str
:ivar machines: fake machines
:type machines: FakeMachine list
"""
CIDR = '192.168.0.1/24'
def __init__(self, bridge, ip_cidr=None, gateway_ip=None, amount=2):
super(PeerMachines, self).__init__()
self.bridge = bridge
self.ip_cidr = ip_cidr or self.CIDR
self.gateway_ip = gateway_ip
self.amount = amount
def _setUp(self):
self.machines = []
for index in range(self.amount):
ip_cidr = net_helpers.increment_ip_cidr(self.ip_cidr, index)
self.machines.append(
self.useFixture(
FakeMachine(self.bridge, ip_cidr, self.gateway_ip)))