Add cpu, cpu_used for compute node
Add cpu, cpu_used for compute node. Change-Id: I1c2e418abaeca56e99fc595e9142a8f767839ab4 Partially-Implements: blueprint expose-host-capabilities
This commit is contained in:
@@ -558,14 +558,33 @@ class DockerDriver(driver.ContainerDriver):
|
|||||||
|
|
||||||
return addresses
|
return addresses
|
||||||
|
|
||||||
def get_container_numbers(self):
|
def get_host_info(self):
|
||||||
with docker_utils.docker_client() as docker:
|
with docker_utils.docker_client() as docker:
|
||||||
info = docker.info()
|
info = docker.info()
|
||||||
total = info['Containers']
|
total = info['Containers']
|
||||||
paused = info['ContainersPaused']
|
paused = info['ContainersPaused']
|
||||||
running = info['ContainersRunning']
|
running = info['ContainersRunning']
|
||||||
stopped = info['ContainersStopped']
|
stopped = info['ContainersStopped']
|
||||||
return total, running, paused, stopped
|
cpus = info['NCPU']
|
||||||
|
return total, running, paused, stopped, cpus
|
||||||
|
|
||||||
|
def get_cpu_used(self):
|
||||||
|
cpu_used = 0
|
||||||
|
with docker_utils.docker_client() as docker:
|
||||||
|
containers = docker.containers()
|
||||||
|
for container in containers:
|
||||||
|
cnt_id = container['Id']
|
||||||
|
# Fixme: if there is a way to get all container inspect info
|
||||||
|
# for one call only?
|
||||||
|
inspect = docker.inspect_container(cnt_id)
|
||||||
|
nanocpus = inspect['HostConfig']['NanoCpus']
|
||||||
|
cpu_period = inspect['HostConfig']['CpuPeriod']
|
||||||
|
cpu_quota = inspect['HostConfig']['CpuQuota']
|
||||||
|
if cpu_period and cpu_quota:
|
||||||
|
cpu_used += float(cpu_quota) / cpu_period
|
||||||
|
else:
|
||||||
|
cpu_used += float(nanocpus) / 1e9
|
||||||
|
return cpu_used
|
||||||
|
|
||||||
|
|
||||||
class NovaDockerDriver(DockerDriver):
|
class NovaDockerDriver(DockerDriver):
|
||||||
|
|||||||
@@ -186,7 +186,10 @@ class ContainerDriver(object):
|
|||||||
def get_host_mem(self):
|
def get_host_mem(self):
|
||||||
return os_capability_linux.LinuxHost().get_host_mem()
|
return os_capability_linux.LinuxHost().get_host_mem()
|
||||||
|
|
||||||
def get_container_numbers(self):
|
def get_host_info(self):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def get_cpu_used(self):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def get_available_resources(self, node):
|
def get_available_resources(self, node):
|
||||||
@@ -197,9 +200,12 @@ class ContainerDriver(object):
|
|||||||
node.mem_total = mem_total // units.Ki
|
node.mem_total = mem_total // units.Ki
|
||||||
node.mem_free = mem_free // units.Ki
|
node.mem_free = mem_free // units.Ki
|
||||||
node.mem_available = mem_ava // units.Ki
|
node.mem_available = mem_ava // units.Ki
|
||||||
numbers = self.get_container_numbers()
|
info = self.get_host_info()
|
||||||
(total, running, paused, stopped) = numbers
|
(total, running, paused, stopped, cpus) = info
|
||||||
node.total_containers = total
|
node.total_containers = total
|
||||||
node.running_containers = running
|
node.running_containers = running
|
||||||
node.paused_containers = paused
|
node.paused_containers = paused
|
||||||
node.stopped_containers = stopped
|
node.stopped_containers = stopped
|
||||||
|
node.cpus = cpus
|
||||||
|
cpu_used = self.get_cpu_used()
|
||||||
|
node.cpu_used = cpu_used
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
|
||||||
|
"""Add container cpus,cpu_used to compute node
|
||||||
|
|
||||||
|
Revision ID: 8c3d80e18eb5
|
||||||
|
Revises: ce9944b346cb
|
||||||
|
Create Date: 2017-04-25 09:26:02.374222
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '8c3d80e18eb5'
|
||||||
|
down_revision = 'ce9944b346cb'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.add_column('compute_node',
|
||||||
|
sa.Column('cpus', sa.Integer(), nullable=False))
|
||||||
|
op.add_column('compute_node',
|
||||||
|
sa.Column('cpu_used', sa.Float(), nullable=False))
|
||||||
@@ -277,3 +277,5 @@ class ComputeNode(Base):
|
|||||||
running_containers = Column(Integer, nullable=False, default=0)
|
running_containers = Column(Integer, nullable=False, default=0)
|
||||||
paused_containers = Column(Integer, nullable=False, default=0)
|
paused_containers = Column(Integer, nullable=False, default=0)
|
||||||
stopped_containers = Column(Integer, nullable=False, default=0)
|
stopped_containers = Column(Integer, nullable=False, default=0)
|
||||||
|
cpus = Column(Integer, nullable=False, default=0)
|
||||||
|
cpu_used = Column(Float, nullable=False, default=0.0)
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ class ComputeNode(base.ZunPersistentObject, base.ZunObject):
|
|||||||
# Version 1.0: Initial version
|
# Version 1.0: Initial version
|
||||||
# Version 1.1: Add mem_total, mem_free, mem_available columns
|
# Version 1.1: Add mem_total, mem_free, mem_available columns
|
||||||
# Version 1.2: Add total, running, pasued, stopped containers columns
|
# Version 1.2: Add total, running, pasued, stopped containers columns
|
||||||
VERSION = '1.2'
|
# Version 1.3: Add cpus, cpu_used
|
||||||
|
VERSION = '1.3'
|
||||||
|
|
||||||
fields = {
|
fields = {
|
||||||
'uuid': fields.UUIDField(read_only=True, nullable=False),
|
'uuid': fields.UUIDField(read_only=True, nullable=False),
|
||||||
@@ -35,6 +36,8 @@ class ComputeNode(base.ZunPersistentObject, base.ZunObject):
|
|||||||
'running_containers': fields.IntegerField(nullable=False),
|
'running_containers': fields.IntegerField(nullable=False),
|
||||||
'paused_containers': fields.IntegerField(nullable=False),
|
'paused_containers': fields.IntegerField(nullable=False),
|
||||||
'stopped_containers': fields.IntegerField(nullable=False),
|
'stopped_containers': fields.IntegerField(nullable=False),
|
||||||
|
'cpus': fields.IntegerField(nullable=False),
|
||||||
|
'cpu_used': fields.FloatField(nullable=False),
|
||||||
}
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
@@ -440,17 +440,30 @@ class TestDockerDriver(base.DriverTestCase):
|
|||||||
self.mock_docker.exec_resize.assert_called_once_with(
|
self.mock_docker.exec_resize.assert_called_once_with(
|
||||||
fake_exec_id, height=100, width=100)
|
fake_exec_id, height=100, width=100)
|
||||||
|
|
||||||
def test_get_container_numbers(self):
|
def test_get_host_info(self):
|
||||||
self.mock_docker.info = mock.Mock()
|
self.mock_docker.info = mock.Mock()
|
||||||
self.mock_docker.info.return_value = {'Containers': 10,
|
self.mock_docker.info.return_value = {'Containers': 10,
|
||||||
'ContainersPaused': 0,
|
'ContainersPaused': 0,
|
||||||
'ContainersRunning': 8,
|
'ContainersRunning': 8,
|
||||||
'ContainersStopped': 2}
|
'ContainersStopped': 2,
|
||||||
total, running, paused, stopped = self.driver.get_container_numbers()
|
'NCPU': 48}
|
||||||
|
total, running, paused, stopped, cpus = self.driver.get_host_info()
|
||||||
self.assertEqual(10, total)
|
self.assertEqual(10, total)
|
||||||
self.assertEqual(8, running)
|
self.assertEqual(8, running)
|
||||||
self.assertEqual(0, paused)
|
self.assertEqual(0, paused)
|
||||||
self.assertEqual(2, stopped)
|
self.assertEqual(2, stopped)
|
||||||
|
self.assertEqual(48, cpus)
|
||||||
|
|
||||||
|
def test_get_cpu_used(self):
|
||||||
|
self.mock_docker.containers = mock.Mock()
|
||||||
|
self.mock_docker.containers.return_value = [{'Id': '123456'}]
|
||||||
|
self.mock_docker.inspect_container = mock.Mock()
|
||||||
|
self.mock_docker.inspect_container.return_value = {
|
||||||
|
'HostConfig': {'NanoCpus': 1.0 * 1e9,
|
||||||
|
'CpuPeriod': 0,
|
||||||
|
'CpuQuota': 0}}
|
||||||
|
cpu_used = self.driver.get_cpu_used()
|
||||||
|
self.assertEqual(1.0, cpu_used)
|
||||||
|
|
||||||
|
|
||||||
class TestNovaDockerDriver(base.DriverTestCase):
|
class TestNovaDockerDriver(base.DriverTestCase):
|
||||||
@@ -548,14 +561,17 @@ class TestNovaDockerDriver(base.DriverTestCase):
|
|||||||
@mock.patch('oslo_concurrency.processutils.execute')
|
@mock.patch('oslo_concurrency.processutils.execute')
|
||||||
@mock.patch('zun.container.driver.ContainerDriver.get_host_mem')
|
@mock.patch('zun.container.driver.ContainerDriver.get_host_mem')
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'zun.container.docker.driver.DockerDriver.get_container_numbers')
|
'zun.container.docker.driver.DockerDriver.get_host_info')
|
||||||
def test_get_available_resources(self, mock_numbers, mock_mem,
|
@mock.patch(
|
||||||
|
'zun.container.docker.driver.DockerDriver.get_cpu_used')
|
||||||
|
def test_get_available_resources(self, mock_cpu_used, mock_info, mock_mem,
|
||||||
mock_output):
|
mock_output):
|
||||||
self.driver = DockerDriver()
|
self.driver = DockerDriver()
|
||||||
mock_output.return_value = LSCPU_ON
|
mock_output.return_value = LSCPU_ON
|
||||||
conf.CONF.set_override('floating_cpu_set', "0")
|
conf.CONF.set_override('floating_cpu_set', "0")
|
||||||
mock_mem.return_value = (100 * units.Ki, 50 * units.Ki, 50 * units.Ki)
|
mock_mem.return_value = (100 * units.Ki, 50 * units.Ki, 50 * units.Ki)
|
||||||
mock_numbers.return_value = (10, 8, 0, 2)
|
mock_info.return_value = (10, 8, 0, 2, 48)
|
||||||
|
mock_cpu_used.return_value = 1.0
|
||||||
node_obj = objects.ComputeNode()
|
node_obj = objects.ComputeNode()
|
||||||
self.driver.get_available_resources(node_obj)
|
self.driver.get_available_resources(node_obj)
|
||||||
self.assertEqual(_numa_topo_spec, node_obj.numa_topology.to_list())
|
self.assertEqual(_numa_topo_spec, node_obj.numa_topology.to_list())
|
||||||
@@ -566,3 +582,5 @@ class TestNovaDockerDriver(base.DriverTestCase):
|
|||||||
self.assertEqual(8, node_obj.running_containers)
|
self.assertEqual(8, node_obj.running_containers)
|
||||||
self.assertEqual(0, node_obj.paused_containers)
|
self.assertEqual(0, node_obj.paused_containers)
|
||||||
self.assertEqual(2, node_obj.stopped_containers)
|
self.assertEqual(2, node_obj.stopped_containers)
|
||||||
|
self.assertEqual(48, node_obj.cpus)
|
||||||
|
self.assertEqual(1.0, node_obj.cpu_used)
|
||||||
|
|||||||
@@ -268,6 +268,8 @@ def get_test_compute_node(**kw):
|
|||||||
'running_containers': kw.get('running_containers', 8),
|
'running_containers': kw.get('running_containers', 8),
|
||||||
'paused_containers': kw.get('paused_containers', 0),
|
'paused_containers': kw.get('paused_containers', 0),
|
||||||
'stopped_containers': kw.get('stopped_containers', 2),
|
'stopped_containers': kw.get('stopped_containers', 2),
|
||||||
|
'cpus': kw.get('cpus', 48),
|
||||||
|
'cpu_used': kw.get('cpu_used', 6.5),
|
||||||
'created_at': kw.get('created_at'),
|
'created_at': kw.get('created_at'),
|
||||||
'updated_at': kw.get('updated_at'),
|
'updated_at': kw.get('updated_at'),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -362,7 +362,7 @@ object_data = {
|
|||||||
'ResourceClass': '1.1-d661c7675b3cd5b8c3618b68ba64324e',
|
'ResourceClass': '1.1-d661c7675b3cd5b8c3618b68ba64324e',
|
||||||
'ResourceProvider': '1.0-92b427359d5a4cf9ec6c72cbe630ee24',
|
'ResourceProvider': '1.0-92b427359d5a4cf9ec6c72cbe630ee24',
|
||||||
'ZunService': '1.0-2a19ab9987a746621b2ada02d8aadf22',
|
'ZunService': '1.0-2a19ab9987a746621b2ada02d8aadf22',
|
||||||
'ComputeNode': '1.2-e50055b4e0d7f02e9c2f4b631dec63d9',
|
'ComputeNode': '1.3-f0b82f7f9593bdbb59b2c2bd07040c5f',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user