summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2015-07-25 03:25:57 +0000
committerGerrit Code Review <review@openstack.org>2015-07-25 03:25:57 +0000
commitcc6c4e5c399b92a8d6d958a8ff37458f1a072a1a (patch)
tree8a3f30b07bfe33e0501b47c2aa269a28a6770700 /openstackclient
parent55d9eba0937944119e6209c85005980c7297d123 (diff)
parent96afb8b1b7b59a8a53b6614457fbbf36fc9882dc (diff)
downloadpython-openstackclient-cc6c4e5c399b92a8d6d958a8ff37458f1a072a1a.tar.gz
Merge "Add support for volume v2 commands"
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/tests/volume/v2/fakes.py17
-rw-r--r--openstackclient/tests/volume/v2/test_volume.py469
-rw-r--r--openstackclient/volume/v2/volume.py235
3 files changed, 719 insertions, 2 deletions
diff --git a/openstackclient/tests/volume/v2/fakes.py b/openstackclient/tests/volume/v2/fakes.py
index c896ed6d..a95bc94b 100644
--- a/openstackclient/tests/volume/v2/fakes.py
+++ b/openstackclient/tests/volume/v2/fakes.py
@@ -17,6 +17,7 @@ import mock
from openstackclient.tests import fakes
from openstackclient.tests.identity.v2_0 import fakes as identity_fakes
+from openstackclient.tests.image.v2 import fakes as image_fakes
from openstackclient.tests import utils
volume_id = "ce26708d-a7f8-4b4b-9861-4a80256615a6"
@@ -26,8 +27,11 @@ volume_status = "available"
volume_size = 20
volume_type = "fake_lvmdriver-1"
volume_metadata = {
- "foo": "bar"
+ 'Alpha': 'a',
+ 'Beta': 'b',
+ 'Gamma': 'g',
}
+volume_metadata_str = "Alpha='a', Beta='b', Gamma='g'"
volume_snapshot_id = 1
volume_availability_zone = "nova"
volume_attachments = ["fake_attachments"]
@@ -169,6 +173,13 @@ QOS_WITH_ASSOCIATIONS = {
'associations': [qos_association]
}
+image_id = 'im1'
+image_name = 'graven'
+IMAGE = {
+ 'id': image_id,
+ 'name': image_name
+}
+
class FakeVolumeClient(object):
def __init__(self, **kwargs):
@@ -200,3 +211,7 @@ class TestVolume(utils.TestCommand):
endpoint=fakes.AUTH_URL,
token=fakes.AUTH_TOKEN
)
+ self.app.client_manager.image = image_fakes.FakeImagev2Client(
+ endpoint=fakes.AUTH_URL,
+ token=fakes.AUTH_TOKEN
+ )
diff --git a/openstackclient/tests/volume/v2/test_volume.py b/openstackclient/tests/volume/v2/test_volume.py
index 9e991b72..4fffefa4 100644
--- a/openstackclient/tests/volume/v2/test_volume.py
+++ b/openstackclient/tests/volume/v2/test_volume.py
@@ -15,18 +15,485 @@
import copy
from openstackclient.tests import fakes
+from openstackclient.tests.identity.v2_0 import fakes as identity_fakes
from openstackclient.tests.volume.v2 import fakes as volume_fakes
from openstackclient.volume.v2 import volume
class TestVolume(volume_fakes.TestVolume):
-
def setUp(self):
super(TestVolume, self).setUp()
self.volumes_mock = self.app.client_manager.volume.volumes
self.volumes_mock.reset_mock()
+ self.projects_mock = self.app.client_manager.identity.tenants
+ self.projects_mock.reset_mock()
+
+ self.users_mock = self.app.client_manager.identity.users
+ self.users_mock.reset_mock()
+
+ self.images_mock = self.app.client_manager.image.images
+ self.images_mock.reset_mock()
+
+
+class TestVolumeCreate(TestVolume):
+ def setUp(self):
+ super(TestVolumeCreate, self).setUp()
+
+ self.volumes_mock.create.return_value = fakes.FakeResource(
+ None,
+ copy.deepcopy(volume_fakes.VOLUME),
+ loaded=True,
+ )
+
+ # Get the command object to test
+ self.cmd = volume.CreateVolume(self.app, None)
+
+ def test_volume_create_min_options(self):
+ arglist = [
+ '--size', str(volume_fakes.volume_size),
+ volume_fakes.volume_name,
+ ]
+ verifylist = [
+ ('size', volume_fakes.volume_size),
+ ('name', volume_fakes.volume_name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # DisplayCommandBase.take_action() returns two tuples
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.volumes_mock.create.assert_called_with(
+ size=volume_fakes.volume_size,
+ snapshot_id=None,
+ name=volume_fakes.volume_name,
+ description=None,
+ volume_type=None,
+ user_id=None,
+ project_id=None,
+ availability_zone=None,
+ metadata=None,
+ imageRef=None,
+ source_volid=None
+ )
+
+ collist = (
+ 'attachments',
+ 'availability_zone',
+ 'description',
+ 'id',
+ 'name',
+ 'properties',
+ 'size',
+ 'snapshot_id',
+ 'status',
+ 'type',
+ )
+ self.assertEqual(collist, columns)
+ datalist = (
+ volume_fakes.volume_attachments,
+ volume_fakes.volume_availability_zone,
+ volume_fakes.volume_description,
+ volume_fakes.volume_id,
+ volume_fakes.volume_name,
+ volume_fakes.volume_metadata_str,
+ volume_fakes.volume_size,
+ volume_fakes.volume_snapshot_id,
+ volume_fakes.volume_status,
+ volume_fakes.volume_type,
+ )
+ self.assertEqual(datalist, data)
+
+ def test_volume_create_options(self):
+ arglist = [
+ '--size', str(volume_fakes.volume_size),
+ '--description', volume_fakes.volume_description,
+ '--type', volume_fakes.volume_type,
+ '--availability-zone', volume_fakes.volume_availability_zone,
+ volume_fakes.volume_name,
+ ]
+ verifylist = [
+ ('size', volume_fakes.volume_size),
+ ('description', volume_fakes.volume_description),
+ ('type', volume_fakes.volume_type),
+ ('availability_zone', volume_fakes.volume_availability_zone),
+ ('name', volume_fakes.volume_name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # DisplayCommandBase.take_action() returns two tuples
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.volumes_mock.create.assert_called_with(
+ size=volume_fakes.volume_size,
+ snapshot_id=None,
+ name=volume_fakes.volume_name,
+ description=volume_fakes.volume_description,
+ volume_type=volume_fakes.volume_type,
+ user_id=None,
+ project_id=None,
+ availability_zone=volume_fakes.volume_availability_zone,
+ metadata=None,
+ imageRef=None,
+ source_volid=None
+ )
+
+ collist = (
+ 'attachments',
+ 'availability_zone',
+ 'description',
+ 'id',
+ 'name',
+ 'properties',
+ 'size',
+ 'snapshot_id',
+ 'status',
+ 'type',
+ )
+ self.assertEqual(collist, columns)
+ datalist = (
+ volume_fakes.volume_attachments,
+ volume_fakes.volume_availability_zone,
+ volume_fakes.volume_description,
+ volume_fakes.volume_id,
+ volume_fakes.volume_name,
+ volume_fakes.volume_metadata_str,
+ volume_fakes.volume_size,
+ volume_fakes.volume_snapshot_id,
+ volume_fakes.volume_status,
+ volume_fakes.volume_type,
+ )
+ self.assertEqual(datalist, data)
+
+ def test_volume_create_user_project_id(self):
+ # Return a project
+ self.projects_mock.get.return_value = fakes.FakeResource(
+ None,
+ copy.deepcopy(identity_fakes.PROJECT),
+ loaded=True,
+ )
+ # Return a user
+ self.users_mock.get.return_value = fakes.FakeResource(
+ None,
+ copy.deepcopy(identity_fakes.USER),
+ loaded=True,
+ )
+
+ arglist = [
+ '--size', str(volume_fakes.volume_size),
+ '--project', identity_fakes.project_id,
+ '--user', identity_fakes.user_id,
+ volume_fakes.volume_name,
+ ]
+ verifylist = [
+ ('size', volume_fakes.volume_size),
+ ('project', identity_fakes.project_id),
+ ('user', identity_fakes.user_id),
+ ('name', volume_fakes.volume_name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # DisplayCommandBase.take_action() returns two tuples
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.volumes_mock.create.assert_called_with(
+ size=volume_fakes.volume_size,
+ snapshot_id=None,
+ name=volume_fakes.volume_name,
+ description=None,
+ volume_type=None,
+ user_id=identity_fakes.user_id,
+ project_id=identity_fakes.project_id,
+ availability_zone=None,
+ metadata=None,
+ imageRef=None,
+ source_volid=None
+ )
+
+ collist = (
+ 'attachments',
+ 'availability_zone',
+ 'description',
+ 'id',
+ 'name',
+ 'properties',
+ 'size',
+ 'snapshot_id',
+ 'status',
+ 'type',
+ )
+ self.assertEqual(collist, columns)
+ datalist = (
+ volume_fakes.volume_attachments,
+ volume_fakes.volume_availability_zone,
+ volume_fakes.volume_description,
+ volume_fakes.volume_id,
+ volume_fakes.volume_name,
+ volume_fakes.volume_metadata_str,
+ volume_fakes.volume_size,
+ volume_fakes.volume_snapshot_id,
+ volume_fakes.volume_status,
+ volume_fakes.volume_type,
+ )
+ self.assertEqual(datalist, data)
+
+ def test_volume_create_user_project_name(self):
+ # Return a project
+ self.projects_mock.get.return_value = fakes.FakeResource(
+ None,
+ copy.deepcopy(identity_fakes.PROJECT),
+ loaded=True,
+ )
+ # Return a user
+ self.users_mock.get.return_value = fakes.FakeResource(
+ None,
+ copy.deepcopy(identity_fakes.USER),
+ loaded=True,
+ )
+
+ arglist = [
+ '--size', str(volume_fakes.volume_size),
+ '--project', identity_fakes.project_name,
+ '--user', identity_fakes.user_name,
+ volume_fakes.volume_name,
+ ]
+ verifylist = [
+ ('size', volume_fakes.volume_size),
+ ('project', identity_fakes.project_name),
+ ('user', identity_fakes.user_name),
+ ('name', volume_fakes.volume_name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # DisplayCommandBase.take_action() returns two tuples
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.volumes_mock.create.assert_called_with(
+ size=volume_fakes.volume_size,
+ snapshot_id=None,
+ name=volume_fakes.volume_name,
+ description=None,
+ volume_type=None,
+ user_id=identity_fakes.user_id,
+ project_id=identity_fakes.project_id,
+ availability_zone=None,
+ metadata=None,
+ imageRef=None,
+ source_volid=None
+ )
+
+ collist = (
+ 'attachments',
+ 'availability_zone',
+ 'description',
+ 'id',
+ 'name',
+ 'properties',
+ 'size',
+ 'snapshot_id',
+ 'status',
+ 'type',
+ )
+ self.assertEqual(collist, columns)
+ datalist = (
+ volume_fakes.volume_attachments,
+ volume_fakes.volume_availability_zone,
+ volume_fakes.volume_description,
+ volume_fakes.volume_id,
+ volume_fakes.volume_name,
+ volume_fakes.volume_metadata_str,
+ volume_fakes.volume_size,
+ volume_fakes.volume_snapshot_id,
+ volume_fakes.volume_status,
+ volume_fakes.volume_type,
+ )
+ self.assertEqual(datalist, data)
+
+ def test_volume_create_properties(self):
+ arglist = [
+ '--property', 'Alpha=a',
+ '--property', 'Beta=b',
+ '--size', str(volume_fakes.volume_size),
+ volume_fakes.volume_name,
+ ]
+ verifylist = [
+ ('property', {'Alpha': 'a', 'Beta': 'b'}),
+ ('size', volume_fakes.volume_size),
+ ('name', volume_fakes.volume_name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # DisplayCommandBase.take_action() returns two tuples
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.volumes_mock.create.assert_called_with(
+ size=volume_fakes.volume_size,
+ snapshot_id=None,
+ name=volume_fakes.volume_name,
+ description=None,
+ volume_type=None,
+ user_id=None,
+ project_id=None,
+ availability_zone=None,
+ metadata={'Alpha': 'a', 'Beta': 'b'},
+ imageRef=None,
+ source_volid=None
+ )
+
+ collist = (
+ 'attachments',
+ 'availability_zone',
+ 'description',
+ 'id',
+ 'name',
+ 'properties',
+ 'size',
+ 'snapshot_id',
+ 'status',
+ 'type',
+ )
+ self.assertEqual(collist, columns)
+ datalist = (
+ volume_fakes.volume_attachments,
+ volume_fakes.volume_availability_zone,
+ volume_fakes.volume_description,
+ volume_fakes.volume_id,
+ volume_fakes.volume_name,
+ volume_fakes.volume_metadata_str,
+ volume_fakes.volume_size,
+ volume_fakes.volume_snapshot_id,
+ volume_fakes.volume_status,
+ volume_fakes.volume_type,
+ )
+ self.assertEqual(datalist, data)
+
+ def test_volume_create_image_id(self):
+ self.images_mock.get.return_value = fakes.FakeResource(
+ None,
+ copy.deepcopy(volume_fakes.IMAGE),
+ loaded=True,
+ )
+
+ arglist = [
+ '--image', volume_fakes.image_id,
+ '--size', str(volume_fakes.volume_size),
+ volume_fakes.volume_name,
+ ]
+ verifylist = [
+ ('image', volume_fakes.image_id),
+ ('size', volume_fakes.volume_size),
+ ('name', volume_fakes.volume_name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # DisplayCommandBase.take_action() returns two tuples
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.volumes_mock.create.assert_called_with(
+ size=volume_fakes.volume_size,
+ snapshot_id=None,
+ name=volume_fakes.volume_name,
+ description=None,
+ volume_type=None,
+ user_id=None,
+ project_id=None,
+ availability_zone=None,
+ metadata=None,
+ imageRef=volume_fakes.image_id,
+ source_volid=None
+ )
+
+ collist = (
+ 'attachments',
+ 'availability_zone',
+ 'description',
+ 'id',
+ 'name',
+ 'properties',
+ 'size',
+ 'snapshot_id',
+ 'status',
+ 'type',
+ )
+ self.assertEqual(collist, columns)
+ datalist = (
+ volume_fakes.volume_attachments,
+ volume_fakes.volume_availability_zone,
+ volume_fakes.volume_description,
+ volume_fakes.volume_id,
+ volume_fakes.volume_name,
+ volume_fakes.volume_metadata_str,
+ volume_fakes.volume_size,
+ volume_fakes.volume_snapshot_id,
+ volume_fakes.volume_status,
+ volume_fakes.volume_type,
+ )
+ self.assertEqual(datalist, data)
+
+ def test_volume_create_image_name(self):
+ self.images_mock.get.return_value = fakes.FakeResource(
+ None,
+ copy.deepcopy(volume_fakes.IMAGE),
+ loaded=True,
+ )
+
+ arglist = [
+ '--image', volume_fakes.image_name,
+ '--size', str(volume_fakes.volume_size),
+ volume_fakes.volume_name,
+ ]
+ verifylist = [
+ ('image', volume_fakes.image_name),
+ ('size', volume_fakes.volume_size),
+ ('name', volume_fakes.volume_name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # DisplayCommandBase.take_action() returns two tuples
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.volumes_mock.create.assert_called_with(
+ size=volume_fakes.volume_size,
+ snapshot_id=None,
+ name=volume_fakes.volume_name,
+ description=None,
+ volume_type=None,
+ user_id=None,
+ project_id=None,
+ availability_zone=None,
+ metadata=None,
+ imageRef=volume_fakes.image_id,
+ source_volid=None
+ )
+
+ collist = (
+ 'attachments',
+ 'availability_zone',
+ 'description',
+ 'id',
+ 'name',
+ 'properties',
+ 'size',
+ 'snapshot_id',
+ 'status',
+ 'type',
+ )
+ self.assertEqual(collist, columns)
+ datalist = (
+ volume_fakes.volume_attachments,
+ volume_fakes.volume_availability_zone,
+ volume_fakes.volume_description,
+ volume_fakes.volume_id,
+ volume_fakes.volume_name,
+ volume_fakes.volume_metadata_str,
+ volume_fakes.volume_size,
+ volume_fakes.volume_snapshot_id,
+ volume_fakes.volume_status,
+ volume_fakes.volume_type,
+ )
+ self.assertEqual(datalist, data)
+
class TestVolumeShow(TestVolume):
def setUp(self):
diff --git a/openstackclient/volume/v2/volume.py b/openstackclient/volume/v2/volume.py
index e50a6f0c..d4536f51 100644
--- a/openstackclient/volume/v2/volume.py
+++ b/openstackclient/volume/v2/volume.py
@@ -20,9 +20,139 @@ from cliff import command
from cliff import show
import six
+from openstackclient.common import parseractions
from openstackclient.common import utils
+class CreateVolume(show.ShowOne):
+ """Create new volume"""
+
+ log = logging.getLogger(__name__ + ".CreateVolume")
+
+ def get_parser(self, prog_name):
+ parser = super(CreateVolume, self).get_parser(prog_name)
+ parser.add_argument(
+ "name",
+ metavar="<name>",
+ help="New volume name"
+ )
+ parser.add_argument(
+ "--size",
+ metavar="<size>",
+ type=int,
+ required=True,
+ help="New volume size in GB"
+ )
+ parser.add_argument(
+ "--snapshot",
+ metavar="<snapshot>",
+ help="Use <snapshot> as source of new volume (name or ID)"
+ )
+ parser.add_argument(
+ "--description",
+ metavar="<description>",
+ help="New volume description"
+ )
+ parser.add_argument(
+ "--type",
+ metavar="<volume-type>",
+ help="Use <volume-type> as the new volume type",
+ )
+ parser.add_argument(
+ '--user',
+ metavar='<user>',
+ help='Specify an alternate user (name or ID)',
+ )
+ parser.add_argument(
+ '--project',
+ metavar='<project>',
+ help='Specify an alternate project (name or ID)',
+ )
+ parser.add_argument(
+ "--availability-zone",
+ metavar="<availability-zone>",
+ help="Create new volume in <availability_zone>"
+ )
+ parser.add_argument(
+ "--image",
+ metavar="<image>",
+ help="Use <image> as source of new volume (name or ID)"
+ )
+ parser.add_argument(
+ "--source",
+ metavar="<volume>",
+ help="Volume to clone (name or ID)"
+ )
+ parser.add_argument(
+ "--property",
+ metavar="<key=value>",
+ action=parseractions.KeyValueAction,
+ help="Set a property to this volume "
+ "(repeat option to set multiple properties)"
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ self.log.debug("take_action: (%s)", parsed_args)
+
+ identity_client = self.app.client_manager.identity
+ volume_client = self.app.client_manager.volume
+ image_client = self.app.client_manager.image
+
+ source_volume = None
+ if parsed_args.source:
+ source_volume = utils.find_resource(
+ volume_client.volumes,
+ parsed_args.source).id
+
+ image = None
+ if parsed_args.image:
+ image = utils.find_resource(
+ image_client.images,
+ parsed_args.image).id
+
+ snapshot = None
+ if parsed_args.snapshot:
+ snapshot = utils.find_resource(
+ volume_client.snapshots,
+ parsed_args.snapshot).id
+
+ project = None
+ if parsed_args.project:
+ project = utils.find_resource(
+ identity_client.projects,
+ parsed_args.project).id
+
+ user = None
+ if parsed_args.user:
+ user = utils.find_resource(
+ identity_client.users,
+ parsed_args.user).id
+
+ volume = volume_client.volumes.create(
+ size=parsed_args.size,
+ snapshot_id=snapshot,
+ name=parsed_args.name,
+ description=parsed_args.description,
+ volume_type=parsed_args.type,
+ user_id=user,
+ project_id=project,
+ availability_zone=parsed_args.availability_zone,
+ metadata=parsed_args.property,
+ imageRef=image,
+ source_volid=source_volume
+ )
+ # Remove key links from being displayed
+ volume._info.update(
+ {
+ 'properties': utils.format_dict(volume._info.pop('metadata')),
+ 'type': volume._info.pop('volume_type')
+ }
+ )
+ volume._info.pop("links", None)
+ return zip(*sorted(six.iteritems(volume._info)))
+
+
class DeleteVolume(command.Command):
"""Delete volume(s)"""
@@ -59,6 +189,77 @@ class DeleteVolume(command.Command):
return
+class SetVolume(show.ShowOne):
+ """Set volume properties"""
+
+ log = logging.getLogger(__name__ + '.SetVolume')
+
+ def get_parser(self, prog_name):
+ parser = super(SetVolume, self).get_parser(prog_name)
+ parser.add_argument(
+ 'volume',
+ metavar='<volume>',
+ help='Volume to change (name or ID)',
+ )
+ parser.add_argument(
+ '--name',
+ metavar='<name>',
+ help='New volume name',
+ )
+ parser.add_argument(
+ '--description',
+ metavar='<description>',
+ help='New volume description',
+ )
+ parser.add_argument(
+ '--size',
+ metavar='<size>',
+ type=int,
+ help='Extend volume size in GB',
+ )
+ parser.add_argument(
+ '--property',
+ metavar='<key=value>',
+ action=parseractions.KeyValueAction,
+ help='Property to add or modify for this volume '
+ '(repeat option to set multiple properties)',
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ self.log.debug('take_action(%s)', parsed_args)
+ volume_client = self.app.client_manager.volume
+ volume = utils.find_resource(volume_client.volumes, parsed_args.volume)
+
+ if parsed_args.size:
+ if volume.status != 'available':
+ self.app.log.error("Volume is in %s state, it must be "
+ "available before size can be extended" %
+ volume.status)
+ return
+ if parsed_args.size <= volume.size:
+ self.app.log.error("New size must be greater than %s GB" %
+ volume.size)
+ return
+ volume_client.volumes.extend(volume.id, parsed_args.size)
+
+ if parsed_args.property:
+ volume_client.volumes.set_metadata(volume.id, parsed_args.property)
+
+ kwargs = {}
+ if parsed_args.name:
+ kwargs['display_name'] = parsed_args.name
+ if parsed_args.description:
+ kwargs['display_description'] = parsed_args.description
+ if kwargs:
+ volume_client.volumes.update(volume.id, **kwargs)
+
+ if not kwargs and not parsed_args.property and not parsed_args.size:
+ self.app.log.error("No changes requested\n")
+
+ return
+
+
class ShowVolume(show.ShowOne):
"""Display volume details"""
@@ -81,3 +282,37 @@ class ShowVolume(show.ShowOne):
# Remove key links from being displayed
volume._info.pop("links", None)
return zip(*sorted(six.iteritems(volume._info)))
+
+
+class UnsetVolume(command.Command):
+ """Unset volume properties"""
+
+ log = logging.getLogger(__name__ + '.UnsetVolume')
+
+ def get_parser(self, prog_name):
+ parser = super(UnsetVolume, self).get_parser(prog_name)
+ parser.add_argument(
+ 'volume',
+ metavar='<volume>',
+ help='Volume to modify (name or ID)',
+ )
+ parser.add_argument(
+ '--property',
+ metavar='<key>',
+ required=True,
+ action='append',
+ default=[],
+ help='Property to remove from volume '
+ '(repeat option to remove multiple properties)',
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ self.log.debug('take_action(%s)', parsed_args)
+ volume_client = self.app.client_manager.volume
+ volume = utils.find_resource(
+ volume_client.volumes, parsed_args.volume)
+
+ volume_client.volumes.delete_metadata(
+ volume.id, parsed_args.property)
+ return