summaryrefslogtreecommitdiff
path: root/openstackclient/tests
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient/tests')
-rw-r--r--openstackclient/tests/functional/common/test_help.py2
-rw-r--r--openstackclient/tests/functional/compute/v2/test_agent.py4
-rw-r--r--openstackclient/tests/functional/compute/v2/test_keypair.py4
-rw-r--r--openstackclient/tests/functional/compute/v2/test_server.py10
-rw-r--r--openstackclient/tests/functional/object/v1/test_object.py2
-rw-r--r--openstackclient/tests/functional/volume/v2/test_backup.py58
-rw-r--r--openstackclient/tests/unit/common/test_project_purge.py30
-rw-r--r--openstackclient/tests/unit/compute/v2/fakes.py3
-rw-r--r--openstackclient/tests/unit/compute/v2/test_server.py289
-rw-r--r--openstackclient/tests/unit/compute/v2/test_service.py105
-rw-r--r--openstackclient/tests/unit/identity/v3/test_endpoint.py41
-rw-r--r--openstackclient/tests/unit/network/v2/test_subnet.py30
-rw-r--r--openstackclient/tests/unit/object/v1/test_object_all.py22
-rw-r--r--openstackclient/tests/unit/volume/v2/test_backup.py6
14 files changed, 559 insertions, 47 deletions
diff --git a/openstackclient/tests/functional/common/test_help.py b/openstackclient/tests/functional/common/test_help.py
index 7f274099..88f7ddbd 100644
--- a/openstackclient/tests/functional/common/test_help.py
+++ b/openstackclient/tests/functional/common/test_help.py
@@ -80,7 +80,7 @@ class HelpTests(base.TestCase):
"""Check help commands without auth info."""
# Pop all auth info. os.environ will be changed in loop, so do not
# replace os.environ.keys() to os.environ
- for key in os.environ.keys():
+ for key in list(os.environ):
if key.startswith('OS_'):
self.useFixture(fixtures.EnvironmentVariable(key, None))
diff --git a/openstackclient/tests/functional/compute/v2/test_agent.py b/openstackclient/tests/functional/compute/v2/test_agent.py
index 1a112e82..25d8c868 100644
--- a/openstackclient/tests/functional/compute/v2/test_agent.py
+++ b/openstackclient/tests/functional/compute/v2/test_agent.py
@@ -21,10 +21,10 @@ class ComputeAgentTests(base.TestCase):
# Generate two different md5hash
MD5HASH1 = hashlib.md5()
- MD5HASH1.update('agent_1')
+ MD5HASH1.update('agent_1'.encode('utf-8'))
MD5HASH1 = MD5HASH1.hexdigest()
MD5HASH2 = hashlib.md5()
- MD5HASH2.update('agent_2')
+ MD5HASH2.update('agent_2'.encode('utf-8'))
MD5HASH2 = MD5HASH2.hexdigest()
def test_compute_agent_delete(self):
diff --git a/openstackclient/tests/functional/compute/v2/test_keypair.py b/openstackclient/tests/functional/compute/v2/test_keypair.py
index 9a88e66f..42f334a4 100644
--- a/openstackclient/tests/functional/compute/v2/test_keypair.py
+++ b/openstackclient/tests/functional/compute/v2/test_keypair.py
@@ -88,7 +88,7 @@ class KeypairTests(KeypairBase):
1) Create keypair with given public key
2) Delete keypair
"""
- with tempfile.NamedTemporaryFile() as f:
+ with tempfile.NamedTemporaryFile(mode='w+') as f:
f.write(self.PUBLIC_KEY)
f.flush()
@@ -108,7 +108,7 @@ class KeypairTests(KeypairBase):
1) Create keypair with private key file
2) Delete keypair
"""
- with tempfile.NamedTemporaryFile() as f:
+ with tempfile.NamedTemporaryFile(mode='w+') as f:
cmd_output = json.loads(self.openstack(
'keypair create -f json --private-key %s tmpkey' % f.name,
))
diff --git a/openstackclient/tests/functional/compute/v2/test_server.py b/openstackclient/tests/functional/compute/v2/test_server.py
index 0b29fe5f..13fdfa06 100644
--- a/openstackclient/tests/functional/compute/v2/test_server.py
+++ b/openstackclient/tests/functional/compute/v2/test_server.py
@@ -586,7 +586,9 @@ class ServerTests(common.ComputeTestCase):
server_name
)
except exceptions.CommandFailed as e:
- self.assertIn('nics are required after microversion 2.36',
- e.stderr)
- else:
- self.fail('CommandFailed should be raised.')
+ # If we got here, it shouldn't be because a nics value wasn't
+ # provided to the server; it is likely due to something else in
+ # the functional tests like there being multiple available
+ # networks and the test didn't specify a specific network.
+ self.assertNotIn('nics are required after microversion 2.36',
+ e.stderr)
diff --git a/openstackclient/tests/functional/object/v1/test_object.py b/openstackclient/tests/functional/object/v1/test_object.py
index 226ef8ad..b3f23e52 100644
--- a/openstackclient/tests/functional/object/v1/test_object.py
+++ b/openstackclient/tests/functional/object/v1/test_object.py
@@ -33,7 +33,7 @@ class ObjectTests(common.ObjectStoreTests):
self.skipTest("No object-store service present")
def test_object(self):
- with tempfile.NamedTemporaryFile() as f:
+ with tempfile.NamedTemporaryFile(mode='w+') as f:
f.write('test content')
f.flush()
self._test_object(f.name)
diff --git a/openstackclient/tests/functional/volume/v2/test_backup.py b/openstackclient/tests/functional/volume/v2/test_backup.py
new file mode 100644
index 00000000..e4890b00
--- /dev/null
+++ b/openstackclient/tests/functional/volume/v2/test_backup.py
@@ -0,0 +1,58 @@
+# 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 json
+import uuid
+
+from openstackclient.tests.functional.volume.v2 import common
+
+
+class VolumeBackupTests(common.BaseVolumeTests):
+ """Functional tests for volume backups. """
+
+ def setUp(self):
+ super(VolumeBackupTests, self).setUp()
+ self.backup_enabled = False
+ serv_list = json.loads(self.openstack('volume service list -f json'))
+ for service in serv_list:
+ if service['Binary'] == 'cinder-backup':
+ if service['Status'] == 'enabled':
+ self.backup_enabled = True
+
+ def test_volume_backup_restore(self):
+ """Test restore backup"""
+ if not self.backup_enabled:
+ self.skipTest('Backup service is not enabled')
+ vol_id = uuid.uuid4().hex
+ # create a volume
+ json.loads(self.openstack(
+ 'volume create -f json ' +
+ '--size 1 ' +
+ vol_id
+ ))
+ # create a backup
+ backup = json.loads(self.openstack(
+ 'volume backup create -f json ' +
+ vol_id
+ ))
+
+ self.wait_for_status("volume", vol_id, "available")
+ self.wait_for_status("backup", backup['id'], "available")
+ # restore the backup
+ backup_restored = json.loads(self.openstack(
+ 'volume backup restore -f json %s %s'
+ % (backup['id'], vol_id)))
+ self.assertEqual(backup_restored['backup_id'], backup['id'])
+ self.wait_for_status("backup", backup['id'], "available")
+ self.wait_for_status("volume", backup_restored['volume_id'],
+ "available")
+ self.addCleanup(self.openstack, 'volume delete %s' % vol_id)
diff --git a/openstackclient/tests/unit/common/test_project_purge.py b/openstackclient/tests/unit/common/test_project_purge.py
index 2385eae8..6e8ce188 100644
--- a/openstackclient/tests/unit/common/test_project_purge.py
+++ b/openstackclient/tests/unit/common/test_project_purge.py
@@ -117,10 +117,11 @@ class TestProjectPurge(TestProjectPurgeInit):
self.projects_mock.get.assert_called_once_with(self.project.id)
self.projects_mock.delete.assert_called_once_with(self.project.id)
self.servers_mock.list.assert_called_once_with(
- search_opts={'tenant_id': self.project.id})
+ search_opts={'tenant_id': self.project.id, 'all_tenants': True})
kwargs = {'filters': {'owner': self.project.id}}
self.images_mock.list.assert_called_once_with(**kwargs)
- volume_search_opts = {'project_id': self.project.id}
+ volume_search_opts = {'project_id': self.project.id,
+ 'all_tenants': True}
self.volumes_mock.list.assert_called_once_with(
search_opts=volume_search_opts)
self.snapshots_mock.list.assert_called_once_with(
@@ -152,10 +153,11 @@ class TestProjectPurge(TestProjectPurgeInit):
self.projects_mock.get.assert_called_once_with(self.project.id)
self.projects_mock.delete.assert_not_called()
self.servers_mock.list.assert_called_once_with(
- search_opts={'tenant_id': self.project.id})
+ search_opts={'tenant_id': self.project.id, 'all_tenants': True})
kwargs = {'filters': {'owner': self.project.id}}
self.images_mock.list.assert_called_once_with(**kwargs)
- volume_search_opts = {'project_id': self.project.id}
+ volume_search_opts = {'project_id': self.project.id,
+ 'all_tenants': True}
self.volumes_mock.list.assert_called_once_with(
search_opts=volume_search_opts)
self.snapshots_mock.list.assert_called_once_with(
@@ -187,10 +189,11 @@ class TestProjectPurge(TestProjectPurgeInit):
self.projects_mock.get.assert_called_once_with(self.project.id)
self.projects_mock.delete.assert_not_called()
self.servers_mock.list.assert_called_once_with(
- search_opts={'tenant_id': self.project.id})
+ search_opts={'tenant_id': self.project.id, 'all_tenants': True})
kwargs = {'filters': {'owner': self.project.id}}
self.images_mock.list.assert_called_once_with(**kwargs)
- volume_search_opts = {'project_id': self.project.id}
+ volume_search_opts = {'project_id': self.project.id,
+ 'all_tenants': True}
self.volumes_mock.list.assert_called_once_with(
search_opts=volume_search_opts)
self.snapshots_mock.list.assert_called_once_with(
@@ -223,10 +226,11 @@ class TestProjectPurge(TestProjectPurgeInit):
self.projects_mock.get.assert_not_called()
self.projects_mock.delete.assert_called_once_with(self.project.id)
self.servers_mock.list.assert_called_once_with(
- search_opts={'tenant_id': self.project.id})
+ search_opts={'tenant_id': self.project.id, 'all_tenants': True})
kwargs = {'filters': {'owner': self.project.id}}
self.images_mock.list.assert_called_once_with(**kwargs)
- volume_search_opts = {'project_id': self.project.id}
+ volume_search_opts = {'project_id': self.project.id,
+ 'all_tenants': True}
self.volumes_mock.list.assert_called_once_with(
search_opts=volume_search_opts)
self.snapshots_mock.list.assert_called_once_with(
@@ -259,10 +263,11 @@ class TestProjectPurge(TestProjectPurgeInit):
self.projects_mock.get.assert_called_once_with(self.project.id)
self.projects_mock.delete.assert_called_once_with(self.project.id)
self.servers_mock.list.assert_called_once_with(
- search_opts={'tenant_id': self.project.id})
+ search_opts={'tenant_id': self.project.id, 'all_tenants': True})
kwargs = {'filters': {'owner': self.project.id}}
self.images_mock.list.assert_called_once_with(**kwargs)
- volume_search_opts = {'project_id': self.project.id}
+ volume_search_opts = {'project_id': self.project.id,
+ 'all_tenants': True}
self.volumes_mock.list.assert_called_once_with(
search_opts=volume_search_opts)
self.snapshots_mock.list.assert_called_once_with(
@@ -295,10 +300,11 @@ class TestProjectPurge(TestProjectPurgeInit):
self.projects_mock.get.assert_called_once_with(self.project.id)
self.projects_mock.delete.assert_called_once_with(self.project.id)
self.servers_mock.list.assert_called_once_with(
- search_opts={'tenant_id': self.project.id})
+ search_opts={'tenant_id': self.project.id, 'all_tenants': True})
kwargs = {'filters': {'owner': self.project.id}}
self.images_mock.list.assert_called_once_with(**kwargs)
- volume_search_opts = {'project_id': self.project.id}
+ volume_search_opts = {'project_id': self.project.id,
+ 'all_tenants': True}
self.volumes_mock.list.assert_called_once_with(
search_opts=volume_search_opts)
self.snapshots_mock.list.assert_called_once_with(
diff --git a/openstackclient/tests/unit/compute/v2/fakes.py b/openstackclient/tests/unit/compute/v2/fakes.py
index 1ec71785..1d97cecb 100644
--- a/openstackclient/tests/unit/compute/v2/fakes.py
+++ b/openstackclient/tests/unit/compute/v2/fakes.py
@@ -17,6 +17,7 @@ import copy
import uuid
import mock
+from novaclient import api_versions
from openstackclient.api import compute_v2
from openstackclient.tests.unit import fakes
@@ -198,6 +199,8 @@ class FakeComputev2Client(object):
self.management_url = kwargs['endpoint']
+ self.api_version = api_versions.APIVersion('2.1')
+
class TestComputev2(utils.TestCommand):
diff --git a/openstackclient/tests/unit/compute/v2/test_server.py b/openstackclient/tests/unit/compute/v2/test_server.py
index 87c9a985..347e8583 100644
--- a/openstackclient/tests/unit/compute/v2/test_server.py
+++ b/openstackclient/tests/unit/compute/v2/test_server.py
@@ -14,10 +14,13 @@
#
import argparse
import collections
+import copy
import getpass
import mock
from mock import call
+from novaclient import api_versions
+from openstack import exceptions as sdk_exceptions
from osc_lib import exceptions
from osc_lib import utils as common_utils
from oslo_utils import timeutils
@@ -62,9 +65,22 @@ class TestServer(compute_fakes.TestComputev2):
self.methods = {}
def setup_servers_mock(self, count):
- servers = compute_fakes.FakeServer.create_servers(attrs=self.attrs,
- methods=self.methods,
- count=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,
@@ -221,11 +237,11 @@ class TestServerAddFloatingIPNetwork(
self.network.ports = mock.Mock(return_value=[_port])
arglist = [
_server.id,
- _floating_ip['ip'],
+ _floating_ip['floating_ip_address'],
]
verifylist = [
('server', _server.id),
- ('ip_address', _floating_ip['ip']),
+ ('ip_address', _floating_ip['floating_ip_address']),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -236,7 +252,7 @@ class TestServerAddFloatingIPNetwork(
}
self.network.find_ip.assert_called_once_with(
- _floating_ip['ip'],
+ _floating_ip['floating_ip_address'],
ignore_missing=False,
)
self.network.ports.assert_called_once_with(
@@ -247,6 +263,64 @@ class TestServerAddFloatingIPNetwork(
**attrs
)
+ def test_server_add_floating_ip_default_no_external_gateway(self,
+ success=False):
+ _server = compute_fakes.FakeServer.create_one_server()
+ self.servers_mock.get.return_value = _server
+ _port = network_fakes.FakePort.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_default_one_external_gateway(self):
+ self.test_server_add_floating_ip_default_no_external_gateway(
+ success=True)
+
def test_server_add_floating_ip_fixed(self):
_server = compute_fakes.FakeServer.create_one_server()
self.servers_mock.get.return_value = _server
@@ -254,26 +328,31 @@ class TestServerAddFloatingIPNetwork(
_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', _floating_ip['fixed_ip'],
+ '--fixed-ip-address', _port.fixed_ips[0]['ip_address'],
_server.id,
- _floating_ip['ip'],
+ _floating_ip['floating_ip_address'],
]
verifylist = [
- ('fixed_ip_address', _floating_ip['fixed_ip']),
+ ('fixed_ip_address', _port.fixed_ips[0]['ip_address']),
('server', _server.id),
- ('ip_address', _floating_ip['ip']),
+ ('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['ip'],
+ _floating_ip['floating_ip_address'],
ignore_missing=False,
)
self.network.ports.assert_called_once_with(
@@ -284,6 +363,40 @@ class TestServerAddFloatingIPNetwork(
**attrs
)
+ def test_server_add_floating_ip_fixed_no_port_found(self):
+ _server = compute_fakes.FakeServer.create_one_server()
+ self.servers_mock.get.return_value = _server
+ _port = network_fakes.FakePort.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):
@@ -844,6 +957,55 @@ class TestServerCreate(TestServer):
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,
+ 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',
@@ -1730,7 +1892,8 @@ class TestServerList(TestServer):
Image = collections.namedtuple('Image', 'id name')
self.images_mock.list.return_value = [
Image(id=s.image['id'], name=self.image.name)
- for s in self.servers
+ # Image will be an empty string if boot-from-volume
+ for s in self.servers if s.image
]
Flavor = collections.namedtuple('Flavor', 'id name')
@@ -1745,7 +1908,8 @@ class TestServerList(TestServer):
s.name,
s.status,
server._format_servers_list_networks(s.networks),
- self.image.name,
+ # Image will be an empty string if boot-from-volume
+ self.image.name if s.image else s.image,
self.flavor.name,
))
self.data_long.append((
@@ -1757,8 +1921,9 @@ class TestServerList(TestServer):
getattr(s, 'OS-EXT-STS:power_state')
),
server._format_servers_list_networks(s.networks),
- self.image.name,
- s.image['id'],
+ # Image will be an empty string if boot-from-volume
+ self.image.name if s.image else s.image,
+ s.image['id'] if s.image else s.image,
self.flavor.name,
s.flavor['id'],
getattr(s, 'OS-EXT-AZ:availability_zone'),
@@ -1770,7 +1935,8 @@ class TestServerList(TestServer):
s.name,
s.status,
server._format_servers_list_networks(s.networks),
- s.image['id'],
+ # Image will be an empty string if boot-from-volume
+ s.image['id'] if s.image else s.image,
s.flavor['id']
))
@@ -1780,12 +1946,18 @@ class TestServerList(TestServer):
('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.list.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.images_mock.get.call_count)
self.assertEqual(self.columns, columns)
self.assertEqual(tuple(self.data), tuple(data))
@@ -1837,6 +2009,28 @@ class TestServerList(TestServer):
self.assertEqual(self.columns, columns)
self.assertEqual(tuple(self.data_no_name_lookup), 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.images_mock.get.assert_called()
+ self.flavors_mock.get.assert_called()
+
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(tuple(self.data), tuple(data))
+
def test_server_list_with_image(self):
arglist = [
@@ -1869,7 +2063,7 @@ class TestServerList(TestServer):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- self.flavors_mock.get.assert_called_with(self.flavor.id)
+ 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)
@@ -2030,6 +2224,9 @@ class TestServerMigrate(TestServer):
]
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)
@@ -2051,6 +2248,9 @@ class TestServerMigrate(TestServer):
]
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)
@@ -2072,6 +2272,9 @@ class TestServerMigrate(TestServer):
]
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)
@@ -2094,6 +2297,9 @@ class TestServerMigrate(TestServer):
]
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)
@@ -2103,6 +2309,28 @@ class TestServerMigrate(TestServer):
self.assertNotCalled(self.servers_mock.migrate)
self.assertIsNone(result)
+ def test_server_live_migrate_225(self):
+ arglist = [
+ '--live', 'fakehost', self.server.id,
+ ]
+ verifylist = [
+ ('live', 'fakehost'),
+ ('block_migration', False),
+ ('wait', False),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.app.client_manager.compute.api_version = \
+ api_versions.APIVersion('2.25')
+
+ 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,
+ host='fakehost')
+ self.assertNotCalled(self.servers_mock.migrate)
+ self.assertIsNone(result)
+
@mock.patch.object(common_utils, 'wait_for_status', return_value=True)
def test_server_migrate_with_wait(self, mock_wait_for_status):
arglist = [
@@ -3059,6 +3287,33 @@ class TestServerShow(TestServer):
self.assertEqual(self.columns, columns)
self.assertEqual(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),
+ ('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])
+
def test_show_diagnostics(self):
arglist = [
'--diagnostics',
diff --git a/openstackclient/tests/unit/compute/v2/test_service.py b/openstackclient/tests/unit/compute/v2/test_service.py
index 8403efc9..f2a91393 100644
--- a/openstackclient/tests/unit/compute/v2/test_service.py
+++ b/openstackclient/tests/unit/compute/v2/test_service.py
@@ -16,7 +16,9 @@
import mock
from mock import call
+from novaclient import api_versions
from osc_lib import exceptions
+import six
from openstackclient.compute.v2 import service
from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes
@@ -342,7 +344,7 @@ class TestServiceSet(TestService):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.service_mock.force_down.assert_called_once_with(
- self.service.host, self.service.binary, force_down=False)
+ self.service.host, self.service.binary, False)
self.assertNotCalled(self.service_mock.enable)
self.assertNotCalled(self.service_mock.disable)
self.assertIsNone(result)
@@ -361,7 +363,7 @@ class TestServiceSet(TestService):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.service_mock.force_down.assert_called_once_with(
- self.service.host, self.service.binary, force_down=True)
+ self.service.host, self.service.binary, True)
self.assertNotCalled(self.service_mock.enable)
self.assertNotCalled(self.service_mock.disable)
self.assertIsNone(result)
@@ -384,7 +386,7 @@ class TestServiceSet(TestService):
self.service_mock.enable.assert_called_once_with(
self.service.host, self.service.binary)
self.service_mock.force_down.assert_called_once_with(
- self.service.host, self.service.binary, force_down=True)
+ self.service.host, self.service.binary, True)
self.assertIsNone(result)
def test_service_set_enable_and_state_down_with_exception(self):
@@ -407,4 +409,99 @@ class TestServiceSet(TestService):
self.assertRaises(exceptions.CommandError,
self.cmd.take_action, parsed_args)
self.service_mock.force_down.assert_called_once_with(
- self.service.host, self.service.binary, force_down=True)
+ self.service.host, self.service.binary, True)
+
+ def test_service_set_2_53_disable_down(self):
+ # Tests disabling and forcing down a compute service with microversion
+ # 2.53 which requires looking up the service by host and binary.
+ arglist = [
+ '--disable',
+ '--down',
+ self.service.host,
+ self.service.binary,
+ ]
+ verifylist = [
+ ('disable', True),
+ ('down', True),
+ ('host', self.service.host),
+ ('service', self.service.binary),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.53')
+ service_id = '339478d0-0b95-4a94-be63-d5be05dfeb1c'
+ self.service_mock.list.return_value = [mock.Mock(id=service_id)]
+ result = self.cmd.take_action(parsed_args)
+ self.service_mock.disable.assert_called_once_with(service_id)
+ self.service_mock.force_down.assert_called_once_with(service_id, True)
+ self.assertIsNone(result)
+
+ def test_service_set_2_53_disable_reason(self):
+ # Tests disabling with reason a compute service with microversion
+ # 2.53 which requires looking up the service by host and binary.
+ reason = 'earthquake'
+ arglist = [
+ '--disable',
+ '--disable-reason', reason,
+ self.service.host,
+ self.service.binary,
+ ]
+ verifylist = [
+ ('disable', True),
+ ('disable_reason', reason),
+ ('host', self.service.host),
+ ('service', self.service.binary),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.53')
+ service_id = '339478d0-0b95-4a94-be63-d5be05dfeb1c'
+ self.service_mock.list.return_value = [mock.Mock(id=service_id)]
+ result = self.cmd.take_action(parsed_args)
+ self.service_mock.disable_log_reason.assert_called_once_with(
+ service_id, reason)
+ self.assertIsNone(result)
+
+ def test_service_set_2_53_enable_up(self):
+ # Tests enabling and bringing up a compute service with microversion
+ # 2.53 which requires looking up the service by host and binary.
+ arglist = [
+ '--enable',
+ '--up',
+ self.service.host,
+ self.service.binary,
+ ]
+ verifylist = [
+ ('enable', True),
+ ('up', True),
+ ('host', self.service.host),
+ ('service', self.service.binary),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.app.client_manager.compute.api_version = api_versions.APIVersion(
+ '2.53')
+ service_id = '339478d0-0b95-4a94-be63-d5be05dfeb1c'
+ self.service_mock.list.return_value = [mock.Mock(id=service_id)]
+ result = self.cmd.take_action(parsed_args)
+ self.service_mock.enable.assert_called_once_with(service_id)
+ self.service_mock.force_down.assert_called_once_with(service_id, False)
+ self.assertIsNone(result)
+
+ def test_service_set_find_service_by_host_and_binary_no_results(self):
+ # Tests that no compute services are found by host and binary.
+ self.service_mock.list.return_value = []
+ ex = self.assertRaises(exceptions.CommandError,
+ self.cmd._find_service_by_host_and_binary,
+ self.service_mock, 'fake-host', 'nova-compute')
+ self.assertIn('Compute service for host "fake-host" and binary '
+ '"nova-compute" not found.', six.text_type(ex))
+
+ def test_service_set_find_service_by_host_and_binary_many_results(self):
+ # Tests that more than one compute service is found by host and binary.
+ self.service_mock.list.return_value = [mock.Mock(), mock.Mock()]
+ ex = self.assertRaises(exceptions.CommandError,
+ self.cmd._find_service_by_host_and_binary,
+ self.service_mock, 'fake-host', 'nova-compute')
+ self.assertIn('Multiple compute services found for host "fake-host" '
+ 'and binary "nova-compute". Unable to proceed.',
+ six.text_type(ex))
diff --git a/openstackclient/tests/unit/identity/v3/test_endpoint.py b/openstackclient/tests/unit/identity/v3/test_endpoint.py
index bfe930d6..62dcf58d 100644
--- a/openstackclient/tests/unit/identity/v3/test_endpoint.py
+++ b/openstackclient/tests/unit/identity/v3/test_endpoint.py
@@ -439,6 +439,47 @@ class TestEndpointList(TestEndpoint):
)
self.assertEqual(datalist, tuple(data))
+ def test_endpoint_list_project_with_project_domain(self):
+ project = identity_fakes.FakeProject.create_one_project()
+ domain = identity_fakes.FakeDomain.create_one_domain()
+
+ self.ep_filter_mock.list_endpoints_for_project.return_value = [
+ self.endpoint
+ ]
+ self.projects_mock.get.return_value = project
+
+ arglist = [
+ '--project', project.name,
+ '--project-domain', domain.name
+ ]
+ verifylist = [
+ ('project', project.name),
+ ('project_domain', domain.name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # In base command class Lister in cliff, abstract method take_action()
+ # returns a tuple containing the column names and an iterable
+ # containing the data to be listed.
+ columns, data = self.cmd.take_action(parsed_args)
+ self.ep_filter_mock.list_endpoints_for_project.assert_called_with(
+ project=project.id
+ )
+
+ self.assertEqual(self.columns, columns)
+ datalist = (
+ (
+ self.endpoint.id,
+ self.endpoint.region,
+ self.service.name,
+ self.service.type,
+ True,
+ self.endpoint.interface,
+ self.endpoint.url,
+ ),
+ )
+ self.assertEqual(datalist, tuple(data))
+
class TestEndpointSet(TestEndpoint):
diff --git a/openstackclient/tests/unit/network/v2/test_subnet.py b/openstackclient/tests/unit/network/v2/test_subnet.py
index b7f741cd..63eedbe0 100644
--- a/openstackclient/tests/unit/network/v2/test_subnet.py
+++ b/openstackclient/tests/unit/network/v2/test_subnet.py
@@ -1046,6 +1046,36 @@ class TestSetSubnet(TestSubnet):
_testsubnet, **attrs)
self.assertIsNone(result)
+ def test_clear_options(self):
+ _testsubnet = network_fakes.FakeSubnet.create_one_subnet(
+ {'host_routes': [{'destination': '10.20.20.0/24',
+ 'nexthop': '10.20.20.1'}],
+ 'allocation_pools': [{'start': '8.8.8.200',
+ 'end': '8.8.8.250'}],
+ 'dns_nameservers': ['10.0.0.1'], })
+ self.network.find_subnet = mock.Mock(return_value=_testsubnet)
+ arglist = [
+ '--no-host-route',
+ '--no-allocation-pool',
+ '--no-dns-nameservers',
+ _testsubnet.name,
+ ]
+ verifylist = [
+ ('no_dns_nameservers', True),
+ ('no_host_route', True),
+ ('no_allocation_pool', True),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ result = self.cmd.take_action(parsed_args)
+ attrs = {
+ 'host_routes': [],
+ 'allocation_pools': [],
+ 'dns_nameservers': [],
+ }
+ self.network.update_subnet.assert_called_once_with(
+ _testsubnet, **attrs)
+ self.assertIsNone(result)
+
def _test_set_tags(self, with_tags=True):
if with_tags:
arglist = ['--tag', 'red', '--tag', 'blue']
diff --git a/openstackclient/tests/unit/object/v1/test_object_all.py b/openstackclient/tests/unit/object/v1/test_object_all.py
index 363f2ea2..08a7534d 100644
--- a/openstackclient/tests/unit/object/v1/test_object_all.py
+++ b/openstackclient/tests/unit/object/v1/test_object_all.py
@@ -241,7 +241,25 @@ class TestObjectSave(TestObjectAll):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- with mock.patch('sys.stdout', new=six.BytesIO()) as fake_stdout:
+ class FakeStdout(six.BytesIO):
+ def __init__(self):
+ six.BytesIO.__init__(self)
+ self.context_manager_calls = []
+
+ def __enter__(self):
+ self.context_manager_calls.append('__enter__')
+ return self
+
+ def __exit__(self, *a):
+ self.context_manager_calls.append('__exit__')
+
+ with mock.patch('sys.stdout') as fake_stdout, mock.patch(
+ 'os.fdopen', return_value=FakeStdout()) as fake_fdopen:
+ fake_stdout.fileno.return_value = 123
self.cmd.take_action(parsed_args)
- self.assertEqual(fake_stdout.getvalue(), object_fakes.object_1_content)
+ self.assertEqual(fake_fdopen.return_value.getvalue(),
+ object_fakes.object_1_content)
+ self.assertEqual(fake_fdopen.mock_calls, [mock.call(123, 'wb')])
+ self.assertEqual(fake_fdopen.return_value.context_manager_calls,
+ ['__enter__', '__exit__'])
diff --git a/openstackclient/tests/unit/volume/v2/test_backup.py b/openstackclient/tests/unit/volume/v2/test_backup.py
index a8e81c7e..9a2ce718 100644
--- a/openstackclient/tests/unit/volume/v2/test_backup.py
+++ b/openstackclient/tests/unit/volume/v2/test_backup.py
@@ -367,7 +367,9 @@ class TestBackupRestore(TestBackup):
self.backups_mock.get.return_value = self.backup
self.volumes_mock.get.return_value = self.volume
- self.restores_mock.restore.return_value = None
+ self.restores_mock.restore.return_value = (
+ volume_fakes.FakeVolume.create_one_volume(
+ {'id': self.volume['id']}))
# Get the command object to mock
self.cmd = backup.RestoreVolumeBackup(self.app, None)
@@ -385,7 +387,7 @@ class TestBackupRestore(TestBackup):
result = self.cmd.take_action(parsed_args)
self.restores_mock.restore.assert_called_with(self.backup.id,
self.backup.volume_id)
- self.assertIsNone(result)
+ self.assertIsNotNone(result)
class TestBackupSet(TestBackup):