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)
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'])
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'])