
Updated pep8 requirements and fixed resulting codes to fix broken pep8 job. Updated docker image build process to use roles to ensure docker rather than using manual docker install process to fix broken ranger image job. Co-Authored-By: Jeremy Houser <jeremyhouser@protonmail.com> Co-Authored-By: Chi Lo <cl566n@att.com> Change-Id: I28df0a27e4b354dd53c17fbb1a9468cb7ff5bc16
610 lines
21 KiB
Python
Executable File
610 lines
21 KiB
Python
Executable File
import time
|
|
|
|
from orm.common.orm_common.injector import injector
|
|
from orm.common.orm_common.utils import utils
|
|
from orm.services.image_manager.ims.logger import get_logger
|
|
from orm.services.image_manager.ims.logic.error_base import \
|
|
ErrorStatus, NotFoundError
|
|
from orm.services.image_manager.ims.persistency.sql_alchemy.db_models import \
|
|
ImageCustomer, ImageRegion
|
|
from orm.services.image_manager.ims.persistency.wsme.models import (
|
|
ImageSummary, ImageSummaryResponse, ImageWrapper, RegionWrapper)
|
|
from orm.services.image_manager.ims.utils import utils as ImsUtils
|
|
import oslo_db
|
|
|
|
LOG = get_logger(__name__)
|
|
|
|
di = injector.get_di()
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def create_image(image_wrapper, image_uuid, transaction_id):
|
|
DataManager = di.resolver.unpack(create_image)
|
|
datamanager = DataManager()
|
|
image_wrapper.image.id = image_uuid
|
|
|
|
image_wrapper.image.created_at = str(int(time.time()))
|
|
image_wrapper.image.updated_at = image_wrapper.image.created_at
|
|
|
|
try:
|
|
image_wrapper.handle_region_group()
|
|
image_wrapper.validate_model()
|
|
sql_image = image_wrapper.to_db_model()
|
|
|
|
image_rec = datamanager.get_record('image')
|
|
|
|
datamanager.begin_transaction()
|
|
image_rec.insert(sql_image)
|
|
datamanager.flush() # i want to get any exception created by this
|
|
# insert
|
|
existing_region_names = []
|
|
send_to_rds_if_needed(sql_image, existing_region_names, "post",
|
|
transaction_id)
|
|
|
|
datamanager.commit()
|
|
|
|
ret_image = get_image_by_uuid(image_uuid)
|
|
return ret_image
|
|
|
|
except oslo_db.exception.DBDuplicateEntry as exception:
|
|
utils.delete_uuid(image_uuid)
|
|
raise ErrorStatus(
|
|
409.2, "Image name '{}' already exists".format(
|
|
image_wrapper.image.name))
|
|
|
|
except Exception as exp:
|
|
LOG.log_exception("ImageLogic - Failed to CreateImage", exp)
|
|
datamanager.rollback()
|
|
utils.delete_uuid(image_uuid)
|
|
raise
|
|
|
|
|
|
@di.dependsOn('rds_proxy')
|
|
def send_to_rds_if_needed(sql_image, existing_region_names, http_action,
|
|
transaction_id):
|
|
rds_proxy = di.resolver.unpack(send_to_rds_if_needed)
|
|
if (sql_image.regions and len(sql_image.regions) > 0) or len(
|
|
existing_region_names) > 0:
|
|
image_dict = sql_image.get_proxy_dict()
|
|
update_region_actions(image_dict, existing_region_names, http_action)
|
|
if image_dict['regions'] or len(existing_region_names) > 0:
|
|
LOG.debug("Image is valid, sending to RDS Proxy ")
|
|
rds_proxy.send_image(image_dict, transaction_id, http_action)
|
|
else:
|
|
LOG.debug("Group with no regions, not sending to RDS Proxy " + str(
|
|
sql_image))
|
|
else:
|
|
LOG.debug("Image with no regions, not sending to RDS Proxy " + str(
|
|
sql_image))
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def update_image(image_wrapper, image_uuid, transaction_id, http_action="put"):
|
|
DataManager = di.resolver.unpack(update_image)
|
|
datamanager = DataManager()
|
|
|
|
try:
|
|
image_wrapper.validate_model('update')
|
|
new_image = image_wrapper.to_db_model()
|
|
new_image.id = image_uuid
|
|
|
|
image_rec = datamanager.get_record('image')
|
|
sql_image = image_rec.get_image_by_id(image_uuid)
|
|
|
|
if sql_image is None:
|
|
raise NotFoundError(
|
|
status_code=404,
|
|
message="Image {0} does not exist for update".format(
|
|
image_uuid))
|
|
|
|
image_wrapper.validate_update(sql_image, new_image)
|
|
|
|
datamanager.begin_transaction()
|
|
|
|
new_image.owner = sql_image.owner
|
|
existing_regions = sql_image.get_existing_region_names()
|
|
new_image.created_at = int(sql_image.created_at)
|
|
new_image.updated_at = int(time.time())
|
|
# result = image_rec.delete_image_by_id(image_uuid)
|
|
datamanager.get_session().delete(sql_image)
|
|
# del sql_image
|
|
image_rec.insert(new_image)
|
|
datamanager.flush()
|
|
|
|
send_to_rds_if_needed(new_image, existing_regions, http_action,
|
|
transaction_id)
|
|
|
|
datamanager.commit()
|
|
|
|
ret_image = get_image_by_uuid(image_uuid)
|
|
|
|
return ret_image
|
|
|
|
except Exception as exp:
|
|
datamanager.rollback()
|
|
LOG.log_exception("ImageLogic - Failed to update image", exp)
|
|
raise
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def delete_image_by_uuid(image_uuid, transaction_id):
|
|
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:
|
|
message_not_found = "Image '{}' not found".format(image_uuid)
|
|
raise ErrorStatus(404, message_not_found)
|
|
|
|
image_existing_region_names = sql_image.get_existing_region_names()
|
|
if len(image_existing_region_names) > 0:
|
|
# Do not delete an image that still has region(s)
|
|
raise ErrorStatus(405,
|
|
"Cannot delete a image with regions. "
|
|
"Please delete the regions first and then "
|
|
"delete the image. ")
|
|
|
|
# Get status from resource status table
|
|
uuid = [sql_image.id]
|
|
resource_status_dict = utils.get_resource_status_from_db(
|
|
datamanager.get_session(), uuid)
|
|
status_model = resource_status_dict.get(sql_image.id)
|
|
|
|
if status_model:
|
|
status = status_model.status
|
|
LOG.debug('Status from resource_status table: {}'.format(status))
|
|
else:
|
|
# Image not found in table, that means it never had any
|
|
# regions. So it is OK to delete it
|
|
status = 'Success'
|
|
LOG.debug('Resource not found in table, so it is OK to delete')
|
|
|
|
if status != '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()
|
|
|
|
# after successful image delete, delete image id from uuids table
|
|
utils.delete_uuid(image_uuid)
|
|
|
|
except Exception as exp:
|
|
LOG.log_exception("ImageLogic - Failed to delete image", exp)
|
|
datamanager.rollback()
|
|
raise
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def add_regions(image_uuid, regions, transaction_id):
|
|
DataManager = di.resolver.unpack(add_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()
|
|
|
|
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 add regions", exp)
|
|
datamanager.rollback()
|
|
raise exp
|
|
except Exception as exp:
|
|
LOG.log_exception("ImageLogic - Failed to add regions", exp)
|
|
datamanager.rollback()
|
|
raise exp
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
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
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def delete_region(image_uuid, region_name, transaction_id, force_delete):
|
|
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))
|
|
# do not allow delete_region for protected images
|
|
if sql_image.protected:
|
|
protect_msg = "Protected image {} cannot be deleted. Please " \
|
|
"update image with protected=false and try again"
|
|
raise ErrorStatus(400, protect_msg.format(image_uuid))
|
|
|
|
existing_region_names = sql_image.get_existing_region_names()
|
|
sql_image.remove_region(region_name)
|
|
|
|
# Get any exception created by previous actions against the database
|
|
datamanager.flush()
|
|
|
|
send_to_rds_if_needed(sql_image, existing_region_names, "put",
|
|
transaction_id)
|
|
if force_delete:
|
|
datamanager.commit()
|
|
else:
|
|
datamanager.rollback()
|
|
|
|
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
|
|
|
|
finally:
|
|
datamanager.close()
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def add_customers(image_uuid, customers, transaction_id):
|
|
DataManager = di.resolver.unpack(add_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 with id: {0} not found'.format(
|
|
image_uuid))
|
|
|
|
if sql_image.visibility == "public":
|
|
raise ErrorStatus(400, 'Cannot add Customers to public Image')
|
|
|
|
existing_region_names = sql_image.get_existing_region_names()
|
|
|
|
for user in customers.customers:
|
|
db_Customer = ImageCustomer(customer_id=user)
|
|
sql_image.add_customer(db_Customer)
|
|
|
|
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()
|
|
|
|
ret_image = get_image_by_uuid(image_uuid)
|
|
return ret_image
|
|
|
|
except Exception as exp:
|
|
if 'conflicts with persistent instance' in str(exp) or \
|
|
'Duplicate entry' in str(exp):
|
|
raise ErrorStatus(409, "Duplicate Customer for Image")
|
|
LOG.log_exception("ImageLogic - Failed to add Customers", exp)
|
|
datamanager.rollback()
|
|
raise
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
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 str(exp) or \
|
|
'Duplicate entry' in str(exp):
|
|
raise ErrorStatus(409, "Duplicate Customer for Image")
|
|
LOG.log_exception("ImageLogic - Failed to add Customers", exp)
|
|
datamanager.rollback()
|
|
raise
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
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 set_resource_status(sql_image, status_model):
|
|
image_wrapper = ImageWrapper.from_db_model(sql_image)
|
|
image_wrapper.image.status = 'no regions'
|
|
|
|
if status_model and status_model.regions:
|
|
for region in image_wrapper.image.regions:
|
|
for status in status_model.regions:
|
|
if status.region == region.name:
|
|
region.status = status.status
|
|
if status.error_msg:
|
|
region.set_error_message(status.error_msg)
|
|
|
|
image_wrapper.image.status = status_model.status
|
|
|
|
return image_wrapper
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def get_image_by_uuid(image_uuid, query_by_id_or_name=False):
|
|
"""This function includes an optional boolean parameter
|
|
query_by_id_or_name. If query_by_id_or_name evaluates to true, IMS logic
|
|
will fetch the image record whose "image_uuid" parameter value matches
|
|
either the image id or name value. Otherwise, it defaults to query by
|
|
image ID value only.
|
|
"""
|
|
DataManager = di.resolver.unpack(get_image_by_uuid)
|
|
datamanager = DataManager()
|
|
|
|
LOG.debug("Get image by uuid : {}".format(image_uuid))
|
|
try:
|
|
|
|
datamanager.begin_transaction()
|
|
image_rec = datamanager.get_record('image')
|
|
|
|
# Only the get_image API will pass the optional parameter and
|
|
# set it to true
|
|
if query_by_id_or_name:
|
|
sql_image = image_rec.get_image(image_uuid)
|
|
else:
|
|
# all other image APIs will NOT pass the optional parameter
|
|
sql_image = image_rec.get_image_by_id(image_uuid)
|
|
|
|
if not sql_image:
|
|
raise NotFoundError(
|
|
status_code=404,
|
|
message="Image {0} not found ".format(image_uuid))
|
|
|
|
# Get the status from resource table
|
|
uuid = [sql_image.id]
|
|
resource_status_dict = utils.get_resource_status_from_db(
|
|
datamanager.get_session(), uuid)
|
|
status_model = resource_status_dict.get(sql_image.id)
|
|
|
|
image_wrapper = set_resource_status(sql_image, status_model)
|
|
|
|
# get image own link
|
|
image_wrapper.image.links, image_wrapper.image.self_link = \
|
|
ImsUtils.get_server_links(image_uuid)
|
|
|
|
# convert time stamp format to human readable time
|
|
image_wrapper.image.created_at = ImsUtils.convert_time_human(
|
|
image_wrapper.image.created_at)
|
|
image_wrapper.image.updated_at = ImsUtils.convert_time_human(
|
|
image_wrapper.image.updated_at)
|
|
|
|
except NotFoundError as exp:
|
|
datamanager.rollback()
|
|
LOG.log_exception("ImageLogic - Failed to update image", exp)
|
|
raise exp
|
|
|
|
except Exception as exp:
|
|
datamanager.rollback()
|
|
LOG.log_exception("ImageLogic - Failed to delete Customer", exp)
|
|
raise
|
|
|
|
return image_wrapper
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def get_image_list_by_params(visibility, region, Customer):
|
|
DataManager = di.resolver.unpack(get_image_list_by_params)
|
|
datamanager = DataManager()
|
|
|
|
try:
|
|
image_record = datamanager.get_record('image')
|
|
sql_images = image_record.get_images_by_criteria(visibility=visibility,
|
|
region=region,
|
|
Customer=Customer)
|
|
|
|
response = ImageSummaryResponse()
|
|
if sql_images:
|
|
uuids = [sql_image.id for sql_image in sql_images]
|
|
resource_status_dict = utils.get_resource_status_from_db(
|
|
datamanager.get_session(), uuids)
|
|
|
|
for sql_image in sql_images:
|
|
status_model = resource_status_dict.get(sql_image.id)
|
|
wsme_image = set_resource_status(sql_image, status_model)
|
|
image_summary = ImageSummary.from_wsme(wsme_image)
|
|
response.images.append(image_summary)
|
|
|
|
return response
|
|
|
|
except ErrorStatus as exp:
|
|
LOG.log_exception("ImageLogic - Failed to get list", exp)
|
|
raise
|
|
except Exception as exp:
|
|
LOG.log_exception("ImageLogic - Failed to get list", exp)
|
|
raise
|
|
|
|
|
|
def update_region_actions(image_dict, existing_region_names, action="put"):
|
|
if action == "delete":
|
|
set_regions_action(image_dict, "delete")
|
|
elif action == "post":
|
|
set_regions_action(image_dict, "create")
|
|
else: # put
|
|
for region in image_dict["regions"]:
|
|
if region["name"] in existing_region_names:
|
|
region["action"] = "modify"
|
|
else:
|
|
region["action"] = "create"
|
|
|
|
# add deleted regions
|
|
for exist_region_name in existing_region_names:
|
|
if region_name_exist_in_regions(exist_region_name,
|
|
image_dict["regions"]):
|
|
continue
|
|
else:
|
|
image_dict["regions"].append(
|
|
{"name": exist_region_name, "action": "delete"})
|
|
|
|
|
|
def region_name_exist_in_regions(region_name, regions):
|
|
for region in regions:
|
|
if region["name"] == region_name:
|
|
return True
|
|
return False
|
|
|
|
|
|
def set_regions_action(image_dict, action):
|
|
for region in image_dict["regions"]:
|
|
region["action"] = action
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
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_by_id(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
|