@@ -116,7 +116,6 @@ class CreateImage(show.ShowOne):
116116
117117 def get_parser (self , prog_name ):
118118 parser = super (CreateImage , self ).get_parser (prog_name )
119- # TODO(mordred): add --volume and --force parameters and support
120119 # TODO(bunting): There are additional arguments that v1 supported
121120 # that v2 either doesn't support or supports weirdly.
122121 # --checksum - could be faked clientside perhaps?
@@ -170,6 +169,19 @@ def get_parser(self, prog_name):
170169 metavar = "<file>" ,
171170 help = "Upload image from local file" ,
172171 )
172+ parser .add_argument (
173+ "--volume" ,
174+ metavar = "<volume>" ,
175+ help = "Create image from a volume" ,
176+ )
177+ parser .add_argument (
178+ "--force" ,
179+ dest = 'force' ,
180+ action = 'store_true' ,
181+ default = False ,
182+ help = "Force image creation if volume is in use "
183+ "(only meaningful with --volume)" ,
184+ )
173185 protected_group = parser .add_mutually_exclusive_group ()
174186 protected_group .add_argument (
175187 "--protected" ,
@@ -245,6 +257,7 @@ def take_action(self, parsed_args):
245257 if getattr (parsed_args , 'properties' , None ):
246258 for k , v in six .iteritems (parsed_args .properties ):
247259 kwargs [k ] = str (v )
260+
248261 # Handle exclusive booleans with care
249262 # Avoid including attributes in kwargs if an option is not
250263 # present on the command line. These exclusive booleans are not
@@ -263,12 +276,33 @@ def take_action(self, parsed_args):
263276 # open the file first to ensure any failures are handled before the
264277 # image is created
265278 fp = gc_utils .get_data_file (parsed_args )
279+ info = {}
280+ if fp is not None and parsed_args .volume :
281+ raise exceptions .CommandError ("Uploading data and using container "
282+ "are not allowed at the same time" )
266283
267284 if fp is None and parsed_args .file :
268285 self .log .warning ("Failed to get an image file." )
269286 return {}, {}
270287
271- image = image_client .images .create (** kwargs )
288+ # If a volume is specified.
289+ if parsed_args .volume :
290+ volume_client = self .app .client_manager .volume
291+ source_volume = utils .find_resource (
292+ volume_client .volumes ,
293+ parsed_args .volume ,
294+ )
295+ response , body = volume_client .volumes .upload_to_image (
296+ source_volume .id ,
297+ parsed_args .force ,
298+ parsed_args .name ,
299+ parsed_args .container_format ,
300+ parsed_args .disk_format ,
301+ )
302+ info = body ['os-volume_upload_image' ]
303+ info ['volume_type' ] = info ['volume_type' ]['name' ]
304+ else :
305+ image = image_client .images .create (** kwargs )
272306
273307 if fp is not None :
274308 with fp :
@@ -289,7 +323,9 @@ def take_action(self, parsed_args):
289323 # update the image after the data has been uploaded
290324 image = image_client .images .get (image .id )
291325
292- info = _format_image (image )
326+ if not info :
327+ info = _format_image (image )
328+
293329 return zip (* sorted (six .iteritems (info )))
294330
295331
@@ -539,8 +575,8 @@ def get_parser(self, prog_name):
539575 # --location - maybe location add?
540576 # --copy-from - does not exist in v2
541577 # --file - should be able to upload file
542- # --volume - needs adding
543- # --force - needs adding
578+ # --volume - not possible with v2 as can't change id
579+ # --force - see `--volume`
544580 # --checksum - maybe could be done client side
545581 # --stdin - could be implemented
546582 parser .add_argument (
0 commit comments