summaryrefslogtreecommitdiff
path: root/cinderclient/tests/unit
diff options
context:
space:
mode:
authorGorka Eguileor <geguileo@redhat.com>2016-10-17 14:39:33 +0200
committerGorka Eguileor <geguileo@redhat.com>2017-10-03 11:03:28 +0200
commit8fce74056fa4afd03149ede9d4b8786cc78ada3e (patch)
tree7c10f8bca19f71a315b0d02e87d1a4e67ec94845 /cinderclient/tests/unit
parent6c214eeec096be25d3f231fa71bb32a9a22c75cf (diff)
downloadpython-cinderclient-8fce74056fa4afd03149ede9d4b8786cc78ada3e.tar.gz
Add cluster support in migration and manage
This patch adds support for API microversion 3.16, which allows us to pass --cluster optional argument to migration and manage operations. For this, a new type of CLI argument is added, the mutually exclusive arguments that can be used similarly to the utils.arg decorator, but with utils.exclusive_arg decorator. Implements: blueprint cinder-volume-active-active-support Change-Id: If004715b9887d2a0f9fc630b44d6e11a4a8b778d
Diffstat (limited to 'cinderclient/tests/unit')
-rw-r--r--cinderclient/tests/unit/v2/fakes.py9
-rw-r--r--cinderclient/tests/unit/v2/test_volumes.py32
-rw-r--r--cinderclient/tests/unit/v3/test_shell.py126
-rw-r--r--cinderclient/tests/unit/v3/test_volumes.py32
4 files changed, 184 insertions, 15 deletions
diff --git a/cinderclient/tests/unit/v2/fakes.py b/cinderclient/tests/unit/v2/fakes.py
index 3e24793..4edf02a 100644
--- a/cinderclient/tests/unit/v2/fakes.py
+++ b/cinderclient/tests/unit/v2/fakes.py
@@ -543,6 +543,15 @@ class FakeHTTPClient(base_client.HTTPClient):
raise AssertionError("Unexpected action: %s" % action)
return (resp, {}, _body)
+ def get_volumes_fake(self, **kw):
+ r = {'volume': self.get_volumes_detail(id='fake')[2]['volumes'][0]}
+ return (200, {}, r)
+
+ def post_volumes_fake_action(self, body, **kw):
+ _body = None
+ resp = 202
+ return (resp, {}, _body)
+
def post_volumes_5678_action(self, body, **kw):
return self.post_volumes_1234_action(body, **kw)
diff --git a/cinderclient/tests/unit/v2/test_volumes.py b/cinderclient/tests/unit/v2/test_volumes.py
index 6e5fd2f..60549ea 100644
--- a/cinderclient/tests/unit/v2/test_volumes.py
+++ b/cinderclient/tests/unit/v2/test_volumes.py
@@ -15,11 +15,13 @@
# License for the specific language governing permissions and limitations
# under the License.
+from cinderclient import api_versions
from cinderclient.tests.unit import utils
from cinderclient.tests.unit.v2 import fakes
from cinderclient.v2.volumes import Volume
cs = fakes.FakeClient()
+cs3 = fakes.FakeClient(api_versions.APIVersion('3.15'))
class VolumesTest(utils.TestCase):
@@ -211,23 +213,23 @@ class VolumesTest(utils.TestCase):
self._assert_request_id(vol)
def test_migrate(self):
- v = cs.volumes.get('1234')
+ v = cs3.volumes.get('1234')
self._assert_request_id(v)
- vol = cs.volumes.migrate_volume(v, 'dest', False, False)
- cs.assert_called('POST', '/volumes/1234/action',
- {'os-migrate_volume': {'host': 'dest',
- 'force_host_copy': False,
+ vol = cs3.volumes.migrate_volume(v, 'dest', False, False)
+ cs3.assert_called('POST', '/volumes/1234/action',
+ {'os-migrate_volume': {'host': 'dest',
+ 'force_host_copy': False,
'lock_volume': False}})
self._assert_request_id(vol)
def test_migrate_with_lock_volume(self):
- v = cs.volumes.get('1234')
+ v = cs3.volumes.get('1234')
self._assert_request_id(v)
- vol = cs.volumes.migrate_volume(v, 'dest', False, True)
- cs.assert_called('POST', '/volumes/1234/action',
- {'os-migrate_volume': {'host': 'dest',
- 'force_host_copy': False,
- 'lock_volume': True}})
+ vol = cs3.volumes.migrate_volume(v, 'dest', False, True)
+ cs3.assert_called('POST', '/volumes/1234/action',
+ {'os-migrate_volume': {'host': 'dest',
+ 'force_host_copy': False,
+ 'lock_volume': True}})
self._assert_request_id(vol)
def test_metadata_update_all(self):
@@ -260,19 +262,19 @@ class VolumesTest(utils.TestCase):
self._assert_request_id(vol)
def test_volume_manage(self):
- vol = cs.volumes.manage('host1', {'k': 'v'})
+ vol = cs3.volumes.manage('host1', {'k': 'v'})
expected = {'host': 'host1', 'name': None, 'availability_zone': None,
'description': None, 'metadata': None, 'ref': {'k': 'v'},
'volume_type': None, 'bootable': False}
- cs.assert_called('POST', '/os-volume-manage', {'volume': expected})
+ cs3.assert_called('POST', '/os-volume-manage', {'volume': expected})
self._assert_request_id(vol)
def test_volume_manage_bootable(self):
- vol = cs.volumes.manage('host1', {'k': 'v'}, bootable=True)
+ vol = cs3.volumes.manage('host1', {'k': 'v'}, bootable=True)
expected = {'host': 'host1', 'name': None, 'availability_zone': None,
'description': None, 'metadata': None, 'ref': {'k': 'v'},
'volume_type': None, 'bootable': True}
- cs.assert_called('POST', '/os-volume-manage', {'volume': expected})
+ cs3.assert_called('POST', '/os-volume-manage', {'volume': expected})
self._assert_request_id(vol)
def test_volume_list_manageable(self):
diff --git a/cinderclient/tests/unit/v3/test_shell.py b/cinderclient/tests/unit/v3/test_shell.py
index 87567dc..f756ec1 100644
--- a/cinderclient/tests/unit/v3/test_shell.py
+++ b/cinderclient/tests/unit/v3/test_shell.py
@@ -1007,3 +1007,129 @@ class ShellTest(utils.TestCase):
columns = ['ID', 'Volume ID', 'Status', 'Name', 'Size', 'User ID']
mock_print_list.assert_called_once_with(mock.ANY, columns,
sortby_index=0)
+
+ @mock.patch('cinderclient.v3.volumes.Volume.migrate_volume')
+ def test_migrate_volume_before_3_16(self, v3_migrate_mock):
+ self.run_command('--os-volume-api-version 3.15 '
+ 'migrate 1234 fakehost')
+
+ v3_migrate_mock.assert_called_once_with(
+ 'fakehost', False, False, None)
+
+ @mock.patch('cinderclient.v3.volumes.Volume.migrate_volume')
+ def test_migrate_volume_3_16(self, v3_migrate_mock):
+ self.run_command('--os-volume-api-version 3.16 '
+ 'migrate 1234 fakehost')
+ self.assertEqual(4, len(v3_migrate_mock.call_args[0]))
+
+ def test_migrate_volume_with_cluster_before_3_16(self):
+ self.assertRaises(exceptions.UnsupportedAttribute,
+ self.run_command,
+ '--os-volume-api-version 3.15 '
+ 'migrate 1234 fakehost --cluster fakecluster')
+
+ @mock.patch('cinderclient.shell.CinderClientArgumentParser.error')
+ def test_migrate_volume_mutual_exclusion(self, error_mock):
+ error_mock.side_effect = SystemExit
+ self.assertRaises(SystemExit,
+ self.run_command,
+ '--os-volume-api-version 3.16 '
+ 'migrate 1234 fakehost --cluster fakecluster')
+ msg = 'argument --cluster: not allowed with argument <host>'
+ error_mock.assert_called_once_with(msg)
+
+ @mock.patch('cinderclient.shell.CinderClientArgumentParser.error')
+ def test_migrate_volume_missing_required(self, error_mock):
+ error_mock.side_effect = SystemExit
+ self.assertRaises(SystemExit,
+ self.run_command,
+ '--os-volume-api-version 3.16 '
+ 'migrate 1234')
+ msg = 'one of the arguments <host> --cluster is required'
+ error_mock.assert_called_once_with(msg)
+
+ def test_migrate_volume_host(self):
+ self.run_command('--os-volume-api-version 3.16 '
+ 'migrate 1234 fakehost')
+ expected = {'os-migrate_volume': {'force_host_copy': False,
+ 'lock_volume': False,
+ 'host': 'fakehost'}}
+ self.assert_called('POST', '/volumes/1234/action', body=expected)
+
+ def test_migrate_volume_cluster(self):
+ self.run_command('--os-volume-api-version 3.16 '
+ 'migrate 1234 --cluster mycluster')
+ expected = {'os-migrate_volume': {'force_host_copy': False,
+ 'lock_volume': False,
+ 'cluster': 'mycluster'}}
+ self.assert_called('POST', '/volumes/1234/action', body=expected)
+
+ def test_migrate_volume_bool_force(self):
+ self.run_command('--os-volume-api-version 3.16 '
+ 'migrate 1234 fakehost --force-host-copy '
+ '--lock-volume')
+ expected = {'os-migrate_volume': {'force_host_copy': True,
+ 'lock_volume': True,
+ 'host': 'fakehost'}}
+ self.assert_called('POST', '/volumes/1234/action', body=expected)
+
+ def test_migrate_volume_bool_force_false(self):
+ # Set both --force-host-copy and --lock-volume to False.
+ self.run_command('--os-volume-api-version 3.16 '
+ 'migrate 1234 fakehost --force-host-copy=False '
+ '--lock-volume=False')
+ expected = {'os-migrate_volume': {'force_host_copy': 'False',
+ 'lock_volume': 'False',
+ 'host': 'fakehost'}}
+ self.assert_called('POST', '/volumes/1234/action', body=expected)
+
+ # Do not set the values to --force-host-copy and --lock-volume.
+ self.run_command('--os-volume-api-version 3.16 '
+ 'migrate 1234 fakehost')
+ expected = {'os-migrate_volume': {'force_host_copy': False,
+ 'lock_volume': False,
+ 'host': 'fakehost'}}
+ self.assert_called('POST', '/volumes/1234/action',
+ body=expected)
+
+ @ddt.data({'bootable': False, 'by_id': False, 'cluster': None},
+ {'bootable': True, 'by_id': False, 'cluster': None},
+ {'bootable': False, 'by_id': True, 'cluster': None},
+ {'bootable': True, 'by_id': True, 'cluster': None},
+ {'bootable': True, 'by_id': True, 'cluster': 'clustername'})
+ @ddt.unpack
+ def test_volume_manage(self, bootable, by_id, cluster):
+ cmd = ('--os-volume-api-version 3.16 '
+ 'manage host1 some_fake_name --name foo --description bar '
+ '--volume-type baz --availability-zone az '
+ '--metadata k1=v1 k2=v2')
+ if by_id:
+ cmd += ' --id-type source-id'
+ if bootable:
+ cmd += ' --bootable'
+ if cluster:
+ cmd += ' --cluster ' + cluster
+
+ self.run_command(cmd)
+ ref = 'source-id' if by_id else 'source-name'
+ expected = {'volume': {'host': 'host1',
+ 'ref': {ref: 'some_fake_name'},
+ 'name': 'foo',
+ 'description': 'bar',
+ 'volume_type': 'baz',
+ 'availability_zone': 'az',
+ 'metadata': {'k1': 'v1', 'k2': 'v2'},
+ 'bootable': bootable}}
+ if cluster:
+ expected['cluster'] = cluster
+ self.assert_called_anytime('POST', '/os-volume-manage', body=expected)
+
+ def test_volume_manage_before_3_16(self):
+ """Cluster optional argument was not acceptable."""
+ self.assertRaises(exceptions.UnsupportedAttribute,
+ self.run_command,
+ 'manage host1 some_fake_name '
+ '--cluster clustername'
+ '--name foo --description bar --bootable '
+ '--volume-type baz --availability-zone az '
+ '--metadata k1=v1 k2=v2')
diff --git a/cinderclient/tests/unit/v3/test_volumes.py b/cinderclient/tests/unit/v3/test_volumes.py
index ff75700..75eb30f 100644
--- a/cinderclient/tests/unit/v3/test_volumes.py
+++ b/cinderclient/tests/unit/v3/test_volumes.py
@@ -27,6 +27,7 @@ from cinderclient.v3 import volumes
from six.moves.urllib import parse
cs = fakes.FakeClient()
+cs3 = fakes.FakeClient(api_versions.APIVersion('3.16'))
@ddt.ddt
@@ -145,3 +146,34 @@ class VolumesTest(utils.TestCase):
request_url = '/scheduler-stats/get_pools?detail=True&name=pool1'
cs.assert_called('GET', request_url)
self._assert_request_id(vol)
+
+ def test_migrate_host(self):
+ v = cs3.volumes.get('1234')
+ self._assert_request_id(v)
+ vol = cs3.volumes.migrate_volume(v, 'host_dest', False, False)
+ cs3.assert_called('POST', '/volumes/1234/action',
+ {'os-migrate_volume': {'host': 'host_dest',
+ 'force_host_copy': False,
+ 'lock_volume': False}})
+ self._assert_request_id(vol)
+
+ def test_migrate_with_lock_volume(self):
+ v = cs3.volumes.get('1234')
+ self._assert_request_id(v)
+ vol = cs3.volumes.migrate_volume(v, 'dest', False, True)
+ cs3.assert_called('POST', '/volumes/1234/action',
+ {'os-migrate_volume': {'host': 'dest',
+ 'force_host_copy': False,
+ 'lock_volume': True}})
+ self._assert_request_id(vol)
+
+ def test_migrate_cluster(self):
+ v = cs3.volumes.get('fake')
+ self._assert_request_id(v)
+ vol = cs3.volumes.migrate_volume(v, 'host_dest', False, False,
+ 'cluster_dest')
+ cs3.assert_called('POST', '/volumes/fake/action',
+ {'os-migrate_volume': {'cluster': 'cluster_dest',
+ 'force_host_copy': False,
+ 'lock_volume': False}})
+ self._assert_request_id(vol)