def delete(self, subcloud_ref): """Delete a subcloud. :param subcloud_ref: ID or name of subcloud to delete. """ context = restcomm.extract_context_from_environ() subcloud = None if subcloud_ref.isdigit(): # Look up subcloud as an ID try: subcloud = db_api.subcloud_get(context, subcloud_ref) except exceptions.SubcloudNotFound: pecan.abort(404, _('Subcloud not found')) else: # Look up subcloud by name try: subcloud = db_api.subcloud_get_by_name(context, subcloud_ref) except exceptions.SubcloudNameNotFound: pecan.abort(404, _('Subcloud not found')) subcloud_id = subcloud.id try: # Ask dcmanager-manager to delete the subcloud. # It will do all the real work... return self.rpc_client.delete_subcloud(context, subcloud_id) except RemoteError as e: pecan.abort(422, e.value) except Exception as e: LOG.exception(e) pecan.abort(500, _('Unable to delete subcloud'))
def patch(self, subcloud_ref=None): """Update a subcloud. :param subcloud_ref: ID or name of subcloud to update """ context = restcomm.extract_context_from_environ() subcloud = None if subcloud_ref is None: pecan.abort(400, _('Subcloud ID required')) payload = eval(request.body) if not payload: pecan.abort(400, _('Body required')) if subcloud_ref.isdigit(): # Look up subcloud as an ID try: subcloud = db_api.subcloud_get(context, subcloud_ref) except exceptions.SubcloudNotFound: pecan.abort(404, _('Subcloud not found')) else: # Look up subcloud by name try: subcloud = db_api.subcloud_get_by_name(context, subcloud_ref) except exceptions.SubcloudNameNotFound: pecan.abort(404, _('Subcloud not found')) subcloud_id = subcloud.id management_state = payload.get('management-state') description = payload.get('description') location = payload.get('location') if not (management_state or description or location): pecan.abort(400, _('nothing to update')) # Syntax checking if management_state and \ management_state not in [consts.MANAGEMENT_UNMANAGED, consts.MANAGEMENT_MANAGED]: pecan.abort(400, _('Invalid management-state')) try: # Inform dcmanager-manager that subcloud has been updated. # It will do all the real work... subcloud = self.rpc_client.update_subcloud( context, subcloud_id, management_state=management_state, description=description, location=location) return subcloud except RemoteError as e: pecan.abort(422, e.value) except Exception as e: # additional exceptions. LOG.exception(e) pecan.abort(500, _('Unable to update subcloud'))
def get(self, subcloud_ref=None): """Get details about software update options. :param subcloud: name or id of subcloud (optional) """ context = restcomm.extract_context_from_environ() if subcloud_ref is None: # List of all subcloud options requested. # Prepend the all clouds default options to the result. result = dict() result['sw-update-options'] = list() default_sw_update_opts_dict = utils.get_sw_update_opts(context) result['sw-update-options'].append(default_sw_update_opts_dict) subclouds = db_api.sw_update_opts_get_all_plus_subcloud_info( context) for subcloud, sw_update_opts in subclouds: if sw_update_opts: result['sw-update-options'].append( db_api.sw_update_opts_w_name_db_model_to_dict( sw_update_opts, subcloud.name)) return result elif subcloud_ref == consts.DEFAULT_REGION_NAME: # Default options requested, guaranteed to succeed return utils.get_sw_update_opts(context) else: # Specific subcloud options requested if subcloud_ref.isdigit(): # Look up subcloud as an ID try: subcloud = db_api.subcloud_get(context, subcloud_ref) except exceptions.SubcloudNotFound: pecan.abort(404, _('Subcloud not found')) else: # Look up subcloud by name try: subcloud = db_api.subcloud_get_by_name( context, subcloud_ref) except exceptions.SubcloudNameNotFound: pecan.abort(404, _('Subcloud not found')) try: return utils.get_sw_update_opts(context, subcloud_id=subcloud.id) except Exception as e: pecan.abort(404, _('%s') % e)
def get(self, steps=None, cloud_name=None): """Get details about software update strategy. :param steps: get the steps for this strategy (optional) :param cloud_name: name of cloud (optional) """ context = restcomm.extract_context_from_environ() if steps is None: # Strategy requested strategy = None try: strategy = db_api.sw_update_strategy_get(context) except exceptions.NotFound: pecan.abort(404, _('Strategy not found')) strategy_dict = db_api.sw_update_strategy_db_model_to_dict( strategy) return strategy_dict elif steps == "steps": # Steps for the strategy requested if cloud_name is None: # List of steps requested result = dict() result['strategy-steps'] = list() strategy_steps = db_api.strategy_step_get_all(context) for strategy_step in strategy_steps: result['strategy-steps'].append( db_api.strategy_step_db_model_to_dict(strategy_step)) return result else: # Single step requested strategy_step = None if cloud_name == consts.SYSTEM_CONTROLLER_NAME: # The system controller step does not map to a subcloud, # so has no name. try: strategy_step = db_api.strategy_step_get(context, None) except exceptions.StrategyStepNotFound: pecan.abort(404, _('Strategy step not found')) else: try: strategy_step = db_api.strategy_step_get_by_name( context, cloud_name) except exceptions.StrategyStepNameNotFound: pecan.abort(404, _('Strategy step not found')) strategy_step_dict = db_api.strategy_step_db_model_to_dict( strategy_step) return strategy_step_dict
def delete(self): """Delete the software update strategy.""" context = restcomm.extract_context_from_environ() try: # Ask dcmanager-manager to delete the strategy. # It will do all the real work... return self.rpc_client.delete_sw_update_strategy(context) except RemoteError as e: pecan.abort(422, e.value) except Exception as e: LOG.exception(e) pecan.abort(500, _('Unable to delete strategy'))
def _get_alarm_aggregates(self): summary = [] context = restcomm.extract_context_from_environ() alarms = self.dcorch_rpc_client.get_alarm_summary(context) for alarm in alarms: alarm_dict = { 'region_name': alarm['region_name'], 'uuid': alarm['uuid'], 'critical_alarms': alarm['critical_alarms'], 'major_alarms': alarm['major_alarms'], 'minor_alarms': alarm['minor_alarms'], 'warnings': alarm['warnings'], 'cloud_status': alarm['cloud_status'] } summary.append(alarm_dict) return {'alarm_summary': summary}
def delete(self, subcloud_ref): """Delete the software update options.""" context = restcomm.extract_context_from_environ() if subcloud_ref == consts.DEFAULT_REGION_NAME: # Delete defaults. # Note by deleting these, the next get will repopulate with # the global constants. try: db_api.sw_update_opts_default_destroy(context) except Exception: return else: if subcloud_ref.isdigit(): # Look up subcloud as an ID try: subcloud = db_api.subcloud_get(context, subcloud_ref) except exceptions.SubcloudNotFound: pecan.abort(404, _('Subcloud not found')) else: # Look up subcloud by name try: subcloud = db_api.subcloud_get_by_name( context, subcloud_ref) except exceptions.SubcloudNameNotFound: pecan.abort(404, _('Subcloud not found')) # Delete the subcloud specific options if db_api.sw_update_opts_get(context, subcloud.id): db_api.sw_update_opts_destroy(context, subcloud.id) else: pecan.abort(404, _('Subcloud patch options not found'))
def post(self, subcloud_ref=None, qualifier=None): """Create a new subcloud. :param subcloud_ref: ID of or name subcloud (only used when generating config) :param qualifier: if 'config', returns the config INI file for the subcloud """ context = restcomm.extract_context_from_environ() if subcloud_ref is None: payload = eval(request.body) if not payload: pecan.abort(400, _('Body required')) name = payload.get('name') if not name: pecan.abort(400, _('name required')) management_subnet = payload.get('management-subnet') if not management_subnet: pecan.abort(400, _('management-subnet required')) management_start_ip = payload.get('management-start-ip') if not management_start_ip: pecan.abort(400, _('management-start-ip required')) management_end_ip = payload.get('management-end-ip') if not management_end_ip: pecan.abort(400, _('management-end-ip required')) management_gateway_ip = payload.get('management-gateway-ip') if not management_gateway_ip: pecan.abort(400, _('management-gateway-ip required')) systemcontroller_gateway_ip = \ payload.get('systemcontroller-gateway-ip') if not systemcontroller_gateway_ip: pecan.abort(400, _('systemcontroller-gateway-ip required')) self._validate_subcloud_config(context, name, management_subnet, management_start_ip, management_end_ip, management_gateway_ip, systemcontroller_gateway_ip) try: # Ask dcmanager-manager to add the subcloud. # It will do all the real work... return self.rpc_client.add_subcloud(context, payload) except RemoteError as e: pecan.abort(422, e.value) except Exception as e: LOG.exception(e) pecan.abort(500, _('Unable to create subcloud')) elif qualifier: if qualifier == 'config': subcloud = None if subcloud_ref.isdigit(): # Look up subcloud as an ID try: subcloud = db_api.subcloud_get(context, subcloud_ref) except exceptions.SubcloudNotFound: pecan.abort(404, _('Subcloud not found')) else: # Look up subcloud by name try: subcloud = db_api.subcloud_get_by_name( context, subcloud_ref) except exceptions.SubcloudNameNotFound: pecan.abort(404, _('Subcloud not found')) payload = dict() if request.body: payload = eval(request.body) config_file = self._create_subcloud_config_file( context, subcloud, payload) result = dict() result['config'] = config_file return result else: pecan.abort(400, _('Invalid request')) else: pecan.abort(400, _('Invalid request'))
def get(self, subcloud_ref=None, qualifier=None): """Get details about subcloud. :param subcloud_ref: ID or name of subcloud """ context = restcomm.extract_context_from_environ() if subcloud_ref is None: # List of subclouds requested subclouds = db_api.subcloud_get_all_with_status(context) result = dict() result['subclouds'] = [] first_time = True subcloud_list = [] subcloud_status_list = [] # We get back a subcloud, subcloud_status pair for every # subcloud_status entry corresponding to a subcloud. (Subcloud # info repeats) # Aggregate all the sync status for each of the # endpoints per subcloud into an overall sync status for subcloud, subcloud_status in subclouds: subcloud_dict = db_api.subcloud_db_model_to_dict(subcloud) subcloud_status_dict = db_api.subcloud_status_db_model_to_dict( subcloud_status) subcloud_dict.update(subcloud_status_dict) if not first_time: if subcloud_list[-1]['id'] == subcloud_dict['id']: # We have a match for this subcloud id already, # check if we have a same sync_status if subcloud_list[-1][consts.SYNC_STATUS] != \ subcloud_dict[consts.SYNC_STATUS]: subcloud_list[-1][consts.SYNC_STATUS] = \ consts.SYNC_STATUS_OUT_OF_SYNC if subcloud_status: subcloud_status_list.append( db_api. subcloud_endpoint_status_db_model_to_dict( # noqa subcloud_status)) subcloud_list[-1][ consts.ENDPOINT_SYNC_STATUS] = subcloud_status_list else: subcloud_status_list = [] if subcloud_status: subcloud_status_list.append( db_api. subcloud_endpoint_status_db_model_to_dict( # noqa subcloud_status)) subcloud_list.append(subcloud_dict) else: if subcloud_status: subcloud_status_list.append( db_api.subcloud_endpoint_status_db_model_to_dict( subcloud_status)) subcloud_list.append(subcloud_dict) first_time = False for s in subcloud_list: result['subclouds'].append(s) return result else: # Single subcloud requested subcloud = None subcloud_dict = dict() subcloud_status_list = [] endpoint_sync_dict = dict() if subcloud_ref.isdigit(): # Look up subcloud as an ID try: subcloud = db_api.subcloud_get(context, subcloud_ref) except exceptions.SubcloudNotFound: pecan.abort(404, _('Subcloud not found')) else: # Look up subcloud by name try: subcloud = db_api.subcloud_get_by_name( context, subcloud_ref) except exceptions.SubcloudNameNotFound: pecan.abort(404, _('Subcloud not found')) subcloud_id = subcloud.id if qualifier: # Configuration for this subcloud requested. # Encrypt before sending. if qualifier == 'config': result = dict() user_list = self._get_subcloud_users() # Use a hash of the subcloud name + management subnet # as the encryption key hashstring = subcloud.name + subcloud.management_subnet h = MD5.new() h.update(hashstring) encryption_key = h.hexdigest() user_list_string = json.dumps(user_list) user_list_encrypted = crypt.urlsafe_encrypt( encryption_key, user_list_string) result['users'] = user_list_encrypted return result else: pecan.abort(400, _('Invalid request')) else: # Data for this subcloud requested # Build up and append a dictionary of the endpoints # sync status to the result. for subcloud, subcloud_status in db_api. \ subcloud_get_with_status(context, subcloud_id): subcloud_dict = db_api.subcloud_db_model_to_dict(subcloud) # may be empty subcloud_status entry, account for this if subcloud_status: subcloud_status_list.append( db_api.subcloud_endpoint_status_db_model_to_dict( subcloud_status)) endpoint_sync_dict = { consts.ENDPOINT_SYNC_STATUS: subcloud_status_list } subcloud_dict.update(endpoint_sync_dict) return subcloud_dict
def post(self, subcloud_ref=None): """Update or create sw update options. :param subcloud: name or id of subcloud (optional) """ # Note creating or updating subcloud specific options require # setting all options. context = restcomm.extract_context_from_environ() payload = eval(request.body) if not payload: pecan.abort(400, _('Body required')) if subcloud_ref == consts.DEFAULT_REGION_NAME: # update default options subcloud_name = consts.SW_UPDATE_DEFAULT_TITLE if db_api.sw_update_opts_default_get(context): # entry already in db, update it. try: sw_update_opts_ref = db_api.sw_update_opts_default_update( context, payload['storage-apply-type'], payload['compute-apply-type'], payload['max-parallel-computes'], payload['alarm-restriction-type'], payload['default-instance-action']) except Exception as e: LOG.exception(e) raise e else: # no entry in db, create one. try: sw_update_opts_ref = db_api.sw_update_opts_default_create( context, payload['storage-apply-type'], payload['compute-apply-type'], payload['max-parallel-computes'], payload['alarm-restriction-type'], payload['default-instance-action']) except Exception as e: LOG.exception(e) raise e else: # update subcloud options if subcloud_ref.isdigit(): # Look up subcloud as an ID try: subcloud = db_api.subcloud_get(context, subcloud_ref) except exceptions.SubcloudNotFound: pecan.abort(404, _('Subcloud not found')) subcloud_name = subcloud.name else: # Look up subcloud by name try: subcloud = db_api.subcloud_get_by_name( context, subcloud_ref) except exceptions.SubcloudNameNotFound: pecan.abort(404, _('Subcloud not found')) subcloud_name = subcloud_ref sw_update_opts = db_api.sw_update_opts_get(context, subcloud.id) if sw_update_opts is None: sw_update_opts_ref = db_api.sw_update_opts_create( context, subcloud.id, payload['storage-apply-type'], payload['compute-apply-type'], payload['max-parallel-computes'], payload['alarm-restriction-type'], payload['default-instance-action']) else: # a row is present in table, update sw_update_opts_ref = db_api.sw_update_opts_update( context, subcloud.id, payload['storage-apply-type'], payload['compute-apply-type'], payload['max-parallel-computes'], payload['alarm-restriction-type'], payload['default-instance-action']) return db_api.sw_update_opts_w_name_db_model_to_dict( sw_update_opts_ref, subcloud_name)
def post(self, actions=None): """Create a new software update strategy.""" context = restcomm.extract_context_from_environ() payload = eval(request.body) if not payload: pecan.abort(400, _('Body required')) if actions is None: # Validate any options that were supplied strategy_type = payload.get('type') if not strategy_type: pecan.abort(400, _('type required')) if strategy_type not in consts.SW_UPDATE_TYPE_PATCH: pecan.abort(400, _('type invalid')) subcloud_apply_type = payload.get('subcloud-apply-type') if subcloud_apply_type is not None: if subcloud_apply_type not in [ consts.SUBCLOUD_APPLY_TYPE_PARALLEL, consts.SUBCLOUD_APPLY_TYPE_SERIAL ]: pecan.abort(400, _('subcloud-apply-type invalid')) max_parallel_subclouds_str = payload.get('max-parallel-subclouds') if max_parallel_subclouds_str is not None: max_parallel_subclouds = None try: max_parallel_subclouds = int(max_parallel_subclouds_str) except ValueError: pecan.abort(400, _('max-parallel-subclouds invalid')) # TODO(Bart): Decide on a maximum if max_parallel_subclouds < 1 or max_parallel_subclouds > 100: pecan.abort(400, _('max-parallel-subclouds invalid')) stop_on_failure = payload.get('stop-on-failure') if stop_on_failure is not None: if stop_on_failure not in ["true", "false"]: pecan.abort(400, _('stop-on-failure invalid')) try: # Ask dcmanager-manager to create the strategy. # It will do all the real work... return self.rpc_client.create_sw_update_strategy( context, payload) except RemoteError as e: pecan.abort(422, e.value) except Exception as e: LOG.exception(e) pecan.abort(500, _('Unable to create strategy')) elif actions == 'actions': # Apply or abort a strategy action = payload.get('action') if not action: pecan.abort(400, _('action required')) if action == consts.SW_UPDATE_ACTION_APPLY: try: # Ask dcmanager-manager to apply the strategy. # It will do all the real work... return self.rpc_client.apply_sw_update_strategy(context) except RemoteError as e: pecan.abort(422, e.value) except Exception as e: LOG.exception(e) pecan.abort(500, _('Unable to apply strategy')) elif action == consts.SW_UPDATE_ACTION_ABORT: try: # Ask dcmanager-manager to abort the strategy. # It will do all the real work... return self.rpc_client.abort_sw_update_strategy(context) except RemoteError as e: pecan.abort(422, e.value) except Exception as e: LOG.exception(e) pecan.abort(500, _('Unable to abort strategy'))