From 6bb076355db1eafdf610c96735cfc72d0dac1862 Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Mon, 16 Mar 2015 16:48:41 -0400 Subject: Initialized to use tito. --- bin/openshift-ansible-cmds.spec | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 bin/openshift-ansible-cmds.spec (limited to 'bin') diff --git a/bin/openshift-ansible-cmds.spec b/bin/openshift-ansible-cmds.spec new file mode 100644 index 000000000..24705ae31 --- /dev/null +++ b/bin/openshift-ansible-cmds.spec @@ -0,0 +1,34 @@ +Summary: OpenShift Operations files for mirror +Name: openshift-ansible-cmds +Version: 0.0.0 +Release: 1%{?dist} +License: ASL 2.0 +URL: https://github.com/openshift/openshift-ansible +Source0: %{name}-%{version}.tar.gz +Requires: python2 +BuildRequires: python2-devel +BuildArch: noarch + +%description +Scripts to make it nicer when working with hosts that are defined only by metadata. + +%prep +%setup -q + +%build + +%install +mkdir -p %{buildroot}/usr/bin +mkdir -p %{buildroot}%{python_sitelib}/openshift_ansible +mkdir -p %{buildroot}/etc/bash_completion.d + +cp -p ossh oscp opssh %{buildroot}/usr/bin +cp -p awsutil.py %{buildroot}%{python_sitelib}/openshift_ansible +cp -p ossh_bash_completion %{buildroot}/etc/bash_completion.d + +%files +/usr/bin/* +%{python_sitelib}/openshift_ansible/* +/etc/bash_completion.d/* + +%changelog -- cgit v1.2.3 From 17c69ff4a4b8b905e2db4dac6c9c0e8d1212b23f Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Mon, 16 Mar 2015 16:50:02 -0400 Subject: Automatic commit of package [openshift-ansible-cmds] release [0.0.1-1]. --- bin/README_BUILD | 4 ++++ bin/openshift-ansible-bin.spec | 34 ++++++++++++++++++++++++++++++++++ bin/openshift-ansible-cmds.spec | 34 ---------------------------------- 3 files changed, 38 insertions(+), 34 deletions(-) create mode 100644 bin/README_BUILD create mode 100644 bin/openshift-ansible-bin.spec delete mode 100644 bin/openshift-ansible-cmds.spec (limited to 'bin') diff --git a/bin/README_BUILD b/bin/README_BUILD new file mode 100644 index 000000000..48d4ff4b3 --- /dev/null +++ b/bin/README_BUILD @@ -0,0 +1,4 @@ +# How to build openshift-ansible + + +Test build diff --git a/bin/openshift-ansible-bin.spec b/bin/openshift-ansible-bin.spec new file mode 100644 index 000000000..2b83a7d0b --- /dev/null +++ b/bin/openshift-ansible-bin.spec @@ -0,0 +1,34 @@ +Summary: OpenShift Operations files for mirror +Name: openshift-ansible-bin +Version: 0.0.1 +Release: 1%{?dist} +License: ASL 2.0 +URL: https://github.com/openshift/openshift-ansible +Source0: %{name}-%{version}.tar.gz +Requires: python2 +BuildRequires: python2-devel +BuildArch: noarch + +%description +Scripts to make it nicer when working with hosts that are defined only by metadata. + +%prep +%setup -q + +%build + +%install +mkdir -p %{buildroot}/usr/bin +mkdir -p %{buildroot}%{python_sitelib}/openshift_ansible +mkdir -p %{buildroot}/etc/bash_completion.d + +cp -p ossh oscp opssh %{buildroot}/usr/bin +cp -p awsutil.py %{buildroot}%{python_sitelib}/openshift_ansible +cp -p ossh_bash_completion %{buildroot}/etc/bash_completion.d + +%files +/usr/bin/* +%{python_sitelib}/openshift_ansible/* +/etc/bash_completion.d/* + +%changelog diff --git a/bin/openshift-ansible-cmds.spec b/bin/openshift-ansible-cmds.spec deleted file mode 100644 index 24705ae31..000000000 --- a/bin/openshift-ansible-cmds.spec +++ /dev/null @@ -1,34 +0,0 @@ -Summary: OpenShift Operations files for mirror -Name: openshift-ansible-cmds -Version: 0.0.0 -Release: 1%{?dist} -License: ASL 2.0 -URL: https://github.com/openshift/openshift-ansible -Source0: %{name}-%{version}.tar.gz -Requires: python2 -BuildRequires: python2-devel -BuildArch: noarch - -%description -Scripts to make it nicer when working with hosts that are defined only by metadata. - -%prep -%setup -q - -%build - -%install -mkdir -p %{buildroot}/usr/bin -mkdir -p %{buildroot}%{python_sitelib}/openshift_ansible -mkdir -p %{buildroot}/etc/bash_completion.d - -cp -p ossh oscp opssh %{buildroot}/usr/bin -cp -p awsutil.py %{buildroot}%{python_sitelib}/openshift_ansible -cp -p ossh_bash_completion %{buildroot}/etc/bash_completion.d - -%files -/usr/bin/* -%{python_sitelib}/openshift_ansible/* -/etc/bash_completion.d/* - -%changelog -- cgit v1.2.3 From a7e3b2363935fc090ce7a41853ba27ba0050dc23 Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Tue, 24 Mar 2015 11:36:30 -0400 Subject: Automatic commit of package [openshift-ansible-bin] release [0.0.1-1]. --- bin/README_BUILD | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'bin') diff --git a/bin/README_BUILD b/bin/README_BUILD index 48d4ff4b3..50010e562 100644 --- a/bin/README_BUILD +++ b/bin/README_BUILD @@ -1,4 +1,25 @@ -# How to build openshift-ansible +# openshift-ansible-bin RPM Build instructions +We use tito to make building and tracking revisions easy. +For more information on tito, please see the [Tito home page](http://rm-rf.ca/tito "Tito home page"). -Test build + +## Build a test package (no tagging needed) +``` +tito build --test --rpm +``` + + +## Tag a new build (bumps version number and adds log entries) +``` +tito tag +``` + +Follow the on screen tito instructions. + + + +## Build a new package based on the latest tag information +``` +tito build --rpm +``` -- cgit v1.2.3 From 7c7cb82fdd5583784fd5832b92886abf86934325 Mon Sep 17 00:00:00 2001 From: Jhon Honce Date: Fri, 6 Mar 2015 13:52:20 -0700 Subject: Use ansible playbook to initialize openshift cluster * Added playbooks/gce/openshift-cluster * Added bin/cluster (will replace cluster.sh) --- bin/cluster | 100 +++++++++++++++++++++ playbooks/gce/openshift-cluster/filter_plugins | 1 + playbooks/gce/openshift-cluster/launch.yml | 62 +++++++++++++ .../gce/openshift-cluster/launch_instances.yml | 37 ++++++++ playbooks/gce/openshift-cluster/terminate.yml | 25 ++++++ playbooks/gce/openshift-cluster/vars.yml | 1 + playbooks/gce/openshift-master/config.yml | 13 ++- playbooks/gce/openshift-master/terminate.yml | 2 +- playbooks/gce/openshift-node/config.yml | 12 ++- playbooks/gce/openshift-node/terminate.yml | 2 +- roles/docker/tasks/main.yml | 2 +- roles/openshift_common/tasks/main.yml | 3 + 12 files changed, 253 insertions(+), 7 deletions(-) create mode 100755 bin/cluster create mode 120000 playbooks/gce/openshift-cluster/filter_plugins create mode 100644 playbooks/gce/openshift-cluster/launch.yml create mode 100644 playbooks/gce/openshift-cluster/launch_instances.yml create mode 100644 playbooks/gce/openshift-cluster/terminate.yml create mode 100644 playbooks/gce/openshift-cluster/vars.yml (limited to 'bin') diff --git a/bin/cluster b/bin/cluster new file mode 100755 index 000000000..7afdce0e5 --- /dev/null +++ b/bin/cluster @@ -0,0 +1,100 @@ +#!/usr/bin/env python +# vim: expandtab:tabstop=4:shiftwidth=4 + +import argparse +import ConfigParser +import sys +import os + + +class Cluster(object): + """Python wrapper to ensure environment is correct for running ansible playbooks + """ + + def __init__(self, args): + self.args = args + + # 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 apply(self): + # setup ansible playbook environment + config = ConfigParser.ConfigParser() + if 'gce' == self.args.provider: + config.readfp(open('inventory/gce/gce.ini')) + + for key in config.options('gce'): + os.environ[key] = config.get('gce', key) + + inventory = '-i inventory/gce/gce.py' + elif 'aws' == self.args.provider: + config.readfp(open('inventory/aws/ec2.ini')) + + for key in config.options('ec2'): + os.environ[key] = config.get('ec2', key) + + inventory = '-i inventory/aws/ec2.py' + else: + assert False, "invalid PROVIDER {}".format(self.args.provider) + + env = {'cluster_id': self.args.cluster_id} + + if 'create' == self.args.action: + playbook = "playbooks/{}/openshift-cluster/launch.yml".format(self.args.provider) + env['masters'] = self.args.masters + env['nodes'] = self.args.nodes + + elif 'terminate' == self.args.action: + playbook = "playbooks/{}/openshift-cluster/terminate.yml".format(self.args.provider) + elif 'list' == self.args.action: + # todo: implement cluster list + argparse.ArgumentError("ACTION {} not implemented".format(self.args.action)) + elif 'update' == self.args.action: + # todo: implement cluster update + argparse.ArgumentError("ACTION {} not implemented".format(self.args.action)) + else: + assert False, "invalid ACTION {}".format(self.args.action) + + verbose = '' + if self.args.verbose > 0: + verbose = '-{}'.format('v' * self.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 self.args.verbose > 1: + command = 'time {}'.format(command) + + if self.args.verbose > 0: + sys.stderr.write('RUN [{}]\n'.format(command)) + sys.stderr.flush() + + os.system(command) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Manage OpenShift Cluster') + parser.add_argument('-p', '--provider', default='gce', choices=['gce', 'aws'], + help='One of the supported cloud providers') + parser.add_argument('-m', '--masters', default=1, type=int, help='number of masters to create in cluster') + parser.add_argument('-n', '--nodes', default=2, type=int, help='number of nodes to create in cluster') + parser.add_argument('-v', '--verbose', action='count', help='Multiple -v options increase the verbosity') + parser.add_argument('--version', action='version', version='%(prog)s 0.1') + parser.add_argument('action', choices=['create', 'terminate', 'update', 'list']) + parser.add_argument('provider', choices=['gce', 'aws']) + parser.add_argument('cluster_id', help='prefix for cluster VM names') + args = parser.parse_args() + + Cluster(args).apply() diff --git a/playbooks/gce/openshift-cluster/filter_plugins b/playbooks/gce/openshift-cluster/filter_plugins new file mode 120000 index 000000000..99a95e4ca --- /dev/null +++ b/playbooks/gce/openshift-cluster/filter_plugins @@ -0,0 +1 @@ +../../../filter_plugins \ No newline at end of file diff --git a/playbooks/gce/openshift-cluster/launch.yml b/playbooks/gce/openshift-cluster/launch.yml new file mode 100644 index 000000000..ba9d58a74 --- /dev/null +++ b/playbooks/gce/openshift-cluster/launch.yml @@ -0,0 +1,62 @@ +--- +- name: Launch instance(s) + hosts: localhost + connection: local + gather_facts: no + + vars_files: + - vars.yml + + tasks: + - set_fact: k8s_type="master" + + - name: "Generate master instance names(s)" + set_fact: scratch="{{ cluster_id }}-{{ k8s_type }}-{{ '%05x' |format( 1048576 |random) }}" + register: instance_names_output + with_sequence: start=1 end={{ masters }} + + # These set_fact's cannot be combined + - set_fact: + instance_names_string: "{% for item in instance_names_output.results %}{{item.ansible_facts.scratch}} {% endfor %}" + + - set_fact: + master_names: "{{ instance_names_string.strip().split(' ') }}" + + - include: launch_instances.yml + vars: + instances: "{{ master_names }}" + cluster: "{{ cluster_id }}" + type: "{{ k8s_type }}" + group_name: "tag_env-host-type-{{ cluster_id }}-openshift-master" + + - set_fact: k8s_type="node" + + - name: "Generate node instance names(s)" + set_fact: scratch="{{ cluster_id }}-{{ k8s_type }}-{{ '%05x' |format( 1048576 |random) }}" + register: instance_names_output + with_sequence: start=1 end={{ nodes }} + + # These set_fact's cannot be combined + - set_fact: + instance_names_string: "{% for item in instance_names_output.results %}{{item.ansible_facts.scratch}} {% endfor %}" + + - set_fact: + node_names: "{{ instance_names_string.strip().split(' ') }}" + + - include: launch_instances.yml + vars: + instances: "{{ node_names }}" + cluster: "{{ cluster_id }}" + type: "{{ k8s_type }}" + group_name: "tag_env-host-type-{{ cluster_id }}-openshift-node" + + +- include: ../openshift-master/config.yml + vars: + oo_host_group_exp: "{{ master_names }}" + oo_env: "{{ cluster_id }}" + +- include: ../openshift-node/config.yml + vars: + oo_host_group_exp: "{{ node_names }}" + oo_env: "{{ cluster_id }}" diff --git a/playbooks/gce/openshift-cluster/launch_instances.yml b/playbooks/gce/openshift-cluster/launch_instances.yml new file mode 100644 index 000000000..ff19b94d8 --- /dev/null +++ b/playbooks/gce/openshift-cluster/launch_instances.yml @@ -0,0 +1,37 @@ + +- set_fact: + machine_type: "{{ lookup('env', 'gce_machine_type') |default('n1-standard-1', true) }}" + machine_image: "{{ lookup('env', 'gce_machine_image') |default('libra-rhel7', true) }}" + +- name: Launch instance(s) + gce: + instance_names: "{{ instances }}" + machine_type: "{{ machine_type }}" + image: "{{ machine_image }}" + service_account_email: "{{ lookup('env', 'gce_service_account_email_address') }}" + pem_file: "{{ lookup('env', 'gce_service_account_pem_file_path') }}" + project_id: "{{ lookup('env', 'gce_project_id') }}" + tags: + - "created-by-{{ cluster }}" + - "env-{{ cluster }}" + - "host-type-{{ type }}" + - "env-host-type-{{ cluster }}-openshift-{{ type }}" + register: gce + +- name: Add new instances public IPs + add_host: "hostname={{ item.name }} ansible_ssh_host={{ item.public_ip }} groups={{ group_name }}" + with_items: gce.instance_data + +- name: Wait for ssh + wait_for: "port=22 host={{ item.public_ip }}" + with_items: gce.instance_data + +- debug: var=gce + +- name: Wait for root user setup + command: "ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o ConnectTimeout=10 -o UserKnownHostsFile=/dev/null root@{{ item.public_ip }} echo root user is setup" + register: result + until: result.rc == 0 + retries: 20 + delay: 10 + with_items: gce.instance_data diff --git a/playbooks/gce/openshift-cluster/terminate.yml b/playbooks/gce/openshift-cluster/terminate.yml new file mode 100644 index 000000000..eff52a807 --- /dev/null +++ b/playbooks/gce/openshift-cluster/terminate.yml @@ -0,0 +1,25 @@ +--- +- name: Terminate instance(s) + hosts: localhost + + vars_files: + - vars.yml + + tasks: + - debug: msg="Retrieve node names" + - debug: msg="Retrieve master names" + - debug: var=groups + +- include: ../openshift-node/terminate.yml + vars: + oo_host_group_exp: 'groups["tag_env-host-type-{{ cluster_id }}-openshift-node"]' + gce_service_account_email: "1043659492591-r0tpbf8q4fbb9dakhjfhj89e4m1ld83t@developer.gserviceaccount.com" + gce_pem_file: "~/.gce/openshift-gce-devel_priv_key.pem" + gce_project_id: "openshift-gce-devel" + +- include: ../openshift-master/terminate.yml + vars: + oo_host_group_exp: 'groups["tag_env-host-type-{{ cluster_id }}-openshift-master"]' + gce_service_account_email: "1043659492591-r0tpbf8q4fbb9dakhjfhj89e4m1ld83t@developer.gserviceaccount.com" + gce_pem_file: "~/.gce/openshift-gce-devel_priv_key.pem" + gce_project_id: "openshift-gce-devel" diff --git a/playbooks/gce/openshift-cluster/vars.yml b/playbooks/gce/openshift-cluster/vars.yml new file mode 100644 index 000000000..ed97d539c --- /dev/null +++ b/playbooks/gce/openshift-cluster/vars.yml @@ -0,0 +1 @@ +--- diff --git a/playbooks/gce/openshift-master/config.yml b/playbooks/gce/openshift-master/config.yml index a74250d13..5581e8401 100644 --- a/playbooks/gce/openshift-master/config.yml +++ b/playbooks/gce/openshift-master/config.yml @@ -1,5 +1,4 @@ ---- -- name: "populate oo_hosts_to_config host group if needed" +- name: "master/config.yml, populate oo_hosts_to_config host group if needed" hosts: localhost gather_facts: no tasks: @@ -13,6 +12,16 @@ connection: ssh user: root +- name: "Retrieve public ip" + hosts: oo_hosts_to_config + connection: ssh + user: root + gather_facts: yes + tasks: + - command: 'curl "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip" -H "Metadata-Flavor: Google"' + register: output + - set_fact: gce_public_ip="{{ output.stdout }}" + - name: "Set Origin specific facts on localhost (for later use)" hosts: localhost gather_facts: no diff --git a/playbooks/gce/openshift-master/terminate.yml b/playbooks/gce/openshift-master/terminate.yml index 76e1404b5..f1345874a 100644 --- a/playbooks/gce/openshift-master/terminate.yml +++ b/playbooks/gce/openshift-master/terminate.yml @@ -12,7 +12,7 @@ - debug: msg="{{ groups['oo_hosts_to_terminate'] }}" -- name: Terminate instances +- name: Terminate master instances hosts: localhost connection: local tasks: diff --git a/playbooks/gce/openshift-node/config.yml b/playbooks/gce/openshift-node/config.yml index 78047cf40..57b9e3198 100644 --- a/playbooks/gce/openshift-node/config.yml +++ b/playbooks/gce/openshift-node/config.yml @@ -1,5 +1,4 @@ ---- -- name: "populate oo_hosts_to_config host group if needed" +- name: "node/config.yml, populate oo_hosts_to_config host group if needed" hosts: localhost gather_facts: no tasks: @@ -12,6 +11,11 @@ hosts: "tag_env-host-type-{{ oo_env }}-openshift-master" connection: ssh user: root + gather_facts: yes + tasks: + - command: 'curl "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip" -H "Metadata-Flavor: Google"' + register: output + - set_fact: gce_public_ip="{{ output.stdout }}" - name: "Set OO sepcific facts on localhost (for later use)" hosts: localhost @@ -36,6 +40,10 @@ user: root vars_files: - vars.yml + + tasks: + - debug: var=gce_public_ip + roles: - { role: openshift_node, diff --git a/playbooks/gce/openshift-node/terminate.yml b/playbooks/gce/openshift-node/terminate.yml index 8d60f27b3..d4555084b 100644 --- a/playbooks/gce/openshift-node/terminate.yml +++ b/playbooks/gce/openshift-node/terminate.yml @@ -12,7 +12,7 @@ - debug: msg="{{ groups['oo_hosts_to_terminate'] }}" -- name: Terminate instances +- name: Terminate node instances hosts: localhost connection: local tasks: diff --git a/roles/docker/tasks/main.yml b/roles/docker/tasks/main.yml index 2ecefd588..ca700db17 100644 --- a/roles/docker/tasks/main.yml +++ b/roles/docker/tasks/main.yml @@ -11,5 +11,5 @@ # From the origin rpm there exists instructions on how to # setup origin properly. The following steps come from there - name: Change root to be in the Docker group - user: name=root groups=docker append=yes + user: name=root groups=dockerroot append=yes diff --git a/roles/openshift_common/tasks/main.yml b/roles/openshift_common/tasks/main.yml index 07737a71f..656a3880d 100644 --- a/roles/openshift_common/tasks/main.yml +++ b/roles/openshift_common/tasks/main.yml @@ -2,6 +2,9 @@ - name: Set hostname hostname: name={{ openshift_hostname }} +- name: Update all packages + yum: name=* state=latest + - name: Configure local facts file file: path=/etc/ansible/facts.d/ state=directory mode=0750 -- cgit v1.2.3 From f6b2eaf7d12ff1f74551662cea46a8bad6beac33 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Fri, 13 Mar 2015 03:02:29 -0400 Subject: Add spacing to implicit string concatenation for python backwards compatibility --- bin/cluster | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'bin') diff --git a/bin/cluster b/bin/cluster index 7afdce0e5..ad6e74577 100755 --- a/bin/cluster +++ b/bin/cluster @@ -18,10 +18,10 @@ class Cluster(object): 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' + ' -o StrictHostKeyChecking=no' + ' -o UserKnownHostsFile=/dev/null' + ' -o ControlMaster=auto' + ' -o ControlPersist=600s' ) def apply(self): -- cgit v1.2.3 From 2147b1608140f2688ac9781b394824c04e55d07e Mon Sep 17 00:00:00 2001 From: Jhon Honce Date: Fri, 20 Mar 2015 09:31:05 -0700 Subject: * Updates from code reviews --- bin/cluster | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'bin') diff --git a/bin/cluster b/bin/cluster index ad6e74577..ce17ee6d7 100755 --- a/bin/cluster +++ b/bin/cluster @@ -42,6 +42,7 @@ class Cluster(object): inventory = '-i inventory/aws/ec2.py' else: + # this code should never be reached assert False, "invalid PROVIDER {}".format(self.args.provider) env = {'cluster_id': self.args.cluster_id} @@ -55,11 +56,12 @@ class Cluster(object): playbook = "playbooks/{}/openshift-cluster/terminate.yml".format(self.args.provider) elif 'list' == self.args.action: # todo: implement cluster list - argparse.ArgumentError("ACTION {} not implemented".format(self.args.action)) + raise argparse.ArgumentError("ACTION {} not implemented".format(self.args.action)) elif 'update' == self.args.action: # todo: implement cluster update - argparse.ArgumentError("ACTION {} not implemented".format(self.args.action)) + raise argparse.ArgumentError("ACTION {} not implemented".format(self.args.action)) else: + # this code should never be reached assert False, "invalid ACTION {}".format(self.args.action) verbose = '' @@ -81,13 +83,14 @@ class Cluster(object): sys.stderr.write('RUN [{}]\n'.format(command)) sys.stderr.flush() - os.system(command) + error = os.system(command) + if error != 0: + raise Exception("Ansible run failed with exit code %d".format(error)) + if __name__ == '__main__': parser = argparse.ArgumentParser(description='Manage OpenShift Cluster') - parser.add_argument('-p', '--provider', default='gce', choices=['gce', 'aws'], - help='One of the supported cloud providers') parser.add_argument('-m', '--masters', default=1, type=int, help='number of masters to create in cluster') parser.add_argument('-n', '--nodes', default=2, type=int, help='number of nodes to create in cluster') parser.add_argument('-v', '--verbose', action='count', help='Multiple -v options increase the verbosity') -- cgit v1.2.3 From 14b19e665b118349327a5c8c219cc49c96ae1d52 Mon Sep 17 00:00:00 2001 From: Jhon Honce Date: Fri, 20 Mar 2015 09:36:34 -0700 Subject: * Replace asserts with raises --- bin/cluster | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bin') diff --git a/bin/cluster b/bin/cluster index ce17ee6d7..af908155c 100755 --- a/bin/cluster +++ b/bin/cluster @@ -43,7 +43,7 @@ class Cluster(object): inventory = '-i inventory/aws/ec2.py' else: # this code should never be reached - assert False, "invalid PROVIDER {}".format(self.args.provider) + raise argparse.ArgumentError("invalid PROVIDER {}".format(self.args.provider)) env = {'cluster_id': self.args.cluster_id} @@ -62,7 +62,7 @@ class Cluster(object): raise argparse.ArgumentError("ACTION {} not implemented".format(self.args.action)) else: # this code should never be reached - assert False, "invalid ACTION {}".format(self.args.action) + raise argparse.ArgumentError("invalid ACTION {}".format(self.args.action)) verbose = '' if self.args.verbose > 0: -- cgit v1.2.3 From 557cc0ca9ecc22a9d90f9cf9ce549186fe286492 Mon Sep 17 00:00:00 2001 From: Jhon Honce Date: Mon, 23 Mar 2015 09:15:08 -0700 Subject: * Updates from code reviews --- bin/cluster | 14 +++++++++++--- playbooks/gce/openshift-cluster/launch_instances.yml | 2 +- playbooks/gce/openshift-master/terminate.yml | 1 + playbooks/gce/openshift-node/terminate.yml | 1 + 4 files changed, 14 insertions(+), 4 deletions(-) (limited to 'bin') diff --git a/bin/cluster b/bin/cluster index af908155c..823f50671 100755 --- a/bin/cluster +++ b/bin/cluster @@ -83,9 +83,10 @@ class Cluster(object): sys.stderr.write('RUN [{}]\n'.format(command)) sys.stderr.flush() - error = os.system(command) - if error != 0: - raise Exception("Ansible run failed with exit code %d".format(error)) + status = os.system(command) + if status != 0: + sys.stderr.write("RUN [{}] failed with exit status %d".format(command, status)) + exit(status) @@ -100,4 +101,11 @@ if __name__ == '__main__': parser.add_argument('cluster_id', help='prefix for cluster VM names') args = parser.parse_args() + if 'terminate' == args.action: + sys.stderr.write("This will terminate the ENTIRE {} environment. Are you sure? [y/N] ".format(args.cluster_id)) + sys.stderr.flush() + answer = sys.stdin.read(1) + if answer not in ['y', 'Y']: + exit(0) + Cluster(args).apply() diff --git a/playbooks/gce/openshift-cluster/launch_instances.yml b/playbooks/gce/openshift-cluster/launch_instances.yml index 443e763de..20e31d990 100644 --- a/playbooks/gce/openshift-cluster/launch_instances.yml +++ b/playbooks/gce/openshift-cluster/launch_instances.yml @@ -12,7 +12,7 @@ pem_file: "{{ lookup('env', 'gce_service_account_pem_file_path') }}" project_id: "{{ lookup('env', 'gce_project_id') }}" tags: - - "created-by-{{ cluster }}" + - "created-by-{{ lookup('env', 'LOGNAME') |default(cluster, true) }}" - "env-{{ cluster }}" - "host-type-{{ type }}" - "env-host-type-{{ cluster }}-openshift-{{ type }}" diff --git a/playbooks/gce/openshift-master/terminate.yml b/playbooks/gce/openshift-master/terminate.yml index f1345874a..9e027cf41 100644 --- a/playbooks/gce/openshift-master/terminate.yml +++ b/playbooks/gce/openshift-master/terminate.yml @@ -15,6 +15,7 @@ - name: Terminate master instances hosts: localhost connection: local + gather_facts: no tasks: - name: Terminate master instances gce: diff --git a/playbooks/gce/openshift-node/terminate.yml b/playbooks/gce/openshift-node/terminate.yml index d4555084b..9aa8a48c1 100644 --- a/playbooks/gce/openshift-node/terminate.yml +++ b/playbooks/gce/openshift-node/terminate.yml @@ -15,6 +15,7 @@ - name: Terminate node instances hosts: localhost connection: local + gather_facts: no tasks: - name: Terminate node instances gce: -- cgit v1.2.3 From 96729907e131f0cef6f37bcca062e9b092e67d29 Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Tue, 24 Mar 2015 13:15:53 -0400 Subject: Added spec files and tito configs. --- BUILD.md | 44 ++++++++++++++++++++++++++++++ README.md | 3 ++ bin/README_BUILD | 25 ----------------- bin/openshift-ansible-bin.spec | 14 +++++----- inventory/openshift-ansible-inventory.spec | 37 +++++++++++++++++++++++++ 5 files changed, 91 insertions(+), 32 deletions(-) create mode 100644 BUILD.md delete mode 100644 bin/README_BUILD create mode 100644 inventory/openshift-ansible-inventory.spec (limited to 'bin') diff --git a/BUILD.md b/BUILD.md new file mode 100644 index 000000000..0016c96a5 --- /dev/null +++ b/BUILD.md @@ -0,0 +1,44 @@ +# openshift-ansible RPM Build instructions +We use tito to make building and tracking revisions easy. + +For more information on tito, please see the [Tito home page](http://rm-rf.ca/tito "Tito home page"). + + +## Build openshift-ansible-bin +- Change into openshift-ansible/bin +``` +cd openshift-ansible/bin +``` +- Build a test package (no tagging needed) +``` +tito build --test --rpm +``` +- Tag a new build (bumps version number and adds log entries) +``` +tito tag +``` +- Follow the on screen tito instructions to push the tags +- Build a new package based on the latest tag information +``` +tito build --rpm +``` + + +## Build openshift-ansible-inventory +- Change into openshift-ansible/inventory +``` +cd openshift-ansible/inventory +``` +- Build a test package (no tagging needed) +``` +tito build --test --rpm +``` +- Tag a new build (bumps version number and adds log entries) +``` +tito tag +``` +- Follow the on screen tito instructions to push the tags +- Build a new package based on the latest tag information +``` +tito build --rpm +``` diff --git a/README.md b/README.md index ffdfee6f2..9a08bccd9 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,9 @@ Setup - [AWS](README_AWS.md) - [GCE](README_GCE.md) +- Build + - [How to build the openshift-ansible rpms](BUILD.md) + - Directory Structure: - [cloud.rb](cloud.rb) - light wrapper around Ansible - [cluster.sh](cluster.sh) - easily create OpenShift 3 clusters diff --git a/bin/README_BUILD b/bin/README_BUILD deleted file mode 100644 index 50010e562..000000000 --- a/bin/README_BUILD +++ /dev/null @@ -1,25 +0,0 @@ -# openshift-ansible-bin RPM Build instructions -We use tito to make building and tracking revisions easy. - -For more information on tito, please see the [Tito home page](http://rm-rf.ca/tito "Tito home page"). - - -## Build a test package (no tagging needed) -``` -tito build --test --rpm -``` - - -## Tag a new build (bumps version number and adds log entries) -``` -tito tag -``` - -Follow the on screen tito instructions. - - - -## Build a new package based on the latest tag information -``` -tito build --rpm -``` diff --git a/bin/openshift-ansible-bin.spec b/bin/openshift-ansible-bin.spec index 2b83a7d0b..7ca0cbe9d 100644 --- a/bin/openshift-ansible-bin.spec +++ b/bin/openshift-ansible-bin.spec @@ -1,11 +1,11 @@ -Summary: OpenShift Operations files for mirror +Summary: OpenShift Ansible Scripts for working with metadata hosts Name: openshift-ansible-bin -Version: 0.0.1 +Version: 0.0.0 Release: 1%{?dist} License: ASL 2.0 URL: https://github.com/openshift/openshift-ansible Source0: %{name}-%{version}.tar.gz -Requires: python2 +Requires: python2, openshift-ansible-inventory BuildRequires: python2-devel BuildArch: noarch @@ -18,17 +18,17 @@ Scripts to make it nicer when working with hosts that are defined only by metada %build %install -mkdir -p %{buildroot}/usr/bin +mkdir -p %{buildroot}%{_bindir} mkdir -p %{buildroot}%{python_sitelib}/openshift_ansible mkdir -p %{buildroot}/etc/bash_completion.d -cp -p ossh oscp opssh %{buildroot}/usr/bin +cp -p ossh oscp opssh %{buildroot}%{_bindir} cp -p awsutil.py %{buildroot}%{python_sitelib}/openshift_ansible cp -p ossh_bash_completion %{buildroot}/etc/bash_completion.d %files -/usr/bin/* -%{python_sitelib}/openshift_ansible/* +%{_bindir}/* +%{python_sitelib}/openshift_ansible/ /etc/bash_completion.d/* %changelog diff --git a/inventory/openshift-ansible-inventory.spec b/inventory/openshift-ansible-inventory.spec new file mode 100644 index 000000000..156b81b86 --- /dev/null +++ b/inventory/openshift-ansible-inventory.spec @@ -0,0 +1,37 @@ +Summary: OpenShift Ansible Inventories +Name: openshift-ansible-inventory +Version: 0.0.0 +Release: 1%{?dist} +License: ASL 2.0 +URL: https://github.com/openshift/openshift-ansible +Source0: %{name}-%{version}.tar.gz +Requires: python2 +BuildRequires: python2-devel +BuildArch: noarch + +%description +Ansible Inventories used with the openshift-ansible scripts and playbooks. + +%prep +%setup -q + +%build + +%install +mkdir -p %{buildroot}/usr/share/ansible/inventory +mkdir -p %{buildroot}/usr/share/ansible/inventory/aws +mkdir -p %{buildroot}/usr/share/ansible/inventory/gce + +cp -p multi_ec2.py multi_ec2.yaml.example %{buildroot}/usr/share/ansible/inventory +cp -p aws/ec2.py aws/ec2.ini %{buildroot}/usr/share/ansible/inventory/aws +cp -p gce/gce.py %{buildroot}/usr/share/ansible/inventory/gce + +%files +%dir /usr/share/ansible/inventory +/usr/share/ansible/inventory/multi_ec2.py* +/usr/share/ansible/inventory/multi_ec2.yaml.example +/usr/share/ansible/inventory/aws/ec2.py* +%config(noreplace) /usr/share/ansible/inventory/aws/ec2.ini +/usr/share/ansible/inventory/gce/gce.py* + +%changelog -- cgit v1.2.3 From e7797109bb0cc162dce6f78ed57343a832330910 Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Tue, 24 Mar 2015 16:14:53 -0400 Subject: Automatic commit of package [openshift-ansible-bin] release [0.0.1-1]. --- bin/openshift-ansible-bin.spec | 5 ++++- rel-eng/packages/openshift-ansible-bin | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 rel-eng/packages/openshift-ansible-bin (limited to 'bin') diff --git a/bin/openshift-ansible-bin.spec b/bin/openshift-ansible-bin.spec index 7ca0cbe9d..86b1d4fdf 100644 --- a/bin/openshift-ansible-bin.spec +++ b/bin/openshift-ansible-bin.spec @@ -1,6 +1,6 @@ Summary: OpenShift Ansible Scripts for working with metadata hosts Name: openshift-ansible-bin -Version: 0.0.0 +Version: 0.0.1 Release: 1%{?dist} License: ASL 2.0 URL: https://github.com/openshift/openshift-ansible @@ -32,3 +32,6 @@ cp -p ossh_bash_completion %{buildroot}/etc/bash_completion.d /etc/bash_completion.d/* %changelog +* Tue Mar 24 2015 Thomas Wiest 0.0.1-1 +- new package built with tito + diff --git a/rel-eng/packages/openshift-ansible-bin b/rel-eng/packages/openshift-ansible-bin new file mode 100644 index 000000000..098772960 --- /dev/null +++ b/rel-eng/packages/openshift-ansible-bin @@ -0,0 +1 @@ +0.0.1-1 bin/ -- cgit v1.2.3 From 16cac480197bfe1738b785aed55204b53d06ad57 Mon Sep 17 00:00:00 2001 From: Jhon Honce Date: Tue, 24 Mar 2015 17:05:13 -0700 Subject: * Refactor bin/cluster to use argparse.subparsers --- bin/cluster | 182 +++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 126 insertions(+), 56 deletions(-) (limited to 'bin') diff --git a/bin/cluster b/bin/cluster index 823f50671..b99286b46 100755 --- a/bin/cluster +++ b/bin/cluster @@ -8,33 +8,79 @@ import os class Cluster(object): - """Python wrapper to ensure environment is correct for running ansible playbooks """ - - def __init__(self, args): - self.args = args - + 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' + '-o ForwardAgent=yes ' + '-o StrictHostKeyChecking=no ' + '-o UserKnownHostsFile=/dev/null ' + '-o ControlMaster=auto ' + '-o ControlPersist=600s ' ) - def apply(self): - # setup ansible playbook environment + 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} + playbook = "playbooks/{}/openshift-cluster/launch.yml".format(args.provider) + inventory = self.setup_provider(args.provider) + + env['masters'] = args.masters + env['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} + 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 + """ + raise NotImplementedError("ACTION [{}] not implemented".format(sys._getframe().f_code.co_name)) + + def update(self, args): + """ + Update OpenShift across clustered VMs + :param args: command line arguments provided by user + :return: exit status from run command + """ + raise NotImplementedError("ACTION [{}] not implemented".format(sys._getframe().f_code.co_name)) + + + 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' == self.args.provider: + if 'gce' == provider: config.readfp(open('inventory/gce/gce.ini')) for key in config.options('gce'): os.environ[key] = config.get('gce', key) inventory = '-i inventory/gce/gce.py' - elif 'aws' == self.args.provider: + elif 'aws' == provider: config.readfp(open('inventory/aws/ec2.ini')) for key in config.options('ec2'): @@ -43,30 +89,23 @@ class Cluster(object): inventory = '-i inventory/aws/ec2.py' else: # this code should never be reached - raise argparse.ArgumentError("invalid PROVIDER {}".format(self.args.provider)) - - env = {'cluster_id': self.args.cluster_id} - - if 'create' == self.args.action: - playbook = "playbooks/{}/openshift-cluster/launch.yml".format(self.args.provider) - env['masters'] = self.args.masters - env['nodes'] = self.args.nodes - - elif 'terminate' == self.args.action: - playbook = "playbooks/{}/openshift-cluster/terminate.yml".format(self.args.provider) - elif 'list' == self.args.action: - # todo: implement cluster list - raise argparse.ArgumentError("ACTION {} not implemented".format(self.args.action)) - elif 'update' == self.args.action: - # todo: implement cluster update - raise argparse.ArgumentError("ACTION {} not implemented".format(self.args.action)) - else: - # this code should never be reached - raise argparse.ArgumentError("invalid ACTION {}".format(self.args.action)) + 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 self.args.verbose > 0: - verbose = '-{}'.format('v' * self.args.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()]) @@ -76,36 +115,67 @@ class Cluster(object): verbose, inventory, ansible_env, playbook ) - if self.args.verbose > 1: + if args.verbose > 1: command = 'time {}'.format(command) - if self.args.verbose > 0: + if args.verbose > 0: sys.stderr.write('RUN [{}]\n'.format(command)) sys.stderr.flush() - status = os.system(command) - if status != 0: - sys.stderr.write("RUN [{}] failed with exit status %d".format(command, status)) - exit(status) - + return os.system(command) if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Manage OpenShift Cluster') - parser.add_argument('-m', '--masters', default=1, type=int, help='number of masters to create in cluster') - parser.add_argument('-n', '--nodes', default=2, type=int, help='number of nodes to create in cluster') + """ + Implemented to support writing unit tests + """ + + cluster = Cluster() + + providers = ['gce', 'aws'] + 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.1') - parser.add_argument('action', choices=['create', 'terminate', 'update', 'list']) - parser.add_argument('provider', choices=['gce', 'aws']) - parser.add_argument('cluster_id', help='prefix for cluster VM names') + 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') + + 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) + + 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: - sys.stderr.write("This will terminate the ENTIRE {} environment. Are you sure? [y/N] ".format(args.cluster_id)) - sys.stderr.flush() - answer = sys.stdin.read(1) + 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']: - exit(0) + sys.stderr.write('\nACTION [update] aborted by user!\n') + exit(1) - Cluster(args).apply() + status = args.func(args) + if status != 0: + sys.stderr.write("ACTION [{}] failed with exit status {}\n".format(args.action, status)) + exit(status) -- cgit v1.2.3 From b1b462f4db3ce1a26cfc251895d5f8fe2e15c484 Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Mon, 30 Mar 2015 11:25:03 -0400 Subject: added config file support to opssh, ossh, and oscp --- bin/awsutil.py | 29 ++++++++++++++++------------- bin/openshift-ansible-bin.spec | 4 ++++ bin/openshift_ansible.conf.example | 6 ++++++ bin/opssh | 32 ++++++++++++++++++++++++++++++-- bin/oscp | 25 +++++++++++++++++++++++-- bin/ossh | 23 ++++++++++++++++++++++- 6 files changed, 101 insertions(+), 18 deletions(-) create mode 100644 bin/openshift_ansible.conf.example (limited to 'bin') diff --git a/bin/awsutil.py b/bin/awsutil.py index 37259b946..78421e5f5 100644 --- a/bin/awsutil.py +++ b/bin/awsutil.py @@ -6,27 +6,30 @@ import json import re class AwsUtil(object): - def __init__(self): - self.host_type_aliases = { - 'legacy-openshift-broker': ['broker', 'ex-srv'], - 'openshift-node': ['node', 'ex-node'], - 'openshift-messagebus': ['msg'], - 'openshift-customer-database': ['mongo'], - 'openshift-website-proxy': ['proxy'], - 'openshift-community-website': ['drupal'], - 'package-mirror': ['mirror'], - } + def __init__(self, inventory_path=None, host_type_aliases={}): + self.host_type_aliases = host_type_aliases + self.file_path = os.path.join(os.path.dirname(os.path.realpath(__file__))) + + if inventory_path is None: + inventory_path = os.path.realpath(os.path.join(self.file_path, \ + '..','inventory','multi_ec2.py')) + + if not os.path.isfile(inventory_path): + raise Exception("Inventory file not found [%s]" % inventory_path) + self.inventory_path = inventory_path + self.setup_host_type_alias_lookup() + + def setup_host_type_alias_lookup(self): self.alias_lookup = {} for key, values in self.host_type_aliases.iteritems(): for value in values: self.alias_lookup[value] = key - self.file_path = os.path.join(os.path.dirname(os.path.realpath(__file__))) - self.multi_ec2_path = os.path.realpath(os.path.join(self.file_path, '..','inventory','multi_ec2.py')) + def get_inventory(self,args=[]): - cmd = [self.multi_ec2_path] + cmd = [self.inventory_path] if args: cmd.extend(args) diff --git a/bin/openshift-ansible-bin.spec b/bin/openshift-ansible-bin.spec index 86b1d4fdf..1bd486bff 100644 --- a/bin/openshift-ansible-bin.spec +++ b/bin/openshift-ansible-bin.spec @@ -21,15 +21,19 @@ Scripts to make it nicer when working with hosts that are defined only by metada mkdir -p %{buildroot}%{_bindir} mkdir -p %{buildroot}%{python_sitelib}/openshift_ansible mkdir -p %{buildroot}/etc/bash_completion.d +mkdir -p %{buildroot}/etc/openshift_ansible cp -p ossh oscp opssh %{buildroot}%{_bindir} cp -p awsutil.py %{buildroot}%{python_sitelib}/openshift_ansible cp -p ossh_bash_completion %{buildroot}/etc/bash_completion.d +cp -p openshift_ansible.conf.example %{buildroot}/etc/openshift_ansible/openshift_ansible.conf + %files %{_bindir}/* %{python_sitelib}/openshift_ansible/ /etc/bash_completion.d/* +%config(noreplace) /etc/openshift_ansible/ %changelog * Tue Mar 24 2015 Thomas Wiest 0.0.1-1 diff --git a/bin/openshift_ansible.conf.example b/bin/openshift_ansible.conf.example new file mode 100644 index 000000000..e891b855a --- /dev/null +++ b/bin/openshift_ansible.conf.example @@ -0,0 +1,6 @@ +#[main] +#inventory = /usr/share/ansible/inventory/multi_ec2.py + +#[host_type_aliases] +#host-type-one = aliasa,aliasb +#host-type-two = aliasfortwo diff --git a/bin/opssh b/bin/opssh index 71e5bf9f2..d64096fd4 100755 --- a/bin/opssh +++ b/bin/opssh @@ -10,16 +10,30 @@ import re import tempfile import time import subprocess +import ConfigParser -DEFAULT_PSSH_PAR=200 +DEFAULT_PSSH_PAR = 200 PSSH = '/usr/bin/pssh' +CONFIG_MAIN_SECTION = 'main' +CONFIG_HOST_TYPE_ALIAS_SECTION = 'host_type_aliases' +CONFIG_INVENTORY_OPTION = 'inventory' + class Opssh(object): def __init__(self): + self.inventory = None + self.host_type_aliases = {} self.file_path = os.path.join(os.path.dirname(os.path.realpath(__file__))) - self.aws = awsutil.AwsUtil() + + # Default the config path to /etc + self.config_path = os.path.join(os.path.sep, 'etc', \ + 'openshift_ansible', \ + 'openshift_ansible.conf') self.parse_cli_args() + self.parse_config_file() + + self.aws = awsutil.AwsUtil(self.inventory, self.host_type_aliases) if self.args.list_host_types: self.aws.print_host_types() @@ -66,6 +80,20 @@ class Opssh(object): return None + def parse_config_file(self): + if os.path.isfile(self.config_path): + config = ConfigParser.ConfigParser() + config.read(self.config_path) + + if config.has_section(CONFIG_MAIN_SECTION) and \ + config.has_option(CONFIG_MAIN_SECTION, CONFIG_INVENTORY_OPTION): + self.inventory = config.get(CONFIG_MAIN_SECTION, CONFIG_INVENTORY_OPTION) + + self.host_type_aliases = {} + if config.has_section(CONFIG_HOST_TYPE_ALIAS_SECTION): + for alias in config.options(CONFIG_HOST_TYPE_ALIAS_SECTION): + value = config.get(CONFIG_HOST_TYPE_ALIAS_SECTION, alias).split(',') + self.host_type_aliases[alias] = value def parse_cli_args(self): """Setup the command line parser with the options we want diff --git a/bin/oscp b/bin/oscp index 146bbbea5..011f37c7c 100755 --- a/bin/oscp +++ b/bin/oscp @@ -7,16 +7,28 @@ import traceback import sys import os import re +import ConfigParser + +CONFIG_MAIN_SECTION = 'main' +CONFIG_INVENTORY_OPTION = 'inventory' class Oscp(object): def __init__(self): + self.inventory = None self.file_path = os.path.join(os.path.dirname(os.path.realpath(__file__))) + + # Default the config path to /etc + self.config_path = os.path.join(os.path.sep, 'etc', \ + 'openshift_ansible', \ + 'openshift_ansible.conf') + self.parse_cli_args() + self.parse_config_file() # parse host and user self.process_host() - self.aws = awsutil.AwsUtil() + self.aws = awsutil.AwsUtil(self.inventory) # get a dict of host inventory if self.args.list: @@ -38,9 +50,18 @@ class Oscp(object): else: self.scp() + def parse_config_file(self): + if os.path.isfile(self.config_path): + config = ConfigParser.ConfigParser() + config.read(self.config_path) + + if config.has_section(CONFIG_MAIN_SECTION) and \ + config.has_option(CONFIG_MAIN_SECTION, CONFIG_INVENTORY_OPTION): + self.inventory = config.get(CONFIG_MAIN_SECTION, CONFIG_INVENTORY_OPTION) + def parse_cli_args(self): parser = argparse.ArgumentParser(description='Openshift Online SSH Tool.') - parser.add_argument('-e', '--env', + parser.add_argument('-e', '--env', action="store", help="Environment where this server exists.") parser.add_argument('-d', '--debug', default=False, action="store_true", help="debug mode") diff --git a/bin/ossh b/bin/ossh index 66a4cfb5c..134f4c46a 100755 --- a/bin/ossh +++ b/bin/ossh @@ -7,13 +7,25 @@ import traceback import sys import os import re +import ConfigParser + +CONFIG_MAIN_SECTION = 'main' +CONFIG_INVENTORY_OPTION = 'inventory' class Ossh(object): def __init__(self): + self.inventory = None self.file_path = os.path.join(os.path.dirname(os.path.realpath(__file__))) + + # Default the config path to /etc + self.config_path = os.path.join(os.path.sep, 'etc', \ + 'openshift_ansible', \ + 'openshift_ansible.conf') + self.parse_cli_args() + self.parse_config_file() - self.aws = awsutil.AwsUtil() + self.aws = awsutil.AwsUtil(self.inventory) # get a dict of host inventory if self.args.list: @@ -37,6 +49,15 @@ class Ossh(object): else: self.ssh() + def parse_config_file(self): + if os.path.isfile(self.config_path): + config = ConfigParser.ConfigParser() + config.read(self.config_path) + + if config.has_section(CONFIG_MAIN_SECTION) and \ + config.has_option(CONFIG_MAIN_SECTION, CONFIG_INVENTORY_OPTION): + self.inventory = config.get(CONFIG_MAIN_SECTION, CONFIG_INVENTORY_OPTION) + def parse_cli_args(self): parser = argparse.ArgumentParser(description='Openshift Online SSH Tool.') parser.add_argument('-e', '--env', action="store", -- cgit v1.2.3 From 1ba0619575f23e880d431ec2a15b9c02bfc5e3a9 Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Mon, 30 Mar 2015 14:51:41 -0400 Subject: Automatic commit of package [openshift-ansible-bin] release [0.0.2-1]. --- bin/openshift-ansible-bin.spec | 4 +++- rel-eng/packages/openshift-ansible-bin | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'bin') diff --git a/bin/openshift-ansible-bin.spec b/bin/openshift-ansible-bin.spec index 1bd486bff..38e0a0d59 100644 --- a/bin/openshift-ansible-bin.spec +++ b/bin/openshift-ansible-bin.spec @@ -1,6 +1,6 @@ Summary: OpenShift Ansible Scripts for working with metadata hosts Name: openshift-ansible-bin -Version: 0.0.1 +Version: 0.0.2 Release: 1%{?dist} License: ASL 2.0 URL: https://github.com/openshift/openshift-ansible @@ -36,6 +36,8 @@ cp -p openshift_ansible.conf.example %{buildroot}/etc/openshift_ansible/openshif %config(noreplace) /etc/openshift_ansible/ %changelog +* Mon Mar 30 2015 Thomas Wiest 0.0.2-1 +- added config file support to opssh, ossh, and oscp (twiest@redhat.com) * Tue Mar 24 2015 Thomas Wiest 0.0.1-1 - new package built with tito diff --git a/rel-eng/packages/openshift-ansible-bin b/rel-eng/packages/openshift-ansible-bin index 098772960..875591484 100644 --- a/rel-eng/packages/openshift-ansible-bin +++ b/rel-eng/packages/openshift-ansible-bin @@ -1 +1 @@ -0.0.1-1 bin/ +0.0.2-1 bin/ -- cgit v1.2.3 From 24ce165d9ca662f9a0438e658197ff41fd02ae03 Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Mon, 30 Mar 2015 17:46:21 -0400 Subject: created a python package named openshift_ansible --- bin/awsutil.py | 141 ------------------------------------- bin/openshift-ansible-bin.spec | 2 +- bin/openshift_ansible/__init__.py | 0 bin/openshift_ansible/awsutil.py | 142 ++++++++++++++++++++++++++++++++++++++ bin/opssh | 3 +- bin/oscp | 3 +- bin/ossh | 3 +- 7 files changed, 149 insertions(+), 145 deletions(-) delete mode 100644 bin/awsutil.py create mode 100644 bin/openshift_ansible/__init__.py create mode 100644 bin/openshift_ansible/awsutil.py (limited to 'bin') diff --git a/bin/awsutil.py b/bin/awsutil.py deleted file mode 100644 index 78421e5f5..000000000 --- a/bin/awsutil.py +++ /dev/null @@ -1,141 +0,0 @@ -# vim: expandtab:tabstop=4:shiftwidth=4 - -import subprocess -import os -import json -import re - -class AwsUtil(object): - def __init__(self, inventory_path=None, host_type_aliases={}): - self.host_type_aliases = host_type_aliases - self.file_path = os.path.join(os.path.dirname(os.path.realpath(__file__))) - - if inventory_path is None: - inventory_path = os.path.realpath(os.path.join(self.file_path, \ - '..','inventory','multi_ec2.py')) - - if not os.path.isfile(inventory_path): - raise Exception("Inventory file not found [%s]" % inventory_path) - - self.inventory_path = inventory_path - self.setup_host_type_alias_lookup() - - def setup_host_type_alias_lookup(self): - self.alias_lookup = {} - for key, values in self.host_type_aliases.iteritems(): - for value in values: - self.alias_lookup[value] = key - - - - def get_inventory(self,args=[]): - cmd = [self.inventory_path] - - if args: - cmd.extend(args) - - env = os.environ - - p = subprocess.Popen(cmd, stderr=subprocess.PIPE, - stdout=subprocess.PIPE, env=env) - - out,err = p.communicate() - - if p.returncode != 0: - raise RuntimeError(err) - - return json.loads(out.strip()) - - def get_environments(self): - pattern = re.compile(r'^tag_environment_(.*)') - - envs = [] - inv = self.get_inventory() - for key in inv.keys(): - m = pattern.match(key) - if m: - envs.append(m.group(1)) - - envs.sort() - return envs - - def get_host_types(self): - pattern = re.compile(r'^tag_host-type_(.*)') - - host_types = [] - inv = self.get_inventory() - for key in inv.keys(): - m = pattern.match(key) - if m: - host_types.append(m.group(1)) - - host_types.sort() - return host_types - - def get_security_groups(self): - pattern = re.compile(r'^security_group_(.*)') - - groups = [] - inv = self.get_inventory() - for key in inv.keys(): - m = pattern.match(key) - if m: - groups.append(m.group(1)) - - groups.sort() - return groups - - def build_host_dict_by_env(self, args=[]): - inv = self.get_inventory(args) - - inst_by_env = {} - for dns, host in inv['_meta']['hostvars'].items(): - # If you don't have an environment tag, we're going to ignore you - if 'ec2_tag_environment' not in host: - continue - - if host['ec2_tag_environment'] not in inst_by_env: - inst_by_env[host['ec2_tag_environment']] = {} - host_id = "%s:%s" % (host['ec2_tag_Name'],host['ec2_id']) - inst_by_env[host['ec2_tag_environment']][host_id] = host - - return inst_by_env - - # Display host_types - def print_host_types(self): - host_types = self.get_host_types() - ht_format_str = "%35s" - alias_format_str = "%-20s" - combined_format_str = ht_format_str + " " + alias_format_str - - print - print combined_format_str % ('Host Types', 'Aliases') - print combined_format_str % ('----------', '-------') - - for ht in host_types: - aliases = [] - if ht in self.host_type_aliases: - aliases = self.host_type_aliases[ht] - print combined_format_str % (ht, ", ".join(aliases)) - else: - print ht_format_str % ht - print - - # Convert host-type aliases to real a host-type - def resolve_host_type(self, host_type): - if self.alias_lookup.has_key(host_type): - return self.alias_lookup[host_type] - return host_type - - def gen_env_host_type_tag(self, host_type, env): - """Generate the environment host type tag - """ - host_type = self.resolve_host_type(host_type) - return "tag_env-host-type_%s-%s" % (env, host_type) - - def get_host_list(self, host_type, env): - """Get the list of hosts from the inventory using host-type and environment - """ - inv = self.get_inventory() - host_type_tag = self.gen_env_host_type_tag(host_type, env) - return inv[host_type_tag] diff --git a/bin/openshift-ansible-bin.spec b/bin/openshift-ansible-bin.spec index 38e0a0d59..349cd3059 100644 --- a/bin/openshift-ansible-bin.spec +++ b/bin/openshift-ansible-bin.spec @@ -24,7 +24,7 @@ mkdir -p %{buildroot}/etc/bash_completion.d mkdir -p %{buildroot}/etc/openshift_ansible cp -p ossh oscp opssh %{buildroot}%{_bindir} -cp -p awsutil.py %{buildroot}%{python_sitelib}/openshift_ansible +cp -p openshift_ansible/* %{buildroot}%{python_sitelib}/openshift_ansible cp -p ossh_bash_completion %{buildroot}/etc/bash_completion.d cp -p openshift_ansible.conf.example %{buildroot}/etc/openshift_ansible/openshift_ansible.conf diff --git a/bin/openshift_ansible/__init__.py b/bin/openshift_ansible/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/bin/openshift_ansible/awsutil.py b/bin/openshift_ansible/awsutil.py new file mode 100644 index 000000000..8fef0a24f --- /dev/null +++ b/bin/openshift_ansible/awsutil.py @@ -0,0 +1,142 @@ +# vim: expandtab:tabstop=4:shiftwidth=4 + +import subprocess +import os +import json +import re + +class AwsUtil(object): + def __init__(self, inventory_path=None, host_type_aliases={}): + self.host_type_aliases = host_type_aliases + self.file_path = os.path.join(os.path.dirname(os.path.realpath(__file__))) + + if inventory_path is None: + inventory_path = os.path.realpath(os.path.join(self.file_path, \ + '..', '..', 'inventory', \ + 'multi_ec2.py')) + + if not os.path.isfile(inventory_path): + raise Exception("Inventory file not found [%s]" % inventory_path) + + self.inventory_path = inventory_path + self.setup_host_type_alias_lookup() + + def setup_host_type_alias_lookup(self): + self.alias_lookup = {} + for key, values in self.host_type_aliases.iteritems(): + for value in values: + self.alias_lookup[value] = key + + + + def get_inventory(self,args=[]): + cmd = [self.inventory_path] + + if args: + cmd.extend(args) + + env = os.environ + + p = subprocess.Popen(cmd, stderr=subprocess.PIPE, + stdout=subprocess.PIPE, env=env) + + out,err = p.communicate() + + if p.returncode != 0: + raise RuntimeError(err) + + return json.loads(out.strip()) + + def get_environments(self): + pattern = re.compile(r'^tag_environment_(.*)') + + envs = [] + inv = self.get_inventory() + for key in inv.keys(): + m = pattern.match(key) + if m: + envs.append(m.group(1)) + + envs.sort() + return envs + + def get_host_types(self): + pattern = re.compile(r'^tag_host-type_(.*)') + + host_types = [] + inv = self.get_inventory() + for key in inv.keys(): + m = pattern.match(key) + if m: + host_types.append(m.group(1)) + + host_types.sort() + return host_types + + def get_security_groups(self): + pattern = re.compile(r'^security_group_(.*)') + + groups = [] + inv = self.get_inventory() + for key in inv.keys(): + m = pattern.match(key) + if m: + groups.append(m.group(1)) + + groups.sort() + return groups + + def build_host_dict_by_env(self, args=[]): + inv = self.get_inventory(args) + + inst_by_env = {} + for dns, host in inv['_meta']['hostvars'].items(): + # If you don't have an environment tag, we're going to ignore you + if 'ec2_tag_environment' not in host: + continue + + if host['ec2_tag_environment'] not in inst_by_env: + inst_by_env[host['ec2_tag_environment']] = {} + host_id = "%s:%s" % (host['ec2_tag_Name'],host['ec2_id']) + inst_by_env[host['ec2_tag_environment']][host_id] = host + + return inst_by_env + + # Display host_types + def print_host_types(self): + host_types = self.get_host_types() + ht_format_str = "%35s" + alias_format_str = "%-20s" + combined_format_str = ht_format_str + " " + alias_format_str + + print + print combined_format_str % ('Host Types', 'Aliases') + print combined_format_str % ('----------', '-------') + + for ht in host_types: + aliases = [] + if ht in self.host_type_aliases: + aliases = self.host_type_aliases[ht] + print combined_format_str % (ht, ", ".join(aliases)) + else: + print ht_format_str % ht + print + + # Convert host-type aliases to real a host-type + def resolve_host_type(self, host_type): + if self.alias_lookup.has_key(host_type): + return self.alias_lookup[host_type] + return host_type + + def gen_env_host_type_tag(self, host_type, env): + """Generate the environment host type tag + """ + host_type = self.resolve_host_type(host_type) + return "tag_env-host-type_%s-%s" % (env, host_type) + + def get_host_list(self, host_type, env): + """Get the list of hosts from the inventory using host-type and environment + """ + inv = self.get_inventory() + host_type_tag = self.gen_env_host_type_tag(host_type, env) + return inv[host_type_tag] diff --git a/bin/opssh b/bin/opssh index d64096fd4..d8137fb20 100755 --- a/bin/opssh +++ b/bin/opssh @@ -2,7 +2,6 @@ # vim: expandtab:tabstop=4:shiftwidth=4 import argparse -import awsutil import traceback import sys import os @@ -12,6 +11,8 @@ import time import subprocess import ConfigParser +from openshift_ansible import awsutil + DEFAULT_PSSH_PAR = 200 PSSH = '/usr/bin/pssh' CONFIG_MAIN_SECTION = 'main' diff --git a/bin/oscp b/bin/oscp index 011f37c7c..461ad0a0f 100755 --- a/bin/oscp +++ b/bin/oscp @@ -2,13 +2,14 @@ # vim: expandtab:tabstop=4:shiftwidth=4 import argparse -import awsutil import traceback import sys import os import re import ConfigParser +from openshift_ansible import awsutil + CONFIG_MAIN_SECTION = 'main' CONFIG_INVENTORY_OPTION = 'inventory' diff --git a/bin/ossh b/bin/ossh index 134f4c46a..c16ea6eda 100755 --- a/bin/ossh +++ b/bin/ossh @@ -2,13 +2,14 @@ # vim: expandtab:tabstop=4:shiftwidth=4 import argparse -import awsutil import traceback import sys import os import re import ConfigParser +from openshift_ansible import awsutil + CONFIG_MAIN_SECTION = 'main' CONFIG_INVENTORY_OPTION = 'inventory' -- cgit v1.2.3 From 4a6d1c328d92047fcd924dce821613c8579f1745 Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Mon, 30 Mar 2015 18:13:27 -0400 Subject: Automatic commit of package [openshift-ansible-bin] release [0.0.3-1]. --- bin/openshift-ansible-bin.spec | 5 ++++- rel-eng/packages/openshift-ansible-bin | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'bin') diff --git a/bin/openshift-ansible-bin.spec b/bin/openshift-ansible-bin.spec index 349cd3059..7cca5ffba 100644 --- a/bin/openshift-ansible-bin.spec +++ b/bin/openshift-ansible-bin.spec @@ -1,6 +1,6 @@ Summary: OpenShift Ansible Scripts for working with metadata hosts Name: openshift-ansible-bin -Version: 0.0.2 +Version: 0.0.3 Release: 1%{?dist} License: ASL 2.0 URL: https://github.com/openshift/openshift-ansible @@ -36,6 +36,9 @@ cp -p openshift_ansible.conf.example %{buildroot}/etc/openshift_ansible/openshif %config(noreplace) /etc/openshift_ansible/ %changelog +* Mon Mar 30 2015 Thomas Wiest 0.0.3-1 +- created a python package named openshift_ansible (twiest@redhat.com) + * Mon Mar 30 2015 Thomas Wiest 0.0.2-1 - added config file support to opssh, ossh, and oscp (twiest@redhat.com) * Tue Mar 24 2015 Thomas Wiest 0.0.1-1 diff --git a/rel-eng/packages/openshift-ansible-bin b/rel-eng/packages/openshift-ansible-bin index 875591484..36b150859 100644 --- a/rel-eng/packages/openshift-ansible-bin +++ b/rel-eng/packages/openshift-ansible-bin @@ -1 +1 @@ -0.0.2-1 bin/ +0.0.3-1 bin/ -- cgit v1.2.3 From d9a178298ae8b6d487baf79559f4d82b2d71e49a Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Tue, 31 Mar 2015 15:36:29 -0400 Subject: Fixed when tag was missing and added opssh completion --- bin/ossh_bash_completion | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'bin') diff --git a/bin/ossh_bash_completion b/bin/ossh_bash_completion index 6a95ce6ee..1467de858 100755 --- a/bin/ossh_bash_completion +++ b/bin/ossh_bash_completion @@ -1,6 +1,7 @@ __ossh_known_hosts(){ if [[ -f ~/.ansible/tmp/multi_ec2_inventory.cache ]]; then - /usr/bin/python -c 'import json,os; z = json.loads(open("%s"%os.path.expanduser("~/.ansible/tmp/multi_ec2_inventory.cache")).read()); print "\n".join(["%s.%s" % (host["ec2_tag_Name"],host["ec2_tag_environment"]) for dns, host in z["_meta"]["hostvars"].items()])' + /usr/bin/python -c 'import json,os; z = json.loads(open("%s"%os.path.expanduser("~/.ansible/tmp/multi_ec2_inventory.cache")).read()); print "\n".join(["%s.%s" % (host["ec2_tag_Name"],host["ec2_tag_environment"]) for dns, host in z["_meta"]["hostvars"].items() if all(k in host for k in ("ec2_tag_Name", "ec2_tag_environment"))])' + fi } @@ -16,3 +17,23 @@ _ossh() return 0 } complete -F _ossh ossh oscp + +__opssh_known_hosts(){ + if [[ -f ~/.ansible/tmp/multi_ec2_inventory.cache ]]; then + /usr/bin/python -c 'import json,os; z = json.loads(open("%s"%os.path.expanduser("~/.ansible/tmp/multi_ec2_inventory.cache")).read()); print "\n".join(["%s" % (host["ec2_tag_host-type"]) for dns, host in z["_meta"]["hostvars"].items() if "ec2_tag_host-type" in host])' + fi +} + +_opssh() +{ + local cur prev known_hosts + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + known_hosts="$(__opssh_known_hosts)" + COMPREPLY=( $(compgen -W "${known_hosts}" -- ${cur})) + + return 0 +} +complete -F _opssh opssh + -- cgit v1.2.3 From 5f0b024fedc826722306c159bbf91a3c74ec3b4e Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Tue, 31 Mar 2015 16:49:13 -0400 Subject: Automatic commit of package [openshift-ansible-bin] release [0.0.4-1]. --- bin/openshift-ansible-bin.spec | 5 ++++- rel-eng/packages/openshift-ansible-bin | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'bin') diff --git a/bin/openshift-ansible-bin.spec b/bin/openshift-ansible-bin.spec index 7cca5ffba..f87002456 100644 --- a/bin/openshift-ansible-bin.spec +++ b/bin/openshift-ansible-bin.spec @@ -1,6 +1,6 @@ Summary: OpenShift Ansible Scripts for working with metadata hosts Name: openshift-ansible-bin -Version: 0.0.3 +Version: 0.0.4 Release: 1%{?dist} License: ASL 2.0 URL: https://github.com/openshift/openshift-ansible @@ -36,6 +36,9 @@ cp -p openshift_ansible.conf.example %{buildroot}/etc/openshift_ansible/openshif %config(noreplace) /etc/openshift_ansible/ %changelog +* Tue Mar 31 2015 Thomas Wiest 0.0.4-1 +- Fixed when tag was missing and added opssh completion (kwoodson@redhat.com) + * Mon Mar 30 2015 Thomas Wiest 0.0.3-1 - created a python package named openshift_ansible (twiest@redhat.com) diff --git a/rel-eng/packages/openshift-ansible-bin b/rel-eng/packages/openshift-ansible-bin index 36b150859..a0e3e205c 100644 --- a/rel-eng/packages/openshift-ansible-bin +++ b/rel-eng/packages/openshift-ansible-bin @@ -1 +1 @@ -0.0.3-1 bin/ +0.0.4-1 bin/ -- cgit v1.2.3 From 4712e72c912a1102bff0508c98bd97da3f33ae95 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Mon, 23 Mar 2015 23:53:17 -0400 Subject: openshift_facts role/module refactor default settings - Add openshift_facts role and module - Created new role openshift_facts that contains an openshift_facts module - Refactor openshift_* roles to use openshift_facts instead of relying on defaults - Refactor playbooks to use openshift_facts - Cleanup inventory group_vars - Update defaults - update openshift_master role firewall defaults - remove etcd peer port, since we will not be supporting clustered embedded etcd - remove 8444 since console now runs on the api port by default - add 8444 and 7001 to disabled services to ensure removal if updating - Add new role os_env_extras_node that is a subset of the docker role - previously, we were starting/enabling docker which was causing issues with some installations - Does not install or start docker, since the openshift-node role will handle that for us - Only adds root to the dockerroot group - Update playbooks to use ops_env_extras_node role instead of docker role - os_firewall bug fixes - ignore ip6tables for now, since we are not configuring any ipv6 rules - if installing package do a daemon-reload before starting/enabling service - Add aws support to bin/cluster - Add list action to bin/cluster - Add update action to bin/cluster - cleanup some stray debug statements - some variable renaming for clarity --- README_AWS.md | 26 +- README_GCE.md | 25 +- bin/cluster | 17 +- cluster.sh | 113 ----- inventory/aws/group_vars/all | 2 + inventory/gce/group_vars/all | 5 - inventory/gce/group_vars/tag_host-type-master | 5 - inventory/gce/group_vars/tag_host-type-node | 6 - .../gce/group_vars/tag_host-type-openshift-master | 1 - .../gce/group_vars/tag_host-type-openshift-node | 1 - playbooks/aws/openshift-cluster/filter_plugins | 1 + playbooks/aws/openshift-cluster/launch.yml | 62 +++ .../aws/openshift-cluster/launch_instances.yml | 62 +++ playbooks/aws/openshift-cluster/list.yml | 17 + playbooks/aws/openshift-cluster/roles | 1 + playbooks/aws/openshift-cluster/terminate.yml | 14 + playbooks/aws/openshift-cluster/update.yml | 13 + playbooks/aws/openshift-cluster/vars.yml | 1 + playbooks/aws/openshift-master/config.yml | 37 +- playbooks/aws/openshift-master/launch.yml | 9 +- playbooks/aws/openshift-master/terminate.yml | 52 +++ playbooks/aws/openshift-master/vars.yml | 1 + playbooks/aws/openshift-node/config.yml | 123 ++++-- playbooks/aws/openshift-node/launch.yml | 13 +- playbooks/aws/openshift-node/terminate.yml | 52 +++ playbooks/aws/openshift-node/vars.yml | 1 + playbooks/gce/openshift-cluster/launch.yml | 9 +- .../gce/openshift-cluster/launch_instances.yml | 7 +- playbooks/gce/openshift-cluster/list.yml | 17 + playbooks/gce/openshift-cluster/update.yml | 13 + playbooks/gce/openshift-master/config.yml | 6 +- playbooks/gce/openshift-master/launch.yml | 12 +- playbooks/gce/openshift-master/terminate.yml | 16 +- playbooks/gce/openshift-master/vars.yml | 1 + playbooks/gce/openshift-node/config.yml | 94 ++-- playbooks/gce/openshift-node/launch.yml | 22 +- playbooks/gce/openshift-node/terminate.yml | 16 +- playbooks/gce/openshift-node/vars.yml | 1 + roles/openshift_common/README.md | 17 +- roles/openshift_common/defaults/main.yml | 1 + roles/openshift_common/meta/main.yml | 1 + roles/openshift_common/tasks/main.yml | 29 +- roles/openshift_common/tasks/set_facts.yml | 9 - roles/openshift_common/vars/main.yml | 5 +- roles/openshift_facts/README.md | 34 ++ roles/openshift_facts/library/openshift_facts.py | 482 +++++++++++++++++++++ roles/openshift_facts/meta/main.yml | 15 + roles/openshift_facts/tasks/main.yml | 3 + roles/openshift_master/README.md | 28 +- roles/openshift_master/defaults/main.yml | 13 +- roles/openshift_master/handlers/main.yml | 1 - roles/openshift_master/tasks/main.yml | 50 ++- roles/openshift_master/vars/main.yml | 2 - roles/openshift_node/README.md | 3 - roles/openshift_node/defaults/main.yml | 2 - roles/openshift_node/handlers/main.yml | 2 +- roles/openshift_node/tasks/main.yml | 27 +- roles/openshift_node/vars/main.yml | 2 - roles/openshift_register_nodes/README.md | 22 +- .../library/kubernetes_register_node.py | 3 +- roles/openshift_register_nodes/meta/main.yml | 141 +----- roles/openshift_register_nodes/tasks/main.yml | 58 ++- roles/openshift_repos/defaults/main.yaml | 2 + roles/openshift_repos/meta/main.yml | 3 +- roles/openshift_repos/tasks/main.yaml | 6 + roles/openshift_sdn_master/defaults/main.yml | 2 - roles/openshift_sdn_master/meta/main.yml | 3 +- roles/openshift_sdn_master/tasks/main.yml | 18 +- roles/openshift_sdn_node/README.md | 6 - roles/openshift_sdn_node/defaults/main.yml | 2 - roles/openshift_sdn_node/meta/main.yml | 3 +- roles/openshift_sdn_node/tasks/main.yml | 23 +- roles/os_env_extras_node/tasks/main.yml | 5 + .../library/os_firewall_manage_iptables.py | 1 + roles/os_firewall/meta/main.yml | 1 + roles/os_firewall/tasks/firewall/firewalld.yml | 5 + roles/os_firewall/tasks/firewall/iptables.yml | 12 +- 77 files changed, 1290 insertions(+), 626 deletions(-) delete mode 100755 cluster.sh create mode 100644 inventory/aws/group_vars/all delete mode 100644 inventory/gce/group_vars/tag_host-type-master delete mode 100644 inventory/gce/group_vars/tag_host-type-node delete mode 120000 inventory/gce/group_vars/tag_host-type-openshift-master delete mode 120000 inventory/gce/group_vars/tag_host-type-openshift-node create mode 120000 playbooks/aws/openshift-cluster/filter_plugins create mode 100644 playbooks/aws/openshift-cluster/launch.yml create mode 100644 playbooks/aws/openshift-cluster/launch_instances.yml create mode 100644 playbooks/aws/openshift-cluster/list.yml create mode 120000 playbooks/aws/openshift-cluster/roles create mode 100644 playbooks/aws/openshift-cluster/terminate.yml create mode 100644 playbooks/aws/openshift-cluster/update.yml create mode 100644 playbooks/aws/openshift-cluster/vars.yml create mode 100644 playbooks/aws/openshift-master/terminate.yml create mode 100644 playbooks/aws/openshift-node/terminate.yml create mode 100644 playbooks/gce/openshift-cluster/list.yml create mode 100644 playbooks/gce/openshift-cluster/update.yml delete mode 100644 roles/openshift_common/tasks/set_facts.yml create mode 100644 roles/openshift_facts/README.md create mode 100755 roles/openshift_facts/library/openshift_facts.py create mode 100644 roles/openshift_facts/meta/main.yml create mode 100644 roles/openshift_facts/tasks/main.yml delete mode 100644 roles/openshift_master/vars/main.yml delete mode 100644 roles/openshift_node/vars/main.yml mode change 100644 => 100755 roles/openshift_register_nodes/library/kubernetes_register_node.py delete mode 100644 roles/openshift_sdn_master/defaults/main.yml delete mode 100644 roles/openshift_sdn_node/defaults/main.yml create mode 100644 roles/os_env_extras_node/tasks/main.yml mode change 100644 => 100755 roles/os_firewall/library/os_firewall_manage_iptables.py (limited to 'bin') diff --git a/README_AWS.md b/README_AWS.md index fb9d0f895..e877f34c6 100644 --- a/README_AWS.md +++ b/README_AWS.md @@ -51,7 +51,29 @@ OSX: Test The Setup -------------- 1. cd openshift-ansible -1. Try to list all instances: +1. Try to list all instances (Passing an empty string as the cluster_id +argument will result in all ec2 instances being listed) ``` - ./cloud.rb aws list + bin/cluster list aws '' +``` + +Creating a cluster +------------------ +1. To create a cluster with one master and two nodes +``` + bin/cluster create aws +``` + +Updating a cluster +--------------------- +1. To update the cluster +``` + bin/cluster update aws +``` + +Terminating a cluster +--------------------- +1. To terminate the cluster +``` + bin/cluster terminate aws ``` diff --git a/README_GCE.md b/README_GCE.md index 209705113..f6c5138c1 100644 --- a/README_GCE.md +++ b/README_GCE.md @@ -65,12 +65,29 @@ Install Dependencies Test The Setup -------------- 1. cd openshift-ansible/ -2. Try to list all instances: +1. Try to list all instances (Passing an empty string as the cluster_id +argument will result in all gce instances being listed) ``` - ./cloud.rb gce list + bin/cluster list gce '' ``` -3. Try to create an instance: +Creating a cluster +------------------ +1. To create a cluster with one master and two nodes ``` - ./cloud.rb gce launch -e int --type openshift-node + bin/cluster create gce +``` + +Updating a cluster +--------------------- +1. To update the cluster +``` + bin/cluster update gce +``` + +Terminating a cluster +--------------------- +1. To terminate the cluster +``` + bin/cluster terminate gce ``` diff --git a/bin/cluster b/bin/cluster index b99286b46..36ab1da1b 100755 --- a/bin/cluster +++ b/bin/cluster @@ -32,8 +32,8 @@ class Cluster(object): playbook = "playbooks/{}/openshift-cluster/launch.yml".format(args.provider) inventory = self.setup_provider(args.provider) - env['masters'] = args.masters - env['nodes'] = args.nodes + env['num_masters'] = args.masters + env['num_nodes'] = args.nodes return self.action(args, inventory, env, playbook) @@ -55,16 +55,23 @@ class Cluster(object): :param args: command line arguments provided by user :return: exit status from run command """ - raise NotImplementedError("ACTION [{}] not implemented".format(sys._getframe().f_code.co_name)) + env = {'cluster_id': args.cluster_id} + playbook = "playbooks/{}/openshift-cluster/list.yml".format(args.provider) + inventory = self.setup_provider(args.provider) + + return self.action(args, inventory, env, playbook) def update(self, args): """ - Update OpenShift across clustered VMs + Update to latest OpenShift across clustered VMs :param args: command line arguments provided by user :return: exit status from run command """ - raise NotImplementedError("ACTION [{}] not implemented".format(sys._getframe().f_code.co_name)) + env = {'cluster_id': args.cluster_id} + 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): """ diff --git a/cluster.sh b/cluster.sh deleted file mode 100755 index 9c9aad4d2..000000000 --- a/cluster.sh +++ /dev/null @@ -1,113 +0,0 @@ -#!/bin/bash -eu - -NODES=2 -MASTERS=1 - -# If the environment variable OO_PROVDER is defined, it used for the provider -PROVIDER=${OO_PROVIDER:-''} -# Otherwise, default is gce (Google Compute Engine) -if [ "x$PROVIDER" == "x" ];then - PROVIDER=gce -fi - -UPPER_CASE_PROVIDER=$(echo $PROVIDER | tr '[:lower:]' '[:upper:]') - - -# Use OO_MASTER_PLAYBOOK/OO_NODE_PLAYBOOK environment variables for playbooks if defined, -# otherwise use openshift default values. -MASTER_PLAYBOOK=${OO_MASTER_PLAYBOOK:-'openshift-master'} -NODE_PLAYBOOK=${OO_NODE_PLAYBOOK:-'openshift-node'} - - -# @formatter:off -function usage { - cat 1>&2 <<-EOT - ${0} : [create|terminate|update|list] { ${UPPER_CASE_PROVIDER} environment tag} - - Supported environment tags: - $(grep --no-messages 'SUPPORTED_ENVS.*=' ./lib/${PROVIDER}_command.rb) - $([ $? -ne 0 ] && echo "No supported environment tags found for ${PROVIDER}") - - Optional arguments for create: - [-p|--provider, -m|--masters, -n|--nodes, --master-playbook, --node-playbook] - - Optional arguments for terminate|update: - [-p|--provider, --master-playbook, --node-playbook] -EOT -} -# @formatter:on - -function create_cluster { - ./cloud.rb "${PROVIDER}" launch -e "${ENV}" --type=$MASTER_PLAYBOOK -c $MASTERS - - ./cloud.rb "${PROVIDER}" launch -e "${ENV}" --type=$NODE_PLAYBOOK -c $NODES - - update_cluster - - echo -e "\nCreated ${MASTERS}/${MASTER_PLAYBOOK} masters and ${NODES}/${NODE_PLAYBOOK} nodes using ${PROVIDER} provider\n" -} - -function update_cluster { - ./cloud.rb "${PROVIDER}" config -e "${ENV}" --type=$MASTER_PLAYBOOK - ./cloud.rb "${PROVIDER}" config -e "${ENV}" --type=$NODE_PLAYBOOK -} - -function terminate_cluster { - ./cloud.rb "${PROVIDER}" terminate -e "${ENV}" --type=$MASTER_PLAYBOOK - ./cloud.rb "${PROVIDER}" terminate -e "${ENV}" --type=$NODE_PLAYBOOK -} - -[ -f ./cloud.rb ] || (echo 1>&2 'Cannot find ./cloud.rb' && exit 1) - -function check_argval { - if [[ $1 == -* ]]; then - echo "Invalid value: '$1'" - usage - exit 1 - fi -} - -# Using GNU getopt to support both small and long formats -OPTIONS=`getopt -o p:m:n:h --long provider:,masters:,nodes:,master-playbook:,node-playbook:,help \ - -n "$0" -- "$@"` -eval set -- "$OPTIONS" - -while true; do - case "$1" in - -h|--help) (usage; exit 1) ; shift ;; - -p|--provider) PROVIDER="$2" ; check_argval $2 ; shift 2 ;; - -m|--masters) MASTERS="$2" ; check_argval $2 ; shift 2 ;; - -n|--nodes) NODES="$2" ; check_argval $2 ; shift 2 ;; - --master-playbook) MASTER_PLAYBOOK="$2" ; check_argval $2 ; shift 2 ;; - --node-playbook) NODE_PLAYBOOK="$2" ; check_argval $2 ; shift 2 ;; - --) shift ; break ;; - *) break ;; - esac -done - -shift $((OPTIND-1)) - -[ -z "${1:-}" ] && (usage; exit 1) - -case "${1}" in - 'create') - [ -z "${2:-}" ] && (usage; exit 1) - ENV="${2}" - create_cluster ;; - 'update') - [ -z "${2:-}" ] && (usage; exit 1) - ENV="${2}" - update_cluster ;; - 'terminate') - [ -z "${2:-}" ] && (usage; exit 1) - ENV="${2}" - terminate_cluster ;; - 'list') ./cloud.rb "${PROVIDER}" list ;; - 'help') usage; exit 0 ;; - *) - echo -n 1>&2 "${1} is not a supported operation"; - usage; - exit 1 ;; -esac - -exit 0 diff --git a/inventory/aws/group_vars/all b/inventory/aws/group_vars/all new file mode 100644 index 000000000..b22da00de --- /dev/null +++ b/inventory/aws/group_vars/all @@ -0,0 +1,2 @@ +--- +ansible_ssh_user: root diff --git a/inventory/gce/group_vars/all b/inventory/gce/group_vars/all index 3e969df63..b22da00de 100644 --- a/inventory/gce/group_vars/all +++ b/inventory/gce/group_vars/all @@ -1,7 +1,2 @@ --- ansible_ssh_user: root -openshift_hostname: "{{ ansible_default_ipv4.address }}" -openshift_public_hostname: "{{ ansible_default_ipv4.address }}" -openshift_ip: "{{ ansible_default_ipv4.address }}" -openshift_public_ip: "{{ gce_public_ip }}" -openshift_env: "{{ oo_env }}" diff --git a/inventory/gce/group_vars/tag_host-type-master b/inventory/gce/group_vars/tag_host-type-master deleted file mode 100644 index ddbdc650c..000000000 --- a/inventory/gce/group_vars/tag_host-type-master +++ /dev/null @@ -1,5 +0,0 @@ ---- -openshift_api_url: https://{{ openshift_hostname }}:8443 -openshift_api_public_url: https://{{ openshift_public_hostname }}:8443 -openshift_webui_url: https://{{ openshift_hostname }}:8444 -openshift_webui_public_url: https://{{ openshift_public_hostname }}:8444 diff --git a/inventory/gce/group_vars/tag_host-type-node b/inventory/gce/group_vars/tag_host-type-node deleted file mode 100644 index bb95a724d..000000000 --- a/inventory/gce/group_vars/tag_host-type-node +++ /dev/null @@ -1,6 +0,0 @@ ---- -openshift_node_cpu: -openshift_node_memory: -openshift_node_pod_cidr: -openshift_node_labels: {} -openshift_node_annotations: {} diff --git a/inventory/gce/group_vars/tag_host-type-openshift-master b/inventory/gce/group_vars/tag_host-type-openshift-master deleted file mode 120000 index c0c4cf370..000000000 --- a/inventory/gce/group_vars/tag_host-type-openshift-master +++ /dev/null @@ -1 +0,0 @@ -tag_host-type-master \ No newline at end of file diff --git a/inventory/gce/group_vars/tag_host-type-openshift-node b/inventory/gce/group_vars/tag_host-type-openshift-node deleted file mode 120000 index ebbce6136..000000000 --- a/inventory/gce/group_vars/tag_host-type-openshift-node +++ /dev/null @@ -1 +0,0 @@ -tag_host-type-node \ No newline at end of file diff --git a/playbooks/aws/openshift-cluster/filter_plugins b/playbooks/aws/openshift-cluster/filter_plugins new file mode 120000 index 000000000..99a95e4ca --- /dev/null +++ b/playbooks/aws/openshift-cluster/filter_plugins @@ -0,0 +1 @@ +../../../filter_plugins \ No newline at end of file diff --git a/playbooks/aws/openshift-cluster/launch.yml b/playbooks/aws/openshift-cluster/launch.yml new file mode 100644 index 000000000..3561c1803 --- /dev/null +++ b/playbooks/aws/openshift-cluster/launch.yml @@ -0,0 +1,62 @@ +--- +- name: Launch instance(s) + hosts: localhost + connection: local + gather_facts: no + vars_files: + - vars.yml + tasks: + - set_fact: k8s_type="master" + + - name: Generate master instance names(s) + set_fact: scratch={{ cluster_id }}-{{ k8s_type }}-{{ '%05x' |format( 1048576 |random) }} + register: master_names_output + with_sequence: start=1 end={{ num_masters }} + + # These set_fact's cannot be combined + - set_fact: + master_names_string: "{% for item in master_names_output.results %}{{ item.ansible_facts.scratch }} {% endfor %}" + + - set_fact: + master_names: "{{ master_names_string.strip().split(' ') }}" + + - include: launch_instances.yml + vars: + instances: "{{ master_names }}" + cluster: "{{ cluster_id }}" + type: "{{ k8s_type }}" + + - set_fact: k8s_type="node" + + - name: Generate node instance names(s) + set_fact: scratch={{ cluster_id }}-{{ k8s_type }}-{{ '%05x' |format( 1048576 |random) }} + register: node_names_output + with_sequence: start=1 end={{ num_nodes }} + + # These set_fact's cannot be combined + - set_fact: + node_names_string: "{% for item in node_names_output.results %}{{ item.ansible_facts.scratch }} {% endfor %}" + + - set_fact: + node_names: "{{ node_names_string.strip().split(' ') }}" + + - include: launch_instances.yml + vars: + instances: "{{ node_names }}" + cluster: "{{ cluster_id }}" + type: "{{ k8s_type }}" + +- hosts: "tag_env_{{ cluster_id }}" + roles: + - openshift_repos + - os_update_latest + +- include: ../openshift-master/config.yml + vars: + oo_host_group_exp: "groups[\"tag_env-host-type_{{ cluster_id }}-openshift-master\"]" + +- include: ../openshift-node/config.yml + vars: + oo_host_group_exp: "groups[\"tag_env-host-type_{{ cluster_id }}-openshift-node\"]" + +- include: list.yml diff --git a/playbooks/aws/openshift-cluster/launch_instances.yml b/playbooks/aws/openshift-cluster/launch_instances.yml new file mode 100644 index 000000000..e4d5952fd --- /dev/null +++ b/playbooks/aws/openshift-cluster/launch_instances.yml @@ -0,0 +1,62 @@ +--- +- set_fact: + machine_type: "{{ lookup('env', 'ec2_instance_type')|default('m3.large', true) }}" + machine_image: "{{ lookup('env', 'ec2_ami')|default('ami-307b3658', true) }}" + machine_region: "{{ lookup('env', 'ec2_region')|default('us-east-1', true) }}" + machine_keypair: "{{ lookup('env', 'ec2_keypair')|default('libra', true) }}" + created_by: "{{ lookup('env', 'LOGNAME')|default(cluster, true) }}" + env: "{{ cluster }}" + host_type: "{{ type }}" + env_host_type: "{{ cluster }}-openshift-{{ type }}" + +- name: Launch instance(s) + ec2: + state: present + region: "{{ machine_region }}" + keypair: "{{ machine_keypair }}" + group: ['public'] + instance_type: "{{ machine_type }}" + image: "{{ machine_image }}" + count: "{{ instances | oo_len }}" + wait: yes + instance_tags: + created-by: "{{ created_by }}" + env: "{{ env }}" + host-type: "{{ host_type }}" + env-host-type: "{{ env_host_type }}" + register: ec2 + +- name: Add Name tag to instances + ec2_tag: resource={{ item.1.id }} region={{ machine_region }} state=present + with_together: + - instances + - ec2.instances + args: + tags: + Name: "{{ item.0 }}" + +- set_fact: + instance_groups: tag_created-by_{{ created_by }}, tag_env_{{ env }}, tag_host-type_{{ host_type }}, tag_env-host-type_{{ env_host_type }} + +- name: Add new instances groups and variables + add_host: + hostname: "{{ item.0 }}" + ansible_ssh_host: "{{ item.1.dns_name }}" + groups: "{{ instance_groups }}" + ec2_private_ip_address: "{{ item.1.private_ip }}" + ec2_ip_address: "{{ item.1.public_ip }}" + with_together: + - instances + - ec2.instances + +- name: Wait for ssh + wait_for: "port=22 host={{ item.dns_name }}" + with_items: ec2.instances + +- name: Wait for root user setup + command: "ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o ConnectTimeout=10 -o UserKnownHostsFile=/dev/null root@{{ item.dns_name }} echo root user is setup" + register: result + until: result.rc == 0 + retries: 20 + delay: 10 + with_items: ec2.instances diff --git a/playbooks/aws/openshift-cluster/list.yml b/playbooks/aws/openshift-cluster/list.yml new file mode 100644 index 000000000..08e9e2df4 --- /dev/null +++ b/playbooks/aws/openshift-cluster/list.yml @@ -0,0 +1,17 @@ +--- +- name: Generate oo_list_hosts group + hosts: localhost + gather_facts: no + tasks: + - set_fact: scratch_group=tag_env_{{ cluster_id }} + when: cluster_id != '' + - set_fact: scratch_group=all + when: scratch_group is not defined + - add_host: name={{ item }} groups=oo_list_hosts + with_items: groups[scratch_group] | difference(['localhost']) + +- name: List Hosts + hosts: oo_list_hosts + gather_facts: no + tasks: + - debug: msg="public:{{hostvars[inventory_hostname].ec2_ip_address}} private:{{hostvars[inventory_hostname].ec2_private_ip_address}}" diff --git a/playbooks/aws/openshift-cluster/roles b/playbooks/aws/openshift-cluster/roles new file mode 120000 index 000000000..20c4c58cf --- /dev/null +++ b/playbooks/aws/openshift-cluster/roles @@ -0,0 +1 @@ +../../../roles \ No newline at end of file diff --git a/playbooks/aws/openshift-cluster/terminate.yml b/playbooks/aws/openshift-cluster/terminate.yml new file mode 100644 index 000000000..39607633a --- /dev/null +++ b/playbooks/aws/openshift-cluster/terminate.yml @@ -0,0 +1,14 @@ +--- +- name: Terminate instance(s) + hosts: localhost + + vars_files: + - vars.yml + +- include: ../openshift-node/terminate.yml + vars: + oo_host_group_exp: 'groups["tag_env-host-type_{{ cluster_id }}-openshift-node"]' + +- include: ../openshift-master/terminate.yml + vars: + oo_host_group_exp: 'groups["tag_env-host-type_{{ cluster_id }}-openshift-master"]' diff --git a/playbooks/aws/openshift-cluster/update.yml b/playbooks/aws/openshift-cluster/update.yml new file mode 100644 index 000000000..90ecdc6ab --- /dev/null +++ b/playbooks/aws/openshift-cluster/update.yml @@ -0,0 +1,13 @@ +--- +- hosts: "tag_env_{{ cluster_id }}" + roles: + - openshift_repos + - os_update_latest + +- include: ../openshift-master/config.yml + vars: + oo_host_group_exp: "groups[\"tag_env-host-type_{{ cluster_id }}-openshift-master\"]" + +- include: ../openshift-node/config.yml + vars: + oo_host_group_exp: "groups[\"tag_env-host-type_{{ cluster_id }}-openshift-node\"]" diff --git a/playbooks/aws/openshift-cluster/vars.yml b/playbooks/aws/openshift-cluster/vars.yml new file mode 100644 index 000000000..ed97d539c --- /dev/null +++ b/playbooks/aws/openshift-cluster/vars.yml @@ -0,0 +1 @@ +--- diff --git a/playbooks/aws/openshift-master/config.yml b/playbooks/aws/openshift-master/config.yml index bbf1f654a..1c4060eee 100644 --- a/playbooks/aws/openshift-master/config.yml +++ b/playbooks/aws/openshift-master/config.yml @@ -1,5 +1,5 @@ --- -- name: "populate oo_masters_to_config host group if needed" +- name: Populate oo_masters_to_config host group if needed hosts: localhost gather_facts: no tasks: @@ -8,34 +8,17 @@ with_items: "{{ oo_host_group_exp | default('') }}" when: oo_host_group_exp is defined -- name: "Gather facts for nodes in {{ oo_env }}" - hosts: "tag_env-host-type_{{ oo_env }}-openshift-node" - connection: ssh - user: root - -- name: "Set Origin specific facts on localhost (for later use)" - hosts: localhost - gather_facts: no - tasks: - - name: Setting openshift_node_ips fact on localhost - set_fact: - openshift_node_ips: "{{ hostvars - | oo_select_keys(groups['tag_env-host-type_' + oo_env + '-openshift-node']) - | oo_collect(attribute='ansible_default_ipv4.address') }}" - when: groups['tag_env-host-type_' + oo_env + '-openshift-node'] is defined - -- name: "Configure instances" +- name: Configure instances hosts: oo_masters_to_config - connection: ssh - user: root + vars: + openshift_hostname: "{{ ec2_private_ip_address }}" + openshift_public_hostname: "{{ ec2_ip_address }}" + # TODO: this should be removed once openshift-sdn packages are available + openshift_use_openshift_sdn: False vars_files: - - vars.yml + - vars.yml roles: - - { - role: openshift_master, - openshift_node_ips: "{{ hostvars['localhost'].openshift_node_ips | default(['']) }}", - openshift_env: "{{ oo_env }}", - openshift_public_ip: "{{ ec2_ip_address }}" - } + - openshift_master + #- openshift_sdn_master - pods - os_env_extras diff --git a/playbooks/aws/openshift-master/launch.yml b/playbooks/aws/openshift-master/launch.yml index 3d5a7f579..3d87879a0 100644 --- a/playbooks/aws/openshift-master/launch.yml +++ b/playbooks/aws/openshift-master/launch.yml @@ -46,13 +46,16 @@ tags: "{{ oo_new_inst_tags }}" - name: Add new instances public IPs to oo_masters_to_config - add_host: "hostname={{ item.0 }} ansible_ssh_host={{ item.1.dns_name }} groupname=oo_masters_to_config" + add_host: + hostname: "{{ item.0 }}" + ansible_ssh_host: "{{ item.1.dns_name }}" + groupname: oo_masters_to_config + ec2_private_ip_address: "{{ item.1.private_ip }}" + ec2_ip_address: "{{ item.1.public_ip }}" with_together: - oo_new_inst_names - ec2.instances - - debug: var=ec2 - - name: Wait for ssh wait_for: "port=22 host={{ item.dns_name }}" with_items: ec2.instances diff --git a/playbooks/aws/openshift-master/terminate.yml b/playbooks/aws/openshift-master/terminate.yml new file mode 100644 index 000000000..fd15cf00f --- /dev/null +++ b/playbooks/aws/openshift-master/terminate.yml @@ -0,0 +1,52 @@ +--- +- name: Populate oo_masters_to_terminate host group if needed + hosts: localhost + gather_facts: no + tasks: + - name: Evaluate oo_host_group_exp if it's set + add_host: "name={{ item }} groups=oo_masters_to_terminate" + with_items: "{{ oo_host_group_exp | default('') }}" + when: oo_host_group_exp is defined + +- name: Gather facts for instances to terminate + hosts: oo_masters_to_terminate + +- name: Terminate instances + hosts: localhost + connection: local + gather_facts: no + vars: + host_vars: "{{ hostvars + | oo_select_keys(groups['oo_masters_to_terminate']) }}" + tasks: + - name: Terminate instances + ec2: + state: absent + instance_ids: ["{{ item.ec2_id }}"] + region: "{{ item.ec2_region }}" + ignore_errors: yes + register: ec2_term + with_items: host_vars + + # Fail if any of the instances failed to terminate with an error other + # than 403 Forbidden + - fail: msg=Terminating instance {{ item.item.ec2_id }} failed with message {{ item.msg }} + when: "item.failed and not item.msg | search(\"error: EC2ResponseError: 403 Forbidden\")" + with_items: ec2_term.results + + - name: Stop instance if termination failed + ec2: + state: stopped + instance_ids: ["{{ item.item.ec2_id }}"] + region: "{{ item.item.ec2_region }}" + register: ec2_stop + when: item.failed + with_items: ec2_term.results + + - name: Rename stopped instances + ec2_tag: resource={{ item.item.item.ec2_id }} region={{ item.item.item.ec2_region }} state=present + args: + tags: + Name: "{{ item.item.item.ec2_tag_Name }}-terminate" + with_items: ec2_stop.results + diff --git a/playbooks/aws/openshift-master/vars.yml b/playbooks/aws/openshift-master/vars.yml index fb5f4ea42..c196b2fca 100644 --- a/playbooks/aws/openshift-master/vars.yml +++ b/playbooks/aws/openshift-master/vars.yml @@ -1,2 +1,3 @@ --- openshift_debug_level: 4 +openshift_cluster_id: "{{ cluster_id }}" diff --git a/playbooks/aws/openshift-node/config.yml b/playbooks/aws/openshift-node/config.yml index 3cf2c58b2..b08ed7571 100644 --- a/playbooks/aws/openshift-node/config.yml +++ b/playbooks/aws/openshift-node/config.yml @@ -1,5 +1,5 @@ --- -- name: "populate oo_nodes_to_config host group if needed" +- name: Populate oo_nodes_to_config host group if needed hosts: localhost gather_facts: no tasks: @@ -7,42 +7,101 @@ add_host: "name={{ item }} groups=oo_nodes_to_config" with_items: "{{ oo_host_group_exp | default('') }}" when: oo_host_group_exp is defined + - add_host: + name: "{{ groups['tag_env-host-type_' ~ cluster_id ~ '-openshift-master'][0] }}" + groups: oo_first_master + when: oo_host_group_exp is defined -- name: "Gather facts for masters in {{ oo_env }}" - hosts: "tag_env-host-type_{{ oo_env }}-openshift-master" - connection: ssh - user: root -- name: "Set OO sepcific facts on localhost (for later use)" - hosts: localhost - gather_facts: no +- name: Gather and set facts for hosts to configure + hosts: oo_nodes_to_config + roles: + - openshift_facts tasks: - - name: Setting openshift_master_ips fact on localhost - set_fact: - openshift_master_ips: "{{ hostvars - | oo_select_keys(groups['tag_env-host-type_' + oo_env + '-openshift-master']) - | oo_collect(attribute='ansible_default_ipv4.address') }}" - when: groups['tag_env-host-type_' + oo_env + '-openshift-master'] is defined - - name: Setting openshift_master_public_ips fact on localhost - set_fact: - openshift_master_public_ips: "{{ hostvars - | oo_select_keys(groups['tag_env-host-type-' + oo_env + '-openshift-master']) - | oo_collect(attribute='ec2_ip_address') }}" - when: groups['tag_env-host-type-' + oo_env + '-openshift-master'] is defined - -- name: "Configure instances" + # Since the master is registering the nodes before they are configured, we + # need to make sure to set the node properties beforehand if we do not want + # the defaults + - openshift_facts: + role: "{{ item.role }}" + local_facts: "{{ item.local_facts }}" + with_items: + - role: common + local_facts: + hostname: "{{ ec2_private_ip_address }}" + public_hostname: "{{ ec2_ip_address }}" + # TODO: this should be removed once openshift-sdn packages are available + use_openshift_sdn: False + - role: node + local_facts: + external_id: "{{ openshift_node_external_id | default(None) }}" + resources_cpu: "{{ openshfit_node_resources_cpu | default(None) }}" + resources_memory: "{{ openshfit_node_resources_memory | default(None) }}" + pod_cidr: "{{ openshfit_node_pod_cidr | default(None) }}" + labels: "{{ openshfit_node_labels | default(None) }}" + annotations: "{{ openshfit_node_annotations | default(None) }}" + + +- name: Register nodes + hosts: oo_first_master + vars: + openshift_nodes: "{{ hostvars + | oo_select_keys(groups['oo_nodes_to_config']) }}" + roles: + - openshift_register_nodes + tasks: + - name: Create local temp directory for syncing certs + local_action: command /usr/bin/mktemp -d /tmp/openshift-ansible-XXXXXXX + register: mktemp + + - name: Sync master certs to localhost + synchronize: + mode: pull + checksum: yes + src: /var/lib/openshift/openshift.local.certificates + dest: "{{ mktemp.stdout }}" + + +- name: Configure instances hosts: oo_nodes_to_config - connection: ssh - user: root vars_files: - - vars.yml + - vars.yml + vars: + openshift_hostname: "{{ ec2_private_ip_address }}" + openshift_public_hostname: "{{ ec2_ip_address }}" + sync_tmpdir: "{{ hostvars[groups['oo_first_master'][0]].mktemp.stdout }}" + cert_parent_rel_path: openshift.local.certificates + cert_rel_path: "{{ cert_parent_rel_path }}/node-{{ openshift.common.hostname }}" + cert_base_path: /var/lib/openshift + cert_parent_path: "{{ cert_base_path }}/{{ cert_parent_rel_path }}" + cert_path: "{{ cert_base_path }}/{{ cert_rel_path }}" + pre_tasks: + - name: Ensure certificate directories exists + file: + path: "{{ item }}" + state: directory + with_items: + - "{{ cert_path }}" + - "{{ cert_parent_path }}/ca" + + # TODO: notify restart openshift-node and/or restart openshift-sdn-node, + # possibly test service started time against certificate/config file + # timestamps in openshift-node or openshift-sdn-node to trigger notify + - name: Sync certs to nodes + synchronize: + checksum: yes + src: "{{ item.src }}" + dest: "{{ item.dest }}" + owner: no + group: no + with_items: + - src: "{{ sync_tmpdir }}/{{ cert_rel_path }}" + dest: "{{ cert_parent_path }}" + - src: "{{ sync_tmpdir }}/{{ cert_parent_rel_path }}/ca/cert.crt" + dest: "{{ cert_parent_path }}/ca/cert.crt" + - local_action: file name={{ sync_tmpdir }} state=absent + run_once: true roles: - - { - role: openshift_node, - openshift_master_ips: "{{ hostvars['localhost'].openshift_master_ips | default(['']) }}", - openshift_master_public_ips: "{{ hostvars['localhost'].openshift_master_public_ips | default(['']) }}", - openshift_env: "{{ oo_env }}", - openshift_public_ip: "{{ ec2_ip_address }}" - } + - openshift_node + #- openshift_sdn_node - os_env_extras - os_env_extras_node diff --git a/playbooks/aws/openshift-node/launch.yml b/playbooks/aws/openshift-node/launch.yml index 4745fc658..b7ef593e7 100644 --- a/playbooks/aws/openshift-node/launch.yml +++ b/playbooks/aws/openshift-node/launch.yml @@ -27,7 +27,9 @@ register: ec2 - name: Add new instances public IPs to the atomic proxy host group - add_host: "hostname={{ item.public_ip }} groupname=new_ec2_instances" + add_host: + hostname: "{{ item.public_ip }}" + groupname: new_ec2_instances" with_items: ec2.instances - name: Add Name and environment tags to instances @@ -46,13 +48,16 @@ tags: "{{ oo_new_inst_tags }}" - name: Add new instances public IPs to oo_nodes_to_config - add_host: "hostname={{ item.0 }} ansible_ssh_host={{ item.1.dns_name }} groupname=oo_nodes_to_config" + add_host: + hostname: "{{ item.0 }}" + ansible_ssh_host: "{{ item.1.dns_name }}" + groupname: oo_nodes_to_config + ec2_private_ip_address: "{{ item.1.private_ip }}" + ec2_ip_address: "{{ item.1.public_ip }}" with_together: - oo_new_inst_names - ec2.instances - - debug: var=ec2 - - name: Wait for ssh wait_for: "port=22 host={{ item.dns_name }}" with_items: ec2.instances diff --git a/playbooks/aws/openshift-node/terminate.yml b/playbooks/aws/openshift-node/terminate.yml new file mode 100644 index 000000000..1c0c77eb7 --- /dev/null +++ b/playbooks/aws/openshift-node/terminate.yml @@ -0,0 +1,52 @@ +--- +- name: Populate oo_nodes_to_terminate host group if needed + hosts: localhost + gather_facts: no + tasks: + - name: Evaluate oo_host_group_exp if it's set + add_host: "name={{ item }} groups=oo_nodes_to_terminate" + with_items: "{{ oo_host_group_exp | default('') }}" + when: oo_host_group_exp is defined + +- name: Gather facts for instances to terminate + hosts: oo_nodes_to_terminate + +- name: Terminate instances + hosts: localhost + connection: local + gather_facts: no + vars: + host_vars: "{{ hostvars + | oo_select_keys(groups['oo_nodes_to_terminate']) }}" + tasks: + - name: Terminate instances + ec2: + state: absent + instance_ids: ["{{ item.ec2_id }}"] + region: "{{ item.ec2_region }}" + ignore_errors: yes + register: ec2_term + with_items: host_vars + + # Fail if any of the instances failed to terminate with an error other + # than 403 Forbidden + - fail: msg=Terminating instance {{ item.item.ec2_id }} failed with message {{ item.msg }} + when: "item.failed and not item.msg | search(\"error: EC2ResponseError: 403 Forbidden\")" + with_items: ec2_term.results + + - name: Stop instance if termination failed + ec2: + state: stopped + instance_ids: ["{{ item.item.ec2_id }}"] + region: "{{ item.item.ec2_region }}" + register: ec2_stop + when: item.failed + with_items: ec2_term.results + + - name: Rename stopped instances + ec2_tag: resource={{ item.item.item.ec2_id }} region={{ item.item.item.ec2_region }} state=present + args: + tags: + Name: "{{ item.item.item.ec2_tag_Name }}-terminate" + with_items: ec2_stop.results + diff --git a/playbooks/aws/openshift-node/vars.yml b/playbooks/aws/openshift-node/vars.yml index fb5f4ea42..c196b2fca 100644 --- a/playbooks/aws/openshift-node/vars.yml +++ b/playbooks/aws/openshift-node/vars.yml @@ -1,2 +1,3 @@ --- openshift_debug_level: 4 +openshift_cluster_id: "{{ cluster_id }}" diff --git a/playbooks/gce/openshift-cluster/launch.yml b/playbooks/gce/openshift-cluster/launch.yml index 889d92d40..14cdd2537 100644 --- a/playbooks/gce/openshift-cluster/launch.yml +++ b/playbooks/gce/openshift-cluster/launch.yml @@ -11,7 +11,7 @@ - name: Generate master instance names(s) set_fact: scratch={{ cluster_id }}-{{ k8s_type }}-{{ '%05x' |format( 1048576 |random) }} register: master_names_output - with_sequence: start=1 end={{ masters }} + with_sequence: start=1 end={{ num_masters }} # These set_fact's cannot be combined - set_fact: @@ -25,14 +25,13 @@ instances: "{{ master_names }}" cluster: "{{ cluster_id }}" type: "{{ k8s_type }}" - group_name: "tag_env-host-type-{{ cluster_id }}-openshift-master" - set_fact: k8s_type="node" - name: Generate node instance names(s) set_fact: scratch={{ cluster_id }}-{{ k8s_type }}-{{ '%05x' |format( 1048576 |random) }} register: node_names_output - with_sequence: start=1 end={{ nodes }} + with_sequence: start=1 end={{ num_nodes }} # These set_fact's cannot be combined - set_fact: @@ -55,9 +54,9 @@ - include: ../openshift-master/config.yml vars: oo_host_group_exp: "groups[\"tag_env-host-type-{{ cluster_id }}-openshift-master\"]" - oo_env: "{{ cluster_id }}" - include: ../openshift-node/config.yml vars: oo_host_group_exp: "groups[\"tag_env-host-type-{{ cluster_id }}-openshift-node\"]" - oo_env: "{{ cluster_id }}" + +- include: list.yml diff --git a/playbooks/gce/openshift-cluster/launch_instances.yml b/playbooks/gce/openshift-cluster/launch_instances.yml index 20e31d990..b4f33bd87 100644 --- a/playbooks/gce/openshift-cluster/launch_instances.yml +++ b/playbooks/gce/openshift-cluster/launch_instances.yml @@ -1,3 +1,7 @@ +--- +# TODO: when we are ready to go to ansible 1.9+ support only, we can update to +# the gce task to use the disk_auto_delete parameter to avoid having to delete +# the disk as a separate step on termination - set_fact: machine_type: "{{ lookup('env', 'gce_machine_type') |default('n1-standard-1', true) }}" @@ -18,12 +22,13 @@ - "env-host-type-{{ cluster }}-openshift-{{ type }}" register: gce -- name: Add new instances public IPs +- name: Add new instances to groups and set variables needed add_host: hostname: "{{ item.name }}" ansible_ssh_host: "{{ item.public_ip }}" groups: "{{ item.tags | oo_prepend_strings_in_list('tag_') | join(',') }}" gce_public_ip: "{{ item.public_ip }}" + gce_private_ip: "{{ item.private_ip }}" with_items: gce.instance_data - name: Wait for ssh diff --git a/playbooks/gce/openshift-cluster/list.yml b/playbooks/gce/openshift-cluster/list.yml new file mode 100644 index 000000000..1124b0ea3 --- /dev/null +++ b/playbooks/gce/openshift-cluster/list.yml @@ -0,0 +1,17 @@ +--- +- name: Generate oo_list_hosts group + hosts: localhost + gather_facts: no + tasks: + - set_fact: scratch_group=tag_env-{{ cluster_id }} + when: cluster_id != '' + - set_fact: scratch_group=all + when: scratch_group is not defined + - add_host: name={{ item }} groups=oo_list_hosts + with_items: groups[scratch_group] | difference(['localhost']) | difference(groups.status_terminated) + +- name: List Hosts + hosts: oo_list_hosts + gather_facts: no + tasks: + - debug: msg="public:{{hostvars[inventory_hostname].gce_public_ip}} private:{{hostvars[inventory_hostname].gce_private_ip}}" diff --git a/playbooks/gce/openshift-cluster/update.yml b/playbooks/gce/openshift-cluster/update.yml new file mode 100644 index 000000000..973e4c3ef --- /dev/null +++ b/playbooks/gce/openshift-cluster/update.yml @@ -0,0 +1,13 @@ +--- +- hosts: "tag_env-{{ cluster_id }}" + roles: + - openshift_repos + - os_update_latest + +- include: ../openshift-master/config.yml + vars: + oo_host_group_exp: "groups[\"tag_env-host-type-{{ cluster_id }}-openshift-master\"]" + +- include: ../openshift-node/config.yml + vars: + oo_host_group_exp: "groups[\"tag_env-host-type-{{ cluster_id }}-openshift-node\"]" diff --git a/playbooks/gce/openshift-master/config.yml b/playbooks/gce/openshift-master/config.yml index e405e2fb4..857da0763 100644 --- a/playbooks/gce/openshift-master/config.yml +++ b/playbooks/gce/openshift-master/config.yml @@ -1,3 +1,4 @@ +--- - name: master/config.yml, populate oo_masters_to_config host group if needed hosts: localhost gather_facts: no @@ -7,11 +8,10 @@ with_items: "{{ oo_host_group_exp | default('') }}" when: oo_host_group_exp is defined -- name: Gather facts for nodes in {{ oo_env }} - hosts: "tag_env-host-type-{{ oo_env }}-openshift-node" - - name: "Configure instances" hosts: oo_masters_to_config + vars: + openshift_hostname: "{{ gce_private_ip }}" vars_files: - vars.yml roles: diff --git a/playbooks/gce/openshift-master/launch.yml b/playbooks/gce/openshift-master/launch.yml index 3512274cc..287596002 100644 --- a/playbooks/gce/openshift-master/launch.yml +++ b/playbooks/gce/openshift-master/launch.yml @@ -1,4 +1,8 @@ --- +# TODO: when we are ready to go to ansible 1.9+ support only, we can update to +# the gce task to use the disk_auto_delete parameter to avoid having to delete +# the disk as a separate step on termination + - name: Launch instance(s) hosts: localhost connection: local @@ -25,15 +29,17 @@ register: gce - name: Add new instances public IPs to oo_masters_to_config - add_host: "hostname={{ item.name }} ansible_ssh_host={{ item.public_ip }} groupname=oo_masters_to_config" + add_host: + hostname: "{{ item.name }}" + ansible_ssh_host: "{{ item.public_ip }}" + groupname: oo_masters_to_config + gce_private_ip: "{{ item.private_ip }}" with_items: gce.instance_data - name: Wait for ssh wait_for: "port=22 host={{ item.public_ip }}" with_items: gce.instance_data - - debug: var=gce - - name: Wait for root user setup command: "ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o ConnectTimeout=10 -o UserKnownHostsFile=/dev/null root@{{ item.public_ip }} echo root user is setup" register: result diff --git a/playbooks/gce/openshift-master/terminate.yml b/playbooks/gce/openshift-master/terminate.yml index 9e027cf41..8319774f8 100644 --- a/playbooks/gce/openshift-master/terminate.yml +++ b/playbooks/gce/openshift-master/terminate.yml @@ -1,17 +1,13 @@ -- name: "populate oo_hosts_to_terminate host group if needed" +--- +- name: Populate oo_masters_to_terminate host group if needed hosts: localhost gather_facts: no tasks: - - debug: var=oo_host_group_exp - - name: Evaluate oo_host_group_exp if it's set - add_host: "name={{ item }} groups=oo_hosts_to_terminate" + add_host: "name={{ item }} groups=oo_masters_to_terminate" with_items: "{{ oo_host_group_exp | default('') }}" when: oo_host_group_exp is defined - - debug: msg="{{ groups['oo_hosts_to_terminate'] }}" - - - name: Terminate master instances hosts: localhost connection: local @@ -23,12 +19,10 @@ pem_file: "{{ gce_pem_file }}" project_id: "{{ gce_project_id }}" state: 'absent' - instance_names: "{{ groups['oo_hosts_to_terminate'] }}" - disks: "{{ groups['oo_hosts_to_terminate'] }}" + instance_names: "{{ groups['oo_masters_to_terminate'] }}" + disks: "{{ groups['oo_masters_to_terminate'] }}" register: gce - - debug: var=gce - - name: Remove disks of instances gce_pd: service_account_email: "{{ gce_service_account_email }}" diff --git a/playbooks/gce/openshift-master/vars.yml b/playbooks/gce/openshift-master/vars.yml index fb5f4ea42..c196b2fca 100644 --- a/playbooks/gce/openshift-master/vars.yml +++ b/playbooks/gce/openshift-master/vars.yml @@ -1,2 +1,3 @@ --- openshift_debug_level: 4 +openshift_cluster_id: "{{ cluster_id }}" diff --git a/playbooks/gce/openshift-node/config.yml b/playbooks/gce/openshift-node/config.yml index e0d074572..771cc3a94 100644 --- a/playbooks/gce/openshift-node/config.yml +++ b/playbooks/gce/openshift-node/config.yml @@ -1,3 +1,4 @@ +--- - name: node/config.yml, populate oo_nodes_to_config host group if needed hosts: localhost gather_facts: no @@ -6,50 +7,42 @@ add_host: "name={{ item }} groups=oo_nodes_to_config" with_items: "{{ oo_host_group_exp | default('') }}" when: oo_host_group_exp is defined - - name: Find masters for env - add_host: "name={{ item }} groups=oo_masters_for_node_config" - with_items: groups['tag_env-host-type-' + oo_env + '-openshift-master'] + - add_host: + name: "{{ groups['tag_env-host-type-' ~ cluster_id ~ '-openshift-master'][0] }}" + groups: oo_first_master + when: oo_host_group_exp is defined -- name: Gather facts for masters in {{ oo_env }} - hosts: tag_env-host-type-{{ oo_env }}-openshift-master - tasks: - - set_fact: - openshift_master_ip: "{{ openshift_ip }}" - openshift_master_api_url: "{{ openshift_api_url }}" - openshift_master_webui_url: "{{ openshift_webui_url }}" - openshift_master_hostname: "{{ openshift_hostname }}" - openshift_master_public_ip: "{{ openshift_public_ip }}" - openshift_master_api_public_url: "{{ openshift_api_public_url }}" - openshift_master_webui_public_url: "{{ openshift_webui_public_url }}" - openshift_master_public_hostnames: "{{ openshift_public_hostname }}" -- name: Gather facts for hosts to configure - hosts: tag_env-host-type-{{ oo_env }}-openshift-node +- name: Gather and set facts for hosts to configure + hosts: oo_nodes_to_config + roles: + - openshift_facts tasks: - - set_fact: - openshift_node_hostname: "{{ openshift_hostname }}" - openshift_node_name: "{{ openshift_hostname }}" - openshift_node_cpu: "{{ openshift_node_cpu if openshift_node_cpu else ansible_processor_cores }}" - openshift_node_memory: "{{ openshift_node_memory if openshift_node_memory else (ansible_memtotal_mb|int * 1024 * 1024 * 0.75)|int }}" - openshift_node_pod_cidr: "{{ openshift_node_pod_cidr if openshift_node_pod_cidr else None }}" - openshift_node_host_ip: "{{ openshift_ip }}" - openshift_node_labels: "{{ openshift_node_labels if openshift_node_labels else {} }}" - openshift_node_annotations: "{{ openshift_node_annotations if openshift_node_annotations else {} }}" + # Since the master is registering the nodes before they are configured, we + # need to make sure to set the node properties beforehand if we do not want + # the defaults + - openshift_facts: + role: "{{ item.role }}" + local_facts: "{{ item.local_facts }}" + with_items: + - role: common + local_facts: + hostname: "{{ gce_private_ip }}" + - role: node + local_facts: + external_id: "{{ openshift_node_external_id | default(None) }}" + resources_cpu: "{{ openshfit_node_resources_cpu | default(None) }}" + resources_memory: "{{ openshfit_node_resources_memory | default(None) }}" + pod_cidr: "{{ openshfit_node_pod_cidr | default(None) }}" + labels: "{{ openshfit_node_labels | default(None) }}" + annotations: "{{ openshfit_node_annotations | default(None) }}" + - name: Register nodes - hosts: tag_env-host-type-{{ oo_env }}-openshift-master[0] + hosts: oo_first_master vars: - openshift_node_group: tag_env-host-type-{{ oo_env }}-openshift-node openshift_nodes: "{{ hostvars - | oo_select_keys(groups[openshift_node_group]) }}" - openshift_master_group: tag_env-host-type-{{ oo_env }}-openshift-master - openshift_master_urls: "{{ hostvars - | oo_select_keys(groups[openshift_master_group]) - | oo_collect(attribute='openshift_master_api_url') }}" - openshift_master_public_urls: "{{ hostvars - | oo_select_keys(groups[openshift_master_group]) - | oo_collect(attribute='openshift_master_api_public_url') }}" - pre_tasks: + | oo_select_keys(groups['oo_nodes_to_config']) }}" roles: - openshift_register_nodes tasks: @@ -64,28 +57,14 @@ src: /var/lib/openshift/openshift.local.certificates dest: "{{ mktemp.stdout }}" -# TODO: sync generated certs between masters -# - name: Configure instances hosts: oo_nodes_to_config vars_files: - vars.yml vars: - openshift_master_group: tag_env-host-type-{{ oo_env }}-openshift-master - openshift_master_ips: "{{ hostvars - | oo_select_keys(groups[openshift_master_group]) - | oo_collect(attribute='openshift_master_ip') }}" - openshift_master_hostnames: "{{ hostvars - | oo_select_keys(groups[openshift_master_group]) - | oo_collect(attribute='openshift_master_hostname') }}" - openshift_master_public_ips: "{{ hostvars - | oo_select_keys(groups[openshift_master_group]) - | oo_collect(attribute='openshift_master_public_ip') }}" - openshift_master_public_hostnames: "{{ hostvars - | oo_select_keys(groups[openshift_master_group]) - | oo_collect(attribute='openshift_master_public_hostname') }}" + sync_tmpdir: "{{ hostvars[groups['oo_first_master'][0]].mktemp.stdout }}" cert_parent_rel_path: openshift.local.certificates - cert_rel_path: "{{ cert_parent_rel_path }}/node-{{ openshift_node_name }}" + cert_rel_path: "{{ cert_parent_rel_path }}/node-{{ openshift.common.hostname }}" cert_base_path: /var/lib/openshift cert_parent_path: "{{ cert_base_path }}/{{ cert_parent_rel_path }}" cert_path: "{{ cert_base_path }}/{{ cert_rel_path }}" @@ -98,11 +77,9 @@ - "{{ cert_path }}" - "{{ cert_parent_path }}/ca" - # TODO: only sync to a node if it's certs have been updated # TODO: notify restart openshift-node and/or restart openshift-sdn-node, # possibly test service started time against certificate/config file # timestamps in openshift-node or openshift-sdn-node to trigger notify - # TODO: also copy ca cert: /var/lib/openshift/openshift.local.certificates/ca/cert.crt - name: Sync certs to nodes synchronize: checksum: yes @@ -111,12 +88,13 @@ owner: no group: no with_items: - - src: "{{ hostvars[groups[openshift_master_group][0]].mktemp.stdout }}/{{ cert_rel_path }}" + - src: "{{ sync_tmpdir }}/{{ cert_rel_path }}" dest: "{{ cert_parent_path }}" - - src: "{{ hostvars[groups[openshift_master_group][0]].mktemp.stdout }}/{{ cert_parent_rel_path }}/ca/cert.crt" + - src: "{{ sync_tmpdir }}/{{ cert_parent_rel_path }}/ca/cert.crt" dest: "{{ cert_parent_path }}/ca/cert.crt" - - local_action: file name={{ hostvars[groups[openshift_master_group][0]].mktemp.stdout }} state=absent + - local_action: file name={{ sync_tmpdir }} state=absent run_once: true roles: - openshift_node - os_env_extras + - os_env_extras_node diff --git a/playbooks/gce/openshift-node/launch.yml b/playbooks/gce/openshift-node/launch.yml index ca2914d8a..73d0478ab 100644 --- a/playbooks/gce/openshift-node/launch.yml +++ b/playbooks/gce/openshift-node/launch.yml @@ -1,4 +1,8 @@ --- +# TODO: when we are ready to go to ansible 1.9+ support only, we can update to +# the gce task to use the disk_auto_delete parameter to avoid having to delete +# the disk as a separate step on termination + - name: Launch instance(s) hosts: localhost connection: local @@ -25,15 +29,17 @@ register: gce - name: Add new instances public IPs to oo_nodes_to_config - add_host: "hostname={{ item.name }} ansible_ssh_host={{ item.public_ip }} groupname=oo_nodes_to_config" + add_host: + hostname: "{{ item.name }}" + ansible_ssh_host: "{{ item.public_ip }}" + groupname: oo_nodes_to_config + gce_private_ip: "{{ item.private_ip }}" with_items: gce.instance_data - name: Wait for ssh wait_for: "port=22 host={{ item.public_ip }}" with_items: gce.instance_data - - debug: var=gce - - name: Wait for root user setup command: "ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o ConnectTimeout=10 -o UserKnownHostsFile=/dev/null root@{{ item.public_ip }} echo root user is setup" register: result @@ -45,13 +51,3 @@ # Apply the configs, separate so that just the configs can be run by themselves - include: config.yml - -# Always bounce service to pick up new credentials -#- name: "Restart instances" -# hosts: oo_nodes_to_config -# connection: ssh -# user: root -# tasks: -# - debug: var=groups.oo_nodes_to_config -# - name: Restart OpenShift -# service: name=openshift-node enabled=yes state=restarted diff --git a/playbooks/gce/openshift-node/terminate.yml b/playbooks/gce/openshift-node/terminate.yml index 9aa8a48c1..7d71dfcab 100644 --- a/playbooks/gce/openshift-node/terminate.yml +++ b/playbooks/gce/openshift-node/terminate.yml @@ -1,17 +1,13 @@ -- name: "populate oo_hosts_to_terminate host group if needed" +--- +- name: Populate oo_nodes_to_terminate host group if needed hosts: localhost gather_facts: no tasks: - - debug: var=oo_host_group_exp - - name: Evaluate oo_host_group_exp if it's set - add_host: "name={{ item }} groups=oo_hosts_to_terminate" + add_host: "name={{ item }} groups=oo_nodes_to_terminate" with_items: "{{ oo_host_group_exp | default('') }}" when: oo_host_group_exp is defined - - debug: msg="{{ groups['oo_hosts_to_terminate'] }}" - - - name: Terminate node instances hosts: localhost connection: local @@ -23,12 +19,10 @@ pem_file: "{{ gce_pem_file }}" project_id: "{{ gce_project_id }}" state: 'absent' - instance_names: "{{ groups['oo_hosts_to_terminate'] }}" - disks: "{{ groups['oo_hosts_to_terminate'] }}" + instance_names: "{{ groups['oo_nodes_to_terminate'] }}" + disks: "{{ groups['oo_nodes_to_terminate'] }}" register: gce - - debug: var=gce - - name: Remove disks of instances gce_pd: service_account_email: "{{ gce_service_account_email }}" diff --git a/playbooks/gce/openshift-node/vars.yml b/playbooks/gce/openshift-node/vars.yml index fb5f4ea42..c196b2fca 100644 --- a/playbooks/gce/openshift-node/vars.yml +++ b/playbooks/gce/openshift-node/vars.yml @@ -1,2 +1,3 @@ --- openshift_debug_level: 4 +openshift_cluster_id: "{{ cluster_id }}" diff --git a/roles/openshift_common/README.md b/roles/openshift_common/README.md index 880d66e2c..14c2037e4 100644 --- a/roles/openshift_common/README.md +++ b/roles/openshift_common/README.md @@ -12,17 +12,20 @@ rhel-7-server-extra-rpms, and rhel-7-server-ose-beta-rpms repos. Role Variables -------------- -| Name | Default value | | -|-------------------------------|------------------------------|----------------------------------------| -| openshift_debug_level | 0 | Global openshift debug log verbosity | -| openshift_hostname | UNDEF (Required) | hostname to use for this instance | -| openshift_public_ip | UNDEF (Required) | Public IP address to use for this host | -| openshift_env | default | Envrionment name if multiple OpenShift instances | +| Name | Default value | | +|---------------------------|-------------------|---------------------------------------------| +| openshift_cluster_id | default | Cluster name if multiple OpenShift clusters | +| openshift_debug_level | 0 | Global openshift debug log verbosity | +| openshift_hostname | UNDEF | Internal hostname to use for this host (this value will set the hostname on the system) | +| openshift_ip | UNDEF | Internal IP address to use for this host | +| openshift_public_hostname | UNDEF | Public hostname to use for this host | +| openshift_public_ip | UNDEF | Public IP address to use for this host | Dependencies ------------ os_firewall +openshift_facts openshift_repos Example Playbook @@ -38,4 +41,4 @@ Apache License, Version 2.0 Author Information ------------------ -TODO +Jason DeTiberus (jdetiber@redhat.com) diff --git a/roles/openshift_common/defaults/main.yml b/roles/openshift_common/defaults/main.yml index 22b2c6ffd..4d3e0fe9e 100644 --- a/roles/openshift_common/defaults/main.yml +++ b/roles/openshift_common/defaults/main.yml @@ -1,2 +1,3 @@ --- +openshift_cluster_id: 'default' openshift_debug_level: 0 diff --git a/roles/openshift_common/meta/main.yml b/roles/openshift_common/meta/main.yml index cee4dd337..81363ec68 100644 --- a/roles/openshift_common/meta/main.yml +++ b/roles/openshift_common/meta/main.yml @@ -13,4 +13,5 @@ galaxy_info: - cloud dependencies: - { role: os_firewall } +- { role: openshift_facts } - { role: openshift_repos } diff --git a/roles/openshift_common/tasks/main.yml b/roles/openshift_common/tasks/main.yml index 07737a71f..941190534 100644 --- a/roles/openshift_common/tasks/main.yml +++ b/roles/openshift_common/tasks/main.yml @@ -1,19 +1,16 @@ --- -- name: Set hostname - hostname: name={{ openshift_hostname }} +- name: Set common OpenShift facts + openshift_facts: + role: 'common' + local_facts: + cluster_id: "{{ openshift_cluster_id | default('default') }}" + debug_level: "{{ openshift_debug_level | default(0) }}" + hostname: "{{ openshift_hostname | default(None) }}" + ip: "{{ openshift_ip | default(None) }}" + public_hostname: "{{ openshift_public_hostname | default(None) }}" + public_ip: "{{ openshift_public_ip | default(None) }}" + use_openshift_sdn: "{{ openshift_use_openshift_sdn | default(None) }}" -- name: Configure local facts file - file: path=/etc/ansible/facts.d/ state=directory mode=0750 +- name: Set hostname + hostname: name={{ openshift.common.hostname }} -- name: Set common OpenShift facts - include: set_facts.yml - facts: - - section: common - option: env - value: "{{ openshift_env | default('default') }}" - - section: common - option: host_type - value: "{{ openshift_host_type }}" - - section: common - option: debug_level - value: "{{ openshift_debug_level }}" diff --git a/roles/openshift_common/tasks/set_facts.yml b/roles/openshift_common/tasks/set_facts.yml deleted file mode 100644 index 349eecd1d..000000000 --- a/roles/openshift_common/tasks/set_facts.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -- name: "Setting local_facts" - ini_file: - dest: /etc/ansible/facts.d/openshift.fact - mode: 0640 - section: "{{ item.section }}" - option: "{{ item.option }}" - value: "{{ item.value }}" - with_items: facts diff --git a/roles/openshift_common/vars/main.yml b/roles/openshift_common/vars/main.yml index 623aed9bf..50816d319 100644 --- a/roles/openshift_common/vars/main.yml +++ b/roles/openshift_common/vars/main.yml @@ -1,6 +1,7 @@ --- -openshift_master_credentials_dir: /var/lib/openshift/openshift.local.certificates/admin/ - # TODO: Upstream kubernetes only supports iptables currently, if this changes, # then these variable should be moved to defaults +# TODO: it might be possible to still use firewalld if we wire up the created +# chains with the public zone (or the zone associated with the correct +# interfaces) os_firewall_use_firewalld: False diff --git a/roles/openshift_facts/README.md b/roles/openshift_facts/README.md new file mode 100644 index 000000000..2fd50e236 --- /dev/null +++ b/roles/openshift_facts/README.md @@ -0,0 +1,34 @@ +OpenShift Facts +=============== + +Provides the openshift_facts module + +Requirements +------------ + +None + +Role Variables +-------------- + +None + +Dependencies +------------ + +None + +Example Playbook +---------------- + +TODO + +License +------- + +Apache License, Version 2.0 + +Author Information +------------------ + +Jason DeTiberus (jdetiber@redhat.com) diff --git a/roles/openshift_facts/library/openshift_facts.py b/roles/openshift_facts/library/openshift_facts.py new file mode 100755 index 000000000..0dd343443 --- /dev/null +++ b/roles/openshift_facts/library/openshift_facts.py @@ -0,0 +1,482 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# vim: expandtab:tabstop=4:shiftwidth=4 + +DOCUMENTATION = ''' +--- +module: openshift_facts +short_description: OpenShift Facts +author: Jason DeTiberus +requirements: [ ] +''' +EXAMPLES = ''' +''' + +import ConfigParser +import copy + +class OpenShiftFactsUnsupportedRoleError(Exception): + pass + +class OpenShiftFactsFileWriteError(Exception): + pass + +class OpenShiftFacts(): + known_roles = ['common', 'master', 'node', 'master_sdn', 'node_sdn'] + + def __init__(self, role, filename, local_facts): + self.changed = False + self.filename = filename + if role not in self.known_roles: + raise OpenShiftFactsUnsupportedRoleError("Role %s is not supported by this module" % role) + self.role = role + self.facts = self.generate_facts(local_facts) + + def generate_facts(self, local_facts): + local_facts = self.init_local_facts(local_facts) + roles = local_facts.keys() + + defaults = self.get_defaults(roles) + provider_facts = self.init_provider_facts() + facts = self.apply_provider_facts(defaults, provider_facts, roles) + + facts = self.merge_facts(facts, local_facts) + facts['current_config'] = self.current_config(facts) + self.set_url_facts_if_unset(facts) + return dict(openshift=facts) + + + def set_url_facts_if_unset(self, facts): + if 'master' in facts: + for (url_var, use_ssl, port, default) in [ + ('api_url', + facts['master']['api_use_ssl'], + facts['master']['api_port'], + facts['common']['hostname']), + ('public_api_url', + facts['master']['api_use_ssl'], + facts['master']['api_port'], + facts['common']['public_hostname']), + ('console_url', + facts['master']['console_use_ssl'], + facts['master']['console_port'], + facts['common']['hostname']), + ('public_console_url' 'console_use_ssl', + facts['master']['console_use_ssl'], + facts['master']['console_port'], + facts['common']['public_hostname'])]: + if url_var not in facts['master']: + scheme = 'https' if use_ssl else 'http' + netloc = default + if (scheme == 'https' and port != '443') or (scheme == 'http' and port != '80'): + netloc = "%s:%s" % (netloc, port) + facts['master'][url_var] = urlparse.urlunparse((scheme, netloc, '', '', '', '')) + + + # Query current OpenShift config and return a dictionary containing + # settings that may be valuable for determining actions that need to be + # taken in the playbooks/roles + def current_config(self, facts): + current_config=dict() + roles = [ role for role in facts if role not in ['common','provider'] ] + for role in roles: + if 'roles' in current_config: + current_config['roles'].append(role) + else: + current_config['roles'] = [role] + + # TODO: parse the /etc/sysconfig/openshift-{master,node} config to + # determine the location of files. + + # Query kubeconfig settings + kubeconfig_dir = '/var/lib/openshift/openshift.local.certificates' + if role == 'node': + kubeconfig_dir = os.path.join(kubeconfig_dir, "node-%s" % facts['common']['hostname']) + + kubeconfig_path = os.path.join(kubeconfig_dir, '.kubeconfig') + if os.path.isfile('/usr/bin/openshift') and os.path.isfile(kubeconfig_path): + try: + _, output, error = module.run_command(["/usr/bin/openshift", "ex", + "config", "view", "-o", + "json", + "--kubeconfig=%s" % kubeconfig_path], + check_rc=False) + config = json.loads(output) + + try: + for cluster in config['clusters']: + config['clusters'][cluster]['certificate-authority-data'] = 'masked' + except KeyError: + pass + try: + for user in config['users']: + config['users'][user]['client-certificate-data'] = 'masked' + config['users'][user]['client-key-data'] = 'masked' + except KeyError: + pass + + current_config['kubeconfig'] = config + except Exception: + pass + + return current_config + + + def apply_provider_facts(self, facts, provider_facts, roles): + if not provider_facts: + return facts + + use_openshift_sdn = provider_facts.get('use_openshift_sdn') + if isinstance(use_openshift_sdn, bool): + facts['common']['use_openshift_sdn'] = use_openshift_sdn + + common_vars = [('hostname', 'ip'), ('public_hostname', 'public_ip')] + for h_var, ip_var in common_vars: + ip_value = provider_facts['network'].get(ip_var) + if ip_value: + facts['common'][ip_var] = ip_value + + facts['common'][h_var] = self.choose_hostname([provider_facts['network'].get(h_var)], facts['common'][ip_var]) + + if 'node' in roles: + ext_id = provider_facts.get('external_id') + if ext_id: + facts['node']['external_id'] = ext_id + + facts['provider'] = provider_facts + return facts + + def hostname_valid(self, hostname): + if (not hostname or + hostname.startswith('localhost') or + hostname.endswith('localdomain') or + len(hostname.split('.')) < 2): + return False + + return True + + def choose_hostname(self, hostnames=[], fallback=''): + hostname = fallback + + ips = [ i for i in hostnames if i is not None and re.match(r'\A\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\Z', i) ] + hosts = [ i for i in hostnames if i is not None and i not in set(ips) ] + + for host_list in (hosts, ips): + for h in host_list: + if self.hostname_valid(h): + return h + + return hostname + + def get_defaults(self, roles): + hardware_facts = self.get_hardware_facts() + net_facts = self.get_net_facts() + base_facts = self.get_base_facts() + + defaults = dict() + + common = dict(use_openshift_sdn=True) + ip = net_facts['default_ipv4']['address'] + common['ip'] = ip + common['public_ip'] = ip + + rc, output, error = module.run_command(['hostname', '-f']) + hostname_f = output.strip() if rc == 0 else '' + hostname_values = [hostname_f, base_facts['nodename'], base_facts['fqdn']] + hostname = self.choose_hostname(hostname_values) + + common['hostname'] = hostname + common['public_hostname'] = hostname + defaults['common'] = common + + if 'master' in roles: + # TODO: provide for a better way to override just the port, or just + # the urls, instead of forcing both, also to override the hostname + # without having to re-generate these urls later + master = dict(api_use_ssl=True, api_port='8443', + console_use_ssl=True, console_path='/console', + console_port='8443', etcd_use_ssl=False, + etcd_port='4001') + defaults['master'] = master + + if 'node' in roles: + node = dict(external_id=common['hostname'], pod_cidr='', + labels={}, annotations={}) + node['resources_cpu'] = hardware_facts['processor_cores'] + node['resources_memory'] = int(int(hardware_facts['memtotal_mb']) * 1024 * 1024 * 0.75) + defaults['node'] = node + + return defaults + + def merge_facts(self, orig, new): + facts = dict() + for key, value in orig.iteritems(): + if key in new: + if isinstance(value, dict): + facts[key] = self.merge_facts(value, new[key]) + else: + facts[key] = copy.copy(new[key]) + else: + facts[key] = copy.deepcopy(value) + new_keys = set(new.keys()) - set(orig.keys()) + for key in new_keys: + facts[key] = copy.deepcopy(new[key]) + return facts + + def query_metadata(self, metadata_url, headers=None, expect_json=False): + r, info = fetch_url(module, metadata_url, headers=headers) + if info['status'] != 200: + module.fail_json(msg='Failed to query metadata', result=r, + info=info) + if expect_json: + return module.from_json(r.read()) + else: + return [line.strip() for line in r.readlines()] + + def walk_metadata(self, metadata_url, headers=None, expect_json=False): + metadata = dict() + + for line in self.query_metadata(metadata_url, headers, expect_json): + if line.endswith('/') and not line == 'public-keys/': + key = line[:-1] + metadata[key]=self.walk_metadata(metadata_url + line, headers, + expect_json) + else: + results = self.query_metadata(metadata_url + line, headers, + expect_json) + if len(results) == 1: + metadata[line] = results.pop() + else: + metadata[line] = results + return metadata + + def get_provider_metadata(self, metadata_url, supports_recursive=False, + headers=None, expect_json=False): + if supports_recursive: + metadata = self.query_metadata(metadata_url, headers, expect_json) + else: + metadata = self.walk_metadata(metadata_url, headers, expect_json) + return metadata + + def get_hardware_facts(self): + if not hasattr(self, 'hardware_facts'): + self.hardware_facts = Hardware().populate() + return self.hardware_facts + + def get_base_facts(self): + if not hasattr(self, 'base_facts'): + self.base_facts = Facts().populate() + return self.base_facts + + def get_virt_facts(self): + if not hasattr(self, 'virt_facts'): + self.virt_facts = Virtual().populate() + return self.virt_facts + + def get_net_facts(self): + if not hasattr(self, 'net_facts'): + self.net_facts = Network(module).populate() + return self.net_facts + + def guess_host_provider(self): + # TODO: cloud provider facts should probably be submitted upstream + virt_facts = self.get_virt_facts() + hardware_facts = self.get_hardware_facts() + product_name = hardware_facts['product_name'] + product_version = hardware_facts['product_version'] + virt_type = virt_facts['virtualization_type'] + virt_role = virt_facts['virtualization_role'] + provider = None + metadata = None + + # TODO: this is not exposed through module_utils/facts.py in ansible, + # need to create PR for ansible to expose it + bios_vendor = get_file_content('/sys/devices/virtual/dmi/id/bios_vendor') + if bios_vendor == 'Google': + provider = 'gce' + metadata_url = 'http://metadata.google.internal/computeMetadata/v1/?recursive=true' + headers = {'Metadata-Flavor': 'Google'} + metadata = self.get_provider_metadata(metadata_url, True, headers, + True) + + # Filter sshKeys and serviceAccounts from gce metadata + metadata['project']['attributes'].pop('sshKeys', None) + metadata['instance'].pop('serviceAccounts', None) + elif virt_type == 'xen' and virt_role == 'guest' and re.match(r'.*\.amazon$', product_version): + provider = 'ec2' + metadata_url = 'http://169.254.169.254/latest/meta-data/' + metadata = self.get_provider_metadata(metadata_url) + elif re.search(r'OpenStack', product_name): + provider = 'openstack' + metadata_url = 'http://169.254.169.254/openstack/latest/meta_data.json' + metadata = self.get_provider_metadata(metadata_url, True, None, True) + ec2_compat_url = 'http://169.254.169.254/latest/meta-data/' + metadata['ec2_compat'] = self.get_provider_metadata(ec2_compat_url) + + # Filter public_keys and random_seed from openstack metadata + metadata.pop('public_keys', None) + metadata.pop('random_seed', None) + return dict(name=provider, metadata=metadata) + + def normalize_provider_facts(self, provider, metadata): + if provider is None or metadata is None: + return {} + + # TODO: test for ipv6_enabled where possible (gce, aws do not support) + # and configure ipv6 facts if available + + # TODO: add support for setting user_data if available + + facts = dict(name=provider, metadata=metadata) + network = dict(interfaces=[], ipv6_enabled=False) + if provider == 'gce': + for interface in metadata['instance']['networkInterfaces']: + int_info = dict(ips=[interface['ip']], network_type=provider) + int_info['public_ips'] = [ ac['externalIp'] for ac in interface['accessConfigs'] ] + int_info['public_ips'].extend(interface['forwardedIps']) + _, _, network_id = interface['network'].rpartition('/') + int_info['network_id'] = network_id + network['interfaces'].append(int_info) + _, _, zone = metadata['instance']['zone'].rpartition('/') + facts['zone'] = zone + facts['external_id'] = metadata['instance']['id'] + + # Default to no sdn for GCE deployments + facts['use_openshift_sdn'] = False + + # GCE currently only supports a single interface + network['ip'] = network['interfaces'][0]['ips'][0] + network['public_ip'] = network['interfaces'][0]['public_ips'][0] + network['hostname'] = metadata['instance']['hostname'] + + # TODO: attempt to resolve public_hostname + network['public_hostname'] = network['public_ip'] + elif provider == 'ec2': + for interface in sorted(metadata['network']['interfaces']['macs'].values(), + key=lambda x: x['device-number']): + int_info = dict() + var_map = {'ips': 'local-ipv4s', 'public_ips': 'public-ipv4s'} + for ips_var, int_var in var_map.iteritems(): + ips = interface[int_var] + int_info[ips_var] = [ips] if isinstance(ips, basestring) else ips + int_info['network_type'] = 'vpc' if 'vpc-id' in interface else 'classic' + int_info['network_id'] = interface['subnet-id'] if int_info['network_type'] == 'vpc' else None + network['interfaces'].append(int_info) + facts['zone'] = metadata['placement']['availability-zone'] + facts['external_id'] = metadata['instance-id'] + + # TODO: actually attempt to determine default local and public ips + # by using the ansible default ip fact and the ipv4-associations + # form the ec2 metadata + network['ip'] = metadata['local-ipv4'] + network['public_ip'] = metadata['public-ipv4'] + + # TODO: verify that local hostname makes sense and is resolvable + network['hostname'] = metadata['local-hostname'] + + # TODO: verify that public hostname makes sense and is resolvable + network['public_hostname'] = metadata['public-hostname'] + elif provider == 'openstack': + # openstack ec2 compat api does not support network interfaces and + # the version tested on did not include the info in the openstack + # metadata api, should be updated if neutron exposes this. + + facts['zone'] = metadata['availability_zone'] + facts['external_id'] = metadata['uuid'] + network['ip'] = metadata['ec2_compat']['local-ipv4'] + network['public_ip'] = metadata['ec2_compat']['public-ipv4'] + + # TODO: verify local hostname makes sense and is resolvable + network['hostname'] = metadata['hostname'] + + # TODO: verify that public hostname makes sense and is resolvable + network['public_hostname'] = metadata['ec2_compat']['public-hostname'] + + facts['network'] = network + return facts + + def init_provider_facts(self): + provider_info = self.guess_host_provider() + provider_facts = self.normalize_provider_facts( + provider_info.get('name'), + provider_info.get('metadata') + ) + return provider_facts + + def get_facts(self): + # TODO: transform facts into cleaner format (openshift_ instead + # of openshift. + return self.facts + + def init_local_facts(self, facts={}): + changed = False + + local_facts = ConfigParser.SafeConfigParser() + local_facts.read(self.filename) + + section = self.role + if not local_facts.has_section(section): + local_facts.add_section(section) + changed = True + + for key, value in facts.iteritems(): + if isinstance(value, bool): + value = str(value) + if not value: + continue + if not local_facts.has_option(section, key) or local_facts.get(section, key) != value: + local_facts.set(section, key, value) + changed = True + + if changed and not module.check_mode: + try: + fact_dir = os.path.dirname(self.filename) + if not os.path.exists(fact_dir): + os.makedirs(fact_dir) + with open(self.filename, 'w') as fact_file: + local_facts.write(fact_file) + except (IOError, OSError) as e: + raise OpenShiftFactsFileWriteError("Could not create fact file: %s, error: %s" % (self.filename, e)) + self.changed = changed + + role_facts = dict() + for section in local_facts.sections(): + role_facts[section] = dict() + for opt, val in local_facts.items(section): + role_facts[section][opt] = val + return role_facts + + +def main(): + global module + module = AnsibleModule( + argument_spec = dict( + role=dict(default='common', + choices=OpenShiftFacts.known_roles, + required=False), + local_facts=dict(default={}, type='dict', required=False), + ), + supports_check_mode=True, + add_file_common_args=True, + ) + + role = module.params['role'] + local_facts = module.params['local_facts'] + fact_file = '/etc/ansible/facts.d/openshift.fact' + + openshift_facts = OpenShiftFacts(role, fact_file, local_facts) + + file_params = module.params.copy() + file_params['path'] = fact_file + file_args = module.load_file_common_arguments(file_params) + changed = module.set_fs_attributes_if_different(file_args, + openshift_facts.changed) + + return module.exit_json(changed=changed, + ansible_facts=openshift_facts.get_facts()) + +# import module snippets +from ansible.module_utils.basic import * +from ansible.module_utils.facts import * +from ansible.module_utils.urls import * +main() diff --git a/roles/openshift_facts/meta/main.yml b/roles/openshift_facts/meta/main.yml new file mode 100644 index 000000000..0be3afd24 --- /dev/null +++ b/roles/openshift_facts/meta/main.yml @@ -0,0 +1,15 @@ +--- +galaxy_info: + author: Jason DeTiberus + description: + company: Red Hat, Inc. + license: Apache License, Version 2.0 + min_ansible_version: 1.8 + platforms: + - name: EL + versions: + - 7 + categories: + - cloud + - system +dependencies: [] diff --git a/roles/openshift_facts/tasks/main.yml b/roles/openshift_facts/tasks/main.yml new file mode 100644 index 000000000..5a7d10d25 --- /dev/null +++ b/roles/openshift_facts/tasks/main.yml @@ -0,0 +1,3 @@ +--- +- name: Gather OpenShift facts + openshift_facts: diff --git a/roles/openshift_master/README.md b/roles/openshift_master/README.md index 2d898bc3b..9f9d0a613 100644 --- a/roles/openshift_master/README.md +++ b/roles/openshift_master/README.md @@ -13,20 +13,24 @@ Role Variables -------------- From this role: -| Name | Default value | -| -|------------------------------------------|-----------------------|----------------------------------------| -| openshift_master_manage_service_externally | False | Should the openshift-master role manage the openshift-master service? | -| openshift_master_debug_level | openshift_debug_level | Verbosity of the debug logs for openshift-master | -| openshift_node_ips | [] | List of the openshift node ip addresses, that we want to pre-register to the system when openshift-master starts up | -| openshift_registry_url | UNDEF (Optional) | Default docker registry to use | +| Name | Default value | | +|-------------------------------------|-----------------------|--------------------------------------------------| +| openshift_master_debug_level | openshift_debug_level | Verbosity of the debug logs for openshift-master | +| openshift_node_ips | [] | List of the openshift node ip addresses to pre-register when openshift-master starts up | +| openshift_registry_url | UNDEF | Default docker registry to use | +| openshift_master_api_port | UNDEF | | +| openshift_master_console_port | UNDEF | | +| openshift_master_api_url | UNDEF | | +| openshift_master_console_url | UNDEF | | +| openshift_master_public_api_url | UNDEF | | +| openshift_master_public_console_url | UNDEF | | From openshift_common: -| Name | Default Value | | -|-------------------------------|---------------------|---------------------| -| openshift_debug_level | 0 | Global openshift debug log verbosity | -| openshift_public_ip | UNDEF (Required) | Public IP address to use for this host | -| openshift_hostname | UNDEF (Required) | hostname to use for this instance | +| Name | Default Value | | +|-------------------------------|----------------|----------------------------------------| +| openshift_debug_level | 0 | Global openshift debug log verbosity | +| openshift_public_ip | UNDEF | Public IP address to use for this host | +| openshift_hostname | UNDEF | hostname to use for this instance | Dependencies ------------ diff --git a/roles/openshift_master/defaults/main.yml b/roles/openshift_master/defaults/main.yml index 0159afbb5..87fb347a8 100644 --- a/roles/openshift_master/defaults/main.yml +++ b/roles/openshift_master/defaults/main.yml @@ -1,16 +1,17 @@ --- -openshift_master_manage_service_externally: false -openshift_master_debug_level: "{{ openshift_debug_level | default(0) }}" openshift_node_ips: [] + +# TODO: update setting these values based on the facts +# TODO: update for console port change os_firewall_allow: - service: etcd embedded port: 4001/tcp -- service: etcd peer - port: 7001/tcp - service: OpenShift api https port: 8443/tcp -- service: OpenShift web console https - port: 8444/tcp os_firewall_deny: - service: OpenShift api http port: 8080/tcp +- service: former OpenShift web console port + port: 8444/tcp +- service: former etcd peer port + port: 7001/tcp diff --git a/roles/openshift_master/handlers/main.yml b/roles/openshift_master/handlers/main.yml index 503d08d41..6fd4dfb51 100644 --- a/roles/openshift_master/handlers/main.yml +++ b/roles/openshift_master/handlers/main.yml @@ -1,4 +1,3 @@ --- - name: restart openshift-master service: name=openshift-master state=restarted - when: not openshift_master_manage_service_externally diff --git a/roles/openshift_master/tasks/main.yml b/roles/openshift_master/tasks/main.yml index 52f5f694c..aa615df39 100644 --- a/roles/openshift_master/tasks/main.yml +++ b/roles/openshift_master/tasks/main.yml @@ -1,19 +1,37 @@ --- -# TODO: allow for overriding default ports where possible -# TODO: if setting up multiple masters, will need to predistribute the certs -# to the additional masters before starting openshift-master +# TODO: actually have api_port, api_use_ssl, console_port, console_use_ssl, +# etcd_use_ssl actually change the master config. + +- name: Set master OpenShift facts + openshift_facts: + role: 'master' + local_facts: + debug_level: "{{ openshift_master_debug_level | default(openshift.common.debug_level) }}" + api_port: "{{ openshift_master_api_port | default(None) }}" + api_url: "{{ openshift_master_api_url | default(None) }}" + api_use_ssl: "{{ openshift_master_api_use_ssl | default(None) }}" + public_api_url: "{{ openshift_master_public_api_url | default(None) }}" + console_port: "{{ openshift_master_console_port | default(None) }}" + console_url: "{{ openshift_master_console_url | default(None) }}" + console_use_ssl: "{{ openshift_master_console_use_ssl | default(None) }}" + public_console_url: "{{ openshift_master_public_console_url | default(None) }}" + etcd_use_ssl: "{{ openshift_master_etcd_use_ssl | default(None) }}" - name: Install OpenShift Master package yum: pkg=openshift-master state=installed +# TODO: We should pre-generate the master config and point to the generated +# config rather than setting command line flags here - name: Configure OpenShift settings lineinfile: dest: /etc/sysconfig/openshift-master regexp: '^OPTIONS=' - line: "OPTIONS=\"--public-master={{ openshift_hostname }} {% if openshift_node_ips %} --nodes={{ openshift_node_ips | join(',') }} {% endif %} --loglevel={{ openshift_master_debug_level }}\"" + line: "OPTIONS=\"--master={{ openshift.common.hostname }} --public-master={{ openshift.common.public_hostname }} {% if openshift_node_ips %} --nodes={{ openshift_node_ips | join(',') }} {% endif %} --loglevel={{ openshift.master.debug_level }}\"" notify: - restart openshift-master +# TODO: should this be populated by a fact based on the deployment type +# (origin, online, enterprise)? - name: Set default registry url lineinfile: dest: /etc/sysconfig/openshift-master @@ -23,34 +41,18 @@ notify: - restart openshift-master -- name: Set master OpenShift facts - include: "{{ role_path | dirname }}/openshift_common/tasks/set_facts.yml" - facts: - - section: master - option: debug_level - value: "{{ openshift_master_debug_level }}" - - section: master - option: public_ip - value: "{{ openshift_public_ip }}" - - section: master - option: externally_managed - value: "{{ openshift_master_manage_service_externally }}" - - name: Start and enable openshift-master service: name=openshift-master enabled=yes state=started - when: not openshift_master_manage_service_externally - register: result - -- name: Disable openshift-master if openshift-master is managed externally - service: name=openshift-master enabled=false - when: openshift_master_manage_service_externally - name: Create .kube directory file: path: /root/.kube state: directory mode: 0700 + +# TODO: Update this file if the contents of the source file are not present in +# the dest file, will need to make sure to ignore things that could be added - name: Configure root user kubeconfig - command: cp /var/lib/openshift/openshift.local.certificates/admin/.kubeconfig /root/.kube/.kubeconfig + command: cp /var/lib/openshift/openshift.local.certificates/openshift-client/.kubeconfig /root/.kube/.kubeconfig args: creates: /root/.kube/.kubeconfig diff --git a/roles/openshift_master/vars/main.yml b/roles/openshift_master/vars/main.yml deleted file mode 100644 index 9a8c4bba2..000000000 --- a/roles/openshift_master/vars/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -openshift_host_type: master diff --git a/roles/openshift_node/README.md b/roles/openshift_node/README.md index c9b4eab34..83359f164 100644 --- a/roles/openshift_node/README.md +++ b/roles/openshift_node/README.md @@ -16,10 +16,7 @@ Role Variables From this role: | Name | Default value | | |------------------------------------------|-----------------------|----------------------------------------| -| openshift_node_manage_service_externally | False | Should the openshift-node role manage the openshift-node service? | | openshift_node_debug_level | openshift_debug_level | Verbosity of the debug logs for openshift-node | -| openshift_master_public_ips | UNDEF (Required) | List of the public IPs for the openhift-master hosts | -| openshift_master_ips | UNDEF (Required) | List of IP addresses for the openshift-master hosts to be used for node -> master communication | | openshift_registry_url | UNDEF (Optional) | Default docker registry to use | From openshift_common: diff --git a/roles/openshift_node/defaults/main.yml b/roles/openshift_node/defaults/main.yml index 6dc73a96e..df7ec41b6 100644 --- a/roles/openshift_node/defaults/main.yml +++ b/roles/openshift_node/defaults/main.yml @@ -1,6 +1,4 @@ --- -openshift_node_manage_service_externally: false -openshift_node_debug_level: "{{ openshift_debug_level | default(0) }}" os_firewall_allow: - service: OpenShift kubelet port: 10250/tcp diff --git a/roles/openshift_node/handlers/main.yml b/roles/openshift_node/handlers/main.yml index f7aa36d88..ca2992637 100644 --- a/roles/openshift_node/handlers/main.yml +++ b/roles/openshift_node/handlers/main.yml @@ -1,4 +1,4 @@ --- - name: restart openshift-node service: name=openshift-node state=restarted - when: not openshift_node_manage_service_externally + when: not openshift.common.use_openshift_sdn|bool diff --git a/roles/openshift_node/tasks/main.yml b/roles/openshift_node/tasks/main.yml index c039e3f05..8cfef0e15 100644 --- a/roles/openshift_node/tasks/main.yml +++ b/roles/openshift_node/tasks/main.yml @@ -1,4 +1,12 @@ --- +# TODO: allow for overriding default ports where possible +# TODO: trigger the external service when restart is needed +- name: Set node OpenShift facts + openshift_facts: + role: 'node' + local_facts: + debug_level: "{{ openshift_node_debug_level | default(openshift.common.debug_level) }}" + - name: Test if node certs and config exist stat: path={{ item }} failed_when: not result.stat.exists @@ -23,7 +31,7 @@ lineinfile: dest: /etc/sysconfig/openshift-node regexp: '^OPTIONS=' - line: "OPTIONS=\"--hostname={{ openshift_hostname }} --loglevel={{ openshift_node_debug_level }} --create-certs=false\"" + line: "OPTIONS=\"--hostname={{ openshift.common.hostname }} --loglevel={{ openshift.node.debug_level }} --create-certs=false\"" notify: - restart openshift-node @@ -36,23 +44,10 @@ notify: - restart openshift-node -- name: Set OpenShift node facts - include: "{{ role_path | dirname }}/openshift_common/tasks/set_facts.yml" - facts: - - section: node - option: debug_level - value: "{{ openshift_node_debug_level }}" - - section: node - option: public_ip - value: "{{ openshift_public_ip }}" - - section: node - option: externally_managed - value: "{{ openshift_node_manage_service_externally }}" - - name: Start and enable openshift-node service: name=openshift-node enabled=yes state=started - when: not openshift_node_manage_service_externally + when: not openshift.common.use_openshift_sdn|bool - name: Disable openshift-node if openshift-node is managed externally service: name=openshift-node enabled=false - when: openshift_node_manage_service_externally + when: openshift.common.use_openshift_sdn|bool diff --git a/roles/openshift_node/vars/main.yml b/roles/openshift_node/vars/main.yml deleted file mode 100644 index 9841d52f9..000000000 --- a/roles/openshift_node/vars/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -openshift_host_type: node diff --git a/roles/openshift_register_nodes/README.md b/roles/openshift_register_nodes/README.md index 225dd44b9..b96faa044 100644 --- a/roles/openshift_register_nodes/README.md +++ b/roles/openshift_register_nodes/README.md @@ -1,38 +1,34 @@ -Role Name -========= +OpenShift Register Nodes +======================== -A brief description of the role goes here. +TODO Requirements ------------ -Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. +TODO Role Variables -------------- -A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. +TODO Dependencies ------------ -A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. +TODO Example Playbook ---------------- -Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: - - - hosts: servers - roles: - - { role: username.rolename, x: 42 } +TODO License ------- -BSD +Apache License Version 2.0 Author Information ------------------ -An optional section for the role authors to include contact information, or a website (HTML is not allowed). +Jason DeTiberus (jdetiber@redhat.com) diff --git a/roles/openshift_register_nodes/library/kubernetes_register_node.py b/roles/openshift_register_nodes/library/kubernetes_register_node.py old mode 100644 new mode 100755 index 409215616..8ebeb087a --- a/roles/openshift_register_nodes/library/kubernetes_register_node.py +++ b/roles/openshift_register_nodes/library/kubernetes_register_node.py @@ -214,7 +214,8 @@ class Node: resources = NodeResources(version, cpu, memory), cidr = podCIDR, labels = labels, - annotations = annotations + annotations = annotations, + externalID = externalID ) elif version == 'v1beta3': metadata = dict(name = name, diff --git a/roles/openshift_register_nodes/meta/main.yml b/roles/openshift_register_nodes/meta/main.yml index 7b1f0ef0a..e40a152c1 100644 --- a/roles/openshift_register_nodes/meta/main.yml +++ b/roles/openshift_register_nodes/meta/main.yml @@ -1,128 +1,17 @@ --- galaxy_info: - author: your name - description: - company: your company (optional) - # Some suggested licenses: - # - BSD (default) - # - MIT - # - GPLv2 - # - GPLv3 - # - Apache - # - CC-BY - license: license (GPLv2, CC-BY, etc) - min_ansible_version: 1.2 - # - # Below are all platforms currently available. Just uncomment - # the ones that apply to your role. If you don't see your - # platform on this list, let us know and we'll get it added! - # - #platforms: - #- name: EL - # versions: - # - all - # - 5 - # - 6 - # - 7 - #- name: GenericUNIX - # versions: - # - all - # - any - #- name: Fedora - # versions: - # - all - # - 16 - # - 17 - # - 18 - # - 19 - # - 20 - #- name: SmartOS - # versions: - # - all - # - any - #- name: opensuse - # versions: - # - all - # - 12.1 - # - 12.2 - # - 12.3 - # - 13.1 - # - 13.2 - #- name: Amazon - # versions: - # - all - # - 2013.03 - # - 2013.09 - #- name: GenericBSD - # versions: - # - all - # - any - #- name: FreeBSD - # versions: - # - all - # - 8.0 - # - 8.1 - # - 8.2 - # - 8.3 - # - 8.4 - # - 9.0 - # - 9.1 - # - 9.1 - # - 9.2 - #- name: Ubuntu - # versions: - # - all - # - lucid - # - maverick - # - natty - # - oneiric - # - precise - # - quantal - # - raring - # - saucy - # - trusty - #- name: SLES - # versions: - # - all - # - 10SP3 - # - 10SP4 - # - 11 - # - 11SP1 - # - 11SP2 - # - 11SP3 - #- name: GenericLinux - # versions: - # - all - # - any - #- name: Debian - # versions: - # - all - # - etch - # - lenny - # - squeeze - # - wheezy - # - # Below are all categories currently available. Just as with - # the platforms above, uncomment those that apply to your role. - # - #categories: - #- cloud - #- cloud:ec2 - #- cloud:gce - #- cloud:rax - #- clustering - #- database - #- database:nosql - #- database:sql - #- development - #- monitoring - #- networking - #- packaging - #- system - #- web -dependencies: [] - # List your role dependencies here, one per line. Only - # dependencies available via galaxy should be listed here. - # Be sure to remove the '[]' above if you add dependencies - # to this list. - + author: Jason DeTiberus + description: + company: Red Hat, Inc. + license: Apache License, Version 2.0 + min_ansible_version: 1.8 + platforms: + - name: EL + versions: + - 7 + categories: + - cloud + - system +dependencies: +- { role: openshift_facts } + diff --git a/roles/openshift_register_nodes/tasks/main.yml b/roles/openshift_register_nodes/tasks/main.yml index 59216fc87..7319b88b1 100644 --- a/roles/openshift_register_nodes/tasks/main.yml +++ b/roles/openshift_register_nodes/tasks/main.yml @@ -1,18 +1,20 @@ --- -# TODO: support configuration for multiple masters, currently hardcoding -# the info from the first master +# TODO: support new create-config command to generate node certs and config +# TODO: recreate master/node configs if settings that affect the configs +# change (hostname, public_hostname, ip, public_ip, etc) # TODO: create a failed_when condition - name: Create node server certificates command: > /usr/bin/openshift admin create-server-cert --overwrite=false - --cert={{ openshift_cert_dir }}/node-{{ item.openshift_node_hostname }}/server.crt - --key={{ openshift_cert_dir }}/node-{{ item.openshift_node_hostname }}/server.key - --hostnames={{ [openshift_hostname, openshift_public_hostname, openshift_ip, openshift_public_ip]|join(",") }} + --cert={{ openshift_cert_dir }}/node-{{ item.openshift.common.hostname }}/server.crt + --key={{ openshift_cert_dir }}/node-{{ item.openshift.common.hostname }}/server.key + --hostnames={{ [item.openshift.common.hostname, + item.openshift.common.public_hostname]|unique|join(",") }} args: chdir: "{{ openshift_cert_dir_parent }}" - creates: "{{ openshift_cert_dir_abs }}/node-{{ item.openshift_node_hostname }}/server.crt" + creates: "{{ openshift_cert_dir_abs }}/node-{{ item.openshift.common.hostname }}/server.crt" with_items: openshift_nodes register: server_cert_result @@ -21,48 +23,42 @@ command: > /usr/bin/openshift admin create-node-cert --overwrite=false - --cert={{ openshift_cert_dir }}/node-{{ item.openshift_node_hostname }}/cert.crt - --key={{ openshift_cert_dir }}/node-{{ item.openshift_node_hostname }}/key.key - --node-name={{ item.openshift_node_hostname }} + --cert={{ openshift_cert_dir }}/node-{{ item.openshift.common.hostname }}/cert.crt + --key={{ openshift_cert_dir }}/node-{{ item.openshift.common.hostname }}/key.key + --node-name={{ item.openshift.common.hostname }} args: chdir: "{{ openshift_cert_dir_parent }}" - creates: "{{ openshift_cert_dir_abs }}/node-{{ item.openshift_node_hostname }}/cert.crt" + creates: "{{ openshift_cert_dir_abs }}/node-{{ item.openshift.common.hostname }}/cert.crt" with_items: openshift_nodes register: node_cert_result -# TODO: re-create kubeconfig if certs were regenerated, not just if -# .kubeconfig doesn't exist # TODO: create a failed_when condition - name: Create kubeconfigs for nodes command: > /usr/bin/openshift admin create-kubeconfig - --client-certificate={{ openshift_cert_dir }}/node-{{ item.openshift_node_hostname }}/cert.crt - --client-key={{ openshift_cert_dir }}/node-{{ item.openshift_node_hostname }}/key.key - --kubeconfig={{ openshift_cert_dir }}/node-{{ item.openshift_node_hostname }}/.kubeconfig - --master={{ openshift_master_urls[0] }} - --public-master={{ openshift_master_public_urls[0] }} + --client-certificate={{ openshift_cert_dir }}/node-{{ item.openshift.common.hostname }}/cert.crt + --client-key={{ openshift_cert_dir }}/node-{{ item.openshift.common.hostname }}/key.key + --kubeconfig={{ openshift_cert_dir }}/node-{{ item.openshift.common.hostname }}/.kubeconfig + --master={{ openshift.master.api_url }} + --public-master={{ openshift.master.public_api_url }} args: chdir: "{{ openshift_cert_dir_parent }}" - creates: "{{ openshift_cert_dir_abs }}/node-{{ item.openshift_node_hostname }}/.kubeconfig" + creates: "{{ openshift_cert_dir_abs }}/node-{{ item.openshift.common.hostname }}/.kubeconfig" with_items: openshift_nodes register: kubeconfig_result -# TODO: generate the node configs (openshift start node --write-config -# --config='{{ openshift_cert_dir }}/node-{{ item.openshift_node_hostname }}/node.yaml' -# --kubeconfig='{{ openshift_cert_dir }}/node-{{ item.openshift_node_hostname }}/.kubeconfig' -# will need to modify the generated node config as needed -# (servingInfo.{certFile,clientCA,keyFile}) - - name: Register unregistered nodes kubernetes_register_node: - name: "{{ item.openshift_node_name }}" + client_user: openshift-client + name: "{{ item.openshift.common.hostname }}" api_version: "{{ openshift_kube_api_version }}" - cpu: "{{ item.openshift_node_cpu if item.openshift_node_cpu else None }}" - memory: "{{ item.openshift_node_memory if item.openshift_node_memory else None }}" - pod_cidr: "{{ item.openshift_node_pod_cidr if item.openshift_node_pod_cidr else None }}" - host_ip: "{{ item.openshift_node_host_ip }}" - labels: "{{ item.openshift_node_labels if item.openshift_node_labels else {} }}" - annotations: "{{ item.openshift_node_annotations if item.openshift_node_annotations else {} }}" + cpu: "{{ item.openshift.node.resources_cpu | default(None) }}" + memory: "{{ item.openshift.node.resources_memory | default(None) }}" + pod_cidr: "{{ item.openshift.node.pod_cidr | default(None) }}" + host_ip: "{{ item.openshift.common.ip }}" + labels: "{{ item.openshift.node.labels | default({}) }}" + annotations: "{{ item.openshift.node.annotations | default({}) }}" + external_id: "{{ item.openshift.node.external_id }}" # TODO: support customizing other attributes such as: client_config, # client_cluster, client_context, client_user # TODO: update for v1beta3 changes after rebase: hostnames, external_ips, diff --git a/roles/openshift_repos/defaults/main.yaml b/roles/openshift_repos/defaults/main.yaml index 6fe2bf621..1730207f4 100644 --- a/roles/openshift_repos/defaults/main.yaml +++ b/roles/openshift_repos/defaults/main.yaml @@ -1,5 +1,7 @@ --- # TODO: once we are able to configure/deploy origin using the openshift roles, # then we should default to origin + +# TODO: push the defaulting of these values to the openshift_facts module openshift_deployment_type: online openshift_additional_repos: {} diff --git a/roles/openshift_repos/meta/main.yml b/roles/openshift_repos/meta/main.yml index cc18c453c..0558b822c 100644 --- a/roles/openshift_repos/meta/main.yml +++ b/roles/openshift_repos/meta/main.yml @@ -11,4 +11,5 @@ galaxy_info: - 7 categories: - cloud -dependencies: [] +dependencies: +- { role: openshift_facts } diff --git a/roles/openshift_repos/tasks/main.yaml b/roles/openshift_repos/tasks/main.yaml index 6219c4906..bb1551d37 100644 --- a/roles/openshift_repos/tasks/main.yaml +++ b/roles/openshift_repos/tasks/main.yaml @@ -1,6 +1,12 @@ --- # TODO: Add flag for enabling EPEL repo, default to false +# TODO: Add subscription-management config, with parameters +# for username, password, poolid(name), and official repos to +# enable/disable. Might need to make a module that extends the +# subscription management module to take a poolid and enable/disable the +# proper repos correctly. + - assert: that: openshift_deployment_type in known_openshift_deployment_types diff --git a/roles/openshift_sdn_master/defaults/main.yml b/roles/openshift_sdn_master/defaults/main.yml deleted file mode 100644 index da7655546..000000000 --- a/roles/openshift_sdn_master/defaults/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -openshift_sdn_master_debug_level: "{{ openshift_debug_level | default(0) }}" diff --git a/roles/openshift_sdn_master/meta/main.yml b/roles/openshift_sdn_master/meta/main.yml index e6e5514d1..5de32cc13 100644 --- a/roles/openshift_sdn_master/meta/main.yml +++ b/roles/openshift_sdn_master/meta/main.yml @@ -11,4 +11,5 @@ galaxy_info: - 7 categories: - cloud -dependencies: [] +dependencies: +- { role: openshift_common } diff --git a/roles/openshift_sdn_master/tasks/main.yml b/roles/openshift_sdn_master/tasks/main.yml index e1761afdc..f2d61043b 100644 --- a/roles/openshift_sdn_master/tasks/main.yml +++ b/roles/openshift_sdn_master/tasks/main.yml @@ -1,4 +1,13 @@ --- +# TODO: add task to set the sdn subnet if openshift-sdn-master hasn't been +# started yet + +- name: Set master sdn OpenShift facts + openshift_facts: + role: 'master_sdn' + local_facts: + debug_level: "{{ openshift_master_sdn_debug_level | default(openshift.common.debug_level) }}" + - name: Install openshift-sdn-master yum: pkg: openshift-sdn-master @@ -8,17 +17,10 @@ lineinfile: dest: /etc/sysconfig/openshift-sdn-master regexp: '^OPTIONS=' - line: "OPTIONS=\"-v={{ openshift_sdn_master_debug_level }}\"" + line: "OPTIONS=\"-v={{ openshift.master_sdn.debug_level }}\"" notify: - restart openshift-sdn-master -- name: Set openshift-sdn-master facts - include: "{{ role_path | dirname }}/openshift_common/tasks/set_facts.yml" - facts: - - section: sdn-master - option: debug_level - value: "{{ openshift_sdn_master_debug_level }}" - - name: Enable openshift-sdn-master service: name: openshift-sdn-master diff --git a/roles/openshift_sdn_node/README.md b/roles/openshift_sdn_node/README.md index 2da2d74eb..e6b6a9503 100644 --- a/roles/openshift_sdn_node/README.md +++ b/roles/openshift_sdn_node/README.md @@ -17,12 +17,6 @@ From this role: | openshift_sdn_node_debug_level | openshift_debug_level | Verbosity of the debug logs for openshift-master | -From openshift_node: -| Name | Default value | | -|-----------------------|------------------|--------------------------------------| -| openshift_master_ips | UNDEF (Required) | List of IP addresses for the openshift-master hosts to be used for node -> master communication | - - From openshift_common: | Name | Default value | | |-------------------------------|---------------------|----------------------------------------| diff --git a/roles/openshift_sdn_node/defaults/main.yml b/roles/openshift_sdn_node/defaults/main.yml deleted file mode 100644 index 9612d9d91..000000000 --- a/roles/openshift_sdn_node/defaults/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -openshift_sdn_node_debug_level: "{{ openshift_debug_level | default(0) }}" diff --git a/roles/openshift_sdn_node/meta/main.yml b/roles/openshift_sdn_node/meta/main.yml index ab45ff51e..ffe10f836 100644 --- a/roles/openshift_sdn_node/meta/main.yml +++ b/roles/openshift_sdn_node/meta/main.yml @@ -11,4 +11,5 @@ galaxy_info: - 7 categories: - cloud -dependencies: [] +dependencies: +- { role: openshift_common } diff --git a/roles/openshift_sdn_node/tasks/main.yml b/roles/openshift_sdn_node/tasks/main.yml index ff05a6972..729c28879 100644 --- a/roles/openshift_sdn_node/tasks/main.yml +++ b/roles/openshift_sdn_node/tasks/main.yml @@ -1,4 +1,10 @@ --- +- name: Set node sdn OpenShift facts + openshift_facts: + role: 'node_sdn' + local_facts: + debug_level: "{{ openshift_node_sdn_debug_level | default(openshift.common.debug_level) }}" + - name: Install openshift-sdn-node yum: pkg: openshift-sdn-node @@ -14,28 +20,19 @@ backrefs: yes with_items: - regex: '^(OPTIONS=)' - line: '\1"-v={{ openshift_sdn_node_debug_level }} -hostname={{ openshift_hostname }}"' + line: '\1"-v={{ openshift.node_sdn.debug_level }} -hostname={{ openshift.common.hostname }}"' - regex: '^(MASTER_URL=)' - line: '\1"http://{{ openshift_master_ips | first }}:4001"' + line: '\1"{{ openshift_sdn_master_url }}"' - regex: '^(MINION_IP=)' - line: '\1"{{ openshift_public_ip }}"' + line: '\1"{{ openshift.common.ip }}"' # TODO lock down the insecure-registry config to a more sane value than # 0.0.0.0/0 - regex: '^(DOCKER_OPTIONS=)' line: '\1"--insecure-registry=0.0.0.0/0 -b=lbr0 --mtu=1450 --selinux-enabled"' notify: restart openshift-sdn-node -- name: Set openshift-sdn-node facts - include: "{{ role_path | dirname }}/openshift_common/tasks/set_facts.yml" - facts: - - section: sdn-node - option: debug_level - value: "{{ openshift_sdn_node_debug_level }}" - -# fixme: Once the openshift_cluster playbook is published state should be started -# Always bounce service to pick up new credentials - name: Start and enable openshift-sdn-node service: name: openshift-sdn-node enabled: yes - state: restarted + state: started diff --git a/roles/os_env_extras_node/tasks/main.yml b/roles/os_env_extras_node/tasks/main.yml new file mode 100644 index 000000000..208065df2 --- /dev/null +++ b/roles/os_env_extras_node/tasks/main.yml @@ -0,0 +1,5 @@ +--- +# From the origin rpm there exists instructions on how to +# setup origin properly. The following steps come from there +- name: Change root to be in the Docker group + user: name=root groups=dockerroot append=yes diff --git a/roles/os_firewall/library/os_firewall_manage_iptables.py b/roles/os_firewall/library/os_firewall_manage_iptables.py old mode 100644 new mode 100755 index 6a018d022..90588d2ae --- a/roles/os_firewall/library/os_firewall_manage_iptables.py +++ b/roles/os_firewall/library/os_firewall_manage_iptables.py @@ -1,5 +1,6 @@ #!/usr/bin/python # -*- coding: utf-8 -*- +# vim: expandtab:tabstop=4:shiftwidth=4 from subprocess import call, check_output diff --git a/roles/os_firewall/meta/main.yml b/roles/os_firewall/meta/main.yml index 7a8cef6c5..8592371e8 100644 --- a/roles/os_firewall/meta/main.yml +++ b/roles/os_firewall/meta/main.yml @@ -1,3 +1,4 @@ +--- galaxy_info: author: Jason DeTiberus description: os_firewall diff --git a/roles/os_firewall/tasks/firewall/firewalld.yml b/roles/os_firewall/tasks/firewall/firewalld.yml index 469cfab6f..b6bddd5c5 100644 --- a/roles/os_firewall/tasks/firewall/firewalld.yml +++ b/roles/os_firewall/tasks/firewall/firewalld.yml @@ -3,6 +3,7 @@ yum: name: firewalld state: present + register: install_result - name: Check if iptables-services is installed command: rpm -q iptables-services @@ -20,6 +21,10 @@ - ip6tables when: pkg_check.rc == 0 +- name: Reload systemd units + command: systemctl daemon-reload + when: install_result | changed + - name: Start and enable firewalld service service: name: firewalld diff --git a/roles/os_firewall/tasks/firewall/iptables.yml b/roles/os_firewall/tasks/firewall/iptables.yml index 87e77c083..7b5c00a9b 100644 --- a/roles/os_firewall/tasks/firewall/iptables.yml +++ b/roles/os_firewall/tasks/firewall/iptables.yml @@ -6,6 +6,7 @@ with_items: - iptables - iptables-services + register: install_result - name: Check if firewalld is installed command: rpm -q firewalld @@ -20,14 +21,15 @@ enabled: no when: pkg_check.rc == 0 -- name: Start and enable iptables services +- name: Reload systemd units + command: systemctl daemon-reload + when: install_result | changed + +- name: Start and enable iptables service service: - name: "{{ item }}" + name: iptables state: started enabled: yes - with_items: - - iptables - - ip6tables register: result - name: need to pause here, otherwise the iptables service starting can sometimes cause ssh to fail -- cgit v1.2.3 From 185261ab927c6997c1bc3eefe2ab4cd804b8a7f0 Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Tue, 7 Apr 2015 16:51:40 -0400 Subject: fixed the opssh default output behavior to be consistent with pssh. Also fixed a bug in how directories are named for --outdir and --errdir. --- bin/opssh | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'bin') diff --git a/bin/opssh b/bin/opssh index d8137fb20..ad1aadc29 100755 --- a/bin/opssh +++ b/bin/opssh @@ -57,13 +57,16 @@ class Opssh(object): """ # Default set of options - pssh_args = [PSSH, '-i', '-t', '0', '-p', str(self.args.par), '--user', self.args.user] + pssh_args = [PSSH, '-t', '0', '-p', str(self.args.par), '--user', self.args.user] + + if self.args.inline: + pssh_args.append("--inline") if self.args.outdir: - pssh_args.append("--outdir='%s'" % self.args.outdir) + pssh_args.extend(["--outdir", self.args.outdir]) if self.args.errdir: - pssh_args.append("--errdir='%s'" % self.args.errdir) + pssh_args.extend(["--errdir", self.args.errdir]) hosts = self.aws.get_host_list(self.args.host_type, self.args.env) with tempfile.NamedTemporaryFile(prefix='opssh-', delete=True) as f: @@ -71,8 +74,8 @@ class Opssh(object): f.write(h + os.linesep) f.flush() - pssh_args.extend(["-h", "%s" % f.name]) - pssh_args.append("%s" % self.args.command) + pssh_args.extend(["-h", f.name]) + pssh_args.append(self.args.command) print print "Running: %s" % ' '.join(pssh_args) @@ -117,6 +120,9 @@ class Opssh(object): parser.add_argument('--user', action='store', default='root', help='username') + parser.add_argument('-i', '--inline', default=False, action='store_true', + help='inline aggregated output and error for each server') + parser.add_argument('-p', '--par', action='store', default=DEFAULT_PSSH_PAR, help=('max number of parallel threads (default %s)' % DEFAULT_PSSH_PAR)) -- cgit v1.2.3 From 4fe5e4645c099c69254b0e99081732a8b6af577a Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Wed, 8 Apr 2015 11:50:11 -0400 Subject: Automatic commit of package [openshift-ansible-bin] release [0.0.5-1]. --- bin/openshift-ansible-bin.spec | 6 +++++- rel-eng/packages/openshift-ansible-bin | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'bin') diff --git a/bin/openshift-ansible-bin.spec b/bin/openshift-ansible-bin.spec index f87002456..f509bdd79 100644 --- a/bin/openshift-ansible-bin.spec +++ b/bin/openshift-ansible-bin.spec @@ -1,6 +1,6 @@ Summary: OpenShift Ansible Scripts for working with metadata hosts Name: openshift-ansible-bin -Version: 0.0.4 +Version: 0.0.5 Release: 1%{?dist} License: ASL 2.0 URL: https://github.com/openshift/openshift-ansible @@ -36,6 +36,10 @@ cp -p openshift_ansible.conf.example %{buildroot}/etc/openshift_ansible/openshif %config(noreplace) /etc/openshift_ansible/ %changelog +* Wed Apr 08 2015 Thomas Wiest 0.0.5-1 +- fixed the opssh default output behavior to be consistent with pssh. Also + fixed a bug in how directories are named for --outdir and --errdir. + (twiest@redhat.com) * Tue Mar 31 2015 Thomas Wiest 0.0.4-1 - Fixed when tag was missing and added opssh completion (kwoodson@redhat.com) diff --git a/rel-eng/packages/openshift-ansible-bin b/rel-eng/packages/openshift-ansible-bin index a0e3e205c..99ae75e8b 100644 --- a/rel-eng/packages/openshift-ansible-bin +++ b/rel-eng/packages/openshift-ansible-bin @@ -1 +1 @@ -0.0.4-1 bin/ +0.0.5-1 bin/ -- cgit v1.2.3 From 6d0b77b9f3dbd439aa7e2d1d877e121214f284a8 Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Thu, 9 Apr 2015 15:04:17 -0400 Subject: fixed bug where opssh would throw an exception if pssh returned a non-zero exit code --- bin/opssh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'bin') diff --git a/bin/opssh b/bin/opssh index ad1aadc29..453da65b4 100755 --- a/bin/opssh +++ b/bin/opssh @@ -19,6 +19,7 @@ CONFIG_MAIN_SECTION = 'main' CONFIG_HOST_TYPE_ALIAS_SECTION = 'host_type_aliases' CONFIG_INVENTORY_OPTION = 'inventory' +class ArgumentMismatchError(ValueError): pass class Opssh(object): def __init__(self): @@ -36,21 +37,18 @@ class Opssh(object): self.aws = awsutil.AwsUtil(self.inventory, self.host_type_aliases) + def run(self): if self.args.list_host_types: self.aws.print_host_types() - return + return 0 if self.args.env and \ self.args.host_type and \ self.args.command: - retval = self.run_pssh() - if retval != 0: - raise ValueError("pssh run failed") - - return + return self.run_pssh() # If it makes it here, we weren't able to determine what they wanted to do - raise ValueError("Invalid combination of arguments") + raise ArgumentMismatchError("Invalid combination of arguments") def run_pssh(self): """Actually run the pssh command based off of the supplied options @@ -142,5 +140,7 @@ if __name__ == '__main__': try: opssh = Opssh() - except ValueError as e: + exitcode = opssh.run() + sys.exit(exitcode) + except ArgumentMismatchError as e: print "\nError: %s\n" % e.message -- cgit v1.2.3 From f0ae24d8346ba8cafe6c8f9890433789b5367078 Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Thu, 9 Apr 2015 15:20:31 -0400 Subject: Automatic commit of package [openshift-ansible-bin] release [0.0.6-1]. --- bin/openshift-ansible-bin.spec | 6 +++++- rel-eng/packages/openshift-ansible-bin | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'bin') diff --git a/bin/openshift-ansible-bin.spec b/bin/openshift-ansible-bin.spec index f509bdd79..695aebc28 100644 --- a/bin/openshift-ansible-bin.spec +++ b/bin/openshift-ansible-bin.spec @@ -1,6 +1,6 @@ Summary: OpenShift Ansible Scripts for working with metadata hosts Name: openshift-ansible-bin -Version: 0.0.5 +Version: 0.0.6 Release: 1%{?dist} License: ASL 2.0 URL: https://github.com/openshift/openshift-ansible @@ -36,6 +36,10 @@ cp -p openshift_ansible.conf.example %{buildroot}/etc/openshift_ansible/openshif %config(noreplace) /etc/openshift_ansible/ %changelog +* Thu Apr 09 2015 Thomas Wiest 0.0.6-1 +- fixed bug where opssh would throw an exception if pssh returned a non-zero + exit code (twiest@redhat.com) + * Wed Apr 08 2015 Thomas Wiest 0.0.5-1 - fixed the opssh default output behavior to be consistent with pssh. Also fixed a bug in how directories are named for --outdir and --errdir. diff --git a/rel-eng/packages/openshift-ansible-bin b/rel-eng/packages/openshift-ansible-bin index 99ae75e8b..a4d727f9d 100644 --- a/rel-eng/packages/openshift-ansible-bin +++ b/rel-eng/packages/openshift-ansible-bin @@ -1 +1 @@ -0.0.5-1 bin/ +0.0.6-1 bin/ -- cgit v1.2.3 From 9fbec064d28a72963b1566258b4bcabcd63b2c23 Mon Sep 17 00:00:00 2001 From: Lénaïc Huard Date: Wed, 8 Apr 2015 16:33:55 +0200 Subject: Add libvirt as a provider --- README.md | 1 + README_libvirt.md | 92 +++++++++++++++++++ bin/cluster | 6 +- inventory/libvirt/group_vars/all | 2 + inventory/libvirt/hosts | 2 + playbooks/libvirt/openshift-cluster/filter_plugins | 1 + playbooks/libvirt/openshift-cluster/launch.yml | 65 +++++++++++++ .../libvirt/openshift-cluster/launch_instances.yml | 102 +++++++++++++++++++++ playbooks/libvirt/openshift-cluster/list.yml | 43 +++++++++ playbooks/libvirt/openshift-cluster/roles | 1 + playbooks/libvirt/openshift-cluster/terminate.yml | 41 +++++++++ playbooks/libvirt/openshift-cluster/vars.yml | 7 ++ playbooks/libvirt/openshift-master/config.yml | 21 +++++ playbooks/libvirt/openshift-master/filter_plugins | 1 + playbooks/libvirt/openshift-master/roles | 1 + playbooks/libvirt/openshift-master/vars.yml | 1 + playbooks/libvirt/openshift-node/config.yml | 102 +++++++++++++++++++++ playbooks/libvirt/openshift-node/filter_plugins | 1 + playbooks/libvirt/openshift-node/roles | 1 + playbooks/libvirt/openshift-node/vars.yml | 1 + playbooks/libvirt/templates/domain.xml | 62 +++++++++++++ playbooks/libvirt/templates/meta-data | 2 + playbooks/libvirt/templates/user-data | 10 ++ 23 files changed, 564 insertions(+), 2 deletions(-) create mode 100644 README_libvirt.md create mode 100644 inventory/libvirt/group_vars/all create mode 100644 inventory/libvirt/hosts create mode 120000 playbooks/libvirt/openshift-cluster/filter_plugins create mode 100644 playbooks/libvirt/openshift-cluster/launch.yml create mode 100644 playbooks/libvirt/openshift-cluster/launch_instances.yml create mode 100644 playbooks/libvirt/openshift-cluster/list.yml create mode 120000 playbooks/libvirt/openshift-cluster/roles create mode 100644 playbooks/libvirt/openshift-cluster/terminate.yml create mode 100644 playbooks/libvirt/openshift-cluster/vars.yml create mode 100644 playbooks/libvirt/openshift-master/config.yml create mode 120000 playbooks/libvirt/openshift-master/filter_plugins create mode 120000 playbooks/libvirt/openshift-master/roles create mode 100644 playbooks/libvirt/openshift-master/vars.yml create mode 100644 playbooks/libvirt/openshift-node/config.yml create mode 120000 playbooks/libvirt/openshift-node/filter_plugins create mode 120000 playbooks/libvirt/openshift-node/roles create mode 100644 playbooks/libvirt/openshift-node/vars.yml create mode 100644 playbooks/libvirt/templates/domain.xml create mode 100644 playbooks/libvirt/templates/meta-data create mode 100644 playbooks/libvirt/templates/user-data (limited to 'bin') diff --git a/README.md b/README.md index e7fa89930..87dbfc1ea 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Setup - Setup for a specific cloud: - [AWS](README_AWS.md) - [GCE](README_GCE.md) + - [local VMs](README_libvirt.md) - Build - [How to build the openshift-ansible rpms](BUILD.md) diff --git a/README_libvirt.md b/README_libvirt.md new file mode 100644 index 000000000..fd2eb57f6 --- /dev/null +++ b/README_libvirt.md @@ -0,0 +1,92 @@ + +LIBVIRT Setup instructions +========================== + +`libvirt` is an `openshift-ansible` provider that uses `libvirt` to create local Fedora VMs that are provisioned exactly the same way that cloud VMs would be provisioned. + +This makes `libvirt` useful to develop, test and debug Openshift and openshift-ansible locally on the developer’s workstation before going to the cloud. + +Install dependencies +-------------------- + +1. Install [dnsmasq](http://www.thekelleys.org.uk/dnsmasq/doc.html) +2. Install [ebtables](http://ebtables.netfilter.org/) +3. Install [qemu](http://wiki.qemu.org/Main_Page) +4. Install [libvirt](http://libvirt.org/) +5. Enable and start the libvirt daemon, e.g: + * ``systemctl enable libvirtd`` + * ``systemctl start libvirtd`` +6. [Grant libvirt access to your user¹](https://libvirt.org/aclpolkit.html) +7. Check that your `$HOME` is accessible to the qemu user² + +#### ¹ Depending on your distribution, libvirt access may be denied by default or may require a password at each access. + +You can test it with the following command: +``` +virsh -c qemu:///system pool-list +``` + +If you have access error messages, please read https://libvirt.org/acl.html and https://libvirt.org/aclpolkit.html . + +In short, if your libvirt has been compiled with Polkit support (ex: Arch, Fedora 21), you can create `/etc/polkit-1/rules.d/50-org.libvirt.unix.manage.rules` as follows to grant full access to libvirt to `$USER` + +``` +sudo /bin/sh -c "cat - > /etc/polkit-1/rules.d/50-org.libvirt.unix.manage.rules" << EOF +polkit.addRule(function(action, subject) { + if (action.id == "org.libvirt.unix.manage" && + subject.user == "$USER") { + return polkit.Result.YES; + polkit.log("action=" + action); + polkit.log("subject=" + subject); + } +}); +EOF +``` + +If your libvirt has not been compiled with Polkit (ex: Ubuntu 14.04.1 LTS), check the permissions on the libvirt unix socket: + +``` +ls -l /var/run/libvirt/libvirt-sock +srwxrwx--- 1 root libvirtd 0 févr. 12 16:03 /var/run/libvirt/libvirt-sock + +usermod -a -G libvirtd $USER +# $USER needs to logout/login to have the new group be taken into account +``` + +(Replace `$USER` with your login name) + +#### ² Qemu will run with a specific user. It must have access to the VMs drives + +All the disk drive resources needed by the VMs (Fedora disk image, cloud-init files) are put inside `~/libvirt-storage-pool-openshift/`. + +As we’re using the `qemu:///system` instance of libvirt, qemu will run with a specific `user:group` distinct from your user. It is configured in `/etc/libvirt/qemu.conf`. That qemu user must have access to that libvirt storage pool. + +If your `$HOME` is world readable, everything is fine. If your `$HOME` is private, `ansible` will fail with an error message like: + +``` +error: Cannot access storage file '$HOME/libvirt-storage-pool-openshift/lenaic-master-216d8.qcow2' (as uid:99, gid:78): Permission denied +``` + +In order to fix that issue, you have several possibilities: +* set `libvirt_storage_pool_path` inside `playbooks/libvirt/openshift-cluster/launch.yml` and `playbooks/libvirt/openshift-cluster/terminate.yml` to a directory: + * backed by a filesystem with a lot of free disk space + * writable by your user; + * accessible by the qemu user. +* Grant the qemu user access to the storage pool. + +On Arch: + +``` +setfacl -m g:kvm:--x ~ +``` + +Test the setup +-------------- + +``` +cd openshift-ansible + +bin/cluster create -m 1 -n 3 libvirt lenaic + +bin/cluster terminate libvirt lenaic +``` diff --git a/bin/cluster b/bin/cluster index 36ab1da1b..ca227721e 100755 --- a/bin/cluster +++ b/bin/cluster @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 # vim: expandtab:tabstop=4:shiftwidth=4 import argparse @@ -94,6 +94,8 @@ class Cluster(object): os.environ[key] = config.get('ec2', key) inventory = '-i inventory/aws/ec2.py' + elif 'libvirt' == provider: + inventory = '-i inventory/libvirt/hosts' else: # this code should never be reached raise ValueError("invalid PROVIDER {}".format(provider)) @@ -139,7 +141,7 @@ if __name__ == '__main__': cluster = Cluster() - providers = ['gce', 'aws'] + providers = ['gce', 'aws', 'libvirt'] parser = argparse.ArgumentParser( description='Python wrapper to ensure proper environment for OpenShift ansible playbooks', ) diff --git a/inventory/libvirt/group_vars/all b/inventory/libvirt/group_vars/all new file mode 100644 index 000000000..b22da00de --- /dev/null +++ b/inventory/libvirt/group_vars/all @@ -0,0 +1,2 @@ +--- +ansible_ssh_user: root diff --git a/inventory/libvirt/hosts b/inventory/libvirt/hosts new file mode 100644 index 000000000..6a818f268 --- /dev/null +++ b/inventory/libvirt/hosts @@ -0,0 +1,2 @@ +# Eventually we'll add the GCE, AWS, etc dynamic inventories, but for now... +localhost ansible_python_interpreter=/usr/bin/python2 diff --git a/playbooks/libvirt/openshift-cluster/filter_plugins b/playbooks/libvirt/openshift-cluster/filter_plugins new file mode 120000 index 000000000..99a95e4ca --- /dev/null +++ b/playbooks/libvirt/openshift-cluster/filter_plugins @@ -0,0 +1 @@ +../../../filter_plugins \ No newline at end of file diff --git a/playbooks/libvirt/openshift-cluster/launch.yml b/playbooks/libvirt/openshift-cluster/launch.yml new file mode 100644 index 000000000..6f2df33af --- /dev/null +++ b/playbooks/libvirt/openshift-cluster/launch.yml @@ -0,0 +1,65 @@ +- name: Launch instance(s) + hosts: localhost + connection: local + gather_facts: no + + vars: + libvirt_storage_pool_path: "{{ lookup('env','HOME') }}/libvirt-storage-pool-openshift" + libvirt_storage_pool: 'openshift' + libvirt_uri: 'qemu:///system' + + vars_files: + - vars.yml + + tasks: + - set_fact: + k8s_type: master + + - name: Generate master instance name(s) + set_fact: + scratch_name: "{{ cluster_id }}-{{ k8s_type }}-{{ '%05x' | format( 1048576 | random ) }}" + register: master_names_output + with_sequence: start=1 end='{{ num_masters }}' + + - set_fact: + master_names: "{{ master_names_output.results | oo_collect('ansible_facts') | oo_collect('scratch_name') }}" + + - include: launch_instances.yml + vars: + instances: '{{ master_names }}' + cluster: '{{ cluster_id }}' + type: '{{ k8s_type }}' + group_name: 'tag_env-host-type-{{ cluster_id }}-openshift-master' + + - set_fact: + k8s_type: node + + - name: Generate node instance name(s) + set_fact: + scratch_name: "{{ cluster_id }}-{{ k8s_type }}-{{ '%05x' | format( 1048576 | random ) }}" + register: node_names_output + with_sequence: start=1 end='{{ num_nodes }}' + + - set_fact: + node_names: "{{ node_names_output.results | oo_collect('ansible_facts') | oo_collect('scratch_name') }}" + + - include: launch_instances.yml + vars: + instances: '{{ node_names }}' + cluster: '{{ cluster_id }}' + type: '{{ k8s_type }}' + +- hosts: 'tag_env-{{ cluster_id }}' + roles: + - openshift_repos + - os_update_latest + +- include: ../openshift-master/config.yml + vars: + oo_host_group_exp: 'groups["tag_env-host-type-{{ cluster_id }}-openshift-master"]' + oo_env: '{{ cluster_id }}' + +- include: ../openshift-node/config.yml + vars: + oo_host_group_exp: 'groups["tag_env-host-type-{{ cluster_id }}-openshift-node"]' + oo_env: '{{ cluster_id }}' diff --git a/playbooks/libvirt/openshift-cluster/launch_instances.yml b/playbooks/libvirt/openshift-cluster/launch_instances.yml new file mode 100644 index 000000000..3bbcae981 --- /dev/null +++ b/playbooks/libvirt/openshift-cluster/launch_instances.yml @@ -0,0 +1,102 @@ +- name: Create the libvirt storage directory for openshift + file: + dest: '{{ libvirt_storage_pool_path }}' + state: directory + +- name: Download Base Cloud image + get_url: + url: '{{ base_image_url }}' + sha256sum: '{{ base_image_sha256 }}' + dest: '{{ libvirt_storage_pool_path }}/{{ base_image_name }}' + +- name: Create the cloud-init config drive path + file: + dest: '{{ libvirt_storage_pool_path }}/{{ item }}_configdrive/openstack/latest' + state: directory + with_items: '{{ instances }}' + +- name: Create the cloud-init config drive files + template: + src: '{{ item[1] }}' + dest: '{{ libvirt_storage_pool_path }}/{{ item[0] }}_configdrive/openstack/latest/{{ item[1] }}' + with_nested: + - '{{ instances }}' + - [ user-data, meta-data ] + +- name: Create the cloud-init config drive + command: 'genisoimage -output {{ libvirt_storage_pool_path }}/{{ item }}_cloud-init.iso -volid cidata -joliet -rock user-data meta-data' + args: + chdir: '{{ libvirt_storage_pool_path }}/{{ item }}_configdrive/openstack/latest' + creates: '{{ libvirt_storage_pool_path }}/{{ item }}_cloud-init.iso' + with_items: '{{ instances }}' + +- name: Create the libvirt storage pool for openshift + command: 'virsh -c {{ libvirt_uri }} pool-create-as {{ libvirt_storage_pool }} dir --target {{ libvirt_storage_pool_path }}' + ignore_errors: yes + +- name: Refresh the libvirt storage pool for openshift + command: 'virsh -c {{ libvirt_uri }} pool-refresh {{ libvirt_storage_pool }}' + +- name: Create VMs drives + command: 'virsh -c {{ libvirt_uri }} vol-create-as {{ libvirt_storage_pool }} {{ item }}.qcow2 10G --format qcow2 --backing-vol {{ base_image_name }} --backing-vol-format qcow2' + with_items: '{{ instances }}' + +- name: Create VMs + virt: + name: '{{ item }}' + command: define + xml: "{{ lookup('template', '../templates/domain.xml') }}" + uri: '{{ libvirt_uri }}' + with_items: '{{ instances }}' + +- name: Start VMs + virt: + name: '{{ item }}' + state: running + uri: '{{ libvirt_uri }}' + with_items: '{{ instances }}' + +- name: Collect MAC addresses of the VMs + shell: 'virsh -c {{ libvirt_uri }} dumpxml {{ item }} | xmllint --xpath "string(//domain/devices/interface/mac/@address)" -' + register: scratch_mac + with_items: '{{ instances }}' + +- name: Wait for the VMs to get an IP + command: "egrep -c '{{ scratch_mac.results | oo_collect('stdout') | join('|') }}' /proc/net/arp" + ignore_errors: yes + register: nb_allocated_ips + until: nb_allocated_ips.stdout == '{{ instances | length }}' + retries: 30 + delay: 1 + +- name: Collect IP addresses of the VMs + shell: "awk '/{{ item.stdout }}/ {print $1}' /proc/net/arp" + register: scratch_ip + with_items: '{{ scratch_mac.results }}' + +- set_fact: + ips: "{{ scratch_ip.results | oo_collect('stdout') }}" + +- name: Add new instances + add_host: + hostname: '{{ item.0 }}' + ansible_ssh_host: '{{ item.1 }}' + ansible_ssh_user: root + groups: 'tag_env-{{ cluster }}, tag_host-type-{{ type }}, tag_env-host-type-{{ cluster }}-openshift-{{ type }}' + with_together: + - instances + - ips + +- name: Wait for ssh + wait_for: + host: '{{ item }}' + port: 22 + with_items: ips + +- name: Wait for root user setup + command: 'ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o ConnectTimeout=10 -o UserKnownHostsFile=/dev/null root@{{ item }} echo root user is setup' + register: result + until: result.rc == 0 + retries: 30 + delay: 1 + with_items: ips diff --git a/playbooks/libvirt/openshift-cluster/list.yml b/playbooks/libvirt/openshift-cluster/list.yml new file mode 100644 index 000000000..6bf07e3c6 --- /dev/null +++ b/playbooks/libvirt/openshift-cluster/list.yml @@ -0,0 +1,43 @@ +- name: Generate oo_list_hosts group + hosts: localhost + connection: local + gather_facts: no + + vars: + libvirt_uri: 'qemu:///system' + + tasks: + - name: List VMs + virt: + command: list_vms + register: list_vms + + - name: Collect MAC addresses of the VMs + shell: 'virsh -c {{ libvirt_uri }} dumpxml {{ item }} | xmllint --xpath "string(//domain/devices/interface/mac/@address)" -' + register: scratch_mac + with_items: '{{ list_vms.list_vms }}' + when: item|truncate(cluster_id|length+1, True) == '{{ cluster_id }}-...' + + - name: Collect IP addresses of the VMs + shell: "awk '/{{ item.stdout }}/ {print $1}' /proc/net/arp" + register: scratch_ip + with_items: '{{ scratch_mac.results }}' + when: item.skipped is not defined + + - name: Add hosts + add_host: + hostname: '{{ item[0] }}' + ansible_ssh_host: '{{ item[1].stdout }}' + ansible_ssh_user: root + groups: oo_list_hosts + with_together: + - '{{ list_vms.list_vms }}' + - '{{ scratch_ip.results }}' + when: item[1].skipped is not defined + +- name: List Hosts + hosts: oo_list_hosts + + tasks: + - debug: + msg: 'public:{{ansible_default_ipv4.address}} private:{{ansible_default_ipv4.address}}' diff --git a/playbooks/libvirt/openshift-cluster/roles b/playbooks/libvirt/openshift-cluster/roles new file mode 120000 index 000000000..20c4c58cf --- /dev/null +++ b/playbooks/libvirt/openshift-cluster/roles @@ -0,0 +1 @@ +../../../roles \ No newline at end of file diff --git a/playbooks/libvirt/openshift-cluster/terminate.yml b/playbooks/libvirt/openshift-cluster/terminate.yml new file mode 100644 index 000000000..c609169d3 --- /dev/null +++ b/playbooks/libvirt/openshift-cluster/terminate.yml @@ -0,0 +1,41 @@ +- name: Terminate instance(s) + hosts: localhost + connection: local + gather_facts: no + + vars: + libvirt_storage_pool_path: "{{ lookup('env','HOME') }}/libvirt-storage-pool-openshift" + libvirt_storage_pool: 'openshift' + libvirt_uri: 'qemu:///system' + + tasks: + - name: List VMs + virt: + command: list_vms + register: list_vms + + - name: Destroy VMs + virt: + name: '{{ item[0] }}' + command: '{{ item[1] }}' + uri: '{{ libvirt_uri }}' + with_nested: + - '{{ list_vms.list_vms }}' + - [ destroy, undefine ] + when: item[0]|truncate(cluster_id|length+1, True) == '{{ cluster_id }}-...' + + - name: Delete VMs config drive + file: + path: '{{ libvirt_storage_pool_path }}/{{ item }}_configdrive/openstack' + state: absent + with_items: '{{ list_vms.list_vms }}' + when: item|truncate(cluster_id|length+1, True) == '{{ cluster_id }}-...' + + - name: Delete VMs drives + command: 'virsh -c {{ libvirt_uri }} vol-delete --pool {{ libvirt_storage_pool }} {{ item[0] }}{{ item[1] }}' + args: + removes: '{{ libvirt_storage_pool_path }}/{{ item[0] }}{{ item[1] }}' + with_nested: + - '{{ list_vms.list_vms }}' + - [ '_configdrive', '_cloud-init.iso', '.qcow2' ] + when: item[0]|truncate(cluster_id|length+1, True) == '{{ cluster_id }}-...' diff --git a/playbooks/libvirt/openshift-cluster/vars.yml b/playbooks/libvirt/openshift-cluster/vars.yml new file mode 100644 index 000000000..4e4eecd46 --- /dev/null +++ b/playbooks/libvirt/openshift-cluster/vars.yml @@ -0,0 +1,7 @@ +# base_image_url: http://download.fedoraproject.org/pub/fedora/linux/releases/21/Cloud/Images/x86_64/Fedora-Cloud-Base-20141203-21.x86_64.qcow2 +# base_image_name: Fedora-Cloud-Base-20141203-21.x86_64.qcow2 +# base_image_sha256: 3a99bb89f33e3d4ee826c8160053cdb8a72c80cd23350b776ce73cd244467d86 + +base_image_url: http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2 +base_image_name: CentOS-7-x86_64-GenericCloud.qcow2 +base_image_sha256: e324e3ab1d24a1bbf035ddb365e7f9058c0b454acf48d7aa15c5519fae5998ab diff --git a/playbooks/libvirt/openshift-master/config.yml b/playbooks/libvirt/openshift-master/config.yml new file mode 100644 index 000000000..dd95fd57f --- /dev/null +++ b/playbooks/libvirt/openshift-master/config.yml @@ -0,0 +1,21 @@ +- name: master/config.yml, populate oo_masters_to_config host group if needed + hosts: localhost + gather_facts: no + tasks: + - name: "Evaluate oo_host_group_exp if it's set" + add_host: + name: '{{ item }}' + groups: oo_masters_to_config + with_items: "{{ oo_host_group_exp | default('') }}" + when: oo_host_group_exp is defined + +- name: Configure instances + hosts: oo_masters_to_config + vars: + openshift_hostname: '{{ ansible_default_ipv4.address }}' + vars_files: + - vars.yml + roles: + - openshift_master + - pods + - os_env_extras diff --git a/playbooks/libvirt/openshift-master/filter_plugins b/playbooks/libvirt/openshift-master/filter_plugins new file mode 120000 index 000000000..99a95e4ca --- /dev/null +++ b/playbooks/libvirt/openshift-master/filter_plugins @@ -0,0 +1 @@ +../../../filter_plugins \ No newline at end of file diff --git a/playbooks/libvirt/openshift-master/roles b/playbooks/libvirt/openshift-master/roles new file mode 120000 index 000000000..20c4c58cf --- /dev/null +++ b/playbooks/libvirt/openshift-master/roles @@ -0,0 +1 @@ +../../../roles \ No newline at end of file diff --git a/playbooks/libvirt/openshift-master/vars.yml b/playbooks/libvirt/openshift-master/vars.yml new file mode 100644 index 000000000..ad0c0fbe2 --- /dev/null +++ b/playbooks/libvirt/openshift-master/vars.yml @@ -0,0 +1 @@ +openshift_debug_level: 4 diff --git a/playbooks/libvirt/openshift-node/config.yml b/playbooks/libvirt/openshift-node/config.yml new file mode 100644 index 000000000..3244a8046 --- /dev/null +++ b/playbooks/libvirt/openshift-node/config.yml @@ -0,0 +1,102 @@ +- name: node/config.yml, populate oo_nodes_to_config host group if needed + hosts: localhost + gather_facts: no + tasks: + - name: "Evaluate oo_host_group_exp if it's set" + add_host: + name: '{{ item }}' + groups: oo_nodes_to_config + with_items: "{{ oo_host_group_exp | default('') }}" + when: oo_host_group_exp is defined + + - add_host: + name: "{{ groups['tag_env-host-type-' ~ cluster_id ~ '-openshift-master'][0] }}" + groups: oo_first_master + when: oo_host_group_exp is defined + + +- name: Gather and set facts for hosts to configure + hosts: oo_nodes_to_config + roles: + - openshift_facts + tasks: + # Since the master is registering the nodes before they are configured, we + # need to make sure to set the node properties beforehand if we do not want + # the defaults + - openshift_facts: + role: "{{ item.role }}" + local_facts: "{{ item.local_facts }}" + with_items: + - role: common + local_facts: + hostname: "{{ ansible_default_ipv4.address }}" + - role: node + local_facts: + external_id: "{{ openshift_node_external_id | default(None) }}" + resources_cpu: "{{ openshfit_node_resources_cpu | default(None) }}" + resources_memory: "{{ openshfit_node_resources_memory | default(None) }}" + pod_cidr: "{{ openshfit_node_pod_cidr | default(None) }}" + labels: "{{ openshfit_node_labels | default(None) }}" + annotations: "{{ openshfit_node_annotations | default(None) }}" + + +- name: Register nodes + hosts: oo_first_master + vars: + openshift_nodes: "{{ hostvars + | oo_select_keys(groups['oo_nodes_to_config']) }}" + roles: + - openshift_register_nodes + tasks: + - name: Create local temp directory for syncing certs + local_action: command /usr/bin/mktemp -d /tmp/openshift-ansible-XXXXXXX + register: mktemp + + - name: Sync master certs to localhost + synchronize: + mode: pull + checksum: yes + src: /var/lib/openshift/openshift.local.certificates + dest: "{{ mktemp.stdout }}" + +- name: Configure instances + hosts: oo_nodes_to_config + vars_files: + - vars.yml + vars: + sync_tmpdir: "{{ hostvars[groups['oo_first_master'][0]].mktemp.stdout }}" + cert_parent_rel_path: openshift.local.certificates + cert_rel_path: "{{ cert_parent_rel_path }}/node-{{ openshift.common.hostname }}" + cert_base_path: /var/lib/openshift + cert_parent_path: "{{ cert_base_path }}/{{ cert_parent_rel_path }}" + cert_path: "{{ cert_base_path }}/{{ cert_rel_path }}" + pre_tasks: + - name: Ensure certificate directories exists + file: + path: "{{ item }}" + state: directory + with_items: + - "{{ cert_path }}" + - "{{ cert_parent_path }}/ca" + + # TODO: notify restart openshift-node and/or restart openshift-sdn-node, + # possibly test service started time against certificate/config file + # timestamps in openshift-node or openshift-sdn-node to trigger notify + - name: Sync certs to nodes + synchronize: + checksum: yes + src: "{{ item.src }}" + dest: "{{ item.dest }}" + owner: no + group: no + with_items: + - src: "{{ sync_tmpdir }}/{{ cert_rel_path }}" + dest: "{{ cert_parent_path }}" + - src: "{{ sync_tmpdir }}/{{ cert_parent_rel_path }}/ca/cert.crt" + dest: "{{ cert_parent_path }}/ca/cert.crt" + - local_action: file name={{ sync_tmpdir }} state=absent + run_once: true + roles: + - openshift_node + - os_env_extras + - os_env_extras_node diff --git a/playbooks/libvirt/openshift-node/filter_plugins b/playbooks/libvirt/openshift-node/filter_plugins new file mode 120000 index 000000000..99a95e4ca --- /dev/null +++ b/playbooks/libvirt/openshift-node/filter_plugins @@ -0,0 +1 @@ +../../../filter_plugins \ No newline at end of file diff --git a/playbooks/libvirt/openshift-node/roles b/playbooks/libvirt/openshift-node/roles new file mode 120000 index 000000000..20c4c58cf --- /dev/null +++ b/playbooks/libvirt/openshift-node/roles @@ -0,0 +1 @@ +../../../roles \ No newline at end of file diff --git a/playbooks/libvirt/openshift-node/vars.yml b/playbooks/libvirt/openshift-node/vars.yml new file mode 100644 index 000000000..ad0c0fbe2 --- /dev/null +++ b/playbooks/libvirt/openshift-node/vars.yml @@ -0,0 +1 @@ +openshift_debug_level: 4 diff --git a/playbooks/libvirt/templates/domain.xml b/playbooks/libvirt/templates/domain.xml new file mode 100644 index 000000000..da037d138 --- /dev/null +++ b/playbooks/libvirt/templates/domain.xml @@ -0,0 +1,62 @@ + + {{ item }} + 1 + 1 + 2 + + hvm + + + + + + + + + + + + + destroy + restart + restart + + /usr/bin/qemu-system-x86_64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/playbooks/libvirt/templates/meta-data b/playbooks/libvirt/templates/meta-data new file mode 100644 index 000000000..5d779519f --- /dev/null +++ b/playbooks/libvirt/templates/meta-data @@ -0,0 +1,2 @@ +instance-id: {{ item[0] }} +local-hostname: {{ item[0] }} diff --git a/playbooks/libvirt/templates/user-data b/playbooks/libvirt/templates/user-data new file mode 100644 index 000000000..985badc8e --- /dev/null +++ b/playbooks/libvirt/templates/user-data @@ -0,0 +1,10 @@ +#cloud-config + +disable_root: 0 + +system_info: + default_user: + name: root + +ssh_authorized_keys: + - {{ lookup('file', '~/.ssh/id_rsa.pub') }} -- cgit v1.2.3 From 6b74f852258b51c1558aff3967288a57ca4efb86 Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Fri, 10 Apr 2015 16:30:32 -0400 Subject: added ohi --- bin/ohi | 96 ++++++++++++++++++++++++++++++++++++++++++ bin/openshift-ansible-bin.spec | 2 +- 2 files changed, 97 insertions(+), 1 deletion(-) create mode 100755 bin/ohi (limited to 'bin') diff --git a/bin/ohi b/bin/ohi new file mode 100755 index 000000000..06a375cdb --- /dev/null +++ b/bin/ohi @@ -0,0 +1,96 @@ +#!/usr/bin/env python +# vim: expandtab:tabstop=4:shiftwidth=4 + +import argparse +import traceback +import sys +import os +import re +import tempfile +import time +import subprocess +import ConfigParser + +from openshift_ansible import awsutil + +CONFIG_MAIN_SECTION = 'main' +CONFIG_HOST_TYPE_ALIAS_SECTION = 'host_type_aliases' +CONFIG_INVENTORY_OPTION = 'inventory' + +class ArgumentMismatchError(ValueError): pass + +class Ohi(object): + def __init__(self): + self.inventory = None + self.host_type_aliases = {} + self.file_path = os.path.join(os.path.dirname(os.path.realpath(__file__))) + + # Default the config path to /etc + self.config_path = os.path.join(os.path.sep, 'etc', \ + 'openshift_ansible', \ + 'openshift_ansible.conf') + + self.parse_cli_args() + self.parse_config_file() + + self.aws = awsutil.AwsUtil(self.inventory, self.host_type_aliases) + + def run(self): + if self.args.list_host_types: + self.aws.print_host_types() + return 0 + + if self.args.env and \ + self.args.host_type: + hosts = self.aws.get_host_list(self.args.host_type, self.args.env) + for host in hosts: + print host + return 0 + + # If it makes it here, we weren't able to determine what they wanted to do + raise ArgumentMismatchError("Invalid combination of arguments") + + def parse_config_file(self): + if os.path.isfile(self.config_path): + config = ConfigParser.ConfigParser() + config.read(self.config_path) + + if config.has_section(CONFIG_MAIN_SECTION) and \ + config.has_option(CONFIG_MAIN_SECTION, CONFIG_INVENTORY_OPTION): + self.inventory = config.get(CONFIG_MAIN_SECTION, CONFIG_INVENTORY_OPTION) + + self.host_type_aliases = {} + if config.has_section(CONFIG_HOST_TYPE_ALIAS_SECTION): + for alias in config.options(CONFIG_HOST_TYPE_ALIAS_SECTION): + value = config.get(CONFIG_HOST_TYPE_ALIAS_SECTION, alias).split(',') + self.host_type_aliases[alias] = value + + def parse_cli_args(self): + """Setup the command line parser with the options we want + """ + + parser = argparse.ArgumentParser(description='Openshift Host Inventory') + + parser.add_argument('--list-host-types', default=False, action='store_true', + help='List all of the host types') + + parser.add_argument('-e', '--env', action="store", + help="Which environment to use") + + parser.add_argument('-t', '--host-type', action="store", + help="Which host type to use") + + self.args = parser.parse_args() + + +if __name__ == '__main__': + if len(sys.argv) == 1: + print "\nError: No options given. Use --help to see the available options\n" + sys.exit(0) + + try: + ohi = Ohi() + exitcode = ohi.run() + sys.exit(exitcode) + except ArgumentMismatchError as e: + print "\nError: %s\n" % e.message diff --git a/bin/openshift-ansible-bin.spec b/bin/openshift-ansible-bin.spec index 695aebc28..876bca1d7 100644 --- a/bin/openshift-ansible-bin.spec +++ b/bin/openshift-ansible-bin.spec @@ -23,7 +23,7 @@ mkdir -p %{buildroot}%{python_sitelib}/openshift_ansible mkdir -p %{buildroot}/etc/bash_completion.d mkdir -p %{buildroot}/etc/openshift_ansible -cp -p ossh oscp opssh %{buildroot}%{_bindir} +cp -p ossh oscp opssh ohi %{buildroot}%{_bindir} cp -p openshift_ansible/* %{buildroot}%{python_sitelib}/openshift_ansible cp -p ossh_bash_completion %{buildroot}/etc/bash_completion.d -- cgit v1.2.3 From 8a7a455abfcf8df7ddc706d11167cb904e1b52dd Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Fri, 10 Apr 2015 17:36:22 -0400 Subject: added the ability to run opssh and ohi on all hosts in an environment, as well as all hosts of the same host-type regardless of environment --- bin/ohi | 36 +++++++++++++++++++++++++----------- bin/openshift_ansible/awsutil.py | 40 +++++++++++++++++++++++++++++++++++++--- bin/opssh | 36 ++++++++++++++++++++++++++---------- 3 files changed, 88 insertions(+), 24 deletions(-) (limited to 'bin') diff --git a/bin/ohi b/bin/ohi index 06a375cdb..408961ee4 100755 --- a/bin/ohi +++ b/bin/ohi @@ -12,13 +12,12 @@ import subprocess import ConfigParser from openshift_ansible import awsutil +from openshift_ansible.awsutil import ArgumentError CONFIG_MAIN_SECTION = 'main' CONFIG_HOST_TYPE_ALIAS_SECTION = 'host_type_aliases' CONFIG_INVENTORY_OPTION = 'inventory' -class ArgumentMismatchError(ValueError): pass - class Ohi(object): def __init__(self): self.inventory = None @@ -40,15 +39,30 @@ class Ohi(object): self.aws.print_host_types() return 0 - if self.args.env and \ - self.args.host_type: - hosts = self.aws.get_host_list(self.args.host_type, self.args.env) - for host in hosts: - print host - return 0 + hosts = None + if self.args.host_type is not None and \ + self.args.env is not None: + # Both env and host-type specified + hosts = self.aws.get_host_list(host_type=self.args.host_type, \ + env=self.args.env) + + if self.args.host_type is None and \ + self.args.env is not None: + # Only env specified + hosts = self.aws.get_host_list(env=self.args.env) + + if self.args.host_type is not None and \ + self.args.env is None: + # Only host-type specified + hosts = self.aws.get_host_list(host_type=self.args.host_type) + + if hosts is None: + # We weren't able to determine what they wanted to do + raise ArgumentError("Invalid combination of arguments") - # If it makes it here, we weren't able to determine what they wanted to do - raise ArgumentMismatchError("Invalid combination of arguments") + for host in hosts: + print host + return 0 def parse_config_file(self): if os.path.isfile(self.config_path): @@ -92,5 +106,5 @@ if __name__ == '__main__': ohi = Ohi() exitcode = ohi.run() sys.exit(exitcode) - except ArgumentMismatchError as e: + except ArgumentError as e: print "\nError: %s\n" % e.message diff --git a/bin/openshift_ansible/awsutil.py b/bin/openshift_ansible/awsutil.py index 8fef0a24f..65b269930 100644 --- a/bin/openshift_ansible/awsutil.py +++ b/bin/openshift_ansible/awsutil.py @@ -5,6 +5,10 @@ import os import json import re +class ArgumentError(Exception): + def __init__(self, message): + self.message = message + class AwsUtil(object): def __init__(self, inventory_path=None, host_type_aliases={}): self.host_type_aliases = host_type_aliases @@ -128,15 +132,45 @@ class AwsUtil(object): return self.alias_lookup[host_type] return host_type + def gen_env_tag(self, env): + """Generate the environment tag + """ + return "tag_environment_%s" % env + + def gen_host_type_tag(self, host_type): + """Generate the host type tag + """ + host_type = self.resolve_host_type(host_type) + return "tag_host-type_%s" % host_type + def gen_env_host_type_tag(self, host_type, env): """Generate the environment host type tag """ host_type = self.resolve_host_type(host_type) return "tag_env-host-type_%s-%s" % (env, host_type) - def get_host_list(self, host_type, env): + def get_host_list(self, host_type=None, env=None): """Get the list of hosts from the inventory using host-type and environment """ inv = self.get_inventory() - host_type_tag = self.gen_env_host_type_tag(host_type, env) - return inv[host_type_tag] + + if host_type is not None and \ + env is not None: + # Both host type and environment were specified + env_host_type_tag = self.gen_env_host_type_tag(host_type, env) + return inv[env_host_type_tag] + + if host_type is None and \ + env is not None: + # Just environment was specified + host_type_tag = self.gen_env_tag(env) + return inv[host_type_tag] + + if host_type is not None and \ + env is None: + # Just host-type was specified + host_type_tag = self.gen_host_type_tag(host_type) + return inv[host_type_tag] + + # We should never reach here! + raise ArgumentError("Invalid combination of parameters") diff --git a/bin/opssh b/bin/opssh index 453da65b4..5fb447318 100755 --- a/bin/opssh +++ b/bin/opssh @@ -12,6 +12,7 @@ import subprocess import ConfigParser from openshift_ansible import awsutil +from openshift_ansible.awsutil import ArgumentError DEFAULT_PSSH_PAR = 200 PSSH = '/usr/bin/pssh' @@ -19,8 +20,6 @@ CONFIG_MAIN_SECTION = 'main' CONFIG_HOST_TYPE_ALIAS_SECTION = 'host_type_aliases' CONFIG_INVENTORY_OPTION = 'inventory' -class ArgumentMismatchError(ValueError): pass - class Opssh(object): def __init__(self): self.inventory = None @@ -42,13 +41,30 @@ class Opssh(object): self.aws.print_host_types() return 0 - if self.args.env and \ - self.args.host_type and \ - self.args.command: - return self.run_pssh() + hosts = None + if self.args.host_type is not None and \ + self.args.env is not None: + # Both env and host-type specified + hosts = self.aws.get_host_list(host_type=self.args.host_type, \ + env=self.args.env) + + if self.args.host_type is None and \ + self.args.env is not None: + # Only env specified + hosts = self.aws.get_host_list(env=self.args.env) + + if self.args.host_type is not None and \ + self.args.env is None: + # Only host-type specified + hosts = self.aws.get_host_list(host_type=self.args.host_type) + + if hosts is None: + # We weren't able to determine what they wanted to do + raise ArgumentError("Invalid combination of arguments") - # If it makes it here, we weren't able to determine what they wanted to do - raise ArgumentMismatchError("Invalid combination of arguments") + for host in hosts: + print host + return 0 def run_pssh(self): """Actually run the pssh command based off of the supplied options @@ -109,7 +125,7 @@ class Opssh(object): parser.add_argument('-e', '--env', action="store", help="Which environment to use") - parser.add_argument('-t', '--host-type', action="store", + parser.add_argument('-t', '--host-type', action="store", default=None, help="Which host type to use") parser.add_argument('-c', '--command', action='store', @@ -142,5 +158,5 @@ if __name__ == '__main__': opssh = Opssh() exitcode = opssh.run() sys.exit(exitcode) - except ArgumentMismatchError as e: + except ArgumentError as e: print "\nError: %s\n" % e.message -- cgit v1.2.3 From 1cb4ba976599e6e4fd18568f7dc46b58db5b4161 Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Mon, 13 Apr 2015 10:07:39 -0400 Subject: Automatic commit of package [openshift-ansible-bin] release [0.0.7-1]. --- bin/openshift-ansible-bin.spec | 7 ++++++- rel-eng/packages/openshift-ansible-bin | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'bin') diff --git a/bin/openshift-ansible-bin.spec b/bin/openshift-ansible-bin.spec index 876bca1d7..04af4546c 100644 --- a/bin/openshift-ansible-bin.spec +++ b/bin/openshift-ansible-bin.spec @@ -1,6 +1,6 @@ Summary: OpenShift Ansible Scripts for working with metadata hosts Name: openshift-ansible-bin -Version: 0.0.6 +Version: 0.0.7 Release: 1%{?dist} License: ASL 2.0 URL: https://github.com/openshift/openshift-ansible @@ -36,6 +36,11 @@ cp -p openshift_ansible.conf.example %{buildroot}/etc/openshift_ansible/openshif %config(noreplace) /etc/openshift_ansible/ %changelog +* Mon Apr 13 2015 Thomas Wiest 0.0.7-1 +- added the ability to run opssh and ohi on all hosts in an environment, as + well as all hosts of the same host-type regardless of environment + (twiest@redhat.com) +- added ohi (twiest@redhat.com) * Thu Apr 09 2015 Thomas Wiest 0.0.6-1 - fixed bug where opssh would throw an exception if pssh returned a non-zero exit code (twiest@redhat.com) diff --git a/rel-eng/packages/openshift-ansible-bin b/rel-eng/packages/openshift-ansible-bin index a4d727f9d..6b4f91660 100644 --- a/rel-eng/packages/openshift-ansible-bin +++ b/rel-eng/packages/openshift-ansible-bin @@ -1 +1 @@ -0.0.6-1 bin/ +0.0.7-1 bin/ -- cgit v1.2.3 From fa08dd34159e16c574f551cd48d7194f5888a128 Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Mon, 13 Apr 2015 16:35:55 -0400 Subject: fixed bug in opssh where it wouldn't actually run pssh --- bin/opssh | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) (limited to 'bin') diff --git a/bin/opssh b/bin/opssh index 5fb447318..a4fceb6a8 100755 --- a/bin/opssh +++ b/bin/opssh @@ -41,30 +41,12 @@ class Opssh(object): self.aws.print_host_types() return 0 - hosts = None - if self.args.host_type is not None and \ + if self.args.host_type is not None or \ self.args.env is not None: - # Both env and host-type specified - hosts = self.aws.get_host_list(host_type=self.args.host_type, \ - env=self.args.env) + return self.run_pssh() - if self.args.host_type is None and \ - self.args.env is not None: - # Only env specified - hosts = self.aws.get_host_list(env=self.args.env) - - if self.args.host_type is not None and \ - self.args.env is None: - # Only host-type specified - hosts = self.aws.get_host_list(host_type=self.args.host_type) - - if hosts is None: - # We weren't able to determine what they wanted to do - raise ArgumentError("Invalid combination of arguments") - - for host in hosts: - print host - return 0 + # We weren't able to determine what they wanted to do + raise ArgumentError("Invalid combination of arguments") def run_pssh(self): """Actually run the pssh command based off of the supplied options @@ -82,7 +64,9 @@ class Opssh(object): if self.args.errdir: pssh_args.extend(["--errdir", self.args.errdir]) - hosts = self.aws.get_host_list(self.args.host_type, self.args.env) + hosts = self.aws.get_host_list(host_type=self.args.host_type, + env=self.args.env) + with tempfile.NamedTemporaryFile(prefix='opssh-', delete=True) as f: for h in hosts: f.write(h + os.linesep) -- cgit v1.2.3 From eb64f8f819139e3901b032a4f2bfa53a3189531e Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Mon, 13 Apr 2015 16:42:36 -0400 Subject: Automatic commit of package [openshift-ansible-bin] release [0.0.8-1]. --- bin/openshift-ansible-bin.spec | 5 ++++- rel-eng/packages/openshift-ansible-bin | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'bin') diff --git a/bin/openshift-ansible-bin.spec b/bin/openshift-ansible-bin.spec index 04af4546c..c7db6f684 100644 --- a/bin/openshift-ansible-bin.spec +++ b/bin/openshift-ansible-bin.spec @@ -1,6 +1,6 @@ Summary: OpenShift Ansible Scripts for working with metadata hosts Name: openshift-ansible-bin -Version: 0.0.7 +Version: 0.0.8 Release: 1%{?dist} License: ASL 2.0 URL: https://github.com/openshift/openshift-ansible @@ -36,6 +36,9 @@ cp -p openshift_ansible.conf.example %{buildroot}/etc/openshift_ansible/openshif %config(noreplace) /etc/openshift_ansible/ %changelog +* Mon Apr 13 2015 Thomas Wiest 0.0.8-1 +- fixed bug in opssh where it wouldn't actually run pssh (twiest@redhat.com) + * Mon Apr 13 2015 Thomas Wiest 0.0.7-1 - added the ability to run opssh and ohi on all hosts in an environment, as well as all hosts of the same host-type regardless of environment diff --git a/rel-eng/packages/openshift-ansible-bin b/rel-eng/packages/openshift-ansible-bin index 6b4f91660..500e1f4b1 100644 --- a/rel-eng/packages/openshift-ansible-bin +++ b/rel-eng/packages/openshift-ansible-bin @@ -1 +1 @@ -0.0.7-1 bin/ +0.0.8-1 bin/ -- cgit v1.2.3