Пример #1
0
    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)
Пример #2
0
    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
Пример #3
0
    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
Пример #4
0
    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)
Пример #5
0
    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
Пример #8
0
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