Exemplo n.º 1
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))