def do_image_upload(gc, args): """Upload data for a specific image.""" image_data = utils.get_data_file(args) if args.progress: filesize = utils.get_file_size(image_data) image_data = progressbar.VerboseFileWrapper(image_data, filesize) gc.images.upload(args.id, image_data, args.size)
def create(self, **kwargs): """Create an image TODO(bcwaldon): document accepted params """ image_data = kwargs.pop('data', None) if image_data is not None: image_size = utils.get_file_size(image_data) if image_size is not None: kwargs.setdefault('size', image_size) fields = {} for field in kwargs: if field in CREATE_PARAMS: fields[field] = kwargs[field] else: msg = 'create() got an unexpected keyword argument \'%s\'' raise TypeError(msg % field) copy_from = fields.pop('copy_from', None) hdrs = self._image_meta_to_headers(fields) if copy_from is not None: hdrs['x-glance-api-copy-from'] = copy_from resp, body_iter = self.api.raw_request( 'POST', '/v1/images', headers=hdrs, body=image_data) body = json.loads(''.join([c for c in body_iter])) return Image(self, self._format_image_meta_for_user(body['image']))
def raw_request(self, method, url, **kwargs): kwargs.setdefault('headers', {}) kwargs['headers'].setdefault('Content-Type', 'application/octet-stream') if 'content_length' in kwargs: content_length = kwargs.pop('content_length') else: content_length = None if (('body' in kwargs) and (hasattr(kwargs['body'], 'read') and method.lower() in ('post', 'put'))): # NOTE(dosaboy): only use chunked transfer if not setting a # content length since setting it will implicitly disable # chunking. file_content_length = utils.get_file_size(kwargs['body']) if content_length is None: content_length = file_content_length elif (file_content_length and (content_length != file_content_length)): errmsg = ("supplied content-length (%s) does not match " "length of supplied data (%s)" % (content_length, file_content_length)) raise AttributeError(errmsg) if content_length is None: # We use 'Transfer-Encoding: chunked' because # body size may not always be known in advance. kwargs['headers']['Transfer-Encoding'] = 'chunked' else: kwargs['headers']['Content-Length'] = str(content_length) return self._http_request(url, method, **kwargs)
def do_image_create(gc, args): """Create a new image.""" # Filter out None values fields = dict(filter(lambda x: x[1] is not None, vars(args).items())) fields['is_public'] = fields.get('is_public') or fields.pop('public') if 'is_protected' in fields: fields['protected'] = fields.pop('is_protected') raw_properties = fields.pop('property') fields['properties'] = {} for datum in raw_properties: key, value = datum.split('=', 1) fields['properties'][key] = value # Filter out values we can't use CREATE_PARAMS = glanceclient.v1.images.CREATE_PARAMS fields = dict(filter(lambda x: x[0] in CREATE_PARAMS, fields.items())) _set_data_field(fields, args) if args.progress: filesize = utils.get_file_size(fields['data']) fields['data'] = progressbar.VerboseFileWrapper( fields['data'], filesize ) image = gc.images.create(**fields) _image_show(image, args.human_readable)
def do_image_create(gc, args): """Create a new image.""" # Filter out None values fields = dict(filter(lambda x: x[1] is not None, vars(args).items())) fields['is_public'] = fields.get('is_public') or fields.pop('public') if 'is_protected' in fields: fields['protected'] = fields.pop('is_protected') raw_properties = fields.pop('property') fields['properties'] = {} for datum in raw_properties: key, value = datum.split('=', 1) fields['properties'][key] = value # Filter out values we can't use CREATE_PARAMS = glanceclient.v1.images.CREATE_PARAMS fields = dict(filter(lambda x: x[0] in CREATE_PARAMS, fields.items())) _set_data_field(fields, args) if args.progress: filesize = utils.get_file_size(fields['data']) fields['data'] = progressbar.VerboseFileWrapper( fields['data'], filesize) image = gc.images.create(**fields) _image_show(image, args.human_readable)
def do_image_create(gc, args): """Create a new image.""" # Filter out None values fields = dict(filter(lambda x: x[1] is not None, vars(args).items())) fields['is_public'] = fields.get('is_public') if 'is_protected' in fields: fields['protected'] = fields.pop('is_protected') raw_properties = fields.pop('property') fields['properties'] = {} for datum in raw_properties: key, value = datum.split('=', 1) fields['properties'][key] = value # Filter out values we can't use CREATE_PARAMS = glanceclient.v1.images.CREATE_PARAMS fields = dict(filter(lambda x: x[0] in CREATE_PARAMS, fields.items())) _set_data_field(fields, args) # Only show progress bar for local image files if fields.get('data') and args.progress: filesize = utils.get_file_size(fields['data']) if filesize is not None: # NOTE(kragniz): do not show a progress bar if the size of the # input is unknown (most likely a piped input) fields['data'] = progressbar.VerboseFileWrapper( fields['data'], filesize ) image = gc.images.create(**fields) _image_show(image, args.human_readable)
def test_raw_request_w_content_length(self): with tempfile.NamedTemporaryFile() as test_file: test_file.write(b'abcd') test_file.seek(0) data_length = 4 self.assertEqual(client_utils.get_file_size(test_file), data_length) exp_resp = {'body': test_file} # NOTE: we expect the actual file size to be overridden by the # supplied content length. exp_resp['headers'] = {'Content-Length': '4', 'Content-Type': 'application/octet-stream'} def mock_request(url, method, **kwargs): return kwargs rq_kwargs = {'body': test_file, 'content_length': data_length} with mock.patch.object(self.client, '_http_request') as mock_rq: mock_rq.side_effect = mock_request resp = self.client.raw_request('PUT', '/v1/images/detail', **rq_kwargs) rq_kwargs.pop('content_length') headers = {'Content-Length': str(data_length), 'Content-Type': 'application/octet-stream'} rq_kwargs['headers'] = headers mock_rq.assert_called_once_with('/v1/images/detail', 'PUT', **rq_kwargs) self.assertEqual(exp_resp, resp)
def test_raw_request_no_content_length(self): with tempfile.NamedTemporaryFile() as test_file: test_file.write(b'abcd') test_file.seek(0) data_length = 4 self.assertEqual(data_length, client_utils.get_file_size(test_file)) exp_resp = {'body': test_file} exp_resp['headers'] = { 'Content-Length': str(data_length), 'Content-Type': 'application/octet-stream' } def mock_request(url, method, **kwargs): return kwargs rq_kwargs = {'body': test_file, 'content_length': None} with mock.patch.object(self.client, '_http_request') as mock_rq: mock_rq.side_effect = mock_request resp = self.client.raw_request('PUT', '/v1/images/detail', **rq_kwargs) rq_kwargs.pop('content_length') headers = { 'Content-Length': str(data_length), 'Content-Type': 'application/octet-stream' } rq_kwargs['headers'] = headers mock_rq.assert_called_once_with('/v1/images/detail', 'PUT', **rq_kwargs) self.assertEqual(exp_resp, resp)
def create(self, **kwargs): """Create an image TODO(bcwaldon): document accepted params """ image_data = kwargs.pop("data", None) if image_data is not None: image_size = utils.get_file_size(image_data) if image_size is not None: kwargs.setdefault("size", image_size) fields = {} for field in kwargs: if field in CREATE_PARAMS: fields[field] = kwargs[field] elif field == "return_req_id": continue else: msg = "create() got an unexpected keyword argument '%s'" raise TypeError(msg % field) copy_from = fields.pop("copy_from", None) hdrs = self._image_meta_to_headers(fields) if copy_from is not None: hdrs["x-glance-api-copy-from"] = copy_from resp, body = self.client.post("/v1/images", headers=hdrs, data=image_data) return_request_id = kwargs.get("return_req_id", None) if return_request_id is not None: return_request_id.append(resp.headers.get(OS_REQ_ID_HDR, None)) return Image(self, self._format_image_meta_for_user(body["image"]))
def do_image_create(gc, args): """Create a new image.""" # Filter out None values fields = dict(filter(lambda x: x[1] is not None, vars(args).items())) fields['is_public'] = fields.get('is_public') if 'is_protected' in fields: fields['protected'] = fields.pop('is_protected') raw_properties = fields.pop('property') fields['properties'] = {} for datum in raw_properties: key, value = datum.split('=', 1) fields['properties'][key] = value # Filter out values we can't use CREATE_PARAMS = glanceclient.v1.images.CREATE_PARAMS fields = dict(filter(lambda x: x[0] in CREATE_PARAMS, fields.items())) _set_data_field(fields, args) # Only show progress bar for local image files if fields.get('data') and args.progress: filesize = utils.get_file_size(fields['data']) if filesize is not None: # NOTE(kragniz): do not show a progress bar if the size of the # input is unknown (most likely a piped input) fields['data'] = progressbar.VerboseFileWrapper( fields['data'], filesize) image = gc.images.create(**fields) _image_show(image, args.human_readable)
def do_image_create(gc, args): """Create a new image.""" # Filter out None values fields = dict(filter(lambda x: x[1] is not None, vars(args).items())) fields["is_public"] = fields.get("is_public") if "is_protected" in fields: fields["protected"] = fields.pop("is_protected") raw_properties = fields.pop("property") fields["properties"] = {} for datum in raw_properties: key, value = datum.split("=", 1) fields["properties"][key] = value # Filter out values we can't use CREATE_PARAMS = glanceclient.v1.images.CREATE_PARAMS fields = dict(filter(lambda x: x[0] in CREATE_PARAMS, fields.items())) _set_data_field(fields, args) # Only show progress bar for local image files if fields.get("data") and args.progress: filesize = utils.get_file_size(fields["data"]) fields["data"] = progressbar.VerboseFileWrapper(fields["data"], filesize) image = gc.images.create(**fields) _image_show(image, args.human_readable)
def do_image_update(gc, args): """Update a specific image.""" # Filter out None values fields = dict(filter(lambda x: x[1] is not None, vars(args).items())) image_arg = fields.pop('image') image = utils.find_resource(gc.images, image_arg) if 'is_protected' in fields: fields['protected'] = fields.pop('is_protected') raw_properties = fields.pop('property') fields['properties'] = {} for datum in raw_properties: key, value = datum.split('=', 1) fields['properties'][key] = value # Filter out values we can't use UPDATE_PARAMS = glanceclient.v1.images.UPDATE_PARAMS fields = dict(filter(lambda x: x[0] in UPDATE_PARAMS, fields.items())) if image.status == 'queued': _set_data_field(fields, args) if args.progress: filesize = utils.get_file_size(fields['data']) fields['data'] = progressbar.VerboseFileWrapper( fields['data'], filesize) image = gc.images.update(image, purge_props=args.purge_props, **fields) _image_show(image, args.human_readable)
def upload_local_image(self, image_name, image_path, container_format='ovf', disk_format='raw', is_public=True, private_user_list=[], **extras): """ Upload a single file as a glance image 'extras' kwargs will be passed directly to glance. """ logger.info("Creating new image %s - %s" % (image_name, container_format)) new_image = self.glance.images.create( name=image_name, container_format=container_format, disk_format=disk_format, visibility="public" if is_public else "private", **extras) logger.info("Uploading file to newly created image %s - %s" % (new_image.id, image_path)) if hasattr(self,'hook') and hasattr(self.hook, 'on_update_status'): self.hook.on_update_status("Uploading file to image %s" % new_image.id) if not os.path.exists(image_path): raise Exception("Image Upload failed! Image path (%s) does not exist." % (image_path)) data_file = open(image_path, 'rb') filesize = utils.get_file_size(data_file) body = ProgressHook(data_file, filesize, getattr(self, 'hook', None), 'upload') self.glance.images.upload(new_image.id, data_file) # ASSERT: New image ID now that 'the_file' has completed the upload logger.info("New image created: %s - %s" % (image_name, new_image.id)) for tenant_name in private_user_list: self.share_image(new_image,tenant_name) logger.info("%s has permission to launch %s" % (tenant_name, new_image)) return new_image.id
def raw_request(self, method, url, **kwargs): kwargs.setdefault("headers", {}) kwargs["headers"].setdefault("Content-Type", "application/octet-stream") if "content_length" in kwargs: content_length = kwargs.pop("content_length") else: content_length = None if ("body" in kwargs) and (hasattr(kwargs["body"], "read") and method.lower() in ("post", "put")): # NOTE(dosaboy): only use chunked transfer if not setting a # content length since setting it will implicitly disable # chunking. file_content_length = utils.get_file_size(kwargs["body"]) if content_length is None: content_length = file_content_length elif file_content_length and (content_length != file_content_length): errmsg = "supplied content-length (%s) does not match " "length of supplied data (%s)" % ( content_length, file_content_length, ) raise AttributeError(errmsg) if content_length is None: # We use 'Transfer-Encoding: chunked' because # body size may not always be known in advance. kwargs["headers"]["Transfer-Encoding"] = "chunked" else: kwargs["headers"]["Content-Length"] = str(content_length) return self._http_request(url, method, **kwargs)
def create(self, **kwargs): """Create an image. TODO(bcwaldon): document accepted params """ image_data = kwargs.pop('data', None) if image_data is not None: image_size = utils.get_file_size(image_data) if image_size is not None: kwargs.setdefault('size', image_size) fields = {} for field in kwargs: if field in CREATE_PARAMS: fields[field] = kwargs[field] elif field == 'return_req_id': continue else: msg = 'create() got an unexpected keyword argument \'%s\'' raise TypeError(msg % field) copy_from = fields.pop('copy_from', None) hdrs = self._image_meta_to_headers(fields) if copy_from is not None: hdrs['x-glance-api-copy-from'] = copy_from resp, body = self.client.post('/v1/images', headers=hdrs, data=image_data) return_request_id = kwargs.get('return_req_id', None) if return_request_id is not None: return_request_id.append(resp.headers.get(OS_REQ_ID_HDR, None)) return Image(self, self._format_image_meta_for_user(body['image']))
def do_image_update(gc, args): """Update a specific image.""" # Filter out None values fields = dict(filter(lambda x: x[1] is not None, vars(args).items())) image_arg = fields.pop("image") image = utils.find_resource(gc.images, image_arg) if "is_protected" in fields: fields["protected"] = fields.pop("is_protected") raw_properties = fields.pop("property") fields["properties"] = {} for datum in raw_properties: key, value = datum.split("=", 1) fields["properties"][key] = value # Filter out values we can't use UPDATE_PARAMS = glanceclient.v1.images.UPDATE_PARAMS fields = dict(filter(lambda x: x[0] in UPDATE_PARAMS, fields.items())) if image.status == "queued": _set_data_field(fields, args) if args.progress: filesize = utils.get_file_size(fields["data"]) fields["data"] = progressbar.VerboseFileWrapper(fields["data"], filesize) image = gc.images.update(image, purge_props=args.purge_props, **fields) _image_show(image, args.human_readable)
def test_get_new_file_size(self): size = 98304 file_obj = StringIO.StringIO("X" * size) try: self.assertEqual(utils.get_file_size(file_obj), size) # Check that get_file_size didn't change original file position. self.assertEqual(file_obj.tell(), 0) finally: file_obj.close()
def test_get_new_file_size(self): size = 98304 file_obj = six.StringIO('X' * size) try: self.assertEqual(size, utils.get_file_size(file_obj)) # Check that get_file_size didn't change original file position. self.assertEqual(0, file_obj.tell()) finally: file_obj.close()
def do_image_upload(gc, args): """Upload data for a specific image.""" image_data = utils.get_data_file(args) if args.progress: filesize = utils.get_file_size(image_data) if filesize is not None: # NOTE(kragniz): do not show a progress bar if the size of the # input is unknown (most likely a piped input) image_data = progressbar.VerboseFileWrapper(image_data, filesize) gc.images.upload(args.id, image_data, args.size)
def test_get_consumed_file_size(self): size, consumed = 98304, 304 file_obj = six.StringIO("X" * size) file_obj.seek(consumed) try: self.assertEqual(size, utils.get_file_size(file_obj)) # Check that get_file_size didn't change original file position. self.assertEqual(consumed, file_obj.tell()) finally: file_obj.close()
def test_get_consumed_file_size(self): size, consumed = 98304, 304 file_obj = StringIO.StringIO('X' * size) file_obj.seek(consumed) try: self.assertEqual(utils.get_file_size(file_obj), size) # Check that get_file_size didn't change original file position. self.assertEqual(file_obj.tell(), consumed) finally: file_obj.close()
def test_raw_request_w_bad_content_length(self): with tempfile.NamedTemporaryFile() as test_file: test_file.write(b'abcd') test_file.seek(0) self.assertEqual(client_utils.get_file_size(test_file), 4) def mock_request(url, method, **kwargs): return kwargs with mock.patch.object(self.client, '_http_request', mock_request): self.assertRaises(AttributeError, self.client.raw_request, 'PUT', '/v1/images/detail', body=test_file, content_length=32)
def test_raw_request_w_bad_content_length(self): with tempfile.NamedTemporaryFile() as test_file: test_file.write(b'abcd') test_file.seek(0) self.assertEqual(4, client_utils.get_file_size(test_file)) def mock_request(url, method, **kwargs): return kwargs with mock.patch.object(self.client, '_http_request', mock_request): self.assertRaises(AttributeError, self.client.raw_request, 'PUT', '/v1/images/detail', body=test_file, content_length=32)
def update(self, image, **kwargs): """Update an image TODO(bcwaldon): document accepted params """ image_data = kwargs.pop('data', None) if image_data is not None: image_size = utils.get_file_size(image_data) if image_size is not None: kwargs.setdefault('size', image_size) hdrs = {} try: purge_props = 'true' if kwargs.pop('purge_props') else 'false' except KeyError: pass else: hdrs['x-glance-registry-purge-props'] = purge_props fields = {} for field in kwargs: if field in UPDATE_PARAMS: fields[field] = kwargs[field] elif field == 'return_req_id': continue else: msg = 'update() got an unexpected keyword argument \'%s\'' raise TypeError(msg % field) copy_from = fields.pop('copy_from', None) hdrs.update(self._image_meta_to_headers(fields)) if copy_from is not None: hdrs['x-glance-api-copy-from'] = copy_from url = '/v1/images/%s' % base.getid(image) resp, body_iter = self.api.raw_request( 'PUT', url, headers=hdrs, body=image_data) body = json.loads(''.join([c for c in body_iter])) return_request_id = kwargs.get('return_req_id', None) if return_request_id is not None: return_request_id.append(resp.getheader(OS_REQ_ID_HDR, None)) return Image(self, self._format_image_meta_for_user(body['image']))
def upload_local_image(self, image_name, image_path, container_format='ovf', disk_format='raw', is_public=True, private_user_list=[], **extras): """ Upload a single file as a glance image 'extras' kwargs will be passed directly to glance. """ logger.info("Creating new image %s - %s" % (image_name, container_format)) new_image = self.glance.images.create( name=image_name, container_format=container_format, disk_format=disk_format, visibility="public" if is_public else "private", **extras) logger.info("Uploading file to newly created image %s - %s" % (new_image.id, image_path)) if hasattr(self, 'hook') and hasattr(self.hook, 'on_update_status'): self.hook.on_update_status("Uploading file to image %s" % new_image.id) if not os.path.exists(image_path): raise Exception( "Image Upload failed! Image path (%s) does not exist." % (image_path)) data_file = open(image_path, 'rb') filesize = utils.get_file_size(data_file) body = ProgressHook(data_file, filesize, getattr(self, 'hook', None), 'upload') self.glance.images.upload(new_image.id, data_file) # ASSERT: New image ID now that 'the_file' has completed the upload logger.info("New image created: %s - %s" % (image_name, new_image.id)) for tenant_name in private_user_list: self.share_image(new_image, tenant_name) logger.info("%s has permission to launch %s" % (tenant_name, new_image)) return new_image.id
def update(self, image, **kwargs): """Update an image TODO(bcwaldon): document accepted params """ image_data = kwargs.pop("data", None) if image_data is not None: image_size = utils.get_file_size(image_data) if image_size is not None: kwargs.setdefault("size", image_size) hdrs = {} purge_props = "false" purge_props_bool = kwargs.pop("purge_props", None) if purge_props_bool: purge_props = "true" hdrs["x-glance-registry-purge-props"] = purge_props fields = {} for field in kwargs: if field in UPDATE_PARAMS: fields[field] = kwargs[field] elif field == "return_req_id": continue else: msg = "update() got an unexpected keyword argument '%s'" raise TypeError(msg % field) copy_from = fields.pop("copy_from", None) hdrs.update(self._image_meta_to_headers(fields)) if copy_from is not None: hdrs["x-glance-api-copy-from"] = copy_from url = "/v1/images/%s" % base.getid(image) resp, body = self.client.put(url, headers=hdrs, data=image_data) return_request_id = kwargs.get("return_req_id", None) if return_request_id is not None: return_request_id.append(resp.headers.get(OS_REQ_ID_HDR, None)) return Image(self, self._format_image_meta_for_user(body["image"]))
def do_image_update(gc, args): """Update a specific image.""" # Filter out None values fields = dict(filter(lambda x: x[1] is not None, vars(args).items())) image_arg = fields.pop('image') image = utils.find_resource(gc.images, image_arg) if 'is_protected' in fields: fields['protected'] = fields.pop('is_protected') raw_properties = fields.pop('property') fields['properties'] = {} for datum in raw_properties: key, value = datum.split('=', 1) fields['properties'][key] = value # Filter out values we can't use UPDATE_PARAMS = glanceclient.v1.images.UPDATE_PARAMS fields = dict(filter(lambda x: x[0] in UPDATE_PARAMS, fields.items())) if image.status == 'queued': _set_data_field(fields, args) if args.progress: filesize = utils.get_file_size(fields['data']) fields['data'] = progressbar.VerboseFileWrapper( fields['data'], filesize ) elif _is_image_data_provided(args): # NOTE(kragniz): Exit with an error if the status is not queued # and image data was provided utils.exit('Unable to upload image data to an image which ' 'is %s.' % image.status) image = gc.images.update(image, purge_props=args.purge_props, **fields) _image_show(image, args.human_readable)
def do_image_create(gc, args): """Create a new image.""" schema = gc.schemas.get("image") _args = [(x[0].replace('-', '_'), x[1]) for x in vars(args).items()] fields = dict( filter( lambda x: x[1] is not None and (x[0] == 'property' or x[0] == 'cache_raw' or x[0] == 'wait' or schema.is_core_property(x[0])), _args)) raw_properties = fields.pop('property', []) cache_raw = fields.pop('cache_raw', False) cache_raw_wait = fields.pop('wait', None) if cache_raw is not False: raw_properties += ['cache_raw=True'] for datum in raw_properties: key, value = datum.split('=', 1) fields[key] = value file_name = fields.pop('file', None) if file_name is not None and os.access(file_name, os.R_OK) is False: utils.exit("File %s does not exist or user does not have read " "privileges to it" % file_name) image = gc.images.create(**fields) try: image_data = utils.get_data_file(args) if image_data is not None: args.id = image['id'] args.size = utils.get_file_size(image_data) do_image_upload(gc, args) # If cache_raw and wait options were chosen, wait until # image is cached. if cache_raw is not False and cache_raw_wait is not None: utils.wait_for_caching(cache_raw_wait, gc, args.id) image = gc.images.get(args.id) finally: utils.print_image(image)
def do_image_create(gc, args): """Create a new image.""" # Filter out None values fields = dict(filter(lambda x: x[1] is not None, vars(args).items())) file_name=None status = True file_attr = fields.get('file') location_attr = fields.get('location') copy_from_attr = fields.get('copy_from') if file_attr: file_name=file_attr elif location_attr: file_name=location_attr elif copy_from_attr: file_name=copy_from_attr elif (sys.stdin.isatty()== False ): file_name = os.readlink('/proc/self/fd/0') if (file_name != None): status = _image_ext_validation(file_name) if(status == False): print("You must provide valid image type (.png, .jpeg, .bmp are not valid)") return False fields['is_public'] = fields.get('is_public') if 'is_protected' in fields: fields['protected'] = fields.pop('is_protected') raw_properties = fields.pop('property') fields['properties'] = {} for datum in raw_properties: key, value = datum.split('=', 1) fields['properties'][key] = value # Filter out values we can't use CREATE_PARAMS = glanceclient.v1.images.CREATE_PARAMS fields = dict(filter(lambda x: x[0] in CREATE_PARAMS, fields.items())) _set_data_field(fields, args) # Only show progress bar for local image files if fields.get('data') and args.progress: filesize = utils.get_file_size(fields['data']) if filesize is not None: # NOTE(kragniz): do not show a progress bar if the size of the # input is unknown (most likely a piped input) fields['data'] = progressbar.VerboseFileWrapper( fields['data'], filesize ) image = gc.images.create(**fields) _image_show(image, args.human_readable)