1034 lines
35 KiB
Python
Executable File
1034 lines
35 KiB
Python
Executable File
from orm.services.flavor_manager.fms_rest.data.sql_alchemy.db_models import (
|
|
FlavorRegion, FlavorTenant)
|
|
from orm.services.flavor_manager.fms_rest.data.wsme.models import (
|
|
ExtraSpecsWrapper,
|
|
FlavorListFullResponse, FlavorWrapper,
|
|
Region, RegionWrapper, TagsWrapper,
|
|
TenantWrapper)
|
|
from orm.services.flavor_manager.fms_rest.logger import get_logger
|
|
from orm.services.flavor_manager.fms_rest.logic.error_base import (
|
|
ConflictError, ErrorStatus, NotFoundError)
|
|
from orm.common.orm_common.injector import injector
|
|
from orm.common.orm_common.utils import utils
|
|
|
|
from oslo_config import cfg
|
|
import oslo_db
|
|
|
|
LOG = get_logger(__name__)
|
|
|
|
di = injector.get_di()
|
|
|
|
|
|
def validate_tenants_regions_list(requested_tenants, requested_regions,
|
|
action, datamanager):
|
|
regions_list, tenants_list = [], []
|
|
results = datamanager.get_valid_tenant_region_list(requested_tenants,
|
|
requested_regions)
|
|
|
|
valid_tenants_list, valid_regions_list = [], []
|
|
|
|
if results:
|
|
# the first element in the results tuple is the tenant prep
|
|
# result_tenant_list from result_rows and remove NoneTypes from list
|
|
result_tenant_list = [x[0] for x in results]
|
|
result_tenant_list = filter(None, result_tenant_list)
|
|
# lastly clean up valid_tenants_list list by removing duplicate items
|
|
valid_tenants_list = list(dict.fromkeys(result_tenant_list))
|
|
|
|
# second element in the results tuple is the region - compile the
|
|
# region data into valid_regions_list and eliminate duplicates
|
|
# from the list
|
|
valid_regions_list = [x[1] for x in results]
|
|
valid_regions_list = list(dict.fromkeys(valid_regions_list))
|
|
|
|
return valid_tenants_list, valid_regions_list
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def create_flavor(flavor, flavor_uuid, transaction_id):
|
|
DataManager = di.resolver.unpack(create_flavor)
|
|
datamanager = DataManager()
|
|
try:
|
|
flavor.flavor.handle_region_groups()
|
|
flavor.flavor.validate_model("create")
|
|
flavor.flavor.id = flavor_uuid
|
|
if not flavor.flavor.ephemeral or flavor.flavor.ephemeral.isspace():
|
|
flavor.flavor.ephemeral = '0'
|
|
flavor.flavor.name = calculate_name(flavor)
|
|
|
|
LOG.debug("Flavor name is [{}] ".format(flavor.flavor.name))
|
|
flavor_regions = []
|
|
for region in flavor.flavor.regions:
|
|
flavor_regions.append(region.name)
|
|
|
|
# Execute the following logic only if at least one region AND one
|
|
# tenant are provided in a private flavor:
|
|
# Validate which tenants from the original tenants list to
|
|
# be assigned to the private flavor; if no valid tenants
|
|
# found, the valid_tenants_list will return empty list
|
|
if (flavor_regions and flavor.flavor.visibility == 'private' and
|
|
flavor.flavor.tenants):
|
|
valid_tenants_list, valid_regions_list = \
|
|
validate_tenants_regions_list(flavor.flavor.tenants,
|
|
flavor_regions,
|
|
'create', datamanager)
|
|
# replace the original tenant list in the private flavor
|
|
# with the valid_tenants_list
|
|
flavor.flavor.tenants = valid_tenants_list
|
|
|
|
sql_flavor = flavor.to_db_model()
|
|
|
|
flavor_rec = datamanager.get_record('flavor')
|
|
|
|
datamanager.begin_transaction()
|
|
|
|
flavor_rec.insert(sql_flavor)
|
|
datamanager.flush() # Get any exception created by this insert
|
|
existing_region_names = []
|
|
send_to_rds_if_needed(
|
|
sql_flavor, existing_region_names, "post", transaction_id)
|
|
|
|
datamanager.commit()
|
|
|
|
ret_flavor = get_flavor_by_uuid(flavor_uuid)
|
|
return ret_flavor
|
|
|
|
except oslo_db.exception.DBDuplicateEntry as exception:
|
|
raise ErrorStatus(
|
|
409.2, "Flavor name '{}' already exists".format(
|
|
flavor.flavor.name))
|
|
|
|
except Exception as exp:
|
|
LOG.log_exception("FlavorLogic - Failed to CreateFlavor",
|
|
str(exp))
|
|
datamanager.rollback()
|
|
if "Duplicate entry" in str(exp):
|
|
raise ConflictError(
|
|
409,
|
|
"Flavor {} already exists".format(flavor.flavor.name))
|
|
raise
|
|
finally:
|
|
datamanager.close()
|
|
|
|
|
|
@di.dependsOn('rds_proxy')
|
|
def send_to_rds_if_needed(sql_flavor,
|
|
existing_region_names,
|
|
http_action,
|
|
transaction_id):
|
|
rds_proxy = di.resolver.unpack(send_to_rds_if_needed)
|
|
if (sql_flavor.flavor_regions and len(sql_flavor.flavor_regions) > 0) \
|
|
or len(existing_region_names) > 0:
|
|
flavor_dict = sql_flavor.todict()
|
|
update_region_actions(flavor_dict, existing_region_names, http_action)
|
|
LOG.debug("Flavor is valid to send to RDS - sending to RDS Proxy ")
|
|
rds_proxy.send_flavor(flavor_dict, transaction_id, http_action)
|
|
else:
|
|
LOG.debug("Flavor with no regions - wasn't sent to RDS Proxy " +
|
|
str(sql_flavor))
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def update_flavor(flavor, flavor_uuid, transaction_id): # pragma: no cover
|
|
DataManager = di.resolver.unpack(update_flavor)
|
|
datamanager = DataManager()
|
|
|
|
try:
|
|
flavor.validate_model("update")
|
|
|
|
sql_flavor = flavor.to_db_model()
|
|
sql_flavor.id = flavor_uuid
|
|
sql_flavor.name = calculate_name(flavor)
|
|
LOG.debug("Flavor name is [{}] ".format(sql_flavor.name))
|
|
|
|
datamanager.begin_transaction()
|
|
flavor_rec = datamanager.get_record('flavor')
|
|
db_flavor = flavor_rec.get_flavor_by_id(flavor_uuid)
|
|
if db_flavor is None:
|
|
raise Exception("Flavor {0} not found".format(flavor_uuid))
|
|
|
|
existing_region_names = db_flavor.get_existing_region_names()
|
|
|
|
flavor_rec.delete_by_uuid(flavor_uuid)
|
|
del(db_flavor)
|
|
|
|
flavor_rec.insert(sql_flavor)
|
|
# get any exception created by this insert method
|
|
datamanager.flush()
|
|
|
|
send_to_rds_if_needed(
|
|
sql_flavor, existing_region_names, "put", transaction_id)
|
|
|
|
datamanager.commit()
|
|
|
|
ret_flavor = get_flavor_by_uuid(flavor_uuid)
|
|
return ret_flavor
|
|
|
|
except Exception as exp:
|
|
LOG.log_exception("FlavorLogic - Failed to update flavor", str(exp))
|
|
datamanager.rollback()
|
|
raise
|
|
finally:
|
|
datamanager.close()
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def delete_flavor_by_uuid(flavor_uuid): # , transaction_id):
|
|
DataManager = di.resolver.unpack(delete_flavor_by_uuid)
|
|
datamanager = DataManager()
|
|
|
|
try:
|
|
datamanager.begin_transaction()
|
|
flavor_rec = datamanager.get_record('flavor')
|
|
|
|
sql_flavor = flavor_rec.get_flavor_by_id(flavor_uuid)
|
|
if sql_flavor is None:
|
|
raise NotFoundError(
|
|
message="Flavor '{}' not found".format(flavor_uuid))
|
|
|
|
existing_region_names = sql_flavor.get_existing_region_names()
|
|
if len(existing_region_names) > 0:
|
|
# Do not delete a flavor that still has some regions
|
|
msg = "Cannot delete a flavor that has regions. " \
|
|
"Please delete the regions first and then " \
|
|
"delete the flavor."
|
|
LOG.info(msg)
|
|
raise ErrorStatus(405, msg)
|
|
else:
|
|
expected_status = 'Success'
|
|
|
|
# Get status from resource status table
|
|
uuid = [sql_flavor.id]
|
|
resource_status_dict = utils.get_resource_status_from_db(
|
|
datamanager.get_session(), uuid)
|
|
status_model = resource_status_dict.get(sql_flavor.id)
|
|
|
|
if status_model:
|
|
status = status_model.status
|
|
LOG.debug(
|
|
'Status from resource_status table: {}'.format(status))
|
|
else:
|
|
# Flavor not found in table, that means it never had any
|
|
# regions. So it is OK to delete it
|
|
status = expected_status
|
|
LOG.debug('Resource not found in table, so it is OK to delete')
|
|
|
|
if status != expected_status:
|
|
msg = "The flavor has not been deleted " \
|
|
"successfully from all of its regions " \
|
|
"(either the deletion failed on one of the " \
|
|
"regions or it is still in progress)"
|
|
LOG.error('Invalid flavor status received from RDS')
|
|
raise ErrorStatus(409, msg)
|
|
|
|
# OK to delete
|
|
flavor_rec.delete_by_uuid(flavor_uuid)
|
|
|
|
# get any exception created by this delete
|
|
datamanager.flush()
|
|
datamanager.commit()
|
|
except Exception as exp:
|
|
LOG.log_exception("FlavorLogic - Failed to delete flavor", str(exp))
|
|
datamanager.rollback()
|
|
raise
|
|
finally:
|
|
datamanager.close()
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def add_regions(flavor_uuid, regions, transaction_id):
|
|
DataManager = di.resolver.unpack(add_regions)
|
|
datamanager = DataManager()
|
|
|
|
try:
|
|
flavor_rec = datamanager.get_record('flavor')
|
|
sql_flavor = flavor_rec.get_flavor_by_id(flavor_uuid)
|
|
if not sql_flavor:
|
|
raise ErrorStatus(404,
|
|
'flavor id {0} not found'.format(flavor_uuid))
|
|
|
|
existing_region_names = sql_flavor.get_existing_region_names()
|
|
|
|
flvr_tenant_list, flvr_region_list = [], []
|
|
for region in regions.regions:
|
|
if region.name == '' or region.name.isspace():
|
|
raise ErrorStatus(400, 'Cannot add region with an empty name')
|
|
if region.type == "group":
|
|
raise ErrorStatus(400,
|
|
"Adding \'group\' type region is supported"
|
|
" only when creating a flavor")
|
|
db_region = FlavorRegion(region_name=region.name,
|
|
region_type='single')
|
|
sql_flavor.add_region(db_region)
|
|
flvr_region_list.append(region.name)
|
|
|
|
# get any exception created by previous actions against the database
|
|
datamanager.flush()
|
|
|
|
# private flavor new logic
|
|
# validate tenants assigned to the flavor
|
|
for tenant in sql_flavor.flavor_tenants:
|
|
flvr_tenant_list.append(tenant.tenant_id)
|
|
|
|
valid_tenants_list, valid_regions_list = \
|
|
validate_tenants_regions_list(flvr_tenant_list,
|
|
flvr_region_list,
|
|
'create', datamanager)
|
|
# update tenant list
|
|
for tenant in flvr_tenant_list:
|
|
if tenant not in valid_tenants_list:
|
|
sql_flavor.remove_tenant(tenant)
|
|
|
|
send_to_rds_if_needed(
|
|
sql_flavor, existing_region_names, "put", transaction_id)
|
|
|
|
datamanager.commit()
|
|
|
|
flavor = get_flavor_by_uuid(flavor_uuid)
|
|
ret = RegionWrapper(regions=flavor.flavor.regions)
|
|
return ret
|
|
|
|
except ErrorStatus as exp:
|
|
LOG.log_exception("FlavorLogic - Failed to update flavor", str(exp))
|
|
datamanager.rollback()
|
|
raise exp
|
|
except Exception as exp:
|
|
LOG.log_exception("FlavorLogic - Failed to add regions", str(exp))
|
|
datamanager.rollback()
|
|
if "conflicts with persistent instance" in str(exp):
|
|
raise ConflictError(409,
|
|
"One or more regions already exists in Flavor")
|
|
raise exp
|
|
finally:
|
|
datamanager.close()
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def delete_region(flavor_uuid, region_name, transaction_id, force_delete):
|
|
DataManager = di.resolver.unpack(delete_region)
|
|
datamanager = DataManager()
|
|
|
|
try:
|
|
flavor_rec = datamanager.get_record('flavor')
|
|
sql_flavor = flavor_rec.get_flavor_by_id(flavor_uuid)
|
|
if not sql_flavor:
|
|
raise ErrorStatus(404,
|
|
'flavor id {0} not found'.format(flavor_uuid))
|
|
|
|
existing_region_names = sql_flavor.get_existing_region_names()
|
|
sql_flavor.remove_region(region_name)
|
|
|
|
# get any exception created by previous actions against the database
|
|
datamanager.flush()
|
|
send_to_rds_if_needed(sql_flavor, existing_region_names, "put",
|
|
transaction_id)
|
|
if force_delete:
|
|
datamanager.commit()
|
|
else:
|
|
datamanager.rollback()
|
|
|
|
except ErrorStatus as exp:
|
|
LOG.log_exception("FlavorLogic - Failed to update flavor", str(exp))
|
|
datamanager.rollback()
|
|
raise exp
|
|
|
|
except Exception as exp:
|
|
LOG.log_exception("FlavorLogic - Failed to delete region", str(exp))
|
|
datamanager.rollback()
|
|
raise exp
|
|
|
|
finally:
|
|
datamanager.close()
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def add_tenants(flavor_uuid, tenants, transaction_id):
|
|
DataManager = di.resolver.unpack(add_tenants)
|
|
datamanager = DataManager()
|
|
|
|
valid_tenants_list, valid_regions_list = [], []
|
|
|
|
try:
|
|
flavor_rec = datamanager.get_record('flavor')
|
|
sql_flavor = flavor_rec.get_flavor_by_id(flavor_uuid)
|
|
if not sql_flavor:
|
|
raise ErrorStatus(404,
|
|
'Flavor id {0} not found'.format(flavor_uuid))
|
|
|
|
if sql_flavor.visibility == "public":
|
|
raise ErrorStatus(405, 'Cannot add tenant to a public flavor')
|
|
|
|
existing_region_names = sql_flavor.get_existing_region_names()
|
|
existing_region_list = []
|
|
|
|
for x in existing_region_names:
|
|
existing_region_list.append(x)
|
|
|
|
if tenants.tenants:
|
|
valid_tenants_list, valid_regions_list = \
|
|
validate_tenants_regions_list(tenants.tenants,
|
|
existing_region_list,
|
|
'create', datamanager)
|
|
|
|
if not valid_tenants_list:
|
|
raise ValueError("At least one valid tenant must be provided")
|
|
|
|
for tenant in valid_tenants_list:
|
|
if not isinstance(tenant, str):
|
|
raise ValueError("tenant type must be a string type,"
|
|
" got {} type".format(type(tenant)))
|
|
|
|
db_tenant = FlavorTenant(tenant_id=tenant)
|
|
sql_flavor.add_tenant(db_tenant)
|
|
# get any exception created by previous actions against the database
|
|
datamanager.flush()
|
|
send_to_rds_if_needed(
|
|
sql_flavor, existing_region_names, "put", transaction_id)
|
|
datamanager.commit()
|
|
|
|
flavor = get_flavor_by_uuid(flavor_uuid)
|
|
ret = TenantWrapper(tenants=flavor.flavor.tenants)
|
|
return ret
|
|
|
|
except (ErrorStatus, ValueError) as exp:
|
|
LOG.log_exception("FlavorLogic - Failed to update flavor", str(exp))
|
|
datamanager.rollback()
|
|
raise
|
|
except Exception as exp:
|
|
datamanager.rollback()
|
|
LOG.log_exception("FlavorLogic - Failed to add tenants", str(exp))
|
|
if "conflicts with persistent instance" in str(exp):
|
|
raise ConflictError(409, "One or more tenants already exist")
|
|
raise
|
|
finally:
|
|
datamanager.close()
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def delete_tenant(flavor_uuid, tenant_id, transaction_id):
|
|
DataManager = di.resolver.unpack(delete_tenant)
|
|
datamanager = DataManager()
|
|
|
|
try:
|
|
flavor_rec = datamanager.get_record('flavor')
|
|
sql_flavor = flavor_rec.get_flavor_by_id(flavor_uuid)
|
|
if not sql_flavor:
|
|
raise ErrorStatus(404,
|
|
'flavor id {0} not found'.format(flavor_uuid))
|
|
# if trying to delete the only one tenant then return value error
|
|
if sql_flavor.visibility == "public":
|
|
raise ValueError("{} is a public flavor, delete tenant"
|
|
" action is not relevant".format(flavor_uuid))
|
|
|
|
existing_region_names = sql_flavor.get_existing_region_names()
|
|
sql_flavor.remove_tenant(tenant_id)
|
|
# get any exception created by previous actions against the database
|
|
datamanager.flush()
|
|
send_to_rds_if_needed(
|
|
sql_flavor, existing_region_names, "put", transaction_id)
|
|
datamanager.commit()
|
|
except NotFoundError as exp:
|
|
datamanager.rollback()
|
|
LOG.log_exception("FlavorLogic - Flavor not found", str(exp))
|
|
raise
|
|
except ErrorStatus as exp:
|
|
datamanager.rollback()
|
|
if exp.status_code == 404:
|
|
LOG.log_exception("FlavorLogic - Tenant not found", str(exp))
|
|
raise
|
|
else:
|
|
LOG.log_exception(
|
|
"FlavorLogic - failed to delete tenant", str(exp))
|
|
raise
|
|
except Exception as exp:
|
|
LOG.log_exception("FlavorLogic - Failed to delete tenant", str(exp))
|
|
datamanager.rollback()
|
|
raise
|
|
finally:
|
|
datamanager.close()
|
|
|
|
|
|
def extra_spec_in_default(extra_spec, default_extra_specs):
|
|
for default_extra_spec in default_extra_specs:
|
|
if extra_spec == default_extra_spec.key_name:
|
|
return True
|
|
return False
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def get_extra_specs_uuid(flavor_id, transaction_id):
|
|
DataManager = di.resolver.unpack(get_extra_specs_uuid)
|
|
datamanager = DataManager()
|
|
|
|
try:
|
|
LOG.debug("LOGIC - get extra specs")
|
|
datamanager.begin_transaction()
|
|
|
|
flavor_rec = datamanager.get_record("flavor")
|
|
sql_flavor = flavor_rec.get_flavor_by_id(flavor_id)
|
|
|
|
if not sql_flavor:
|
|
raise NotFoundError(404, 'flavor id {0} not found'.format(
|
|
flavor_id))
|
|
|
|
result = ExtraSpecsWrapper.from_db_model(sql_flavor.flavor_extra_specs)
|
|
|
|
except NotFoundError as exp:
|
|
datamanager.rollback()
|
|
LOG.log_exception("FlavorLogic - Flavor Not Found", str(exp))
|
|
raise
|
|
|
|
except Exception as exp:
|
|
datamanager.rollback()
|
|
LOG.log_exception("FlavorLogic - Flavor Not Found", str(exp))
|
|
raise
|
|
finally:
|
|
datamanager.close()
|
|
|
|
return result
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def delete_extra_specs(flavor_id, transaction_id, extra_spec=None):
|
|
DataManager = di.resolver.unpack(delete_extra_specs)
|
|
datamanager = DataManager()
|
|
|
|
try:
|
|
LOG.debug("LOGIC - delete extra specs")
|
|
datamanager.begin_transaction()
|
|
|
|
flavor_rec = datamanager.get_record("flavor")
|
|
sql_flavor = flavor_rec.get_flavor_by_id(flavor_id)
|
|
if not sql_flavor:
|
|
raise NotFoundError(404, 'flavor id {0} not found'.format(
|
|
flavor_id))
|
|
|
|
existing_region_names = sql_flavor.get_existing_region_names()
|
|
# calculate default flavor extra
|
|
flavor_wrapper = FlavorWrapper.from_db_model(sql_flavor)
|
|
default_extra_specs = flavor_wrapper.get_extra_spec_needed()
|
|
# check if delete all or one
|
|
if extra_spec:
|
|
if not extra_spec_in_default(extra_spec, default_extra_specs):
|
|
sql_flavor.remove_extra_spec(extra_spec)
|
|
else:
|
|
raise ErrorStatus(400,
|
|
"Bad request, this key cannot be deleted")
|
|
else:
|
|
sql_flavor.delete_all_extra_specs()
|
|
sql_flavor.add_extra_specs(default_extra_specs)
|
|
# get any exception created by previous actions against the database
|
|
datamanager.flush()
|
|
send_to_rds_if_needed(sql_flavor, existing_region_names, "put",
|
|
transaction_id)
|
|
datamanager.commit()
|
|
|
|
except NotFoundError as exp:
|
|
datamanager.rollback()
|
|
LOG.log_exception("FlavorLogic - Flavor not found", str(exp))
|
|
raise
|
|
|
|
except ErrorStatus as exp:
|
|
datamanager.rollback()
|
|
if exp.status_code == 404:
|
|
LOG.log_exception("FlavorLogic - extra specs not found", str(exp))
|
|
raise
|
|
else:
|
|
LOG.log_exception("FlavorLogic - failed to delete extra specs",
|
|
str(exp))
|
|
raise
|
|
|
|
except Exception as exp:
|
|
datamanager.rollback()
|
|
LOG.log_exception("FlavorLogic - fail to delete extra spec", str(exp))
|
|
raise
|
|
finally:
|
|
datamanager.close()
|
|
|
|
return
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def get_tags(flavor_uuid):
|
|
DataManager = di.resolver.unpack(get_tags)
|
|
|
|
datamanager = DataManager()
|
|
flavor_record = datamanager.get_record('flavor')
|
|
|
|
sql_flavor = flavor_record.get_flavor_by_id(flavor_uuid)
|
|
|
|
if not sql_flavor:
|
|
raise ErrorStatus(404, 'flavor id {0} not found'.format(flavor_uuid))
|
|
|
|
flavor_wrapper = FlavorWrapper.from_db_model(sql_flavor)
|
|
datamanager.close()
|
|
|
|
return flavor_wrapper.flavor.tag
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def delete_tags(flavor_id, tag, transaction_id):
|
|
DataManager = di.resolver.unpack(delete_tags)
|
|
datamanager = DataManager()
|
|
|
|
try:
|
|
LOG.debug("LOGIC - delete tags")
|
|
datamanager.begin_transaction()
|
|
|
|
flavor_rec = datamanager.get_record("flavor")
|
|
sql_flavor = flavor_rec.get_flavor_by_id(flavor_id)
|
|
|
|
if not sql_flavor:
|
|
raise NotFoundError(404,
|
|
'flavor id {0} not found'.format(flavor_id))
|
|
|
|
if tag:
|
|
sql_flavor.remove_tag(tag)
|
|
else:
|
|
sql_flavor.remove_all_tags()
|
|
|
|
datamanager.flush()
|
|
datamanager.commit()
|
|
|
|
except NotFoundError as exp:
|
|
datamanager.rollback()
|
|
LOG.log_exception("FlavorLogic - Flavor not found", exp)
|
|
raise
|
|
|
|
except ErrorStatus as exp:
|
|
if exp.status_code == 404:
|
|
LOG.log_exception("FlavorLogic - Tag not found", exp)
|
|
raise
|
|
else:
|
|
LOG.log_exception("FlavorLogic - failed to delete tags", exp)
|
|
raise
|
|
|
|
except Exception as exp:
|
|
datamanager.rollback()
|
|
LOG.log_exception("FlavorLogic - failed to delete tags", exp)
|
|
raise
|
|
finally:
|
|
datamanager.close()
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def update_tags(flavor_id, tags, transaction_id):
|
|
DataManager = di.resolver.unpack(update_tags)
|
|
datamanager = DataManager()
|
|
|
|
try:
|
|
LOG.debug("LOGIC - update tags")
|
|
datamanager.begin_transaction()
|
|
flavor_rec = datamanager.get_record("flavor")
|
|
sql_flavor = flavor_rec.get_flavor_by_id(flavor_id)
|
|
|
|
if not sql_flavor:
|
|
raise NotFoundError(404, "flavor id {} not found".format(
|
|
flavor_id))
|
|
|
|
tags_models = tags.to_db_model()
|
|
sql_flavor.replace_tags(tags_models)
|
|
|
|
datamanager.flush()
|
|
datamanager.commit()
|
|
|
|
# create return json to wsme
|
|
result = TagsWrapper.from_db_model(tags_models)
|
|
except NotFoundError as exp:
|
|
datamanager.rollback()
|
|
LOG.log_exception("flavor id {} not found".format(flavor_id), exp)
|
|
raise
|
|
|
|
except Exception as exp:
|
|
datamanager.rollback()
|
|
LOG.log_exception("failed to update tags", exp)
|
|
raise
|
|
finally:
|
|
datamanager.close()
|
|
|
|
return result
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def add_extra_specs(flavor_id, extra_specs, transaction_id):
|
|
DataManager = di.resolver.unpack(add_extra_specs)
|
|
datamanager = DataManager()
|
|
|
|
try:
|
|
LOG.debug("LOGIC - add extra specs")
|
|
datamanager.begin_transaction()
|
|
|
|
flavor_rec = datamanager.get_record("flavor")
|
|
sql_flavor = flavor_rec.get_flavor_by_id(flavor_id)
|
|
|
|
if not sql_flavor:
|
|
raise NotFoundError(404, 'flavor id {0} not found'.format(
|
|
flavor_id))
|
|
|
|
existing_region_names = sql_flavor.get_existing_region_names()
|
|
extra_specs_model = extra_specs.to_db_model()
|
|
|
|
sql_flavor.add_extra_specs(extra_specs_model)
|
|
# get any exception created by previous actions against the database
|
|
datamanager.flush()
|
|
send_to_rds_if_needed(sql_flavor, existing_region_names, "put",
|
|
transaction_id)
|
|
datamanager.commit()
|
|
|
|
# create return json to wsme
|
|
result = ExtraSpecsWrapper.from_db_model(sql_flavor.flavor_extra_specs)
|
|
except NotFoundError as exp:
|
|
datamanager.rollback()
|
|
LOG.log_exception("FlavorLogic - Flavor Not Found", exp)
|
|
raise
|
|
|
|
except Exception as exp:
|
|
datamanager.rollback()
|
|
if "conflicts with persistent instance" in str(exp.args):
|
|
raise ConflictError(
|
|
409,
|
|
"one or all extra specs {} already"
|
|
" exists".format(extra_specs.os_extra_specs))
|
|
LOG.log_exception("FlavorLogic - fail to add extra spec", exp)
|
|
raise
|
|
finally:
|
|
datamanager.close()
|
|
|
|
return result
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def update_extra_specs(flavor_id, extra_specs, transaction_id):
|
|
DataManager = di.resolver.unpack(update_extra_specs)
|
|
datamanager = DataManager()
|
|
|
|
try:
|
|
LOG.debug("LOGIC - update extra specs")
|
|
datamanager.begin_transaction()
|
|
flavor_rec = datamanager.get_record("flavor")
|
|
sql_flavor = flavor_rec.get_flavor_by_id(flavor_id)
|
|
|
|
if not sql_flavor:
|
|
raise NotFoundError(404, "flavor id {} not found".format(
|
|
flavor_id))
|
|
|
|
extra_specs_models = extra_specs.to_db_model()
|
|
existing_region_names = sql_flavor.get_existing_region_names()
|
|
|
|
# remove old extra specs
|
|
sql_flavor.delete_all_extra_specs()
|
|
# calculate default flavor extra
|
|
flavor_wrapper = FlavorWrapper.from_db_model(sql_flavor).to_db_model()
|
|
default_extra_specs = flavor_wrapper.flavor_extra_specs
|
|
|
|
# add default extra specs to user extra specs and add to DB
|
|
extra_specs_models += default_extra_specs
|
|
sql_flavor.add_extra_specs(extra_specs_models)
|
|
|
|
# get exception if there is any from previous action with the database
|
|
datamanager.flush()
|
|
send_to_rds_if_needed(sql_flavor, existing_region_names, "put",
|
|
transaction_id)
|
|
LOG.debug("extra specs updated and sent to rds")
|
|
datamanager.commit()
|
|
|
|
# create return json to wsme
|
|
result = ExtraSpecsWrapper.from_db_model(extra_specs_models)
|
|
except NotFoundError as exp:
|
|
datamanager.rollback()
|
|
LOG.log_exception("flavor id {} not found".format(flavor_id), exp)
|
|
raise
|
|
|
|
except Exception as exp:
|
|
datamanager.rollback()
|
|
LOG.log_exception("failed to update extra specs", exp)
|
|
raise
|
|
finally:
|
|
datamanager.close()
|
|
|
|
return result
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def get_flavor_by_uuid(flavor_uuid):
|
|
DataManager = di.resolver.unpack(get_flavor_by_uuid)
|
|
|
|
datamanager = DataManager()
|
|
try:
|
|
flavor_record = datamanager.get_record('flavor')
|
|
|
|
sql_flavor = flavor_record.get_flavor_by_id(flavor_uuid)
|
|
|
|
if not sql_flavor:
|
|
raise ErrorStatus(
|
|
404, 'flavor id {0} not found'.format(flavor_uuid))
|
|
|
|
flavor_wrapper = get_flavor_status(
|
|
sql_flavor, datamanager.get_session())
|
|
|
|
except Exception as exp:
|
|
LOG.log_exception("Failed to get_flavor_by_uuid", exp)
|
|
raise
|
|
|
|
return flavor_wrapper
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def add_tags(flavor_id, tags, transaction_id):
|
|
DataManager = di.resolver.unpack(add_tags)
|
|
datamanager = DataManager()
|
|
|
|
try:
|
|
LOG.debug("LOGIC - add tags")
|
|
datamanager.begin_transaction()
|
|
|
|
flavor_rec = datamanager.get_record("flavor")
|
|
sql_flavor = flavor_rec.get_flavor_by_id(flavor_id)
|
|
|
|
if not sql_flavor:
|
|
raise NotFoundError(404, 'flavor id {0} not found'.format(
|
|
flavor_id))
|
|
|
|
tags_model = tags.to_db_model()
|
|
sql_flavor.add_tags(tags_model)
|
|
|
|
datamanager.flush()
|
|
datamanager.commit()
|
|
|
|
# create return json to wsme
|
|
result = TagsWrapper.from_db_model(sql_flavor.flavor_tags)
|
|
except NotFoundError as exp:
|
|
datamanager.rollback()
|
|
LOG.log_exception("FlavorLogic - Flavor Not Found", exp)
|
|
raise
|
|
|
|
except Exception as exp:
|
|
datamanager.rollback()
|
|
if "conflicts with persistent instance" in str(exp.args):
|
|
raise ConflictError(
|
|
409, "one or all tags {} already exists".format(tags.tags))
|
|
LOG.log_exception("FlavorLogic - fail to add tags", exp)
|
|
raise
|
|
finally:
|
|
datamanager.close()
|
|
|
|
return result
|
|
|
|
|
|
def get_flavor_status(sql_flavor, session):
|
|
|
|
flavor_wrapper = FlavorWrapper.from_db_model(sql_flavor)
|
|
region_names = [reg.region_name for reg in sql_flavor.flavor_regions]
|
|
|
|
if len(region_names):
|
|
uuid = [sql_flavor.id]
|
|
resource_status_dict = utils.get_resource_status_from_db(
|
|
session, uuid)
|
|
|
|
status_model = resource_status_dict.get(sql_flavor.id)
|
|
update_region_statuses(
|
|
flavor_wrapper.flavor, region_names, status_model)
|
|
else:
|
|
# flavor has no regions
|
|
flavor_wrapper.flavor.status = "no regions"
|
|
|
|
return flavor_wrapper
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def get_flavor_by_uuid_or_name(flavor_uuid_or_name):
|
|
DataManager = di.resolver.unpack(get_flavor_by_uuid_or_name)
|
|
|
|
datamanager = DataManager()
|
|
try:
|
|
flavor_record = datamanager.get_record('flavor')
|
|
|
|
sql_flavor = flavor_record.get_flavor_by_id_or_name(
|
|
flavor_uuid_or_name)
|
|
|
|
if not sql_flavor:
|
|
raise ErrorStatus(
|
|
404,
|
|
'flavor id or name {0} not found'.format(flavor_uuid_or_name))
|
|
|
|
flavor_wrapper = get_flavor_status(
|
|
sql_flavor, datamanager.get_session())
|
|
|
|
except Exception as exp:
|
|
LOG.log_exception("Failed to get_flavor_by_uuid_or_name", exp)
|
|
raise
|
|
finally:
|
|
datamanager.close()
|
|
|
|
return flavor_wrapper
|
|
|
|
|
|
def update_region_statuses(flavor, region_names, status_model):
|
|
# remove the regions comes from database and return the regions which
|
|
# return from rds, because there might be group region there (in the db)
|
|
# and in the response from the rds we will have a list of all regions
|
|
# belong to this group
|
|
flavor.regions[:] = []
|
|
|
|
flavor.status = 'no regions'
|
|
error_status = submitted_status = success_status = 0
|
|
|
|
if status_model and status_model.regions_status:
|
|
# get region status if region in flavor_regions_list
|
|
if region_names:
|
|
for status in status_model.regions_status:
|
|
# check that the region read from RDS is in the
|
|
# flavor_regions_list
|
|
if status.region in region_names:
|
|
flavor.regions.append(
|
|
Region(name=status.region, type="single",
|
|
status=status.status,
|
|
error_message=status.error_msg))
|
|
|
|
flavor.status = status_model.status
|
|
|
|
|
|
@di.dependsOn('data_manager')
|
|
def get_flavor_list_by_params(visibility, region, tenant, series, vm_type,
|
|
vnf_name, starts_with, contains, alias):
|
|
DataManager = di.resolver.unpack(get_flavor_list_by_params)
|
|
|
|
datamanager = DataManager()
|
|
try:
|
|
flavor_record = datamanager.get_record('flavor')
|
|
sql_flavors = flavor_record.get_flavors_by_criteria(
|
|
visibility=visibility,
|
|
region=region,
|
|
tenant=tenant,
|
|
series=series,
|
|
vm_type=vm_type,
|
|
vnf_name=vnf_name,
|
|
starts_with=starts_with,
|
|
contains=contains,
|
|
alias=alias)
|
|
|
|
response = FlavorListFullResponse()
|
|
|
|
if sql_flavors:
|
|
uuids = [sql_flavor.id for sql_flavor in sql_flavors]
|
|
|
|
resource_status_dict = utils.get_resource_status_from_db(
|
|
datamanager.get_session(), uuids)
|
|
|
|
for sql_flavor in sql_flavors:
|
|
flavor_wrapper = FlavorWrapper.from_db_model(sql_flavor)
|
|
region_names = [reg.region_name for reg
|
|
in sql_flavor.flavor_regions]
|
|
|
|
status_model = resource_status_dict.get(sql_flavor.id)
|
|
update_region_statuses(
|
|
flavor_wrapper.flavor, region_names, status_model)
|
|
|
|
response.flavors.append(flavor_wrapper.flavor)
|
|
|
|
except Exception as exp:
|
|
LOG.log_exception("Fail to get_flavor_list_by_params", exp)
|
|
raise
|
|
finally:
|
|
datamanager.close()
|
|
|
|
return response
|
|
|
|
|
|
def calculate_name(flavor):
|
|
|
|
""" calculate_name function returns the ranger flavor_name:
|
|
Ranger flavor name is made up of the following components, each separated
|
|
by a DOT separator:
|
|
- flavor series
|
|
- flavor attributes (cores, ram, disk, swap file, ephemeral disks)
|
|
- flavor options (OPTIONAL)
|
|
|
|
Following is a sample flavor name:
|
|
name = xx.c1r1d1s4e5.i2n0
|
|
|
|
where xx : flavor series name
|
|
c1 : number of cores (or cpu); sample shows vcpu = 1
|
|
r1 : RAM value divided by units of 1024 MB; sample ram = 1024 (in MB)
|
|
d3 : disk value measured in units of GB; sample shows disk = 3
|
|
s4 : (optional) swap disk value divided by units of 1024 MB;
|
|
sample swap value = 4096 (in MB)
|
|
e5 : (optional) ephemeral disk measured in units of GB -
|
|
sample shows ephemeral = 5 (in GB)
|
|
|
|
Anything after the second dot separator are flavor options 'i2'
|
|
and 'n0' - flavor options are OPTIONAL
|
|
"""
|
|
|
|
option_order = ['n0', 'i2', 't0']
|
|
name = "{0}.c{1}r{2}d{3}".format(flavor.flavor.series, flavor.flavor.vcpus,
|
|
int(flavor.flavor.ram) // 1024,
|
|
flavor.flavor.disk)
|
|
|
|
# add swap disk info to flavor name IF provided
|
|
swap = getattr(flavor.flavor, 'swap', 0)
|
|
if swap and int(swap):
|
|
name += '{}{}'.format('s', int(swap) // 1024)
|
|
|
|
# add ephemeral disk info to flavor name IF provided
|
|
ephemeral = getattr(flavor.flavor, 'ephemeral', 0)
|
|
if ephemeral and int(ephemeral):
|
|
name += '{}{}'.format('e', ephemeral)
|
|
|
|
# add the valid option keys to the flavor name
|
|
series_metadata = cfg.CONF['flavor_series_metadata'][flavor.flavor.series]
|
|
|
|
valid_options = [series_metadata[x] for x in
|
|
series_metadata if x.startswith("valid_options_")]
|
|
|
|
options = [n for n in valid_options if n in
|
|
list(flavor.flavor.options.keys()) and
|
|
flavor.flavor.options[n].lower() == 'true']
|
|
|
|
if 'i2' in options and 'n0' not in options:
|
|
options.remove('i2')
|
|
if 't0' in options and flavor.flavor.visibility.lower() != 'private':
|
|
options.remove('t0')
|
|
|
|
if options:
|
|
name += '.'
|
|
for item in option_order:
|
|
if item in options:
|
|
name += item
|
|
|
|
return name
|
|
|
|
|
|
def update_region_actions(flavor_dict, existing_region_names, action="put"):
|
|
if action == "delete":
|
|
set_regions_action(flavor_dict, "delete")
|
|
elif action == "post":
|
|
set_regions_action(flavor_dict, "create")
|
|
else: # put
|
|
for region in flavor_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,
|
|
flavor_dict["regions"]):
|
|
continue
|
|
else:
|
|
flavor_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(flavor_dict, action):
|
|
for region in flavor_dict["regions"]:
|
|
region["action"] = action
|