Add SRIOV support 31/36631/1
authorJing Zhang <jing.c.zhang@nokia.com>
Fri, 31 Mar 2017 13:20:46 +0000 (09:20 -0400)
committerJing Lu <lvjing5@huawei.com>
Wed, 28 Jun 2017 08:53:33 +0000 (08:53 +0000)
A generic provider network solution is introduced. To identify whether a network specified in the test case is a provider network new attributes are introduced in the test case network section:

networks:
  test-net:
    cidr: '192.168.1.0/24'
    provider: "sriov"
    physical_network: 'physnet1'

If the "provider" attribute is present, the network is an existing provider network. If the value is "sriov", binding:vnic_type=direct is added to the interface in the heat deployment template. In orchestrator/heat.py, the interface creating functions are given a new parameter that tells if the network in use is a provider network. The benchmark/contexts/model.py is changed to store the value of the provider attribute from the test case and function calls to port creation is updated with the provider parameter. The same change is made in contexts/heat.py as well. Also calls for creating a new tenant network is replaced for creating a new provider network if the provider attribute is present.

Update-1: Change test_model.py
Update-2: Per comment, change comment style to """"
Update-3: Change test_heat.py
Update-4: Add unit test cases to pass coverage test
Update-5: Add SRIOV provider network example in opnfv_yardstick_tc008.yaml
Update-6: Per comment, remove empty line in orchestrator/test_heat.py
Update-7: Per comment, change comment lines in orchestrator/test_heat.py
Update-8: Add more unit test cases to pass coverage test
Update-9: Change to create SRIOV provider network on the fly so as to support co-current test runs
Update-10: Per comment, init physical_network to 'physnet1'

Change-Id: I76004c4fcc9bffcfd8ed021fd647e0cecb346ef4
JIRA: YARDSTICK-612
Signed-off-by: Jing Zhang <jing.c.zhang@nokia.com>
(cherry picked from commit f51ba41255d6ab2c03fd62a044d372b73b496459)

tests/opnfv/test_cases/opnfv_yardstick_tc008.yaml
tests/unit/benchmark/contexts/test_heat.py
tests/unit/benchmark/contexts/test_model.py
tests/unit/orchestrator/__init__.py [new file with mode: 0644]
tests/unit/orchestrator/test_heat.py
yardstick/benchmark/contexts/heat.py
yardstick/benchmark/contexts/model.py
yardstick/orchestrator/heat.py

index a980234..4c7fdab 100644 (file)
@@ -65,3 +65,6 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
+    #test-sriov:
+      #cidr: '10.0.1.0/24'
+      #provider: "sriov"
index 8f4852c..b56d0c8 100644 (file)
@@ -21,6 +21,7 @@ import uuid
 import mock
 
 from yardstick.benchmark.contexts import heat
+from yardstick.benchmark.contexts import model
 
 
 LOG = logging.getLogger(__name__)
@@ -102,12 +103,18 @@ class HeatContextTestCase(unittest.TestCase):
         self.test_context.keypair_name = "foo-key"
         self.test_context.secgroup_name = "foo-secgroup"
         self.test_context.key_uuid = "2f2e4997-0a8e-4eb7-9fa4-f3f8fbbc393b"
+        netattrs = {'cidr': '10.0.0.0/24', 'provider': None, 'external_network': 'ext_net'}
+        self.mock_context.name = 'bar'
+        self.test_context.networks = [model.Network("fool-network", self.mock_context, netattrs)]
 
         self.test_context._add_resources_to_template(mock_template)
         mock_template.add_keypair.assert_called_with(
             "foo-key",
             "2f2e4997-0a8e-4eb7-9fa4-f3f8fbbc393b")
         mock_template.add_security_group.assert_called_with("foo-secgroup")
+        mock_template.add_network.assert_called_with("bar-fool-network", 'physnet1', None)
+        mock_template.add_router.assert_called_with("bar-fool-network-router", netattrs["external_network"], "bar-fool-network-subnet")
+        mock_template.add_router_interface.assert_called_with("bar-fool-network-router-if0", "bar-fool-network-router", "bar-fool-network-subnet")
 
     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
     def test_deploy(self, mock_template):
index a4b7d81..dd52680 100644 (file)
@@ -170,6 +170,9 @@ class ServerTestCase(unittest.TestCase):
         self.mock_context.keypair_name = 'some-keys'
         self.mock_context.secgroup_name = 'some-secgroup'
         self.mock_context.user = "some-user"
+        netattrs = {'cidr': '10.0.0.0/24', 'provider': None, 'external_network': 'ext_net'}
+        self.mock_context.networks = [model.Network("some-network", self.mock_context, netattrs)]
+
 
     def test_construct_defaults(self):
 
@@ -208,13 +211,16 @@ class ServerTestCase(unittest.TestCase):
     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
     def test__add_instance(self, mock_template):
 
-        attrs = {'image': 'some-image', 'flavor': 'some-flavor'}
+        attrs = {'image': 'some-image', 'flavor': 'some-flavor', 'floating_ip': '192.168.1.10', 'floating_ip_assoc': 'some-vm'}
         test_server = model.Server('foo', self.mock_context, attrs)
 
         mock_network = mock.Mock()
         mock_network.name = 'some-network'
         mock_network.stack_name = 'some-network-stack'
         mock_network.subnet_stack_name = 'some-network-stack-subnet'
+        mock_network.provider = 'sriov'
+        mock_network.external_network = 'ext_net'
+        mock_network.router = model.Router('some-router', 'some-network', self.mock_context, 'ext_net')
 
         test_server._add_instance(mock_template, 'some-server',
                                   [mock_network], 'hints')
@@ -223,7 +229,22 @@ class ServerTestCase(unittest.TestCase):
             'some-server-some-network-port',
             mock_network.stack_name,
             mock_network.subnet_stack_name,
-            sec_group_id=self.mock_context.secgroup_name)
+            sec_group_id=self.mock_context.secgroup_name,
+            provider=mock_network.provider)
+
+        mock_template.add_floating_ip.assert_called_with(
+            'some-server-fip',
+            mock_network.external_network,
+            'some-server-some-network-port',
+            'bar-some-network-some-router-if0',
+            'some-secgroup'
+        )
+
+        mock_template.add_floating_ip_association.assert_called_with(
+            'some-server-fip-assoc',
+            'some-server-fip',
+            'some-server-some-network-port'
+        )
 
         mock_template.add_server.assert_called_with(
             'some-server', 'some-image', 'some-flavor',
diff --git a/tests/unit/orchestrator/__init__.py b/tests/unit/orchestrator/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
index 97314c2..2f9c800 100644 (file)
@@ -13,6 +13,7 @@
 
 import unittest
 import uuid
+import mock
 
 from yardstick.orchestrator import heat
 
@@ -24,3 +25,61 @@ class HeatContextTestCase(unittest.TestCase):
         k = heat.get_short_key_uuid(u)
         self.assertEqual(heat.HEAT_KEY_UUID_LENGTH, len(k))
         self.assertIn(k, str(u))
+
+class HeatTemplateTestCase(unittest.TestCase):
+
+    def setUp(self):
+        self.template = heat.HeatTemplate('test')
+
+    def test_add_tenant_network(self):
+        self.template.add_network('some-network')
+
+        self.assertEqual(self.template.resources['some-network']['type'], 'OS::Neutron::Net')
+
+    def test_add_provider_network(self):
+        self.template.add_network('some-network', 'physnet2', 'sriov')
+
+        self.assertEqual(self.template.resources['some-network']['type'], 'OS::Neutron::ProviderNet')
+        self.assertEqual(self.template.resources['some-network']['properties']['physical_network'], 'physnet2')
+
+    def test_add_subnet(self):
+        netattrs = {'cidr': '10.0.0.0/24', 'provider': None, 'external_network': 'ext_net'}
+        self.template.add_subnet('some-subnet', "some-network", netattrs['cidr'])
+
+        self.assertEqual(self.template.resources['some-subnet']['type'], 'OS::Neutron::Subnet')
+        self.assertEqual(self.template.resources['some-subnet']['properties']['cidr'], '10.0.0.0/24')
+
+    def test_add_router(self):
+        self.template.add_router('some-router', 'ext-net', 'some-subnet')
+
+        self.assertEqual(self.template.resources['some-router']['type'], 'OS::Neutron::Router')
+        self.assertIn('some-subnet', self.template.resources['some-router']['depends_on'])
+
+    def test_add_router_interface(self):
+        self.template.add_router_interface('some-router-if', 'some-router', 'some-subnet')
+
+        self.assertEqual(self.template.resources['some-router-if']['type'], 'OS::Neutron::RouterInterface')
+        self.assertIn('some-subnet', self.template.resources['some-router-if']['depends_on'])
+
+    def test_add_servergroup(self):
+        self.template.add_servergroup('some-server-group', 'anti-affinity')
+
+        self.assertEqual(self.template.resources['some-server-group']['type'], 'OS::Nova::ServerGroup')
+        self.assertEqual(self.template.resources['some-server-group']['properties']['policies'], ['anti-affinity'])
+
+class HeatStackTestCase(unittest.TestCase):
+
+    def test_delete_calls__delete_multiple_times(self):
+        stack = heat.HeatStack('test')
+        stack.uuid = 1
+        with mock.patch.object(stack, "_delete") as delete_mock:
+            stack.delete()
+        # call once and then call again if uuid is not none
+        self.assertGreater(delete_mock.call_count, 1)
+
+    def test_delete_all_calls_delete(self):
+        stack = heat.HeatStack('test')
+        stack.uuid = 1
+        with mock.patch.object(stack, "delete") as delete_mock:
+            stack.delete_all()
+        self.assertGreater(delete_mock.call_count, 0)
index 604df80..d5dccd2 100644 (file)
@@ -133,8 +133,11 @@ class HeatContext(Context):
         template.add_security_group(self.secgroup_name)
 
         for network in self.networks:
-            template.add_network(network.stack_name)
-            template.add_subnet(network.subnet_stack_name, network.stack_name,
+            template.add_network(network.stack_name,
+                                 network.physical_network,
+                                 network.provider)
+            template.add_subnet(network.subnet_stack_name,
+                                network.stack_name,
                                 network.subnet_cidr)
 
             if network.router:
index 8cf3b62..0aabfad 100644 (file)
@@ -105,6 +105,8 @@ class Network(Object):
         self.subnet_stack_name = self.stack_name + "-subnet"
         self.subnet_cidr = attrs.get('cidr', '10.0.1.0/24')
         self.router = None
+        self.physical_network = attrs.get('physical_network', 'physnet1')
+        self.provider = attrs.get('provider', None)
 
         if "external_network" in attrs:
             self.router = Router("router", self.name,
@@ -226,7 +228,8 @@ class Server(Object):     # pragma: no cover
             self.ports[network.name] = {"stack_name": port_name}
             template.add_port(port_name, network.stack_name,
                               network.subnet_stack_name,
-                              sec_group_id=self.secgroup_name)
+                              sec_group_id=self.secgroup_name,
+                              provider=network.provider)
             port_name_list.append(port_name)
 
             if self.floating_ip:
index 500776e..357e8cc 100644 (file)
@@ -32,6 +32,8 @@ log = logging.getLogger(__name__)
 
 HEAT_KEY_UUID_LENGTH = 8
 
+PROVIDER_SRIOV = "sriov"
+
 
 def get_short_key_uuid(uuid):
     return str(uuid)[:HEAT_KEY_UUID_LENGTH]
@@ -189,13 +191,23 @@ class HeatTemplate(HeatObject):
 
         log.debug("template object '%s' created", name)
 
-    def add_network(self, name):
+    def add_network(self, name, physical_network='physnet1', provider=None):
         """add to the template a Neutron Net"""
         log.debug("adding Neutron::Net '%s'", name)
-        self.resources[name] = {
-            'type': 'OS::Neutron::Net',
-            'properties': {'name': name}
-        }
+        if provider is None:
+            self.resources[name] = {
+                'type': 'OS::Neutron::Net',
+                'properties': {'name': name}
+            }
+        else:
+            self.resources[name] = {
+                'type': 'OS::Neutron::ProviderNet',
+                'properties': {
+                    'name': name,
+                    'network_type': 'vlan',
+                    'physical_network': physical_network
+                }
+            }
 
     def add_server_group(self, name, policies):     # pragma: no cover
         """add to the template a ServerGroup"""
@@ -229,7 +241,6 @@ class HeatTemplate(HeatObject):
     def add_router(self, name, ext_gw_net, subnet_name):
         """add to the template a Neutron Router and interface"""
         log.debug("adding Neutron::Router:'%s', gw-net:'%s'", name, ext_gw_net)
-
         self.resources[name] = {
             'type': 'OS::Neutron::Router',
             'depends_on': [subnet_name],
@@ -245,7 +256,6 @@ class HeatTemplate(HeatObject):
         """add to the template a Neutron RouterInterface and interface"""
         log.debug("adding Neutron::RouterInterface '%s' router:'%s', "
                   "subnet:'%s'", name, router_name, subnet_name)
-
         self.resources[name] = {
             'type': 'OS::Neutron::RouterInterface',
             'depends_on': [router_name, subnet_name],
@@ -255,7 +265,8 @@ class HeatTemplate(HeatObject):
             }
         }
 
-    def add_port(self, name, network_name, subnet_name, sec_group_id=None):
+    def add_port(self, name, network_name, subnet_name, sec_group_id=None,
+                 provider=None):
         """add to the template a named Neutron Port"""
         log.debug("adding Neutron::Port '%s', network:'%s', subnet:'%s', "
                   "secgroup:%s", name, network_name, subnet_name, sec_group_id)
@@ -270,6 +281,10 @@ class HeatTemplate(HeatObject):
             }
         }
 
+        if provider == PROVIDER_SRIOV:
+            self.resources[name]['properties']['binding:vnic_type'] = \
+                'direct'
+
         if sec_group_id:
             self.resources[name]['depends_on'].append(sec_group_id)
             self.resources[name]['properties']['security_groups'] = \