示例#1
0
    def on_put(self, req, resp, name):
        """
        Handles the creation of a new Cluster.

        :param req: Request instance that will be passed through.
        :type req: falcon.Request
        :param resp: Response instance that will be passed through.
        :type resp: falcon.Response
        :param name: The name of the Cluster being created.
        :type name: str
        """
        # PUT is idempotent, and since there's no body to this request,
        # there's nothing to conflict with.  The request should always
        # succeed, even if we didn't actually do anything.
        key = '/commissaire/clusters/{0}'.format(name)
        try:
            etcd_resp = self.store.get(key)
            self.logger.info(
                'Creation of already exisiting cluster {0} requested.'.format(
                    name))
        except etcd.EtcdKeyNotFound:
            cluster = Cluster(status='ok', hostset=[])
            etcd_resp = self.store.set(key, cluster.to_json(secure=True))
            self.logger.info(
                'Created cluster {0} per request.'.format(name))
        cluster = Cluster(**json.loads(etcd_resp.value))
        resp.status = falcon.HTTP_201
示例#2
0
    def on_put(self, req, resp, name):
        """
        Handles the creation of a new Cluster.

        :param req: Request instance that will be passed through.
        :type req: falcon.Request
        :param resp: Response instance that will be passed through.
        :type resp: falcon.Response
        :param name: The name of the Cluster being created.
        :type name: str
        """
        # PUT is idempotent, and since there's no body to this request,
        # there's nothing to conflict with.  The request should always
        # succeed, even if we didn't actually do anything.
        if util.etcd_cluster_exists(self.store, name):
            self.logger.info(
                'Creation of already exisiting cluster {0} requested.'.format(
                    name))
        else:
            key = util.etcd_cluster_key(name)
            cluster = Cluster(status='ok', hostset=[])
            etcd_resp = self.store.set(key, cluster.to_json(secure=True))
            self.logger.info(
                'Created cluster {0} per request.'.format(name))
            self.logger.debug('Etcd Response: {0}'.format(etcd_resp))
        resp.status = falcon.HTTP_201
示例#3
0
    def on_put(self, req, resp, name):
        """
        Handles the creation of a new Cluster.

        :param req: Request instance that will be passed through.
        :type req: falcon.Request
        :param resp: Response instance that will be passed through.
        :type resp: falcon.Response
        :param name: The name of the Cluster being created.
        :type name: str
        """
        # PUT is idempotent, and since there's no body to this request,
        # there's nothing to conflict with.  The request should always
        # succeed, even if we didn't actually do anything.
        if util.etcd_cluster_exists(name):
            self.logger.info(
                'Creation of already exisiting cluster {0} requested.'.format(
                    name))
        else:
            key = util.etcd_cluster_key(name)
            cluster = Cluster(status='ok', hostset=[])
            etcd_resp, _ = cherrypy.engine.publish(
                'store-save', key, cluster.to_json(secure=True))[0]
            self.logger.info('Created cluster {0} per request.'.format(name))
            self.logger.debug('Etcd Response: {0}'.format(etcd_resp))
        resp.status = falcon.HTTP_201
示例#4
0
    def on_delete(self, req, resp, address):
        """
        Handles the Deletion of a Host.

        :param req: Request instance that will be passed through.
        :type req: falcon.Request
        :param resp: Response instance that will be passed through.
        :type resp: falcon.Response
        :param address: The address of the Host being requested.
        :type address: str
        """
        resp.body = "{}"
        try:
            host = self.store.delete("/commissaire/hosts/{0}".format(address))
            resp.status = falcon.HTTP_410
        except etcd.EtcdKeyNotFound:
            resp.status = falcon.HTTP_404

        # Also remove the host from all clusters.
        # Note: We've done all we need to for the host deletion,
        #       so if an error occurs from here just log it and
        #       return.
        try:
            clusters_dir = self.store.get("/commissaire/clusters")
        except etcd.EtcdKeyNotFound:
            self.logger.warn("Etcd does not have any clusters")
            return
        if len(clusters_dir._children):
            for etcd_resp in clusters_dir.leaves:
                cluster = Cluster(**json.loads(etcd_resp.value))
                if address in cluster.hostset:
                    cluster.hostset.remove(address)
                    self.store.set(etcd_resp.key, cluster.to_json(secure=True))
示例#5
0
    def on_delete(self, req, resp, address):
        """
        Handles the Deletion of a Host.

        :param req: Request instance that will be passed through.
        :type req: falcon.Request
        :param resp: Response instance that will be passed through.
        :type resp: falcon.Response
        :param address: The address of the Host being requested.
        :type address: str
        """
        resp.body = '{}'
        try:
            self.store.delete(util.etcd_host_key(address))
            resp.status = falcon.HTTP_200
        except etcd.EtcdKeyNotFound:
            resp.status = falcon.HTTP_404

        # Also remove the host from all clusters.
        # Note: We've done all we need to for the host deletion,
        #       so if an error occurs from here just log it and
        #       return.
        try:
            clusters_dir = self.store.get('/commissaire/clusters')
            self.logger.debug('Etcd Response: {0}'.format(clusters_dir))
        except etcd.EtcdKeyNotFound:
            self.logger.warn('Etcd does not have any clusters')
            return
        if len(clusters_dir._children):
            self.logger.info(
                'There are clusters associated with {0}...'.format(address))
            for etcd_resp in clusters_dir.leaves:
                cluster = Cluster(**json.loads(etcd_resp.value))
                if address in cluster.hostset:
                    cluster_name = etcd_resp.key.split('/')[-1]
                    self.logger.info('Removing {0} from cluster {1}'.format(
                        address, cluster_name))
                    cluster.hostset.remove(address)
                    self.store.set(etcd_resp.key, cluster.to_json(secure=True))
                    self.logger.info(
                        '{0} has been removed from cluster {1}'.format(
                            address, cluster_name))
示例#6
0
    def on_delete(self, req, resp, address):
        """
        Handles the Deletion of a Host.

        :param req: Request instance that will be passed through.
        :type req: falcon.Request
        :param resp: Response instance that will be passed through.
        :type resp: falcon.Response
        :param address: The address of the Host being requested.
        :type address: str
        """
        resp.body = '{}'
        try:
            self.store.delete(util.etcd_host_key(address))
            resp.status = falcon.HTTP_200
        except etcd.EtcdKeyNotFound:
            resp.status = falcon.HTTP_404

        # Also remove the host from all clusters.
        # Note: We've done all we need to for the host deletion,
        #       so if an error occurs from here just log it and
        #       return.
        try:
            clusters_dir = self.store.get('/commissaire/clusters')
            self.logger.debug('Etcd Response: {0}'.format(clusters_dir))
        except etcd.EtcdKeyNotFound:
            self.logger.warn('Etcd does not have any clusters')
            return
        if len(clusters_dir._children):
            self.logger.info(
                'There are clusters associated with {0}...'.format(address))
            for etcd_resp in clusters_dir.leaves:
                cluster = Cluster(**json.loads(etcd_resp.value))
                if address in cluster.hostset:
                    cluster_name = etcd_resp.key.split('/')[-1]
                    self.logger.info('Removing {0} from cluster {1}'.format(
                        address, cluster_name))
                    cluster.hostset.remove(address)
                    self.store.set(etcd_resp.key, cluster.to_json(secure=True))
                    self.logger.info(
                        '{0} has been removed from cluster {1}'.format(
                            address, cluster_name))
示例#7
0
    def on_put(self, req, resp, address):
        """
        Handles the creation of a new Host.

        :param req: Request instance that will be passed through.
        :type req: falcon.Request
        :param resp: Response instance that will be passed through.
        :type resp: falcon.Response
        :param address: The address of the Host being requested.
        :type address: str
        """
        # TODO: Verify input
        try:
            host = self.store.get("/commissaire/hosts/{0}".format(address))
            resp.status = falcon.HTTP_409
            return
        except etcd.EtcdKeyNotFound:
            pass

        data = req.stream.read().decode()
        host_creation = json.loads(data)
        ssh_priv_key = host_creation["ssh_priv_key"]
        host_creation["address"] = address
        host_creation["os"] = ""
        host_creation["status"] = "investigating"
        host_creation["cpus"] = -1
        host_creation["memory"] = -1
        host_creation["space"] = -1
        host_creation["last_check"] = None

        # Don't store the cluster name in etcd.
        cluster_name = host_creation.pop("cluster", None)

        # Verify the cluster exists, if given.  Do it now
        # so we can fail before writing anything to etcd.
        if cluster_name:
            # XXX: Based on ClusterSingleHostResource.on_put().
            #      Add a util module to share common operations.
            cluster_key = "/commissaire/clusters/{0}".format(cluster_name)
            try:
                etcd_resp = self.store.get(cluster_key)
                self.logger.info("Request for cluster {0}".format(cluster_name))
                self.logger.debug("{0}".format(etcd_resp))
            except etcd.EtcdKeyNotFound:
                self.logger.info("Request for non-existent cluster {0}.".format(cluster_name))
                resp.status = falcon.HTTP_409
                return
            cluster = Cluster(**json.loads(etcd_resp.value))
            hostset = set(cluster.hostset)
            hostset.add(address)  # Ensures no duplicates
            cluster.hostset = list(hostset)

        host = Host(**host_creation)
        new_host = self.store.set("/commissaire/hosts/{0}".format(address), host.to_json(secure=True))
        INVESTIGATE_QUEUE.put((host_creation, ssh_priv_key))

        # Add host to the requested cluster.
        if cluster_name:
            # 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.
            self.store.set(cluster_key, cluster.to_json(secure=True))

        resp.status = falcon.HTTP_201
        req.context["model"] = Host(**json.loads(new_host.value))