From 09dcc583ec5ab04e80e7a4349dcc4061ed794b47 Mon Sep 17 00:00:00 2001 From: sritharan Date: Thu, 13 Oct 2022 05:43:13 +0000 Subject: [PATCH] Bug 2180 fixed Change-Id: Ib136760251c09cd803f2e313b184fa87428efd9b Signed-off-by: sritharan --- NG-RO/osm_ng_ro/ns.py | 87 ++++++--- NG-RO/osm_ng_ro/tests/test_ns.py | 175 +++++++++++++----- .../osm_rovim_openstack/vimconn_openstack.py | 41 +++- .../notes/fix_bug_2180-dd1ab93148aa4eb2.yaml | 22 +++ 4 files changed, 239 insertions(+), 86 deletions(-) create mode 100644 releasenotes/notes/fix_bug_2180-dd1ab93148aa4eb2.yaml diff --git a/NG-RO/osm_ng_ro/ns.py b/NG-RO/osm_ng_ro/ns.py index 9a16241d..77b391cc 100644 --- a/NG-RO/osm_ng_ro/ns.py +++ b/NG-RO/osm_ng_ro/ns.py @@ -647,44 +647,57 @@ class Ns(object): Tuple[Dict[str, Any], bool]: [description] """ numa = {} + numa_list = [] epa_vcpu_set = False if guest_epa_quota.get("numa-node-policy"): numa_node_policy = guest_epa_quota.get("numa-node-policy") if numa_node_policy.get("node"): - numa_node = numa_node_policy["node"][0] - - if numa_node.get("num-cores"): - numa["cores"] = numa_node["num-cores"] - epa_vcpu_set = True - - paired_threads = numa_node.get("paired-threads", {}) - if paired_threads.get("num-paired-threads"): - numa["paired-threads"] = int( - numa_node["paired-threads"]["num-paired-threads"] - ) - epa_vcpu_set = True + for numa_node in numa_node_policy["node"]: + vcpu_list = [] + if numa_node.get("id"): + numa["id"] = int(numa_node["id"]) + + if numa_node.get("vcpu"): + for vcpu in numa_node.get("vcpu"): + vcpu_id = int(vcpu.get("id")) + vcpu_list.append(vcpu_id) + numa["vcpu"] = vcpu_list + + if numa_node.get("num-cores"): + numa["cores"] = numa_node["num-cores"] + epa_vcpu_set = True + + paired_threads = numa_node.get("paired-threads", {}) + if paired_threads.get("num-paired-threads"): + numa["paired_threads"] = int( + numa_node["paired-threads"]["num-paired-threads"] + ) + epa_vcpu_set = True - if paired_threads.get("paired-thread-ids"): - numa["paired-threads-id"] = [] + if paired_threads.get("paired-thread-ids"): + numa["paired-threads-id"] = [] - for pair in paired_threads["paired-thread-ids"]: - numa["paired-threads-id"].append( - ( - str(pair["thread-a"]), - str(pair["thread-b"]), + for pair in paired_threads["paired-thread-ids"]: + numa["paired-threads-id"].append( + ( + str(pair["thread-a"]), + str(pair["thread-b"]), + ) ) - ) - if numa_node.get("num-threads"): - numa["threads"] = int(numa_node["num-threads"]) - epa_vcpu_set = True + if numa_node.get("num-threads"): + numa["threads"] = int(numa_node["num-threads"]) + epa_vcpu_set = True - if numa_node.get("memory-mb"): - numa["memory"] = max(int(int(numa_node["memory-mb"]) / 1024), 1) + if numa_node.get("memory-mb"): + numa["memory"] = max(int(int(numa_node["memory-mb"]) / 1024), 1) - return numa, epa_vcpu_set + numa_list.append(numa) + numa = {} + + return numa_list, epa_vcpu_set @staticmethod def _process_guest_epa_cpu_pinning_params( @@ -732,23 +745,39 @@ class Ns(object): """ extended = {} numa = {} + numa_list = [] if target_flavor.get("guest-epa"): guest_epa = target_flavor["guest-epa"] - numa, epa_vcpu_set = Ns._process_guest_epa_numa_params( + numa_list, epa_vcpu_set = Ns._process_guest_epa_numa_params( guest_epa_quota=guest_epa ) if guest_epa.get("mempage-size"): extended["mempage-size"] = guest_epa.get("mempage-size") + if guest_epa.get("cpu-pinning-policy"): + extended["cpu-pinning-policy"] = guest_epa.get("cpu-pinning-policy") + + if guest_epa.get("cpu-thread-pinning-policy"): + extended["cpu-thread-pinning-policy"] = guest_epa.get( + "cpu-thread-pinning-policy" + ) + + if guest_epa.get("numa-node-policy"): + if guest_epa.get("numa-node-policy").get("mem-policy"): + extended["mem-policy"] = guest_epa.get("numa-node-policy").get( + "mem-policy" + ) + tmp_numa, epa_vcpu_set = Ns._process_guest_epa_cpu_pinning_params( guest_epa_quota=guest_epa, vcpu_count=int(target_flavor.get("vcpu-count", 1)), epa_vcpu_set=epa_vcpu_set, ) - numa.update(tmp_numa) + for numa in numa_list: + numa.update(tmp_numa) extended.update( Ns._process_guest_epa_quota_params( @@ -758,7 +787,7 @@ class Ns(object): ) if numa: - extended["numas"] = [numa] + extended["numas"] = numa_list return extended diff --git a/NG-RO/osm_ng_ro/tests/test_ns.py b/NG-RO/osm_ng_ro/tests/test_ns.py index e69a4c5c..af448508 100644 --- a/NG-RO/osm_ng_ro/tests/test_ns.py +++ b/NG-RO/osm_ng_ro/tests/test_ns.py @@ -831,19 +831,18 @@ class TestNs(unittest.TestCase): self.assertDictEqual(expected_result, result) def test__process_guest_epa_numa_params_with_empty_numa_params(self): - expected_numa_result = {} + expected_numa_result = [] expected_epa_vcpu_set_result = False guest_epa_quota = {} numa_result, epa_vcpu_set_result = Ns._process_guest_epa_numa_params( guest_epa_quota=guest_epa_quota, ) - - self.assertDictEqual(expected_numa_result, numa_result) + self.assertEqual(expected_numa_result, numa_result) self.assertEqual(expected_epa_vcpu_set_result, epa_vcpu_set_result) def test__process_guest_epa_numa_params_with_wrong_numa_params(self): - expected_numa_result = {} + expected_numa_result = [] expected_epa_vcpu_set_result = False guest_epa_quota = {"no_nume": "here"} @@ -851,11 +850,11 @@ class TestNs(unittest.TestCase): guest_epa_quota=guest_epa_quota, ) - self.assertDictEqual(expected_numa_result, numa_result) + self.assertEqual(expected_numa_result, numa_result) self.assertEqual(expected_epa_vcpu_set_result, epa_vcpu_set_result) def test__process_guest_epa_numa_params_with_numa_node_policy(self): - expected_numa_result = {} + expected_numa_result = [] expected_epa_vcpu_set_result = False guest_epa_quota = {"numa-node-policy": {}} @@ -863,11 +862,11 @@ class TestNs(unittest.TestCase): guest_epa_quota=guest_epa_quota, ) - self.assertDictEqual(expected_numa_result, numa_result) + self.assertEqual(expected_numa_result, numa_result) self.assertEqual(expected_epa_vcpu_set_result, epa_vcpu_set_result) def test__process_guest_epa_numa_params_with_no_node(self): - expected_numa_result = {} + expected_numa_result = [] expected_epa_vcpu_set_result = False guest_epa_quota = { "numa-node-policy": { @@ -879,11 +878,11 @@ class TestNs(unittest.TestCase): guest_epa_quota=guest_epa_quota, ) - self.assertDictEqual(expected_numa_result, numa_result) + self.assertEqual(expected_numa_result, numa_result) self.assertEqual(expected_epa_vcpu_set_result, epa_vcpu_set_result) def test__process_guest_epa_numa_params_with_1_node_num_cores(self): - expected_numa_result = {"cores": 3} + expected_numa_result = [{"cores": 3}] expected_epa_vcpu_set_result = True guest_epa_quota = { "numa-node-policy": { @@ -899,11 +898,11 @@ class TestNs(unittest.TestCase): guest_epa_quota=guest_epa_quota, ) - self.assertDictEqual(expected_numa_result, numa_result) + self.assertEqual(expected_numa_result, numa_result) self.assertEqual(expected_epa_vcpu_set_result, epa_vcpu_set_result) def test__process_guest_epa_numa_params_with_1_node_paired_threads(self): - expected_numa_result = {"paired-threads": 3} + expected_numa_result = [{"paired_threads": 3}] expected_epa_vcpu_set_result = True guest_epa_quota = { "numa-node-policy": { @@ -919,13 +918,15 @@ class TestNs(unittest.TestCase): guest_epa_quota=guest_epa_quota, ) - self.assertDictEqual(expected_numa_result, numa_result) + self.assertEqual(expected_numa_result, numa_result) self.assertEqual(expected_epa_vcpu_set_result, epa_vcpu_set_result) def test__process_guest_epa_numa_params_with_1_node_paired_threads_ids(self): - expected_numa_result = { - "paired-threads-id": [("0", "1"), ("4", "5")], - } + expected_numa_result = [ + { + "paired-threads-id": [("0", "1"), ("4", "5")], + } + ] expected_epa_vcpu_set_result = False guest_epa_quota = { "numa-node-policy": { @@ -952,11 +953,11 @@ class TestNs(unittest.TestCase): guest_epa_quota=guest_epa_quota, ) - self.assertDictEqual(expected_numa_result, numa_result) + self.assertEqual(expected_numa_result, numa_result) self.assertEqual(expected_epa_vcpu_set_result, epa_vcpu_set_result) def test__process_guest_epa_numa_params_with_1_node_num_threads(self): - expected_numa_result = {"threads": 3} + expected_numa_result = [{"threads": 3}] expected_epa_vcpu_set_result = True guest_epa_quota = { "numa-node-policy": { @@ -972,11 +973,11 @@ class TestNs(unittest.TestCase): guest_epa_quota=guest_epa_quota, ) - self.assertDictEqual(expected_numa_result, numa_result) + self.assertEqual(expected_numa_result, numa_result) self.assertEqual(expected_epa_vcpu_set_result, epa_vcpu_set_result) def test__process_guest_epa_numa_params_with_1_node_memory_mb(self): - expected_numa_result = {"memory": 2} + expected_numa_result = [{"memory": 2}] expected_epa_vcpu_set_result = False guest_epa_quota = { "numa-node-policy": { @@ -992,17 +993,71 @@ class TestNs(unittest.TestCase): guest_epa_quota=guest_epa_quota, ) - self.assertDictEqual(expected_numa_result, numa_result) + self.assertEqual(expected_numa_result, numa_result) self.assertEqual(expected_epa_vcpu_set_result, epa_vcpu_set_result) - def test__process_guest_epa_numa_params_with_1_node(self): - expected_numa_result = { - "cores": 3, - "paired-threads": 3, - "paired-threads-id": [("0", "1"), ("4", "5")], - "threads": 3, - "memory": 2, + def test__process_guest_epa_numa_params_with_1_node_vcpu(self): + expected_numa_result = [ + { + "id": 0, + "vcpu": [0, 1], + } + ] + expected_epa_vcpu_set_result = False + guest_epa_quota = { + "numa-node-policy": { + "node": [{"id": "0", "vcpu": [{"id": "0"}, {"id": "1"}]}], + }, } + + numa_result, epa_vcpu_set_result = Ns._process_guest_epa_numa_params( + guest_epa_quota=guest_epa_quota, + ) + + self.assertEqual(expected_numa_result, numa_result) + self.assertEqual(expected_epa_vcpu_set_result, epa_vcpu_set_result) + + def test__process_guest_epa_numa_params_with_2_node_vcpu(self): + expected_numa_result = [ + { + "id": 0, + "vcpu": [0, 1], + }, + { + "id": 1, + "vcpu": [2, 3], + }, + ] + + expected_epa_vcpu_set_result = False + guest_epa_quota = { + "numa-node-policy": { + "node": [ + {"id": "0", "vcpu": [{"id": "0"}, {"id": "1"}]}, + {"id": "1", "vcpu": [{"id": "2"}, {"id": "3"}]}, + ], + }, + } + + numa_result, epa_vcpu_set_result = Ns._process_guest_epa_numa_params( + guest_epa_quota=guest_epa_quota, + ) + + self.assertEqual(expected_numa_result, numa_result) + self.assertEqual(expected_epa_vcpu_set_result, epa_vcpu_set_result) + + def test__process_guest_epa_numa_params_with_1_node(self): + expected_numa_result = [ + { + # "id": 0, + # "vcpu": [0, 1], + "cores": 3, + "paired_threads": 3, + "paired-threads-id": [("0", "1"), ("4", "5")], + "threads": 3, + "memory": 2, + } + ] expected_epa_vcpu_set_result = True guest_epa_quota = { "numa-node-policy": { @@ -1033,17 +1088,26 @@ class TestNs(unittest.TestCase): guest_epa_quota=guest_epa_quota, ) - self.assertDictEqual(expected_numa_result, numa_result) + self.assertEqual(expected_numa_result, numa_result) self.assertEqual(expected_epa_vcpu_set_result, epa_vcpu_set_result) def test__process_guest_epa_numa_params_with_2_nodes(self): - expected_numa_result = { - "cores": 3, - "paired-threads": 3, - "paired-threads-id": [("0", "1"), ("4", "5")], - "threads": 3, - "memory": 2, - } + expected_numa_result = [ + { + "cores": 3, + "paired_threads": 3, + "paired-threads-id": [("0", "1"), ("4", "5")], + "threads": 3, + "memory": 2, + }, + { + "cores": 7, + "paired_threads": 7, + "paired-threads-id": [("2", "3"), ("5", "6")], + "threads": 4, + "memory": 4, + }, + ] expected_epa_vcpu_set_result = True guest_epa_quota = { "numa-node-policy": { @@ -1092,7 +1156,7 @@ class TestNs(unittest.TestCase): guest_epa_quota=guest_epa_quota, ) - self.assertDictEqual(expected_numa_result, numa_result) + self.assertEqual(expected_numa_result, numa_result) self.assertEqual(expected_epa_vcpu_set_result, epa_vcpu_set_result) def test__process_guest_epa_cpu_pinning_params_with_empty_params(self): @@ -1237,10 +1301,15 @@ class TestNs(unittest.TestCase): guest_epa_cpu_pinning_params, guest_epa_quota_params, ): - expected_result = {} + expected_result = { + "mem-policy": "STRICT", + } target_flavor = { "guest-epa": { "vcpu-count": 1, + "numa-node-policy": { + "mem-policy": "STRICT", + }, }, } @@ -1268,9 +1337,16 @@ class TestNs(unittest.TestCase): ): expected_result = { "mempage-size": "1G", + "mem-policy": "STRICT", } target_flavor = { - "guest-epa": {"vcpu-count": 1, "mempage-size": "1G"}, + "guest-epa": { + "vcpu-count": 1, + "mempage-size": "1G", + "numa-node-policy": { + "mem-policy": "STRICT", + }, + }, } guest_epa_numa_params.return_value = ({}, False) @@ -1297,6 +1373,8 @@ class TestNs(unittest.TestCase): ): expected_result = { "mempage-size": "1G", + "cpu-pinning-policy": "DEDICATED", + "cpu-thread-pinning-policy": "PREFER", "numas": [ { "cores": 3, @@ -1363,13 +1441,15 @@ class TestNs(unittest.TestCase): } guest_epa_numa_params.return_value = ( - { - "cores": 3, - "paired-threads": 3, - "paired-threads-id": [("0", "1"), ("4", "5")], - "threads": 3, - "memory": 2, - }, + [ + { + "cores": 3, + "paired-threads": 3, + "paired-threads-id": [("0", "1"), ("4", "5")], + "threads": 3, + "memory": 2, + }, + ], True, ) guest_epa_cpu_pinning_params.return_value = ( @@ -1404,8 +1484,7 @@ class TestNs(unittest.TestCase): result = Ns._process_epa_params( target_flavor=target_flavor, ) - - self.assertDictEqual(expected_result, result) + self.assertEqual(expected_result, result) self.assertTrue(guest_epa_numa_params.called) self.assertTrue(guest_epa_cpu_pinning_params.called) self.assertTrue(guest_epa_quota_params.called) diff --git a/RO-VIM-openstack/osm_rovim_openstack/vimconn_openstack.py b/RO-VIM-openstack/osm_rovim_openstack/vimconn_openstack.py index eda56990..3aaedf60 100644 --- a/RO-VIM-openstack/osm_rovim_openstack/vimconn_openstack.py +++ b/RO-VIM-openstack/osm_rovim_openstack/vimconn_openstack.py @@ -1283,13 +1283,7 @@ class vimconnector(vimconn.VimConnector): if numas: numa_nodes = len(numas) - if numa_nodes > 1: - return -1, "Can not add flavor with more than one numa" - extra_specs["hw:numa_nodes"] = str(numa_nodes) - extra_specs["hw:mem_page_size"] = "large" - extra_specs["hw:cpu_policy"] = "dedicated" - extra_specs["hw:numa_mempolicy"] = "strict" if self.vim_type == "VIO": extra_specs[ @@ -1298,13 +1292,25 @@ class vimconnector(vimconn.VimConnector): extra_specs["vmware:latency_sensitivity_level"] = "high" for numa in numas: + if "id" in numa: + node_id = numa["id"] + + if "memory" in numa: + memory_mb = numa["memory"] * 1024 + memory = "hw:numa_mem.{}".format(node_id) + extra_specs[memory] = int(memory_mb) + + if "vcpu" in numa: + vcpu = numa["vcpu"] + cpu = "hw:numa_cpus.{}".format(node_id) + vcpu = ",".join(map(str, vcpu)) + extra_specs[cpu] = vcpu + # overwrite ram and vcpus # check if key "memory" is present in numa else use ram value at flavor - if "memory" in numa: - ram = numa["memory"] * 1024 # See for reference: https://specs.openstack.org/openstack/nova-specs/specs/mitaka/ # implemented/virt-driver-cpu-thread-pinning.html - extra_specs["hw:cpu_sockets"] = 1 + extra_specs["hw:cpu_sockets"] = str(numa_nodes) if "paired-threads" in numa: vcpus = numa["paired-threads"] * 2 @@ -1369,6 +1375,23 @@ class vimconnector(vimconn.VimConnector): "Invalid mempage-size %s. Will be ignored", extended.get("mempage-size"), ) + if extended.get("cpu-pinning-policy"): + extra_specs["hw:cpu_policy"] = extended.get( + "cpu-pinning-policy" + ).lower() + + # Set the cpu thread pinning policy as specified in the descriptor + if extended.get("cpu-thread-pinning-policy"): + extra_specs["hw:cpu_thread_policy"] = extended.get( + "cpu-thread-pinning-policy" + ).lower() + + # Set the mem policy as specified in the descriptor + if extended.get("mem-policy"): + extra_specs["hw:numa_mempolicy"] = extended.get( + "mem-policy" + ).lower() + # create flavor new_flavor = self.nova.flavors.create( name=name, diff --git a/releasenotes/notes/fix_bug_2180-dd1ab93148aa4eb2.yaml b/releasenotes/notes/fix_bug_2180-dd1ab93148aa4eb2.yaml new file mode 100644 index 00000000..23886374 --- /dev/null +++ b/releasenotes/notes/fix_bug_2180-dd1ab93148aa4eb2.yaml @@ -0,0 +1,22 @@ +####################################################################################### +# Copyright ETSI Contributors and Others. +# +# 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. +####################################################################################### +--- +fixes: + - | + This fixes the bug 2180.EPA will set only the parameters that are explicitly + defined in the vnfd descriptor.Numa policy supports for multiple nodes with numa + cpus. -- 2.17.1