def replace_customers(image_uuid, customers, transaction_id): DataManager = di.resolver.unpack(replace_customers) datamanager = DataManager() try: image_rec = datamanager.get_record('image') sql_image = image_rec.get_image_by_id(image_uuid) if not sql_image: raise ErrorStatus(404, 'image {0} not found'.format(image_uuid)) if sql_image.visibility == "public": raise ValueError('Cannot add Customers to public Image') existing_region_names = sql_image.get_existing_region_names() sql_image.remove_all_customers() datamanager.flush() for cust in customers.customers: db_Customer = ImageCustomer(customer_id=cust) sql_image.add_customer(db_Customer) datamanager.flush() # get exception created by previous db actions send_to_rds_if_needed(sql_image, existing_region_names, "put", transaction_id) datamanager.commit() ret_image = get_image_by_uuid(image_uuid) return ret_image except Exception as exp: if 'conflicts with persistent instance' in exp.message or 'Duplicate entry' in exp.message: raise ErrorStatus(409, "Duplicate Customer for Image") LOG.log_exception("ImageLogic - Failed to add Customers", exp) datamanager.rollback() raise
def delete_image_by_uuid(image_uuid, transaction_id): rds_proxy, DataManager = di.resolver.unpack(delete_image_by_uuid) datamanager = DataManager() try: datamanager.begin_transaction() image_rec = datamanager.get_record('image') sql_image = image_rec.get_image_by_id(image_uuid) if sql_image is None: return image_existing_region_names = sql_image.get_existing_region_names() if len(image_existing_region_names) > 0: # Do not delete a flavor that still has some regions raise ErrorStatus(405, "Cannot delete a image with regions. " "Please delete the regions first and then " "delete the image. ") # Get status from RDS image_status = rds_proxy.get_status(sql_image.id, False) status_resp = None if image_status.status_code == 200: status_resp = image_status.json()['status'] LOG.debug('RDS returned status: {}'.format(status_resp)) elif image_status.status_code == 404: status_resp = 'Success' else: # fail to get status from rds raise ErrorStatus(500, "fail to get status for this resource " "deleting image not allowed ") if status_resp != 'Success': raise ErrorStatus(405, "not allowed as aggregate status " "have to be Success (either the deletion" " failed on one of the regions or it is " "still in progress)") image_rec.delete_image_by_id(image_uuid) datamanager.flush() # i want to get any exception created by this # delete datamanager.commit() except Exception as exp: LOG.log_exception("ImageLogic - Failed to delete image", exp) datamanager.rollback() raise
def delete_region(image_uuid, region_name, transaction_id): DataManager = di.resolver.unpack(delete_region) datamanager = DataManager() try: image_rec = datamanager.get_record('image') sql_image = image_rec.get_image_by_id(image_uuid) if not sql_image: raise ErrorStatus(404, 'image with id: {0} not found'.format( image_uuid)) existing_region_names = sql_image.get_existing_region_names() sql_image.remove_region(region_name) datamanager.flush() # i want to get any exception created by # previous actions against the database send_to_rds_if_needed(sql_image, existing_region_names, "put", transaction_id) datamanager.commit() except ErrorStatus as exp: LOG.log_exception("ImageLogic - Failed to update image", exp) datamanager.rollback() raise except Exception as exp: LOG.log_exception("ImageLogic - Failed to delete region", exp) datamanager.rollback() raise
def delete_customer(image_uuid, customer_id, transaction_id): DataManager = di.resolver.unpack(delete_customer) datamanager = DataManager() try: image_rec = datamanager.get_record('image') sql_image = image_rec.get_image_by_id(image_uuid) if not sql_image: raise ErrorStatus(404, 'image {0} not found'.format(image_uuid)) # if trying to delete the only one Customer then return value error if sql_image.visibility == "public": raise ValueError("Image {} is public, no customers".format(image_uuid)) if len(sql_image.customers) == 1 and \ sql_image.customers[0].customer_id == customer_id: raise ValueError('Private Image must have at least one Customer - ' 'You are trying to delete the only one Customer') existing_region_names = sql_image.get_existing_region_names() sql_image.remove_customer(customer_id) datamanager.flush() # i want to get any exception created by # previous actions against the database send_to_rds_if_needed(sql_image, existing_region_names, "put", transaction_id) datamanager.commit() except Exception as exp: LOG.log_exception("ImageLogic - Failed to delete Customer", exp) datamanager.rollback() raise
def enable_image(image_uuid, int_enabled, transaction_id): DataManager = di.resolver.unpack(enable_image) datamanager = DataManager() try: image_rec = datamanager.get_record('image') sql_image = image_rec.get_image(image_uuid) if not sql_image: raise ErrorStatus(404, 'Image with id: {0} not found'.format( image_uuid)) sql_image.enabled = int_enabled existing_region_names = sql_image.get_existing_region_names() datamanager.flush() # i want to get any exception created by this # insert method send_to_rds_if_needed(sql_image, existing_region_names, "put", transaction_id) datamanager.commit() ret_image = get_image_by_uuid(image_uuid) return ret_image except ErrorStatus as exp: LOG.log_exception("ImageLogic - Failed to change image activation value", exp) datamanager.rollback() raise exp except Exception as exp: LOG.log_exception("ImageLogic - Failed to change image activation value", exp) datamanager.rollback() raise exp
def get_logic_mock(): global image_logic_mock image_logic_mock = mock.MagicMock() if return_error == 0: image_logic_mock.enable_image.return_value = ImageWrapper() elif return_error == 1: image_logic_mock.enable_image.side_effect = SystemError() elif return_error == 2: image_logic_mock.enable_image.side_effect = ErrorStatus( status_code=404) elif return_error == 3: image_logic_mock.enable_image.side_effect = ErrorStatus( status_code=409) return image_logic_mock
def get_logic_mock(): global image_logic_mock image_logic_mock = mock.MagicMock() if return_error == 0: image_logic_mock.update_image.return_value = ImageWrapper() image_logic_mock.create_image.return_value = ImageWrapper() image_logic_mock.get_image_by_uuid.return_value = ImageWrapper() image_logic_mock.get_image_list_by_params.return_value = ImageSummaryResponse( ) elif return_error == 1: image_logic_mock.update_image.side_effect = SystemError() image_logic_mock.create_image.side_effect = SystemError() image_logic_mock.get_image_by_uuid.side_effect = SystemError() image_logic_mock.get_image_list_by_params.side_effect = SystemError() image_logic_mock.delete_image_by_uuid.side_effect = SystemError() elif return_error == 2: image_logic_mock.update_image.side_effect = ErrorStatus( status_code=404) image_logic_mock.create_image.side_effect = ErrorStatus( status_code=404) image_logic_mock.get_image_by_uuid.side_effect = ErrorStatus( status_code=404) image_logic_mock.get_image_list_by_params.side_effect = ErrorStatus( status_code=404) image_logic_mock.delete_image_by_uuid.side_effect = ErrorStatus( status_code=404) elif return_error == 3: image_logic_mock.create_image.side_effect = ErrorStatus( status_code=409) image_logic_mock.update_image.side_effect = ErrorStatus( status_code=409) return image_logic_mock
def get_logic_mock(): global image_logic_mock image_logic_mock = mock.MagicMock() if return_error == 0: image_logic_mock.add_regions.return_value = RegionWrapper() image_logic_mock.replace_regions.return_value = RegionWrapper() elif return_error == 1: image_logic_mock.add_regions.side_effect = SystemError() image_logic_mock.replace_regions.side_effect = SystemError() image_logic_mock.delete_region.side_effect = SystemError() elif return_error == 2: image_logic_mock.add_regions.side_effect = ErrorStatus(status_code=404) image_logic_mock.replace_regions.side_effect = ErrorStatus( status_code=404) image_logic_mock.delete_region.side_effect = ErrorStatus( status_code=404) return image_logic_mock
def handle_region_group(self): regions_to_add = [] for region in self.regions[:]: # get copy of it to be able to delete from the origin if region.type == "group": group_regions = self.get_regions_for_group(region.name) if group_regions is None: raise ErrorStatus( 404, "Group {} does not exist".format(region.name)) for group_region in group_regions: regions_to_add.append( Region(name=group_region, type='single')) self.regions.remove(region) self.regions.extend(set(regions_to_add)) # remove duplicates if exist
def add_region(self, image_region): assert isinstance(image_region, ImageRegion) try: LOG.debug("add region {0} to image {1}".format( str(image_region), str(self))) region_list = filter( lambda region: region.region_name == image_region.region_name, self.regions) if len(region_list) > 0: raise ErrorStatus( 409, "Region {} already exist in Image {}".format( image_region.region_name, self.name)) self.regions.append(image_region) except Exception as exception: LOG.log_exception( "Failed to add region {0} to image {1}".format( str(image_region), str(self)), exception) raise
def post(self, image_id, enabled): image_logic, utils = di.resolver.unpack(EnabledController) auth.authorize(request, "image:enable") try: LOG.debug("method not allowed only put allowed") raise ErrorStatus(405, "method not allowed only 'put' method allowed") return None except ErrorStatus as exception: LOG.log_exception("Failed in EnableImage", exception) raise err_utils.get_error(request.transaction_id, message=exception.message, status_code=exception.status_code) except Exception as exception: LOG.log_exception("Failed in EnableImage", exception) raise err_utils.get_error(request.transaction_id, status_code=500, error_details=str(exception))
def put(self, image_id, image_wrapper): image_logic, utils = di.resolver.unpack(ImageController) auth.authorize(request, "image:update") try: LOG.info("ImageController - UpdateImage: " + str(image_wrapper.image.name)) try: result = image_logic.update_image(image_wrapper, image_id, request.transaction_id) except oslo_db.exception.DBDuplicateEntry as exception: raise ErrorStatus( 409.2, 'The field {0} already exists'.format(exception.columns)) LOG.info("ImageController - UpdateImage finished well: " + str(image_wrapper.image.name)) event_details = 'Image {} {} {}, visibility: {}, created in regions: {} with tenants: {}'.format( image_id, image_wrapper.image.name, image_wrapper.image.url, image_wrapper.image.visibility, [r.name for r in image_wrapper.image.regions], image_wrapper.image.customers) utils.audit_trail('update image', request.transaction_id, request.headers, image_id, event_details=event_details) return result except ErrorStatus as exception: LOG.log_exception("Failed in UpdateImage", exception) raise err_utils.get_error(request.transaction_id, message=exception.message, status_code=exception.status_code) except Exception as exception: LOG.log_exception("ImageController - Failed to UpdateImage", exception) raise err_utils.get_error(request.transaction_id, status_code=500, error_details=str(exception))
def replace_regions(image_uuid, regions, transaction_id): DataManager = di.resolver.unpack(replace_regions) datamanager = DataManager() try: image_rec = datamanager.get_record('image') sql_image = image_rec.get_image_by_id(image_uuid) if not sql_image: raise ErrorStatus(404, 'image with id: {0} not found'.format( image_uuid)) existing_region_names = sql_image.get_existing_region_names() sql_image.remove_all_regions() datamanager.flush() for region in regions.regions: db_region = ImageRegion(region_name=region.name, region_type=region.type) sql_image.add_region(db_region) datamanager.flush() # i want to get any exception created by # previous actions against the database send_to_rds_if_needed(sql_image, existing_region_names, "put", transaction_id) datamanager.commit() image_wrapper = get_image_by_uuid(image_uuid) ret = RegionWrapper(regions=image_wrapper.image.regions) return ret except ErrorStatus as exp: LOG.log_exception("ImageLogic - Failed to replace regions", exp) datamanager.rollback() raise exp except Exception as exp: LOG.log_exception("ImageLogic - Failed to repalce regions", exp) datamanager.rollback() raise exp
def add_metadata(image_id, region_name, metadata_wrapper): DataManager = di.resolver.unpack(add_metadata) datamanager = DataManager() try: image_rec = datamanager.get_record('image') sql_image = image_rec.get_image_by_id(image_id) if not sql_image: raise ErrorStatus(404, 'image {0} not found'.format(image_id)) for region in sql_image.regions: if region.region_name == region_name: region.checksum = metadata_wrapper.metadata.checksum region.size = metadata_wrapper.metadata.size region.virtual_size = metadata_wrapper.metadata.virtual_size datamanager.flush() datamanager.commit() except Exception as exp: LOG.log_exception("ImageLogic - Failed to add regions", exp) datamanager.rollback() raise
def put(self, image_id, region_wrapper): # add regions to image image_logic, utils = di.resolver.unpack(RegionController) auth.authorize(request, "region:update") try: if not region_wrapper.regions: raise ErrorStatus(400, " bad resquest please provide correct json") LOG.info("RegionController - replace regions: " + str(region_wrapper)) result = image_logic.replace_regions(image_id, region_wrapper, request.transaction_id) LOG.info("RegionController - regions replaced: " + str(result)) event_details = 'Image {} regions: {} updated'.format( image_id, [r.name for r in region_wrapper.regions]) utils.audit_trail('replace regions', request.transaction_id, request.headers, image_id, event_details=event_details) return result except ErrorStatus as exception: LOG.log_exception("RegionController - Failed to replace region", exception) raise err_utils.get_error(request.transaction_id, message=exception.message, status_code=exception.status_code) except Exception as exception: LOG.log_exception("RegionController - Failed to replace region", exception) raise err_utils.get_error(request.transaction_id, status_code=500, error_details=exception.message)
def validate_model(self, context=None): # Validate visibility if self.visibility == 'public' and self.customers: raise ErrorStatus( 400, 'Visibility is public but some customers were' ' specified!') elif self.visibility == 'private' and not self.customers: raise ErrorStatus( 400, 'Visibility is private but no customers were' ' specified!') # Validate disk format valid_disk_formats = ( 'ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2', 'vdi', 'iso', ) if self.disk_format not in valid_disk_formats: raise ErrorStatus(400, 'Invalid disk format!') # validate customer input unique customer_input = set() for customer in self.customers: if customer in customer_input: raise ErrorStatus( 400, "customer {} exist more than one".format(customer)) customer_input.add(customer) # Validate container format valid_container_formats = ('ami', 'ari', 'aki', 'bare', 'ovf', 'ova', 'docker') if self.container_format not in valid_container_formats: raise ErrorStatus( 400, 'Invalid container format! {}'.format(self.container_format)) # Validate min-disk and min-ram (wsme automatically converts booleans # to int, and isinstance(False, int) returns True, so that is how we # validate the type) if 'min-disk' in request.json['image'] and not type( request.json['image']['min-disk']) == int: raise ErrorStatus(400, 'min-disk must be an integer!') if 'min-ram' in request.json['image'] and not type( request.json['image']['min-ram']) == int: raise ErrorStatus(400, 'min-ram must be an integer!') if self.min_disk != wsme.Unset and int( self.min_disk) > 2147483646 or int(self.min_disk) < 0: raise ErrorStatus(400, 'value must be positive less than 2147483646') if self.min_ram != wsme.Unset and int( self.min_ram) > 2147483646 or int(self.min_ram) < 0: raise ErrorStatus(400, 'value must be positive less than 2147483646') if context == "update": for region in self.regions: if region.type == "group": raise ErrorStatus( 400, "region {} type is invalid for update, \'group\' can be only in create" .format(region.name))
def post(self, invalid_extra_param=None, image_wrapper=None): image_logic, utils = di.resolver.unpack(ImageController) uuid = "FailedToGetFromUUIDGen" auth.authorize(request, "image:create") if not image_wrapper: raise err_utils.get_error(request.transaction_id, message="Body not supplied", status_code=400) if invalid_extra_param: raise err_utils.get_error( request.transaction_id, message="URL has invalid extra param '{}' ".format( invalid_extra_param), status_code=405) try: LOG.info("ImageController - Create image: " + str(image_wrapper.image.name)) image_wrapper.image.owner = request.headers.get( 'X-RANGER-Owner') or '' if not image_wrapper.image.id: uuid = utils.make_uuid() else: try: uuid = utils.create_existing_uuid(image_wrapper.id) except TypeError: raise ErrorStatus(409.1, message='Image UUID already exists') try: ret_image = image_logic.create_image(image_wrapper, uuid, request.transaction_id) except oslo_db.exception.DBDuplicateEntry as exception: raise ErrorStatus( 409.2, 'The field {0} already exists'.format(exception.columns)) LOG.info("ImageController - Image Created: " + str(ret_image)) event_details = 'Image {} {} {}, visibility: {}, created in regions: {} with tenants: {}'.format( uuid, image_wrapper.image.name, image_wrapper.image.url, image_wrapper.image.visibility, [r.name for r in image_wrapper.image.regions], image_wrapper.image.customers) utils.audit_trail('create image', request.transaction_id, request.headers, uuid, event_details=event_details) return ret_image except ErrorStatus as exception: LOG.log_exception("ImageController - Failed to CreateImage", exception) raise err_utils.get_error(request.transaction_id, message=exception.message, status_code=exception.status_code) except Exception as exception: LOG.log_exception("ImageController - Failed to CreateImage", exception) raise err_utils.get_error(request.transaction_id, status_code=500, error_details=exception.message)
def send_image(image_dict, transaction_id, action="put"): # action can be "post" for creating image or "delete" for deleting image requests = di.resolver.unpack(send_image) data = { "service_template": { "resource": { "resource_type": "image" }, "model": str(json.dumps(image_dict)), "tracking": { "external_id": "", "tracking_id": transaction_id } } } data_to_display = { "service_template": { "resource": { "resource_type": "image" }, "model": image_dict, "tracking": { "external_id": "", "tracking_id": transaction_id } } } try: pp = pprint.PrettyPrinter(width=30) pretty_text = pp.pformat(data_to_display) wrapper_json = json.dumps(data) headers['X-RANGER-Client'] = request.headers[ 'X-RANGER-Client'] if 'X-RANGER-Client' in request.headers else \ 'NA' headers['X-RANGER-Requester'] = request.headers[ 'X-RANGER-Requester'] if 'X-RANGER-Requester' in request.headers else \ '' LOG.debug( "Wrapper JSON before sending action: {0} to Rds Proxy {1}".format( action, pretty_text)) LOG.info("Sending to RDS Server: " + conf.api.rds_server.base + conf.api.rds_server.resources) if action == "post": resp = requests.post(conf.api.rds_server.base + conf.api.rds_server.resources, data=wrapper_json, headers=headers, verify=conf.verify) elif action == "put": resp = requests.put(conf.api.rds_server.base + conf.api.rds_server.resources, data=wrapper_json, headers=headers, verify=conf.verify) elif action == "delete": resp = requests.delete(conf.api.rds_server.base + conf.api.rds_server.resources, data=wrapper_json, headers=headers, verify=conf.verify) else: raise Exception("Invalid action in RdxProxy.send_image(" "image_dict, transaction_id, action) " "action can be post or delete, " "got {0}".format(action)) content = resp.content LOG.debug("return from rds server status code: {0} " "content: {1}".format(resp.status_code, resp.content)) if resp.content and 200 <= resp.status_code < 300: content = resp.json() else: # In case of error from rds, the response is WSME format response. # the error message is within the 'faultstring' raise ErrorStatus(resp.status_code, json.loads(content)["faultstring"]) except Exception as exp: LOG.log_exception("ImageLogic - Failed to update image", exp) raise exp return content