summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/common/quota.py33
-rw-r--r--openstackclient/compute/v2/server.py14
-rw-r--r--openstackclient/network/v2/port.py6
-rw-r--r--openstackclient/tests/functional/common/test_quota.py3
-rw-r--r--openstackclient/tests/functional/compute/v2/test_aggregate.py46
-rw-r--r--openstackclient/tests/functional/network/v2/test_floating_ip.py39
-rw-r--r--openstackclient/tests/functional/volume/v2/test_qos.py4
-rw-r--r--openstackclient/tests/functional/volume/v2/test_snapshot.py239
-rw-r--r--openstackclient/tests/functional/volume/v2/test_volume.py305
-rw-r--r--openstackclient/tests/unit/common/test_quota.py72
-rw-r--r--openstackclient/tests/unit/volume/v2/test_qos_specs.py28
-rw-r--r--openstackclient/volume/v2/qos_specs.py11
12 files changed, 588 insertions, 212 deletions
diff --git a/openstackclient/common/quota.py b/openstackclient/common/quota.py
index fa6c5765..d86aec58 100644
--- a/openstackclient/common/quota.py
+++ b/openstackclient/common/quota.py
@@ -182,9 +182,36 @@ class SetQuota(command.Command):
project,
**volume_kwargs)
if network_kwargs:
- network_client.update_quota(
- project,
- **network_kwargs)
+ if hasattr(_quota.Quota, 'allow_get'):
+ # TODO(huanxuan): Remove this block once the fixed
+ # SDK Quota class is the minimum required version.
+ # This is expected to be SDK release 0.9.13
+ res = network_client._get_resource(
+ _quota.Quota, project, **network_kwargs)
+ if any([res._body.dirty, res._header.dirty]):
+ request = res._prepare_request(prepend_key=True)
+ # remove the id in the body
+ if 'id' in request.body[res.resource_key]:
+ del request.body[res.resource_key]['id']
+ if res.patch_update:
+ response = network_client.session.patch(
+ request.uri,
+ endpoint_filter=res.service,
+ json=request.body,
+ headers=request.headers
+ )
+ else:
+ response = network_client.session.put(
+ request.uri,
+ endpoint_filter=res.service,
+ json=request.body,
+ headers=request.headers
+ )
+ res._translate_response(response, has_body=True)
+ else:
+ network_client.update_quota(
+ project,
+ **network_kwargs)
class ShowQuota(command.ShowOne):
diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py
index d9221873..798d3d3f 100644
--- a/openstackclient/compute/v2/server.py
+++ b/openstackclient/compute/v2/server.py
@@ -144,6 +144,20 @@ def _prep_server_detail(compute_client, server):
except Exception:
info['flavor'] = flavor_id
+ if 'os-extended-volumes:volumes_attached' in info:
+ info.update(
+ {
+ 'volumes_attached': utils.format_list_of_dicts(
+ info.pop('os-extended-volumes:volumes_attached'))
+ }
+ )
+ if 'security_groups' in info:
+ info.update(
+ {
+ 'security_groups': utils.format_list_of_dicts(
+ info.pop('security_groups'))
+ }
+ )
# NOTE(dtroyer): novaclient splits these into separate entries...
# Format addresses in a useful way
info['addresses'] = _format_servers_list_networks(server.networks)
diff --git a/openstackclient/network/v2/port.py b/openstackclient/network/v2/port.py
index 4525da18..20f3ad75 100644
--- a/openstackclient/network/v2/port.py
+++ b/openstackclient/network/v2/port.py
@@ -35,6 +35,10 @@ def _format_admin_state(state):
return 'UP' if state else 'DOWN'
+def _format_dns_assignment(dns_assignment):
+ return utils.format_list_of_dicts(dns_assignment) \
+ if dns_assignment else None
+
_formatters = {
'admin_state_up': _format_admin_state,
'is_admin_state_up': _format_admin_state,
@@ -43,7 +47,7 @@ _formatters = {
'binding_vif_details': utils.format_dict,
'binding:profile': utils.format_dict,
'binding:vif_details': utils.format_dict,
- 'dns_assignment': utils.format_list_of_dicts,
+ 'dns_assignment': _format_dns_assignment,
'extra_dhcp_opts': utils.format_list_of_dicts,
'fixed_ips': utils.format_list_of_dicts,
'security_group_ids': utils.format_list,
diff --git a/openstackclient/tests/functional/common/test_quota.py b/openstackclient/tests/functional/common/test_quota.py
index b2b198af..c1de9aa9 100644
--- a/openstackclient/tests/functional/common/test_quota.py
+++ b/openstackclient/tests/functional/common/test_quota.py
@@ -10,8 +10,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import testtools
-
from openstackclient.tests.functional import base
@@ -27,7 +25,6 @@ class QuotaTests(base.TestCase):
cls.PROJECT_NAME =\
cls.get_openstack_configuration_value('auth.project_name')
- @testtools.skip('broken SDK testing')
def test_quota_set(self):
self.openstack('quota set --instances 11 --volumes 11 --networks 11 ' +
self.PROJECT_NAME)
diff --git a/openstackclient/tests/functional/compute/v2/test_aggregate.py b/openstackclient/tests/functional/compute/v2/test_aggregate.py
index 2bc88e7b..38368103 100644
--- a/openstackclient/tests/functional/compute/v2/test_aggregate.py
+++ b/openstackclient/tests/functional/compute/v2/test_aggregate.py
@@ -48,7 +48,7 @@ class AggregateTests(base.TestCase):
self.assertEqual(self.NAME + "\n", raw_output)
def test_aggregate_properties(self):
- opts = self.get_opts(['properties'])
+ opts = self.get_opts(['name', 'properties'])
raw_output = self.openstack(
'aggregate set --property a=b --property c=d ' + self.NAME
@@ -56,7 +56,7 @@ class AggregateTests(base.TestCase):
self.assertEqual('', raw_output)
raw_output = self.openstack('aggregate show ' + self.NAME + opts)
- self.assertIn("a='b', c='d'\n", raw_output)
+ self.assertIn(self.NAME + "\na='b', c='d'\n", raw_output)
raw_output = self.openstack(
'aggregate unset --property a ' + self.NAME
@@ -64,4 +64,44 @@ class AggregateTests(base.TestCase):
self.assertEqual('', raw_output)
raw_output = self.openstack('aggregate show ' + self.NAME + opts)
- self.assertIn("c='d'\n", raw_output)
+ self.assertIn(self.NAME + "\nc='d'\n", raw_output)
+
+ raw_output = self.openstack(
+ 'aggregate set --property a=b --property c=d ' + self.NAME
+ )
+ self.assertEqual('', raw_output)
+
+ raw_output = self.openstack(
+ 'aggregate set --no-property ' + self.NAME
+ )
+ self.assertEqual('', raw_output)
+
+ raw_output = self.openstack('aggregate show ' + self.NAME + opts)
+ self.assertNotIn("a='b', c='d'", raw_output)
+
+ def test_aggregate_set(self):
+ opts = self.get_opts(["name", "availability_zone"])
+
+ raw_output = self.openstack(
+ 'aggregate set --zone Zone_1 ' + self.NAME)
+ self.assertEqual("", raw_output)
+
+ raw_output = self.openstack('aggregate show ' + self.NAME + opts)
+ self.assertEqual("Zone_1\n" + self.NAME + "\n", raw_output)
+
+ def test_aggregate_add_and_remove_host(self):
+ opts = self.get_opts(["hosts", "name"])
+
+ raw_output = self.openstack('host list -f value -c "Host Name"')
+ host_name = raw_output.split()[0]
+
+ self.openstack(
+ 'aggregate add host ' + self.NAME + ' ' + host_name)
+ raw_output = self.openstack('aggregate show ' + self.NAME + opts)
+ self.assertEqual("[u'" + host_name + "']" + "\n" + self.NAME + "\n",
+ raw_output)
+
+ self.openstack(
+ 'aggregate remove host ' + self.NAME + ' ' + host_name)
+ raw_output = self.openstack('aggregate show ' + self.NAME + opts)
+ self.assertEqual("[]\n" + self.NAME + "\n", raw_output)
diff --git a/openstackclient/tests/functional/network/v2/test_floating_ip.py b/openstackclient/tests/functional/network/v2/test_floating_ip.py
index fa9607a0..8fbec3d5 100644
--- a/openstackclient/tests/functional/network/v2/test_floating_ip.py
+++ b/openstackclient/tests/functional/network/v2/test_floating_ip.py
@@ -31,25 +31,38 @@ class FloatingIpTests(base.TestCase):
cls.re_description = re.compile("description\s+\|\s+([^|]+?)\s+\|")
cls.re_network_id = re.compile("floating_network_id\s+\|\s+(\S+)")
- # Make a random subnet
- cls.subnet = ".".join(map(
- str,
- (random.randint(0, 223) for _ in range(3))
- )) + ".0/26"
-
# Create a network for the floating ip
raw_output = cls.openstack(
'network create --external ' + cls.NETWORK_NAME
)
cls.network_id = re.search(cls.re_id, raw_output).group(1)
- # Create a subnet for the network
- raw_output = cls.openstack(
- 'subnet create ' +
- '--network ' + cls.NETWORK_NAME + ' ' +
- '--subnet-range ' + cls.subnet + ' ' +
- cls.SUBNET_NAME
- )
+ # Try random subnet range for subnet creating
+ # Because we can not determine ahead of time what subnets are already
+ # in use, possibly by another test running in parallel, try 4 times
+ for i in range(4):
+ # Make a random subnet
+ cls.subnet = ".".join(map(
+ str,
+ (random.randint(0, 223) for _ in range(3))
+ )) + ".0/26"
+ try:
+ # Create a subnet for the network
+ raw_output = cls.openstack(
+ 'subnet create ' +
+ '--network ' + cls.NETWORK_NAME + ' ' +
+ '--subnet-range ' + cls.subnet + ' ' +
+ cls.SUBNET_NAME
+ )
+ except Exception:
+ if (i == 3):
+ # raise the exception at the last time
+ raise
+ pass
+ else:
+ # break and no longer retry if create sucessfully
+ break
+
cls.subnet_id = re.search(cls.re_id, raw_output).group(1)
@classmethod
diff --git a/openstackclient/tests/functional/volume/v2/test_qos.py b/openstackclient/tests/functional/volume/v2/test_qos.py
index a54acbfd..1558c216 100644
--- a/openstackclient/tests/functional/volume/v2/test_qos.py
+++ b/openstackclient/tests/functional/volume/v2/test_qos.py
@@ -50,13 +50,13 @@ class QosTests(common.BaseVolumeTests):
raw_output = self.openstack(
'volume qos set --property a=b --property c=d ' + self.ID)
self.assertEqual("", raw_output)
- opts = self.get_opts(['name', 'specs'])
+ opts = self.get_opts(['name', 'properties'])
raw_output = self.openstack('volume qos show ' + self.ID + opts)
self.assertEqual(self.NAME + "\na='b', c='d'\n", raw_output)
raw_output = self.openstack(
'volume qos unset --property a ' + self.ID)
self.assertEqual("", raw_output)
- opts = self.get_opts(['name', 'specs'])
+ opts = self.get_opts(['name', 'properties'])
raw_output = self.openstack('volume qos show ' + self.ID + opts)
self.assertEqual(self.NAME + "\nc='d'\n", raw_output)
diff --git a/openstackclient/tests/functional/volume/v2/test_snapshot.py b/openstackclient/tests/functional/volume/v2/test_snapshot.py
index 4eb69e9d..c83e79f8 100644
--- a/openstackclient/tests/functional/volume/v2/test_snapshot.py
+++ b/openstackclient/tests/functional/volume/v2/test_snapshot.py
@@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import json
import time
import uuid
@@ -20,9 +21,6 @@ class VolumeSnapshotTests(common.BaseVolumeTests):
"""Functional tests for volume snapshot. """
VOLLY = uuid.uuid4().hex
- NAME = uuid.uuid4().hex
- OTHER_NAME = uuid.uuid4().hex
- HEADERS = ['"Name"']
@classmethod
def wait_for_status(cls, command, status, tries):
@@ -37,52 +35,211 @@ class VolumeSnapshotTests(common.BaseVolumeTests):
@classmethod
def setUpClass(cls):
super(VolumeSnapshotTests, cls).setUpClass()
- cls.openstack('volume create --size 1 ' + cls.VOLLY)
- cls.wait_for_status('volume show ' + cls.VOLLY, 'available\n', 3)
- opts = cls.get_opts(['status'])
- raw_output = cls.openstack('volume snapshot create --volume ' +
- cls.VOLLY + ' ' + cls.NAME + opts)
- cls.assertOutput('creating\n', raw_output)
- cls.wait_for_status(
- 'volume snapshot show ' + cls.NAME, 'available\n', 3)
+ # create a volume for all tests to create snapshot
+ cmd_output = json.loads(cls.openstack(
+ 'volume create -f json ' +
+ '--size 1 ' +
+ cls.VOLLY
+ ))
+ cls.wait_for_status('volume show ' + cls.VOLLY, 'available\n', 6)
+ cls.VOLUME_ID = cmd_output['id']
@classmethod
def tearDownClass(cls):
- # Rename test
- raw_output = cls.openstack(
- 'volume snapshot set --name ' + cls.OTHER_NAME + ' ' + cls.NAME)
- cls.assertOutput('', raw_output)
- # Delete test
- raw_output_snapshot = cls.openstack(
- 'volume snapshot delete ' + cls.OTHER_NAME)
cls.wait_for_status('volume show ' + cls.VOLLY, 'available\n', 6)
- raw_output_volume = cls.openstack('volume delete --force ' + cls.VOLLY)
- cls.assertOutput('', raw_output_snapshot)
- cls.assertOutput('', raw_output_volume)
+ raw_output = cls.openstack('volume delete --force ' + cls.VOLLY)
+ cls.assertOutput('', raw_output)
- def test_snapshot_list(self):
- opts = self.get_opts(self.HEADERS)
- raw_output = self.openstack('volume snapshot list' + opts)
- self.assertIn(self.NAME, raw_output)
+ def test_volume_snapshot__delete(self):
+ """Test create, delete multiple"""
+ name1 = uuid.uuid4().hex
+ cmd_output = json.loads(self.openstack(
+ 'volume snapshot create -f json ' +
+ name1 +
+ ' --volume ' + self.VOLLY
+ ))
+ self.assertEqual(
+ name1,
+ cmd_output["name"],
+ )
- def test_snapshot_properties(self):
- raw_output = self.openstack(
- 'volume snapshot set --property a=b --property c=d ' + self.NAME)
- self.assertEqual("", raw_output)
- opts = self.get_opts(["properties"])
- raw_output = self.openstack('volume snapshot show ' + self.NAME + opts)
- self.assertEqual("a='b', c='d'\n", raw_output)
+ name2 = uuid.uuid4().hex
+ cmd_output = json.loads(self.openstack(
+ 'volume snapshot create -f json ' +
+ name2 +
+ ' --volume ' + self.VOLLY
+ ))
+ self.assertEqual(
+ name2,
+ cmd_output["name"],
+ )
+
+ self.wait_for_status(
+ 'volume snapshot show ' + name1, 'available\n', 6)
+ self.wait_for_status(
+ 'volume snapshot show ' + name2, 'available\n', 6)
+
+ del_output = self.openstack(
+ 'volume snapshot delete ' + name1 + ' ' + name2)
+ self.assertOutput('', del_output)
+
+ def test_volume_snapshot_list(self):
+ """Test create, list filter"""
+ name1 = uuid.uuid4().hex
+ cmd_output = json.loads(self.openstack(
+ 'volume snapshot create -f json ' +
+ name1 +
+ ' --volume ' + self.VOLLY
+ ))
+ self.addCleanup(self.openstack, 'volume snapshot delete ' + name1)
+ self.assertEqual(
+ name1,
+ cmd_output["name"],
+ )
+ self.assertEqual(
+ self.VOLUME_ID,
+ cmd_output["volume_id"],
+ )
+ self.assertEqual(
+ 1,
+ cmd_output["size"],
+ )
+ self.wait_for_status(
+ 'volume snapshot show ' + name1, 'available\n', 6)
+ name2 = uuid.uuid4().hex
+ cmd_output = json.loads(self.openstack(
+ 'volume snapshot create -f json ' +
+ name2 +
+ ' --volume ' + self.VOLLY
+ ))
+ self.addCleanup(self.openstack, 'volume snapshot delete ' + name2)
+ self.assertEqual(
+ name2,
+ cmd_output["name"],
+ )
+ self.assertEqual(
+ self.VOLUME_ID,
+ cmd_output["volume_id"],
+ )
+ self.assertEqual(
+ 1,
+ cmd_output["size"],
+ )
+ self.wait_for_status(
+ 'volume snapshot show ' + name2, 'available\n', 6)
raw_output = self.openstack(
- 'volume snapshot unset --property a ' + self.NAME)
- self.assertEqual("", raw_output)
- raw_output = self.openstack('volume snapshot show ' + self.NAME + opts)
- self.assertEqual("c='d'\n", raw_output)
+ 'volume snapshot set ' +
+ '--state error ' +
+ name2
+ )
+ self.assertOutput('', raw_output)
+
+ # Test list --long, --status
+ cmd_output = json.loads(self.openstack(
+ 'volume snapshot list -f json ' +
+ '--long ' +
+ '--status error'
+ ))
+ names = [x["Name"] for x in cmd_output]
+ self.assertNotIn(name1, names)
+ self.assertIn(name2, names)
+
+ # Test list --volume
+ cmd_output = json.loads(self.openstack(
+ 'volume snapshot list -f json ' +
+ '--volume ' + self.VOLLY
+ ))
+ names = [x["Name"] for x in cmd_output]
+ self.assertIn(name1, names)
+ self.assertIn(name2, names)
+
+ # Test list --name
+ cmd_output = json.loads(self.openstack(
+ 'volume snapshot list -f json ' +
+ '--name ' + name1
+ ))
+ names = [x["Name"] for x in cmd_output]
+ self.assertIn(name1, names)
+ self.assertNotIn(name2, names)
def test_snapshot_set(self):
+ """Test create, set, unset, show, delete volume snapshot"""
+ name = uuid.uuid4().hex
+ new_name = name + "_"
+ cmd_output = json.loads(self.openstack(
+ 'volume snapshot create -f json ' +
+ '--volume ' + self.VOLLY +
+ ' --description aaaa ' +
+ '--property Alpha=a ' +
+ name
+ ))
+ self.addCleanup(self.openstack, 'volume snapshot delete ' + new_name)
+ self.assertEqual(
+ name,
+ cmd_output["name"],
+ )
+ self.assertEqual(
+ 1,
+ cmd_output["size"],
+ )
+ self.assertEqual(
+ 'aaaa',
+ cmd_output["description"],
+ )
+ self.assertEqual(
+ "Alpha='a'",
+ cmd_output["properties"],
+ )
+ self.wait_for_status(
+ 'volume snapshot show ' + name, 'available\n', 6)
+
+ # Test volume snapshot set
raw_output = self.openstack(
- 'volume snapshot set --description backup ' + self.NAME)
- self.assertEqual("", raw_output)
- opts = self.get_opts(["description", "name"])
- raw_output = self.openstack('volume snapshot show ' + self.NAME + opts)
- self.assertEqual("backup\n" + self.NAME + "\n", raw_output)
+ 'volume snapshot set ' +
+ '--name ' + new_name +
+ ' --description bbbb ' +
+ '--property Alpha=c ' +
+ '--property Beta=b ' +
+ name,
+ )
+ self.assertOutput('', raw_output)
+
+ # Show snapshot set result
+ cmd_output = json.loads(self.openstack(
+ 'volume snapshot show -f json ' +
+ new_name
+ ))
+ self.assertEqual(
+ new_name,
+ cmd_output["name"],
+ )
+ self.assertEqual(
+ 1,
+ cmd_output["size"],
+ )
+ self.assertEqual(
+ 'bbbb',
+ cmd_output["description"],
+ )
+ self.assertEqual(
+ "Alpha='c', Beta='b'",
+ cmd_output["properties"],
+ )
+
+ # Test volume unset
+ raw_output = self.openstack(
+ 'volume snapshot unset ' +
+ '--property Alpha ' +
+ new_name,
+ )
+ self.assertOutput('', raw_output)
+
+ cmd_output = json.loads(self.openstack(
+ 'volume snapshot show -f json ' +
+ new_name
+ ))
+ self.assertEqual(
+ "Beta='b'",
+ cmd_output["properties"],
+ )
diff --git a/openstackclient/tests/functional/volume/v2/test_volume.py b/openstackclient/tests/functional/volume/v2/test_volume.py
index ea891cba..203ca819 100644
--- a/openstackclient/tests/functional/volume/v2/test_volume.py
+++ b/openstackclient/tests/functional/volume/v2/test_volume.py
@@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import json
import time
import uuid
@@ -19,118 +20,220 @@ from openstackclient.tests.functional.volume.v2 import common
class VolumeTests(common.BaseVolumeTests):
"""Functional tests for volume. """
- NAME = uuid.uuid4().hex
- SNAPSHOT_NAME = uuid.uuid4().hex
- VOLUME_FROM_SNAPSHOT_NAME = uuid.uuid4().hex
- OTHER_NAME = uuid.uuid4().hex
- HEADERS = ['"Display Name"']
- FIELDS = ['name']
-
- @classmethod
- def setUpClass(cls):
- super(VolumeTests, cls).setUpClass()
- opts = cls.get_opts(cls.FIELDS)
-
- # Create test volume
- raw_output = cls.openstack('volume create --size 1 ' + cls.NAME + opts)
- expected = cls.NAME + '\n'
- cls.assertOutput(expected, raw_output)
-
- @classmethod
- def tearDownClass(cls):
- # Rename test volume
- raw_output = cls.openstack(
- 'volume set --name ' + cls.OTHER_NAME + ' ' + cls.NAME)
- cls.assertOutput('', raw_output)
-
- # Set volume state
- cls.openstack('volume set --state error ' + cls.OTHER_NAME)
- opts = cls.get_opts(["status"])
- raw_output_status = cls.openstack(
- 'volume show ' + cls.OTHER_NAME + opts)
-
- # Delete test volume
- raw_output = cls.openstack('volume delete ' + cls.OTHER_NAME)
- cls.assertOutput('', raw_output)
- cls.assertOutput('error\n', raw_output_status)
+ def test_volume_delete(self):
+ """Test create, delete multiple"""
+ name1 = uuid.uuid4().hex
+ cmd_output = json.loads(self.openstack(
+ 'volume create -f json ' +
+ '--size 1 ' +
+ name1
+ ))
+ self.assertEqual(
+ 1,
+ cmd_output["size"],
+ )
+
+ name2 = uuid.uuid4().hex
+ cmd_output = json.loads(self.openstack(
+ 'volume create -f json ' +
+ '--size 2 ' +
+ name2
+ ))
+ self.assertEqual(
+ 2,
+ cmd_output["size"],
+ )
+
+ self.wait_for("volume", name1, "available")
+ self.wait_for("volume", name2, "available")
+ del_output = self.openstack('volume delete ' + name1 + ' ' + name2)
+ self.assertOutput('', del_output)
def test_volume_list(self):
- opts = self.get_opts(self.HEADERS)
- raw_output = self.openstack('volume list' + opts)
- self.assertIn(self.NAME, raw_output)
-
- def test_volume_show(self):
- opts = self.get_opts(self.FIELDS)
- raw_output = self.openstack('volume show ' + self.NAME + opts)
- self.assertEqual(self.NAME + "\n", raw_output)
-
- def test_volume_properties(self):
+ """Test create, list filter"""
+ name1 = uuid.uuid4().hex
+ cmd_output = json.loads(self.openstack(
+ 'volume create -f json ' +
+ '--size 1 ' +
+ name1
+ ))
+ self.addCleanup(self.openstack, 'volume delete ' + name1)
+ self.assertEqual(
+ 1,
+ cmd_output["size"],
+ )
+ self.wait_for("volume", name1, "available")
+
+ name2 = uuid.uuid4().hex
+ cmd_output = json.loads(self.openstack(
+ 'volume create -f json ' +
+ '--size 2 ' +
+ name2
+ ))
+ self.addCleanup(self.openstack, 'volume delete ' + name2)
+ self.assertEqual(
+ 2,
+ cmd_output["size"],
+ )
+ self.wait_for("volume", name2, "available")
raw_output = self.openstack(
- 'volume set --property a=b --property c=d ' + self.NAME)
- self.assertEqual("", raw_output)
- opts = self.get_opts(["properties"])
- raw_output = self.openstack('volume show ' + self.NAME + opts)
- self.assertEqual("a='b', c='d'\n", raw_output)
+ 'volume set ' +
+ '--state error ' +
+ name2
+ )
+ self.assertOutput('', raw_output)
- raw_output = self.openstack('volume unset --property a ' + self.NAME)
- self.assertEqual("", raw_output)
- raw_output = self.openstack('volume show ' + self.NAME + opts)
- self.assertEqual("c='d'\n", raw_output)
+ # Test list --long
+ cmd_output = json.loads(self.openstack(
+ 'volume list -f json ' +
+ '--long'
+ ))
+ names = [x["Display Name"] for x in cmd_output]
+ self.assertIn(name1, names)
+ self.assertIn(name2, names)
+
+ # Test list --status
+ cmd_output = json.loads(self.openstack(
+ 'volume list -f json ' +
+ '--status error'
+ ))
+ names = [x["Display Name"] for x in cmd_output]
+ self.assertNotIn(name1, names)
+ self.assertIn(name2, names)
+
+ # TODO(qiangjiahui): Add project option to filter tests when we can
+ # specify volume with project
def test_volume_set(self):
- discription = uuid.uuid4().hex
- self.openstack('volume set --description ' + discription + ' ' +
- self.NAME)
- opts = self.get_opts(["description", "name"])
- raw_output = self.openstack('volume show ' + self.NAME + opts)
- self.assertEqual(discription + "\n" + self.NAME + "\n", raw_output)
-
- def test_volume_set_size(self):
- self.openstack('volume set --size 2 ' + self.NAME)
- opts = self.get_opts(["name", "size"])
- raw_output = self.openstack('volume show ' + self.NAME + opts)
- self.assertEqual(self.NAME + "\n2\n", raw_output)
-
- def test_volume_set_bootable(self):
- self.openstack('volume set --bootable ' + self.NAME)
- opts = self.get_opts(["bootable"])
- raw_output = self.openstack('volume show ' + self.NAME + opts)
- self.assertEqual("true\n", raw_output)
-
- self.openstack('volume set --non-bootable ' + self.NAME)
- opts = self.get_opts(["bootable"])
- raw_output = self.openstack('volume show ' + self.NAME + opts)
- self.assertEqual("false\n", raw_output)
+ """Tests create volume, set, unset, show, delete"""
+ name = uuid.uuid4().hex
+ new_name = name + "_"
+ cmd_output = json.loads(self.openstack(
+ 'volume create -f json ' +
+ '--size 1 ' +
+ '--description aaaa ' +
+ '--property Alpha=a ' +
+ name
+ ))
+ self.addCleanup(self.openstack, 'volume delete ' + new_name)
+ self.assertEqual(
+ name,
+ cmd_output["name"],
+ )
+ self.assertEqual(
+ 1,
+ cmd_output["size"],
+ )
+ self.assertEqual(
+ 'aaaa',
+ cmd_output["description"],
+ )
+ self.assertEqual(
+ "Alpha='a'",
+ cmd_output["properties"],
+ )
+ self.assertEqual(
+ 'false',
+ cmd_output["bootable"],
+ )
+ self.wait_for("volume", name, "available")
+
+ # Test volume set
+ raw_output = self.openstack(
+ 'volume set ' +
+ '--name ' + new_name +
+ ' --size 2 ' +
+ '--description bbbb ' +
+ '--property Alpha=c ' +
+ '--property Beta=b ' +
+ '--bootable ' +
+ name,
+ )
+ self.assertOutput('', raw_output)
- def test_volume_snapshot(self):
- opts = self.get_opts(self.FIELDS)
-
- # Create snapshot from test volume
- raw_output = self.openstack('volume snapshot create ' +
- self.SNAPSHOT_NAME +
- ' --volume ' + self.NAME + opts)
- expected = self.SNAPSHOT_NAME + '\n'
- self.assertOutput(expected, raw_output)
- self.wait_for("volume snapshot", self.SNAPSHOT_NAME, "available")
-
- # Create volume from snapshot
- raw_output = self.openstack('volume create --size 2 --snapshot ' +
- self.SNAPSHOT_NAME + ' ' +
- self.VOLUME_FROM_SNAPSHOT_NAME + opts)
- expected = self.VOLUME_FROM_SNAPSHOT_NAME + '\n'
- self.assertOutput(expected, raw_output)
- self.wait_for("volume", self.VOLUME_FROM_SNAPSHOT_NAME, "available")
-
- # Delete volume that create from snapshot
- raw_output = self.openstack('volume delete ' +
- self.VOLUME_FROM_SNAPSHOT_NAME)
+ cmd_output = json.loads(self.openstack(
+ 'volume show -f json ' +
+ new_name
+ ))
+ self.assertEqual(
+ new_name,
+ cmd_output["name"],
+ )
+ self.assertEqual(
+ 2,
+ cmd_output["size"],
+ )
+ self.assertEqual(
+ 'bbbb',
+ cmd_output["description"],
+ )
+ self.assertEqual(
+ "Alpha='c', Beta='b'",
+ cmd_output["properties"],
+ )
+ self.assertEqual(
+ 'true',
+ cmd_output["bootable"],
+ )
+
+ # Test volume unset
+ raw_output = self.openstack(
+ 'volume unset ' +
+ '--property Alpha ' +
+ new_name,
+ )
self.assertOutput('', raw_output)
- # Delete test snapshot
+ cmd_output = json.loads(self.openstack(
+ 'volume show -f json ' +
+ new_name
+ ))
+ self.assertEqual(
+ "Beta='b'",
+ cmd_output["properties"],
+ )
+
+ def test_volume_snapshot(self):
+ """Tests volume create from snapshot"""
+
+ volume_name = uuid.uuid4().hex
+ snapshot_name = uuid.uuid4().hex
+ # Make a snapshot
+ cmd_output = json.loads(self.openstack(
+ 'volume create -f json ' +
+ '--size 1 ' +
+ volume_name
+ ))
+ self.wait_for("volume", volume_name, "available")
+ self.assertEqual(
+ volume_name,
+ cmd_output["name"],
+ )
+ cmd_output = json.loads(self.openstack(
+ 'volume snapshot create -f json ' +
+ snapshot_name +
+ ' --volume ' + volume_name
+ ))
+ self.wait_for("volume snapshot", snapshot_name, "available")
+
+ name = uuid.uuid4().hex
+ cmd_output = json.loads(self.openstack(
+ 'volume create -f json ' +
+ '--snapshot ' + snapshot_name +
+ ' ' + name
+ ))
+ self.addCleanup(self.openstack, 'volume delete ' + name)
+ self.addCleanup(self.openstack, 'volume delete ' + volume_name)
+ self.assertEqual(
+ name,
+ cmd_output["name"],
+ )
+ self.wait_for("volume", name, "available")
+
+ # Delete snapshot
raw_output = self.openstack(
- 'volume snapshot delete ' + self.SNAPSHOT_NAME)
+ 'volume snapshot delete ' + snapshot_name)
self.assertOutput('', raw_output)
- self.wait_for("volume", self.NAME, "available")
def wait_for(self, check_type, check_name, desired_status, wait=120,
interval=5, failures=['ERROR']):
diff --git a/openstackclient/tests/unit/common/test_quota.py b/openstackclient/tests/unit/common/test_quota.py
index 7dd23373..244d74d2 100644
--- a/openstackclient/tests/unit/common/test_quota.py
+++ b/openstackclient/tests/unit/common/test_quota.py
@@ -13,6 +13,8 @@
import copy
import mock
+from openstack.network.v2 import quota as _quota
+
from openstackclient.common import quota
from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes
from openstackclient.tests.unit import fakes
@@ -282,27 +284,32 @@ class TestQuotaSet(TestQuota):
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- result = self.cmd.take_action(parsed_args)
- kwargs = {
- 'subnet': network_fakes.QUOTA['subnet'],
- 'network': network_fakes.QUOTA['network'],
- 'floatingip': network_fakes.QUOTA['floatingip'],
- 'subnetpool': network_fakes.QUOTA['subnetpool'],
- 'security_group_rule':
- network_fakes.QUOTA['security_group_rule'],
- 'security_group': network_fakes.QUOTA['security_group'],
- 'router': network_fakes.QUOTA['router'],
- 'rbac_policy': network_fakes.QUOTA['rbac_policy'],
- 'port': network_fakes.QUOTA['port'],
- 'vip': network_fakes.QUOTA['vip'],
- 'healthmonitor': network_fakes.QUOTA['healthmonitor'],
- 'l7policy': network_fakes.QUOTA['l7policy'],
- }
- self.network_mock.update_quota.assert_called_once_with(
- identity_fakes.project_id,
- **kwargs
- )
- self.assertIsNone(result)
+ # TODO(huanxuan): Remove this if condition once the fixed
+ # SDK Quota class is the minimum required version.
+ # This is expected to be SDK release 0.9.13
+ if not hasattr(_quota.Quota, 'allow_get'):
+ # Just run this when sdk <= 0.9.10
+ result = self.cmd.take_action(parsed_args)
+ kwargs = {
+ 'subnet': network_fakes.QUOTA['subnet'],
+ 'network': network_fakes.QUOTA['network'],
+ 'floatingip': network_fakes.QUOTA['floatingip'],
+ 'subnetpool': network_fakes.QUOTA['subnetpool'],
+ 'security_group_rule':
+ network_fakes.QUOTA['security_group_rule'],
+ 'security_group': network_fakes.QUOTA['security_group'],
+ 'router': network_fakes.QUOTA['router'],
+ 'rbac_policy': network_fakes.QUOTA['rbac_policy'],
+ 'port': network_fakes.QUOTA['port'],
+ 'vip': network_fakes.QUOTA['vip'],
+ 'healthmonitor': network_fakes.QUOTA['healthmonitor'],
+ 'l7policy': network_fakes.QUOTA['l7policy'],
+ }
+ self.network_mock.update_quota.assert_called_once_with(
+ identity_fakes.project_id,
+ **kwargs
+ )
+ self.assertIsNone(result)
def test_quota_set_with_class(self):
arglist = [
@@ -476,15 +483,20 @@ class TestQuotaShow(TestQuota):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.cmd.take_action(parsed_args)
-
- self.quotas_mock.defaults.assert_called_once_with(
- identity_fakes.project_id)
- self.volume_quotas_mock.defaults.assert_called_once_with(
- identity_fakes.project_id)
- self.network.get_quota_default.assert_called_once_with(
- identity_fakes.project_id)
- self.assertNotCalled(self.network.get_quota)
+ # TODO(huanxuan): Remove this if condition once the fixed
+ # SDK QuotaDefault class is the minimum required version.
+ # This is expected to be SDK release 0.9.13
+ if not hasattr(_quota.QuotaDefault, 'project'):
+ # Just run this when sdk <= 0.9.10
+ self.cmd.take_action(parsed_args)
+
+ self.quotas_mock.defaults.assert_called_once_with(
+ identity_fakes.project_id)
+ self.volume_quotas_mock.defaults.assert_called_once_with(
+ identity_fakes.project_id)
+ self.network.get_quota_default.assert_called_once_with(
+ identity_fakes.project_id)
+ self.assertNotCalled(self.network.get_quota)
def test_quota_show_with_class(self):
arglist = [
diff --git a/openstackclient/tests/unit/volume/v2/test_qos_specs.py b/openstackclient/tests/unit/volume/v2/test_qos_specs.py
index 7597e852..35d9a345 100644
--- a/openstackclient/tests/unit/volume/v2/test_qos_specs.py
+++ b/openstackclient/tests/unit/volume/v2/test_qos_specs.py
@@ -70,24 +70,26 @@ class TestQosAssociate(TestQos):
class TestQosCreate(TestQos):
- new_qos_spec = volume_fakes.FakeQos.create_one_qos()
columns = (
'consumer',
'id',
'name',
- 'specs'
- )
- data = (
- new_qos_spec.consumer,
- new_qos_spec.id,
- new_qos_spec.name,
- new_qos_spec.specs
+ 'properties'
)
def setUp(self):
super(TestQosCreate, self).setUp()
+ self.new_qos_spec = volume_fakes.FakeQos.create_one_qos()
self.qos_mock.create.return_value = self.new_qos_spec
+
+ self.data = (
+ self.new_qos_spec.consumer,
+ self.new_qos_spec.id,
+ self.new_qos_spec.name,
+ utils.format_dict(self.new_qos_spec.specs)
+ )
+
# Get the command object to test
self.cmd = qos_specs.CreateQos(self.app, None)
@@ -147,11 +149,11 @@ class TestQosCreate(TestQos):
columns, data = self.cmd.take_action(parsed_args)
- self.new_qos_spec.specs.update(
- {'consumer': self.new_qos_spec.consumer})
self.qos_mock.create.assert_called_with(
self.new_qos_spec.name,
- self.new_qos_spec.specs
+ {'consumer': self.new_qos_spec.consumer,
+ 'foo': 'bar',
+ 'iops': '9001'}
)
self.assertEqual(self.columns, columns)
@@ -307,7 +309,7 @@ class TestQosList(TestQos):
'Name',
'Consumer',
'Associations',
- 'Specs',
+ 'Properties',
)
data = []
for q in qos_specs:
@@ -383,7 +385,7 @@ class TestQosShow(TestQos):
'consumer',
'id',
'name',
- 'specs'
+ 'properties'
)
data = (
qos_association.name,
diff --git a/openstackclient/volume/v2/qos_specs.py b/openstackclient/volume/v2/qos_specs.py
index b7f49eca..8e1d67b5 100644
--- a/openstackclient/volume/v2/qos_specs.py
+++ b/openstackclient/volume/v2/qos_specs.py
@@ -95,6 +95,9 @@ class CreateQos(command.ShowOne):
qos_spec = volume_client.qos_specs.create(parsed_args.name, specs)
+ qos_spec._info.update(
+ {'properties': utils.format_dict(qos_spec._info.pop('specs'))}
+ )
return zip(*sorted(six.iteritems(qos_spec._info)))
@@ -190,8 +193,11 @@ class ListQos(command.Lister):
for association in qos_associations]
qos._info.update({'associations': associations})
+ display_columns = (
+ 'ID', 'Name', 'Consumer', 'Associations', 'Properties')
+
columns = ('ID', 'Name', 'Consumer', 'Associations', 'Specs')
- return (columns,
+ return (display_columns,
(utils.get_dict_properties(
s._info, columns,
formatters={
@@ -254,7 +260,8 @@ class ShowQos(command.ShowOne):
qos_spec._info.update({
'associations': utils.format_list(associations)
})
- qos_spec._info.update({'specs': utils.format_dict(qos_spec.specs)})
+ qos_spec._info.update(
+ {'properties': utils.format_dict(qos_spec._info.pop('specs'))})
return zip(*sorted(six.iteritems(qos_spec._info)))