def on_put(self, req, resp, name): """ Handles PUT requests for Cluster hosts. This replaces the entire host list for a 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 requested. :type name: str """ try: req_body = json.loads(req.stream.read().decode()) old_hosts = set(req_body['old']) # Ensures no duplicates new_hosts = set(req_body['new']) # Ensures no duplicates except (KeyError, TypeError): self.logger.info( 'Bad client PUT request for cluster {0}: {1}'. format(name, req_body)) resp.status = falcon.HTTP_400 return cluster = util.get_cluster_model(name) if not cluster: resp.status = falcon.HTTP_404 return # old_hosts must match current hosts to accept new_hosts. # Note: Order doesn't matter, so etcd's atomic comparison # of the raw values would be too strict. if old_hosts != set(cluster.hostset): self.logger.info( 'Conflict setting hosts for cluster {0}'.format(name)) resp.status = falcon.HTTP_409 return # FIXME: Need input validation. For each new host, # - Does the host exist at /commissaire/hosts/{IP}? # - 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. cluster.hostset = list(new_hosts) cherrypy.engine.publish( 'store-save', cluster.etcd.key, cluster.to_json(secure=True)) resp.status = falcon.HTTP_200
def on_put(self, req, resp, name): """ Handles PUT requests for Cluster hosts. This replaces the entire host list for a 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 requested. :type name: str """ try: req_body = json.loads(req.stream.read().decode()) old_hosts = set(req_body['old']) # Ensures no duplicates new_hosts = set(req_body['new']) # Ensures no duplicates except (KeyError, TypeError): self.logger.info( 'Bad client PUT request for cluster {0}: {1}'.format( name, req_body)) resp.status = falcon.HTTP_400 return cluster = util.get_cluster_model(name) if not cluster: resp.status = falcon.HTTP_404 return # old_hosts must match current hosts to accept new_hosts. # Note: Order doesn't matter, so etcd's atomic comparison # of the raw values would be too strict. if old_hosts != set(cluster.hostset): self.logger.info( 'Conflict setting hosts for cluster {0}'.format(name)) resp.status = falcon.HTTP_409 return # FIXME: Need input validation. For each new host, # - Does the host exist at /commissaire/hosts/{IP}? # - 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. cluster.hostset = list(new_hosts) cherrypy.engine.publish('store-save', cluster.etcd.key, cluster.to_json(secure=True)) resp.status = falcon.HTTP_200
def on_get(self, req, resp, name): """ Handles GET requests for Cluster hosts. :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 requested. :type name: str """ cluster = util.get_cluster_model(self.store, name) if not cluster: resp.status = falcon.HTTP_404 return resp.body = json.dumps(cluster.hostset) resp.status = falcon.HTTP_200
def on_get(self, req, resp, name): """ Handles GET requests for Cluster hosts. :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 requested. :type name: str """ cluster = util.get_cluster_model(name) if not cluster: resp.status = falcon.HTTP_404 return resp.body = json.dumps(cluster.hostset) resp.status = falcon.HTTP_200
def on_get(self, req, resp, name): """ Handles retrieval of an existing 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 requested. :type name: str """ cluster = util.get_cluster_model(self.store, name) if not cluster: resp.status = falcon.HTTP_404 return self._calculate_hosts(cluster) # Have to set resp.body explicitly to include Hosts. resp.body = cluster.to_json_with_hosts() resp.status = falcon.HTTP_200
def on_get(self, req, resp, name, address): """ Handles GET requests for individual hosts in a Cluster. This is a membership test, returning 200 OK if the host address is part of the cluster, or else 404 Not Found. :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 requested. :type name: str :param address: The address of the Host being requested. :type address: str """ cluster = util.get_cluster_model(self.store, name) if not cluster: resp.status = falcon.HTTP_404 return if address in cluster.hostset: resp.status = falcon.HTTP_200 else: resp.status = falcon.HTTP_404
def on_get(self, req, resp, name, address): """ Handles GET requests for individual hosts in a Cluster. This is a membership test, returning 200 OK if the host address is part of the cluster, or else 404 Not Found. :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 requested. :type name: str :param address: The address of the Host being requested. :type address: str """ cluster = util.get_cluster_model(name) if not cluster: resp.status = falcon.HTTP_404 return if address in cluster.hostset: resp.status = falcon.HTTP_200 else: resp.status = falcon.HTTP_404