Ejemplo n.º 1
0
class TestDscpMarkingQoSOvs(_TestDscpMarkingQoS, base.BaseFullStackTestCase):
    scenarios = fullstack_utils.get_ovs_interface_scenarios()
    l2_agent_type = constants.AGENT_TYPE_OVS

    def _wait_for_dscp_marking_rule_applied(self, vm, dscp_mark):
        l2_extensions.wait_until_dscp_marking_rule_applied_ovs(
            vm.bridge, vm.port.name, dscp_mark)
Ejemplo n.º 2
0
class TestMinBwQoSOvs(_TestMinBwQoS, base.BaseFullStackTestCase):
    l2_agent_type = constants.AGENT_TYPE_OVS
    direction_scenarios = [('egress', {
        'direction': constants.EGRESS_DIRECTION
    })]
    scenarios = testscenarios.multiply_scenarios(
        direction_scenarios, fullstack_utils.get_ovs_interface_scenarios())

    def _wait_for_min_bw_rule_applied(self, vm, min_bw, direction):
        if direction == constants.EGRESS_DIRECTION:
            utils.wait_until_true(lambda: vm.bridge.get_egress_min_bw_for_port(
                vm.neutron_port['id']) == min_bw)
        elif direction == constants.INGRESS_DIRECTION:
            self.fail('"%s" direction not implemented' %
                      constants.INGRESS_DIRECTION)

    def test_bw_limit_qos_port_removed(self):
        """Test if rate limit config is properly removed when whole port is
        removed.
        """
        # Create port with qos policy attached
        vm, qos_policy = self._prepare_vm_with_qos_policy([
            functools.partial(self._add_min_bw_rule, MIN_BANDWIDTH,
                              self.direction)
        ])
        self._wait_for_min_bw_rule_applied(vm, MIN_BANDWIDTH, self.direction)

        # Delete port with qos policy attached
        vm.destroy()
        self._wait_for_min_bw_rule_removed(vm, self.direction)
        self.assertIsNone(vm.bridge.find_qos(vm.port.name))
        self.assertIsNone(
            vm.bridge.find_queue(vm.port.name, ovs_lib.QOS_DEFAULT_QUEUE))
Ejemplo n.º 3
0
class TestBwLimitQoSOvs(_TestBwLimitQoS, base.BaseFullStackTestCase):
    l2_agent_type = constants.AGENT_TYPE_OVS
    scenarios = fullstack_utils.get_ovs_interface_scenarios()

    def _wait_for_bw_rule_applied(self, vm, limit, burst):
        utils.wait_until_true(lambda: vm.bridge.get_egress_bw_limit_for_port(
            vm.port.name) == (limit, burst))
Ejemplo n.º 4
0
class TestUninterruptedConnectivityOnL2AgentRestart(
        BaseConnectivitySameNetworkTest):

    num_hosts = 2

    ovs_agent_scenario = [('OVS', {'l2_agent_type': constants.AGENT_TYPE_OVS})]
    lb_agent_scenario = [('LB', {
        'l2_agent_type': constants.AGENT_TYPE_LINUXBRIDGE
    })]

    network_scenarios = [
        ('Flat network', {
            'network_type': 'flat',
            'l2_pop': False
        }),
        ('VLANs', {
            'network_type': 'vlan',
            'l2_pop': False
        }),
        ('VXLAN', {
            'network_type': 'vxlan',
            'l2_pop': False
        }),
    ]
    scenarios = (
        testscenarios.multiply_scenarios(ovs_agent_scenario, network_scenarios,
                                         utils.get_ovs_interface_scenarios()) +
        testscenarios.multiply_scenarios(lb_agent_scenario, network_scenarios))

    def test_l2_agent_restart(self, agent_restart_timeout=20):
        # Environment preparation is effectively the same as connectivity test
        vms = self._prepare_vms_in_single_network()
        vms.ping_all()

        ns0 = vms[0].namespace
        ip1 = vms[1].ip
        agents = [host.l2_agent for host in self.environment.hosts]

        # Restart agents on all nodes simultaneously while pinging across
        # the hosts. The ping has to cross int and phys bridges and travels
        # via central bridge as the vms are on separate hosts.
        with net_helpers.async_ping(ns0, [ip1],
                                    timeout=2,
                                    count=agent_restart_timeout) as done:
            LOG.debug("Restarting agents")
            executor = futures.ThreadPoolExecutor(max_workers=len(agents))
            restarts = [agent.restart(executor=executor) for agent in agents]

            futures.wait(restarts, timeout=agent_restart_timeout)

            self.assertTrue(all([r.done() for r in restarts]))
            LOG.debug("Restarting agents - done")

            # It is necessary to give agents time to initialize
            # because some crucial steps (e.g. setting up bridge flows)
            # happen only after RPC is established
            common_utils.wait_until_true(
                done,
                exception=RuntimeError("Could not ping the other VM, L2 agent "
                                       "restart leads to network disruption"))
Ejemplo n.º 5
0
class TestBwLimitQoSOvs(_TestBwLimitQoS, base.BaseFullStackTestCase):
    l2_agent_type = constants.AGENT_TYPE_OVS
    direction_scenarios = [('ingress', {
        'direction': constants.INGRESS_DIRECTION
    }), ('egress', {
        'direction': constants.EGRESS_DIRECTION
    })]
    scenarios = testscenarios.multiply_scenarios(
        direction_scenarios, fullstack_utils.get_ovs_interface_scenarios())

    @staticmethod
    def _get_expected_burst_value(limit, direction):
        # For egress bandwidth limit this value should be calculated as
        # bandwidth_limit * qos_consts.DEFAULT_BURST_RATE
        if direction == constants.EGRESS_DIRECTION:
            return TestBwLimitQoSOvs._get_expected_egress_burst_value(limit)
        else:
            return 0

    def _wait_for_bw_rule_applied(self, vm, limit, burst, direction):
        if direction == constants.EGRESS_DIRECTION:
            utils.wait_until_true(
                lambda: vm.bridge.get_egress_bw_limit_for_port(vm.port.name) ==
                (limit, burst))
        elif direction == constants.INGRESS_DIRECTION:
            utils.wait_until_true(
                lambda: vm.bridge.get_ingress_bw_limit_for_port(
                    vm.port.name) == (limit, burst))
Ejemplo n.º 6
0
class TestOvsConnectivitySameNetworkOnOvsBridgeControllerStop(
        BaseConnectivitySameNetworkTest):

    num_hosts = 2

    l2_agent_type = constants.AGENT_TYPE_OVS
    network_scenarios = [('VXLAN', {
        'network_type': 'vxlan',
        'l2_pop': False
    }), ('GRE and l2pop', {
        'network_type': 'gre',
        'l2_pop': True
    }), ('VLANs', {
        'network_type': 'vlan',
        'l2_pop': False
    })]

    # Do not test for CLI ofctl interface as controller is irrelevant for CLI
    scenarios = testscenarios.multiply_scenarios(
        network_scenarios, [(m, v)
                            for (m, v) in utils.get_ovs_interface_scenarios()
                            if v['of_interface'] != 'ovs-ofctl'])

    def _test_controller_timeout_does_not_break_connectivity(
            self, kill_signal=None):
        # Environment preparation is effectively the same as connectivity test
        vms = self._prepare_vms_in_single_network()
        vms.ping_all()

        ns0 = vms[0].namespace
        ip1 = vms[1].ip

        LOG.debug("Stopping agents (hence also OVS bridge controllers)")
        for host in self.environment.hosts:
            if kill_signal is not None:
                host.l2_agent.stop(kill_signal=kill_signal)
            else:
                host.l2_agent.stop()

        # Ping to make sure that 3 x 5 seconds is overcame even under a high
        # load. The time was chosen to match three times inactivity_probe time,
        # which is the time after which the OVS vswitchd
        # treats the controller as dead and starts managing the bridge
        # by itself when the fail type settings is not set to secure (see
        # ovs-vsctl man page for further details)
        with net_helpers.async_ping(ns0, [ip1], timeout=2, count=25) as done:
            common_utils.wait_until_true(done,
                                         exception=RuntimeError(
                                             "Networking interrupted after "
                                             "controllers have vanished"))

    def test_controller_timeout_does_not_break_connectivity_sigterm(self):
        self._test_controller_timeout_does_not_break_connectivity()

    def test_controller_timeout_does_not_break_connectivity_sigkill(self):
        self._test_controller_timeout_does_not_break_connectivity(
            signal.SIGKILL)
Ejemplo n.º 7
0
class TestDscpMarkingQoSOvs(BaseQoSRuleTestCase, base.BaseFullStackTestCase):
    scenarios = fullstack_utils.get_ovs_interface_scenarios()
    l2_agent_type = constants.AGENT_TYPE_OVS

    def _wait_for_dscp_marking_rule_applied(self, vm, dscp_mark):
        l2_extensions.wait_until_dscp_marking_rule_applied(
            vm.bridge, vm.port.name, dscp_mark)

    def _wait_for_dscp_marking_rule_removed(self, vm):
        self._wait_for_dscp_marking_rule_applied(vm, None)

    def _add_dscp_rule(self, dscp_mark, qos_policy):
        qos_policy_id = qos_policy['id']
        rule = self.safe_client.create_dscp_marking_rule(
            self.tenant_id, qos_policy_id, dscp_mark)
        # Make it consistent with GET reply
        rule['type'] = qos_consts.RULE_TYPE_DSCP_MARKING
        rule['qos_policy_id'] = qos_policy_id
        qos_policy['rules'].append(rule)

    def test_dscp_qos_policy_rule_lifecycle(self):
        new_dscp_mark = DSCP_MARK + 8

        # Create port with qos policy attached
        vm, qos_policy = self._prepare_vm_with_qos_policy(
            [functools.partial(self._add_dscp_rule, DSCP_MARK)])
        dscp_rule = qos_policy['rules'][0]

        self._wait_for_dscp_marking_rule_applied(vm, DSCP_MARK)
        qos_policy_id = qos_policy['id']

        self.client.delete_dscp_marking_rule(dscp_rule['id'], qos_policy_id)
        self._wait_for_dscp_marking_rule_removed(vm)

        # Create new rule
        new_rule = self.safe_client.create_dscp_marking_rule(
            self.tenant_id, qos_policy_id, new_dscp_mark)
        self._wait_for_dscp_marking_rule_applied(vm, new_dscp_mark)

        # Update qos policy rule id
        self.client.update_dscp_marking_rule(
            new_rule['id'],
            qos_policy_id,
            body={'dscp_marking_rule': {
                'dscp_mark': DSCP_MARK
            }})
        self._wait_for_dscp_marking_rule_applied(vm, DSCP_MARK)

        # Remove qos policy from port
        self.client.update_port(vm.neutron_port['id'],
                                body={'port': {
                                    'qos_policy_id': None
                                }})
        self._wait_for_dscp_marking_rule_removed(vm)
Ejemplo n.º 8
0
class TestMinBwQoSOvs(_TestMinBwQoS, base.BaseFullStackTestCase):
    l2_agent_type = constants.AGENT_TYPE_OVS
    direction_scenarios = [('egress', {
        'direction': constants.EGRESS_DIRECTION
    })]
    scenarios = testscenarios.multiply_scenarios(
        direction_scenarios, fullstack_utils.get_ovs_interface_scenarios())

    def _wait_for_min_bw_rule_applied(self, vm, min_bw, direction):
        if direction == constants.EGRESS_DIRECTION:
            utils.wait_until_true(lambda: vm.bridge.get_egress_min_bw_for_port(
                vm.neutron_port['id']) == min_bw)
        elif direction == constants.INGRESS_DIRECTION:
            self.fail('"%s" direction not implemented' %
                      constants.INGRESS_DIRECTION)

    def _find_agent_qos_and_queue(self, vm):
        # NOTE(ralonsoh): the "_min_bw_qos_id" in vm.bridge is not the same as
        # the ID in the agent br_int instance. We need first to find the QoS
        # register and the Queue assigned to vm.neutron_port['id']
        queue = vm.bridge._find_queue(vm.neutron_port['id'])
        queue_num = int(queue['external_ids']['queue-num'])
        qoses = vm.bridge._list_qos()
        for qos in qoses:
            qos_queue = qos['queues'].get(queue_num)
            if qos_queue and qos_queue.uuid == queue['_uuid']:
                return qos, qos_queue

        self.fail('QoS register not found with queue-num %s' % queue_num)

    def test_min_bw_qos_port_removed(self):
        """Test if min BW limit config is properly removed when port removed"""
        # Create port with qos policy attached
        vm, qos_policy = self._prepare_vm_with_qos_policy([
            functools.partial(self._add_min_bw_rule, MIN_BANDWIDTH,
                              self.direction)
        ])
        self._wait_for_min_bw_rule_applied(vm, MIN_BANDWIDTH, self.direction)

        qos, queue = self._find_agent_qos_and_queue(vm)
        self.assertEqual({'min-rate': str(MIN_BANDWIDTH * 1000)},
                         queue.other_config)
        queues = vm.bridge._list_queues(port=vm.neutron_port['id'])
        self.assertEqual(1, len(queues))
        self.assertEqual(queue.uuid, queues[0]['_uuid'])

        # Delete port with qos policy attached
        vm.destroy()
        self._wait_for_min_bw_rule_removed(vm, self.direction)
        self.assertEqual([],
                         vm.bridge._list_queues(port=vm.neutron_port['id']))
Ejemplo n.º 9
0
class TestBwLimitQoSOvs(_TestBwLimitQoS, base.BaseFullStackTestCase):
    l2_agent_type = constants.AGENT_TYPE_OVS
    direction_scenarios = [('ingress', {
        'direction': constants.INGRESS_DIRECTION
    }), ('egress', {
        'direction': constants.EGRESS_DIRECTION
    })]
    scenarios = testscenarios.multiply_scenarios(
        direction_scenarios, fullstack_utils.get_ovs_interface_scenarios())

    @staticmethod
    def _get_expected_burst_value(limit, direction):
        # For egress bandwidth limit this value should be calculated as
        # bandwidth_limit * qos_consts.DEFAULT_BURST_RATE
        if direction == constants.EGRESS_DIRECTION:
            return TestBwLimitQoSOvs._get_expected_egress_burst_value(limit)
        else:
            return 0

    def _wait_for_bw_rule_applied(self, vm, limit, burst, direction):
        if direction == constants.EGRESS_DIRECTION:
            utils.wait_until_true(
                lambda: vm.bridge.get_egress_bw_limit_for_port(vm.port.name) ==
                (limit, burst))
        elif direction == constants.INGRESS_DIRECTION:
            utils.wait_until_true(
                lambda: vm.bridge.get_ingress_bw_limit_for_port(
                    vm.port.name) == (limit, burst))

    @tests_base.unstable_test("bug 1737892")
    def test_bw_limit_qos_port_removed(self):
        """Test if rate limit config is properly removed when whole port is
        removed.
        """

        # Create port with qos policy attached
        vm, qos_policy = self._prepare_vm_with_qos_policy([
            functools.partial(self._add_bw_limit_rule, BANDWIDTH_LIMIT,
                              BANDWIDTH_BURST, self.direction)
        ])
        self._wait_for_bw_rule_applied(vm, BANDWIDTH_LIMIT, BANDWIDTH_BURST,
                                       self.direction)

        # Delete port with qos policy attached
        vm.destroy()
        self._wait_for_bw_rule_removed(vm, self.direction)
        self.assertIsNone(vm.bridge.find_qos(vm.port.name))
        self.assertIsNone(
            vm.bridge.find_queue(vm.port.name, ovs_lib.QOS_DEFAULT_QUEUE))
Ejemplo n.º 10
0
class TestOvsConnectivitySameNetwork(BaseConnectivitySameNetworkTest):

    l2_agent_type = constants.AGENT_TYPE_OVS
    network_scenarios = [
        ('VXLAN', {'network_type': 'vxlan',
                   'l2_pop': False}),
        ('GRE-l2pop-arp_responder', {'network_type': 'gre',
                                     'l2_pop': True,
                                     'arp_responder': True}),
        ('VLANs', {'network_type': 'vlan',
                   'l2_pop': False})]
    scenarios = testscenarios.multiply_scenarios(
        network_scenarios, utils.get_ovs_interface_scenarios())

    def test_connectivity(self):
        self._test_connectivity()
Ejemplo n.º 11
0
class TestUninterruptedConnectivityOnL2AgentRestart(
        BaseConnectivitySameNetworkTest):

    num_hosts = 2

    ovs_agent_scenario = [('OVS', {'l2_agent_type': constants.AGENT_TYPE_OVS})]
    lb_agent_scenario = [('LB', {
        'l2_agent_type': constants.AGENT_TYPE_LINUXBRIDGE
    })]

    network_scenarios = [
        ('Flat network', {
            'network_type': 'flat',
            'l2_pop': False
        }),
        ('VLANs', {
            'network_type': 'vlan',
            'l2_pop': False
        }),
        ('VXLAN', {
            'network_type': 'vxlan',
            'l2_pop': False
        }),
    ]
    scenarios = (
        testscenarios.multiply_scenarios(ovs_agent_scenario, network_scenarios,
                                         utils.get_ovs_interface_scenarios()) +
        testscenarios.multiply_scenarios(lb_agent_scenario, network_scenarios))

    def test_l2_agent_restart(self, agent_restart_timeout=20):
        # Environment preparation is effectively the same as connectivity test
        vms = self._prepare_vms_in_single_network()
        vms.ping_all()

        ns0 = vms[0].namespace
        ip1 = vms[1].ip
        agents = [host.l2_agent for host in self.environment.hosts]

        # Restart agents on all nodes simultaneously while pinging across
        # the hosts. The ping has to cross int and phys bridges and travels
        # via central bridge as the vms are on separate hosts.
        self._assert_ping_during_agents_restart(
            agents,
            ns0, [ip1],
            restart_timeout=agent_restart_timeout,
            ping_timeout=2,
            count=agent_restart_timeout)
Ejemplo n.º 12
0
class TestBwLimitQoSOvs(_TestBwLimitQoS, base.BaseFullStackTestCase):
    l2_agent_type = constants.AGENT_TYPE_OVS
    direction_scenarios = [('ingress', {
        'direction': common_constants.INGRESS_DIRECTION
    }), ('egress', {
        'direction': common_constants.EGRESS_DIRECTION
    })]
    scenarios = testscenarios.multiply_scenarios(
        direction_scenarios, fullstack_utils.get_ovs_interface_scenarios())

    def _wait_for_bw_rule_applied(self, vm, limit, burst, direction):
        if direction == common_constants.EGRESS_DIRECTION:
            utils.wait_until_true(
                lambda: vm.bridge.get_egress_bw_limit_for_port(vm.port.name) ==
                (limit, burst))
        elif direction == common_constants.INGRESS_DIRECTION:
            utils.wait_until_true(
                lambda: vm.bridge.get_ingress_bw_limit_for_port(
                    vm.port.name) == (limit, burst))

    def test_bw_limit_direction_change(self):
        # Create port with qos policy attached, with rule self.direction
        vm, qos_policy = self._prepare_vm_with_qos_policy([
            functools.partial(self._add_bw_limit_rule, BANDWIDTH_LIMIT,
                              BANDWIDTH_BURST, self.direction)
        ])
        bw_rule = qos_policy['rules'][0]

        self._wait_for_bw_rule_applied(vm, BANDWIDTH_LIMIT, BANDWIDTH_BURST,
                                       self.direction)

        # Update rule by changing direction to opposite then it was before
        self.client.update_bandwidth_limit_rule(bw_rule['id'],
                                                qos_policy['id'],
                                                body={
                                                    'bandwidth_limit_rule': {
                                                        'direction':
                                                        self.reverse_direction
                                                    }
                                                })
        self._wait_for_bw_rule_removed(vm, self.direction)
        self._wait_for_bw_rule_applied(vm, BANDWIDTH_LIMIT, BANDWIDTH_BURST,
                                       self.reverse_direction)
Ejemplo n.º 13
0
class TestDscpMarkingQoSOvs(BaseQoSRuleTestCase, base.BaseFullStackTestCase):
    scenarios = fullstack_utils.get_ovs_interface_scenarios()
    l2_agent_type = constants.AGENT_TYPE_OVS

    def setUp(self):
        host_desc = [
            environment.HostDescription(l3_agent=False,
                                        of_interface=self.of_interface,
                                        ovsdb_interface=self.ovsdb_interface,
                                        l2_agent_type=self.l2_agent_type)
            for _ in range(2)
        ]
        env_desc = environment.EnvironmentDescription(qos=True)
        env = environment.Environment(env_desc, host_desc)
        super(BaseQoSRuleTestCase, self).setUp(env)

        self.tenant_id = uuidutils.generate_uuid()
        self.network = self.safe_client.create_network(self.tenant_id,
                                                       'network-test')
        self.subnet = self.safe_client.create_subnet(self.tenant_id,
                                                     self.network['id'],
                                                     cidr='10.0.0.0/24',
                                                     gateway_ip='10.0.0.1',
                                                     name='subnet-test',
                                                     enable_dhcp=False)

    def _wait_for_dscp_marking_rule_applied(self, vm, dscp_mark):
        l2_extensions.wait_until_dscp_marking_rule_applied(
            vm.bridge, vm.port.name, dscp_mark)

    def _wait_for_dscp_marking_rule_removed(self, vm):
        self._wait_for_dscp_marking_rule_applied(vm, None)

    def _add_dscp_rule(self, dscp_mark, qos_policy):
        qos_policy_id = qos_policy['id']
        rule = self.safe_client.create_dscp_marking_rule(
            self.tenant_id, qos_policy_id, dscp_mark)
        # Make it consistent with GET reply
        rule['type'] = qos_consts.RULE_TYPE_DSCP_MARKING
        rule['qos_policy_id'] = qos_policy_id
        qos_policy['rules'].append(rule)

    def test_dscp_qos_policy_rule_lifecycle(self):
        new_dscp_mark = DSCP_MARK + 8

        # Create port with qos policy attached
        vm, qos_policy = self._prepare_vm_with_qos_policy(
            [functools.partial(self._add_dscp_rule, DSCP_MARK)])
        dscp_rule = qos_policy['rules'][0]

        self._wait_for_dscp_marking_rule_applied(vm, DSCP_MARK)
        qos_policy_id = qos_policy['id']

        self.client.delete_dscp_marking_rule(dscp_rule['id'], qos_policy_id)
        self._wait_for_dscp_marking_rule_removed(vm)

        # Create new rule
        new_rule = self.safe_client.create_dscp_marking_rule(
            self.tenant_id, qos_policy_id, new_dscp_mark)
        self._wait_for_dscp_marking_rule_applied(vm, new_dscp_mark)

        # Update qos policy rule id
        self.client.update_dscp_marking_rule(
            new_rule['id'],
            qos_policy_id,
            body={'dscp_marking_rule': {
                'dscp_mark': DSCP_MARK
            }})
        self._wait_for_dscp_marking_rule_applied(vm, DSCP_MARK)

        # Remove qos policy from port
        self.client.update_port(vm.neutron_port['id'],
                                body={'port': {
                                    'qos_policy_id': None
                                }})
        self._wait_for_dscp_marking_rule_removed(vm)

    def test_dscp_marking_packets(self):
        # Create port (vm) which will be used to received and test packets
        receiver_port = self.safe_client.create_port(
            self.tenant_id, self.network['id'],
            self.environment.hosts[1].hostname)

        receiver = self.useFixture(
            machine.FakeFullstackMachine(self.environment.hosts[1],
                                         self.network['id'],
                                         self.tenant_id,
                                         self.safe_client,
                                         neutron_port=receiver_port))

        # Create port with qos policy attached
        sender, qos_policy = self._prepare_vm_with_qos_policy(
            [functools.partial(self._add_dscp_rule, DSCP_MARK)])

        sender.block_until_boot()
        receiver.block_until_boot()

        self._wait_for_dscp_marking_rule_applied(sender, DSCP_MARK)
        l2_extensions.wait_for_dscp_marked_packet(sender, receiver, DSCP_MARK)