def _check_and_update_services(storage_ceph_ext): svcs = api_helper.getListFromServices(storage_ceph_ext) # If glance/nova is already a service on other rbd backend, remove it from there check_svcs = [constants.SB_SVC_GLANCE, constants.SB_SVC_NOVA] for s in check_svcs: if s in svcs: sb_list = pecan.request.dbapi.storage_backend_get_list() if sb_list: for sb in sb_list: if (sb.uuid != storage_ceph_ext.get("uuid", None) and sb.backend in [ constants.SB_TYPE_CEPH, constants.SB_TYPE_CEPH_EXTERNAL ] and s in sb.get('services')): services = api_helper.getListFromServices(sb) services.remove(s) cap = sb.capabilities for k in HIERA_DATA[s]: cap.pop(k, None) values = { 'services': ','.join(services), 'capabilities': cap, } pecan.request.dbapi.storage_backend_update( sb.uuid, values)
def _get_options_string(storage_lvm): opt_str = "" caps = storage_lvm.get('capabilities', {}) services = api_helper.getListFromServices(storage_lvm) # get the backend parameters backend_dict = caps.get("backend", {}) be_str = "" for key in backend_dict: be_str += "\t%s: %s\n" % (key, backend_dict[key]) # Only show the backend values if any are present if len(be_str) > 0: opt_str = "Backend:\n%s" % be_str # Get any supported service parameters for svc in constants.SB_LVM_SVCS_SUPPORTED: svc_dict = caps.get(svc, None) if svc_dict and svc in services: svc_str = "" for key in svc_dict: svc_str += "\t%s: %s\n" % (key, svc_dict.get(key, None)) if len(svc_str) > 0: opt_str += "%s:\n%s" % (svc.title(), svc_str) if len(opt_str) > 0: opt_str = "Applying the following options:\n\n" + opt_str return opt_str
def _check_backend_lvm(req, storage_lvm, confirmed=False): # check for the backend parameters capabilities = storage_lvm.get('capabilities', {}) # Discover the latest hiera_data for the supported service _discover_and_validate_backend_hiera_data(capabilities) for k in HIERA_DATA['backend']: if not capabilities.get(k, None): raise wsme.exc.ClientSideError("Missing required backend " "parameter: %s" % k) # go through the service list and validate req_services = api_helper.getListFromServices(storage_lvm) # Cinder is mandatory for lvm backend if constants.SB_SVC_CINDER not in req_services: raise wsme.exc.ClientSideError( "Service %s is mandatory for " "the %s backend." % (constants.SB_SVC_CINDER, constants.SB_TYPE_LVM)) for svc in req_services: if svc not in constants.SB_LVM_SVCS_SUPPORTED: raise wsme.exc.ClientSideError( "Service %s is not supported for the" " %s backend" % (svc, constants.SB_TYPE_LVM)) # Service is valid. Discover the latest hiera_data for the supported service discover_func = eval('_discover_and_validate_' + svc + '_hiera_data') discover_func(capabilities) # Service is valid. Check the params for k in HIERA_DATA[svc]: if not capabilities.get(k, None): raise wsme.exc.ClientSideError("Missing required %s service " "parameter: %s" % (svc, k)) # Update based on any discovered values storage_lvm['capabilities'] = capabilities # TODO (rchurch): Put this back in some form for delivery OR move to specific # backend checks to limit operations based on the backend # # if req == constants.SB_API_OP_MODIFY or req == constants.SB_API_OP_DELETE: # raise wsme.exc.ClientSideError("API Operation %s is not supported for " # "the %s backend" % # (req, constants.SB_TYPE_LVM)) # Check for confirmation if not confirmed: _options_str = _get_options_string(storage_lvm) raise wsme.exc.ClientSideError( _("%s\nWARNING : THIS OPERATION IS NOT REVERSIBLE AND CANNOT BE CANCELLED. \n" "\nBy confirming this operation, the LVM backend will be created.\n\n" "Please refer to the system admin guide for minimum spec for LVM\n" "storage. Set the 'confirmed' field to execute this operation\n" "for the %s backend.") % (_options_str, constants.SB_TYPE_LVM))
def _apply_backend_changes(op, sb_obj): if op == constants.SB_API_OP_CREATE: services = api_helper.getListFromServices(sb_obj.as_dict()) if constants.SB_SVC_CINDER in services: # Services are specified: Update backend + service actions api_helper.enable_backend( sb_obj, pecan.request.rpcapi.update_lvm_cinder_config) elif op == constants.SB_API_OP_MODIFY: if sb_obj.state == constants.SB_STATE_CONFIG_ERR: api_helper.enable_backend( sb_obj, pecan.request.rpcapi.update_lvm_cinder_config) elif op == constants.SB_API_OP_DELETE: pass
def _apply_backend_changes(op, sb_obj): if op == constants.SB_API_OP_CREATE: # This is a DB only change => Set the state to configured pecan.request.dbapi.storage_ceph_rook_update( sb_obj.uuid, {'state': constants.SB_STATE_CONFIGURED}) services = api_helper.getListFromServices(sb_obj.as_dict()) pecan.request.rpcapi.update_ceph_rook_config(pecan.request.context, sb_obj.get('uuid'), services) elif op == constants.SB_API_OP_MODIFY: pass elif op == constants.SB_API_OP_DELETE: pass
def _check_backend_file(req, storage_file, confirmed=False): # check for the backend parameters capabilities = storage_file.get('capabilities', {}) # Discover the latest hiera_data for the supported service _discover_and_validate_backend_hiera_data(capabilities) for k in HIERA_DATA['backend']: if not capabilities.get(k, None): raise wsme.exc.ClientSideError("Missing required backend " "parameter: %s" % k) # go through the service list and validate req_services = api_helper.getListFromServices(storage_file) for svc in req_services: if svc not in constants.SB_FILE_SVCS_SUPPORTED: raise wsme.exc.ClientSideError( "Service %s is not supported for the" " %s backend" % (svc, constants.SB_TYPE_FILE)) # Service is valid. Discover the latest hiera_data for the supported service discover_func = eval('_discover_and_validate_' + svc + '_hiera_data') discover_func(capabilities) # Service is valid. Check the params for k in HIERA_DATA[svc]: if not capabilities.get(k, None): raise wsme.exc.ClientSideError("Missing required %s service " "parameter: %s" % (svc, k)) # Update based on any discovered values storage_file['capabilities'] = capabilities # TODO (rchurch): Put this back # if req == constants.SB_API_OP_MODIFY or req == constants.SB_API_OP_DELETE: # raise wsme.exc.ClientSideError("API Operation %s is not supported for " # "the %s backend" % # (req, constants.SB_TYPE_FILE)) # Check for confirmation if not confirmed: _options_str = _get_options_string(storage_file) raise wsme.exc.ClientSideError( _("%s\nWARNING : THIS OPERATION IS NOT REVERSIBLE AND CANNOT BE " "CANCELLED. \n\nPlease set the 'confirmed' field to execute " "this operation for the %s backend.") % (_options_str, constants.SB_TYPE_FILE))
def _check_backend_external(req, storage_external, confirmed=False): # check if it is running on secondary region system = pecan.request.dbapi.isystem_get_one() if system and system.capabilities.get('region_config') is not True: raise wsme.exc.ClientSideError("External backend can only be added on " "secondary region.") # check for the backend parameters capabilities = storage_external.get('capabilities', {}) # Discover the latest hiera_data for the supported service _discover_and_validate_backend_hiera_data(capabilities) for k in HIERA_DATA['backend']: if not capabilities.get(k, None): raise wsme.exc.ClientSideError("Missing required backend " "parameter: %s" % k) # go through the service list and validate req_services = api_helper.getListFromServices(storage_external) for svc in req_services: if svc not in constants.SB_EXTERNAL_SVCS_SUPPORTED: raise wsme.exc.ClientSideError( "Service %s is not supported for the" " %s backend" % (svc, constants.SB_TYPE_EXTERNAL)) # Service is valid. Discover the latest hiera_data for the supported service discover_func = eval('_discover_and_validate_' + svc + '_hiera_data') discover_func(capabilities) # Service is valid. Check the params for k in HIERA_DATA[svc]: if not capabilities.get(k, None): raise wsme.exc.ClientSideError("Missing required %s service " "parameter: %s" % (svc, k)) # Update based on any discovered values storage_external['capabilities'] = capabilities # Check for confirmation if not confirmed: _options_str = _get_options_string(storage_external) raise wsme.exc.ClientSideError( _("%s\nWARNING : THIS OPERATION IS NOT REVERSIBLE AND CANNOT BE " "CANCELLED. \n\nPlease set the 'confirmed' field to execute " "this operation for the %s backend.") % (_options_str, constants.SB_TYPE_EXTERNAL))
def _check_backend_ceph_rook(req, storage_ceph_rook, confirmed=False): # check for the backend parameters capabilities = storage_ceph_rook.get('capabilities', {}) # Discover the latest hiera_data for the supported service _discover_and_validate_backend_hiera_data(capabilities) for k in HIERA_DATA['backend']: if not capabilities.get(k, None): raise wsme.exc.ClientSideError("Missing required backend " "parameter: %s" % k) # go through the service list and validate req_services = api_helper.getListFromServices(storage_ceph_rook) for svc in req_services: if svc not in constants.SB_CEPH_ROOK_SVCS_SUPPORTED: raise wsme.exc.ClientSideError( "Service %s is not supported for the" " %s backend" % (svc, constants.SB_TYPE_FILE)) # Service is valid. Discover the latest hiera_data for the supported service discover_func = eval('_discover_and_validate_' + svc + '_hiera_data') discover_func(capabilities) # Service is valid. Check the params for k in HIERA_DATA[svc]: if not capabilities.get(k, None): raise wsme.exc.ClientSideError("Missing required %s service " "parameter: %s" % (svc, k)) # Update based on any discovered values storage_ceph_rook['capabilities'] = capabilities storage_ceph_rook['state'] = constants.SB_STATE_CONFIGURED storage_ceph_rook['task'] = constants.SB_TASK_NONE # Check for confirmation if not confirmed: _options_str = _get_options_string(storage_ceph_rook) raise wsme.exc.ClientSideError( _("%s\nWARNING : THIS OPERATION IS NOT REVERSIBLE AND CANNOT BE " "CANCELLED. \n\nPlease set the 'confirmed' field to execute " "this operation for the %s backend.") % (_options_str, constants.SB_TYPE_CEPH_ROOK))
def _apply_ceph_external_backend_changes(op, sb_obj, orig_sb_obj=None): if ((op == constants.SB_API_OP_CREATE) or (op == constants.SB_API_OP_MODIFY and sb_obj.get('ceph_conf') != orig_sb_obj.get('ceph_conf'))): values = {'task': constants.SB_TASK_APPLY_CONFIG_FILE} pecan.request.dbapi.storage_ceph_external_update(sb_obj.get('uuid'), values) try: pecan.request.rpcapi.distribute_ceph_external_config( pecan.request.context, sb_obj.get('ceph_conf')) except Exception as e: LOG.exception(e) msg = _("Failed to distribute ceph config file.") raise wsme.exc.ClientSideError(msg) services = api_helper.getListFromServices(sb_obj) pecan.request.rpcapi.update_ceph_external_config( pecan.request.context, sb_obj.get('uuid'), services) elif op == constants.SB_API_OP_DELETE: msg = _("Delete a Ceph external backend is not supported currently.") raise wsme.exc.ClientSideError(msg) else: # Compare ceph pools caps = sb_obj.get('capabilities', {}) orig_caps = orig_sb_obj.get('capabilities', {}) services = [] for svc in constants.SB_CEPH_EXTERNAL_SVCS_SUPPORTED: for k in HIERA_DATA[svc]: if caps.get(k, None) != orig_caps.get(k, None): services.append(svc) pecan.request.rpcapi.update_ceph_external_config( pecan.request.context, sb_obj.get('uuid'), services)
def _apply_backend_changes(op, sb_obj): if op in [constants.SB_API_OP_CREATE, constants.SB_API_OP_MODIFY]: services = api_helper.getListFromServices(sb_obj.as_dict()) if constants.SB_SVC_CINDER in services: # Services are specified: Update backend + service actions api_helper.enable_backend( sb_obj, pecan.request.rpcapi.update_external_cinder_config) else: # If no service is specified or glance or swift is the only service # this is a DB only change => Set the state to configured pecan.request.dbapi.storage_external_update( sb_obj.uuid, {'state': constants.SB_STATE_CONFIGURED}) # update shared_services s_s = utils.get_shared_services() shared_services = [] if s_s is None else ast.literal_eval(s_s) if services is not None: for s in services: if (s == constants.SB_SVC_CINDER and constants.SERVICE_TYPE_VOLUME not in shared_services): shared_services.append(constants.SERVICE_TYPE_VOLUME) if (s == constants.SB_SVC_GLANCE and constants.SERVICE_TYPE_IMAGE not in shared_services): shared_services.append(constants.SERVICE_TYPE_IMAGE) system = pecan.request.dbapi.isystem_get_one() system.capabilities['shared_services'] = str(shared_services) pecan.request.dbapi.isystem_update( system.uuid, {'capabilities': system.capabilities}) elif op == constants.SB_API_OP_DELETE: pass
def _check_backend_ceph_external(storage_ceph_ext): """Prechecks for adding an external Ceph backend.""" # go through the service list and validate svcs = api_helper.getListFromServices(storage_ceph_ext) for svc in svcs: if svc not in constants.SB_CEPH_EXTERNAL_SVCS_SUPPORTED: raise wsme.exc.ClientSideError( "Service %s is not supported for the" " %s backend" % (svc, constants.SB_TYPE_CEPH_EXTERNAL)) # check for the backend parameters capabilities = storage_ceph_ext.get('capabilities', {}) # Discover the latest hiera_data for the supported service _discover_and_validate_backend_hiera_data(capabilities) for svc in svcs: for k in HIERA_DATA[svc]: if not capabilities.get(k, None): raise wsme.exc.ClientSideError("Missing required %s service " "parameter: %s" % (svc, k)) for svc in constants.SB_CEPH_EXTERNAL_SVCS_SUPPORTED: for k in HIERA_DATA[svc]: if capabilities.get(k, None) and svc not in svcs: raise wsme.exc.ClientSideError( "Missing required service %s for " "parameter: %s" % (svc, k)) valid_pars = [i for sublist in HIERA_DATA.values() for i in sublist] if len(set(capabilities.keys()) - set(valid_pars)) > 0: raise wsme.exc.ClientSideError( "Parameter %s is not valid " % list(set(capabilities.keys()) - set(valid_pars))) # Check the Ceph configuration file ceph_conf_file = storage_ceph_ext.get('ceph_conf') if ceph_conf_file: if (ceph_conf_file == constants.SB_TYPE_CEPH_CONF_FILENAME): msg = _("The %s name is reserved for the internally managed Ceph " "cluster.\nPlease use a different name and try again." % constants.SB_TYPE_CEPH_CONF_FILENAME) raise wsme.exc.ClientSideError(msg) else: # Raise error if the Ceph configuration file is not provided. msg = _("A Ceph configuration file must be provided for provisioning " "an external Ceph cluster.") raise wsme.exc.ClientSideError(msg) # If a conf file is specified, make sure the backend's name is not already # used / one of the default names for other backends. if ceph_conf_file: backend_name = storage_ceph_ext.get('name') backend_list = pecan.request.dbapi.storage_backend_get_list() for backend in backend_list: if backend.uuid != storage_ceph_ext.get("uuid", None): if backend_name in constants.SB_DEFAULT_NAMES.values(): msg = _( "The \"%s\" name is reserved for internally managed " "backends." % backend_name) raise wsme.exc.ClientSideError(msg) if backend.name == backend_name: msg = _( "The \"%s\" name is already used for another backend." % backend_name) raise wsme.exc.ClientSideError(msg)