Merge "Introduce os-capability parsing"
This commit is contained in:
commit
797d8115fe
@ -388,6 +388,10 @@ class EntityNotFound(ZunException):
|
||||
message = _("The %(entity)s (%(name)s) could not be found.")
|
||||
|
||||
|
||||
class CommandError(ZunException):
|
||||
message = _("The command: %(cmd)s failed on the system.")
|
||||
|
||||
|
||||
class NoValidHost(ZunException):
|
||||
message = _("No valid host was found. %(reason)s")
|
||||
|
||||
|
0
zun/container/os_capability/__init__.py
Normal file
0
zun/container/os_capability/__init__.py
Normal file
25
zun/container/os_capability/host_capability.py
Normal file
25
zun/container/os_capability/host_capability.py
Normal file
@ -0,0 +1,25 @@
|
||||
# Copyright 2017 IBM Corp
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
class Host(object):
|
||||
|
||||
def __init__(self):
|
||||
self.capabilities = None
|
||||
|
||||
def get_cpu_numa_info(self):
|
||||
"""This method returns a dict containing the cpuset info for a host"""
|
||||
|
||||
raise NotImplementedError()
|
0
zun/container/os_capability/linux/__init__.py
Normal file
0
zun/container/os_capability/linux/__init__.py
Normal file
60
zun/container/os_capability/linux/os_capability_linux.py
Normal file
60
zun/container/os_capability/linux/os_capability_linux.py
Normal file
@ -0,0 +1,60 @@
|
||||
# Copyright 2017 IBM Corp
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from collections import defaultdict
|
||||
import re
|
||||
import six
|
||||
|
||||
from oslo_concurrency import processutils
|
||||
from oslo_log import log as logging
|
||||
from zun.common import exception
|
||||
from zun.common.i18n import _LE
|
||||
from zun.container.os_capability import host_capability
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LinuxHost(host_capability.Host):
|
||||
|
||||
def get_cpu_numa_info(self):
|
||||
# TODO(sbiswas7): rootwrap changes for zun required.
|
||||
old_lscpu = False
|
||||
try:
|
||||
output = processutils.execute('lscpu', '-p=socket,cpu,online')
|
||||
except processutils.ProcessExecutionError as e:
|
||||
LOG.exception(_LE("There was a problem while executing lscpu "
|
||||
"-p=socket,cpu,online : %s"), six.text_type(e))
|
||||
# There is a possibility that an older version of lscpu is used
|
||||
# So let's try without the online column
|
||||
try:
|
||||
output = processutils.execute('lscpu', '-p=socket,cpu')
|
||||
old_lscpu = True
|
||||
except processutils.ProcessExecutionError as e:
|
||||
LOG.exception(_LE("There was a problem while executing lscpu "
|
||||
"-p=socket,cpu : %s"), six.text_type(e))
|
||||
raise exception.CommandError(cmd="lscpu")
|
||||
if old_lscpu:
|
||||
cpu_sock_pair = re.findall("\d+(?:,\d+)?", str(output))
|
||||
else:
|
||||
cpu_sock_pair = re.findall("\d+(?:,\d+,[Y/N])?", str(output))
|
||||
sock_map = defaultdict(list)
|
||||
for value in cpu_sock_pair:
|
||||
val = value.split(",")
|
||||
if len(val) == 3 and val[2] == 'Y':
|
||||
sock_map[val[0]].append(val[1])
|
||||
elif len(val) == 2 and old_lscpu:
|
||||
sock_map[val[0]].append(val[1])
|
||||
return sock_map
|
0
zun/tests/unit/container/os_capability/__init__.py
Normal file
0
zun/tests/unit/container/os_capability/__init__.py
Normal file
@ -0,0 +1,65 @@
|
||||
# Copyright 2017 IBM Corp.
|
||||
#
|
||||
# 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.
|
||||
|
||||
import mock
|
||||
|
||||
from oslo_concurrency import processutils
|
||||
from zun.common import exception
|
||||
from zun.container.os_capability.linux import os_capability_linux
|
||||
from zun.tests import base
|
||||
|
||||
LSCPU_ON = """# The following is the parsable format, which can be fed to other
|
||||
# programs. Each different item in every column has an unique ID
|
||||
# starting from zero.
|
||||
# Socket,CPU,Online
|
||||
0,0,Y
|
||||
0,8,Y
|
||||
1,16,Y
|
||||
1,24,Y
|
||||
2,32,Y"""
|
||||
|
||||
LSCPU_NO_ONLINE = """# The following is the parsable format, which can be fed to
|
||||
# programs. Each different item in every column has an unique ID
|
||||
# starting from zero.
|
||||
# Socket,CPU
|
||||
0,0
|
||||
0,1
|
||||
1,2
|
||||
1,3"""
|
||||
|
||||
|
||||
class TestOSCapability(base.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(TestOSCapability, self).setUp()
|
||||
|
||||
@mock.patch('oslo_concurrency.processutils.execute')
|
||||
def test_get_cpu_numa_info_with_online(self, mock_output):
|
||||
mock_output.return_value = LSCPU_ON
|
||||
output = os_capability_linux.LinuxHost().get_cpu_numa_info()
|
||||
expected_output = {'0': ['0', '8'], '1': ['16', '24'], '2': ['32']}
|
||||
self.assertEqual(expected_output, output)
|
||||
|
||||
@mock.patch('oslo_concurrency.processutils.execute')
|
||||
def test_get_cpu_numa_info_exception(self, mock_output):
|
||||
mock_output.side_effect = processutils.ProcessExecutionError()
|
||||
self.assertRaises(exception.CommandError,
|
||||
os_capability_linux.LinuxHost().get_cpu_numa_info)
|
||||
|
||||
@mock.patch('oslo_concurrency.processutils.execute')
|
||||
def test_get_cpu_numa_info_without_online(self, mock_output):
|
||||
mock_output.side_effect = [processutils.ProcessExecutionError(),
|
||||
LSCPU_NO_ONLINE]
|
||||
expected_output = {'0': ['0', '1'], '1': ['2', '3']}
|
||||
output = os_capability_linux.LinuxHost().get_cpu_numa_info()
|
||||
self.assertEqual(expected_output, output)
|
Loading…
x
Reference in New Issue
Block a user