def update_new_cluster_member_status(bus, cluster, *hosts): """ Call this helper function when adding new hosts to a cluster. If applicable, it will register each host with the cluster's container manager. Then it will update the host status accordingly and save the model(s) to permanent storage. :param bus: Bus instance :type bus: commissaire_http.bus.Bus :param cluster: A Cluster model instance :type cluster: commissaire.models.Cluster :param hosts: Tuple of Host model instances :type hosts: (commissaire.models.Host, ...) """ for host in hosts: try: host.status = C.HOST_STATUS_DISASSOCIATED if cluster.container_manager: bus.request('container.register_node', params=[cluster.container_manager, host.address]) host.status = C.HOST_STATUS_ACTIVE except Exception as error: LOGGER.warn('Unable to register %s to container manager "%s": %s', host.address, cluster.container_manager, error.args[0]) raise error # Save the updated host models. bus.storage.save_many(hosts)
def _does_cluster_exist(bus, cluster_name): """ Shorthand to check and see if a cluster exists. If it does, return the message response data. :param bus: Bus instance. :type bus: commissaire_http.bus.Bus :param cluster_name: The name of the Cluster to look up. :type cluster_name: str :returns: The found Cluster instance or None :rtype: mixed """ LOGGER.debug('Checking on cluster "{}"'.format(cluster_name)) try: cluster = bus.storage.get_cluster(cluster_name) LOGGER.debug('Found cluster: "{}"'.format(cluster)) return cluster except _bus.StorageLookupError as error: LOGGER.warn( 'create_host could not find cluster "{}"'.format(cluster_name)) return None
def _does_cluster_exist(bus, cluster_name): """ Shorthand to check and see if a cluster exists. If it does, return the message response data. :param bus: Bus instance. :type bus: commissaire_http.bus.Bus :param cluster_name: The name of the Cluster to look up. :type cluster_name: str :returns: The found Cluster instance or None :rtype: mixed """ LOGGER.debug('Checking on cluster "{}"'.format(cluster_name)) try: cluster = bus.request('storage.get', params=[ 'Cluster', {'name': cluster_name}, True]) LOGGER.debug('Found cluster: "{}"'.format(cluster)) return models.Cluster.new(**cluster['result']) except _bus.RemoteProcedureCallError as error: LOGGER.warn( 'create_host could not find cluster "{}"'.format(cluster_name)) LOGGER.debug('Error: {}: "{}"'.format(type(error), error))
def get_host_status(message, bus): """ Gets the status of an exisiting 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 """ try: host_response = bus.request( 'storage.get', params=['Host', { 'address': message['params']['address'] }]) host = models.Host.new(**host_response['result']) status = models.HostStatus.new( host={ 'last_check': host.last_check, 'status': host.status, }, # TODO: Update when we add other types. type=C.CLUSTER_TYPE_HOST) LOGGER.debug('Status for host "{0}": "{1}"'.format( host.address, status.to_json())) return create_response(message['id'], status.to_dict()) except _bus.RemoteProcedureCallError as error: LOGGER.warn('Could not retrieve host "{}". {}: {}'.format( message['params']['address'], type(error), error)) return return_error(message, error, JSONRPC_ERRORS['NOT_FOUND']) except Exception as error: LOGGER.debug('Host Status exception caught for {0}: {1}:{2}'.format( host.address, type(error), error)) return return_error(message, error, JSONRPC_ERRORS['INTERNAL_ERROR'])
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: # TODO: pass this off to the bootstrap process host = models.Host.new(**message['params']) host._validate() bus.request( 'storage.save', params=[ 'Host', host.to_dict(True)]) return create_response(message['id'], host.to_dict()) except models.ValidationError as error: return return_error(message, error, JSONRPC_ERRORS['INVALID_REQUEST'])