def test_on_message_with_success(self):
        """
        Verify WatcherService.on_message handles a successful message properly.
        """
        body = models.WatcherRecord(
            address='127.0.0.1',
            last_check=(datetime.datetime.utcnow() -
                        datetime.timedelta(minutes=10)).isoformat())
        message = mock.MagicMock(payload=body.to_json(),
                                 delivery_info={'routing_key': 'jobs.watcher'})

        self.service_instance._check = mock.MagicMock()
        self.service_instance.on_message(body.to_json(), message)
        # The message must get ack'd
        message.ack.assert_called_once_with()
        # Check should be called
        self.service_instance._check.assert_called_once_with('127.0.0.1')
    def test_on_message_with_early_address(self):
        """
        Verify WatcherService.on_message requeues addresses that have been checked recently.
        """
        with mock.patch('commissaire_service.watcher.sleep') as _sleep:
            body = models.WatcherRecord(
                address='127.0.0.1',
                last_check=datetime.datetime.utcnow().isoformat())
            message = mock.MagicMock(
                payload=body.to_json(),
                delivery_info={'routing_key': 'jobs.watcher'})

            self.service_instance._check = mock.MagicMock()
            self.service_instance.on_message(body.to_json(), message)
            # The message must get ack'd
            message.ack.assert_called_once_with()
            # Check should NOT be called
            self.assertEquals(0, self.service_instance._check.call_count)
            # We should have been asked to sleep
            _sleep.assert_called_once_with(mock.ANY)
Exemplo n.º 3
0
def create_host(message, bus):
    """
    Creates a new host.

    :param message: jsonrpc message structure.
    :type message: dict
    :param bus: Bus instance.
    :type bus: commissaire_http.bus.Bus
    :returns: A jsonrpc structure.
    :rtype: dict
    """
    LOGGER.debug('create_host params: "{}"'.format(message['params']))
    try:
        address = message['params']['address']
    except KeyError:
        return create_jsonrpc_error(
            message, '"address" must be given in the url or in the PUT body',
            JSONRPC_ERRORS['BAD_REQUEST'])

    # If a cluster if provided, grab it from storage
    cluster_data = {}
    cluster_name = message['params'].get('cluster')
    if cluster_name:
        cluster = _does_cluster_exist(bus, cluster_name)
        if not cluster:
            return create_jsonrpc_error(message, 'Cluster does not exist',
                                        JSONRPC_ERRORS['CONFLICT'])
        else:
            cluster_data = cluster.to_dict()
            LOGGER.debug('Found cluster. Data: "{}"'.format(cluster))
    try:
        host = bus.storage.get_host(address)
        LOGGER.debug('Host "{}" already exisits.'.format(address))

        # Verify the keys match
        if host.ssh_priv_key != message['params'].get('ssh_priv_key', ''):
            return create_jsonrpc_error(message, 'Host already exists',
                                        JSONRPC_ERRORS['CONFLICT'])

        # Verify the host is in the cluster if it is expected
        if cluster_name and address not in cluster.hostset:
            LOGGER.debug('Host "{}" is not in cluster "{}"'.format(
                address, cluster_name))
            return create_jsonrpc_error(message, 'Host not in cluster',
                                        JSONRPC_ERRORS['CONFLICT'])

        # Return out now. No more processing needed.
        return create_jsonrpc_response(message['id'], host.to_dict_safe())

    except _bus.RemoteProcedureCallError as error:
        LOGGER.debug('Brand new host "{}" being created.'.format(
            message['params']['address']))

    # Save the host to the cluster if it isn't already there
    if cluster_name:
        if address not in cluster.hostset:
            cluster.hostset.append(address)
            bus.storage.save(cluster)
            LOGGER.debug('Saved host "{}" to cluster "{}"'.format(
                address, cluster_name))

    try:
        host = bus.storage.save(models.Host.new(**message['params']))

        # pass this off to the investigator
        bus.notify('jobs.investigate',
                   params={
                       'address': address,
                       'cluster_data': cluster_data
                   })

        # Push the host to the Watcher queue
        watcher_record = models.WatcherRecord(
            address=address, last_check=_dt.utcnow().isoformat())
        bus.producer.publish(watcher_record.to_json(), 'jobs.watcher')

        return create_jsonrpc_response(message['id'], host.to_dict_safe())
    except models.ValidationError as error:
        return create_jsonrpc_error(message, error,
                                    JSONRPC_ERRORS['INVALID_REQUEST'])
Exemplo n.º 4
0
def create_host(message, bus):
    """
    Creates a new host.

    :param message: jsonrpc message structure.
    :type message: dict
    :param bus: Bus instance.
    :type bus: commissaire_http.bus.Bus
    :returns: A jsonrpc structure.
    :rtype: dict
    """
    LOGGER.debug('create_host params: "{}"'.format(message['params']))
    try:
        address = message['params']['address']
    except KeyError:
        return return_error(
            message, '"address" must be given in the url or in the PUT body',
            JSONRPC_ERRORS['INVALID_PARAMETERS'])
    try:
        host = bus.request('storage.get',
                           params=['Host', {
                               'address': address
                           }, True])
        LOGGER.debug('Host "{}" already exisits.'.format(address))

        # Verify the keys match
        if (host['result']['ssh_priv_key'] != message['params'].get(
                'ssh_priv_key', '')):
            return return_error(message, 'Host already exists',
                                JSONRPC_ERRORS['CONFLICT'])

        # Verify the cluster exists and it's in the cluster
        if message['params'].get('cluster'):
            cluster = _does_cluster_exist(bus, message['params']['cluster'])
            if not cluster:
                return return_error(message, 'Cluster does not exist',
                                    JSONRPC_ERRORS['INVALID_PARAMETERS'])
            # Verify the host is in the cluster
            if address not in cluster.hostset:
                LOGGER.debug('Host "{}" is not in cluster "{}"'.format(
                    address, message['params']['cluster']))
                return return_error(message, 'Host not in cluster',
                                    JSONRPC_ERRORS['CONFLICT'])

        # Return out now. No more processing needed.
        return create_response(message['id'],
                               models.Host.new(**host['result']).to_dict())

    except _bus.RemoteProcedureCallError as error:
        LOGGER.debug('Brand new host "{}" being created.'.format(
            message['params']['address']))

    if message['params'].get('cluster'):
        # Verify the cluster existence and add the host to it
        cluster_name = message['params']['cluster']
        cluster = _does_cluster_exist(bus, message['params']['cluster'])
        if not cluster:
            LOGGER.warn(
                'create_host could not find cluster "{}" for the creation '
                'of new host "{}"'.format(cluster_name, address))
            return return_error(message, 'Cluster does not exist',
                                JSONRPC_ERRORS['INVALID_PARAMETERS'])

        LOGGER.debug('Found cluster. Data: "{}"'.format(cluster))
        if address not in cluster.hostset:
            cluster.hostset.append(address)
            bus.request('storage.save',
                        params=['Cluster', cluster.to_dict(True)])

    try:
        host = models.Host.new(**message['params'])
        host._validate()
        bus.request('storage.save', params=['Host', host.to_dict(True)])

        # pass this off to the investigator
        bus.notify('jobs.investigate', params={'address': address})

        # Push the host to the Watcher queue
        watcher_record = models.WatcherRecord(
            address=address, last_check=_dt.utcnow().isoformat())
        bus.producer.publish(watcher_record.to_json(), 'jobs.watcher')

        return create_response(message['id'], host.to_dict())
    except models.ValidationError as error:
        return return_error(message, error, JSONRPC_ERRORS['INVALID_REQUEST'])