summaryrefslogtreecommitdiffstats
path: root/bin/cluster
diff options
context:
space:
mode:
authorWesley Hearn <wesley.s.hearn@gmail.com>2015-04-24 14:06:12 -0400
committerWesley Hearn <wesley.s.hearn@gmail.com>2015-04-24 14:06:12 -0400
commit519e097df31e2148ac520ab273d0bd2fb2f7bb43 (patch)
tree4c5413c72a2dd2ec732730b6994a104cca6a9798 /bin/cluster
parentdb9cf8ef4f030f30391e021f360fe0c3db1dce74 (diff)
parent8ce5e1de898d2fd2c4aa4620f31b57b62ed0c5d6 (diff)
downloadopenshift-519e097df31e2148ac520ab273d0bd2fb2f7bb43.tar.gz
openshift-519e097df31e2148ac520ab273d0bd2fb2f7bb43.tar.bz2
openshift-519e097df31e2148ac520ab273d0bd2fb2f7bb43.tar.xz
openshift-519e097df31e2148ac520ab273d0bd2fb2f7bb43.zip
Merge pull request #188 from openshift/master
Merge master into stage
Diffstat (limited to 'bin/cluster')
-rwxr-xr-xbin/cluster241
1 files changed, 241 insertions, 0 deletions
diff --git a/bin/cluster b/bin/cluster
new file mode 100755
index 000000000..79f1f988f
--- /dev/null
+++ b/bin/cluster
@@ -0,0 +1,241 @@
+#!/usr/bin/env python2
+# vim: expandtab:tabstop=4:shiftwidth=4
+
+import argparse
+import ConfigParser
+import sys
+import os
+
+
+class Cluster(object):
+ """
+ Control and Configuration Interface for OpenShift Clusters
+ """
+ def __init__(self):
+ # setup ansible ssh environment
+ if 'ANSIBLE_SSH_ARGS' not in os.environ:
+ os.environ['ANSIBLE_SSH_ARGS'] = (
+ '-o ForwardAgent=yes '
+ '-o StrictHostKeyChecking=no '
+ '-o UserKnownHostsFile=/dev/null '
+ '-o ControlMaster=auto '
+ '-o ControlPersist=600s '
+ )
+
+ def get_deployment_type(self, args):
+ """
+ Get the deployment_type based on the environment variables and the
+ command line arguments
+ :param args: command line arguments provided by the user
+ :return: string representing the deployment type
+ """
+ deployment_type = 'origin'
+ if args.deployment_type:
+ deployment_type = args.deployment_type
+ elif 'OS_DEPLOYMENT_TYPE' in os.environ:
+ deployment_type = os.environ['OS_DEPLOYMENT_TYPE']
+ return deployment_type
+
+ def create(self, args):
+ """
+ Create an OpenShift cluster for given provider
+ :param args: command line arguments provided by user
+ :return: exit status from run command
+ """
+ env = {'cluster_id': args.cluster_id,
+ 'deployment_type': self.get_deployment_type(args)}
+ playbook = "playbooks/{}/openshift-cluster/launch.yml".format(args.provider)
+ inventory = self.setup_provider(args.provider)
+
+ env['num_masters'] = args.masters
+ env['num_nodes'] = args.nodes
+
+ return self.action(args, inventory, env, playbook)
+
+ def terminate(self, args):
+ """
+ Destroy OpenShift cluster
+ :param args: command line arguments provided by user
+ :return: exit status from run command
+ """
+ env = {'cluster_id': args.cluster_id,
+ 'deployment_type': self.get_deployment_type(args)}
+ playbook = "playbooks/{}/openshift-cluster/terminate.yml".format(args.provider)
+ inventory = self.setup_provider(args.provider)
+
+ return self.action(args, inventory, env, playbook)
+
+ def list(self, args):
+ """
+ List VMs in cluster
+ :param args: command line arguments provided by user
+ :return: exit status from run command
+ """
+ env = {'cluster_id': args.cluster_id,
+ 'deployment_type': self.get_deployment_type(args)}
+ playbook = "playbooks/{}/openshift-cluster/list.yml".format(args.provider)
+ inventory = self.setup_provider(args.provider)
+
+ return self.action(args, inventory, env, playbook)
+
+ def config(self, args):
+ """
+ Configure or reconfigure OpenShift across clustered VMs
+ :param args: command line arguments provided by user
+ :return: exit status from run command
+ """
+ env = {'cluster_id': args.cluster_id,
+ 'deployment_type': self.get_deployment_type(args)}
+ playbook = "playbooks/{}/openshift-cluster/config.yml".format(args.provider)
+ inventory = self.setup_provider(args.provider)
+
+ return self.action(args, inventory, env, playbook)
+
+ def update(self, args):
+ """
+ Update to latest OpenShift across clustered VMs
+ :param args: command line arguments provided by user
+ :return: exit status from run command
+ """
+ env = {'cluster_id': args.cluster_id,
+ 'deployment_type': self.get_deployment_type(args)}
+ playbook = "playbooks/{}/openshift-cluster/update.yml".format(args.provider)
+ inventory = self.setup_provider(args.provider)
+
+ return self.action(args, inventory, env, playbook)
+
+ def setup_provider(self, provider):
+ """
+ Setup ansible playbook environment
+ :param provider: command line arguments provided by user
+ :return: path to inventory for given provider
+ """
+ config = ConfigParser.ConfigParser()
+ if 'gce' == provider:
+ config.readfp(open('inventory/gce/hosts/gce.ini'))
+
+ for key in config.options('gce'):
+ os.environ[key] = config.get('gce', key)
+
+ inventory = '-i inventory/gce/hosts'
+ elif 'aws' == provider:
+ config.readfp(open('inventory/aws/hosts/ec2.ini'))
+
+ for key in config.options('ec2'):
+ os.environ[key] = config.get('ec2', key)
+
+ inventory = '-i inventory/aws/hosts'
+ elif 'libvirt' == provider:
+ inventory = '-i inventory/libvirt/hosts'
+ else:
+ # this code should never be reached
+ raise ValueError("invalid PROVIDER {}".format(provider))
+
+ return inventory
+
+ def action(self, args, inventory, env, playbook):
+ """
+ Build ansible-playbook command line and execute
+ :param args: command line arguments provided by user
+ :param inventory: derived provider library
+ :param env: environment variables for kubernetes
+ :param playbook: ansible playbook to execute
+ :return: exit status from ansible-playbook command
+ """
+
+ verbose = ''
+ if args.verbose > 0:
+ verbose = '-{}'.format('v' * args.verbose)
+
+ ansible_env = '-e \'{}\''.format(
+ ' '.join(['%s=%s' % (key, value) for (key, value) in env.items()])
+ )
+
+ command = 'ansible-playbook {} {} {} {}'.format(
+ verbose, inventory, ansible_env, playbook
+ )
+
+ if args.verbose > 1:
+ command = 'time {}'.format(command)
+
+ if args.verbose > 0:
+ sys.stderr.write('RUN [{}]\n'.format(command))
+ sys.stderr.flush()
+
+ return os.system(command)
+
+
+if __name__ == '__main__':
+ """
+ Implemented to support writing unit tests
+ """
+
+ cluster = Cluster()
+
+ providers = ['gce', 'aws', 'libvirt']
+ parser = argparse.ArgumentParser(
+ description='Python wrapper to ensure proper environment for OpenShift ansible playbooks',
+ )
+ parser.add_argument('-v', '--verbose', action='count',
+ help='Multiple -v options increase the verbosity')
+ parser.add_argument('--version', action='version', version='%(prog)s 0.2')
+
+ meta_parser = argparse.ArgumentParser(add_help=False)
+ meta_parser.add_argument('provider', choices=providers, help='provider')
+ meta_parser.add_argument('cluster_id', help='prefix for cluster VM names')
+ meta_parser.add_argument('-t', '--deployment-type',
+ choices=['origin', 'online', 'enterprise'],
+ help='Deployment type. (default: origin)')
+
+ action_parser = parser.add_subparsers(dest='action', title='actions',
+ description='Choose from valid actions')
+
+ create_parser = action_parser.add_parser('create', help='Create a cluster',
+ parents=[meta_parser])
+ create_parser.add_argument('-m', '--masters', default=1, type=int,
+ help='number of masters to create in cluster')
+ create_parser.add_argument('-n', '--nodes', default=2, type=int,
+ help='number of nodes to create in cluster')
+ create_parser.set_defaults(func=cluster.create)
+
+ config_parser = action_parser.add_parser('config',
+ help='Configure or reconfigure a cluster',
+ parents=[meta_parser])
+ config_parser.set_defaults(func=cluster.config)
+
+ terminate_parser = action_parser.add_parser('terminate',
+ help='Destroy a cluster',
+ parents=[meta_parser])
+ terminate_parser.add_argument('-f', '--force', action='store_true',
+ help='Destroy cluster without confirmation')
+ terminate_parser.set_defaults(func=cluster.terminate)
+
+ update_parser = action_parser.add_parser('update',
+ help='Update OpenShift across cluster',
+ parents=[meta_parser])
+ update_parser.add_argument('-f', '--force', action='store_true',
+ help='Update cluster without confirmation')
+ update_parser.set_defaults(func=cluster.update)
+
+ list_parser = action_parser.add_parser('list', help='List VMs in cluster',
+ parents=[meta_parser])
+ list_parser.set_defaults(func=cluster.list)
+
+ args = parser.parse_args()
+
+ if 'terminate' == args.action and not args.force:
+ answer = raw_input("This will destroy the ENTIRE {} environment. Are you sure? [y/N] ".format(args.cluster_id))
+ if answer not in ['y', 'Y']:
+ sys.stderr.write('\nACTION [terminate] aborted by user!\n')
+ exit(1)
+
+ if 'update' == args.action and not args.force:
+ answer = raw_input("This is destructive and could corrupt {} environment. Continue? [y/N] ".format(args.cluster_id))
+ if answer not in ['y', 'Y']:
+ sys.stderr.write('\nACTION [update] aborted by user!\n')
+ exit(1)
+
+ status = args.func(args)
+ if status != 0:
+ sys.stderr.write("ACTION [{}] failed with exit status {}\n".format(args.action, status))
+ exit(status)