# Copyright 2013 Nebula Inc. # # 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 argparse import collections import copy import getpass import json import tempfile from unittest import mock from unittest.mock import call import iso8601 from novaclient import api_versions from openstack import exceptions as sdk_exceptions from openstack import utils as sdk_utils from osc_lib.cli import format_columns from osc_lib import exceptions from osc_lib import utils as common_utils from openstackclient.compute.v2 import server from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes from openstackclient.tests.unit.image.v2 import fakes as image_fakes from openstackclient.tests.unit.network.v2 import fakes as network_fakes from openstackclient.tests.unit import utils from openstackclient.tests.unit.volume.v2 import fakes as volume_fakes class TestPowerStateColumn(utils.TestCase): def test_human_readable(self): self.assertEqual( 'NOSTATE', server.PowerStateColumn(0x00).human_readable()) self.assertEqual( 'Running', server.PowerStateColumn(0x01).human_readable()) self.assertEqual( '', server.PowerStateColumn(0x02).human_readable()) self.assertEqual( 'Paused', server.PowerStateColumn(0x03).human_readable()) self.assertEqual( 'Shutdown', server.PowerStateColumn(0x04).human_readable()) self.assertEqual( '', server.PowerStateColumn(0x05).human_readable()) self.assertEqual( 'Crashed', server.PowerStateColumn(0x06).human_readable()) self.assertEqual( 'Suspended', server.PowerStateColumn(0x07).human_readable()) self.assertEqual( 'N/A', server.PowerStateColumn(0x08).human_readable()) class TestServer(compute_fakes.TestComputev2): def setUp(self): super(TestServer, self).setUp() # Get a shortcut to the compute client ServerManager Mock self.servers_mock = self.app.client_manager.compute.servers self.servers_mock.reset_mock() self.app.client_manager.sdk_connection = mock.Mock() self.app.client_manager.sdk_connection.compute = mock.Mock() self.sdk_client = self.app.client_manager.sdk_connection.compute # Get a shortcut to the compute client ServerMigrationsManager Mock self.server_migrations_mock = \ self.app.client_manager.compute.server_migrations self.server_migrations_mock.reset_mock() # Get a shortcut to the compute client VolumeManager mock self.servers_volumes_mock = self.app.client_manager.compute.volumes self.servers_volumes_mock.reset_mock() # Get a shortcut to the compute client MigrationManager mock self.migrations_mock = self.app.client_manager.compute.migrations self.migrations_mock.reset_mock() # Get a shortcut to the compute client FlavorManager Mock self.flavors_mock = self.app.client_manager.compute.flavors self.flavors_mock.reset_mock() # Get a shortcut to the image client ImageManager Mock self.images_mock = self.app.client_manager.image.images self.images_mock.reset_mock() self.find_image_mock = self.app.client_manager.image.find_image self.find_image_mock.reset_mock() self.get_image_mock = self.app.client_manager.image.get_image self.get_image_mock.reset_mock() # Get a shortcut to the volume client VolumeManager Mock self.volumes_mock = self.app.client_manager.volume.volumes self.volumes_mock.reset_mock() self.app.client_manager.sdk_connection.volume = mock.Mock() self.sdk_volume_client = self.app.client_manager.sdk_connection.volume # Get a shortcut to the volume client VolumeManager Mock self.snapshots_mock = self.app.client_manager.volume.volume_snapshots self.snapshots_mock.reset_mock() # Set object attributes to be tested. Could be overwritten in subclass. self.attrs = {} # Set object methods to be tested. Could be overwritten in subclass. self.methods = {} def setup_servers_mock(self, count): # If we are creating more than one server, make one of them # boot-from-volume include_bfv = count > 1 servers = compute_fakes.FakeServer.create_servers( attrs=self.attrs, methods=self.methods, count=count - 1 if include_bfv else count ) if include_bfv: attrs = copy.deepcopy(self.attrs) attrs['image'] = '' bfv_server = compute_fakes.FakeServer.create_one_server( attrs=attrs, methods=self.methods ) servers.append(bfv_server) # This is the return value for utils.find_resource() self.servers_mock.get = compute_fakes.FakeServer.get_servers(servers, 0) return servers def setup_sdk_servers_mock(self, count): servers = compute_fakes.FakeServer.create_sdk_servers( attrs=self.attrs, methods=self.methods, count=count, ) # This is the return value for compute_client.find_server() self.sdk_client.find_server.side_effect = servers return servers def setup_sdk_volumes_mock(self, count): volumes = volume_fakes.FakeVolume.create_sdk_volumes(count=count) # This is the return value for volume_client.find_volume() self.sdk_volume_client.find_volume.side_effect = volumes return volumes def run_method_with_servers(self, method_name, server_count): servers = self.setup_servers_mock(server_count) arglist = [] verifylist = [] for s in servers: arglist.append(s.id) verifylist = [ ('server', arglist), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) for s in servers: method = getattr(s, method_name) if method_name == 'lock': version = self.app.client_manager.compute.api_version if version >= api_versions.APIVersion('2.73'): method.assert_called_with(reason=None) elif method_name == 'unshelve': version = self.app.client_manager.compute.api_version if version >= api_versions.APIVersion('2.77'): method.assert_called_with(availability_zone=None) else: method.assert_called_with() else: method.assert_called_with() self.assertIsNone(result) def run_method_with_sdk_servers(self, method_name, server_count): servers = self.setup_sdk_servers_mock(count=server_count) arglist = [s.id for s in servers] verifylist = [ ('server', arglist), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) calls = [call(s.id) for s in servers] method = getattr(self.sdk_client, method_name) method.assert_has_calls(calls) self.assertIsNone(result) class TestServerAddFixedIP(TestServer): def setUp(self): super().setUp() # Get the command object to test self.cmd = server.AddFixedIP(self.app, None) # Mock network methods self.find_network = mock.Mock() self.app.client_manager.network.find_network = self.find_network @mock.patch.object(sdk_utils, 'supports_microversion') def test_server_add_fixed_ip_pre_v244(self, sm_mock): sm_mock.return_value = False servers = self.setup_sdk_servers_mock(count=1) network = compute_fakes.FakeNetwork.create_one_network() with mock.patch.object( self.app.client_manager, 'is_network_endpoint_enabled', return_value=False ): arglist = [ servers[0].id, network['id'], ] verifylist = [ ('server', servers[0].id), ('network', network['id']), ('fixed_ip_address', None), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.sdk_client.add_fixed_ip_to_server.assert_called_once_with( servers[0].id, network['id'] ) # the legacy API operates asynchronously self.assertEqual(((), ()), result) @mock.patch.object(sdk_utils, 'supports_microversion') def test_server_add_fixed_ip_pre_v244_with_fixed_ip(self, sm_mock): sm_mock.return_value = False servers = self.setup_sdk_servers_mock(count=1) network = compute_fakes.FakeNetwork.create_one_network() with mock.patch.object( self.app.client_manager, 'is_network_endpoint_enabled', return_value=False ): arglist = [ servers[0].id, network['id'], '--fixed-ip-address', '5.6.7.8' ] verifylist = [ ('server', servers[0].id), ('network', network['id']), ('fixed_ip_address', '5.6.7.8'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.sdk_client.add_fixed_ip_to_server.assert_called_once_with( servers[0].id, network['id'] ) # the legacy API operates asynchronously self.assertEqual(((), ()), result) @mock.patch.object(sdk_utils, 'supports_microversion') def test_server_add_fixed_ip_pre_v244_with_tag(self, sm_mock): sm_mock.return_value = False servers = self.setup_sdk_servers_mock(count=1) network = compute_fakes.FakeNetwork.create_one_network() with mock.patch.object( self.app.client_manager, 'is_network_endpoint_enabled', return_value=False ): arglist = [ servers[0].id, network['id'], '--fixed-ip-address', '5.6.7.8', '--tag', 'tag1' ] verifylist = [ ('server', servers[0].id), ('network', network['id']), ('fixed_ip_address', '5.6.7.8'), ('tag', 'tag1') ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) ex = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-compute-api-version 2.49 or greater is required', str(ex)) @mock.patch.object(sdk_utils, 'supports_microversion') def test_server_add_fixed_ip_pre_v249_with_tag(self, sm_mock): sm_mock.side_effect = [False, True] servers = self.setup_sdk_servers_mock(count=1) network = compute_fakes.FakeNetwork.create_one_network() with mock.patch.object( self.app.client_manager, 'is_network_endpoint_enabled', return_value=False ): arglist = [ servers[0].id, network['id'], '--fixed-ip-address', '5.6.7.8', '--tag', 'tag1' ] verifylist = [ ('server', servers[0].id), ('network', network['id']), ('fixed_ip_address', '5.6.7.8'), ('tag', 'tag1') ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) ex = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-compute-api-version 2.49 or greater is required', str(ex)) @mock.patch.object(sdk_utils, 'supports_microversion') def test_server_add_fixed_ip(self, sm_mock): sm_mock.side_effect = [True, False] servers = self.setup_sdk_servers_mock(count=1) network = compute_fakes.FakeNetwork.create_one_network() interface = compute_fakes.create_one_server_interface() self.sdk_client.create_server_interface.return_value = interface with mock.patch.object( self.app.client_manager, 'is_network_endpoint_enabled', return_value=False ): arglist = [ servers[0].id, network['id'] ] verifylist = [ ('server', servers[0].id), ('network', network['id']) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) expected_columns = ( 'Port ID', 'Server ID', 'Network ID', 'MAC Address', 'Port State', 'Fixed IPs', ) expected_data = ( interface.port_id, interface.server_id, interface.net_id, interface.mac_addr, interface.port_state, format_columns.ListDictColumn(interface.fixed_ips), ) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(expected_columns, columns) self.assertEqual(expected_data, tuple(data)) self.sdk_client.create_server_interface.assert_called_once_with( servers[0].id, net_id=network['id'], fixed_ip=None ) @mock.patch.object(sdk_utils, 'supports_microversion') def test_server_add_fixed_ip_with_fixed_ip(self, sm_mock): sm_mock.side_effect = [True, True] servers = self.setup_sdk_servers_mock(count=1) network = compute_fakes.FakeNetwork.create_one_network() interface = compute_fakes.create_one_server_interface() self.sdk_client.create_server_interface.return_value = interface with mock.patch.object( self.app.client_manager, 'is_network_endpoint_enabled', return_value=False ): arglist = [ servers[0].id, network['id'], '--fixed-ip-address', '5.6.7.8' ] verifylist = [ ('server', servers[0].id), ('network', network['id']), ('fixed_ip_address', '5.6.7.8') ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) expected_columns = ( 'Port ID', 'Server ID', 'Network ID', 'MAC Address', 'Port State', 'Fixed IPs', 'Tag', ) expected_data = ( interface.port_id, interface.server_id, interface.net_id, interface.mac_addr, interface.port_state, format_columns.ListDictColumn(interface.fixed_ips), interface.tag, ) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(expected_columns, columns) self.assertEqual(expected_data, tuple(data)) self.sdk_client.create_server_interface.assert_called_once_with( servers[0].id, net_id=network['id'], fixed_ip='5.6.7.8' ) @mock.patch.object(sdk_utils, 'supports_microversion') def test_server_add_fixed_ip_with_tag(self, sm_mock): sm_mock.side_effect = [True, True, True] servers = self.setup_sdk_servers_mock(count=1) network = compute_fakes.FakeNetwork.create_one_network() interface = compute_fakes.create_one_server_interface() self.sdk_client.create_server_interface.return_value = interface with mock.patch.object( self.app.client_manager, 'is_network_endpoint_enabled', return_value=False ): arglist = [ servers[0].id, network['id'], '--fixed-ip-address', '5.6.7.8', '--tag', 'tag1' ] verifylist = [ ('server', servers[0].id), ('network', network['id']), ('fixed_ip_address', '5.6.7.8'), ('tag', 'tag1') ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) expected_columns = ( 'Port ID', 'Server ID', 'Network ID', 'MAC Address', 'Port State', 'Fixed IPs', 'Tag', ) expected_data = ( interface.port_id, interface.server_id, interface.net_id, interface.mac_addr, interface.port_state, format_columns.ListDictColumn(interface.fixed_ips), interface.tag, ) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(expected_columns, columns) self.assertEqual(expected_data, tuple(data)) self.sdk_client.create_server_interface.assert_called_once_with( servers[0].id, net_id=network['id'], fixed_ip='5.6.7.8', tag='tag1', ) @mock.patch( 'openstackclient.api.compute_v2.APIv2.floating_ip_add' ) class TestServerAddFloatingIPCompute(compute_fakes.TestComputev2): def setUp(self): super(TestServerAddFloatingIPCompute, self).setUp() self.app.client_manager.network_endpoint_enabled = False # Get the command object to test self.cmd = server.AddFloatingIP(self.app, None) def test_server_add_floating_ip_default(self, fip_mock): _floating_ip = compute_fakes.FakeFloatingIP.create_one_floating_ip() arglist = [ 'server1', _floating_ip['ip'], ] verifylist = [ ('server', 'server1'), ('ip_address', _floating_ip['ip']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) fip_mock.assert_called_once_with( 'server1', _floating_ip['ip'], fixed_address=None, ) def test_server_add_floating_ip_fixed(self, fip_mock): _floating_ip = compute_fakes.FakeFloatingIP.create_one_floating_ip() arglist = [ '--fixed-ip-address', _floating_ip['fixed_ip'], 'server1', _floating_ip['ip'], ] verifylist = [ ('fixed_ip_address', _floating_ip['fixed_ip']), ('server', 'server1'), ('ip_address', _floating_ip['ip']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) fip_mock.assert_called_once_with( 'server1', _floating_ip['ip'], fixed_address=_floating_ip['fixed_ip'], ) class TestServerAddFloatingIPNetwork( TestServer, network_fakes.TestNetworkV2, ): def setUp(self): super(TestServerAddFloatingIPNetwork, self).setUp() self.app.client_manager.network = mock.Mock() self.network = self.app.client_manager.network self.network.update_ip = mock.Mock(return_value=None) # Get the command object to test self.cmd = server.AddFloatingIP(self.app, self.namespace) def test_server_add_floating_ip(self): _server = compute_fakes.FakeServer.create_one_server() self.servers_mock.get.return_value = _server _port = network_fakes.create_one_port() _floating_ip = network_fakes.FakeFloatingIP.create_one_floating_ip() self.network.find_ip = mock.Mock(return_value=_floating_ip) self.network.ports = mock.Mock(return_value=[_port]) arglist = [ _server.id, _floating_ip['floating_ip_address'], ] verifylist = [ ('server', _server.id), ('ip_address', _floating_ip['floating_ip_address']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) attrs = { 'port_id': _port.id, } self.network.find_ip.assert_called_once_with( _floating_ip['floating_ip_address'], ignore_missing=False, ) self.network.ports.assert_called_once_with( device_id=_server.id, ) self.network.update_ip.assert_called_once_with( _floating_ip, **attrs ) def test_server_add_floating_ip_no_ports(self): server = compute_fakes.FakeServer.create_one_server() floating_ip = network_fakes.FakeFloatingIP.create_one_floating_ip() self.servers_mock.get.return_value = server self.network.find_ip = mock.Mock(return_value=floating_ip) self.network.ports = mock.Mock(return_value=[]) arglist = [ server.id, floating_ip['floating_ip_address'], ] verifylist = [ ('server', server.id), ('ip_address', floating_ip['floating_ip_address']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) ex = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( 'No attached ports found to associate floating IP with', str(ex)) self.network.find_ip.assert_called_once_with( floating_ip['floating_ip_address'], ignore_missing=False, ) self.network.ports.assert_called_once_with( device_id=server.id, ) def test_server_add_floating_ip_no_external_gateway(self, success=False): _server = compute_fakes.FakeServer.create_one_server() self.servers_mock.get.return_value = _server _port = network_fakes.create_one_port() _floating_ip = network_fakes.FakeFloatingIP.create_one_floating_ip() self.network.find_ip = mock.Mock(return_value=_floating_ip) return_value = [_port] # In the success case, we'll have two ports, where the first port is # not attached to an external gateway but the second port is. if success: return_value.append(_port) self.network.ports = mock.Mock(return_value=return_value) side_effect = [sdk_exceptions.NotFoundException()] if success: side_effect.append(None) self.network.update_ip = mock.Mock(side_effect=side_effect) arglist = [ _server.id, _floating_ip['floating_ip_address'], ] verifylist = [ ('server', _server.id), ('ip_address', _floating_ip['floating_ip_address']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) if success: self.cmd.take_action(parsed_args) else: self.assertRaises(sdk_exceptions.NotFoundException, self.cmd.take_action, parsed_args) attrs = { 'port_id': _port.id, } self.network.find_ip.assert_called_once_with( _floating_ip['floating_ip_address'], ignore_missing=False, ) self.network.ports.assert_called_once_with( device_id=_server.id, ) if success: self.assertEqual(2, self.network.update_ip.call_count) calls = [mock.call(_floating_ip, **attrs)] * 2 self.network.update_ip.assert_has_calls(calls) else: self.network.update_ip.assert_called_once_with( _floating_ip, **attrs ) def test_server_add_floating_ip_one_external_gateway(self): self.test_server_add_floating_ip_no_external_gateway(success=True) def test_server_add_floating_ip_with_fixed_ip(self): _server = compute_fakes.FakeServer.create_one_server() self.servers_mock.get.return_value = _server _port = network_fakes.create_one_port() _floating_ip = network_fakes.FakeFloatingIP.create_one_floating_ip() self.network.find_ip = mock.Mock(return_value=_floating_ip) self.network.ports = mock.Mock(return_value=[_port]) # The user has specified a fixed ip that matches one of the ports # already attached to the instance. arglist = [ '--fixed-ip-address', _port.fixed_ips[0]['ip_address'], _server.id, _floating_ip['floating_ip_address'], ] verifylist = [ ('fixed_ip_address', _port.fixed_ips[0]['ip_address']), ('server', _server.id), ('ip_address', _floating_ip['floating_ip_address']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) # We expect the update_ip call to specify a new fixed_ip_address which # will overwrite the floating ip's existing fixed_ip_address. attrs = { 'port_id': _port.id, 'fixed_ip_address': _port.fixed_ips[0]['ip_address'], } self.network.find_ip.assert_called_once_with( _floating_ip['floating_ip_address'], ignore_missing=False, ) self.network.ports.assert_called_once_with( device_id=_server.id, ) self.network.update_ip.assert_called_once_with( _floating_ip, **attrs ) def test_server_add_floating_ip_with_fixed_ip_no_port_found(self): _server = compute_fakes.FakeServer.create_one_server() self.servers_mock.get.return_value = _server _port = network_fakes.create_one_port() _floating_ip = network_fakes.FakeFloatingIP.create_one_floating_ip() self.network.find_ip = mock.Mock(return_value=_floating_ip) self.network.ports = mock.Mock(return_value=[_port]) # The user has specified a fixed ip that does not match any of the # ports already attached to the instance. nonexistent_ip = '10.0.0.9' arglist = [ '--fixed-ip-address', nonexistent_ip, _server.id, _floating_ip['floating_ip_address'], ] verifylist = [ ('fixed_ip_address', nonexistent_ip), ('server', _server.id), ('ip_address', _floating_ip['floating_ip_address']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.network.find_ip.assert_called_once_with( _floating_ip['floating_ip_address'], ignore_missing=False, ) self.network.ports.assert_called_once_with( device_id=_server.id, ) self.network.update_ip.assert_not_called() class TestServerAddPort(TestServer): def setUp(self): super(TestServerAddPort, self).setUp() # Get the command object to test self.cmd = server.AddPort(self.app, None) # Set add_fixed_ip method to be tested. self.methods = { 'interface_attach': None, } self.find_port = mock.Mock() self.app.client_manager.network.find_port = self.find_port def _test_server_add_port(self, port_id): servers = self.setup_sdk_servers_mock(count=1) port = 'fake-port' arglist = [ servers[0].id, port, ] verifylist = [ ('server', servers[0].id), ('port', port) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.sdk_client.create_server_interface.assert_called_once_with( servers[0], port_id=port_id, fixed_ip=None) self.assertIsNone(result) def test_server_add_port(self): self._test_server_add_port(self.find_port.return_value.id) self.find_port.assert_called_once_with( 'fake-port', ignore_missing=False) def test_server_add_port_no_neutron(self): self.app.client_manager.network_endpoint_enabled = False self._test_server_add_port('fake-port') self.find_port.assert_not_called() @mock.patch.object(sdk_utils, 'supports_microversion', return_value=True) def test_server_add_port_with_tag(self, sm_mock): self.app.client_manager.compute.api_version = api_versions.APIVersion( '2.49') servers = self.setup_sdk_servers_mock(count=1) self.find_port.return_value.id = 'fake-port' arglist = [ servers[0].id, 'fake-port', '--tag', 'tag1', ] verifylist = [ ('server', servers[0].id), ('port', 'fake-port'), ('tag', 'tag1'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.assertIsNone(result) self.sdk_client.create_server_interface.assert_called_once_with( servers[0], port_id='fake-port', fixed_ip=None, tag='tag1') @mock.patch.object(sdk_utils, 'supports_microversion', return_value=False) def test_server_add_port_with_tag_pre_v249(self, sm_mock): self.app.client_manager.compute.api_version = api_versions.APIVersion( '2.48') servers = self.setup_servers_mock(count=1) self.find_port.return_value.id = 'fake-port' arglist = [ servers[0].id, 'fake-port', '--tag', 'tag1', ] verifylist = [ ('server', servers[0].id), ('port', 'fake-port'), ('tag', 'tag1'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) ex = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-compute-api-version 2.49 or greater is required', str(ex)) class TestServerVolume(TestServer): def setUp(self): super(TestServerVolume, self).setUp() self.methods = { 'create_volume_attachment': None, } self.servers = self.setup_sdk_servers_mock(count=1) self.volumes = self.setup_sdk_volumes_mock(count=1) attrs = { 'server_id': self.servers[0].id, 'volume_id': self.volumes[0].id, } self.volume_attachment = \ compute_fakes.FakeVolumeAttachment.\ create_one_sdk_volume_attachment(attrs=attrs) self.sdk_client.create_volume_attachment.return_value = \ self.volume_attachment class TestServerAddVolume(TestServerVolume): def setUp(self): super(TestServerAddVolume, self).setUp() # Get the command object to test self.cmd = server.AddServerVolume(self.app, None) @mock.patch.object(sdk_utils, 'supports_microversion', return_value=False) def test_server_add_volume(self, sm_mock): arglist = [ '--device', '/dev/sdb', self.servers[0].id, self.volumes[0].id, ] verifylist = [ ('server', self.servers[0].id), ('volume', self.volumes[0].id), ('device', '/dev/sdb'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) expected_columns = ('ID', 'Server ID', 'Volume ID', 'Device') expected_data = ( self.volume_attachment.id, self.volume_attachment.server_id, self.volume_attachment.volume_id, '/dev/sdb', ) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(expected_columns, columns) self.assertEqual(expected_data, data) self.sdk_client.create_volume_attachment.assert_called_once_with( self.servers[0], volumeId=self.volumes[0].id, device='/dev/sdb') @mock.patch.object(sdk_utils, 'supports_microversion') def test_server_add_volume_with_tag(self, sm_mock): def side_effect(compute_client, version): if version == '2.49': return True return False sm_mock.side_effect = side_effect arglist = [ '--device', '/dev/sdb', '--tag', 'foo', self.servers[0].id, self.volumes[0].id, ] verifylist = [ ('server', self.servers[0].id), ('volume', self.volumes[0].id), ('device', '/dev/sdb'), ('tag', 'foo'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) expected_columns = ('ID', 'Server ID', 'Volume ID', 'Device', 'Tag') expected_data = ( self.volume_attachment.id, self.volume_attachment.server_id, self.volume_attachment.volume_id, self.volume_attachment.device, self.volume_attachment.tag, ) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(expected_columns, columns) self.assertEqual(expected_data, data) self.sdk_client.create_volume_attachment.assert_called_once_with( self.servers[0], volumeId=self.volumes[0].id, device='/dev/sdb', tag='foo') @mock.patch.object(sdk_utils, 'supports_microversion', return_value=False) def test_server_add_volume_with_tag_pre_v249(self, sm_mock): arglist = [ self.servers[0].id, self.volumes[0].id, '--tag', 'foo', ] verifylist = [ ('server', self.servers[0].id), ('volume', self.volumes[0].id), ('tag', 'foo'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) ex = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-compute-api-version 2.49 or greater is required', str(ex)) @mock.patch.object(sdk_utils, 'supports_microversion', return_value=True) def test_server_add_volume_with_enable_delete_on_termination( self, sm_mock, ): self.volume_attachment.delete_on_termination = True arglist = [ '--enable-delete-on-termination', '--device', '/dev/sdb', self.servers[0].id, self.volumes[0].id, ] verifylist = [ ('server', self.servers[0].id), ('volume', self.volumes[0].id), ('device', '/dev/sdb'), ('enable_delete_on_termination', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) expected_columns = ( 'ID', 'Server ID', 'Volume ID', 'Device', 'Tag', 'Delete On Termination', ) expected_data = ( self.volume_attachment.id, self.volume_attachment.server_id, self.volume_attachment.volume_id, self.volume_attachment.device, self.volume_attachment.tag, self.volume_attachment.delete_on_termination, ) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(expected_columns, columns) self.assertEqual(expected_data, data) self.sdk_client.create_volume_attachment.assert_called_once_with( self.servers[0], volumeId=self.volumes[0].id, device='/dev/sdb', delete_on_termination=True) @mock.patch.object(sdk_utils, 'supports_microversion', return_value=True) def test_server_add_volume_with_disable_delete_on_termination( self, sm_mock, ): self.volume_attachment.delete_on_termination = False arglist = [ '--disable-delete-on-termination', '--device', '/dev/sdb', self.servers[0].id, self.volumes[0].id, ] verifylist = [ ('server', self.servers[0].id), ('volume', self.volumes[0].id), ('device', '/dev/sdb'), ('disable_delete_on_termination', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) expected_columns = ( 'ID', 'Server ID', 'Volume ID', 'Device', 'Tag', 'Delete On Termination', ) expected_data = ( self.volume_attachment.id, self.volume_attachment.server_id, self.volume_attachment.volume_id, self.volume_attachment.device, self.volume_attachment.tag, self.volume_attachment.delete_on_termination, ) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(expected_columns, columns) self.assertEqual(expected_data, data) self.sdk_client.create_volume_attachment.assert_called_once_with( self.servers[0], volumeId=self.volumes[0].id, device='/dev/sdb', delete_on_termination=False) @mock.patch.object(sdk_utils, 'supports_microversion') def test_server_add_volume_with_enable_delete_on_termination_pre_v279( self, sm_mock, ): def side_effect(compute_client, version): if version == '2.79': return False return True sm_mock.side_effect = side_effect arglist = [ self.servers[0].id, self.volumes[0].id, '--enable-delete-on-termination', ] verifylist = [ ('server', self.servers[0].id), ('volume', self.volumes[0].id), ('enable_delete_on_termination', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) ex = self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn('--os-compute-api-version 2.79 or greater is required', str(ex)) @mock.patch.object(sdk_utils, 'supports_microversion') def test_server_add_volume_with_disable_delete_on_termination_pre_v279( self, sm_mock, ): def side_effect(compute_client, version): if version == '2.79': return False return True sm_mock.side_effect = side_effect arglist = [ self.servers[0].id, self.volumes[0].id, '--disable-delete-on-termination', ] verifylist = [ ('server', self.servers[0].id), ('volume', self.volumes[0].id), ('disable_delete_on_termination', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) ex = self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn('--os-compute-api-version 2.79 or greater is required', str(ex)) @mock.patch.object(sdk_utils, 'supports_microversion', return_value=True) def test_server_add_volume_with_disable_and_enable_delete_on_termination( self, sm_mock, ): arglist = [ '--enable-delete-on-termination', '--disable-delete-on-termination', '--device', '/dev/sdb', self.servers[0].id, self.volumes[0].id, ] verifylist = [ ('server', self.servers[0].id), ('volume', self.volumes[0].id), ('device', '/dev/sdb'), ('enable_delete_on_termination', True), ('disable_delete_on_termination', True), ] ex = self.assertRaises(utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) self.assertIn('argument --disable-delete-on-termination: not allowed ' 'with argument --enable-delete-on-termination', str(ex)) class TestServerRemoveVolume(TestServerVolume): def setUp(self): super(TestServerRemoveVolume, self).setUp() # Get the command object to test self.cmd = server.RemoveServerVolume(self.app, None) def test_server_remove_volume(self): arglist = [ self.servers[0].id, self.volumes[0].id, ] verifylist = [ ('server', self.servers[0].id), ('volume', self.volumes[0].id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.assertIsNone(result) self.sdk_client.delete_volume_attachment.assert_called_once_with( self.volumes[0], self.servers[0], ignore_missing=False, ) class TestServerAddNetwork(TestServer): def setUp(self): super(TestServerAddNetwork, self).setUp() # Get the command object to test self.cmd = server.AddNetwork(self.app, None) # Set add_fixed_ip method to be tested. self.methods = { 'interface_attach': None, } self.find_network = mock.Mock() self.app.client_manager.network.find_network = self.find_network def _test_server_add_network(self, net_id): servers = self.setup_sdk_servers_mock(count=1) network = 'fake-network' arglist = [ servers[0].id, network, ] verifylist = [ ('server', servers[0].id), ('network', network) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.sdk_client.create_server_interface.assert_called_once_with( servers[0], net_id=net_id, fixed_ip=None) self.assertIsNone(result) def test_server_add_network(self): self._test_server_add_network(self.find_network.return_value.id) self.find_network.assert_called_once_with( 'fake-network', ignore_missing=False) def test_server_add_network_no_neutron(self): self.app.client_manager.network_endpoint_enabled = False self._test_server_add_network('fake-network') self.find_network.assert_not_called() @mock.patch.object(sdk_utils, 'supports_microversion', return_value=True) def test_server_add_network_with_tag(self, sm_mock): self.app.client_manager.compute.api_version = api_versions.APIVersion( '2.49') servers = self.setup_sdk_servers_mock(count=1) self.find_network.return_value.id = 'fake-network' arglist = [ servers[0].id, 'fake-network', '--tag', 'tag1', ] verifylist = [ ('server', servers[0].id), ('network', 'fake-network'), ('tag', 'tag1'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.assertIsNone(result) self.sdk_client.create_server_interface.assert_called_once_with( servers[0], net_id='fake-network', fixed_ip=None, tag='tag1' ) @mock.patch.object(sdk_utils, 'supports_microversion', return_value=False) def test_server_add_network_with_tag_pre_v249(self, sm_mock): self.app.client_manager.compute.api_version = api_versions.APIVersion( '2.48') servers = self.setup_sdk_servers_mock(count=1) self.find_network.return_value.id = 'fake-network' arglist = [ servers[0].id, 'fake-network', '--tag', 'tag1', ] verifylist = [ ('server', servers[0].id), ('network', 'fake-network'), ('tag', 'tag1'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) ex = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-compute-api-version 2.49 or greater is required', str(ex)) @mock.patch( 'openstackclient.api.compute_v2.APIv2.security_group_find' ) class TestServerAddSecurityGroup(TestServer): def setUp(self): super(TestServerAddSecurityGroup, self).setUp() self.security_group = \ compute_fakes.FakeSecurityGroup.create_one_security_group() attrs = { 'security_groups': [{'name': self.security_group['id']}] } methods = { 'add_security_group': None, } self.server = compute_fakes.FakeServer.create_one_server( attrs=attrs, methods=methods ) # This is the return value for utils.find_resource() for server self.servers_mock.get.return_value = self.server # Get the command object to test self.cmd = server.AddServerSecurityGroup(self.app, None) def test_server_add_security_group(self, sg_find_mock): sg_find_mock.return_value = self.security_group arglist = [ self.server.id, self.security_group['id'] ] verifylist = [ ('server', self.server.id), ('group', self.security_group['id']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) sg_find_mock.assert_called_with( self.security_group['id'], ) self.servers_mock.get.assert_called_with(self.server.id) self.server.add_security_group.assert_called_with( self.security_group['id'], ) self.assertIsNone(result) class TestServerCreate(TestServer): columns = ( 'OS-EXT-STS:power_state', 'addresses', 'flavor', 'id', 'image', 'name', 'networks', 'properties', ) def datalist(self): datalist = ( server.PowerStateColumn( getattr(self.new_server, 'OS-EXT-STS:power_state')), format_columns.DictListColumn({}), self.flavor.name + ' (' + self.new_server.flavor.get('id') + ')', self.new_server.id, self.image.name + ' (' + self.new_server.image.get('id') + ')', self.new_server.name, self.new_server.networks, format_columns.DictColumn(self.new_server.metadata), ) return datalist def setUp(self): super(TestServerCreate, self).setUp() attrs = { 'networks': {}, } self.new_server = compute_fakes.FakeServer.create_one_server( attrs=attrs) # This is the return value for utils.find_resource(). # This is for testing --wait option. self.servers_mock.get.return_value = self.new_server self.servers_mock.create.return_value = self.new_server self.image = image_fakes.create_one_image() self.find_image_mock.return_value = self.image self.get_image_mock.return_value = self.image self.flavor = compute_fakes.FakeFlavor.create_one_flavor() self.flavors_mock.get.return_value = self.flavor self.volume = volume_fakes.FakeVolume.create_one_volume() self.volumes_mock.get.return_value = self.volume self.snapshot = volume_fakes.FakeSnapshot.create_one_snapshot() self.snapshots_mock.get.return_value = self.snapshot # Get the command object to test self.cmd = server.CreateServer(self.app, None) def test_server_create_no_options(self): arglist = [ self.new_server.name, ] verifylist = [ ('server_name', self.new_server.name), ] self.assertRaises(utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_server_create_minimal(self): arglist = [ '--image', 'image1', '--flavor', 'flavor1', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # In base command class ShowOne in cliff, abstract method take_action() # returns a two-part tuple with a tuple of column names and a tuple of # data to be shown. columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[], nics=[], scheduler_hints={}, config_drive=None, ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) self.assertFalse(self.images_mock.called) self.assertFalse(self.flavors_mock.called) def test_server_create_with_options(self): arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--key-name', 'keyname', '--property', 'Beta=b', '--security-group', 'securitygroup', '--use-config-drive', '--password', 'passw0rd', '--hint', 'a=b', '--hint', 'a=c', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('key_name', 'keyname'), ('properties', {'Beta': 'b'}), ('security_group', ['securitygroup']), ('hint', {'a': ['b', 'c']}), ('config_drive', True), ('password', 'passw0rd'), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # In base command class ShowOne in cliff, abstract method take_action() # returns a two-part tuple with a tuple of column names and a tuple of # data to be shown. fake_sg = network_fakes.FakeSecurityGroup.create_security_groups() mock_find_sg = ( network_fakes.FakeSecurityGroup.get_security_groups(fake_sg) ) self.app.client_manager.network.find_security_group = mock_find_sg columns, data = self.cmd.take_action(parsed_args) mock_find_sg.assert_called_once_with('securitygroup', ignore_missing=False) # Set expected values kwargs = dict( meta={'Beta': 'b'}, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[fake_sg[0].id], userdata=None, key_name='keyname', availability_zone=None, admin_pass='passw0rd', block_device_mapping_v2=[], nics=[], scheduler_hints={'a': ['b', 'c']}, config_drive=True, ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_not_exist_security_group(self): arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--key-name', 'keyname', '--security-group', 'securitygroup', '--security-group', 'not_exist_sg', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('key_name', 'keyname'), ('security_group', ['securitygroup', 'not_exist_sg']), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) fake_sg = network_fakes.FakeSecurityGroup.create_security_groups( count=1) fake_sg.append(exceptions.NotFound(code=404)) mock_find_sg = ( network_fakes.FakeSecurityGroup.get_security_groups(fake_sg) ) self.app.client_manager.network.find_security_group = mock_find_sg self.assertRaises(exceptions.NotFound, self.cmd.take_action, parsed_args) mock_find_sg.assert_called_with('not_exist_sg', ignore_missing=False) def test_server_create_with_security_group_in_nova_network(self): arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--key-name', 'keyname', '--security-group', 'securitygroup', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('key_name', 'keyname'), ('security_group', ['securitygroup']), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(self.app.client_manager, 'is_network_endpoint_enabled', return_value=False): with mock.patch.object(self.app.client_manager.compute.api, 'security_group_find', return_value={'name': 'fake_sg'} ) as mock_find: columns, data = self.cmd.take_action(parsed_args) mock_find.assert_called_once_with('securitygroup') # Set expected values kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=['fake_sg'], userdata=None, key_name='keyname', availability_zone=None, admin_pass=None, block_device_mapping_v2=[], nics=[], scheduler_hints={}, config_drive=None, ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_network(self): arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--network', 'net1', '--nic', 'net-id=net1,v4-fixed-ip=10.0.0.2', '--port', 'port1', '--network', 'net1', '--nic', 'port-id=port2', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('nics', [ { 'net-id': 'net1', 'port-id': '', 'v4-fixed-ip': '', 'v6-fixed-ip': '', }, { 'net-id': 'net1', 'port-id': '', 'v4-fixed-ip': '10.0.0.2', 'v6-fixed-ip': '', }, { 'net-id': '', 'port-id': 'port1', 'v4-fixed-ip': '', 'v6-fixed-ip': '', }, { 'net-id': 'net1', 'port-id': '', 'v4-fixed-ip': '', 'v6-fixed-ip': '', }, { 'net-id': '', 'port-id': 'port2', 'v4-fixed-ip': '', 'v6-fixed-ip': '', }, ]), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) get_endpoints = mock.Mock() get_endpoints.return_value = {'network': []} self.app.client_manager.auth_ref = mock.Mock() self.app.client_manager.auth_ref.service_catalog = mock.Mock() self.app.client_manager.auth_ref.service_catalog.get_endpoints = ( get_endpoints) find_network = mock.Mock() find_port = mock.Mock() network_client = self.app.client_manager.network network_client.find_network = find_network network_client.find_port = find_port network_resource = mock.Mock(id='net1_uuid') port1_resource = mock.Mock(id='port1_uuid') port2_resource = mock.Mock(id='port2_uuid') find_network.return_value = network_resource find_port.side_effect = (lambda port_id, ignore_missing: {"port1": port1_resource, "port2": port2_resource}[port_id]) # Mock sdk APIs. _network = mock.Mock(id='net1_uuid') _port1 = mock.Mock(id='port1_uuid') _port2 = mock.Mock(id='port2_uuid') find_network = mock.Mock() find_port = mock.Mock() find_network.return_value = _network find_port.side_effect = (lambda port_id, ignore_missing: {"port1": _port1, "port2": _port2}[port_id]) self.app.client_manager.network.find_network = find_network self.app.client_manager.network.find_port = find_port # In base command class ShowOne in cliff, abstract method take_action() # returns a two-part tuple with a tuple of column names and a tuple of # data to be shown. columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[], nics=[{'net-id': 'net1_uuid', 'v4-fixed-ip': '', 'v6-fixed-ip': '', 'port-id': ''}, {'net-id': 'net1_uuid', 'v4-fixed-ip': '10.0.0.2', 'v6-fixed-ip': '', 'port-id': ''}, {'net-id': '', 'v4-fixed-ip': '', 'v6-fixed-ip': '', 'port-id': 'port1_uuid'}, {'net-id': 'net1_uuid', 'v4-fixed-ip': '', 'v6-fixed-ip': '', 'port-id': ''}, {'net-id': '', 'v4-fixed-ip': '', 'v6-fixed-ip': '', 'port-id': 'port2_uuid'}], scheduler_hints={}, config_drive=None, ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_network_tag(self): self.app.client_manager.compute.api_version = api_versions.APIVersion( '2.43') arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--nic', 'net-id=net1,tag=foo', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('nics', [ { 'net-id': 'net1', 'port-id': '', 'v4-fixed-ip': '', 'v6-fixed-ip': '', 'tag': 'foo', }, ]), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) find_network = mock.Mock() network_client = self.app.client_manager.network network_client.find_network = find_network network_resource = mock.Mock(id='net1_uuid') find_network.return_value = network_resource # Mock sdk APIs. _network = mock.Mock(id='net1_uuid') find_network = mock.Mock() find_network.return_value = _network self.app.client_manager.network.find_network = find_network # In base command class ShowOne in cliff, abstract method take_action() # returns a two-part tuple with a tuple of column names and a tuple of # data to be shown. columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[], nics=[ { 'net-id': 'net1_uuid', 'v4-fixed-ip': '', 'v6-fixed-ip': '', 'port-id': '', 'tag': 'foo', }, ], scheduler_hints={}, config_drive=None, ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) network_client.find_network.assert_called_once() self.app.client_manager.network.find_network.assert_called_once() def test_server_create_with_network_tag_pre_v243(self): self.app.client_manager.compute.api_version = api_versions.APIVersion( '2.42') arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--nic', 'net-id=net1,tag=foo', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('nics', [ { 'net-id': 'net1', 'port-id': '', 'v4-fixed-ip': '', 'v6-fixed-ip': '', 'tag': 'foo', }, ]), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) def test_server_create_with_auto_network(self): arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--nic', 'auto', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('nics', ['auto']), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[], nics='auto', scheduler_hints={}, config_drive=None, ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_auto_network_default_v2_37(self): """Tests creating a server without specifying --nic using 2.37.""" arglist = [ '--image', 'image1', '--flavor', 'flavor1', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # Since check_parser doesn't handle compute global options like # --os-compute-api-version, we have to mock the construction of # the novaclient client object with our own APIVersion. with mock.patch.object(self.app.client_manager.compute, 'api_version', api_versions.APIVersion('2.37')): columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[], nics='auto', scheduler_hints={}, config_drive=None, ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_none_network(self): arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--nic', 'none', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('nics', ['none']), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[], nics='none', scheduler_hints={}, config_drive=None, ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_conflict_network_options(self): arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--nic', 'none', '--nic', 'auto', '--nic', 'port-id=port1', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('nics', [ 'none', 'auto', { 'net-id': '', 'port-id': 'port1', 'v4-fixed-ip': '', 'v6-fixed-ip': '', }, ]), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) get_endpoints = mock.Mock() get_endpoints.return_value = {'network': []} self.app.client_manager.auth_ref = mock.Mock() self.app.client_manager.auth_ref.service_catalog = mock.Mock() self.app.client_manager.auth_ref.service_catalog.get_endpoints = ( get_endpoints) find_port = mock.Mock() network_client = self.app.client_manager.network network_client.find_port = find_port port_resource = mock.Mock(id='port1_uuid') find_port.return_value = port_resource self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertNotCalled(self.servers_mock.create) def test_server_create_with_invalid_network_options(self): arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--nic', 'abcdefgh', self.new_server.name, ] self.assertRaises( argparse.ArgumentTypeError, self.check_parser, self.cmd, arglist, []) self.assertNotCalled(self.servers_mock.create) def test_server_create_with_invalid_network_key(self): arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--nic', 'abcdefgh=12324', self.new_server.name, ] self.assertRaises( argparse.ArgumentTypeError, self.check_parser, self.cmd, arglist, []) self.assertNotCalled(self.servers_mock.create) def test_server_create_with_empty_network_key_value(self): arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--nic', 'net-id=', self.new_server.name, ] self.assertRaises( argparse.ArgumentTypeError, self.check_parser, self.cmd, arglist, []) self.assertNotCalled(self.servers_mock.create) def test_server_create_with_only_network_key(self): arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--nic', 'net-id', self.new_server.name, ] self.assertRaises( argparse.ArgumentTypeError, self.check_parser, self.cmd, arglist, []) self.assertNotCalled(self.servers_mock.create) @mock.patch.object(common_utils, 'wait_for_status', return_value=True) def test_server_create_with_wait_ok(self, mock_wait_for_status): arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--wait', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('config_drive', False), ('wait', True), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) mock_wait_for_status.assert_called_once_with( self.servers_mock.get, self.new_server.id, callback=mock.ANY, ) kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[], nics=[], scheduler_hints={}, config_drive=None, ) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) @mock.patch.object(common_utils, 'wait_for_status', return_value=False) def test_server_create_with_wait_fails(self, mock_wait_for_status): arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--wait', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('config_drive', False), ('wait', True), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(SystemExit, self.cmd.take_action, parsed_args) mock_wait_for_status.assert_called_once_with( self.servers_mock.get, self.new_server.id, callback=mock.ANY, ) kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[], nics=[], scheduler_hints={}, config_drive=None, ) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) @mock.patch('openstackclient.compute.v2.server.io.open') def test_server_create_userdata(self, mock_open): mock_file = mock.Mock(name='File') mock_open.return_value = mock_file mock_open.read.return_value = '#!/bin/sh' arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--user-data', 'userdata.sh', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('user_data', 'userdata.sh'), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # In base command class ShowOne in cliff, abstract method take_action() # returns a two-part tuple with a tuple of column names and a tuple of # data to be shown. columns, data = self.cmd.take_action(parsed_args) # Ensure the userdata file is opened mock_open.assert_called_with('userdata.sh') # Ensure the userdata file is closed mock_file.close.assert_called_with() # Set expected values kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=mock_file, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[], nics=[], scheduler_hints={}, config_drive=None, ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_volume(self): arglist = [ '--flavor', self.flavor.id, '--volume', self.volume.name, self.new_server.name, ] verifylist = [ ('flavor', self.flavor.id), ('volume', self.volume.name), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # CreateServer.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = { 'meta': None, 'files': {}, 'reservation_id': None, 'min_count': 1, 'max_count': 1, 'security_groups': [], 'userdata': None, 'key_name': None, 'availability_zone': None, 'admin_pass': None, 'block_device_mapping_v2': [{ 'uuid': self.volume.id, 'boot_index': '0', 'source_type': 'volume', 'destination_type': 'volume', }], 'nics': [], 'scheduler_hints': {}, 'config_drive': None, } # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, None, self.flavor, **kwargs ) self.volumes_mock.get.assert_called_once_with( self.volume.name) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_snapshot(self): arglist = [ '--flavor', self.flavor.id, '--snapshot', self.snapshot.name, self.new_server.name, ] verifylist = [ ('flavor', self.flavor.id), ('snapshot', self.snapshot.name), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # CreateServer.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = { 'meta': None, 'files': {}, 'reservation_id': None, 'min_count': 1, 'max_count': 1, 'security_groups': [], 'userdata': None, 'key_name': None, 'availability_zone': None, 'admin_pass': None, 'block_device_mapping_v2': [{ 'uuid': self.snapshot.id, 'boot_index': '0', 'source_type': 'snapshot', 'destination_type': 'volume', 'delete_on_termination': False, }], 'nics': [], 'scheduler_hints': {}, 'config_drive': None, } # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, None, self.flavor, **kwargs ) self.snapshots_mock.get.assert_called_once_with( self.snapshot.name) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_block_device(self): block_device = f'uuid={self.volume.id},source_type=volume' arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--block-device', block_device, self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', self.flavor.id), ('block_devices', [ { 'uuid': self.volume.id, 'source_type': 'volume', }, ]), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # CreateServer.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = { 'meta': None, 'files': {}, 'reservation_id': None, 'min_count': 1, 'max_count': 1, 'security_groups': [], 'userdata': None, 'key_name': None, 'availability_zone': None, 'admin_pass': None, 'block_device_mapping_v2': [{ 'uuid': self.volume.id, 'source_type': 'volume', 'destination_type': 'volume', }], 'nics': [], 'scheduler_hints': {}, 'config_drive': None, } # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_block_device_full(self): self.app.client_manager.compute.api_version = api_versions.APIVersion( '2.67') block_device = ( f'uuid={self.volume.id},source_type=volume,' f'destination_type=volume,disk_bus=ide,device_type=disk,' f'device_name=sdb,guest_format=ext4,volume_size=64,' f'volume_type=foo,boot_index=1,delete_on_termination=true,' f'tag=foo' ) arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--block-device', block_device, self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', self.flavor.id), ('block_devices', [ { 'uuid': self.volume.id, 'source_type': 'volume', 'destination_type': 'volume', 'disk_bus': 'ide', 'device_type': 'disk', 'device_name': 'sdb', 'guest_format': 'ext4', 'volume_size': '64', 'volume_type': 'foo', 'boot_index': '1', 'delete_on_termination': 'true', 'tag': 'foo', }, ]), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # CreateServer.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = { 'meta': None, 'files': {}, 'reservation_id': None, 'min_count': 1, 'max_count': 1, 'security_groups': [], 'userdata': None, 'key_name': None, 'availability_zone': None, 'admin_pass': None, 'block_device_mapping_v2': [{ 'uuid': self.volume.id, 'source_type': 'volume', 'destination_type': 'volume', 'disk_bus': 'ide', 'device_name': 'sdb', 'volume_size': '64', 'guest_format': 'ext4', 'boot_index': 1, 'device_type': 'disk', 'delete_on_termination': True, 'tag': 'foo', 'volume_type': 'foo', }], 'nics': 'auto', 'scheduler_hints': {}, 'config_drive': None, } # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_block_device_from_file(self): self.app.client_manager.compute.api_version = api_versions.APIVersion( '2.67') block_device = { 'uuid': self.volume.id, 'source_type': 'volume', 'destination_type': 'volume', 'disk_bus': 'ide', 'device_type': 'disk', 'device_name': 'sdb', 'guest_format': 'ext4', 'volume_size': 64, 'volume_type': 'foo', 'boot_index': 1, 'delete_on_termination': True, 'tag': 'foo', } with tempfile.NamedTemporaryFile(mode='w+') as fp: json.dump(block_device, fp=fp) fp.flush() arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--block-device', fp.name, self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', self.flavor.id), ('block_devices', [block_device]), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # CreateServer.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = { 'meta': None, 'files': {}, 'reservation_id': None, 'min_count': 1, 'max_count': 1, 'security_groups': [], 'userdata': None, 'key_name': None, 'availability_zone': None, 'admin_pass': None, 'block_device_mapping_v2': [{ 'uuid': self.volume.id, 'source_type': 'volume', 'destination_type': 'volume', 'disk_bus': 'ide', 'device_name': 'sdb', 'volume_size': 64, 'guest_format': 'ext4', 'boot_index': 1, 'device_type': 'disk', 'delete_on_termination': True, 'tag': 'foo', 'volume_type': 'foo', }], 'nics': 'auto', 'scheduler_hints': {}, 'config_drive': None, } # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_block_device_invalid_boot_index(self): block_device = \ f'uuid={self.volume.name},source_type=volume,boot_index=foo' arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--block-device', block_device, self.new_server.name, ] parsed_args = self.check_parser(self.cmd, arglist, []) ex = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn('The boot_index key of --block-device ', str(ex)) def test_server_create_with_block_device_invalid_source_type(self): block_device = f'uuid={self.volume.name},source_type=foo' arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--block-device', block_device, self.new_server.name, ] parsed_args = self.check_parser(self.cmd, arglist, []) ex = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn('The source_type key of --block-device ', str(ex)) def test_server_create_with_block_device_invalid_destination_type(self): block_device = \ f'uuid={self.volume.name},destination_type=foo' arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--block-device', block_device, self.new_server.name, ] parsed_args = self.check_parser(self.cmd, arglist, []) ex = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn('The destination_type key of --block-device ', str(ex)) def test_server_create_with_block_device_invalid_shutdown(self): block_device = \ f'uuid={self.volume.name},delete_on_termination=foo' arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--block-device', block_device, self.new_server.name, ] parsed_args = self.check_parser(self.cmd, arglist, []) ex = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( 'The delete_on_termination key of --block-device ', str(ex)) def test_server_create_with_block_device_tag_pre_v242(self): self.app.client_manager.compute.api_version = api_versions.APIVersion( '2.41') block_device = \ f'uuid={self.volume.name},tag=foo' arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--block-device', block_device, self.new_server.name, ] parsed_args = self.check_parser(self.cmd, arglist, []) ex = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-compute-api-version 2.42 or greater is required', str(ex)) def test_server_create_with_block_device_volume_type_pre_v267(self): self.app.client_manager.compute.api_version = api_versions.APIVersion( '2.66') block_device = f'uuid={self.volume.name},volume_type=foo' arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--block-device', block_device, self.new_server.name, ] parsed_args = self.check_parser(self.cmd, arglist, []) ex = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-compute-api-version 2.67 or greater is required', str(ex)) def test_server_create_with_block_device_mapping(self): arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--block-device-mapping', 'vda=' + self.volume.name + ':::false', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', self.flavor.id), ('block_device_mapping', [ { 'device_name': 'vda', 'uuid': self.volume.name, 'source_type': 'volume', 'destination_type': 'volume', 'delete_on_termination': 'false', } ]), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # CreateServer.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[{ 'device_name': 'vda', 'uuid': self.volume.id, 'destination_type': 'volume', 'source_type': 'volume', 'delete_on_termination': 'false', }], nics=[], scheduler_hints={}, config_drive=None, ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_block_device_mapping_min_input(self): arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--block-device-mapping', 'vdf=' + self.volume.name, self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', self.flavor.id), ('block_device_mapping', [ { 'device_name': 'vdf', 'uuid': self.volume.name, 'source_type': 'volume', 'destination_type': 'volume', } ]), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # CreateServer.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[{ 'device_name': 'vdf', 'uuid': self.volume.id, 'destination_type': 'volume', 'source_type': 'volume', }], nics=[], scheduler_hints={}, config_drive=None, ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_block_device_mapping_default_input(self): arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--block-device-mapping', 'vdf=' + self.volume.name + ':::', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', self.flavor.id), ('block_device_mapping', [ { 'device_name': 'vdf', 'uuid': self.volume.name, 'source_type': 'volume', 'destination_type': 'volume', } ]), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # CreateServer.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[{ 'device_name': 'vdf', 'uuid': self.volume.id, 'destination_type': 'volume', 'source_type': 'volume', }], nics=[], scheduler_hints={}, config_drive=None, ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_block_device_mapping_full_input(self): arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--block-device-mapping', 'vde=' + self.volume.name + ':volume:3:true', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', self.flavor.id), ('block_device_mapping', [ { 'device_name': 'vde', 'uuid': self.volume.name, 'source_type': 'volume', 'destination_type': 'volume', 'volume_size': '3', 'delete_on_termination': 'true', } ]), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # CreateServer.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[{ 'device_name': 'vde', 'uuid': self.volume.id, 'destination_type': 'volume', 'source_type': 'volume', 'delete_on_termination': 'true', 'volume_size': '3' }], nics=[], scheduler_hints={}, config_drive=None, ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_block_device_mapping_snapshot(self): arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--block-device-mapping', 'vds=' + self.volume.name + ':snapshot:5:true', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', self.flavor.id), ('block_device_mapping', [ { 'device_name': 'vds', 'uuid': self.volume.name, 'source_type': 'snapshot', 'volume_size': '5', 'destination_type': 'volume', 'delete_on_termination': 'true', } ]), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # CreateServer.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[{ 'device_name': 'vds', 'uuid': self.snapshot.id, 'destination_type': 'volume', 'source_type': 'snapshot', 'delete_on_termination': 'true', 'volume_size': '5' }], nics=[], scheduler_hints={}, config_drive=None, ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_block_device_mapping_multiple(self): arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--block-device-mapping', 'vdb=' + self.volume.name + ':::false', '--block-device-mapping', 'vdc=' + self.volume.name + ':::true', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', self.flavor.id), ('block_device_mapping', [ { 'device_name': 'vdb', 'uuid': self.volume.name, 'source_type': 'volume', 'destination_type': 'volume', 'delete_on_termination': 'false', }, { 'device_name': 'vdc', 'uuid': self.volume.name, 'source_type': 'volume', 'destination_type': 'volume', 'delete_on_termination': 'true', }, ]), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # CreateServer.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[ { 'device_name': 'vdb', 'uuid': self.volume.id, 'destination_type': 'volume', 'source_type': 'volume', 'delete_on_termination': 'false', }, { 'device_name': 'vdc', 'uuid': self.volume.id, 'destination_type': 'volume', 'source_type': 'volume', 'delete_on_termination': 'true', } ], nics=[], scheduler_hints={}, config_drive=None, ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_block_device_mapping_invalid_format(self): # block device mapping don't contain equal sign "=" arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--block-device-mapping', 'not_contain_equal_sign', self.new_server.name, ] self.assertRaises( argparse.ArgumentTypeError, self.check_parser, self.cmd, arglist, []) # block device mapping don't contain device name "=uuid:::true" arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--block-device-mapping', '=uuid:::true', self.new_server.name, ] self.assertRaises( argparse.ArgumentTypeError, self.check_parser, self.cmd, arglist, []) def test_server_create_with_block_device_mapping_no_uuid(self): arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--block-device-mapping', 'vdb=', self.new_server.name, ] self.assertRaises( argparse.ArgumentTypeError, self.check_parser, self.cmd, arglist, []) def test_server_create_volume_boot_from_volume_conflict(self): # Tests that specifying --volume and --boot-from-volume results in # an error. Since --boot-from-volume requires --image or # --image-property but those are in a mutex group with --volume, we # only specify --volume and --boot-from-volume for this test since # the validation is not handled with argparse. arglist = [ '--flavor', self.flavor.id, '--volume', 'volume1', '--boot-from-volume', '1', self.new_server.name, ] verifylist = [ ('flavor', self.flavor.id), ('volume', 'volume1'), ('boot_from_volume', 1), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) ex = self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) # Assert it is the error we expect. self.assertIn('--volume is not allowed with --boot-from-volume', str(ex)) def test_server_create_image_property(self): arglist = [ '--image-property', 'hypervisor_type=qemu', '--flavor', 'flavor1', '--nic', 'none', self.new_server.name, ] verifylist = [ ('image_properties', {'hypervisor_type': 'qemu'}), ('flavor', 'flavor1'), ('nics', ['none']), ('config_drive', False), ('server_name', self.new_server.name), ] # create a image_info as the side_effect of the fake image_list() image_info = { 'hypervisor_type': 'qemu', } _image = image_fakes.create_one_image(image_info) self.images_mock.return_value = [_image] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[], nics='none', meta=None, scheduler_hints={}, config_drive=None, ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, _image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_image_property_multi(self): arglist = [ '--image-property', 'hypervisor_type=qemu', '--image-property', 'hw_disk_bus=ide', '--flavor', 'flavor1', '--nic', 'none', self.new_server.name, ] verifylist = [ ('image_properties', {'hypervisor_type': 'qemu', 'hw_disk_bus': 'ide'}), ('flavor', 'flavor1'), ('nics', ['none']), ('config_drive', False), ('server_name', self.new_server.name), ] # create a image_info as the side_effect of the fake image_list() image_info = { 'hypervisor_type': 'qemu', 'hw_disk_bus': 'ide', } _image = image_fakes.create_one_image(image_info) self.images_mock.return_value = [_image] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[], nics='none', meta=None, scheduler_hints={}, config_drive=None, ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, _image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_image_property_missed(self): arglist = [ '--image-property', 'hypervisor_type=qemu', '--image-property', 'hw_disk_bus=virtio', '--flavor', 'flavor1', '--nic', 'none', self.new_server.name, ] verifylist = [ ('image_properties', {'hypervisor_type': 'qemu', 'hw_disk_bus': 'virtio'}), ('flavor', 'flavor1'), ('nics', ['none']), ('config_drive', False), ('server_name', self.new_server.name), ] # create a image_info as the side_effect of the fake image_list() image_info = { 'hypervisor_type': 'qemu', 'hw_disk_bus': 'ide', } _image = image_fakes.create_one_image(image_info) self.images_mock.return_value = [_image] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) def test_server_create_image_property_with_image_list(self): arglist = [ '--image-property', 'owner_specified.openstack.object=image/cirros', '--flavor', 'flavor1', '--nic', 'none', self.new_server.name, ] verifylist = [ ('image_properties', {'owner_specified.openstack.object': 'image/cirros'}), ('flavor', 'flavor1'), ('nics', ['none']), ('server_name', self.new_server.name), ] # create a image_info as the side_effect of the fake image_list() image_info = { 'properties': { 'owner_specified.openstack.object': 'image/cirros' } } target_image = image_fakes.create_one_image(image_info) another_image = image_fakes.create_one_image({}) self.images_mock.return_value = [target_image, another_image] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[], nics='none', meta=None, scheduler_hints={}, config_drive=None, ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, target_image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_swap(self): arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--swap', '1024', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', self.flavor.id), ('swap', 1024), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # CreateServer.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = { 'meta': None, 'files': {}, 'reservation_id': None, 'min_count': 1, 'max_count': 1, 'security_groups': [], 'userdata': None, 'key_name': None, 'availability_zone': None, 'admin_pass': None, 'block_device_mapping_v2': [{ 'boot_index': -1, 'source_type': 'blank', 'destination_type': 'local', 'guest_format': 'swap', 'volume_size': 1024, 'delete_on_termination': True, }], 'nics': [], 'scheduler_hints': {}, 'config_drive': None, } # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_ephemeral(self): arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--ephemeral', 'size=1024,format=ext4', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', self.flavor.id), ('ephemerals', [{'size': '1024', 'format': 'ext4'}]), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # CreateServer.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = { 'meta': None, 'files': {}, 'reservation_id': None, 'min_count': 1, 'max_count': 1, 'security_groups': [], 'userdata': None, 'key_name': None, 'availability_zone': None, 'admin_pass': None, 'block_device_mapping_v2': [{ 'boot_index': -1, 'source_type': 'blank', 'destination_type': 'local', 'guest_format': 'ext4', 'volume_size': '1024', 'delete_on_termination': True, }], 'nics': [], 'scheduler_hints': {}, 'config_drive': None, } # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) def test_server_create_with_ephemeral_missing_key(self): arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--ephemeral', 'format=ext3', self.new_server.name, ] self.assertRaises( argparse.ArgumentTypeError, self.check_parser, self.cmd, arglist, []) def test_server_create_with_ephemeral_invalid_key(self): arglist = [ '--image', 'image1', '--flavor', self.flavor.id, '--ephemeral', 'size=1024,foo=bar', self.new_server.name, ] self.assertRaises( argparse.ArgumentTypeError, self.check_parser, self.cmd, arglist, []) def test_server_create_invalid_hint(self): # Not a key-value pair arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--hint', 'a0cf03a5-d921-4877-bb5c-86d26cf818e1', self.new_server.name, ] self.assertRaises(argparse.ArgumentTypeError, self.check_parser, self.cmd, arglist, []) # Empty key arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--hint', '=a0cf03a5-d921-4877-bb5c-86d26cf818e1', self.new_server.name, ] self.assertRaises(argparse.ArgumentTypeError, self.check_parser, self.cmd, arglist, []) def test_server_create_with_description_api_newer(self): # Description is supported for nova api version 2.19 or above self.app.client_manager.compute.api_version = 2.19 arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--description', 'description1', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('description', 'description1'), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(api_versions, 'APIVersion', return_value=2.19): # In base command class ShowOne in cliff, abstract method # take_action() returns a two-part tuple with a tuple of # column names and a tuple of data to be shown. columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[], nics='auto', scheduler_hints={}, config_drive=None, description='description1', ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) self.assertFalse(self.images_mock.called) self.assertFalse(self.flavors_mock.called) def test_server_create_with_description_api_older(self): # Description is not supported for nova api version below 2.19 self.app.client_manager.compute.api_version = 2.18 arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--description', 'description1', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('description', 'description1'), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(api_versions, 'APIVersion', return_value=2.19): self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) def test_server_create_with_tag(self): self.app.client_manager.compute.api_version = api_versions.APIVersion( '2.52') arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--tag', 'tag1', '--tag', 'tag2', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('tags', ['tag1', 'tag2']), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = { 'meta': None, 'files': {}, 'reservation_id': None, 'min_count': 1, 'max_count': 1, 'security_groups': [], 'userdata': None, 'key_name': None, 'availability_zone': None, 'block_device_mapping_v2': [], 'admin_pass': None, 'nics': 'auto', 'scheduler_hints': {}, 'config_drive': None, 'tags': ['tag1', 'tag2'], } # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) self.assertFalse(self.images_mock.called) self.assertFalse(self.flavors_mock.called) def test_server_create_with_tag_pre_v252(self): self.app.client_manager.compute.api_version = api_versions.APIVersion( '2.51') arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--tag', 'tag1', '--tag', 'tag2', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('tags', ['tag1', 'tag2']), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) ex = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-compute-api-version 2.52 or greater is required', str(ex)) def test_server_create_with_host_v274(self): # Explicit host is supported for nova api version 2.74 or above self.app.client_manager.compute.api_version = 2.74 arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--host', 'host1', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('host', 'host1'), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(api_versions, 'APIVersion', return_value=2.74): # In base command class ShowOne in cliff, abstract method # take_action() returns a two-part tuple with a tuple of # column names and a tuple of data to be shown. columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[], nics='auto', scheduler_hints={}, config_drive=None, host='host1', ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) self.assertFalse(self.images_mock.called) self.assertFalse(self.flavors_mock.called) def test_server_create_with_host_pre_v274(self): # Host is not supported for nova api version below 2.74 self.app.client_manager.compute.api_version = 2.73 arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--host', 'host1', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('host', 'host1'), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(api_versions, 'APIVersion', return_value=2.74): self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) def test_server_create_with_hypervisor_hostname_v274(self): # Explicit hypervisor_hostname is supported for nova api version # 2.74 or above self.app.client_manager.compute.api_version = 2.74 arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--hypervisor-hostname', 'node1', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('hypervisor_hostname', 'node1'), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(api_versions, 'APIVersion', return_value=2.74): # In base command class ShowOne in cliff, abstract method # take_action() returns a two-part tuple with a tuple of # column names and a tuple of data to be shown. columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[], nics='auto', scheduler_hints={}, config_drive=None, hypervisor_hostname='node1', ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) self.assertFalse(self.images_mock.called) self.assertFalse(self.flavors_mock.called) def test_server_create_with_hypervisor_hostname_pre_v274(self): # Hypervisor_hostname is not supported for nova api version below 2.74 self.app.client_manager.compute.api_version = 2.73 arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--hypervisor-hostname', 'node1', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('hypervisor_hostname', 'node1'), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(api_versions, 'APIVersion', return_value=2.74): self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) def test_server_create_with_host_and_hypervisor_hostname_v274(self): # Explicit host and hypervisor_hostname is supported for nova api # version 2.74 or above self.app.client_manager.compute.api_version = 2.74 arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--host', 'host1', '--hypervisor-hostname', 'node1', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('host', 'host1'), ('hypervisor_hostname', 'node1'), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(api_versions, 'APIVersion', return_value=2.74): # In base command class ShowOne in cliff, abstract method # take_action() returns a two-part tuple with a tuple of # column names and a tuple of data to be shown. columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[], nics='auto', scheduler_hints={}, config_drive=None, host='host1', hypervisor_hostname='node1', ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) self.assertFalse(self.images_mock.called) self.assertFalse(self.flavors_mock.called) def test_server_create_with_hostname_v290(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.90') arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--hostname', 'hostname', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('hostname', 'hostname'), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[], nics='auto', scheduler_hints={}, config_drive=None, hostname='hostname', ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) self.assertFalse(self.images_mock.called) self.assertFalse(self.flavors_mock.called) def test_server_create_with_hostname_pre_v290(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.89') arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--hostname', 'hostname', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('hostname', 'hostname'), ('config_drive', False), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) def test_server_create_with_trusted_image_cert(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.63') arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--trusted-image-cert', 'foo', '--trusted-image-cert', 'bar', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('config_drive', False), ('trusted_image_certs', ['foo', 'bar']), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) # Set expected values kwargs = dict( meta=None, files={}, reservation_id=None, min_count=1, max_count=1, security_groups=[], userdata=None, key_name=None, availability_zone=None, admin_pass=None, block_device_mapping_v2=[], nics='auto', scheduler_hints={}, config_drive=None, trusted_image_certificates=['foo', 'bar'], ) # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, self.image, self.flavor, **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) self.assertFalse(self.images_mock.called) self.assertFalse(self.flavors_mock.called) def test_server_create_with_trusted_image_cert_prev263(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.62') arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--trusted-image-cert', 'foo', '--trusted-image-cert', 'bar', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('config_drive', False), ('trusted_image_certs', ['foo', 'bar']), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) def test_server_create_with_trusted_image_cert_from_volume(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.63') arglist = [ '--volume', 'volume1', '--flavor', 'flavor1', '--trusted-image-cert', 'foo', '--trusted-image-cert', 'bar', self.new_server.name, ] verifylist = [ ('volume', 'volume1'), ('flavor', 'flavor1'), ('config_drive', False), ('trusted_image_certs', ['foo', 'bar']), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) def test_server_create_with_trusted_image_cert_from_snapshot(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.63') arglist = [ '--snapshot', 'snapshot1', '--flavor', 'flavor1', '--trusted-image-cert', 'foo', '--trusted-image-cert', 'bar', self.new_server.name, ] verifylist = [ ('snapshot', 'snapshot1'), ('flavor', 'flavor1'), ('config_drive', False), ('trusted_image_certs', ['foo', 'bar']), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) def test_server_create_with_trusted_image_cert_boot_from_volume(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.63') arglist = [ '--image', 'image1', '--flavor', 'flavor1', '--boot-from-volume', '1', '--trusted-image-cert', 'foo', '--trusted-image-cert', 'bar', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', 'flavor1'), ('boot_from_volume', 1), ('config_drive', False), ('trusted_image_certs', ['foo', 'bar']), ('server_name', self.new_server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) class TestServerDelete(TestServer): def setUp(self): super(TestServerDelete, self).setUp() self.servers_mock.delete.return_value = None self.servers_mock.force_delete.return_value = None # Get the command object to test self.cmd = server.DeleteServer(self.app, None) def test_server_delete_no_options(self): servers = self.setup_servers_mock(count=1) arglist = [ servers[0].id, ] verifylist = [ ('server', [servers[0].id]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.servers_mock.delete.assert_called_with(servers[0].id) self.servers_mock.force_delete.assert_not_called() self.assertIsNone(result) def test_server_delete_with_force(self): servers = self.setup_servers_mock(count=1) arglist = [ servers[0].id, '--force', ] verifylist = [ ('server', [servers[0].id]), ('force', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.servers_mock.force_delete.assert_called_with(servers[0].id) self.servers_mock.delete.assert_not_called() self.assertIsNone(result) def test_server_delete_multi_servers(self): servers = self.setup_servers_mock(count=3) arglist = [] verifylist = [] for s in servers: arglist.append(s.id) verifylist = [ ('server', arglist), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) calls = [] for s in servers: calls.append(call(s.id)) self.servers_mock.delete.assert_has_calls(calls) self.assertIsNone(result) @mock.patch.object(common_utils, 'find_resource') def test_server_delete_with_all_projects(self, mock_find_resource): servers = self.setup_servers_mock(count=1) mock_find_resource.side_effect = compute_fakes.FakeServer.get_servers( servers, 0, ) arglist = [ servers[0].id, '--all-projects', ] verifylist = [ ('server', [servers[0].id]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) mock_find_resource.assert_called_once_with( mock.ANY, servers[0].id, all_tenants=True, ) @mock.patch.object(common_utils, 'wait_for_delete', return_value=True) def test_server_delete_wait_ok(self, mock_wait_for_delete): servers = self.setup_servers_mock(count=1) arglist = [ servers[0].id, '--wait' ] verifylist = [ ('server', [servers[0].id]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.servers_mock.delete.assert_called_with(servers[0].id) mock_wait_for_delete.assert_called_once_with( self.servers_mock, servers[0].id, callback=mock.ANY, ) self.assertIsNone(result) @mock.patch.object(common_utils, 'wait_for_delete', return_value=False) def test_server_delete_wait_fails(self, mock_wait_for_delete): servers = self.setup_servers_mock(count=1) arglist = [ servers[0].id, '--wait' ] verifylist = [ ('server', [servers[0].id]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(SystemExit, self.cmd.take_action, parsed_args) self.servers_mock.delete.assert_called_with(servers[0].id) mock_wait_for_delete.assert_called_once_with( self.servers_mock, servers[0].id, callback=mock.ANY, ) class TestServerDumpCreate(TestServer): def setUp(self): super(TestServerDumpCreate, self).setUp() # Get the command object to test self.cmd = server.CreateServerDump(self.app, None) # Set methods to be tested. self.methods = { 'trigger_crash_dump': None, } def test_server_dump_one_server(self): self.run_method_with_servers('trigger_crash_dump', 1) def test_server_dump_multi_servers(self): self.run_method_with_servers('trigger_crash_dump', 3) class _TestServerList(TestServer): # Columns to be listed up. columns = ( 'ID', 'Name', 'Status', 'Networks', 'Image', 'Flavor', ) columns_long = ( 'ID', 'Name', 'Status', 'Task State', 'Power State', 'Networks', 'Image Name', 'Image ID', 'Flavor Name', 'Flavor ID', 'Availability Zone', 'Host', 'Properties', ) def setUp(self): super(_TestServerList, self).setUp() self.search_opts = { 'reservation_id': None, 'ip': None, 'ip6': None, 'name': None, 'instance_name': None, 'status': None, 'flavor': None, 'image': None, 'host': None, 'tenant_id': None, 'all_tenants': False, 'user_id': None, 'deleted': False, 'changes-since': None, 'changes-before': None, } # Default params of the core function of the command in the case of no # commandline option specified. self.kwargs = { 'search_opts': self.search_opts, 'marker': None, 'limit': None, } # The fake servers' attributes. Use the original attributes names in # nova, not the ones printed by "server list" command. self.attrs = { 'status': 'ACTIVE', 'OS-EXT-STS:task_state': 'None', 'OS-EXT-STS:power_state': 0x01, # Running 'networks': { u'public': [u'10.20.30.40', u'2001:db8::5'] }, 'OS-EXT-AZ:availability_zone': 'availability-zone-xxx', 'OS-EXT-SRV-ATTR:host': 'host-name-xxx', 'Metadata': format_columns.DictColumn({}), } # The servers to be listed. self.servers = self.setup_servers_mock(3) self.servers_mock.list.return_value = self.servers self.image = image_fakes.create_one_image() # self.images_mock.return_value = [self.image] self.find_image_mock.return_value = self.image self.get_image_mock.return_value = self.image self.flavor = compute_fakes.FakeFlavor.create_one_flavor() self.flavors_mock.get.return_value = self.flavor # Get the command object to test self.cmd = server.ListServer(self.app, None) class TestServerList(_TestServerList): def setUp(self): super(TestServerList, self).setUp() Image = collections.namedtuple('Image', 'id name') self.images_mock.return_value = [ Image(id=s.image['id'], name=self.image.name) # Image will be an empty string if boot-from-volume for s in self.servers if s.image ] Flavor = collections.namedtuple('Flavor', 'id name') self.flavors_mock.list.return_value = [ Flavor(id=s.flavor['id'], name=self.flavor.name) for s in self.servers ] self.data = tuple( ( s.id, s.name, s.status, format_columns.DictListColumn(s.networks), # Image will be an empty string if boot-from-volume self.image.name if s.image else server.IMAGE_STRING_FOR_BFV, self.flavor.name, ) for s in self.servers ) def test_server_list_no_option(self): arglist = [] verifylist = [ ('all_projects', False), ('long', False), ('deleted', False), ('name_lookup_one_by_one', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.servers_mock.list.assert_called_with(**self.kwargs) self.images_mock.assert_called() self.flavors_mock.list.assert_called() # we did not pass image or flavor, so gets on those must be absent self.assertFalse(self.flavors_mock.get.call_count) self.assertFalse(self.get_image_mock.call_count) self.assertEqual(self.columns, columns) self.assertEqual(self.data, tuple(data)) def test_server_list_no_servers(self): arglist = [] verifylist = [ ('all_projects', False), ('long', False), ('deleted', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.servers_mock.list.return_value = [] self.data = () columns, data = self.cmd.take_action(parsed_args) self.servers_mock.list.assert_called_with(**self.kwargs) self.assertEqual(0, self.images_mock.list.call_count) self.assertEqual(0, self.flavors_mock.list.call_count) self.assertEqual(self.columns, columns) self.assertEqual(self.data, tuple(data)) def test_server_list_long_option(self): self.data = tuple( ( s.id, s.name, s.status, getattr(s, 'OS-EXT-STS:task_state'), server.PowerStateColumn( getattr(s, 'OS-EXT-STS:power_state') ), format_columns.DictListColumn(s.networks), # Image will be an empty string if boot-from-volume self.image.name if s.image else server.IMAGE_STRING_FOR_BFV, s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV, self.flavor.name, s.flavor['id'], getattr(s, 'OS-EXT-AZ:availability_zone'), getattr(s, 'OS-EXT-SRV-ATTR:host'), s.Metadata, ) for s in self.servers) arglist = [ '--long', ] verifylist = [ ('all_projects', False), ('long', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.servers_mock.list.assert_called_with(**self.kwargs) self.assertEqual(self.columns_long, columns) self.assertEqual(self.data, tuple(data)) def test_server_list_column_option(self): arglist = [ '-c', 'Project ID', '-c', 'User ID', '-c', 'Created At', '-c', 'Security Groups', '--long' ] verifylist = [ ('long', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.servers_mock.list.assert_called_with(**self.kwargs) self.assertIn('Project ID', columns) self.assertIn('User ID', columns) self.assertIn('Created At', columns) self.assertIn('Security Groups', columns) def test_server_list_no_name_lookup_option(self): self.data = tuple( ( s.id, s.name, s.status, format_columns.DictListColumn(s.networks), # Image will be an empty string if boot-from-volume s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV, s.flavor['id'] ) for s in self.servers ) arglist = [ '--no-name-lookup', ] verifylist = [ ('all_projects', False), ('no_name_lookup', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.servers_mock.list.assert_called_with(**self.kwargs) self.assertEqual(self.columns, columns) self.assertEqual(self.data, tuple(data)) def test_server_list_n_option(self): self.data = tuple( ( s.id, s.name, s.status, format_columns.DictListColumn(s.networks), # Image will be an empty string if boot-from-volume s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV, s.flavor['id'] ) for s in self.servers ) arglist = [ '-n', ] verifylist = [ ('all_projects', False), ('no_name_lookup', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.servers_mock.list.assert_called_with(**self.kwargs) self.assertEqual(self.columns, columns) self.assertEqual(self.data, tuple(data)) def test_server_list_name_lookup_one_by_one(self): arglist = [ '--name-lookup-one-by-one' ] verifylist = [ ('all_projects', False), ('no_name_lookup', False), ('name_lookup_one_by_one', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.servers_mock.list.assert_called_with(**self.kwargs) self.assertFalse(self.images_mock.list.call_count) self.assertFalse(self.flavors_mock.list.call_count) self.get_image_mock.assert_called() self.flavors_mock.get.assert_called() self.assertEqual(self.columns, columns) self.assertEqual(self.data, tuple(data)) def test_server_list_with_image(self): arglist = [ '--image', self.image.id ] verifylist = [ ('image', self.image.id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.find_image_mock.assert_called_with(self.image.id, ignore_missing=False) self.search_opts['image'] = self.image.id self.servers_mock.list.assert_called_with(**self.kwargs) self.assertEqual(self.columns, columns) self.assertEqual(self.data, tuple(data)) def test_server_list_with_flavor(self): arglist = [ '--flavor', self.flavor.id ] verifylist = [ ('flavor', self.flavor.id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.flavors_mock.get.has_calls(self.flavor.id) self.search_opts['flavor'] = self.flavor.id self.servers_mock.list.assert_called_with(**self.kwargs) self.assertEqual(self.columns, columns) self.assertEqual(self.data, tuple(data)) def test_server_list_with_changes_since(self): arglist = [ '--changes-since', '2016-03-04T06:27:59Z', '--deleted' ] verifylist = [ ('changes_since', '2016-03-04T06:27:59Z'), ('deleted', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.search_opts['changes-since'] = '2016-03-04T06:27:59Z' self.search_opts['deleted'] = True self.servers_mock.list.assert_called_with(**self.kwargs) self.assertEqual(self.columns, columns) self.assertEqual(self.data, tuple(data)) @mock.patch.object(iso8601, 'parse_date', side_effect=iso8601.ParseError) def test_server_list_with_invalid_changes_since(self, mock_parse_isotime): arglist = [ '--changes-since', 'Invalid time value', ] verifylist = [ ('changes_since', 'Invalid time value'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) try: self.cmd.take_action(parsed_args) self.fail('CommandError should be raised.') except exceptions.CommandError as e: self.assertEqual('Invalid changes-since value: Invalid time ' 'value', str(e)) mock_parse_isotime.assert_called_once_with( 'Invalid time value' ) def test_server_list_with_tag(self): self.app.client_manager.compute.api_version = api_versions.APIVersion( '2.26') arglist = [ '--tag', 'tag1', '--tag', 'tag2', ] verifylist = [ ('tags', ['tag1', 'tag2']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.search_opts['tags'] = 'tag1,tag2' self.servers_mock.list.assert_called_with(**self.kwargs) self.assertEqual(self.columns, columns) self.assertEqual(self.data, tuple(data)) def test_server_list_with_tag_pre_v225(self): self.app.client_manager.compute.api_version = api_versions.APIVersion( '2.25') arglist = [ '--tag', 'tag1', '--tag', 'tag2', ] verifylist = [ ('tags', ['tag1', 'tag2']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) ex = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-compute-api-version 2.26 or greater is required', str(ex)) def test_server_list_with_not_tag(self): self.app.client_manager.compute.api_version = api_versions.APIVersion( '2.26') arglist = [ '--not-tag', 'tag1', '--not-tag', 'tag2', ] verifylist = [ ('not_tags', ['tag1', 'tag2']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.search_opts['not-tags'] = 'tag1,tag2' self.servers_mock.list.assert_called_with(**self.kwargs) self.assertEqual(self.columns, columns) self.assertEqual(self.data, tuple(data)) def test_server_list_with_not_tag_pre_v226(self): self.app.client_manager.compute.api_version = api_versions.APIVersion( '2.25') arglist = [ '--not-tag', 'tag1', '--not-tag', 'tag2', ] verifylist = [ ('not_tags', ['tag1', 'tag2']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) ex = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-compute-api-version 2.26 or greater is required', str(ex)) def test_server_list_with_availability_zone(self): arglist = [ '--availability-zone', 'test-az', ] verifylist = [ ('availability_zone', 'test-az'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.search_opts['availability_zone'] = 'test-az' self.servers_mock.list.assert_called_with(**self.kwargs) self.assertEqual(self.columns, columns) self.assertEqual(tuple(self.data), tuple(data)) def test_server_list_with_key_name(self): arglist = [ '--key-name', 'test-key', ] verifylist = [ ('key_name', 'test-key'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.search_opts['key_name'] = 'test-key' self.servers_mock.list.assert_called_with(**self.kwargs) self.assertEqual(self.columns, columns) self.assertEqual(tuple(self.data), tuple(data)) def test_server_list_with_config_drive(self): arglist = [ '--config-drive', ] verifylist = [ ('has_config_drive', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.search_opts['config_drive'] = True self.servers_mock.list.assert_called_with(**self.kwargs) self.assertEqual(self.columns, columns) self.assertEqual(tuple(self.data), tuple(data)) def test_server_list_with_no_config_drive(self): arglist = [ '--no-config-drive', ] verifylist = [ ('has_config_drive', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.search_opts['config_drive'] = False self.servers_mock.list.assert_called_with(**self.kwargs) self.assertEqual(self.columns, columns) self.assertEqual(tuple(self.data), tuple(data)) def test_server_list_with_progress(self): arglist = [ '--progress', '100', ] verifylist = [ ('progress', 100), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.search_opts['progress'] = '100' self.servers_mock.list.assert_called_with(**self.kwargs) self.assertEqual(self.columns, columns) self.assertEqual(tuple(self.data), tuple(data)) def test_server_list_with_progress_invalid(self): arglist = [ '--progress', '101', ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verify_args=[]) def test_server_list_with_vm_state(self): arglist = [ '--vm-state', 'active', ] verifylist = [ ('vm_state', 'active'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.search_opts['vm_state'] = 'active' self.servers_mock.list.assert_called_with(**self.kwargs) self.assertEqual(self.columns, columns) self.assertEqual(tuple(self.data), tuple(data)) def test_server_list_with_task_state(self): arglist = [ '--task-state', 'deleting', ] verifylist = [ ('task_state', 'deleting'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.search_opts['task_state'] = 'deleting' self.servers_mock.list.assert_called_with(**self.kwargs) self.assertEqual(self.columns, columns) self.assertEqual(tuple(self.data), tuple(data)) def test_server_list_with_power_state(self): arglist = [ '--power-state', 'running', ] verifylist = [ ('power_state', 'running'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.search_opts['power_state'] = 1 self.servers_mock.list.assert_called_with(**self.kwargs) self.assertEqual(self.columns, columns) self.assertEqual(tuple(self.data), tuple(data)) class TestServerListV273(_TestServerList): # Columns to be listed up. columns = ( 'ID', 'Name', 'Status', 'Networks', 'Image', 'Flavor', ) columns_long = ( 'ID', 'Name', 'Status', 'Task State', 'Power State', 'Networks', 'Image Name', 'Image ID', 'Flavor', 'Availability Zone', 'Host', 'Properties', ) def setUp(self): super(TestServerListV273, self).setUp() # The fake servers' attributes. Use the original attributes names in # nova, not the ones printed by "server list" command. self.attrs['flavor'] = { 'vcpus': self.flavor.vcpus, 'ram': self.flavor.ram, 'disk': self.flavor.disk, 'ephemeral': self.flavor.ephemeral, 'swap': self.flavor.swap, 'original_name': self.flavor.name, 'extra_specs': self.flavor.extra_specs, } # The servers to be listed. self.servers = self.setup_servers_mock(3) self.servers_mock.list.return_value = self.servers Image = collections.namedtuple('Image', 'id name') self.images_mock.return_value = [ Image(id=s.image['id'], name=self.image.name) # Image will be an empty string if boot-from-volume for s in self.servers if s.image ] # The flavor information is embedded, so now reason for this to be # called self.flavors_mock.list = mock.NonCallableMock() self.data = tuple( ( s.id, s.name, s.status, format_columns.DictListColumn(s.networks), # Image will be an empty string if boot-from-volume self.image.name if s.image else server.IMAGE_STRING_FOR_BFV, self.flavor.name, ) for s in self.servers) def test_server_list_with_locked_pre_v273(self): arglist = [ '--locked' ] verifylist = [ ('locked', True) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) ex = self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-compute-api-version 2.73 or greater is required', str(ex)) def test_server_list_with_locked(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.73') arglist = [ '--locked' ] verifylist = [ ('locked', True) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.search_opts['locked'] = True self.servers_mock.list.assert_called_with(**self.kwargs) self.assertItemsEqual(self.columns, columns) self.assertItemsEqual(self.data, tuple(data)) def test_server_list_with_unlocked_v273(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.73') arglist = [ '--unlocked' ] verifylist = [ ('unlocked', True) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.search_opts['locked'] = False self.servers_mock.list.assert_called_with(**self.kwargs) self.assertItemsEqual(self.columns, columns) self.assertItemsEqual(self.data, tuple(data)) def test_server_list_with_locked_and_unlocked(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.73') arglist = [ '--locked', '--unlocked' ] verifylist = [ ('locked', True), ('unlocked', True) ] ex = self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) self.assertIn('Argument parse failed', str(ex)) def test_server_list_with_changes_before(self): self.app.client_manager.compute.api_version = ( api_versions.APIVersion('2.66')) arglist = [ '--changes-before', '2016-03-05T06:27:59Z', '--deleted' ] verifylist = [ ('changes_before', '2016-03-05T06:27:59Z'), ('deleted', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.search_opts['changes-before'] = '2016-03-05T06:27:59Z' self.search_opts['deleted'] = True self.servers_mock.list.assert_called_with(**self.kwargs) self.assertItemsEqual(self.columns, columns) self.assertItemsEqual(self.data, tuple(data)) @mock.patch.object(iso8601, 'parse_date', side_effect=iso8601.ParseError) def test_server_list_with_invalid_changes_before( self, mock_parse_isotime): self.app.client_manager.compute.api_version = ( api_versions.APIVersion('2.66')) arglist = [ '--changes-before', 'Invalid time value', ] verifylist = [ ('changes_before', 'Invalid time value'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) try: self.cmd.take_action(parsed_args) self.fail('CommandError should be raised.') except exceptions.CommandError as e: self.assertEqual('Invalid changes-before value: Invalid time ' 'value', str(e)) mock_parse_isotime.assert_called_once_with( 'Invalid time value' ) def test_server_with_changes_before_pre_v266(self): self.app.client_manager.compute.api_version = ( api_versions.APIVersion('2.65')) arglist = [ '--changes-before', '2016-03-05T06:27:59Z', '--deleted' ] verifylist = [ ('changes_before', '2016-03-05T06:27:59Z'), ('deleted', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) def test_server_list_v269_with_partial_constructs(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.69') arglist = [] verifylist = [] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # include "partial results" from non-responsive part of # infrastructure. server_dict = { "id": "server-id-95a56bfc4xxxxxx28d7e418bfd97813a", "status": "UNKNOWN", "tenant_id": "6f70656e737461636b20342065766572", "created": "2018-12-03T21:06:18Z", "links": [ { "href": "http://fake/v2.1/", "rel": "self" }, { "href": "http://fake", "rel": "bookmark" } ], # We need to pass networks as {} because its defined as a property # of the novaclient Server class which gives {} by default. If not # it will fail at formatting the networks info later on. "networks": {} } server = compute_fakes.fakes.FakeResource( info=server_dict, ) self.servers.append(server) columns, data = self.cmd.take_action(parsed_args) # get the first three servers out since our interest is in the partial # server. next(data) next(data) next(data) partial_server = next(data) expected_row = ( 'server-id-95a56bfc4xxxxxx28d7e418bfd97813a', '', 'UNKNOWN', format_columns.DictListColumn({}), '', '') self.assertEqual(expected_row, partial_server) class TestServerLock(TestServer): def setUp(self): super(TestServerLock, self).setUp() # Get the command object to test self.cmd = server.LockServer(self.app, None) # Set methods to be tested. self.methods = { 'lock': None, } def test_server_lock_one_server(self): self.run_method_with_servers('lock', 1) def test_server_lock_multi_servers(self): self.run_method_with_servers('lock', 3) def test_server_lock_with_reason(self): server = compute_fakes.FakeServer.create_one_server() arglist = [ server.id, '--reason', "blah", ] verifylist = [ ('reason', "blah"), ('server', [server.id]) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) ex = self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-compute-api-version 2.73 or greater is required', str(ex)) class TestServerLockV273(TestServerLock): def setUp(self): super(TestServerLockV273, self).setUp() self.server = compute_fakes.FakeServer.create_one_server( methods=self.methods) # This is the return value for utils.find_resource() self.servers_mock.get.return_value = self.server self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.73') # Get the command object to test self.cmd = server.LockServer(self.app, None) def test_server_lock_with_reason(self): arglist = [ self.server.id, '--reason', "blah", ] verifylist = [ ('reason', "blah"), ('server', [self.server.id]) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.server.lock.assert_called_with(reason="blah") def test_server_lock_multi_servers_with_reason(self): server2 = compute_fakes.FakeServer.create_one_server( methods=self.methods) arglist = [ self.server.id, server2.id, '--reason', "choo..choo", ] verifylist = [ ('reason', "choo..choo"), ('server', [self.server.id, server2.id]) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.assertEqual(2, self.servers_mock.get.call_count) self.server.lock.assert_called_with(reason="choo..choo") self.assertEqual(2, self.server.lock.call_count) class TestServerMigrate(TestServer): def setUp(self): super(TestServerMigrate, self).setUp() methods = { 'migrate': None, 'live_migrate': None, } self.server = compute_fakes.FakeServer.create_one_server( methods=methods) # This is the return value for utils.find_resource() self.servers_mock.get.return_value = self.server self.servers_mock.migrate.return_value = None self.servers_mock.live_migrate.return_value = None # Get the command object to test self.cmd = server.MigrateServer(self.app, None) def test_server_migrate_no_options(self): arglist = [ self.server.id, ] verifylist = [ ('live_migration', False), ('block_migration', None), ('disk_overcommit', None), ('wait', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.server.migrate.assert_called_with() self.assertNotCalled(self.servers_mock.live_migrate) self.assertIsNone(result) def test_server_migrate_with_host_2_56(self): # Tests that --host is allowed for a cold migration # for microversion 2.56 and greater. arglist = [ '--host', 'fakehost', self.server.id, ] verifylist = [ ('live_migration', False), ('host', 'fakehost'), ('block_migration', None), ('disk_overcommit', None), ('wait', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.56') result = self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.server.migrate.assert_called_with(host='fakehost') self.assertNotCalled(self.servers_mock.live_migrate) self.assertIsNone(result) def test_server_migrate_with_block_migration(self): arglist = [ '--block-migration', self.server.id, ] verifylist = [ ('live_migration', False), ('block_migration', True), ('disk_overcommit', None), ('wait', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.assertNotCalled(self.servers_mock.live_migrate) self.assertNotCalled(self.servers_mock.migrate) def test_server_migrate_with_disk_overcommit(self): arglist = [ '--disk-overcommit', self.server.id, ] verifylist = [ ('live_migration', False), ('block_migration', None), ('disk_overcommit', True), ('wait', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.assertNotCalled(self.servers_mock.live_migrate) self.assertNotCalled(self.servers_mock.migrate) def test_server_migrate_with_host_pre_v256(self): # Tests that --host is not allowed for a cold migration # before microversion 2.56 (the test defaults to 2.1). arglist = [ '--host', 'fakehost', self.server.id, ] verifylist = [ ('live_migration', False), ('host', 'fakehost'), ('block_migration', None), ('disk_overcommit', None), ('wait', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) ex = self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) # Make sure it's the error we expect. self.assertIn('--os-compute-api-version 2.56 or greater is required ' 'to use --host without --live-migration.', str(ex)) self.servers_mock.get.assert_called_with(self.server.id) self.assertNotCalled(self.servers_mock.live_migrate) self.assertNotCalled(self.servers_mock.migrate) def test_server_live_migrate(self): # Tests the --live-migration option without --host or --live. arglist = [ '--live-migration', self.server.id, ] verifylist = [ ('live_migration', True), ('host', None), ('block_migration', None), ('disk_overcommit', None), ('wait', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.server.live_migrate.assert_called_with( block_migration=False, disk_over_commit=False, host=None) self.assertNotCalled(self.servers_mock.migrate) self.assertIsNone(result) def test_server_live_migrate_with_host(self): # This requires --os-compute-api-version >= 2.30 so the test uses 2.30. arglist = [ '--live-migration', '--host', 'fakehost', self.server.id, ] verifylist = [ ('live_migration', True), ('host', 'fakehost'), ('block_migration', None), ('disk_overcommit', None), ('wait', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.30') result = self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) # No disk_overcommit and block_migration defaults to auto with # microversion >= 2.25 self.server.live_migrate.assert_called_with( block_migration='auto', host='fakehost') self.assertNotCalled(self.servers_mock.migrate) self.assertIsNone(result) def test_server_live_migrate_with_host_pre_v230(self): # Tests that the --host option is not supported for --live-migration # before microversion 2.30 (the test defaults to 2.1). arglist = [ '--live-migration', '--host', 'fakehost', self.server.id, ] verifylist = [ ('live_migration', True), ('host', 'fakehost'), ('block_migration', None), ('disk_overcommit', None), ('wait', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) ex = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) # Make sure it's the error we expect. self.assertIn( '--os-compute-api-version 2.30 or greater is required ' 'when using --host', str(ex)) self.servers_mock.get.assert_called_with(self.server.id) self.assertNotCalled(self.servers_mock.live_migrate) self.assertNotCalled(self.servers_mock.migrate) def test_server_block_live_migrate(self): arglist = [ '--live-migration', '--block-migration', self.server.id, ] verifylist = [ ('live_migration', True), ('block_migration', True), ('disk_overcommit', None), ('wait', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.24') result = self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.server.live_migrate.assert_called_with( block_migration=True, disk_over_commit=False, host=None) self.assertNotCalled(self.servers_mock.migrate) self.assertIsNone(result) def test_server_live_migrate_with_disk_overcommit(self): arglist = [ '--live-migration', '--disk-overcommit', self.server.id, ] verifylist = [ ('live_migration', True), ('block_migration', None), ('disk_overcommit', True), ('wait', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.24') result = self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.server.live_migrate.assert_called_with( block_migration=False, disk_over_commit=True, host=None) self.assertNotCalled(self.servers_mock.migrate) self.assertIsNone(result) def test_server_live_migrate_with_disk_overcommit_post_v224(self): arglist = [ '--live-migration', '--disk-overcommit', self.server.id, ] verifylist = [ ('live_migration', True), ('block_migration', None), ('disk_overcommit', True), ('wait', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.25') with mock.patch.object(self.cmd.log, 'warning') as mock_warning: result = self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) # There should be no 'disk_over_commit' value present self.server.live_migrate.assert_called_with( block_migration='auto', host=None) self.assertNotCalled(self.servers_mock.migrate) self.assertIsNone(result) # A warning should have been logged for using --disk-overcommit. mock_warning.assert_called_once() self.assertIn( 'The --disk-overcommit and --no-disk-overcommit options ', str(mock_warning.call_args[0][0])) @mock.patch.object(common_utils, 'wait_for_status', return_value=True) def test_server_migrate_with_wait(self, mock_wait_for_status): arglist = [ '--wait', self.server.id, ] verifylist = [ ('live_migration', False), ('block_migration', None), ('disk_overcommit', None), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.server.migrate.assert_called_with() self.assertNotCalled(self.servers_mock.live_migrate) self.assertIsNone(result) @mock.patch.object(common_utils, 'wait_for_status', return_value=False) def test_server_migrate_with_wait_fails(self, mock_wait_for_status): arglist = [ '--wait', self.server.id, ] verifylist = [ ('live_migration', False), ('block_migration', None), ('disk_overcommit', None), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(SystemExit, self.cmd.take_action, parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.server.migrate.assert_called_with() self.assertNotCalled(self.servers_mock.live_migrate) class TestServerPause(TestServer): def setUp(self): super(TestServerPause, self).setUp() # Get the command object to test self.cmd = server.PauseServer(self.app, None) # Set methods to be tested. self.methods = { 'pause': None, } def test_server_pause_one_server(self): self.run_method_with_sdk_servers('pause_server', 1) def test_server_pause_multi_servers(self): self.run_method_with_sdk_servers('pause_server', 3) class TestServerRebuild(TestServer): def setUp(self): super(TestServerRebuild, self).setUp() # Return value for utils.find_resource for image self.image = image_fakes.create_one_image() self.get_image_mock.return_value = self.image # Fake the rebuilt new server. attrs = { 'image': { 'id': self.image.id }, 'networks': {}, 'adminPass': 'passw0rd', } new_server = compute_fakes.FakeServer.create_one_server(attrs=attrs) # Fake the server to be rebuilt. The IDs of them should be the same. attrs['id'] = new_server.id methods = { 'rebuild': new_server, } self.server = compute_fakes.FakeServer.create_one_server( attrs=attrs, methods=methods ) # Return value for utils.find_resource for server. self.servers_mock.get.return_value = self.server self.cmd = server.RebuildServer(self.app, None) def test_rebuild_with_image_name(self): image_name = 'my-custom-image' user_image = image_fakes.create_one_image( attrs={'name': image_name}) self.find_image_mock.return_value = user_image attrs = { 'image': { 'id': user_image.id }, 'networks': {}, 'adminPass': 'passw0rd', } new_server = compute_fakes.FakeServer.create_one_server(attrs=attrs) self.server.rebuild.return_value = new_server arglist = [ self.server.id, '--image', image_name ] verifylist = [ ('server', self.server.id), ('image', image_name) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # Get the command object to test. self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.find_image_mock.assert_called_with( image_name, ignore_missing=False) self.get_image_mock.assert_called_with(user_image.id) self.server.rebuild.assert_called_with(user_image, None) def test_rebuild_with_current_image(self): arglist = [ self.server.id, ] verifylist = [ ('server', self.server.id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # Get the command object to test. self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.find_image_mock.assert_not_called() self.get_image_mock.assert_called_with(self.image.id) self.server.rebuild.assert_called_with(self.image, None) def test_rebuild_with_name(self): name = 'test-server-xxx' arglist = [ self.server.id, '--name', name, ] verifylist = [ ('server', self.server.id), ('name', name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # Get the command object to test self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.get_image_mock.assert_called_with(self.image.id) self.server.rebuild.assert_called_with(self.image, None, name=name) def test_rebuild_with_preserve_ephemeral(self): arglist = [ self.server.id, '--preserve-ephemeral', ] verifylist = [ ('server', self.server.id), ('preserve_ephemeral', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # Get the command object to test self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.get_image_mock.assert_called_with(self.image.id) self.server.rebuild.assert_called_with( self.image, None, preserve_ephemeral=True) def test_rebuild_with_no_preserve_ephemeral(self): arglist = [ self.server.id, '--no-preserve-ephemeral', ] verifylist = [ ('server', self.server.id), ('preserve_ephemeral', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # Get the command object to test self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.get_image_mock.assert_called_with(self.image.id) self.server.rebuild.assert_called_with( self.image, None, preserve_ephemeral=False) def test_rebuild_with_password(self): password = 'password-xxx' arglist = [ self.server.id, '--password', password ] verifylist = [ ('server', self.server.id), ('password', password) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # Get the command object to test self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.get_image_mock.assert_called_with(self.image.id) self.server.rebuild.assert_called_with(self.image, password) def test_rebuild_with_description(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.19') description = 'description1' arglist = [ self.server.id, '--description', description ] verifylist = [ ('server', self.server.id), ('description', description) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.get_image_mock.assert_called_with(self.image.id) self.server.rebuild.assert_called_with(self.image, None, description=description) def test_rebuild_with_description_pre_v219(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.18') description = 'description1' arglist = [ self.server.id, '--description', description ] verifylist = [ ('server', self.server.id), ('description', description) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) @mock.patch.object(common_utils, 'wait_for_status', return_value=True) def test_rebuild_with_wait_ok(self, mock_wait_for_status): arglist = [ '--wait', self.server.id, ] verifylist = [ ('wait', True), ('server', self.server.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # Get the command object to test. self.cmd.take_action(parsed_args) # kwargs = dict(success_status=['active', 'verify_resize'],) mock_wait_for_status.assert_called_once_with( self.servers_mock.get, self.server.id, callback=mock.ANY, # **kwargs ) self.servers_mock.get.assert_called_with(self.server.id) self.get_image_mock.assert_called_with(self.image.id) self.server.rebuild.assert_called_with(self.image, None) @mock.patch.object(common_utils, 'wait_for_status', return_value=False) def test_rebuild_with_wait_fails(self, mock_wait_for_status): arglist = [ '--wait', self.server.id, ] verifylist = [ ('wait', True), ('server', self.server.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(SystemExit, self.cmd.take_action, parsed_args) mock_wait_for_status.assert_called_once_with( self.servers_mock.get, self.server.id, callback=mock.ANY, ) self.servers_mock.get.assert_called_with(self.server.id) self.get_image_mock.assert_called_with(self.image.id) self.server.rebuild.assert_called_with(self.image, None) def test_rebuild_with_property(self): arglist = [ self.server.id, '--property', 'key1=value1', '--property', 'key2=value2' ] expected_properties = {'key1': 'value1', 'key2': 'value2'} verifylist = [ ('server', self.server.id), ('properties', expected_properties) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # Get the command object to test self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.get_image_mock.assert_called_with(self.image.id) self.server.rebuild.assert_called_with( self.image, None, meta=expected_properties) def test_rebuild_with_keypair_name(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.54') self.server.key_name = 'mykey' arglist = [ self.server.id, '--key-name', self.server.key_name, ] verifylist = [ ('server', self.server.id), ('key_name', self.server.key_name) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.get_image_mock.assert_called_with(self.image.id) self.server.rebuild.assert_called_with( self.image, None, key_name=self.server.key_name) def test_rebuild_with_keypair_name_pre_v254(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.53') self.server.key_name = 'mykey' arglist = [ self.server.id, '--key-name', self.server.key_name, ] verifylist = [ ('server', self.server.id), ('key_name', self.server.key_name) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) def test_rebuild_with_no_keypair_name(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.54') self.server.key_name = 'mykey' arglist = [ self.server.id, '--no-key-name', ] verifylist = [ ('server', self.server.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.get_image_mock.assert_called_with(self.image.id) self.server.rebuild.assert_called_with( self.image, None, key_name=None) def test_rebuild_with_keypair_name_and_unset(self): self.server.key_name = 'mykey' arglist = [ self.server.id, '--key-name', self.server.key_name, '--no-key-name', ] verifylist = [ ('server', self.server.id), ('key_name', self.server.key_name) ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) @mock.patch('openstackclient.compute.v2.server.io.open') def test_rebuild_with_user_data(self, mock_open): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.57') mock_file = mock.Mock(name='File') mock_open.return_value = mock_file mock_open.read.return_value = '#!/bin/sh' arglist = [ self.server.id, '--user-data', 'userdata.sh', ] verifylist = [ ('server', self.server.id), ('user_data', 'userdata.sh'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) # Ensure the userdata file is opened mock_open.assert_called_with('userdata.sh') # Ensure the userdata file is closed mock_file.close.assert_called_with() self.servers_mock.get.assert_called_with(self.server.id) self.get_image_mock.assert_called_with(self.image.id) self.server.rebuild.assert_called_with( self.image, None, userdata=mock_file,) def test_rebuild_with_user_data_pre_v257(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.56') arglist = [ self.server.id, '--user-data', 'userdata.sh', ] verifylist = [ ('server', self.server.id), ('user_data', 'userdata.sh'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) def test_rebuild_with_no_user_data(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.54') self.server.key_name = 'mykey' arglist = [ self.server.id, '--no-user-data', ] verifylist = [ ('server', self.server.id), ('no_user_data', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.get_image_mock.assert_called_with(self.image.id) self.server.rebuild.assert_called_with( self.image, None, userdata=None) def test_rebuild_with_no_user_data_pre_v254(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.53') arglist = [ self.server.id, '--no-user-data', ] verifylist = [ ('server', self.server.id), ('no_user_data', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) def test_rebuild_with_user_data_and_unset(self): arglist = [ self.server.id, '--user-data', 'userdata.sh', '--no-user-data', ] self.assertRaises( utils.ParserException, self.check_parser, self.cmd, arglist, None) def test_rebuild_with_trusted_image_cert(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.63') arglist = [ self.server.id, '--trusted-image-cert', 'foo', '--trusted-image-cert', 'bar', ] verifylist = [ ('server', self.server.id), ('trusted_image_certs', ['foo', 'bar']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.get_image_mock.assert_called_with(self.image.id) self.server.rebuild.assert_called_with( self.image, None, trusted_image_certificates=['foo', 'bar']) def test_rebuild_with_trusted_image_cert_pre_v263(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.62') arglist = [ self.server.id, '--trusted-image-cert', 'foo', '--trusted-image-cert', 'bar', ] verifylist = [ ('server', self.server.id), ('trusted_image_certs', ['foo', 'bar']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) def test_rebuild_with_no_trusted_image_cert(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.63') arglist = [ self.server.id, '--no-trusted-image-certs', ] verifylist = [ ('server', self.server.id), ('no_trusted_image_certs', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.get_image_mock.assert_called_with(self.image.id) self.server.rebuild.assert_called_with( self.image, None, trusted_image_certificates=None) def test_rebuild_with_no_trusted_image_cert_pre_v263(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.62') arglist = [ self.server.id, '--no-trusted-image-certs', ] verifylist = [ ('server', self.server.id), ('no_trusted_image_certs', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) def test_rebuild_with_hostname(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.90') arglist = [ self.server.id, '--hostname', 'new-hostname' ] verifylist = [ ('server', self.server.id), ('hostname', 'new-hostname') ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.get_image_mock.assert_called_with(self.image.id) self.server.rebuild.assert_called_with( self.image, None, hostname='new-hostname') def test_rebuild_with_hostname_pre_v290(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.89') arglist = [ self.server.id, '--hostname', 'new-hostname', ] verifylist = [ ('server', self.server.id), ('hostname', 'new-hostname') ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) class TestEvacuateServer(TestServer): def setUp(self): super(TestEvacuateServer, self).setUp() # Return value for utils.find_resource for image self.image = image_fakes.create_one_image() self.images_mock.get.return_value = self.image # Fake the rebuilt new server. attrs = { 'image': { 'id': self.image.id }, 'networks': {}, 'adminPass': 'passw0rd', } new_server = compute_fakes.FakeServer.create_one_server(attrs=attrs) # Fake the server to be rebuilt. The IDs of them should be the same. attrs['id'] = new_server.id methods = { 'evacuate': new_server, } self.server = compute_fakes.FakeServer.create_one_server( attrs=attrs, methods=methods ) # Return value for utils.find_resource for server. self.servers_mock.get.return_value = self.server self.cmd = server.EvacuateServer(self.app, None) def _test_evacuate(self, args, verify_args, evac_args): parsed_args = self.check_parser(self.cmd, args, verify_args) # Get the command object to test self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.server.evacuate.assert_called_with(**evac_args) def test_evacuate(self): args = [ self.server.id, ] verify_args = [ ('server', self.server.id), ] evac_args = { 'host': None, 'on_shared_storage': False, 'password': None, } self._test_evacuate(args, verify_args, evac_args) def test_evacuate_with_password(self): args = [ self.server.id, '--password', 'password', ] verify_args = [ ('server', self.server.id), ('password', 'password'), ] evac_args = { 'host': None, 'on_shared_storage': False, 'password': 'password', } self._test_evacuate(args, verify_args, evac_args) def test_evacuate_with_host(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.29') host = 'target-host' args = [ self.server.id, '--host', 'target-host', ] verify_args = [ ('server', self.server.id), ('host', 'target-host'), ] evac_args = {'host': host, 'password': None} self._test_evacuate(args, verify_args, evac_args) def test_evacuate_with_host_pre_v229(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.28') args = [ self.server.id, '--host', 'target-host', ] verify_args = [ ('server', self.server.id), ('host', 'target-host'), ] parsed_args = self.check_parser(self.cmd, args, verify_args) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) def test_evacuate_without_share_storage(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.13') args = [ self.server.id, '--shared-storage' ] verify_args = [ ('server', self.server.id), ('shared_storage', True), ] evac_args = { 'host': None, 'on_shared_storage': True, 'password': None, } self._test_evacuate(args, verify_args, evac_args) def test_evacuate_without_share_storage_post_v213(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.14') args = [ self.server.id, '--shared-storage' ] verify_args = [ ('server', self.server.id), ('shared_storage', True), ] parsed_args = self.check_parser(self.cmd, args, verify_args) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) @mock.patch.object(common_utils, 'wait_for_status', return_value=True) def test_evacuate_with_wait_ok(self, mock_wait_for_status): args = [ self.server.id, '--wait', ] verify_args = [ ('server', self.server.id), ('wait', True), ] evac_args = { 'host': None, 'on_shared_storage': False, 'password': None, } self._test_evacuate(args, verify_args, evac_args) mock_wait_for_status.assert_called_once_with( self.servers_mock.get, self.server.id, callback=mock.ANY, ) class TestServerRemoveFixedIP(TestServer): def setUp(self): super(TestServerRemoveFixedIP, self).setUp() # Get the command object to test self.cmd = server.RemoveFixedIP(self.app, None) # Set unshelve method to be tested. self.methods = { 'remove_fixed_ip': None, } def test_server_remove_fixed_ip(self): servers = self.setup_servers_mock(count=1) arglist = [ servers[0].id, '1.2.3.4', ] verifylist = [ ('server', servers[0].id), ('ip_address', '1.2.3.4'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) servers[0].remove_fixed_ip.assert_called_once_with('1.2.3.4') self.assertIsNone(result) class TestServerRescue(TestServer): def setUp(self): super(TestServerRescue, self).setUp() # Return value for utils.find_resource for image self.image = image_fakes.create_one_image() self.get_image_mock.return_value = self.image new_server = compute_fakes.FakeServer.create_one_server() attrs = { 'id': new_server.id, 'image': { 'id': self.image.id, }, 'networks': {}, 'adminPass': 'passw0rd', } methods = { 'rescue': new_server, } self.server = compute_fakes.FakeServer.create_one_server( attrs=attrs, methods=methods, ) # Return value for utils.find_resource for server self.servers_mock.get.return_value = self.server self.cmd = server.RescueServer(self.app, None) def test_rescue_with_current_image(self): arglist = [ self.server.id, ] verifylist = [ ('server', self.server.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # Get the command object to test self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.server.rescue.assert_called_with(image=None, password=None) def test_rescue_with_new_image(self): new_image = image_fakes.create_one_image() self.find_image_mock.return_value = new_image arglist = [ '--image', new_image.id, self.server.id, ] verifylist = [ ('image', new_image.id), ('server', self.server.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # Get the command object to test self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.find_image_mock.assert_called_with(new_image.id) self.server.rescue.assert_called_with(image=new_image, password=None) def test_rescue_with_current_image_and_password(self): password = 'password-xxx' arglist = [ '--password', password, self.server.id, ] verifylist = [ ('password', password), ('server', self.server.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # Get the command object to test self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.server.rescue.assert_called_with(image=None, password=password) @mock.patch( 'openstackclient.api.compute_v2.APIv2.floating_ip_remove' ) class TestServerRemoveFloatingIPCompute(compute_fakes.TestComputev2): def setUp(self): super(TestServerRemoveFloatingIPCompute, self).setUp() self.app.client_manager.network_endpoint_enabled = False # Get the command object to test self.cmd = server.RemoveFloatingIP(self.app, None) def test_server_remove_floating_ip(self, fip_mock): _floating_ip = compute_fakes.FakeFloatingIP.create_one_floating_ip() arglist = [ 'server1', _floating_ip['ip'], ] verifylist = [ ('server', 'server1'), ('ip_address', _floating_ip['ip']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) fip_mock.assert_called_once_with( 'server1', _floating_ip['ip'], ) class TestServerRemoveFloatingIPNetwork(network_fakes.TestNetworkV2): def setUp(self): super(TestServerRemoveFloatingIPNetwork, self).setUp() self.app.client_manager.network = mock.Mock() self.network = self.app.client_manager.network self.network.update_ip = mock.Mock(return_value=None) # Get the command object to test self.cmd = server.RemoveFloatingIP(self.app, self.namespace) def test_server_remove_floating_ip_default(self): _server = compute_fakes.FakeServer.create_one_server() _floating_ip = network_fakes.FakeFloatingIP.create_one_floating_ip() self.network.find_ip = mock.Mock(return_value=_floating_ip) arglist = [ _server.id, _floating_ip['ip'], ] verifylist = [ ('server', _server.id), ('ip_address', _floating_ip['ip']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) attrs = { 'port_id': None, } self.network.find_ip.assert_called_once_with( _floating_ip['ip'], ignore_missing=False, ) self.network.update_ip.assert_called_once_with( _floating_ip, **attrs ) class TestServerRemovePort(TestServer): def setUp(self): super(TestServerRemovePort, self).setUp() # Get the command object to test self.cmd = server.RemovePort(self.app, None) # Set method to be tested. self.methods = { 'delete_server_interface': None, } self.find_port = mock.Mock() self.app.client_manager.network.find_port = self.find_port def _test_server_remove_port(self, port_id): servers = self.setup_sdk_servers_mock(count=1) port = 'fake-port' arglist = [ servers[0].id, port, ] verifylist = [ ('server', servers[0].id), ('port', port), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.sdk_client.delete_server_interface.assert_called_with( port_id, server=servers[0], ignore_missing=False) self.assertIsNone(result) def test_server_remove_port(self): self._test_server_remove_port(self.find_port.return_value.id) self.find_port.assert_called_once_with( 'fake-port', ignore_missing=False) def test_server_remove_port_no_neutron(self): self.app.client_manager.network_endpoint_enabled = False self._test_server_remove_port('fake-port') self.find_port.assert_not_called() class TestServerRemoveNetwork(TestServer): def setUp(self): super(TestServerRemoveNetwork, self).setUp() # Get the command object to test self.cmd = server.RemoveNetwork(self.app, None) # Set method to be tested. self.fake_inf = mock.Mock() self.methods = { 'server_interfaces': [self.fake_inf], 'delete_server_interface': None, } self.find_network = mock.Mock() self.app.client_manager.network.find_network = self.find_network self.sdk_client.server_interfaces.return_value = [self.fake_inf] def _test_server_remove_network(self, network_id): self.fake_inf.net_id = network_id self.fake_inf.port_id = 'fake-port' servers = self.setup_sdk_servers_mock(count=1) network = 'fake-network' arglist = [ servers[0].id, network, ] verifylist = [ ('server', servers[0].id), ('network', network), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.sdk_client.server_interfaces.assert_called_once_with(servers[0]) self.sdk_client.delete_server_interface.assert_called_once_with( 'fake-port', server=servers[0]) self.assertIsNone(result) def test_server_remove_network(self): self._test_server_remove_network(self.find_network.return_value.id) self.find_network.assert_called_once_with( 'fake-network', ignore_missing=False) def test_server_remove_network_no_neutron(self): self.app.client_manager.network_endpoint_enabled = False self._test_server_remove_network('fake-network') self.find_network.assert_not_called() @mock.patch( 'openstackclient.api.compute_v2.APIv2.security_group_find' ) class TestServerRemoveSecurityGroup(TestServer): def setUp(self): super(TestServerRemoveSecurityGroup, self).setUp() self.security_group = \ compute_fakes.FakeSecurityGroup.create_one_security_group() attrs = { 'security_groups': [{'name': self.security_group['id']}] } methods = { 'remove_security_group': None, } self.server = compute_fakes.FakeServer.create_one_server( attrs=attrs, methods=methods ) # This is the return value for utils.find_resource() for server self.servers_mock.get.return_value = self.server # Get the command object to test self.cmd = server.RemoveServerSecurityGroup(self.app, None) def test_server_remove_security_group(self, sg_find_mock): sg_find_mock.return_value = self.security_group arglist = [ self.server.id, self.security_group['id'] ] verifylist = [ ('server', self.server.id), ('group', self.security_group['id']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) sg_find_mock.assert_called_with( self.security_group['id'], ) self.servers_mock.get.assert_called_with(self.server.id) self.server.remove_security_group.assert_called_with( self.security_group['id'], ) self.assertIsNone(result) class TestServerResize(TestServer): def setUp(self): super(TestServerResize, self).setUp() self.server = compute_fakes.FakeServer.create_one_server() # This is the return value for utils.find_resource() self.servers_mock.get.return_value = self.server self.servers_mock.resize.return_value = None self.servers_mock.confirm_resize.return_value = None self.servers_mock.revert_resize.return_value = None # This is the return value for utils.find_resource() self.flavors_get_return_value = \ compute_fakes.FakeFlavor.create_one_flavor() self.flavors_mock.get.return_value = self.flavors_get_return_value # Get the command object to test self.cmd = server.ResizeServer(self.app, None) def test_server_resize_no_options(self): arglist = [ self.server.id, ] verifylist = [ ('confirm', False), ('revert', False), ('server', self.server.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.assertNotCalled(self.servers_mock.resize) self.assertNotCalled(self.servers_mock.confirm_resize) self.assertNotCalled(self.servers_mock.revert_resize) self.assertIsNone(result) def test_server_resize(self): arglist = [ '--flavor', self.flavors_get_return_value.id, self.server.id, ] verifylist = [ ('flavor', self.flavors_get_return_value.id), ('confirm', False), ('revert', False), ('server', self.server.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.flavors_mock.get.assert_called_with( self.flavors_get_return_value.id, ) self.servers_mock.resize.assert_called_with( self.server, self.flavors_get_return_value, ) self.assertNotCalled(self.servers_mock.confirm_resize) self.assertNotCalled(self.servers_mock.revert_resize) self.assertIsNone(result) def test_server_resize_confirm(self): arglist = [ '--confirm', self.server.id, ] verifylist = [ ('confirm', True), ('revert', False), ('server', self.server.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(self.cmd.log, 'warning') as mock_warning: result = self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.assertNotCalled(self.servers_mock.resize) self.servers_mock.confirm_resize.assert_called_with(self.server) self.assertNotCalled(self.servers_mock.revert_resize) self.assertIsNone(result) # A warning should have been logged for using --confirm. mock_warning.assert_called_once() self.assertIn('The --confirm option has been deprecated.', str(mock_warning.call_args[0][0])) def test_server_resize_revert(self): arglist = [ '--revert', self.server.id, ] verifylist = [ ('confirm', False), ('revert', True), ('server', self.server.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(self.cmd.log, 'warning') as mock_warning: result = self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.assertNotCalled(self.servers_mock.resize) self.assertNotCalled(self.servers_mock.confirm_resize) self.servers_mock.revert_resize.assert_called_with(self.server) self.assertIsNone(result) # A warning should have been logged for using --revert. mock_warning.assert_called_once() self.assertIn('The --revert option has been deprecated.', str(mock_warning.call_args[0][0])) @mock.patch.object(common_utils, 'wait_for_status', return_value=True) def test_server_resize_with_wait_ok(self, mock_wait_for_status): arglist = [ '--flavor', self.flavors_get_return_value.id, '--wait', self.server.id, ] verifylist = [ ('flavor', self.flavors_get_return_value.id), ('confirm', False), ('revert', False), ('wait', True), ('server', self.server.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with( self.server.id, ) kwargs = dict(success_status=['active', 'verify_resize'],) mock_wait_for_status.assert_called_once_with( self.servers_mock.get, self.server.id, callback=mock.ANY, **kwargs ) self.servers_mock.resize.assert_called_with( self.server, self.flavors_get_return_value ) self.assertNotCalled(self.servers_mock.confirm_resize) self.assertNotCalled(self.servers_mock.revert_resize) @mock.patch.object(common_utils, 'wait_for_status', return_value=False) def test_server_resize_with_wait_fails(self, mock_wait_for_status): arglist = [ '--flavor', self.flavors_get_return_value.id, '--wait', self.server.id, ] verifylist = [ ('flavor', self.flavors_get_return_value.id), ('confirm', False), ('revert', False), ('wait', True), ('server', self.server.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(SystemExit, self.cmd.take_action, parsed_args) self.servers_mock.get.assert_called_with( self.server.id, ) kwargs = dict(success_status=['active', 'verify_resize'],) mock_wait_for_status.assert_called_once_with( self.servers_mock.get, self.server.id, callback=mock.ANY, **kwargs ) self.servers_mock.resize.assert_called_with( self.server, self.flavors_get_return_value ) class TestServerResizeConfirm(TestServer): def setUp(self): super(TestServerResizeConfirm, self).setUp() methods = { 'confirm_resize': None, } self.server = compute_fakes.FakeServer.create_one_server( methods=methods) # This is the return value for utils.find_resource() self.servers_mock.get.return_value = self.server self.servers_mock.confirm_resize.return_value = None # Get the command object to test self.cmd = server.ResizeConfirm(self.app, None) def test_resize_confirm(self): arglist = [ self.server.id, ] verifylist = [ ('server', self.server.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.server.confirm_resize.assert_called_with() # TODO(stephenfin): Remove in OSC 7.0 class TestServerMigrateConfirm(TestServer): def setUp(self): super().setUp() methods = { 'confirm_resize': None, } self.server = compute_fakes.FakeServer.create_one_server( methods=methods) # This is the return value for utils.find_resource() self.servers_mock.get.return_value = self.server self.servers_mock.confirm_resize.return_value = None # Get the command object to test self.cmd = server.MigrateConfirm(self.app, None) def test_migrate_confirm(self): arglist = [ self.server.id, ] verifylist = [ ('server', self.server.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(self.cmd.log, 'warning') as mock_warning: self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.server.confirm_resize.assert_called_with() mock_warning.assert_called_once() self.assertIn( "The 'server migrate confirm' command has been deprecated", str(mock_warning.call_args[0][0]) ) class TestServerConfirmMigration(TestServerResizeConfirm): def setUp(self): super().setUp() methods = { 'confirm_resize': None, } self.server = compute_fakes.FakeServer.create_one_server( methods=methods) # This is the return value for utils.find_resource() self.servers_mock.get.return_value = self.server self.servers_mock.confirm_resize.return_value = None # Get the command object to test self.cmd = server.ConfirmMigration(self.app, None) def test_migration_confirm(self): arglist = [ self.server.id, ] verifylist = [ ('server', self.server.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.server.confirm_resize.assert_called_with() class TestServerResizeRevert(TestServer): def setUp(self): super(TestServerResizeRevert, self).setUp() methods = { 'revert_resize': None, } self.server = compute_fakes.FakeServer.create_one_server( methods=methods) # This is the return value for utils.find_resource() self.servers_mock.get.return_value = self.server self.servers_mock.revert_resize.return_value = None # Get the command object to test self.cmd = server.ResizeRevert(self.app, None) def test_resize_revert(self): arglist = [ self.server.id, ] verifylist = [ ('server', self.server.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.server.revert_resize.assert_called_with() # TODO(stephenfin): Remove in OSC 7.0 class TestServerMigrateRevert(TestServer): def setUp(self): super().setUp() methods = { 'revert_resize': None, } self.server = compute_fakes.FakeServer.create_one_server( methods=methods) # This is the return value for utils.find_resource() self.servers_mock.get.return_value = self.server self.servers_mock.revert_resize.return_value = None # Get the command object to test self.cmd = server.MigrateRevert(self.app, None) def test_migrate_revert(self): arglist = [ self.server.id, ] verifylist = [ ('server', self.server.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(self.cmd.log, 'warning') as mock_warning: self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.server.revert_resize.assert_called_with() mock_warning.assert_called_once() self.assertIn( "The 'server migrate revert' command has been deprecated", str(mock_warning.call_args[0][0]) ) class TestServerRevertMigration(TestServer): def setUp(self): super().setUp() methods = { 'revert_resize': None, } self.server = compute_fakes.FakeServer.create_one_server( methods=methods) # This is the return value for utils.find_resource() self.servers_mock.get.return_value = self.server self.servers_mock.revert_resize.return_value = None # Get the command object to test self.cmd = server.RevertMigration(self.app, None) def test_migration_revert(self): arglist = [ self.server.id, ] verifylist = [ ('server', self.server.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(self.server.id) self.server.revert_resize.assert_called_with() class TestServerRestore(TestServer): def setUp(self): super(TestServerRestore, self).setUp() # Get the command object to test self.cmd = server.RestoreServer(self.app, None) # Set methods to be tested. self.methods = { 'restore': None, } def test_server_restore_one_server(self): self.run_method_with_servers('restore', 1) def test_server_restore_multi_servers(self): self.run_method_with_servers('restore', 3) class TestServerResume(TestServer): def setUp(self): super(TestServerResume, self).setUp() # Get the command object to test self.cmd = server.ResumeServer(self.app, None) # Set methods to be tested. self.methods = { 'resume': None, } def test_server_resume_one_server(self): self.run_method_with_sdk_servers('resume_server', 1) def test_server_resume_multi_servers(self): self.run_method_with_sdk_servers('resume_server', 3) class TestServerSet(TestServer): def setUp(self): super(TestServerSet, self).setUp() self.attrs = { 'api_version': None, } self.methods = { 'update': None, 'reset_state': None, 'change_password': None, 'clear_password': None, 'add_tag': None, 'set_tags': None, } self.fake_servers = self.setup_servers_mock(2) # Get the command object to test self.cmd = server.SetServer(self.app, None) def test_server_set_no_option(self): arglist = [ 'foo_vm' ] verifylist = [ ('server', 'foo_vm') ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.assertNotCalled(self.fake_servers[0].update) self.assertNotCalled(self.fake_servers[0].reset_state) self.assertNotCalled(self.fake_servers[0].change_password) self.assertNotCalled(self.servers_mock.set_meta) self.assertIsNone(result) def test_server_set_with_state(self): for index, state in enumerate(['active', 'error']): arglist = [ '--state', state, 'foo_vm', ] verifylist = [ ('state', state), ('server', 'foo_vm'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.fake_servers[index].reset_state.assert_called_once_with( state=state) self.assertIsNone(result) def test_server_set_with_invalid_state(self): arglist = [ '--state', 'foo_state', 'foo_vm', ] verifylist = [ ('state', 'foo_state'), ('server', 'foo_vm'), ] self.assertRaises(utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_server_set_with_name(self): arglist = [ '--name', 'foo_name', 'foo_vm', ] verifylist = [ ('name', 'foo_name'), ('server', 'foo_vm'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.fake_servers[0].update.assert_called_once_with(name='foo_name') self.assertIsNone(result) def test_server_set_with_property(self): arglist = [ '--property', 'key1=value1', '--property', 'key2=value2', 'foo_vm', ] verifylist = [ ('properties', {'key1': 'value1', 'key2': 'value2'}), ('server', 'foo_vm'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.servers_mock.set_meta.assert_called_once_with( self.fake_servers[0], parsed_args.properties) self.assertIsNone(result) def test_server_set_with_password(self): arglist = [ '--password', 'foo', 'foo_vm', ] verifylist = [ ('password', 'foo'), ('server', 'foo_vm'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.fake_servers[0].change_password.assert_called_once_with('foo') def test_server_set_with_no_password(self): arglist = [ '--no-password', 'foo_vm', ] verifylist = [ ('no_password', True), ('server', 'foo_vm'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.fake_servers[0].clear_password.assert_called_once_with() # TODO(stephenfin): Remove this in a future major version @mock.patch.object(getpass, 'getpass', return_value=mock.sentinel.fake_pass) def test_server_set_with_root_password(self, mock_getpass): arglist = [ '--root-password', 'foo_vm', ] verifylist = [ ('root_password', True), ('server', 'foo_vm'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.fake_servers[0].change_password.assert_called_once_with( mock.sentinel.fake_pass) self.assertIsNone(result) def test_server_set_with_description(self): # Description is supported for nova api version 2.19 or above self.fake_servers[0].api_version = api_versions.APIVersion('2.19') arglist = [ '--description', 'foo_description', 'foo_vm', ] verifylist = [ ('description', 'foo_description'), ('server', 'foo_vm'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.fake_servers[0].update.assert_called_once_with( description='foo_description') self.assertIsNone(result) def test_server_set_with_description_pre_v219(self): # Description is not supported for nova api version below 2.19 self.fake_servers[0].api_version = api_versions.APIVersion('2.18') arglist = [ '--description', 'foo_description', 'foo_vm', ] verifylist = [ ('description', 'foo_description'), ('server', 'foo_vm'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) def test_server_set_with_tag(self): self.fake_servers[0].api_version = api_versions.APIVersion('2.26') arglist = [ '--tag', 'tag1', '--tag', 'tag2', 'foo_vm', ] verifylist = [ ('tags', ['tag1', 'tag2']), ('server', 'foo_vm'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.fake_servers[0].add_tag.assert_has_calls([ mock.call(tag='tag1'), mock.call(tag='tag2'), ]) self.assertIsNone(result) def test_server_set_with_tag_pre_v226(self): self.fake_servers[0].api_version = api_versions.APIVersion('2.25') arglist = [ '--tag', 'tag1', '--tag', 'tag2', 'foo_vm', ] verifylist = [ ('tags', ['tag1', 'tag2']), ('server', 'foo_vm'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) ex = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-compute-api-version 2.26 or greater is required', str(ex)) def test_server_set_with_hostname(self): self.fake_servers[0].api_version = api_versions.APIVersion('2.90') arglist = [ '--hostname', 'foo-hostname', 'foo_vm', ] verifylist = [ ('hostname', 'foo-hostname'), ('server', 'foo_vm'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.fake_servers[0].update.assert_called_once_with( hostname='foo-hostname') self.assertIsNone(result) def test_server_set_with_hostname_pre_v290(self): self.fake_servers[0].api_version = api_versions.APIVersion('2.89') arglist = [ '--hostname', 'foo-hostname', 'foo_vm', ] verifylist = [ ('hostname', 'foo-hostname'), ('server', 'foo_vm'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) class TestServerShelve(TestServer): def setUp(self): super(TestServerShelve, self).setUp() # Get the command object to test self.cmd = server.ShelveServer(self.app, None) def test_shelve(self): server_info = {'status': 'ACTIVE'} server_methods = { 'shelve': None, 'shelve_offload': None, } server = compute_fakes.FakeServer.create_one_server( attrs=server_info, methods=server_methods) self.servers_mock.get.return_value = server arglist = [server.name] verifylist = [ ('servers', [server.name]), ('wait', False), ('offload', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.assertIsNone(result) self.servers_mock.get.assert_called_once_with(server.name) server.shelve.assert_called_once_with() server.shelve_offload.assert_not_called() def test_shelve_already_shelved(self): server_info = {'status': 'SHELVED'} server_methods = { 'shelve': None, 'shelve_offload': None, } server = compute_fakes.FakeServer.create_one_server( attrs=server_info, methods=server_methods) self.servers_mock.get.return_value = server arglist = [server.name] verifylist = [ ('servers', [server.name]), ('wait', False), ('offload', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.assertIsNone(result) self.servers_mock.get.assert_called_once_with(server.name) server.shelve.assert_not_called() server.shelve_offload.assert_not_called() @mock.patch.object(common_utils, 'wait_for_status', return_value=True) def test_shelve_with_wait(self, mock_wait_for_status): server_info = {'status': 'ACTIVE'} server_methods = { 'shelve': None, 'shelve_offload': None, } server = compute_fakes.FakeServer.create_one_server( attrs=server_info, methods=server_methods) self.servers_mock.get.return_value = server arglist = ['--wait', server.name] verifylist = [ ('servers', [server.name]), ('wait', True), ('offload', False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.assertIsNone(result) self.servers_mock.get.assert_called_once_with(server.name) server.shelve.assert_called_once_with() server.shelve_offload.assert_not_called() mock_wait_for_status.assert_called_once_with( self.servers_mock.get, server.id, callback=mock.ANY, success_status=('shelved', 'shelved_offloaded'), ) @mock.patch.object(common_utils, 'wait_for_status', return_value=True) def test_shelve_offload(self, mock_wait_for_status): server_info = {'status': 'ACTIVE'} server_methods = { 'shelve': None, 'shelve_offload': None, } server = compute_fakes.FakeServer.create_one_server( attrs=server_info, methods=server_methods) self.servers_mock.get.return_value = server arglist = ['--offload', server.name] verifylist = [ ('servers', [server.name]), ('wait', False), ('offload', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.assertIsNone(result) self.servers_mock.get.assert_has_calls([ mock.call(server.name), mock.call(server.name), ]) server.shelve.assert_called_once_with() server.shelve_offload.assert_called_once_with() mock_wait_for_status.assert_called_once_with( self.servers_mock.get, server.id, callback=mock.ANY, success_status=('shelved', 'shelved_offloaded'), ) class TestServerShow(TestServer): def setUp(self): super(TestServerShow, self).setUp() self.image = image_fakes.create_one_image() self.flavor = compute_fakes.FakeFlavor.create_one_flavor() self.topology = { 'nodes': [{'vcpu_set': [0, 1]}, {'vcpu_set': [2, 3]}], 'pagesize_kb': None, } server_info = { 'image': {'id': self.image.id}, 'flavor': {'id': self.flavor.id}, 'tenant_id': 'tenant-id-xxx', 'networks': {'public': ['10.20.30.40', '2001:db8::f']}, } # Fake the server.diagnostics() method. The return value contains http # response and data. The data is a dict. Sincce this method itself is # faked, we don't need to fake everything of the return value exactly. resp = mock.Mock() resp.status_code = 200 server_method = { 'diagnostics': (resp, {'test': 'test'}), 'topology': self.topology, } self.server = compute_fakes.FakeServer.create_one_server( attrs=server_info, methods=server_method) # This is the return value for utils.find_resource() self.servers_mock.get.return_value = self.server self.get_image_mock.return_value = self.image self.flavors_mock.get.return_value = self.flavor # Get the command object to test self.cmd = server.ShowServer(self.app, None) self.columns = ( 'OS-EXT-STS:power_state', 'addresses', 'flavor', 'id', 'image', 'name', 'networks', 'project_id', 'properties', ) self.data = ( server.PowerStateColumn( getattr(self.server, 'OS-EXT-STS:power_state')), format_columns.DictListColumn(self.server.networks), self.flavor.name + " (" + self.flavor.id + ")", self.server.id, self.image.name + " (" + self.image.id + ")", self.server.name, {'public': ['10.20.30.40', '2001:db8::f']}, 'tenant-id-xxx', format_columns.DictColumn({}), ) def test_show_no_options(self): arglist = [] verifylist = [] self.assertRaises(utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_show(self): arglist = [ self.server.name, ] verifylist = [ ('diagnostics', False), ('topology', False), ('server', self.server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(self.columns, columns) self.assertCountEqual(self.data, data) def test_show_embedded_flavor(self): # Tests using --os-compute-api-version >= 2.47 where the flavor # details are embedded in the server response body excluding the id. arglist = [ self.server.name, ] verifylist = [ ('diagnostics', False), ('topology', False), ('server', self.server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.server.info['flavor'] = { 'ephemeral': 0, 'ram': 512, 'original_name': 'm1.tiny', 'vcpus': 1, 'extra_specs': {}, 'swap': 0, 'disk': 1 } columns, data = self.cmd.take_action(parsed_args) self.assertEqual(self.columns, columns) # Since the flavor details are in a dict we can't be sure of the # ordering so just assert that one of the keys is in the output. self.assertIn('original_name', data[2]._value) def test_show_diagnostics(self): arglist = [ '--diagnostics', self.server.name, ] verifylist = [ ('diagnostics', True), ('topology', False), ('server', self.server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(('test',), columns) self.assertEqual(('test',), data) def test_show_topology(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.78') arglist = [ '--topology', self.server.name, ] verifylist = [ ('diagnostics', False), ('topology', True), ('server', self.server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.columns += ('topology',) self.data += (format_columns.DictColumn(self.topology),) columns, data = self.cmd.take_action(parsed_args) self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.data, data) def test_show_topology_pre_v278(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.77') arglist = [ '--topology', self.server.name, ] verifylist = [ ('diagnostics', False), ('topology', True), ('server', self.server.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) @mock.patch('openstackclient.compute.v2.server.os.system') class TestServerSsh(TestServer): def setUp(self): super().setUp() self.cmd = server.SshServer(self.app, None) self.app.client_manager.auth_ref = mock.Mock() self.app.client_manager.auth_ref.username = 'cloud' self.attrs = { 'addresses': { 'public': [ { 'addr': '192.168.1.30', 'OS-EXT-IPS-MAC:mac_addr': '00:0c:29:0d:11:74', 'OS-EXT-IPS:type': 'fixed', 'version': 4, }, ], }, } self.server = compute_fakes.FakeServer.create_one_server( attrs=self.attrs, methods=self.methods, ) self.servers_mock.get.return_value = self.server def test_server_ssh_no_opts(self, mock_exec): arglist = [ self.server.name, ] verifylist = [ ('server', self.server.name), ('login', None), ('port', None), ('identity', None), ('option', None), ('ipv4', False), ('ipv6', False), ('address_type', 'public'), ('verbose', False), ('ssh_args', []), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(self.cmd.log, 'warning') as mock_warning: result = self.cmd.take_action(parsed_args) self.assertIsNone(result) mock_exec.assert_called_once_with('ssh 192.168.1.30 -l cloud') mock_warning.assert_not_called() def test_server_ssh_passthrough_opts(self, mock_exec): arglist = [ self.server.name, '--', '-l', 'username', '-p', '2222', ] verifylist = [ ('server', self.server.name), ('login', None), ('port', None), ('identity', None), ('option', None), ('ipv4', False), ('ipv6', False), ('address_type', 'public'), ('verbose', False), ('ssh_args', ['-l', 'username', '-p', '2222']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(self.cmd.log, 'warning') as mock_warning: result = self.cmd.take_action(parsed_args) self.assertIsNone(result) mock_exec.assert_called_once_with( 'ssh 192.168.1.30 -l username -p 2222' ) mock_warning.assert_not_called() def test_server_ssh_deprecated_opts(self, mock_exec): arglist = [ self.server.name, '-l', 'username', '-p', '2222', ] verifylist = [ ('server', self.server.name), ('login', 'username'), ('port', 2222), ('identity', None), ('option', None), ('ipv4', False), ('ipv6', False), ('address_type', 'public'), ('verbose', False), ('ssh_args', []), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(self.cmd.log, 'warning') as mock_warning: result = self.cmd.take_action(parsed_args) self.assertIsNone(result) mock_exec.assert_called_once_with( 'ssh 192.168.1.30 -p 2222 -l username' ) mock_warning.assert_called_once() self.assertIn( 'The ssh options have been deprecated.', mock_warning.call_args[0][0], ) class TestServerStart(TestServer): def setUp(self): super(TestServerStart, self).setUp() # Get the command object to test self.cmd = server.StartServer(self.app, None) # Set methods to be tested. self.methods = { 'start': None, } def test_server_start_one_server(self): self.run_method_with_servers('start', 1) def test_server_start_multi_servers(self): self.run_method_with_servers('start', 3) @mock.patch.object(common_utils, 'find_resource') def test_server_start_with_all_projects(self, mock_find_resource): servers = self.setup_servers_mock(count=1) mock_find_resource.side_effect = compute_fakes.FakeServer.get_servers( servers, 0, ) arglist = [ servers[0].id, '--all-projects', ] verifylist = [ ('server', [servers[0].id]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) mock_find_resource.assert_called_once_with( mock.ANY, servers[0].id, all_tenants=True, ) class TestServerStop(TestServer): def setUp(self): super(TestServerStop, self).setUp() # Get the command object to test self.cmd = server.StopServer(self.app, None) # Set methods to be tested. self.methods = { 'stop': None, } def test_server_stop_one_server(self): self.run_method_with_servers('stop', 1) def test_server_stop_multi_servers(self): self.run_method_with_servers('stop', 3) @mock.patch.object(common_utils, 'find_resource') def test_server_start_with_all_projects(self, mock_find_resource): servers = self.setup_servers_mock(count=1) mock_find_resource.side_effect = compute_fakes.FakeServer.get_servers( servers, 0, ) arglist = [ servers[0].id, '--all-projects', ] verifylist = [ ('server', [servers[0].id]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) mock_find_resource.assert_called_once_with( mock.ANY, servers[0].id, all_tenants=True, ) class TestServerSuspend(TestServer): def setUp(self): super(TestServerSuspend, self).setUp() # Get the command object to test self.cmd = server.SuspendServer(self.app, None) # Set methods to be tested. self.methods = { 'suspend': None, } def test_server_suspend_one_server(self): self.run_method_with_sdk_servers('suspend_server', 1) def test_server_suspend_multi_servers(self): self.run_method_with_sdk_servers('suspend_server', 3) class TestServerUnlock(TestServer): def setUp(self): super(TestServerUnlock, self).setUp() # Get the command object to test self.cmd = server.UnlockServer(self.app, None) # Set methods to be tested. self.methods = { 'unlock': None, } def test_server_unlock_one_server(self): self.run_method_with_servers('unlock', 1) def test_server_unlock_multi_servers(self): self.run_method_with_servers('unlock', 3) class TestServerUnpause(TestServer): def setUp(self): super(TestServerUnpause, self).setUp() # Get the command object to test self.cmd = server.UnpauseServer(self.app, None) # Set methods to be tested. self.methods = { 'unpause': None, } def test_server_unpause_one_server(self): self.run_method_with_sdk_servers('unpause_server', 1) def test_server_unpause_multi_servers(self): self.run_method_with_sdk_servers('unpause_server', 3) class TestServerUnset(TestServer): def setUp(self): super(TestServerUnset, self).setUp() self.fake_server = self.setup_servers_mock(1)[0] # Get the command object to test self.cmd = server.UnsetServer(self.app, None) def test_server_unset_no_option(self): arglist = [ 'foo_vm', ] verifylist = [ ('server', 'foo_vm'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.assertNotCalled(self.servers_mock.delete_meta) self.assertIsNone(result) def test_server_unset_with_property(self): arglist = [ '--property', 'key1', '--property', 'key2', 'foo_vm', ] verifylist = [ ('properties', ['key1', 'key2']), ('server', 'foo_vm'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.servers_mock.delete_meta.assert_called_once_with( self.fake_server, ['key1', 'key2']) self.assertIsNone(result) def test_server_unset_with_description_api_newer(self): # Description is supported for nova api version 2.19 or above self.app.client_manager.compute.api_version = 2.19 arglist = [ '--description', 'foo_vm', ] verifylist = [ ('description', True), ('server', 'foo_vm'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(api_versions, 'APIVersion', return_value=2.19): result = self.cmd.take_action(parsed_args) self.servers_mock.update.assert_called_once_with( self.fake_server, description="") self.assertIsNone(result) def test_server_unset_with_description_api_older(self): # Description is not supported for nova api version below 2.19 self.app.client_manager.compute.api_version = 2.18 arglist = [ '--description', 'foo_vm', ] verifylist = [ ('description', True), ('server', 'foo_vm'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(api_versions, 'APIVersion', return_value=2.19): self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) def test_server_unset_with_tag(self): self.app.client_manager.compute.api_version = api_versions.APIVersion( '2.26') arglist = [ '--tag', 'tag1', '--tag', 'tag2', 'foo_vm', ] verifylist = [ ('tags', ['tag1', 'tag2']), ('server', 'foo_vm'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.assertIsNone(result) self.servers_mock.delete_tag.assert_has_calls([ mock.call(self.fake_server, tag='tag1'), mock.call(self.fake_server, tag='tag2'), ]) def test_server_unset_with_tag_pre_v226(self): self.app.client_manager.compute.api_version = api_versions.APIVersion( '2.25') arglist = [ '--tag', 'tag1', '--tag', 'tag2', 'foo_vm', ] verifylist = [ ('tags', ['tag1', 'tag2']), ('server', 'foo_vm'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) ex = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-compute-api-version 2.26 or greater is required', str(ex)) class TestServerUnshelve(TestServer): def setUp(self): super(TestServerUnshelve, self).setUp() # Get the command object to test self.cmd = server.UnshelveServer(self.app, None) # Set unshelve method to be tested. self.methods = { 'unshelve': None, } self.attrs = { 'status': 'SHELVED', } def test_unshelve_one_server(self): self.run_method_with_servers('unshelve', 1) def test_unshelve_multi_servers(self): self.run_method_with_servers('unshelve', 3) def test_unshelve_with_specified_az(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.77') server = compute_fakes.FakeServer.create_one_server( attrs=self.attrs, methods=self.methods) self.servers_mock.get.return_value = server arglist = [ '--availability-zone', "foo-az", server.id, ] verifylist = [ ('availability_zone', "foo-az"), ('server', [server.id]) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.servers_mock.get.assert_called_with(server.id) server.unshelve.assert_called_with(availability_zone="foo-az") def test_unshelve_with_specified_az_pre_v277(self): self.app.client_manager.compute.api_version = \ api_versions.APIVersion('2.76') server = compute_fakes.FakeServer.create_one_server( attrs=self.attrs, methods=self.methods) arglist = [ server.id, '--availability-zone', "foo-az", ] verifylist = [ ('availability_zone', "foo-az"), ('server', [server.id]) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) ex = self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) self.assertIn( '--os-compute-api-version 2.77 or greater is required', str(ex)) @mock.patch.object(common_utils, 'wait_for_status', return_value=True) def test_unshelve_with_wait(self, mock_wait_for_status): server = compute_fakes.FakeServer.create_one_server( attrs=self.attrs, methods=self.methods) self.servers_mock.get.return_value = server arglist = ['--wait', server.name] verifylist = [ ('server', [server.name]), ('wait', True), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.assertIsNone(result) self.servers_mock.get.assert_called_once_with(server.name) server.unshelve.assert_called_once_with() mock_wait_for_status.assert_called_once_with( self.servers_mock.get, server.id, callback=mock.ANY, success_status=('active', 'shutoff'), ) class TestServerGeneral(TestServer): OLD = { 'private': [ { 'addr': '192.168.0.3', 'version': 4, }, ] } NEW = { 'foo': [ { 'OS-EXT-IPS-MAC:mac_addr': 'fa:16:3e:93:b3:01', 'version': 4, 'addr': '10.10.1.2', 'OS-EXT-IPS:type': 'fixed', }, { 'OS-EXT-IPS-MAC:mac_addr': 'fa:16:3e:93:b3:02', 'version': 6, 'addr': '0:0:0:0:0:ffff:a0a:103', 'OS-EXT-IPS:type': 'floating', }, ] } ODD = {'jenkins': ['10.3.3.18', '124.12.125.4']} def test_get_ip_address(self): self.assertEqual("192.168.0.3", server._get_ip_address(self.OLD, 'private', [4, 6])) self.assertEqual("10.10.1.2", server._get_ip_address(self.NEW, 'fixed', [4, 6])) self.assertEqual("10.10.1.2", server._get_ip_address(self.NEW, 'private', [4, 6])) self.assertEqual("0:0:0:0:0:ffff:a0a:103", server._get_ip_address(self.NEW, 'public', [6])) self.assertEqual("0:0:0:0:0:ffff:a0a:103", server._get_ip_address(self.NEW, 'floating', [6])) self.assertEqual("124.12.125.4", server._get_ip_address(self.ODD, 'public', [4, 6])) self.assertEqual("10.3.3.18", server._get_ip_address(self.ODD, 'private', [4, 6])) self.assertRaises(exceptions.CommandError, server._get_ip_address, self.NEW, 'public', [4]) self.assertRaises(exceptions.CommandError, server._get_ip_address, self.NEW, 'admin', [4]) self.assertRaises(exceptions.CommandError, server._get_ip_address, self.OLD, 'public', [4, 6]) self.assertRaises(exceptions.CommandError, server._get_ip_address, self.OLD, 'private', [6]) @mock.patch('osc_lib.utils.find_resource') def test_prep_server_detail(self, find_resource): # Setup mock method return value. utils.find_resource() will be called # three times in _prep_server_detail(): # - The first time, return server info. # - The second time, return image info. # - The third time, return flavor info. _image = image_fakes.create_one_image() _flavor = compute_fakes.FakeFlavor.create_one_flavor() server_info = { 'image': {u'id': _image.id}, 'flavor': {u'id': _flavor.id}, 'tenant_id': u'tenant-id-xxx', 'networks': {u'public': [u'10.20.30.40', u'2001:db8::f']}, 'links': u'http://xxx.yyy.com', 'properties': '', 'volumes_attached': [{"id": "6344fe9d-ef20-45b2-91a6"}], } _server = compute_fakes.FakeServer.create_one_server(attrs=server_info) find_resource.side_effect = [_server, _flavor] self.get_image_mock.return_value = _image # Prepare result data. info = { 'id': _server.id, 'name': _server.name, 'image': '%s (%s)' % (_image.name, _image.id), 'flavor': '%s (%s)' % (_flavor.name, _flavor.id), 'OS-EXT-STS:power_state': server.PowerStateColumn( getattr(_server, 'OS-EXT-STS:power_state')), 'properties': '', 'volumes_attached': [{"id": "6344fe9d-ef20-45b2-91a6"}], 'addresses': format_columns.DictListColumn(_server.networks), 'project_id': 'tenant-id-xxx', } # Call _prep_server_detail(). server_detail = server._prep_server_detail( self.app.client_manager.compute, self.app.client_manager.image, _server ) # 'networks' is used to create _server. Remove it. server_detail.pop('networks') # Check the results. self.assertCountEqual(info, server_detail)