From: Ihar Hrachyshka Date: Wed, 5 Aug 2015 15:15:40 +0000 (+0200) Subject: Merge remote-tracking branch 'origin/feature/qos' into merge-branch X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=cc0ae6dd49da3e67c1d0400bc422e735c27e98fb;p=openstack-build%2Fneutron-build.git Merge remote-tracking branch 'origin/feature/qos' into merge-branch Change-Id: I683102e617202e0ffc953a0d3cc179879f8faf82 --- cc0ae6dd49da3e67c1d0400bc422e735c27e98fb diff --cc etc/neutron.conf index ca3baa9cf,29a4095f8..52ca260a5 mode 100644,100755..100644 --- a/etc/neutron.conf +++ b/etc/neutron.conf diff --cc neutron/cmd/sanity/checks.py index 37f0947f2,c3ef8a3c9..659c02e67 --- a/neutron/cmd/sanity/checks.py +++ b/neutron/cmd/sanity/checks.py @@@ -127,9 -127,10 +127,11 @@@ def arp_header_match_supported() def vf_management_supported(): + is_supported = True required_caps = ( ip_link_support.IpLinkConstants.IP_LINK_CAPABILITY_STATE, - ip_link_support.IpLinkConstants.IP_LINK_CAPABILITY_SPOOFCHK) ++ ip_link_support.IpLinkConstants.IP_LINK_CAPABILITY_SPOOFCHK, + ip_link_support.IpLinkConstants.IP_LINK_CAPABILITY_RATE) try: vf_section = ip_link_support.IpLinkSupport.get_vf_mgmt_section() for cap in required_caps: diff --cc neutron/db/migration/alembic_migrations/versions/liberty/expand/48153cb5f051_qos_db_changes.py index 000000000,940b4def5..99f4f1f12 mode 000000,100755..100755 --- a/neutron/db/migration/alembic_migrations/versions/liberty/expand/48153cb5f051_qos_db_changes.py +++ b/neutron/db/migration/alembic_migrations/versions/liberty/expand/48153cb5f051_qos_db_changes.py @@@ -1,0 -1,69 +1,69 @@@ + # Copyright 2015 Huawei Technologies India Pvt Ltd, Inc + # + # 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. + # + + """qos db changes + + Revision ID: 48153cb5f051 -Revises: 8675309a5c4f ++Revises: 1c844d1677f7 + Create Date: 2015-06-24 17:03:34.965101 + + """ + + # revision identifiers, used by Alembic. + revision = '48153cb5f051' -down_revision = '8675309a5c4f' ++down_revision = '1c844d1677f7' + + from alembic import op + import sqlalchemy as sa + + from neutron.api.v2 import attributes as attrs + + + def upgrade(): + op.create_table( + 'qos_policies', + sa.Column('id', sa.String(length=36), primary_key=True), + sa.Column('name', sa.String(length=attrs.NAME_MAX_LEN)), + sa.Column('description', sa.String(length=attrs.DESCRIPTION_MAX_LEN)), + sa.Column('shared', sa.Boolean(), nullable=False), + sa.Column('tenant_id', sa.String(length=attrs.TENANT_ID_MAX_LEN), + index=True)) + + op.create_table( + 'qos_network_policy_bindings', + sa.Column('policy_id', sa.String(length=36), + sa.ForeignKey('qos_policies.id', ondelete='CASCADE'), + nullable=False), + sa.Column('network_id', sa.String(length=36), + sa.ForeignKey('networks.id', ondelete='CASCADE'), + nullable=False, unique=True)) + + op.create_table( + 'qos_port_policy_bindings', + sa.Column('policy_id', sa.String(length=36), + sa.ForeignKey('qos_policies.id', ondelete='CASCADE'), + nullable=False), + sa.Column('port_id', sa.String(length=36), + sa.ForeignKey('ports.id', ondelete='CASCADE'), + nullable=False, unique=True)) + + op.create_table( + 'qos_bandwidth_limit_rules', + sa.Column('id', sa.String(length=36), primary_key=True), + sa.Column('qos_policy_id', sa.String(length=36), + sa.ForeignKey('qos_policies.id', ondelete='CASCADE'), + nullable=False, unique=True), + sa.Column('max_kbps', sa.Integer()), + sa.Column('max_burst_kbps', sa.Integer())) diff --cc neutron/db/migration/models/head.py index 8680b06a4,85aaa6882..3c3da37b3 --- a/neutron/db/migration/models/head.py +++ b/neutron/db/migration/models/head.py @@@ -41,7 -41,8 +41,8 @@@ from neutron.db import model_bas from neutron.db import models_v2 # noqa from neutron.db import portbindings_db # noqa from neutron.db import portsecurity_db # noqa + from neutron.db.qos import models as qos_models # noqa -from neutron.db import quota_db # noqa +from neutron.db.quota import models # noqa from neutron.db import rbac_db_models # noqa from neutron.db import securitygroups_db # noqa from neutron.db import servicetype_db # noqa diff --cc neutron/plugins/ml2/drivers/mech_sriov/agent/pci_lib.py index 3e7ec1b14,723e4b43d..a1e31cd66 --- a/neutron/plugins/ml2/drivers/mech_sriov/agent/pci_lib.py +++ b/neutron/plugins/ml2/drivers/mech_sriov/agent/pci_lib.py @@@ -106,22 -106,21 +106,37 @@@ class PciDeviceIPWrapper(ip_lib.IPWrapp raise exc.IpCommandError(dev_name=self.dev_name, reason=e) + def set_vf_spoofcheck(self, vf_index, enabled): + """sets vf spoofcheck + + @param vf_index: vf index + @param enabled: True to enable spoof checking, + False to disable + """ + setting = "on" if enabled else "off" + + try: + self._as_root('', "link", ("set", self.dev_name, "vf", + str(vf_index), "spoofchk", setting)) + except Exception as e: + raise exc.IpCommandError(dev_name=self.dev_name, + reason=str(e)) + + def set_vf_max_rate(self, vf_index, max_tx_rate): + """sets vf max rate. + + @param vf_index: vf index + @param max_tx_rate: vf max tx rate + """ + try: + self._as_root([], "link", ("set", self.dev_name, "vf", + str(vf_index), "rate", + str(max_tx_rate))) + except Exception as e: + LOG.exception(_LE("Failed executing ip command")) + raise exc.IpCommandError(dev_name=self.dev_name, + reason=e) + def _get_vf_link_show(self, vf_list, link_show_out): """Get link show output for VFs diff --cc neutron/plugins/ml2/plugin.py index 7bcf39378,aeaf68733..55addebe1 --- a/neutron/plugins/ml2/plugin.py +++ b/neutron/plugins/ml2/plugin.py @@@ -75,7 -75,7 +76,8 @@@ from neutron.plugins.ml2 import driver_ from neutron.plugins.ml2 import managers from neutron.plugins.ml2 import models from neutron.plugins.ml2 import rpc +from neutron.quota import resource_registry + from neutron.services.qos import qos_consts LOG = log.getLogger(__name__) diff --cc neutron/tests/api/base.py index 6de006163,30d00b8d6..b8981147a --- a/neutron/tests/api/base.py +++ b/neutron/tests/api/base.py @@@ -85,6 -87,9 +85,8 @@@ class BaseNetworkTest(neutron.tests.tem cls.metering_label_rules = [] cls.fw_rules = [] cls.fw_policies = [] - cls.ipsecpolicies = [] + cls.qos_rules = [] + cls.qos_policies = [] cls.ethertype = "IPv" + str(cls._ip_version) cls.address_scopes = [] cls.admin_address_scopes = [] @@@ -100,6 -109,22 +102,14 @@@ for fw_rule in cls.fw_rules: cls._try_delete_resource(cls.client.delete_firewall_rule, fw_rule['id']) + # Clean up QoS policies + for qos_policy in cls.qos_policies: + cls._try_delete_resource(cls.admin_client.delete_qos_policy, + qos_policy['id']) + # Clean up QoS rules + for qos_rule in cls.qos_rules: + cls._try_delete_resource(cls.admin_client.delete_qos_rule, + qos_rule['id']) - # Clean up ike policies - for ikepolicy in cls.ikepolicies: - cls._try_delete_resource(cls.client.delete_ikepolicy, - ikepolicy['id']) - # Clean up vpn services - for vpnservice in cls.vpnservices: - cls._try_delete_resource(cls.client.delete_vpnservice, - vpnservice['id']) # Clean up floating IPs for floating_ip in cls.floating_ips: cls._try_delete_resource(cls.client.delete_floatingip, diff --cc neutron/tests/unit/plugins/ml2/drivers/mech_sriov/agent/test_pci_lib.py index 67ef92de2,38e0eac06..5512ea95f --- a/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/agent/test_pci_lib.py +++ b/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/agent/test_pci_lib.py @@@ -111,6 -96,23 +111,23 @@@ class TestPciLib(base.BaseTestCase) "_execute") as mock_exec: mock_exec.side_effect = Exception() self.assertRaises(exc.IpCommandError, - self.pci_wrapper.set_vf_state, + self.pci_wrapper.set_vf_spoofcheck, self.VF_INDEX, True) + + def test_set_vf_max_rate(self): + with mock.patch.object(self.pci_wrapper, "_as_root") \ + as mock_as_root: + result = self.pci_wrapper.set_vf_max_rate(self.VF_INDEX, 1000) + self.assertIsNone(result) + mock_as_root.assert_called_once_with([], "link", + ("set", self.DEV_NAME, "vf", str(self.VF_INDEX), "rate", '1000')) + + def test_set_vf_max_rate_fail(self): + with mock.patch.object(self.pci_wrapper, + "_execute") as mock_exec: + mock_exec.side_effect = Exception() + self.assertRaises(exc.IpCommandError, + self.pci_wrapper.set_vf_max_rate, + self.VF_INDEX, + 1000) diff --cc neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py index 26a9a30b8,301a5cf5f..f1e718434 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py @@@ -402,6 -380,28 +402,29 @@@ class TestOvsNeutronAgent(object) self.assertTrue(self._mock_treat_devices_added_updated( details, mock.Mock(), 'treat_vif_port')) + def test_treat_devices_added_updated_sends_vif_port_into_extension_manager( + self, *args): + details = mock.MagicMock() + details.__contains__.side_effect = lambda x: True + port = mock.MagicMock() + + def fake_handle_port(context, port): + self.assertIn('vif_port', port) + + with mock.patch.object(self.agent.plugin_rpc, - 'get_devices_details_list', - return_value=[details]),\ ++ 'get_devices_details_list_and_failed_devices', ++ return_value={'devices': [details], ++ 'failed_devices': None}),\ + mock.patch.object(self.agent.agent_extensions_mgr, + 'handle_port', new=fake_handle_port),\ + mock.patch.object(self.agent.int_br, + 'get_vifs_by_ids', + return_value={details['device']: port}),\ + mock.patch.object(self.agent, 'treat_vif_port', + return_value=False): + + self.agent.treat_devices_added_or_updated([{}], False) + def test_treat_devices_added_updated_skips_if_port_not_found(self): dev_mock = mock.MagicMock() dev_mock.__getitem__.return_value = 'the_skipped_one' diff --cc neutron/tests/unit/plugins/ml2/test_rpc.py index 72775b9fe,e039c9261..5e79eb761 --- a/neutron/tests/unit/plugins/ml2/test_rpc.py +++ b/neutron/tests/unit/plugins/ml2/test_rpc.py @@@ -135,7 -135,35 +136,35 @@@ class RpcCallbacksTestCase(base.BaseTes self.callbacks.get_device_details(mock.Mock()) self.assertTrue(self.plugin.update_port_status.called) + def test_get_device_details_qos_policy_id_none(self): + port = collections.defaultdict(lambda: 'fake_port') + self.plugin.get_bound_port_context().current = port + self.plugin.get_bound_port_context().network._network = ( + {"id": "fake_network"}) + res = self.callbacks.get_device_details(mock.Mock(), host='fake') + self.assertIsNone(res['qos_policy_id']) + + def test_get_device_details_qos_policy_id_inherited_from_network(self): + port = collections.defaultdict(lambda: 'fake_port') + self.plugin.get_bound_port_context().current = port + self.plugin.get_bound_port_context().network._network = ( + {"id": "fake_network", + qos_consts.QOS_POLICY_ID: 'test-policy-id'}) + res = self.callbacks.get_device_details(mock.Mock(), host='fake') + self.assertEqual('test-policy-id', res['qos_policy_id']) + + def test_get_device_details_qos_policy_id_taken_from_port(self): + port = collections.defaultdict( + lambda: 'fake_port', + {qos_consts.QOS_POLICY_ID: 'test-port-policy-id'}) + self.plugin.get_bound_port_context().current = port + self.plugin.get_bound_port_context().network._network = ( + {"id": "fake_network", + qos_consts.QOS_POLICY_ID: 'test-net-policy-id'}) + res = self.callbacks.get_device_details(mock.Mock(), host='fake') + self.assertEqual('test-port-policy-id', res['qos_policy_id']) + - def test_get_devices_details_list(self): + def _test_get_devices_list(self, callback, side_effect, expected): devices = [1, 2, 3, 4, 5] kwargs = {'host': 'fake_host', 'agent_id': 'fake_agent_id'} with mock.patch.object(self.callbacks, 'get_device_details', diff --cc setup.cfg index 9cda3e8d2,b3a3608a4..739063a63 --- a/setup.cfg +++ b/setup.cfg @@@ -187,6 -196,8 +190,7 @@@ neutron.ml2.extension_drivers test = neutron.tests.unit.plugins.ml2.drivers.ext_test:TestExtensionDriver testdb = neutron.tests.unit.plugins.ml2.drivers.ext_test:TestDBExtensionDriver port_security = neutron.plugins.ml2.extensions.port_security:PortSecurityExtensionDriver - cisco_n1kv_ext = neutron.plugins.ml2.drivers.cisco.n1kv.n1kv_ext_driver:CiscoN1kvExtensionDriver + qos = neutron.plugins.ml2.extensions.qos:QosExtensionDriver neutron.openstack.common.cache.backends = memory = neutron.openstack.common.cache._backends.memory:MemoryBackend neutron.ipam_drivers =