From c4bc6364eb7c68c46eb9685fc905d133f576e329 Mon Sep 17 00:00:00 2001 From: Dennis Dmitriev Date: Thu, 13 Jul 2017 16:26:46 +0300 Subject: [PATCH] Add new option 'show-resources' to dos.py Show total and per-node maximum vcpu, memory and storage capacity usage, if defined. It will help to plan the CI hardware usage mode carefully. Example: $ dos.py show-resources test-environment-name Change-Id: I1bb891ef394d74b06e07c667fc88139377c8c96f --- devops/shell.py | 54 ++++++++++++++++++++++++++ devops/tests/test_shell.py | 78 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 128 insertions(+), 4 deletions(-) diff --git a/devops/shell.py b/devops/shell.py index c43c5cf6..2d4c2aaa 100644 --- a/devops/shell.py +++ b/devops/shell.py @@ -79,6 +79,55 @@ class Shell(object): for node in nodes] self.print_table(headers=headers, columns=columns) + def do_show_resources(self): + nodes = sorted(self.env.get_nodes(), key=lambda node: node.name) + headers = ("NAME", "ROLE", "GROUP", "VCPU", "MEMORY,Gb", "STORAGE,Gb") + total_vcpu = 0 + total_memory = 0 + total_storage = 0 + columns = list() + for node in nodes: + vcpu = 0 + memory = 0 + storage = 0 + + if 'vcpu' in node.get_defined_params(): + vcpu = node.vcpu + + if 'memory' in node.get_defined_params(): + memory = node.memory + + volumes = node.get_volumes() + for volume in volumes: + if 'capacity' in volume.get_defined_params(): + storage += int(volume.capacity) + + columns.append( + ( + node.name, + node.role, + node.group.name, + vcpu or '-', + memory or '-', + storage or '-', + ) + ) + total_vcpu += vcpu + total_memory += memory + total_storage += storage + + columns.append( + ( + "Total:", + '', + '', + total_vcpu or '-', + total_memory or '-', + total_storage or '-', + ) + ) + self.print_table(headers=headers, columns=columns) + def do_erase(self): self.env.erase() @@ -433,6 +482,11 @@ class Shell(object): subparsers.add_parser('show', parents=[name_parser], help="Show VMs in environment", description="Show VMs in environment") + subparsers.add_parser('show-resources', parents=[name_parser], + help=("Show resources consumed by VMs " + "in environment"), + description=("Show resources consumed by VMs " + "in environment")) subparsers.add_parser('erase', parents=[name_parser], help="Delete environment", description="Delete environment and VMs on it") diff --git a/devops/tests/test_shell.py b/devops/tests/test_shell.py index bf858e7a..13b2d7f3 100644 --- a/devops/tests/test_shell.py +++ b/devops/tests/test_shell.py @@ -130,10 +130,22 @@ class TestShell(unittest.TestCase): create_l2netdev_mock('storage', self.aps['env1'][2], ), )) - def create_node_mock(name, vnc_port=5005, snapshots=None, ips=None): + def create_volume_mock(name, capacity): + m = mock.Mock(spec=models.Volume) + m.name = name + m.capacity = capacity + m.get_defined_params.return_value = ['capacity'] + return m + + def create_node_mock(name, role, vcpu=1, memory=1, + vnc_port=5005, volumes=None, + snapshots=None, ips=None): m = mock.Mock(spec=models.Node) m.name = name + m.role = role m.group.name = 'rack-01' + m.vcpu = vcpu + m.memory = memory m.set_vcpu = mock.Mock(return_value=None) m.set_memory = mock.Mock(return_value=None) m.get_vnc_port = mock.Mock(return_value=vnc_port) @@ -145,20 +157,65 @@ class TestShell(unittest.TestCase): m.get_snapshots.return_value = snap_mocks m.get_ip_address_by_network_name.side_effect = ( lambda name: ips[name]) + m.get_defined_params.return_value = ['vcpu', 'memory'] + vol_mocks = [] + if volumes: + vol_mocks = [ + create_volume_mock(vol['name'], vol['capacity']) + for vol in volumes] + m.get_volumes.return_value = vol_mocks return name, m self.nodes = { 'env1': collections.OrderedDict(( - create_node_mock('admin', snapshots=[('snap1', 15), - ('snap2', 16)], + create_node_mock('admin', + role='master', + snapshots=[('snap1', 15), + ('snap2', 16)], + vcpu=2, + memory=2, + volumes=[ + { + 'name': 'system', + 'capacity': 2, + }, + { + 'name': 'iso', + 'capacity': 1, + }], ips={'fuelweb_admin': '192.168.1.2', 'public': '192.168.2.2', 'storage': '192.168.3.2'}), - create_node_mock('slave-01', snapshots=[('snap1', 15)], + create_node_mock('slave-01', + role='slave', + snapshots=[('snap1', 15)], + vcpu=4, + memory=8, + volumes=[ + { + 'name': 'system', + 'capacity': 4, + }, + { + 'name': 'ceph', + 'capacity': 32, + }], ips={'fuelweb_admin': '192.168.1.3', 'public': '192.168.2.3', 'storage': '192.168.3.3'}), create_node_mock('slave-02', + role='slave', + vcpu=2, + memory=16, + volumes=[ + { + 'name': 'system', + 'capacity': 2, + }, + { + 'name': 'glusterfs', + 'capacity': 8, + }], ips={'fuelweb_admin': '192.168.1.4', 'public': '192.168.2.4', 'storage': '192.168.3.4'}), @@ -259,6 +316,19 @@ class TestShell(unittest.TestCase): ' 5005 slave-01 rack-01\n' ' 5005 slave-02 rack-01') + def test_show_resources(self): + sh = shell.Shell(['show-resources', 'env1']) + sh.execute() + + self.client_inst.get_env.assert_called_once_with('env1') + self.print_mock.assert_called_once_with( + 'NAME ROLE GROUP VCPU MEMORY,Gb STORAGE,Gb\n' + '-------- ------ ------- ------ ----------- ------------\n' + 'admin master rack-01 2 2 3\n' + 'slave-01 slave rack-01 4 8 36\n' + 'slave-02 slave rack-01 2 16 10\n' + 'Total: 8 26 49') + def test_show_none(self): sh = shell.Shell(['show', 'env2']) sh.execute()