Merge "Add support for volume v2 commands"
This commit is contained in:
		| @@ -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 | ||||
|         ) | ||||
|   | ||||
| @@ -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): | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -393,8 +393,11 @@ openstack.volume.v2 = | ||||
|     snapshot_show = openstackclient.volume.v2.snapshot:ShowSnapshot | ||||
|     snapshot_unset = openstackclient.volume.v2.snapshot:UnsetSnapshot | ||||
|  | ||||
|     volume_create = openstackclient.volume.v2.volume:CreateVolume | ||||
|     volume_delete = openstackclient.volume.v2.volume:DeleteVolume | ||||
|     volume_set = openstackclient.volume.v2.volume:SetVolume | ||||
|     volume_show = openstackclient.volume.v2.volume:ShowVolume | ||||
|     volume_unset = openstackclient.volume.v2.volume:UnsetVolume | ||||
|  | ||||
|     volume_type_create = openstackclient.volume.v2.volume_type:CreateVolumeType | ||||
|     volume_type_delete = openstackclient.volume.v2.volume_type:DeleteVolumeType | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Jenkins
					Jenkins