def on_get(self, req, resp, name): """ Handles GET (or "status") requests for a Cluster upgrade. :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 upgraded. :type name: str """ key = '/commissaire/cluster/{0}/upgrade'.format(name) if not util.etcd_cluster_exists(name): self.logger.info( 'Upgrade GET requested for nonexistent cluster {0}'.format( name)) resp.status = falcon.HTTP_404 return status, error = cherrypy.engine.publish('store-get', key)[0] self.logger.debug('Etcd Response: {0}'.format(status)) if error: # Return "204 No Content" if we have no status, # meaning no upgrade is in progress. The client # can't be expected to know that, so it's not a # client error (4xx). self.logger.debug(('Upgrade GET requested for {0} but no upgrade ' 'has ever been executed.').format(name)) resp.status = falcon.HTTP_204 return resp.status = falcon.HTTP_200 req.context['model'] = ClusterUpgrade(**json.loads(status.value))
def on_put(self, req, resp, name): """ Handles PUT (or "initiate") requests for a Cluster upgrade. :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 upgraded. :type name: str """ data = req.stream.read().decode() try: args = json.loads(data) upgrade_to = args['upgrade_to'] except (KeyError, ValueError): resp.status = falcon.HTTP_400 return # Make sure the cluster name is valid. if not util.etcd_cluster_exists(name): self.logger.info( 'Upgrade PUT requested for nonexistent cluster {0}'.format( name)) resp.status = falcon.HTTP_404 return # If the operation is already in progress and the requested version # matches, return the current status with response code 200 OK. # If the requested version conflicts with the operation in progress, # return the current status with response code 409 Conflict. key = '/commissaire/cluster/{0}/upgrade'.format(name) etcd_resp, error = cherrypy.engine.publish('store-get', key)[0] self.logger.debug('Etcd Response: {0}'.format(etcd_resp)) if not error: cluster_upgrade = ClusterUpgrade(**json.loads(etcd_resp.value)) if not cluster_upgrade.finished_at: if cluster_upgrade.upgrade_to == upgrade_to: self.logger.debug( 'Cluster {0} upgrade to {1} already in progress'. format(name, upgrade_to)) resp.status = falcon.HTTP_200 else: self.logger.debug( 'Cluster upgrade to {0} requested while ' 'upgrade to {1} was already in progress'.format( upgrade_to, cluster_upgrade.upgrade_to)) resp.status = falcon.HTTP_409 req.context['model'] = cluster_upgrade return # FIXME: How do I pass 'upgrade_to'? p = Process(target=clusterexec, args=(name, 'upgrade')) p.start() self.logger.debug( 'Started upgrade in clusterexecpool for {0}'.format(name)) cluster_upgrade_default = { 'status': 'in_process', 'upgrade_to': upgrade_to, 'upgraded': [], 'in_process': [], 'started_at': datetime.datetime.utcnow().isoformat(), 'finished_at': None } cluster_upgrade = ClusterUpgrade(**cluster_upgrade_default) cherrypy.engine.publish('store-save', key, cluster_upgrade.to_json()) resp.status = falcon.HTTP_201 req.context['model'] = cluster_upgrade