Merge "Adding SRIOV scenario"
authorTim Rozet <trozet@redhat.com>
Fri, 16 Mar 2018 14:22:52 +0000 (14:22 +0000)
committerGerrit Code Review <gerrit@opnfv.org>
Fri, 16 Mar 2018 14:22:52 +0000 (14:22 +0000)
apex/deploy.py
apex/overcloud/deploy.py
apex/settings/deploy_settings.py
apex/tests/test_apex_overcloud_deploy.py
build/rpm_specs/opnfv-apex-common.spec
config/deploy/deploy_settings.yaml
config/deploy/os-odl-sriov-ha.yaml [new file with mode: 0644]
config/deploy/os-odl-sriov-noha.yaml [new file with mode: 0644]
docs/release/installation/architecture.rst
lib/ansible/playbooks/configure_undercloud.yml
lib/ansible/playbooks/deploy_overcloud.yml

index 5703e08..b9267a3 100644 (file)
@@ -523,6 +523,7 @@ def main():
         deploy_vars['sfc'] = ds_opts['sfc']
         deploy_vars['vpn'] = ds_opts['vpn']
         deploy_vars['l2gw'] = ds_opts.get('l2gw')
+        deploy_vars['sriov'] = ds_opts.get('sriov')
         # TODO(trozet): pull all logs and store in tmp dir in overcloud
         # playbook
         post_overcloud = os.path.join(args.lib_dir, ANSIBLE_PATH,
index 5bbcaed..33641ed 100644 (file)
@@ -39,6 +39,7 @@ SDN_FILE_MAP = {
             'default': 'neutron-opendaylight-honeycomb.yaml'
         },
         'l2gw': 'neutron-l2gw-opendaylight.yaml',
+        'sriov': 'neutron-opendaylight-sriov.yaml',
         'default': 'neutron-opendaylight.yaml',
     },
     'onos': {
@@ -137,6 +138,9 @@ def create_deploy_cmd(ds, ns, inv, tmp_dir,
         prep_storage_env(ds, tmp_dir)
         deploy_options.append(os.path.join(con.THT_ENV_DIR,
                                            'storage-environment.yaml'))
+    if ds_opts['sriov']:
+        prep_sriov_env(ds, tmp_dir)
+
     if ds['global_params']['ha_enabled']:
         deploy_options.append(os.path.join(con.THT_ENV_DIR,
                                            'puppet-pacemaker.yaml'))
@@ -459,6 +463,13 @@ def prep_env(ds, ns, inv, opnfv_env, net_env, tmp_dir):
             elif 'ComputeServices' in line:
                 output_line = ("  ComputeServices:\n"
                                "    - OS::TripleO::Services::NeutronDhcpAgent")
+        # SRIOV networks are VLAN based provider networks. In order to simplify
+        # the deployment, nfv_sriov will be the default physnet. VLANs are not
+        # needed in advance, and the user will have to create the network
+        # specifying the segmentation-id.
+        if ds_opts['sriov']:
+            if 'NeutronNetworkVLANRanges' in line:
+                output_line = ("{},nfv_sriov'".format(line[:-1]))
 
         if perf:
             for role in 'NovaCompute', 'Controller':
@@ -569,6 +580,46 @@ def prep_storage_env(ds, tmp_dir):
             ))
 
 
+def prep_sriov_env(ds, tmp_dir):
+    """
+    Creates SRIOV environment file for deployment. Source file is copied by
+    undercloud playbook to host.
+    :param ds:
+    :param tmp_dir:
+    :return:
+    """
+    ds_opts = ds['deploy_options']
+    sriov_iface = ds_opts['sriov']
+    sriov_file = os.path.join(tmp_dir, 'neutron-opendaylight-sriov.yaml')
+    if not os.path.isfile(sriov_file):
+        logging.error("sriov-environment file is not in tmp directory: {}. "
+                      "Check if file was copied from "
+                      "undercloud".format(tmp_dir))
+        raise ApexDeployException("sriov-environment file not copied from "
+                                  "undercloud")
+    # TODO(rnoriega): Instead of line editing, refactor this code to load
+    # yaml file into a dict, edit it and write the file back.
+    for line in fileinput.input(sriov_file, inplace=True):
+        line = line.strip('\n')
+        if 'NovaSchedulerDefaultFilters' in line:
+            print("  {}".format(line[3:]))
+        elif 'NovaSchedulerAvailableFilters' in line:
+            print("  {}".format(line[3:]))
+        elif 'NeutronPhysicalDevMappings' in line:
+            print("  NeutronPhysicalDevMappings: \"nfv_sriov:{}\""
+                  .format(sriov_iface))
+        elif 'NeutronSriovNumVFs' in line:
+            print("  NeutronSriovNumVFs: \"{}:8\"".format(sriov_iface))
+        elif 'NovaPCIPassthrough' in line:
+            print("  NovaPCIPassthrough:")
+        elif 'devname' in line:
+            print("    - devname: \"{}\"".format(sriov_iface))
+        elif 'physical_network' in line:
+            print("      physical_network: \"nfv_sriov\"")
+        else:
+            print(line)
+
+
 def external_network_cmds(ns):
     """
     Generates external network openstack commands
index eec9822..c05922b 100644 (file)
@@ -24,7 +24,8 @@ REQ_DEPLOY_SETTINGS = ['sdn_controller',
                        'gluon',
                        'rt_kvm',
                        'os_version',
-                       'l2gw']
+                       'l2gw',
+                       'sriov']
 
 OPT_DEPLOY_SETTINGS = ['performance',
                        'vsperf',
@@ -116,6 +117,11 @@ class DeploySettings(dict):
                 raise DeploySettingsException(
                     "Invalid ODL version: {}".format(self[deploy_options][
                         'odl_version']))
+            elif req_set == 'sriov':
+                if self['deploy_options'][req_set] is True:
+                    raise DeploySettingsException(
+                        "Invalid SRIOV interface name: {}".format(
+                            self['deploy_options']['sriov']))
 
         if self['deploy_options']['odl_version'] == 'oxygen':
             self['deploy_options']['odl_version'] = 'master'
index 420a70d..b5b1b75 100644 (file)
@@ -25,6 +25,7 @@ from apex.overcloud.deploy import make_ssh_key
 from apex.overcloud.deploy import prep_env
 from apex.overcloud.deploy import generate_ceph_key
 from apex.overcloud.deploy import prep_storage_env
+from apex.overcloud.deploy import prep_sriov_env
 from apex.overcloud.deploy import external_network_cmds
 from apex.overcloud.deploy import create_congress_cmds
 from apex.overcloud.deploy import SDN_FILE_MAP
@@ -80,10 +81,12 @@ class TestOvercloudDeploy(unittest.TestCase):
                os.path.join(prefix, 'neutron-bgpvpn-opendaylight.yaml')]
         assert_equal(build_sdn_env_list(ds, SDN_FILE_MAP), res)
 
+    @patch('apex.overcloud.deploy.prep_sriov_env')
     @patch('apex.overcloud.deploy.prep_storage_env')
     @patch('apex.overcloud.deploy.build_sdn_env_list')
     @patch('builtins.open', mock_open())
-    def test_create_deploy_cmd(self, mock_sdn_list, mock_prep_storage):
+    def test_create_deploy_cmd(self, mock_sdn_list, mock_prep_storage,
+                               mock_prep_sriov):
         mock_sdn_list.return_value = []
         ds = {'deploy_options': MagicMock(),
               'global_params': MagicMock()}
@@ -106,11 +109,12 @@ class TestOvercloudDeploy(unittest.TestCase):
         assert_in('--control-scale 3', result_cmd)
         assert_in('--compute-scale 2', result_cmd)
 
+    @patch('apex.overcloud.deploy.prep_sriov_env')
     @patch('apex.overcloud.deploy.prep_storage_env')
     @patch('apex.overcloud.deploy.build_sdn_env_list')
     @patch('builtins.open', mock_open())
     def test_create_deploy_cmd_no_ha_bm(self, mock_sdn_list,
-                                        mock_prep_storage):
+                                        mock_prep_storage, mock_prep_sriov):
         mock_sdn_list.return_value = []
         ds = {'deploy_options': MagicMock(),
               'global_params': MagicMock()}
@@ -129,9 +133,11 @@ class TestOvercloudDeploy(unittest.TestCase):
         assert_not_in('enable_congress.yaml', result_cmd)
         assert_not_in('enable_barometer.yaml', result_cmd)
 
+    @patch('apex.overcloud.deploy.prep_sriov_env')
     @patch('apex.overcloud.deploy.prep_storage_env')
     @patch('apex.overcloud.deploy.build_sdn_env_list')
-    def test_create_deploy_cmd_raises(self, mock_sdn_list, mock_prep_storage):
+    def test_create_deploy_cmd_raises(self, mock_sdn_list, mock_prep_storage,
+                                      mock_prep_sriov):
         mock_sdn_list.return_value = []
         ds = {'deploy_options': MagicMock(),
               'global_params': MagicMock()}
@@ -251,6 +257,7 @@ class TestOvercloudDeploy(unittest.TestCase):
               {'sdn_controller': 'opendaylight',
                'odl_vpp_routing_node': 'test',
                'dataplane': 'ovs_dpdk',
+               'sriov': 'xxx',
                'performance': {'Compute': {'vpp': {'main-core': 'test',
                                                    'corelist-workers': 'test'},
                                            'ovs': {'dpdk_cores': 'test'},
@@ -293,6 +300,7 @@ class TestOvercloudDeploy(unittest.TestCase):
         ds = {'deploy_options':
               {'sdn_controller': False,
                'dataplane': 'fdio',
+               'sriov': 'xxx',
                'performance': {'Compute': {},
                                'Controller': {}}}}
         ns = {'domain_name': 'test.domain',
@@ -332,6 +340,7 @@ class TestOvercloudDeploy(unittest.TestCase):
         ds = {'deploy_options':
               {'sdn_controller': 'opendaylight',
                'dataplane': 'fdio',
+               'sriov': 'xxx',
                'dvr': True}}
         ns = {'domain_name': 'test.domain',
               'networks':
@@ -385,6 +394,52 @@ class TestOvercloudDeploy(unittest.TestCase):
         ds = {'deploy_options': MagicMock()}
         assert_raises(ApexDeployException, prep_storage_env, ds, '/tmp')
 
+    @patch('apex.overcloud.deploy.generate_ceph_key')
+    @patch('apex.overcloud.deploy.fileinput')
+    @patch('apex.overcloud.deploy.os.path.isfile')
+    @patch('builtins.open', mock_open())
+    def test_prep_sriov_env(self, mock_isfile, mock_fileinput, mock_ceph_key):
+        ds = {'deploy_options':
+              {'sdn_controller': 'opendaylight',
+               'sriov': 'xxx'}}
+        try:
+            # Swap stdout
+            saved_stdout = sys.stdout
+            out = StringIO()
+            sys.stdout = out
+            # Run tests
+            mock_fileinput.input.return_value = \
+                ['#  NovaSchedulerDefaultFilters',
+                 '#  NovaSchedulerAvailableFilters',
+                 '#NeutronPhysicalDevMappings: "datacentre:ens20f2"',
+                 '#NeutronSriovNumVFs: \"ens20f2:5\"',
+                 '#NovaPCIPassthrough:',
+                 '#  - devname: \"ens20f2\"',
+                 '#    physical_network: \"datacentre\"']
+            prep_sriov_env(ds, '/tmp')
+            output = out.getvalue().strip()
+            assert_in('NovaSchedulerDefaultFilters', output)
+            assert_in('NovaSchedulerAvailableFilters', output)
+            assert_in('NeutronPhysicalDevMappings: \"nfv_sriov:xxx\"', output)
+            assert_in('NeutronSriovNumVFs: \"xxx:8\"', output)
+            assert_in('NovaPCIPassthrough:', output)
+            assert_in('- devname: \"xxx\"', output)
+            assert_in('physical_network: \"nfv_sriov\"', output)
+        finally:
+            # put stdout back
+            sys.stdout = saved_stdout
+
+    @patch('apex.overcloud.deploy.os.path.isfile')
+    @patch('builtins.open', mock_open())
+    def test_prep_sriov_env_raises(self, mock_isfile):
+        ds_opts = {'sriov': True}
+        ds = {'deploy_options': MagicMock()}
+        ds['deploy_options'].__getitem__.side_effect = \
+            lambda i: ds_opts.get(i, MagicMock())
+        mock_isfile.return_value = False
+        ds = {'deploy_options': MagicMock()}
+        assert_raises(ApexDeployException, prep_sriov_env, ds, '/tmp')
+
     def test_external_network_cmds(self):
         cidr = MagicMock()
         cidr.version = 6
index f8226e4..124f252 100644 (file)
@@ -98,6 +98,8 @@ install config/inventory/pod_example_settings.yaml %{buildroot}%{_docdir}/opnfv/
 %{_sysconfdir}/opnfv-apex/os-odl-ovs_dpdk-ha.yaml
 %{_sysconfdir}/opnfv-apex/os-odl-nofeature-ha.yaml
 %{_sysconfdir}/opnfv-apex/os-odl-nofeature-noha.yaml
+%{_sysconfdir}/opnfv-apex/os-odl-sriov-ha.yaml
+%{_sysconfdir}/opnfv-apex/os-odl-sriov-noha.yaml
 %{_sysconfdir}/opnfv-apex/os-odl-gluon-noha.yaml
 %{_sysconfdir}/opnfv-apex/os-ovn-nofeature-noha.yaml
 %{_sysconfdir}/opnfv-apex/os-onos-nofeature-ha.yaml
index ab3b0a3..a6721b4 100644 (file)
@@ -52,6 +52,11 @@ deploy_options:
   # The dataplane should be specified as fdio if this is set to true
   vpp: false
 
+  # Whether to install and configure SRIOV service in the compute node(s) to
+  # allow VMs to use VFs/PFs. The user must know in advance the name of the
+  # SRIOV capable NIC that will be configured.
+  sriov: em2
+
   # Whether to run vsperf after the install has completed
   # vsperf: false
 
diff --git a/config/deploy/os-odl-sriov-ha.yaml b/config/deploy/os-odl-sriov-ha.yaml
new file mode 100644 (file)
index 0000000..03e34a2
--- /dev/null
@@ -0,0 +1,21 @@
+---
+global_params:
+  ha_enabled: true
+
+deploy_options:
+  sdn_controller: opendaylight
+  odl_version: nitrogen
+  tacker: true
+  congress: true
+  sfc: false
+  vpn: false
+  sriov: em2
+  performance:
+    Controller:
+      kernel:
+    Compute:
+      kernel:
+        hugepagesz: 2M
+        hugepages: 2048
+        intel_iommu: 'on'
+        iommu: pt
diff --git a/config/deploy/os-odl-sriov-noha.yaml b/config/deploy/os-odl-sriov-noha.yaml
new file mode 100644 (file)
index 0000000..52b5aa1
--- /dev/null
@@ -0,0 +1,21 @@
+---
+global_params:
+  ha_enabled: false
+
+deploy_options:
+  sdn_controller: opendaylight
+  odl_version: nitrogen
+  tacker: true
+  congress: true
+  sfc: false
+  vpn: false
+  sriov: em2
+  performance:
+    Controller:
+      kernel:
+    Compute:
+      kernel:
+        hugepagesz: 2M
+        hugepages: 2048
+        intel_iommu: 'on'
+        iommu: pt
index b8db7c8..70067ed 100644 (file)
@@ -159,11 +159,15 @@ issues per scenario.  The following scenarios correspond to a supported
 | os-odl-bgpvpn-ha        | SDNVPN      | Yes           |
 +-------------------------+-------------+---------------+
 | os-odl-bgpvpn-noha      | SDNVPN      | Yes           |
-++-------------------------+-------------+---------------+
++-------------------------+-------------+---------------+
+| os-odl-sriov-ha         | Apex        | No            |
++-------------------------+-------------+---------------+
+| os-odl-sriov-noha       | Apex        | No            |
++-------------------------+-------------+---------------+
 | os-odl-l2gw-ha          | Apex        | No            |
 +-------------------------+-------------+---------------+
 | os-odl-l2gw-noha        | Apex        | No            |
--------------------------+-------------+---------------+
++-------------------------+-------------+---------------+
 | os-odl-sfc-ha           | SFC         | No            |
 +-------------------------+-------------+---------------+
 | os-odl-sfc-noha         | SFC         | Yes           |
index e9ce875..9ef0d88 100644 (file)
         src: /usr/share/openstack-tripleo-heat-templates/environments/storage-environment.yaml
         dest: "{{ apex_temp_dir }}/"
         flat: yes
+    - name: fetch sriov environment file
+      fetch:
+        src: /usr/share/openstack-tripleo-heat-templates/environments/neutron-opendaylight-sriov.yaml
+        dest: "{{ apex_temp_dir }}/"
+        flat: yes
 
 - include: undercloud_aarch64.yml
   when: aarch64
index aa3d806..268a517 100644 (file)
         owner: root
         group: root
         mode: 0664
+    - copy:
+        src: "{{ apex_temp_dir }}/neutron-opendaylight-sriov.yaml"
+        dest: /usr/share/openstack-tripleo-heat-templates/environments/neutron-opendaylight-sriov.yaml
+        owner: root
+        group: root
+        mode: 0664
     - systemd:
         name: openstack-swift-proxy
         state: restarted