def _run(self, csa: CloudServerAction) -> Optional[str]: # # Mark the action as "running" # csa.status = CloudServerAction.STATUS_PROCESSING self._store.save(csa) # # Get the resource adapter # parts = csa.cloudserver_id.split(":") if len(parts) == 1: msg = ("Cloud server ID does not contain resource adapter " "prefix, skipping: {}".format(csa.cloudserver_id)) logger.warning(msg) return msg ra_name = parts.pop(0) ra = get_api(ra_name) ra.session = self._sess logger.info('Found resource adapter: {}'.format(ra.__adaptername__)) # # Get the cloud connector profile ID # ccp_id = csa.cloudconnectorprofile_id if not ccp_id: ccp_id = DEFAULT_CONFIGURATION_PROFILE_NAME # # Get the action method from the resource adapter instance. Supported # actions are any methods on the ResourceAdapter instance that have # the method name cloudserveraction_<action-name> # action_name = "cloudserveraction_{}".format(csa.action) action = getattr(ra, action_name) if not action: raise Exception('Action not supported: {}'.format(csa.action)) # # Get any additional action parameters # if csa.action_params: if not isinstance(csa.action_params, dict): raise Exception("Invalid action_params: {}".format( csa.action_params)) params = csa.action_params else: params = {} # # Run the action! # action(ccp_id, csa.cloudserver_id, **params) # # Attempt a local delete, if possible # if csa.action == "delete": self._local_delete(ra_name, ccp_id, csa.cloudserver_id)
def __getResourceAdapter(self, hardwareProfile: HardwareProfileModel): """ Raises: OperationFailed """ if not hardwareProfile.resourceadapter: raise OperationFailed( 'Hardware profile [%s] does not have an associated' ' resource adapter' % (hardwareProfile.name)) return resourceAdapterFactory.get_api( hardwareProfile.resourceadapter.name) \ if hardwareProfile.resourceadapter else None
def __get_resource_adapter(self, session: Session, hardwareProfile: HardwareProfileModel): """ Raises: OperationFailed """ if not hardwareProfile.resourceadapter: raise OperationFailed( 'Hardware profile [%s] does not have an associated' ' resource adapter' % (hardwareProfile.name)) adapter = resourceAdapterFactory.get_api( hardwareProfile.resourceadapter.name) adapter.session = session return adapter
def _get_resource_adapter(self, sess: Session, node_id: str) -> ResourceAdapter: node_store = NodeStoreManager.get() node = node_store.get(node_id) # # Lookup the hardware profile for the node # hwp_store = HardwareProfileStoreManager.get() hwp = hwp_store.get(node.hardwareprofile_id) # # Lookup the resource adapter for the hardware profile # ra_handler = ResourceAdaptersDbHandler() for db_ra in ra_handler.getResourceAdapterList(sess): if db_ra.id == int(hwp.resourceadapter_id): # # Get a instantiated ResourceAdapter instance # return get_api(db_ra.name) raise Exception('Resource adapter not found with ID: %s', hwp.rsourceadapter_id)
def __getResourceAdapter(self, session: Session, hardwareProfile: HardwareProfileModel) \ -> Optional[ResourceAdapter]: """ Raises: OperationFailed """ if not hardwareProfile.resourceadapter: raise OperationFailed( 'Hardware profile [%s] does not have an associated' ' resource adapter' % (hardwareProfile.name)) adapter = resourceAdapterFactory.get_api( hardwareProfile.resourceadapter.name) \ if hardwareProfile.resourceadapter else None if not adapter: return None adapter.session = session return adapter
async def __poller(self, queue, tasks) -> NoReturn: resource_adapter = get_api('AWS') while not self.__done: if self.__next_poll < time.time(): self.logger.debug('Polling spot instance requests') results = self.metadata_ws_api.list() resource_adapter.session = self.__dbm.openSession() resource_adapter_cfgs = {} try: for result in results: if not result['key'].startswith('sir-'): # ignore any unrelated entries self.logger.debug('Ignoring metadata key [%s]', result['key']) continue with await self.__bad_request_lock: if result['key'] in self.__bad_requests: self.logger.warning( 'Invalid spot instance request [%s] will not be' ' queued', result['key']) continue # Parse the embedded value to get the corresponding # resource adapter configuration value = json.loads(result['value']) # Store the request ID in the value. This is used by the handlers later on. value['spot_instance_request_id'] = result['key'] resource_adapter_cfg = value[ 'resource_adapter_configuration'] # Cache resource adapter configurations. # First check if this one has been cached if not resource_adapter_cfg in resource_adapter_cfgs: self.logger.debug( 'Loading adapter configuration: [%s]', resource_adapter_cfg) # Get the the configuration for the spot instance request config = resource_adapter.get_config( resource_adapter_cfg) # Save the fields that we may need for other requests in this loop resource_adapter_cfgs[resource_adapter_cfg] = { 'cfg': config, 'ec2_conn': resource_adapter.getEC2Connection(config), 'max_register_duration': config.get('spot_provision_timeout', self.__max_register_duration), } # Update the record to queue to have the appropriate # cached data for the request. result['value'] = value result['ec2_conn'] = resource_adapter_cfgs[ resource_adapter_cfg]['ec2_conn'] result['max_register_duration'] = \ resource_adapter_cfgs[resource_adapter_cfg]['max_register_duration'] # enqueue spot instance request queue.put_nowait(result) except Exception as ex: # pylint: disable=broad-except self.logger.error( 'Unable to poll spot instance requests: %s', ex) finally: resource_adapter.session.close() if self.__one_time: await queue.join() self.__done = True break self.logger.debug('Sleeping for %ds', self.__polling_interval) self.__next_poll = time.time() + self.__polling_interval await asyncio.sleep(1) try: for task in tasks: await asyncio.wait_for(task, timeout=30.0) self.logger.debug('Exiting poller') except Exception as ex: # pylint: disable=broad-except self.logger.error('Unable to wait for worker tasks: %s', ex)
def get_resource_adapter(self) -> ResourceAdapter: adapter = get_api(self._adapter_name) adapter.session = self.session return adapter
def validate_addnodes_request(session: Session, addNodesRequest: Dict[str, Any]): """ Raises: HardwareProfileNotFound SoftwareProfileNotFound ProfileMappingNotAllowed InvalidArgument OperationFailed """ if 'hardwareProfile' not in addNodesRequest and \ 'softwareProfile' not in addNodesRequest: raise InvalidArgument( 'Hardware and/or software profile must be specified') hpapi = HardwareProfilesDbHandler() spapi = SoftwareProfilesDbHandler() hardwareProfileName = addNodesRequest['hardwareProfile'] \ if 'hardwareProfile' in addNodesRequest else None nodeDetails = addNodesRequest.get('nodeDetails', []) softwareProfileName = addNodesRequest['softwareProfile'] \ if 'softwareProfile' in addNodesRequest else None nodeCount = int(addNodesRequest.get('count', 0)) rackNumber = addNodesRequest.get('rack') # Look up hardware profile hp = hpapi.getHardwareProfile(session, hardwareProfileName) \ if hardwareProfileName else None # Look up software profile sp = spapi.getSoftwareProfile( session, softwareProfileName) if softwareProfileName else None # Make sure that if a software profile is given that it is allowed # to be used with the given hardware profile if sp is not None and hp is not None: checkProfilesMapped(sp, hp) elif sp is not None and hp is None: if not sp.hardwareprofiles: raise InvalidArgument( 'Software profile [{0}] is not mapped to any hardware' ' profiles'.format(softwareProfileName)) if len(sp.hardwareprofiles) > 1: raise InvalidArgument( 'Ambiguous request: multiple hardware profiles are' ' mapped to software profile [{0}]'.format( softwareProfileName)) hp = sp.hardwareprofiles[0] elif hp is not None and sp is None: if not hp.mappedsoftwareprofiles: raise InvalidArgument( 'Hardware profile [{0}] is not mapped to any software' ' profiles'.format(hardwareProfileName)) if len(hp.mappedsoftwareprofiles) > 1: raise InvalidArgument( 'Ambiguous request: multiple software profiles are' ' mapped to hardware profile [{0}]'.format( hardwareProfileName)) sp = hp.mappedsoftwareprofiles[0] if sp and 'softwareProfile' not in addNodesRequest: addNodesRequest['softwareProfile'] = sp.name if 'hardwareProfile' not in addNodesRequest: addNodesRequest['hardwareProfile'] = hp.name swprofile_node_count = len(sp.nodes) # Validate 'nodeDetails' if nodeDetails: # Reconcile nodeDetails that contain hostnames with hwp name # format bWildcardNameFormat = hp.nameFormat == '*' hostname = nodeDetails[0]['name'] \ if 'name' in nodeDetails[0] else None if hostname and not bWildcardNameFormat: # Host name specified, but hardware profile does not # allow setting the host name raise InvalidArgument('Hardware profile does not allow setting' ' host names of imported nodes') if nodeCount > 0 and nodeCount != len(nodeDetails): raise InvalidArgument('Node count must be equal to number' ' of MAC/IP/node names provided') # check if software profile is locked if sp.lockedState: if sp.lockedState == 'HardLocked': raise OperationFailed( 'Nodes cannot be added to hard locked software' ' profile [{}]'.format(sp.name)) elif sp.lockedState == 'SoftLocked': if 'force' not in addNodesRequest or \ not addNodesRequest['force']: raise OperationFailed( 'Use --force argument to add nodes to soft locked' f' software profile [{sp.name}]') # ensure adding nodes does not exceed imposed limits if sp.maxNodes > 0 and \ (swprofile_node_count + nodeCount) > sp.maxNodes: raise OperationFailed( 'Request to add {} node(s) exceeds software profile' ' limit of {} nodes'.format(nodeCount, sp.maxNodes)) # Prohibit running add-host against installer validate_hwprofile(hp) # If the given hardwareProfile's nameFormat contains "#R', # then the rackNumber is required. nameFormat = hp.nameFormat if nameFormat.find('#R') != -1 and rackNumber is None: raise InvalidArgument('Missing "rackNumber" for name format [%s] of' ' hardware profile [%s]' % (nameFormat, hp)) adapter = resourceAdapterFactory.get_api(hp.resourceadapter.name) adapter.session = session adapter.validate_start_arguments(addNodesRequest, hp, dbSoftwareProfile=sp)
def get_resource_adapter(self) -> ResourceAdapter: adapter = get_api('AWS') adapter.session = self.session return adapter