3333
3434from glanceclient .common import utils as gc_utils
3535from openstackclient .api import utils as api_utils
36- from openstackclient .common import exceptions
3736from openstackclient .common import parseractions
3837from openstackclient .common import utils
3938
@@ -244,29 +243,7 @@ def take_action(self, parsed_args):
244243
245244 # Wrap the call to catch exceptions in order to close files
246245 try :
247- try :
248- image = utils .find_resource (
249- image_client .images ,
250- parsed_args .name ,
251- )
252-
253- # Preserve previous properties if any are being set now
254- if image .properties :
255- if parsed_args .properties :
256- image .properties .update (kwargs ['properties' ])
257- kwargs ['properties' ] = image .properties
258-
259- except exceptions .CommandError :
260- if not parsed_args .volume :
261- # This is normal for a create or reserve (create w/o
262- # an image), but skip for create from volume
263- image = image_client .images .create (** kwargs )
264- else :
265- # Update an existing reservation
266-
267- # If an image is specified via --file, --location or
268- # --copy-from let the API handle it
269- image = image_client .images .update (image .id , ** kwargs )
246+ image = image_client .images .create (** kwargs )
270247 finally :
271248 # Clean up open files - make sure data isn't a string
272249 if ('data' in kwargs and hasattr (kwargs ['data' ], 'close' ) and
@@ -561,6 +538,51 @@ def get_parser(self, prog_name):
561538 help = "Set a property on this image "
562539 "(repeat option to set multiple properties)" ,
563540 )
541+ parser .add_argument (
542+ "--store" ,
543+ metavar = "<store>" ,
544+ help = "Upload image to this store" ,
545+ )
546+ parser .add_argument (
547+ "--location" ,
548+ metavar = "<image-url>" ,
549+ help = "Download image from an existing URL" ,
550+ )
551+ parser .add_argument (
552+ "--copy-from" ,
553+ metavar = "<image-url>" ,
554+ help = "Copy image from the data store (similar to --location)" ,
555+ )
556+ parser .add_argument (
557+ "--file" ,
558+ metavar = "<file>" ,
559+ help = "Upload image from local file" ,
560+ )
561+ parser .add_argument (
562+ "--volume" ,
563+ metavar = "<volume>" ,
564+ help = "Create image from a volume" ,
565+ )
566+ parser .add_argument (
567+ "--force" ,
568+ dest = 'force' ,
569+ action = 'store_true' ,
570+ default = False ,
571+ help = "Force image change if volume is in use "
572+ "(only meaningful with --volume)" ,
573+ )
574+ parser .add_argument (
575+ "--stdin" ,
576+ dest = 'stdin' ,
577+ action = 'store_true' ,
578+ default = False ,
579+ help = "Read image data from standard input" ,
580+ )
581+ parser .add_argument (
582+ "--checksum" ,
583+ metavar = "<checksum>" ,
584+ help = "Image hash used for verification" ,
585+ )
564586 return parser
565587
566588 def take_action (self , parsed_args ):
@@ -569,7 +591,8 @@ def take_action(self, parsed_args):
569591
570592 kwargs = {}
571593 copy_attrs = ('name' , 'owner' , 'min_disk' , 'min_ram' , 'properties' ,
572- 'container_format' , 'disk_format' , 'size' )
594+ 'container_format' , 'disk_format' , 'size' , 'store' ,
595+ 'location' , 'copy_from' , 'volume' , 'force' , 'checksum' )
573596 for attr in copy_attrs :
574597 if attr in parsed_args :
575598 val = getattr (parsed_args , attr , None )
@@ -592,20 +615,63 @@ def take_action(self, parsed_args):
592615 if parsed_args .private :
593616 kwargs ['is_public' ] = False
594617
595- if not kwargs :
596- self .log .warning ('no arguments specified' )
597- return {}, {}
598-
599- image = utils .find_resource (
600- image_client .images ,
601- parsed_args .image ,
602- )
603-
604- if image .properties and parsed_args .properties :
605- image .properties .update (kwargs ['properties' ])
606- kwargs ['properties' ] = image .properties
618+ # Wrap the call to catch exceptions in order to close files
619+ try :
620+ image = utils .find_resource (
621+ image_client .images ,
622+ parsed_args .image ,
623+ )
607624
608- image = image_client .images .update (image .id , ** kwargs )
625+ if not parsed_args .location and not parsed_args .copy_from :
626+ if parsed_args .volume :
627+ volume_client = self .app .client_manager .volume
628+ source_volume = utils .find_resource (
629+ volume_client .volumes ,
630+ parsed_args .volume ,
631+ )
632+ response , body = volume_client .volumes .upload_to_image (
633+ source_volume .id ,
634+ parsed_args .force ,
635+ parsed_args .image ,
636+ (parsed_args .container_format
637+ if parsed_args .container_format
638+ else image .container_format ),
639+ (parsed_args .disk_format
640+ if parsed_args .disk_format
641+ else image .disk_format ),
642+ )
643+ info = body ['os-volume_upload_image' ]
644+ elif parsed_args .file :
645+ # Send an open file handle to glanceclient so it will
646+ # do a chunked transfer
647+ kwargs ["data" ] = io .open (parsed_args .file , "rb" )
648+ else :
649+ # Read file from stdin
650+ if sys .stdin .isatty () is not True :
651+ if parsed_args .stdin :
652+ if msvcrt :
653+ msvcrt .setmode (sys .stdin .fileno (), os .O_BINARY )
654+ # Send an open file handle to glanceclient so it
655+ # will do a chunked transfer
656+ kwargs ["data" ] = sys .stdin
657+ else :
658+ self .log .warning ('Use --stdin to enable read image'
659+ ' data from standard input' )
660+
661+ if image .properties and parsed_args .properties :
662+ image .properties .update (kwargs ['properties' ])
663+ kwargs ['properties' ] = image .properties
664+
665+ if not kwargs :
666+ self .log .warning ('no arguments specified' )
667+ return {}, {}
668+
669+ image = image_client .images .update (image .id , ** kwargs )
670+ finally :
671+ # Clean up open files - make sure data isn't a string
672+ if ('data' in kwargs and hasattr (kwargs ['data' ], 'close' ) and
673+ kwargs ['data' ] != sys .stdin ):
674+ kwargs ['data' ].close ()
609675
610676 info = {}
611677 info .update (image ._info )
0 commit comments