Skip to content

Commit ea9ec1c

Browse files
author
Dean Troyer
committed
Tweak volume commands and add k=v argparse action
Basic cleanups: * change metadata to property * add new KeyValueAction to parse the property options * multiple properties can be set using multiple --property args * consistent formatting * do lookups for volume args Change-Id: Ib6c43f01ad46b395aee8c61e886f42e2a5f5573e
1 parent d49fcb7 commit ea9ec1c

4 files changed

Lines changed: 223 additions & 58 deletions

File tree

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Copyright 2013 OpenStack Foundation
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
#
15+
16+
"""argparse Custom Actions"""
17+
18+
import argparse
19+
20+
21+
class KeyValueAction(argparse.Action):
22+
"""A custom action to parse arguments as key=value pairs.
23+
Ensures that dest is a dict
24+
"""
25+
def __call__(self, parser, namespace, values, option_string=None):
26+
# Make sure we have an empty dict rather than None
27+
if getattr(namespace, self.dest, None) is None:
28+
setattr(namespace, self.dest, {})
29+
30+
# Add value if an assignment else remove it
31+
if '=' in values:
32+
getattr(namespace, self.dest, {}).update([values.split('=', 1)])
33+
else:
34+
getattr(namespace, self.dest, {}).pop(values, None)

openstackclient/volume/v1/type.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from cliff import lister
2222
from cliff import show
2323

24+
from openstackclient.common import parseractions
2425
from openstackclient.common import utils
2526

2627

@@ -118,21 +119,22 @@ def get_parser(self, prog_name):
118119
help='Volume type name or ID to update',
119120
)
120121
parser.add_argument(
121-
'meta_data',
122+
'--property',
122123
metavar='<key=value>',
123-
help='meta-data to add to volume type',
124+
action=parseractions.KeyValueAction,
125+
help='Property to add/change for this volume type '
126+
'(repeat option to set multiple properties)',
124127
)
125128
return parser
126129

127130
def take_action(self, parsed_args):
128131
self.log.debug('take_action(%s)' % parsed_args)
129-
130-
meta = dict(v.split('=') for v in parsed_args.meta_data.split(' '))
131132
volume_client = self.app.client_manager.volume
132133
volume_type = utils.find_resource(
133134
volume_client.volume_types, parsed_args.volume_type)
134135

135-
volume_type.set_keys(meta)
136+
if parsed_args.property:
137+
volume_type.set_keys(parsed_args.property)
136138

137139
return
138140

@@ -148,25 +150,33 @@ def get_parser(self, prog_name):
148150
parser.add_argument(
149151
'volume_type',
150152
metavar='<volume-type>',
151-
help='Type ID or name to update',
153+
help='Type ID or name to remove',
152154
)
153155
parser.add_argument(
154-
'meta_data',
156+
'--property',
155157
metavar='<key>',
156-
help='meta-data to remove from volume type (key only)',
158+
action='append',
159+
default=[],
160+
help='Property key to remove from volume '
161+
'(repeat option to remove multiple properties)',
157162
)
158163
return parser
159164

160165
def take_action(self, parsed_args):
161166
self.log.debug('take_action(%s)' % parsed_args)
162167
volume_client = self.app.client_manager.volume
163168
volume_type = utils.find_resource(
164-
volume_client.volume_types, parsed_args.volume_type)
165-
166-
key_list = []
167-
key_list.append(parsed_args.meta_data)
168-
volume_type.unset_keys(key_list)
169+
volume_client.volume_types,
170+
parsed_args.volume_type,
171+
)
169172

173+
if parsed_args.property:
174+
volume_client.volumes.delete_metadata(
175+
volume_type.id,
176+
parsed_args.property,
177+
)
178+
else:
179+
self.app.log.error("No changes requested\n")
170180
return
171181

172182

openstackclient/volume/v1/volume.py

Lines changed: 62 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@
1616
"""Volume v1 Volume action implementations"""
1717

1818
import logging
19-
import sys
2019

2120
from cliff import command
2221
from cliff import lister
2322
from cliff import show
2423

24+
from openstackclient.common import parseractions
2525
from openstackclient.common import utils
2626

2727

@@ -63,32 +63,34 @@ def get_parser(self, prog_name):
6363
parser.add_argument(
6464
'--user-id',
6565
metavar='<user-id>',
66-
help='User id derived from context',
66+
help='Override user id derived from context (admin only)',
6767
)
6868
parser.add_argument(
6969
'--project-id',
7070
metavar='<project-id>',
71-
help='Project id derived from context',
71+
help='Override project id derived from context (admin only)',
7272
)
7373
parser.add_argument(
7474
'--availability-zone',
7575
metavar='<availability-zone>',
76-
help='Availability Zone to use',
76+
help='Availability zone to use',
7777
)
7878
parser.add_argument(
7979
'--property',
8080
metavar='<key=value>',
81-
help='Optional property to set on volume creation',
81+
action=parseractions.KeyValueAction,
82+
help='Property to store for this volume '
83+
'(repeat option to set multiple properties)',
8284
)
8385
parser.add_argument(
84-
'--image-ref',
85-
metavar='<image-ref>',
86-
help='reference to an image stored in glance',
86+
'--image',
87+
metavar='<image>',
88+
help='Reference to a stored image',
8789
)
8890
parser.add_argument(
89-
'--source-volid',
90-
metavar='<source-volid>',
91-
help='ID of source volume to clone from',
91+
'--source',
92+
metavar='<volume>',
93+
help='Source for volume clone',
9294
)
9395

9496
return parser
@@ -98,22 +100,25 @@ def take_action(self, parsed_args):
98100

99101
volume_client = self.app.client_manager.volume
100102

101-
meta = None
102-
if parsed_args.meta_data:
103-
meta = dict(v.split('=') for v in parsed_args.meta_data.split(' '))
103+
source_volume = None
104+
if parsed_args.source:
105+
source_volume = utils.find_resource(
106+
volume_client.volumes,
107+
parsed_args.source,
108+
).id
104109

105110
volume = volume_client.volumes.create(
106111
parsed_args.size,
107112
parsed_args.snapshot_id,
108-
parsed_args.source_volid,
113+
source_volume,
109114
parsed_args.name,
110115
parsed_args.description,
111116
parsed_args.volume_type,
112117
parsed_args.user_id,
113118
parsed_args.project_id,
114119
parsed_args.availability_zone,
115-
meta,
116-
parsed_args.image_ref
120+
parsed_args.property,
121+
parsed_args.image
117122
)
118123

119124
return zip(*sorted(volume._info.iteritems()))
@@ -175,13 +180,13 @@ def get_parser(self, prog_name):
175180
'--all-tenants',
176181
action='store_true',
177182
default=False,
178-
help='Display information from all tenants (Admin-only)',
183+
help='Display information from all tenants (admin only)',
179184
)
180185
parser.add_argument(
181186
'--long',
182187
action='store_true',
183188
default=False,
184-
help='Display meta-data',
189+
help='Display properties',
185190
)
186191
return parser
187192

@@ -221,41 +226,48 @@ def get_parser(self, prog_name):
221226
parser.add_argument(
222227
'volume',
223228
metavar='<volume>',
224-
help='Name or ID of volume to change')
229+
help='Name or ID of volume to change',
230+
)
225231
parser.add_argument(
226232
'--name',
227-
metavar='<new-volume-name>',
228-
help='New volume name')
233+
metavar='<new-name>',
234+
help='New volume name',
235+
)
229236
parser.add_argument(
230237
'--description',
231-
metavar='<volume-description>',
232-
help='New volume description')
238+
metavar='<new-description>',
239+
help='New volume description',
240+
)
233241
parser.add_argument(
234-
'--meta-data',
242+
'--property',
235243
metavar='<key=value>',
236-
help='meta-data to add to volume')
244+
action=parseractions.KeyValueAction,
245+
help='Property to add/change for this volume '
246+
'(repeat option to set multiple properties)',
247+
)
237248
return parser
238249

239250
def take_action(self, parsed_args):
240251
self.log.debug('take_action(%s)' % parsed_args)
241252
volume_client = self.app.client_manager.volume
242253
volume = utils.find_resource(volume_client.volumes, parsed_args.volume)
243254

244-
meta = None
245255
if parsed_args.property:
246-
meta = dict(v.split('=') for v in parsed_args.property.split(' '))
247-
volume_client.volumes.set_metadata(volume.id, meta)
256+
print "property: %s" % parsed_args.property
257+
volume_client.volumes.set_metadata(volume.id, parsed_args.property)
248258

249259
kwargs = {}
250260
if parsed_args.name:
251261
kwargs['display_name'] = parsed_args.name
252262
if parsed_args.description:
253263
kwargs['display_description'] = parsed_args.description
264+
if kwargs:
265+
print "kwargs: %s" % kwargs
266+
volume_client.volumes.update(volume.id, **kwargs)
267+
268+
if not kwargs and not parsed_args.property:
269+
self.app.log.error("No changes requested\n")
254270

255-
if not kwargs and not meta:
256-
sys.stdout.write("Volume not updated, no arguments present \n")
257-
return
258-
volume_client.volumes.update(volume.id, **kwargs)
259271
return
260272

261273

@@ -270,7 +282,8 @@ def get_parser(self, prog_name):
270282
parser.add_argument(
271283
'volume',
272284
metavar='<volume>',
273-
help='Name or ID of volume to display')
285+
help='Name or ID of volume to display',
286+
)
274287
return parser
275288

276289
def take_action(self, parsed_args):
@@ -292,11 +305,16 @@ def get_parser(self, prog_name):
292305
parser.add_argument(
293306
'volume',
294307
metavar='<volume>',
295-
help='Name or ID of volume to change')
308+
help='Name or ID of volume to change',
309+
)
296310
parser.add_argument(
297-
'--meta-data',
311+
'--property',
298312
metavar='<key>',
299-
help='meta-data to remove from volume (key only)')
313+
action='append',
314+
default=[],
315+
help='Property key to remove from volume '
316+
'(repeat to set multiple values)',
317+
)
300318
return parser
301319

302320
def take_action(self, parsed_args):
@@ -305,14 +323,13 @@ def take_action(self, parsed_args):
305323
volume = utils.find_resource(
306324
volume_client.volumes, parsed_args.volume)
307325

308-
if not parsed_args.meta_data:
309-
sys.stdout.write("Volume not updated, no arguments present \n")
310-
return
311-
312-
key_list = []
313-
key_list.append(parsed_args.meta_data)
314-
volume_client.volumes.delete_metadata(volume.id, key_list)
315-
326+
if parsed_args.property:
327+
volume_client.volumes.delete_metadata(
328+
volume.id,
329+
parsed_args.property,
330+
)
331+
else:
332+
self.app.log.error("No changes requested\n")
316333
return
317334

318335

0 commit comments

Comments
 (0)