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
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 """ key = util.etcd_cluster_key(name) etcd_resp, error = cherrypy.engine.publish('store-get', key)[0] if error: resp.status = falcon.HTTP_404 return cluster = Cluster(**json.loads(etcd_resp.value)) 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_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))
def get_cluster_model(name): """ Returns a Cluster instance from the etcd record for the given cluster name, if it exists, or else None. For convenience, the EtcdResult is embedded in the Cluster instance as an 'etcd' property. :param name: Name of a cluster :type name: str """ key = etcd_cluster_key(name) etcd_resp, error = cherrypy.engine.publish('store-get', key)[0] if error: return None cluster = Cluster(**json.loads(etcd_resp.value)) cluster.etcd = etcd_resp return cluster
def get_cluster_model(store, name): """ Returns a Cluster instance from the etcd record for the given cluster name, if it exists, or else None. For convenience, the EtcdResult is embedded in the Cluster instance as an 'etcd' property. :param store: Data store. :type store: etcd.Client :param name: Name of a cluster :type name: str """ key = etcd_cluster_key(name) try: etcd_resp = store.get(key) except etcd.EtcdKeyNotFound: return None cluster = Cluster(**json.loads(etcd_resp.value)) cluster.etcd = etcd_resp return cluster
# Copyright (C) 2016 Red Hat, Inc # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. """ Cluster(s) handlers. """ import datetime import json import cherrypy import falcon from multiprocessing import Process from commissaire.resource import Resource from commissaire.jobs.clusterexec import clusterexec from commissaire.handlers.models import (Cluster, Clusters, ClusterRestart, ClusterUpgrade, Host)