示例#1
0
def check_cluster_member(message, bus):
    """
    Checks is a member is part of the cluster.

    :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 = message['params']['host']
        name = message['params']['name']
        cluster = bus.storage.get_cluster(name)
        if host in cluster.hostset:
            # Return back the host in a list
            return create_jsonrpc_response(message['id'], [host])
        else:
            return create_jsonrpc_response(
                message['id'],
                error='The requested host is not part of the cluster.',
                error_code=JSONRPC_ERRORS['NOT_FOUND'])
    except Exception as error:
        return create_jsonrpc_error(message, error,
                                    JSONRPC_ERRORS['INTERNAL_ERROR'])
示例#2
0
def create_cluster(message, bus):
    """
    Creates a new cluster.

    :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:
        name = message['params']['name']
        bus.storage.get_cluster(name)
        LOGGER.debug('Creation of already exisiting cluster %s requested.',
                     name)
    except Exception as error:
        LOGGER.debug('Brand new cluster being created.')

        network_name = message['params'].get('network')
        if network_name:
            # Verify the networks existence
            try:
                bus.storage.get_network(network_name)
            except Exception as error:
                # Default if the network doesn't exist
                message['params']['network'] = C.DEFAULT_CLUSTER_NETWORK_JSON[
                    'name']  # noqa

    try:
        cluster = bus.storage.save(models.Cluster.new(**message['params']))
        return create_jsonrpc_response(message['id'], cluster.to_dict_safe())
    except models.ValidationError as error:
        return create_jsonrpc_error(message, error,
                                    JSONRPC_ERRORS['INVALID_REQUEST'])
示例#3
0
def create_cluster_deploy(message, bus):
    """
    Creates a new cluster deployment.

    :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:
        cluster_deploy = models.ClusterDeploy.new(
            name=message['params'].get('name'),
            version=message['params'].get('version'))
        cluster_deploy._validate()

        result = bus.request(
            'jobs.clusterexec.deploy',
            params=[cluster_deploy.name, cluster_deploy.version])
        return create_jsonrpc_response(message['id'], result['result'])
    except models.ValidationError as error:
        LOGGER.info('Invalid data provided. "%s"', error)
        LOGGER.debug('Data="%s"', message['params'])
        return create_jsonrpc_error(message, error,
                                    JSONRPC_ERRORS['INVALID_REQUEST'])
    except Exception as error:
        LOGGER.debug('Error creating ClusterDeploy: %s: %s', type(error),
                     error)
        return create_jsonrpc_error(message, error,
                                    JSONRPC_ERRORS['INTERNAL_ERROR'])
def delete_container_manager(message, bus):
    """
    Deletes an exisiting ContainerManagerConfig.

    :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:
        name = message['params']['name']
        LOGGER.debug(
            'Attempting to delete ContainerManagerConfig "{}"'.format(name))
        bus.storage.delete(models.ContainerManagerConfig.new(name=name))
        return create_jsonrpc_response(message['id'], [])
    except _bus.StorageLookupError as error:
        return create_jsonrpc_error(message, error,
                                    JSONRPC_ERRORS['NOT_FOUND'])
    except Exception as error:
        LOGGER.debug('Error deleting ContainerManagerConfig: {}: {}'.format(
            type(error), error))
        return create_jsonrpc_error(message, error,
                                    JSONRPC_ERRORS['INTERNAL_ERROR'])
示例#5
0
def get_cluster_operation(model_cls, message, bus):
    """
    Gets a specific operation based on the model_cls.

    :param model_cls: The model class to use.
    :type model_cls: class
    :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:
        name = message['params']['name']
        model = bus.storage.get(model_cls.new(name=name))
        model._validate()

        return create_jsonrpc_response(message['id'], model.to_dict_safe())
    except models.ValidationError as error:
        LOGGER.info('Invalid data retrieved. "%s"', error)
        LOGGER.debug('Data="%s"', message['params'])
        return create_jsonrpc_error(message, error,
                                    JSONRPC_ERRORS['INVALID_REQUEST'])
    except _bus.StorageLookupError as error:
        return create_jsonrpc_error(message, error,
                                    JSONRPC_ERRORS['NOT_FOUND'])
    except Exception as error:
        LOGGER.debug('Error getting %s: %s: %s', model_cls.__name__,
                     type(error), error)
        return create_jsonrpc_error(message, error,
                                    JSONRPC_ERRORS['INTERNAL_ERROR'])
示例#6
0
def list_cluster_members(message, bus):
    """
    Lists hosts in a cluster.

    :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:
        name = message['params']['name']
        cluster = bus.storage.get_cluster(name)
        LOGGER.debug('Cluster found: {}'.format(cluster.name))
        LOGGER.debug('Returning: {}'.format(cluster.hostset))
        return create_jsonrpc_response(
            message['id'], result=cluster.hostset)
    except _bus.StorageLookupError as error:
        return create_jsonrpc_error(
            message, error, JSONRPC_ERRORS['NOT_FOUND'])
    except Exception as error:
        LOGGER.debug('Error listing cluster: {}: {}'.format(
            type(error), error))
        return create_jsonrpc_error(
            message, error, JSONRPC_ERRORS['INTERNAL_ERROR'])
示例#7
0
def get_cluster_deploy(message, bus):
    """
    Gets a specific deployment.

    :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:
        name = message['params']['name']
        cluster_deploy = bus.storage.get(models.ClusterDeploy.new(name=name))
        cluster_deploy._validate()

        return create_jsonrpc_response(message['id'],
                                       cluster_deploy.to_dict_safe())
    except models.ValidationError as error:
        LOGGER.info('Invalid data retrieved. "%s"', error)
        LOGGER.debug('Data="%s"', message['params'])
        return create_jsonrpc_error(message, error,
                                    JSONRPC_ERRORS['INVALID_REQUEST'])
    except _bus.StorageLookupError as error:
        return create_jsonrpc_error(message, error,
                                    JSONRPC_ERRORS['NOT_FOUND'])
    except Exception as error:
        return create_jsonrpc_error(message, error,
                                    JSONRPC_ERRORS['INTERNAL_ERROR'])
示例#8
0
def delete_cluster(message, bus):
    """
    Deletes an existing cluster.

    :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:
        name = message['params']['name']
        LOGGER.debug('Attempting to delete cluster "%s"', name)
        cluster = bus.storage.get_cluster(name)
        if cluster.container_manager:
            params = [cluster.container_manager]
            bus.request('container.remove_all_nodes', params=params)
        bus.storage.delete(cluster)
        return create_jsonrpc_response(message['id'], [])
    except _bus.StorageLookupError as error:
        return create_jsonrpc_error(message, error,
                                    JSONRPC_ERRORS['NOT_FOUND'])
    except Exception as error:
        LOGGER.debug('Error deleting cluster: %s: %s'.format(
            type(error), error))
        return create_jsonrpc_error(message, error,
                                    JSONRPC_ERRORS['INTERNAL_ERROR'])
示例#9
0
def delete_cluster_member(message, bus):
    """
    Deletes a member from the cluster.

    :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 = message['params']['host']
        name = message['params']['name']
        cluster = bus.storage.get_cluster(name)
        if host in cluster.hostset:
            # FIXME: Should guard against races here, since we're fetching
            #        the cluster record and writing it back with some parts
            #        unmodified.  Use either locking or a conditional write
            #        with the etcd 'modifiedIndex'.  Deferring for now.
            idx = cluster.hostset.index(host)
            cluster.hostset.pop(idx)
            bus.storage.save(cluster)

            # Remove from container manager (if applicable)
            if cluster.container_manager:
                params = [cluster.container_manager, host]
                bus.request('container.remove_node', params=params)

        return create_jsonrpc_response(message['id'], [])
    except Exception as error:
        return create_jsonrpc_error(message, error,
                                    JSONRPC_ERRORS['NOT_FOUND'])
示例#10
0
 def test_list_hosts(self):
     """
     Verify list_hosts responds with the right information.
     """
     bus = mock.MagicMock()
     bus.storage.list.return_value = Hosts.new(hosts=[HOST])
     self.assertEquals(create_jsonrpc_response(ID, [HOST.to_dict_safe()]),
                       hosts.list_hosts.handler(NO_PARAMS_REQUEST, bus))
示例#11
0
 def test_get_host(self):
     """
     Verify get_host responds with the right information.
     """
     bus = mock.MagicMock()
     bus.storage.get_host.return_value = HOST
     self.assertEquals(create_jsonrpc_response(ID, HOST.to_dict_safe()),
                       hosts.get_host.handler(SIMPLE_HOST_REQUEST, bus))
 def test_list_clusters(self):
     """
     Verify list_clusters responds with the right information.
     """
     bus = mock.MagicMock()
     bus.storage.list.return_value = Clusters.new(clusters=[CLUSTER])
     self.assertEquals(
         create_jsonrpc_response(ID, [CLUSTER.name]),
         clusters.list_clusters.handler(NO_PARAMS_REQUEST, bus))
示例#13
0
 def test_create_jsonrpc_response_with_result(self):
     """
     Verify create_jsonrpc_response creates the proper result jsonrpc structure.
     """
     response = handlers.create_jsonrpc_response(
         UID, result={'test': 'data'})
     self.assertEquals('2.0', response['jsonrpc'])
     self.assertEquals(UID, response['id'])
     self.assertEquals({'test': 'data'}, response['result'])
示例#14
0
 def test_list_networks(self):
     """
     Verify list_networks responds with the right information.
     """
     bus = mock.MagicMock()
     bus.storage.list.return_value = Networks.new(networks=[NETWORK])
     self.assertEquals(
         create_jsonrpc_response(ID, ['test']),
         networks.list_networks.handler(NO_PARAMS_REQUEST, bus))
示例#15
0
 def test_get_network(self):
     """
     Verify get_network responds with the right information.
     """
     bus = mock.MagicMock()
     bus.storage.get_network.return_value = NETWORK
     self.assertEquals(
         create_jsonrpc_response(ID, NETWORK.to_dict()),
         networks.get_network.handler(SIMPLE_NETWORK_REQUEST, bus))
示例#16
0
def create_network(message, bus):
    """
    Creates a new network.

    :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:
        name = message['params']['name']
        LOGGER.debug('create_network params: {}'.format(message['params']))
        # Check to see if we already have a network with that name
        input_network = models.Network.new(**message['params'])
        saved_network = bus.storage.get(input_network)
        LOGGER.debug(
            'Creation of already exisiting network "{0}" requested.'.format(
                name))

        # If they are the same thing then go ahead and return success
        if saved_network.to_dict() == input_network.to_dict():
            return create_jsonrpc_response(
                message['id'], saved_network.to_dict_safe())

        # Otherwise error with a CONFLICT
        return create_jsonrpc_error(
            message,
            'A network with that name already exists.',
            JSONRPC_ERRORS['CONFLICT'])
    except _bus.StorageLookupError as error:
        LOGGER.info('Attempting to create new network: "{}"'.format(
            message['params']))

    # Create the new network
    try:
        input_network = models.Network.new(**message['params'])
        saved_network = bus.storage.save(input_network)
        return create_jsonrpc_response(
            message['id'], saved_network.to_dict_safe())
    except models.ValidationError as error:
        return create_jsonrpc_error(
            message, error, JSONRPC_ERRORS['INVALID_REQUEST'])
 def test_get_container_manager(self):
     """
     Verify get_container_manager responds with the right information.
     """
     bus = mock.MagicMock()
     bus.storage.get.return_value = CONTAINER_MANAGER_CONFIG
     self.assertEquals(
         create_jsonrpc_response(ID, CONTAINER_MANAGER_CONFIG.to_dict()),
         container_managers.get_container_manager.handler(
             SIMPLE_CONTAINER_MANAGER_CONFIG_REQUEST, bus))
 def test_list_cluster_members(self):
     """
     Verify that list_cluster_members returns proper information.
     """
     bus = mock.MagicMock()
     bus.storage.get_cluster.return_value = Cluster.new(
         name='test', hostset=['127.0.0.1'])
     self.assertEquals(
         create_jsonrpc_response(ID, ['127.0.0.1']),
         clusters.list_cluster_members.handler(SIMPLE_CLUSTER_REQUEST, bus))
示例#19
0
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:
        address = message['params']['address']
        host = bus.storage.get_host(address)
        container_manager = {}

        # Find the host's container manager status (if applicable)
        container = bus.storage.list(models.Clusters)
        for cluster in container.clusters:
            if address in cluster.hostset:
                if cluster.container_manager:
                    try:
                        params = [cluster.container_manager, address]
                        container_manager = bus.request(
                            'container.get_node_status', params=params)
                    except _bus.ContainerManagerError as error:
                        # If we fail to get the container manager's
                        # status for the host, leave that part of the
                        # status structure empty.
                        pass

                # A host can only be part of one cluster so break the loop.
                break

        status = models.HostStatus.new(
            host={
                'last_check': host.last_check,
                'status': host.status,
            },
            container_manager=container_manager,
            # TODO: Update when we add other types.
            type='host_only')

        LOGGER.debug('Status for host "{0}": "{1}"'.format(
            host.address, status.to_json_safe()))

        return create_jsonrpc_response(message['id'], status.to_dict_safe())
    except _bus.RemoteProcedureCallError as error:
        return create_jsonrpc_error(message, error,
                                    JSONRPC_ERRORS['NOT_FOUND'])
    except Exception as error:
        LOGGER.debug('Host Status exception caught for {0}: {1}:{2}'.format(
            address, type(error), error))
        return create_jsonrpc_error(message, error,
                                    JSONRPC_ERRORS['INTERNAL_ERROR'])
 def test_list_container_managers(self):
     """
     Verify list_container_managers responds with the right information.
     """
     bus = mock.MagicMock()
     bus.storage.list.return_value = ContainerManagerConfigs.new(
         container_managers=[CONTAINER_MANAGER_CONFIG])
     self.assertEquals(
         create_jsonrpc_response(ID, ['test']),
         container_managers.list_container_managers.handler(
             NO_PARAMS_REQUEST, bus))
示例#21
0
 def test_get_host_creds(self):
     """
     Verify get_hostcreds responds with the right information.
     """
     bus = mock.MagicMock()
     bus.storage.get_host.return_value = HOST
     self.assertEquals(
         create_jsonrpc_response(ID, {
             'ssh_priv_key': '',
             'remote_user': '******'
         }), hosts.get_hostcreds.handler(SIMPLE_HOST_REQUEST, bus))
    def test_create_cluster(self):
        """
        Verify create_cluster saves new clusters.
        """
        bus = mock.MagicMock()
        bus.storage.get_cluster.side_effect = Exception
        bus.storage.save.return_value = CLUSTER

        self.assertEquals(
            create_jsonrpc_response(ID, CLUSTER.to_dict_safe()),
            clusters.create_cluster.handler(SIMPLE_CLUSTER_REQUEST, bus))
示例#23
0
 def test_create_network(self):
     """
     Verify create_network can create a new network.
     """
     bus = mock.MagicMock()
     # Network doesn't yet exist
     bus.storage.get.side_effect = _bus.StorageLookupError('test', NETWORK)
     # Creation response
     bus.storage.save.return_value = NETWORK
     self.assertEquals(
         create_jsonrpc_response(ID, NETWORK.to_dict()),
         networks.create_network.handler(SIMPLE_NETWORK_REQUEST, bus))
示例#24
0
 def test_create_network_idempotent(self):
     """
     Verify create_network acts idempotent.
     """
     bus = mock.MagicMock()
     # Network exists
     bus.storage.get.return_value = NETWORK
     # Creation response
     bus.storage.save.return_value = NETWORK
     self.assertEquals(
         create_jsonrpc_response(ID, NETWORK.to_dict()),
         networks.create_network.handler(SIMPLE_NETWORK_REQUEST, bus))
示例#25
0
    def test_create_host_with_the_same_existing_host(self):
        """
        Verify create_host succeeds when a new host matches an existing one.
        """
        bus = mock.MagicMock()
        # Existing host
        bus.storage.get_host.return_value = HOST
        # Result from save
        bus.storage.save.return_value = HOST

        self.assertEquals(create_jsonrpc_response(ID, HOST.to_dict_safe()),
                          hosts.create_host.handler(SIMPLE_HOST_REQUEST, bus))
 def test_create_container_manager_idempotent(self):
     """
     Verify create_container_manager acts idempotent.
     """
     bus = mock.MagicMock()
     # ContainerManagerConfig exists
     bus.storage.get.return_value = CONTAINER_MANAGER_CONFIG
     # Creation response
     bus.storage.save.return_value = CONTAINER_MANAGER_CONFIG
     self.assertEquals(
         create_jsonrpc_response(ID, CONTAINER_MANAGER_CONFIG.to_dict()),
         container_managers.create_container_manager.handler(
             SIMPLE_CONTAINER_MANAGER_CONFIG_REQUEST, bus))
示例#27
0
    def test_create_host(self):
        """
        Verify create_host saves new hosts.
        """
        bus = mock.MagicMock()
        # Host doesn't exist yet
        bus.storage.get_host.side_effect = _bus.RemoteProcedureCallError(
            'test')
        # Result from save
        bus.storage.save.return_value = HOST

        self.assertEquals(create_jsonrpc_response(ID, HOST.to_dict_safe()),
                          hosts.create_host.handler(SIMPLE_HOST_REQUEST, bus))
    def test_check_cluster_member_with_valid_member(self):
        """
        Verify that check_cluster_member returns proper data when a valid member is requested.
        """
        bus = mock.MagicMock()
        cluster = Cluster.new(
            name='test', hostset=['127.0.0.1'])

        bus.storage.get_cluster.return_value = cluster

        self.assertEquals(
            create_jsonrpc_response(ID, ['127.0.0.1']),
            clusters.check_cluster_member.handler(CHECK_CLUSTER_REQUEST, bus))
示例#29
0
def add_cluster_member(message, bus):
    """
    Adds a member to the cluster.

    :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:
        address = message['params']['host']
        name = message['params']['name']
    except KeyError as error:
        return create_jsonrpc_error(
            message, error, JSONRPC_ERRORS['BAD_REQUEST'])

    try:
        host = bus.storage.get_host(address)
        cluster = bus.storage.get_cluster(name)
    except _bus.StorageLookupError as error:
        return create_jsonrpc_error(
            message, error, JSONRPC_ERRORS['NOT_FOUND'])

    if host.address not in cluster.hostset:
        # FIXME: Need more input validation.
        #        - Does the host already belong to another cluster?

        # FIXME: Should guard against races here, since we're fetching
        #        the cluster record and writing it back with some parts
        #        unmodified.  Use either locking or a conditional write
        #        with the etcd 'modifiedIndex'.  Deferring for now.

        if host_suitable_for_cluster(host):
            cluster.hostset.append(host.address)
            bus.storage.save(cluster)

            # Register new host with the cluster's container manager
            # (if applicable), and update its status.
            update_new_cluster_member_status(bus, cluster, host)
        else:
            msg = (
                'Host {} (status: {}) not ready to join cluster '
                '"{}"'.format(host.address, host.status, cluster.name))
            LOGGER.error(msg)
            return create_jsonrpc_error(
                message, msg, JSONRPC_ERRORS['METHOD_NOT_ALLOWED'])

    # Return back the host in a list
    return create_jsonrpc_response(message['id'], [host.address])
 def test_create_container_manager(self):
     """
     Verify create_container_manager can create a new ContainerManagerConfig.
     """
     bus = mock.MagicMock()
     # ContainerManagerConfig doesn't yet exist
     bus.storage.get.side_effect = _bus.StorageLookupError(
         'test', CONTAINER_MANAGER_CONFIG)
     # Creation response
     bus.storage.save.return_value = CONTAINER_MANAGER_CONFIG
     self.assertEquals(
         create_jsonrpc_response(ID, CONTAINER_MANAGER_CONFIG.to_dict()),
         container_managers.create_container_manager.handler(
             SIMPLE_CONTAINER_MANAGER_CONFIG_REQUEST, bus))