From 9d9b495c5b9ced42a69446d0bf18612d7eb43315 Mon Sep 17 00:00:00 2001 From: Dennis Dmitriev Date: Mon, 20 Feb 2017 20:24:15 +0200 Subject: [PATCH] Extend 'slave-ip-list' CLI options - show address pool names or specify an --address-pool-name=<...> - show node names or set --ip-only flag Output examples: $ dos.py slave-ip-list ac_linear_test public-pool01: master,10.100.0.128 slave-0,10.100.0.129 slave-1,10.100.0.130 neutron-pool01: master,10.100.2.2 slave-0,10.100.2.3 slave-1,10.100.2.4 private-pool01: master,10.100.1.128 slave-0,10.100.1.129 slave-1,10.100.1.130 $ dos.py slave-ip-list ac_linear_test --ip-only public-pool01: 10.100.0.128 10.100.0.129 10.100.0.130 neutron-pool01: 10.100.2.2 10.100.2.3 10.100.2.4 private-pool01: 10.100.1.128 10.100.1.129 10.100.1.130 $ dos.py slave-ip-list ac_linear_test --address-pool-name=public-pool01 master,10.100.0.128 slave-0,10.100.0.129 slave-1,10.100.0.130 $ dos.py slave-ip-list ac_linear_test --address-pool-name=public-pool01 --ip-only 10.100.0.128 10.100.0.129 10.100.0.130 Change-Id: I75635f73b90f37d9e50de1772bc7da6720c41cec Related-Bug:#1658630 --- devops/models/node.py | 4 +- devops/shell.py | 47 +++++++++++++++++----- devops/tests/test_shell.py | 82 ++++++++++++++++++++++++++++---------- 3 files changed, 99 insertions(+), 34 deletions(-) diff --git a/devops/models/node.py b/devops/models/node.py index 4ca5cce6..c11c1942 100644 --- a/devops/models/node.py +++ b/devops/models/node.py @@ -291,13 +291,12 @@ class Node( return None return self.interface_set.get(label=label) - # NOTE: this method works only for master node def get_ip_address_by_network_name(self, name, interface=None): interface = interface or self.interface_set.filter( l2_network_device__name=name).order_by('id')[0] return interface.address_set.get(interface=interface).ip_address - # NOTE: this method works only for master node + # NOTE: this method works only for Fuel master node def get_ip_address_by_nailgun_network_name(self, name): interface = self.get_interface_by_nailgun_network_name(name) return interface.address_set.first().ip_address @@ -318,7 +317,6 @@ class Node( password=password, private_keys=private_keys, auth=auth) # LEGACY - # NOTE: this method works only for master node def await(self, network_name, timeout=120, by_port=22): helpers.wait_pass( lambda: helpers.tcp_ping_( diff --git a/devops/shell.py b/devops/shell.py index 51e4bd44..24efefc5 100644 --- a/devops/shell.py +++ b/devops/shell.py @@ -144,19 +144,35 @@ class Shell(object): self.print_table(headers=headers, columns=columns) def do_slave_ip_list(self): - slave_ips = [] + address_pool_name = self.params.address_pool_name + + slave_ips = {} for l2dev in self.env.get_env_l2_network_devices(): - # Suppress output of IPs from non-DHCP nets - if not l2dev.dhcp: + if address_pool_name and \ + l2dev.address_pool.name != address_pool_name: continue + + ap_slave_ips = [] for node in self.env.get_nodes(): - slave_ips.append( - node.get_ip_address_by_network_name(l2dev.name)) + if self.params.ip_only: + ap_slave_ips.append( + node.get_ip_address_by_network_name(l2dev.name)) + else: + ap_slave_ips.append( + "{0},{1}".format( + node.name, + node.get_ip_address_by_network_name(l2dev.name))) + if ap_slave_ips: + slave_ips[l2dev.address_pool.name] = ap_slave_ips if not slave_ips: - print('No IPs allocated for environment!') - else: - print(' '.join(slave_ips)) + sys.exit('No IPs were allocated for environment!') + + for ap, n_ips in sorted(slave_ips.items()): + if address_pool_name: + print(' '.join(n_ips)) + else: + print(ap + ": " + ' '.join(n_ips)) def do_time_sync(self): if not self.env.has_admin(): @@ -379,6 +395,17 @@ class Shell(object): net_pool.add_argument('--net-pool', '-P', dest='net_pool', help='Set ip network pool (cidr)', default="10.21.0.0/16:24", type=str) + address_pool_name = argparse.ArgumentParser(add_help=False) + address_pool_name.add_argument( + '--address-pool-name', '-A', + dest='address_pool_name', + help='Specified address pool for printing IPs', + default=None, type=str) + ip_only_parser = argparse.ArgumentParser(add_help=False) + ip_only_parser.add_argument('--ip-only', dest='ip_only', + action='store_const', const=True, + help='Print just IP addresses', + default=False) second_disk_size = argparse.ArgumentParser(add_help=False) second_disk_size.add_argument('--second-disk-size', dest='second_disk_size', @@ -453,7 +480,9 @@ class Shell(object): description="Display allocated networks for " "environment") subparsers.add_parser('slave-ip-list', - parents=[name_parser], + parents=[name_parser, + address_pool_name, + ip_only_parser], help="Show slave node IPs in environment", description="Display allocated IPs for " "environment slave nodes") diff --git a/devops/tests/test_shell.py b/devops/tests/test_shell.py index e4e72f52..4368dfcc 100644 --- a/devops/tests/test_shell.py +++ b/devops/tests/test_shell.py @@ -86,6 +86,7 @@ class TestShell(unittest.TestCase): def setUp(self): super(TestShell, self).setUp() + self.sys_mock = self.patch('devops.shell.sys') self.print_mock = self.patch('devops.shell.print') self.tzlocal_mock = self.patch( 'devops.helpers.helpers.tz.tzlocal', @@ -101,16 +102,32 @@ class TestShell(unittest.TestCase): m.created = datetime.datetime(2016, 5, 12, 15, 12, t) return m - def create_l2netdev_mock(name, dhcp=False): + def create_ap_mock(name, ip_network): + m = mock.Mock(spec=models.AddressPool) + m.name = name + m.ip_network = netaddr.IPNetwork(ip_network) + return m + + self.aps = { + 'env1': [ + create_ap_mock('fuelweb_admin-pool01', '109.10.0.0/24'), + create_ap_mock('public-pool01', '109.10.1.0/24'), + create_ap_mock('storage-pool01', '109.10.2.0/24'), + ] + } + + def create_l2netdev_mock(name, address_pool, dhcp=False): m = mock.Mock(spec=models.L2NetworkDevice) m.name = name m.dhcp = dhcp + m.address_pool = address_pool return name, m self.l2netdevs = collections.OrderedDict(( - create_l2netdev_mock('fuelweb_admin', dhcp=True), - create_l2netdev_mock('public', dhcp=True), - create_l2netdev_mock('storage'), + create_l2netdev_mock('fuelweb_admin', self.aps['env1'][0], + dhcp=True), + create_l2netdev_mock('public', self.aps['env1'][1], dhcp=True), + create_l2netdev_mock('storage', self.aps['env1'][2], ), )) def create_node_mock(name, vnc_port=5005, snapshots=None, ips=None): @@ -148,20 +165,6 @@ class TestShell(unittest.TestCase): )) } - def create_ap_mock(name, ip_network): - m = mock.Mock(spec=models.AddressPool) - m.name = name - m.ip_network = netaddr.IPNetwork(ip_network) - return m - - self.aps = { - 'env1': [ - create_ap_mock('fuelweb_admin-pool01', '109.10.0.0/24'), - create_ap_mock('public-pool01', '109.10.1.0/24'), - create_ap_mock('storage-pool01', '109.10.2.0/24'), - ] - } - def create_env_mock(env_name, created, nodes, aps, admin_ip=None): m = mock.Mock(created=created) m.name = env_name @@ -351,16 +354,51 @@ class TestShell(unittest.TestCase): sh = shell.Shell(['slave-ip-list', 'env1']) sh.execute() + self.print_mock.assert_has_calls(( + mock.call('fuelweb_admin-pool01: admin,192.168.1.2' + ' slave-01,192.168.1.3 slave-02,192.168.1.4'), + mock.call('public-pool01: admin,192.168.2.2' + ' slave-01,192.168.2.3 slave-02,192.168.2.4'), + mock.call('storage-pool01: admin,192.168.3.2' + ' slave-01,192.168.3.3 slave-02,192.168.3.4'), + )) + + def test_slave_ip_list_ip_only(self): + sh = shell.Shell(['slave-ip-list', 'env1', '--ip-only']) + sh.execute() + + self.print_mock.assert_has_calls(( + mock.call( + 'fuelweb_admin-pool01: 192.168.1.2 192.168.1.3 192.168.1.4'), + mock.call('public-pool01: 192.168.2.2 192.168.2.3 192.168.2.4'), + mock.call('storage-pool01: 192.168.3.2 192.168.3.3 192.168.3.4'), + )) + + def test_slave_ip_list_specific_ap(self): + sh = shell.Shell(['slave-ip-list', 'env1', + '--address-pool-name', 'public-pool01']) + sh.execute() + self.print_mock.assert_called_once_with( - '192.168.1.2 192.168.1.3 192.168.1.4 ' - '192.168.2.2 192.168.2.3 192.168.2.4') + 'admin,192.168.2.2 slave-01,192.168.2.3 slave-02,192.168.2.4') + + def test_slave_ip_list_specific_ap_ip_only(self): + sh = shell.Shell([ + 'slave-ip-list', 'env1', + '--address-pool-name', 'fuelweb_admin-pool01', + '--ip-only']) + sh.execute() + + self.print_mock.assert_called_once_with( + '192.168.1.2 192.168.1.3 192.168.1.4' + ) def test_slave_ip_list_empty(self): sh = shell.Shell(['slave-ip-list', 'env2']) sh.execute() - self.print_mock.assert_called_once_with( - 'No IPs allocated for environment!') + self.sys_mock.exit.assert_called_once_with( + 'No IPs were allocated for environment!') def test_net_list(self): sh = shell.Shell(['net-list', 'env1'])