예제 #1
0
파일: api.py 프로젝트: yosshy/compass-core
    def get(self, cluster_id):
        """Lists progress details of a specific cluster

        :param cluster_id: the unique identifier of the cluster
        """
        progress_result = {}
        with database.session() as session:
            cluster = session.query(ModelCluster).filter_by(id=cluster_id)\
                                                 .first()
            if not cluster:
                error_msg = "The cluster id=%s does not exist!" % cluster_id
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            if not cluster.state:
                progress_result = {
                    'id': cluster_id,
                    'state': 'UNINITIALIZED',
                    'percentage': 0,
                    'message': "Waiting..............",
                    'severity': "INFO"
                }
            else:
                progress_result['id'] = cluster_id
                progress_result['state'] = cluster.state.state
                progress_result['percentage'] = cluster.state.progress
                progress_result['message'] = cluster.state.message
                progress_result['severity'] = cluster.state.severity

        logging.info('progress result for cluster %s: %s',
                     cluster_id, progress_result)
        return util.make_json_response(
            200, {"status": "OK",
                  "progress": progress_result})
예제 #2
0
파일: api.py 프로젝트: gasopbf1/compasstest
    def _remove_hosts(cluster_id, hosts):
        """Remove existing cluster host from the cluster"""

        removed_hosts = []
        with database.session() as session:
            failed_hosts = []
            for host_id in hosts:
                host = session.query(ModelClusterHost).filter_by(id=host_id)\
                                                      .first()

                if not host:
                    failed_hosts.append(host)
                    continue

                host_res = {"id": host_id, "machine_id": host.machine_id}
                removed_hosts.append(host_res)

            if failed_hosts:
                error_msg = 'Cluster hosts do not exist!'
                value = {"failedHosts": failed_hosts}
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg), value)

            filter_clause = []
            for host_id in hosts:
                filter_clause.append('id=%s' % host_id)

            # Delete the requested hosts from database
            session.query(ModelClusterHost).filter(or_(*filter_clause))\
                   .delete(synchronize_session='fetch')

        return util.make_json_response(200, {
            "status": "OK",
            "cluster_hosts": removed_hosts
        })
예제 #3
0
파일: api.py 프로젝트: jerryz1982/compass
    def get(self, host_id):
        """
        Lists progress details of a specific cluster host
        :param host_id: cluster host ID in db
        """
        progress_result = {}
        with database.session() as session:
            host = session.query(ModelClusterHost).filter_by(id=host_id)\
                                                  .first()
            if not host:
                error_msg = "The host id=%s does not exist!" % host_id
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            if not host.state:
                progress_result = {
                    'id': host_id,
                    'state': 'UNINITIALIZED',
                    'percentage': 0,
                    'message': "Waiting..............",
                    'severity': "INFO",
                }
            else:
                progress_result['id'] = host_id
                progress_result['state'] = host.state.state
                progress_result['percentage'] = host.state.progress
                progress_result['message'] = host.state.message
                progress_result['severity'] = host.state.severity

        logging.info('progress result for %s: %s', host_id, progress_result)
        return util.make_json_response(
            200, {"status": "OK",
                  "progress": progress_result})
예제 #4
0
파일: api.py 프로젝트: gasopbf1/compasstest
    def _deploy(cluster_id):
        """Deploy the cluster"""

        deploy_hosts_urls = []
        with database.session() as session:
            cluster_hosts_ids = session.query(ModelClusterHost.id)\
                                       .filter_by(cluster_id=cluster_id).all()
            if not cluster_hosts_ids:
                # No host belongs to this cluster
                error_msg = ('Cannot find any host in cluster id=%s' %
                             cluster_id)
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            for elm in cluster_hosts_ids:
                host_id = str(elm[0])
                progress_url = '/cluster_hosts/%s/progress' % host_id
                deploy_hosts_urls.append(progress_url)

            # Lock cluster hosts and its cluster
            session.query(ModelClusterHost).filter_by(cluster_id=cluster_id)\
                                           .update({'mutable': False})
            session.query(ModelCluster).filter_by(id=cluster_id)\
                                       .update({'mutable': False})

        celery.send_task("compass.tasks.trigger_install", (cluster_id, ))
        return util.make_json_response(202, {
            "status": "OK",
            "deployment": deploy_hosts_urls
        })
예제 #5
0
    def get(self, host_id):
        """
        Lists progress details of a specific cluster host
        :param host_id: cluster host ID in db
        """
        progress_result = {}
        with database.session() as session:
            host = session.query(ModelClusterHost).filter_by(id=host_id)\
                                                  .first()
            if not host:
                error_msg = "The host id=%s does not exist!" % host_id
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            if not host.state:
                progress_result = {
                    'id': host_id,
                    'state': 'UNINITIALIZED',
                    'percentage': 0,
                    'message': "Waiting..............",
                    'severity': "INFO",
                }
            else:
                progress_result['id'] = host_id
                progress_result['state'] = host.state.state
                progress_result['percentage'] = host.state.progress
                progress_result['message'] = host.state.message
                progress_result['severity'] = host.state.severity

        logging.info('progress result for %s: %s', host_id, progress_result)
        return util.make_json_response(200, {
            "status": "OK",
            "progress": progress_result
        })
예제 #6
0
파일: api.py 프로젝트: jerryz1982/compass
    def delete(self, host_id, subkey):
        """
        Delete one attribute in configuration of a specific cluster host
        :param host_id: the cluster host ID
        :param subkey: the attribute name in configuration
        """
        available_delete_keys = ['ip', 'role']
        with database.session() as session:
            host = session.query(ModelClusterHost).filter_by(id=host_id)\
                                                  .first()
            if not host:
                error_msg = "The host id=%s does not exist!" % host_id
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            if subkey not in available_delete_keys:
                error_msg = "subkey %s is not supported!" % subkey
                return errors.handle_invalid_usage(
                    errors.UserInvalidUsage(error_msg))

            if not host.mutable:
                error_msg = "The host 'id=%s' is not mutable!" % host_id
                return errors.handle_invalid_usage(
                    errors.UserInvalidUsage(error_msg))

            config = json.loads(host.config_data)
            # Set the subkey's value to ""
            util.update_dict_value(subkey, "", config)
            host.config = config

        return util.make_json_response(
            200, {"status": "OK"})
예제 #7
0
파일: api.py 프로젝트: jerryz1982/compass
    def get(self, switch_id):
        """
        Lists details of the switch with the specific switch id.
        :param switch_id: switch ID in db
        """
        switch_res = {}
        with database.session() as session:
            switch = session.query(ModelSwitch).filter_by(id=switch_id).first()
            logging.info('switch for id %s: %s', switch_id, switch)

            if not switch:
                error_msg = "Cannot find the switch with id=%s" % switch_id
                logging.error("[/switches/{id}]error_msg: %s", error_msg)

                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg)
                    )

            switch_res['id'] = switch.id
            switch_res['state'] = switch.state
            switch_res['link'] = {
                'rel': 'self',
                'href': '/'.join((self.ENDPOINT, str(switch.id)))}

        logging.info('switch info for %s: %s', switch_id, switch_res)
        return util.make_json_response(
            200, {"status": "OK",
                  "switch": switch_res})
예제 #8
0
파일: api.py 프로젝트: jerryz1982/compass
    def get(self, machine_id):
        """
        Lists details of the machine with specific machine id.
        :param machine_id: the machine ID in db
        """
        machine_res = {}
        with database.session() as session:
            machine = session.query(ModelMachine)\
                             .filter_by(id=machine_id)\
                             .first()
            logging.info('machine for id %s: %s', machine_id, machine)

            if not machine:
                error_msg = "Cannot find the machine with id=%s" % machine_id
                logging.error("[/api/machines/{id}]error_msg: %s", error_msg)

                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            machine_res['id'] = machine.id
            machine_res['mac'] = machine.mac
            machine_res['port'] = machine.port
            machine_res['vlan'] = machine.vlan
            if machine.switch:
                machine_res['switch_ip'] = machine.switch.ip
            else:
                machine_res['switch_ip'] = None
            machine_res['link'] = {
                'rel': 'self',
                'href': '/'.join((self.ENDPOINT, str(machine.id)))}

        logging.info('machine info for %s: %s', machine_id, machine_res)
        return util.make_json_response(
            200, {"status": "OK",
                  "machine": machine_res})
예제 #9
0
파일: api.py 프로젝트: gasopbf1/compasstest
def list_adapter_roles(adapter_id):
    """Lists details of all roles of the specified adapter

    :param adapter_id: the unique identifier of the adapter
    """
    roles_list = []
    with database.session() as session:
        adapter_q = session.query(Adapter)\
                           .filter_by(id=adapter_id).first()
        if not adapter_q:
            error_msg = "Adapter id=%s does not exist!" % adapter_id
            return errors.handle_not_exist(
                errors.ObjectDoesNotExist(error_msg))

        roles = session.query(Role, Adapter)\
                       .filter(Adapter.id == adapter_id,
                               Adapter.target_system == Role.target_system)\
                       .all()

        for role, adapter in roles:
            role_res = {}
            role_res['name'] = role.name
            role_res['description'] = role.description
            roles_list.append(role_res)

    return util.make_json_response(200, {"status": "OK", "roles": roles_list})
예제 #10
0
파일: api.py 프로젝트: gasopbf1/compasstest
    def delete(self, host_id, subkey):
        """
        Delete one attribute in configuration of the specified cluster host

        :param host_id: the unique identifier of the host
        :param subkey: the attribute name in configuration
        """
        available_delete_keys = ['ip', 'roles']
        with database.session() as session:
            host = session.query(ModelClusterHost).filter_by(id=host_id)\
                                                  .first()
            if not host:
                error_msg = "The host id=%s does not exist!" % host_id
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            if subkey not in available_delete_keys:
                error_msg = "subkey %s is not supported!" % subkey
                return errors.handle_invalid_usage(
                    errors.UserInvalidUsage(error_msg))

            if not host.mutable:
                error_msg = "The host 'id=%s' is not mutable!" % host_id
                return errors.handle_invalid_usage(
                    errors.UserInvalidUsage(error_msg))

            config = json.loads(host.config_data)
            # Set the subkey's value to ""
            util.update_dict_value(subkey, "", config)
            host.config = config

        return util.make_json_response(200, {"status": "OK"})
예제 #11
0
파일: api.py 프로젝트: gasopbf1/compasstest
    def get(self, cluster_id):
        """Lists progress details of a specific cluster

        :param cluster_id: the unique identifier of the cluster
        """
        progress_result = {}
        with database.session() as session:
            cluster = session.query(ModelCluster).filter_by(id=cluster_id)\
                                                 .first()
            if not cluster:
                error_msg = "The cluster id=%s does not exist!" % cluster_id
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            if not cluster.state:
                progress_result = {
                    'id': cluster_id,
                    'state': 'UNINITIALIZED',
                    'percentage': 0,
                    'message': "Waiting..............",
                    'severity': "INFO"
                }
            else:
                progress_result['id'] = cluster_id
                progress_result['state'] = cluster.state.state
                progress_result['percentage'] = cluster.state.progress
                progress_result['message'] = cluster.state.message
                progress_result['severity'] = cluster.state.severity

        logging.info('progress result for cluster %s: %s', cluster_id,
                     progress_result)
        return util.make_json_response(200, {
            "status": "OK",
            "progress": progress_result
        })
예제 #12
0
파일: api.py 프로젝트: yosshy/compass-core
def list_adapter(adapter_id):
    """
    Lists details of the specified adapter.

    :param adapter_id: the unique identifier of the adapter
    """
    endpoint = '/adapters'
    adapter_res = {}
    with database.session() as session:
        adapter = session.query(Adapter).filter_by(id=adapter_id).first()

        if not adapter:
            error_msg = "Adapter id=%s does not exist!" % adapter_id
            return errors.handle_not_exist(
                errors.ObjectDoesNotExist(error_msg))
        adapter_res['name'] = adapter.name
        adapter_res['os'] = adapter.os
        adapter_res['id'] = adapter.id
        adapter_res['target_system'] = adapter.target_system,
        adapter_res['link'] = {
            "href": "/".join((endpoint, str(adapter.id))),
            "rel": "self"}
    return util.make_json_response(
        200, {"status": "OK",
              "adapter": adapter_res})
예제 #13
0
파일: api.py 프로젝트: jerryz1982/compass
def list_adapter_roles(adapter_id):
    """
    Lists details of all roles of a specific adapter
    :param adapter_id: the adaper ID in db
    """
    roles_list = []
    with database.session() as session:
        adapter_q = session.query(Adapter)\
                           .filter_by(id=adapter_id).first()
        if not adapter_q:
            error_msg = "Adapter id=%s does not exist!" % adapter_id
            return errors.handle_not_exist(
                errors.ObjectDoesNotExist(error_msg))

        roles = session.query(Role, Adapter)\
                       .filter(Adapter.id == adapter_id,
                               Adapter.target_system == Role.target_system)\
                       .all()

        for role, adapter in roles:
            role_res = {}
            role_res['name'] = role.name
            role_res['description'] = role.description
            roles_list.append(role_res)

    return util.make_json_response(
        200, {"status": "OK",
              "roles": roles_list})
예제 #14
0
파일: api.py 프로젝트: jerryz1982/compass
    def get(self):
        """
        Return a list of dashboard links
        """
        cluster_id = request.args.get('cluster_id', None)
        logging.info('get cluster links with cluster_id=%s', cluster_id)
        links = {}
        with database.session() as session:
            hosts = session.query(ModelClusterHost)\
                           .filter_by(cluster_id=cluster_id).all()
            if not hosts:
                error_msg = "Cannot find hosts in cluster id=%s" % cluster_id
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            for host in hosts:
                config = host.config
                if ('has_dashboard_roles' in config and
                       config['has_dashboard_roles']):
                    ip = config.get(
                        'networking', {}).get(
                        'interfaces', {}).get(
                        'management', {}).get(
                        'ip', '')
                    roles = config.get('roles', [])
                    for role in roles:
                        links[role] = 'http://%s' % ip

        return util.make_json_response(
            200, {"status": "OK",
                  "dashboardlinks": links}
            )
예제 #15
0
파일: api.py 프로젝트: gasopbf1/compasstest
def list_adapter(adapter_id):
    """
    Lists details of the specified adapter.

    :param adapter_id: the unique identifier of the adapter
    """
    endpoint = '/adapters'
    adapter_res = {}
    with database.session() as session:
        adapter = session.query(Adapter).filter_by(id=adapter_id).first()

        if not adapter:
            error_msg = "Adapter id=%s does not exist!" % adapter_id
            return errors.handle_not_exist(
                errors.ObjectDoesNotExist(error_msg))
        adapter_res['name'] = adapter.name
        adapter_res['os'] = adapter.os
        adapter_res['id'] = adapter.id
        adapter_res['target_system'] = adapter.target_system,
        adapter_res['link'] = {
            "href": "/".join((endpoint, str(adapter.id))),
            "rel": "self"
        }
    return util.make_json_response(200, {
        "status": "OK",
        "adapter": adapter_res
    })
예제 #16
0
파일: api.py 프로젝트: gasopbf1/compasstest
    def get(self, switch_id):
        """Lists details of the specified switch.

        :param switch_id: switch ID in db
        """
        switch_res = {}
        with database.session() as session:
            switch = session.query(ModelSwitch).filter_by(id=switch_id).first()
            logging.info('switch for id %s: %s', switch_id, switch)

            if not switch:
                error_msg = "Cannot find the switch with id=%s" % switch_id
                logging.error("[/switches/{id}]error_msg: %s", error_msg)

                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            switch_res['id'] = switch.id
            switch_res['ip'] = switch.ip
            switch_res['state'] = switch.state
            switch_res['link'] = {
                'rel': 'self',
                'href': '/'.join((self.ENDPOINT, str(switch.id)))
            }

        logging.info('switch info for %s: %s', switch_id, switch_res)
        return util.make_json_response(200, {
            "status": "OK",
            "switch": switch_res
        })
예제 #17
0
파일: api.py 프로젝트: gasopbf1/compasstest
    def get(self):
        """
        Return a list of dashboard links
        """
        cluster_id = request.args.get('cluster_id', None)
        logging.info('get cluster links with cluster_id=%s', cluster_id)
        links = {}
        with database.session() as session:
            hosts = session.query(ModelClusterHost)\
                           .filter_by(cluster_id=cluster_id).all()
            if not hosts:
                error_msg = "Cannot find hosts in cluster id=%s" % cluster_id
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            for host in hosts:
                config = host.config
                if ('has_dashboard_roles' in config
                        and config['has_dashboard_roles']):
                    ip = config.get('networking',
                                    {}).get('interfaces',
                                            {}).get('management',
                                                    {}).get('ip', '')
                    roles = config.get('roles', [])
                    for role in roles:
                        links[role] = 'http://%s' % ip

        return util.make_json_response(200, {
            "status": "OK",
            "dashboardlinks": links
        })
예제 #18
0
파일: api.py 프로젝트: jerryz1982/compass
    def _deploy(cluster_id):
        """Deploy the cluster"""

        deploy_hosts_urls = []
        with database.session() as session:
            cluster_hosts_ids = session.query(ModelClusterHost.id)\
                                       .filter_by(cluster_id=cluster_id).all()
            if not cluster_hosts_ids:
                # No host belongs to this cluster
                error_msg = ('Cannot find any host in cluster id=%s' %
                             cluster_id)
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            for host_id in cluster_hosts_ids:
                progress_url = '/cluster_hosts/%s/progress' % str(host_id)
                deploy_hosts_urls.append(progress_url)

            # Lock cluster hosts and its cluster
            session.query(ModelClusterHost).filter_by(cluster_id=cluster_id)\
                                           .update({'mutable': False})
            session.query(ModelCluster).filter_by(id=cluster_id)\
                                       .update({'mutable': False})

        celery.send_task("compass.tasks.trigger_install", (cluster_id,))
        return util.make_json_response(
            202, {"status": "OK",
                  "deployment": deploy_hosts_urls})
예제 #19
0
파일: api.py 프로젝트: gasopbf1/compasstest
    def put(self, cluster_id, resource):
        """
        Update the resource information of the specified cluster in database

        :param cluster_id: the unique identifier of the cluster
        :param resource: resource name(security, networking, partition)
        """
        resources = {
            self.SECURITY: {
                'validator': 'is_valid_security_config',
                'column': 'security_config'
            },
            self.NETWORKING: {
                'validator': 'is_valid_networking_config',
                'column': 'networking_config'
            },
            self.PARTITION: {
                'validator': 'is_valid_partition_config',
                'column': 'partition_config'
            },
        }
        request_data = json.loads(request.data)
        with database.session() as session:
            cluster = session.query(ModelCluster).filter_by(id=cluster_id)\
                                                 .first()

            if not cluster:
                error_msg = 'You are trying to update a non-existing cluster!'
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))
            if resource not in request_data:
                error_msg = "Invalid resource name '%s'" % resource
                return errors.handle_invalid_usage(
                    errors.UserInvalidUsage(error_msg))

            value = request_data[resource]

            if resource not in resources.keys():
                error_msg = "Invalid resource name '%s'" % resource
                return errors.handle_invalid_usage(
                    errors.UserInvalidUsage(error_msg))

            validate_func = resources[resource]['validator']
            module = globals()['util']
            is_valid, msg = getattr(module, validate_func)(value)

            if is_valid:
                column = resources[resource]['column']
                session.query(ModelCluster).filter_by(id=cluster_id)\
                       .update({column: json.dumps(value)})
            else:
                return errors.handle_mssing_input(
                    errors.InputMissingError(msg))

        return util.make_json_response(200, {"status": "OK"})
예제 #20
0
파일: api.py 프로젝트: yosshy/compass-core
    def put(self, host_id):
        """
        Update configuration of the specified cluster host

        :param host_id: the unique identifier of the host
        """
        with database.session() as session:
            host = session.query(ModelClusterHost).filter_by(id=host_id)\
                                                  .first()
            if not host:
                error_msg = "The host id=%s does not exist!" % host_id
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))
            logging.debug("cluster config put request.data %s", request.data)
            request_data = json.loads(request.data)
            if not request_data:
                error_msg = "request data is %s" % request_data
                return errors.handle_mssing_input(
                    errors.InputMissingError(error_msg))

            if not host.mutable:
                error_msg = "The host 'id=%s' is not mutable!" % host_id
                return errors.handle_invalid_usage(
                    errors.UserInvalidUsage(error_msg))

            #Valid if keywords in request_data are all correct
            if 'hostname' in request_data:
                hostname = request_data['hostname']
                cluster_id = host.cluster_id
                test_host = session.query(ModelClusterHost)\
                                   .filter_by(cluster_id=cluster_id,
                                              hostname=hostname).first()
                if test_host:
                    error_msg = ("Hostname '%s' has been used for other host "
                                 "in the cluster, cluster ID is %s!"
                                 % (hostname, cluster_id))

                    return errors.handle_invalid_usage(
                        errors.UserInvalidUsage(error_msg))

                session.query(ModelClusterHost).filter_by(id=host_id)\
                       .update({"hostname": request_data['hostname']})
                del request_data['hostname']

            try:
                util.valid_host_config(request_data)
            except errors.UserInvalidUsage as exc:
                return errors.handle_invalid_usage(exc)

            host.config = request_data

            return util.make_json_response(
                200, {"status": "OK"})
예제 #21
0
파일: api.py 프로젝트: jerryz1982/compass
    def _add_hosts(cluster_id, hosts):
        """Add cluster host(s) to the cluster by cluster_id"""

        cluseter_hosts = []
        available_machines = []
        failed_machines = []
        with database.session() as session:
            failed_machines = []
            for host in hosts:
                # Check if machine exists
                machine = session.query(ModelMachine).filter_by(id=host)\
                                                     .first()
                if not machine:
                    error_msg = "Machine id=%s does not exist!" % host
                    return errors.handle_not_exist(
                        errors.ObjectDoesNotExist(error_msg)
                        )
                clusterhost = session.query(ModelClusterHost)\
                                     .filter_by(machine_id=host)\
                                     .first()
                if clusterhost:
                    # Machine is already used
                    failed_machines.append(clusterhost.machine_id)
                    continue
                # Add the available machine to available_machines list
                available_machines.append(machine)

            if failed_machines:
                value = {
                    'failedMachines': failed_machines
                }
                error_msg = "Conflict!"
                return errors.handle_duplicate_object(
                    errors.ObjectDuplicateError(error_msg), value
                    )
            for machine, host in zip(available_machines, hosts):
                host = ModelClusterHost(cluster_id=cluster_id,
                                        machine_id=machine.id)
                session.add(host)
                session.flush()
                cluster_res = {}
                cluster_res['id'] = host.id
                cluster_res['machine_id'] = machine.id
                cluseter_hosts.append(cluster_res)

        logging.info('cluster_hosts result is %s', cluseter_hosts)
        return util.make_json_response(
            200, {
                "status": "OK",
                "clusterHosts": cluseter_hosts
                }
            )
예제 #22
0
파일: api.py 프로젝트: yosshy/compass-core
    def put(self, cluster_id, resource):
        """
        Update the resource information of the specified cluster in database

        :param cluster_id: the unique identifier of the cluster
        :param resource: resource name(security, networking, partition)
        """
        resources = {
            self.SECURITY: {'validator': 'is_valid_security_config',
                            'column': 'security_config'},
            self.NETWORKING: {'validator': 'is_valid_networking_config',
                              'column': 'networking_config'},
            self.PARTITION: {'validator': 'is_valid_partition_config',
                             'column': 'partition_config'},
        }
        request_data = json.loads(request.data)
        with database.session() as session:
            cluster = session.query(ModelCluster).filter_by(id=cluster_id)\
                                                 .first()

            if not cluster:
                error_msg = 'You are trying to update a non-existing cluster!'
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg)
                    )
            if resource not in request_data:
                error_msg = "Invalid resource name '%s'" % resource
                return errors.handle_invalid_usage(
                    errors.UserInvalidUsage(error_msg))

            value = request_data[resource]

            if resource not in resources.keys():
                error_msg = "Invalid resource name '%s'" % resource
                return errors.handle_invalid_usage(
                    errors.UserInvalidUsage(error_msg))

            validate_func = resources[resource]['validator']
            module = globals()['util']
            is_valid, msg = getattr(module, validate_func)(value)

            if is_valid:
                column = resources[resource]['column']
                session.query(ModelCluster).filter_by(id=cluster_id)\
                       .update({column: json.dumps(value)})
            else:
                return errors.handle_mssing_input(
                    errors.InputMissingError(msg))

        return util.make_json_response(
            200, {"status": "OK"})
예제 #23
0
파일: api.py 프로젝트: yosshy/compass-core
    def _deploy(cluster_id, hosts):
        """Deploy the cluster"""

        deploy_hosts_info = []
        deploy_cluster_info = {}
        with database.session() as session:
            if not hosts:
                # Deploy all hosts in the cluster
                cluster_hosts = session.query(ModelClusterHost)\
                                       .filter_by(cluster_id=cluster_id).all()

                if not cluster_hosts:
                    # No host belongs to this cluster
                    error_msg = ('Cannot find any host in cluster id=%s' %
                                 cluster_id)
                    return errors.handle_not_exist(
                        errors.ObjectDoesNotExist(error_msg))

                for host in cluster_hosts:
                    if not host.mutable:
                        # The host is not allowed to modified
                        error_msg = ("The host id=%s is not allowed to be "
                                     "modified now!") % host.id
                        return errors.UserInvalidUsage(
                            errors.UserInvalidUsage(error_msg))

                    hosts.append(host.id)

            deploy_cluster_info["cluster_id"] = int(cluster_id)
            deploy_cluster_info["url"] = '/clusters/%s/progress' % cluster_id

            for host_id in hosts:
                host_info = {}
                progress_url = '/cluster_hosts/%s/progress' % host_id
                host_info["host_id"] = host_id
                host_info["url"] = progress_url
                deploy_hosts_info.append(host_info)

            # Lock cluster hosts and its cluster
            session.query(ModelClusterHost).filter_by(cluster_id=cluster_id)\
                                           .update({'mutable': False})
            session.query(ModelCluster).filter_by(id=cluster_id)\
                                       .update({'mutable': False})

        celery.send_task("compass.tasks.trigger_install", (cluster_id, hosts))
        return util.make_json_response(
            202, {"status": "accepted",
                  "deployment": {
                      "cluster": deploy_cluster_info,
                      "hosts": deploy_hosts_info
                      }})
예제 #24
0
파일: api.py 프로젝트: yosshy/compass-core
    def get(self, cluster_id, resource=None):
        """
        Lists details of the specified cluster if resource is not specified.
        Otherwise, lists details of the resource of this cluster

        :param cluster_id: the unique identifier of the cluster
        :param resource: the resource name(security, networking, partition)
        """
        cluster_resp = {}
        resp = {}
        with database.session() as session:
            cluster = session.query(ModelCluster)\
                             .filter_by(id=cluster_id)\
                             .first()
            logging.debug('cluster is %s', cluster)
            if not cluster:
                error_msg = 'Cannot found the cluster with id=%s' % cluster_id
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg)
                    )

            if resource:
                # List resource details
                if resource == self.SECURITY:
                    cluster_resp = cluster.security
                elif resource == self.NETWORKING:
                    cluster_resp = cluster.networking
                elif resource == self.PARTITION:
                    cluster_resp = cluster.partition
                else:
                    error_msg = "Invalid resource name '%s'!" % resource
                    return errors.handle_invalid_usage(
                        errors.UserInvalidUsage(error_msg)
                    )
                resp = {"status": "OK",
                        resource: cluster_resp}

            else:
                cluster_resp['clusterName'] = cluster.name
                cluster_resp['link'] = {
                    'rel': 'self',
                    'href': '/'.join((self.ENDPOINT, str(cluster.id)))
                }
                cluster_resp['id'] = cluster.id
                resp = {"status": "OK",
                        "cluster": cluster_resp}

        logging.info('get cluster result is %s', cluster_resp)
        return util.make_json_response(200, resp)
예제 #25
0
파일: api.py 프로젝트: gasopbf1/compasstest
    def _add_hosts(cluster_id, hosts):
        """Add cluster host(s) to the cluster by cluster_id"""

        cluseter_hosts = []
        available_machines = []
        failed_machines = []
        with database.session() as session:
            failed_machines = []
            for host in hosts:
                # Check if machine exists
                machine = session.query(ModelMachine).filter_by(id=host)\
                                                     .first()
                if not machine:
                    error_msg = "Machine id=%s does not exist!" % host
                    return errors.handle_not_exist(
                        errors.ObjectDoesNotExist(error_msg))
                clusterhost = session.query(ModelClusterHost)\
                                     .filter_by(machine_id=host)\
                                     .first()
                if clusterhost:
                    # Machine is already used
                    failed_machines.append(clusterhost.machine_id)
                    continue
                # Add the available machine to available_machines list
                available_machines.append(machine)

            if failed_machines:
                value = {'failedMachines': failed_machines}
                error_msg = "Conflict!"
                return errors.handle_duplicate_object(
                    errors.ObjectDuplicateError(error_msg), value)
            for machine, host in zip(available_machines, hosts):
                host = ModelClusterHost(cluster_id=cluster_id,
                                        machine_id=machine.id)
                session.add(host)
                session.flush()
                cluster_res = {}
                cluster_res['id'] = host.id
                cluster_res['machine_id'] = machine.id
                cluseter_hosts.append(cluster_res)

        logging.info('cluster_hosts result is %s', cluseter_hosts)
        return util.make_json_response(200, {
            "status": "OK",
            "cluster_hosts": cluseter_hosts
        })
예제 #26
0
파일: api.py 프로젝트: gasopbf1/compasstest
    def put(self, switch_id):
        """Update an existing switch information.

        :param switch_id: the unqiue identifier of the switch
        """
        switch = None
        with database.session() as session:
            switch = session.query(ModelSwitch).filter_by(id=switch_id).first()
            logging.info('PUT switch id is %s: %s', switch_id, switch)

            if not switch:
                # No switch is found.
                error_msg = 'Cannot update a non-existing switch!'
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

        credential = None
        logging.debug('PUT a switch request from curl is %s', request.data)
        json_data = json.loads(request.data)
        credential = json_data['switch']['credential']

        logging.info('PUT switch id=%s credential=%s(%s)', switch_id,
                     credential, type(credential))
        ip_addr = None
        switch_res = {}
        with database.session() as session:
            switch = session.query(ModelSwitch).filter_by(id=switch_id).first()
            switch.credential = credential
            switch.state = "not_reached"

            ip_addr = switch.ip
            switch_res['id'] = switch.id
            switch_res['ip'] = switch.ip
            switch_res['state'] = switch.state
            link = {
                'rel': 'self',
                'href': '/'.join((self.ENDPOINT, str(switch.id)))
            }
            switch_res['link'] = link

        celery.send_task("compass.tasks.pollswitch", (ip_addr, ))
        return util.make_json_response(202, {
            "status": "accepted",
            "switch": switch_res
        })
예제 #27
0
파일: api.py 프로젝트: gasopbf1/compasstest
    def get(self, cluster_id, resource=None):
        """
        Lists details of the specified cluster if resource is not specified.
        Otherwise, lists details of the resource of this cluster

        :param cluster_id: the unique identifier of the cluster
        :param resource: the resource name(security, networking, partition)
        """
        cluster_resp = {}
        resp = {}
        with database.session() as session:
            cluster = session.query(ModelCluster)\
                             .filter_by(id=cluster_id)\
                             .first()
            logging.debug('cluster is %s', cluster)
            if not cluster:
                error_msg = 'Cannot found the cluster with id=%s' % cluster_id
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            if resource:
                # List resource details
                if resource == self.SECURITY:
                    cluster_resp = cluster.security
                elif resource == self.NETWORKING:
                    cluster_resp = cluster.networking
                elif resource == self.PARTITION:
                    cluster_resp = cluster.partition
                else:
                    error_msg = "Invalid resource name '%s'!" % resource
                    return errors.handle_invalid_usage(
                        errors.UserInvalidUsage(error_msg))
                resp = {"status": "OK", resource: cluster_resp}

            else:
                cluster_resp['clusterName'] = cluster.name
                cluster_resp['link'] = {
                    'rel': 'self',
                    'href': '/'.join((self.ENDPOINT, str(cluster.id)))
                }
                cluster_resp['id'] = cluster.id
                resp = {"status": "OK", "cluster": cluster_resp}

        logging.info('get cluster result is %s', cluster_resp)
        return util.make_json_response(200, resp)
예제 #28
0
파일: api.py 프로젝트: yosshy/compass-core
    def put(self, switch_id):
        """Update an existing switch information.

        :param switch_id: the unqiue identifier of the switch
        """
        switch = None
        credential = None
        logging.debug('PUT a switch request from curl is %s', request.data)

        ip_addr = None
        switch_res = {}

        with database.session() as session:
            switch = session.query(ModelSwitch).filter_by(id=switch_id).first()
            logging.info('PUT switch id is %s: %s', switch_id, switch)

            if not switch:
                # No switch is found.
                error_msg = 'Cannot update a non-existing switch!'
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            json_data = json.loads(request.data)
            credential = json_data['switch']['credential']

            logging.info('PUT switch id=%s credential=%s(%s)',
                         switch_id, credential, type(credential))

            switch.credential = credential
            switch.state = "repolling"
            switch.err_msg = ""

            ip_addr = switch.ip
            switch_res['id'] = switch.id
            switch_res['ip'] = switch.ip
            switch_res['state'] = switch.state
            link = {'rel': 'self',
                    'href': '/'.join((self.ENDPOINT, str(switch.id)))}
            switch_res['link'] = link

        celery.send_task("compass.tasks.pollswitch", (ip_addr,))
        return util.make_json_response(
            202, {"status": "accepted",
                  "switch": switch_res})
예제 #29
0
파일: api.py 프로젝트: yosshy/compass-core
    def _remove_hosts(cluster_id, hosts):
        """Remove existing cluster host from the cluster"""

        removed_hosts = []
        with database.session() as session:
            failed_hosts = []
            for host_id in hosts:
                host = session.query(ModelClusterHost)\
                              .filter_by(id=host_id, cluster_id=cluster_id)\
                              .first()

                if not host:
                    failed_hosts.append(host_id)
                    continue

                host_res = {
                    "id": host_id,
                    "machine_id": host.machine_id
                }
                removed_hosts.append(host_res)

            if failed_hosts:
                error_msg = 'Hosts do not exist! Or not in this cluster'
                value = {
                    "failedHosts": failed_hosts
                }
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg), value
                    )

            filter_clause = []
            for host_id in hosts:
                filter_clause.append('id=%s' % host_id)

            # Delete the requested hosts from database
            session.query(ModelClusterHost).filter(or_(*filter_clause))\
                   .delete(synchronize_session='fetch')

        return util.make_json_response(
            200, {
                "status": "OK",
                "cluster_hosts": removed_hosts
                }
            )
예제 #30
0
파일: api.py 프로젝트: yosshy/compass-core
    def post(self):
        """Create a new cluster.

        :param name: the name of the cluster
        :param adapter_id: the unique identifier of the adapter
        """
        request_data = None
        request_data = json.loads(request.data)
        cluster_name = request_data['cluster']['name']
        adapter_id = request_data['cluster']['adapter_id']
        cluster_resp = {}
        cluster = None

        with database.session() as session:
            cluster = session.query(ModelCluster).filter_by(name=cluster_name)\
                                                 .first()
            if cluster:
                error_msg = "Cluster name '%s' already exists!" % cluster.name
                return errors.handle_duplicate_object(
                    errors.ObjectDuplicateError(error_msg))

            adapter = session.query(Adapter).filter_by(id=adapter_id).first()
            if not adapter:
                error_msg = "No adapter id=%s can be found!" % adapter_id
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            # Create a new cluster in database
            cluster = ModelCluster(name=cluster_name, adapter_id=adapter_id)
            session.add(cluster)
            session.flush()
            cluster_resp['id'] = cluster.id
            cluster_resp['name'] = cluster.name
            cluster_resp['adapter_id'] = cluster.adapter_id
            cluster_resp['link'] = {
                'rel': 'self',
                'href': '/'.join((self.ENDPOINT, str(cluster.id)))
            }

        return util.make_json_response(
            200, {"status": "OK",
                  "cluster": cluster_resp}
            )
예제 #31
0
파일: api.py 프로젝트: jerryz1982/compass
    def get(self, host_id):
        """
        Lists configuration details of a specific cluster host
        :param host_id: the cluster host ID
        """
        config_res = {}
        with database.session() as session:
            host = session.query(ModelClusterHost).filter_by(id=host_id)\
                                                  .first()
            if not host:
                # The host does not exist.
                error_msg = "The host id=%s does not exist!" % host_id
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            config_res = host.config

        logging.debug("The config of host id=%s is %s", host_id, config_res)
        return util.make_json_response(
            200, {"status": "OK",
                  "config": config_res})
예제 #32
0
파일: api.py 프로젝트: gasopbf1/compasstest
    def get(self, host_id):
        """Lists configuration details of the specified cluster host

        :param host_id: the unique identifier of the host
        """
        config_res = {}
        with database.session() as session:
            host = session.query(ModelClusterHost).filter_by(id=host_id)\
                                                  .first()
            if not host:
                # The host does not exist.
                error_msg = "The host id=%s does not exist!" % host_id
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            config_res = host.config

        logging.debug("The config of host id=%s is %s", host_id, config_res)
        return util.make_json_response(200, {
            "status": "OK",
            "config": config_res
        })
예제 #33
0
파일: api.py 프로젝트: gasopbf1/compasstest
    def put(self, host_id):
        """
        Update configuration of the specified cluster host

        :param host_id: the unique identifier of the host
        """
        with database.session() as session:
            host = session.query(ModelClusterHost).filter_by(id=host_id)\
                                                  .first()
            if not host:
                error_msg = "The host id=%s does not exist!" % host_id
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))
            logging.debug("cluster config put request.data %s", request.data)
            request_data = json.loads(request.data)
            if not request_data:
                error_msg = "request data is %s" % request_data
                return errors.handle_mssing_input(
                    errors.InputMissingError(error_msg))

            if not host.mutable:
                error_msg = "The host 'id=%s' is not mutable!" % host_id
                return errors.handle_invalid_usage(
                    errors.UserInvalidUsage(error_msg))

            #Valid if keywords in request_data are all correct
            if 'hostname' in request_data:
                session.query(ModelClusterHost).filter_by(id=host_id)\
                       .update({"hostname": request_data['hostname']})
                del request_data['hostname']

            try:
                util.valid_host_config(request_data)
            except errors.UserInvalidUsage as exc:
                return errors.handle_invalid_usage(exc)

            host.config = request_data

            return util.make_json_response(200, {"status": "OK"})
예제 #34
0
파일: api.py 프로젝트: gasopbf1/compasstest
    def get(self, machine_id):
        """
        Lists details of the specified machine.

        :param machine_id: the unique identifier of the machine
        """
        machine_res = {}
        with database.session() as session:
            machine = session.query(ModelMachine)\
                             .filter_by(id=machine_id)\
                             .first()
            logging.info('machine for id %s: %s', machine_id, machine)

            if not machine:
                error_msg = "Cannot find the machine with id=%s" % machine_id
                logging.error("[/api/machines/{id}]error_msg: %s", error_msg)

                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            machine_res['id'] = machine.id
            machine_res['mac'] = machine.mac
            machine_res['port'] = machine.port
            machine_res['vlan'] = machine.vlan
            if machine.switch:
                machine_res['switch_ip'] = machine.switch.ip
            else:
                machine_res['switch_ip'] = None
            machine_res['link'] = {
                'rel': 'self',
                'href': '/'.join((self.ENDPOINT, str(machine.id)))
            }

        logging.info('machine info for %s: %s', machine_id, machine_res)
        return util.make_json_response(200, {
            "status": "OK",
            "machine": machine_res
        })
예제 #35
0
파일: api.py 프로젝트: jerryz1982/compass
 def get(self, host_id):
     """
     Lists details of a specific cluster host
     :param host_id: cluster host ID in db
     """
     host_res = {}
     with database.session() as session:
         host = session.query(ModelClusterHost).filter_by(id=host_id)\
                                               .first()
         if not host:
             error_msg = "The host id=%s does not exist!" % host_id
             return errors.handle_not_exist(
                 errors.ObjectDoesNotExist(error_msg))
         host_res['hostname'] = host.hostname
         host_res['mutable'] = host.mutable
         host_res['id'] = host.id
         host_res['link'] = {
             "href": '/'.join((self.ENDPOINT, str(host.id))),
             "rel": "self"
         }
     return util.make_json_response(
         200, {"status": "OK",
               "cluster_host": host_res})
예제 #36
0
파일: api.py 프로젝트: gasopbf1/compasstest
    def get(self, host_id):
        """Lists details of the specified cluster host

        :param host_id: the unique identifier of the host
        """
        host_res = {}
        with database.session() as session:
            host = session.query(ModelClusterHost).filter_by(id=host_id)\
                                                  .first()
            if not host:
                error_msg = "The host id=%s does not exist!" % host_id
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))
            host_res['hostname'] = host.hostname
            host_res['mutable'] = host.mutable
            host_res['id'] = host.id
            host_res['link'] = {
                "href": '/'.join((self.ENDPOINT, str(host.id))),
                "rel": "self"
            }
        return util.make_json_response(200, {
            "status": "OK",
            "cluster_host": host_res
        })
예제 #37
0
파일: api.py 프로젝트: gasopbf1/compasstest
def execute_cluster_action(cluster_id):
    """Execute the specified  action to the cluster.

    :param cluster_id: the unique identifier of the cluster
    :param addHosts: the action of adding excepted hosts to the cluster
    :param removeHosts: the action of removing expected hosts from the cluster
    :param replaceAllHosts: the action of removing all existing hosts in
                            cluster and add new hosts
    :param deploy: the action of starting to deploy
    """
    def _add_hosts(cluster_id, hosts):
        """Add cluster host(s) to the cluster by cluster_id"""

        cluseter_hosts = []
        available_machines = []
        failed_machines = []
        with database.session() as session:
            failed_machines = []
            for host in hosts:
                # Check if machine exists
                machine = session.query(ModelMachine).filter_by(id=host)\
                                                     .first()
                if not machine:
                    error_msg = "Machine id=%s does not exist!" % host
                    return errors.handle_not_exist(
                        errors.ObjectDoesNotExist(error_msg))
                clusterhost = session.query(ModelClusterHost)\
                                     .filter_by(machine_id=host)\
                                     .first()
                if clusterhost:
                    # Machine is already used
                    failed_machines.append(clusterhost.machine_id)
                    continue
                # Add the available machine to available_machines list
                available_machines.append(machine)

            if failed_machines:
                value = {'failedMachines': failed_machines}
                error_msg = "Conflict!"
                return errors.handle_duplicate_object(
                    errors.ObjectDuplicateError(error_msg), value)
            for machine, host in zip(available_machines, hosts):
                host = ModelClusterHost(cluster_id=cluster_id,
                                        machine_id=machine.id)
                session.add(host)
                session.flush()
                cluster_res = {}
                cluster_res['id'] = host.id
                cluster_res['machine_id'] = machine.id
                cluseter_hosts.append(cluster_res)

        logging.info('cluster_hosts result is %s', cluseter_hosts)
        return util.make_json_response(200, {
            "status": "OK",
            "cluster_hosts": cluseter_hosts
        })

    def _remove_hosts(cluster_id, hosts):
        """Remove existing cluster host from the cluster"""

        removed_hosts = []
        with database.session() as session:
            failed_hosts = []
            for host_id in hosts:
                host = session.query(ModelClusterHost).filter_by(id=host_id)\
                                                      .first()

                if not host:
                    failed_hosts.append(host)
                    continue

                host_res = {"id": host_id, "machine_id": host.machine_id}
                removed_hosts.append(host_res)

            if failed_hosts:
                error_msg = 'Cluster hosts do not exist!'
                value = {"failedHosts": failed_hosts}
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg), value)

            filter_clause = []
            for host_id in hosts:
                filter_clause.append('id=%s' % host_id)

            # Delete the requested hosts from database
            session.query(ModelClusterHost).filter(or_(*filter_clause))\
                   .delete(synchronize_session='fetch')

        return util.make_json_response(200, {
            "status": "OK",
            "cluster_hosts": removed_hosts
        })

    def _replace_all_hosts(cluster_id, hosts):
        """Remove all existing hosts from the cluster and add new ones"""

        with database.session() as session:
            # Delete all existing hosts of the cluster
            session.query(ModelClusterHost)\
                   .filter_by(cluster_id=cluster_id).delete()
            session.flush()
        return _add_hosts(cluster_id, hosts)

    def _deploy(cluster_id):
        """Deploy the cluster"""

        deploy_hosts_urls = []
        with database.session() as session:
            cluster_hosts_ids = session.query(ModelClusterHost.id)\
                                       .filter_by(cluster_id=cluster_id).all()
            if not cluster_hosts_ids:
                # No host belongs to this cluster
                error_msg = ('Cannot find any host in cluster id=%s' %
                             cluster_id)
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            for elm in cluster_hosts_ids:
                host_id = str(elm[0])
                progress_url = '/cluster_hosts/%s/progress' % host_id
                deploy_hosts_urls.append(progress_url)

            # Lock cluster hosts and its cluster
            session.query(ModelClusterHost).filter_by(cluster_id=cluster_id)\
                                           .update({'mutable': False})
            session.query(ModelCluster).filter_by(id=cluster_id)\
                                       .update({'mutable': False})

        celery.send_task("compass.tasks.trigger_install", (cluster_id, ))
        return util.make_json_response(202, {
            "status": "OK",
            "deployment": deploy_hosts_urls
        })

    request_data = None
    with database.session() as session:
        cluster = session.query(ModelCluster).filter_by(id=cluster_id).first()
        if not cluster:
            error_msg = 'Cluster id=%s does not exist!'
            return errors.handle_not_exist(
                errors.ObjectDoesNotExist(error_msg))
        if not cluster.mutable:
            # The cluster cannot be deploy again
            error_msg = "The cluster id=%s cannot deploy again!" % cluster_id
            return errors.handle_invalid_usage(
                errors.UserInvalidUsage(error_msg))

    request_data = json.loads(request.data)
    action = request_data.keys()[0]
    value = request_data.get(action)

    if 'addHosts' in request_data:
        return _add_hosts(cluster_id, value)

    elif 'removeHosts' in request_data:
        return _remove_hosts(cluster_id, value)

    elif 'deploy' in request_data:
        return _deploy(cluster_id)

    elif 'replaceAllHosts' in request_data:
        return _replace_all_hosts(cluster_id, value)
    else:
        return errors.handle_invalid_usage(
            errors.UserInvalidUsage('%s action is not support!' % action))
예제 #38
0
파일: api.py 프로젝트: jerryz1982/compass
def execute_cluster_action(cluster_id):
    """
    Execute a specific action to the cluster:
    addHosts: add excepted hosts to the cluster
    removeHosts: remove expected hosts from the cluster
    replaceAllHosts: remove all existing hosts in cluster and add new hosts
    deploy: start to deploy

    :param cluster_id: string of cluster id
    """
    def _add_hosts(cluster_id, hosts):
        """Add cluster host(s) to the cluster by cluster_id"""

        cluseter_hosts = []
        available_machines = []
        failed_machines = []
        with database.session() as session:
            failed_machines = []
            for host in hosts:
                # Check if machine exists
                machine = session.query(ModelMachine).filter_by(id=host)\
                                                     .first()
                if not machine:
                    error_msg = "Machine id=%s does not exist!" % host
                    return errors.handle_not_exist(
                        errors.ObjectDoesNotExist(error_msg)
                        )
                clusterhost = session.query(ModelClusterHost)\
                                     .filter_by(machine_id=host)\
                                     .first()
                if clusterhost:
                    # Machine is already used
                    failed_machines.append(clusterhost.machine_id)
                    continue
                # Add the available machine to available_machines list
                available_machines.append(machine)

            if failed_machines:
                value = {
                    'failedMachines': failed_machines
                }
                error_msg = "Conflict!"
                return errors.handle_duplicate_object(
                    errors.ObjectDuplicateError(error_msg), value
                    )
            for machine, host in zip(available_machines, hosts):
                host = ModelClusterHost(cluster_id=cluster_id,
                                        machine_id=machine.id)
                session.add(host)
                session.flush()
                cluster_res = {}
                cluster_res['id'] = host.id
                cluster_res['machine_id'] = machine.id
                cluseter_hosts.append(cluster_res)

        logging.info('cluster_hosts result is %s', cluseter_hosts)
        return util.make_json_response(
            200, {
                "status": "OK",
                "clusterHosts": cluseter_hosts
                }
            )

    def _remove_hosts(cluster_id, hosts):
        """Remove existing cluster host from the cluster"""

        removed_hosts = []
        with database.session() as session:
            failed_hosts = []
            for host_id in hosts:
                host = session.query(ModelClusterHost).filter_by(id=host_id)\
                                                      .first()

                if not host:
                    failed_hosts.append(host)
                    continue

                host_res = {
                    "id": host_id,
                    "machine_id": host.machine_id
                }
                removed_hosts.append(host_res)

            if failed_hosts:
                error_msg = 'Cluster hosts do not exist!'
                value = {
                    "failedHosts": failed_hosts
                }
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg), value
                    )

            filter_clause = []
            for host_id in hosts:
                filter_clause.append('id=%s' % host_id)

            # Delete the requested hosts from database
            session.query(ModelClusterHost).filter(or_(*filter_clause))\
                   .delete(synchronize_session='fetch')

        return util.make_json_response(
            200, {
                "status": "OK",
                "clusterHosts": removed_hosts
                }
            )

    def _replace_all_hosts(cluster_id, hosts):
        """Remove all existing hosts from the cluster and add new ones"""

        with database.session() as session:
            # Delete all existing hosts of the cluster
            session.query(ModelClusterHost)\
                   .filter_by(cluster_id=cluster_id).delete()
            session.flush()
        return _add_hosts(cluster_id, hosts)

    def _deploy(cluster_id):
        """Deploy the cluster"""

        deploy_hosts_urls = []
        with database.session() as session:
            cluster_hosts_ids = session.query(ModelClusterHost.id)\
                                       .filter_by(cluster_id=cluster_id).all()
            if not cluster_hosts_ids:
                # No host belongs to this cluster
                error_msg = ('Cannot find any host in cluster id=%s' %
                             cluster_id)
                return errors.handle_not_exist(
                    errors.ObjectDoesNotExist(error_msg))

            for host_id in cluster_hosts_ids:
                progress_url = '/cluster_hosts/%s/progress' % str(host_id)
                deploy_hosts_urls.append(progress_url)

            # Lock cluster hosts and its cluster
            session.query(ModelClusterHost).filter_by(cluster_id=cluster_id)\
                                           .update({'mutable': False})
            session.query(ModelCluster).filter_by(id=cluster_id)\
                                       .update({'mutable': False})

        celery.send_task("compass.tasks.trigger_install", (cluster_id,))
        return util.make_json_response(
            202, {"status": "OK",
                  "deployment": deploy_hosts_urls})

    request_data = None
    with database.session() as session:
        cluster = session.query(ModelCluster).filter_by(id=cluster_id).first()
        if not cluster:
            error_msg = 'Cluster id=%s does not exist!'
            return errors.handle_not_exist(
                errors.ObjectDoesNotExist(error_msg)
                )
        if not cluster.mutable:
            # The cluster cannot be deploy again
            error_msg = "The cluster id=%s cannot deploy again!" % cluster_id
            return errors.handle_invalid_usage(
                errors.UserInvalidUsage(error_msg))

    request_data = json.loads(request.data)
    action = request_data.keys()[0]
    value = request_data.get(action)

    if 'addHosts' in request_data:
        return _add_hosts(cluster_id, value)

    elif 'removeHosts' in request_data:
        return _remove_hosts(cluster_id, value)

    elif 'deploy' in request_data:
        return _deploy(cluster_id)

    elif 'replaceAllHosts' in request_data:
        return _replace_all_hosts(cluster_id, value)
    else:
        return errors.handle_invalid_usage(
            errors.UserInvalidUsage('%s action is not support!' % action)
            )