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
@@ -560,6 +537,51 @@ def get_parser(self, prog_name):
560537 help = "Set a property on this image "
561538 "(repeat option to set multiple properties)" ,
562539 )
540+ parser .add_argument (
541+ "--store" ,
542+ metavar = "<store>" ,
543+ help = "Upload image to this store" ,
544+ )
545+ parser .add_argument (
546+ "--location" ,
547+ metavar = "<image-url>" ,
548+ help = "Download image from an existing URL" ,
549+ )
550+ parser .add_argument (
551+ "--copy-from" ,
552+ metavar = "<image-url>" ,
553+ help = "Copy image from the data store (similar to --location)" ,
554+ )
555+ parser .add_argument (
556+ "--file" ,
557+ metavar = "<file>" ,
558+ help = "Upload image from local file" ,
559+ )
560+ parser .add_argument (
561+ "--volume" ,
562+ metavar = "<volume>" ,
563+ help = "Create image from a volume" ,
564+ )
565+ parser .add_argument (
566+ "--force" ,
567+ dest = 'force' ,
568+ action = 'store_true' ,
569+ default = False ,
570+ help = "Force image change if volume is in use "
571+ "(only meaningful with --volume)" ,
572+ )
573+ parser .add_argument (
574+ "--stdin" ,
575+ dest = 'stdin' ,
576+ action = 'store_true' ,
577+ default = False ,
578+ help = "Read image data from standard input" ,
579+ )
580+ parser .add_argument (
581+ "--checksum" ,
582+ metavar = "<checksum>" ,
583+ help = "Image hash used for verification" ,
584+ )
563585 return parser
564586
565587 def take_action (self , parsed_args ):
@@ -568,7 +590,8 @@ def take_action(self, parsed_args):
568590
569591 kwargs = {}
570592 copy_attrs = ('name' , 'owner' , 'min_disk' , 'min_ram' , 'properties' ,
571- 'container_format' , 'disk_format' , 'size' )
593+ 'container_format' , 'disk_format' , 'size' , 'store' ,
594+ 'location' , 'copy_from' , 'volume' , 'force' , 'checksum' )
572595 for attr in copy_attrs :
573596 if attr in parsed_args :
574597 val = getattr (parsed_args , attr , None )
@@ -591,20 +614,63 @@ def take_action(self, parsed_args):
591614 if parsed_args .private :
592615 kwargs ['is_public' ] = False
593616
594- if not kwargs :
595- self .log .warning ('no arguments specified' )
596- return {}, {}
597-
598- image = utils .find_resource (
599- image_client .images ,
600- parsed_args .image ,
601- )
602-
603- if image .properties and parsed_args .properties :
604- image .properties .update (kwargs ['properties' ])
605- kwargs ['properties' ] = image .properties
617+ # Wrap the call to catch exceptions in order to close files
618+ try :
619+ image = utils .find_resource (
620+ image_client .images ,
621+ parsed_args .image ,
622+ )
606623
607- image = image_client .images .update (image .id , ** kwargs )
624+ if not parsed_args .location and not parsed_args .copy_from :
625+ if parsed_args .volume :
626+ volume_client = self .app .client_manager .volume
627+ source_volume = utils .find_resource (
628+ volume_client .volumes ,
629+ parsed_args .volume ,
630+ )
631+ response , body = volume_client .volumes .upload_to_image (
632+ source_volume .id ,
633+ parsed_args .force ,
634+ parsed_args .image ,
635+ (parsed_args .container_format
636+ if parsed_args .container_format
637+ else image .container_format ),
638+ (parsed_args .disk_format
639+ if parsed_args .disk_format
640+ else image .disk_format ),
641+ )
642+ info = body ['os-volume_upload_image' ]
643+ elif parsed_args .file :
644+ # Send an open file handle to glanceclient so it will
645+ # do a chunked transfer
646+ kwargs ["data" ] = io .open (parsed_args .file , "rb" )
647+ else :
648+ # Read file from stdin
649+ if sys .stdin .isatty () is not True :
650+ if parsed_args .stdin :
651+ if msvcrt :
652+ msvcrt .setmode (sys .stdin .fileno (), os .O_BINARY )
653+ # Send an open file handle to glanceclient so it
654+ # will do a chunked transfer
655+ kwargs ["data" ] = sys .stdin
656+ else :
657+ self .log .warning ('Use --stdin to enable read image'
658+ ' data from standard input' )
659+
660+ if image .properties and parsed_args .properties :
661+ image .properties .update (kwargs ['properties' ])
662+ kwargs ['properties' ] = image .properties
663+
664+ if not kwargs :
665+ self .log .warning ('no arguments specified' )
666+ return {}, {}
667+
668+ image = image_client .images .update (image .id , ** kwargs )
669+ finally :
670+ # Clean up open files - make sure data isn't a string
671+ if ('data' in kwargs and hasattr (kwargs ['data' ], 'close' ) and
672+ kwargs ['data' ] != sys .stdin ):
673+ kwargs ['data' ].close ()
608674
609675 info = {}
610676 info .update (image ._info )
0 commit comments