From: Tim Rozet Date: Fri, 16 Mar 2018 14:22:52 +0000 (+0000) Subject: Merge "Adding SRIOV scenario" X-Git-Tag: opnfv-6.0.0~17 X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=commitdiff_plain;h=a008f8394e07f1b82d5bf7288f46c63252f6084f;hp=29367db39d60da9ba839e0ee2254b164fd43e2a1;p=apex.git Merge "Adding SRIOV scenario" --- diff --git a/apex/deploy.py b/apex/deploy.py index 5703e081..b9267a3c 100644 --- a/apex/deploy.py +++ b/apex/deploy.py @@ -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, diff --git a/apex/overcloud/deploy.py b/apex/overcloud/deploy.py index 5bbcaede..33641ed5 100644 --- a/apex/overcloud/deploy.py +++ b/apex/overcloud/deploy.py @@ -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 diff --git a/apex/settings/deploy_settings.py b/apex/settings/deploy_settings.py index eec98225..c05922bf 100644 --- a/apex/settings/deploy_settings.py +++ b/apex/settings/deploy_settings.py @@ -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' diff --git a/apex/tests/test_apex_overcloud_deploy.py b/apex/tests/test_apex_overcloud_deploy.py index 420a70d6..b5b1b75e 100644 --- a/apex/tests/test_apex_overcloud_deploy.py +++ b/apex/tests/test_apex_overcloud_deploy.py @@ -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 diff --git a/build/rpm_specs/opnfv-apex-common.spec b/build/rpm_specs/opnfv-apex-common.spec index f8226e43..124f2527 100644 --- a/build/rpm_specs/opnfv-apex-common.spec +++ b/build/rpm_specs/opnfv-apex-common.spec @@ -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 diff --git a/config/deploy/deploy_settings.yaml b/config/deploy/deploy_settings.yaml index ab3b0a37..a6721b4a 100644 --- a/config/deploy/deploy_settings.yaml +++ b/config/deploy/deploy_settings.yaml @@ -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 index 00000000..03e34a23 --- /dev/null +++ b/config/deploy/os-odl-sriov-ha.yaml @@ -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 index 00000000..52b5aa18 --- /dev/null +++ b/config/deploy/os-odl-sriov-noha.yaml @@ -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 diff --git a/docs/release/installation/architecture.rst b/docs/release/installation/architecture.rst index b8db7c86..70067ed0 100644 --- a/docs/release/installation/architecture.rst +++ b/docs/release/installation/architecture.rst @@ -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 | diff --git a/lib/ansible/playbooks/configure_undercloud.yml b/lib/ansible/playbooks/configure_undercloud.yml index e9ce8754..9ef0d883 100644 --- a/lib/ansible/playbooks/configure_undercloud.yml +++ b/lib/ansible/playbooks/configure_undercloud.yml @@ -148,6 +148,11 @@ 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 diff --git a/lib/ansible/playbooks/deploy_overcloud.yml b/lib/ansible/playbooks/deploy_overcloud.yml index aa3d8067..268a5173 100644 --- a/lib/ansible/playbooks/deploy_overcloud.yml +++ b/lib/ansible/playbooks/deploy_overcloud.yml @@ -30,6 +30,12 @@ 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