From f08516929901730dc3b003f0942dbbd630663a80 Mon Sep 17 00:00:00 2001 From: Jhon Honce Date: Thu, 25 Sep 2014 17:25:27 -0700 Subject: Add cluster.sh --- cloud.rb | 83 ++++++++++++++++++++++++-------- cluster.sh | 86 ++++++++++++++++++++++++++++++++++ playbooks/gce/os3-master/terminate.yml | 18 +++++++ playbooks/gce/os3-minion/terminate.yml | 18 +++++++ 4 files changed, 185 insertions(+), 20 deletions(-) create mode 100755 cluster.sh create mode 100644 playbooks/gce/os3-master/terminate.yml create mode 100644 playbooks/gce/os3-minion/terminate.yml diff --git a/cloud.rb b/cloud.rb index 8f53b9460..840742b8c 100755 --- a/cloud.rb +++ b/cloud.rb @@ -6,13 +6,14 @@ require 'yaml' require 'securerandom' require 'fileutils' require 'parseconfig' +require 'open3' SCRIPT_DIR = File.expand_path(File.dirname(__FILE__)) module OpenShift module Ops # WARNING: we do not currently support environments with hyphens in the name - SUPPORTED_ENVS = ['prod','stg','int','tint','kint','test'] + SUPPORTED_ENVS = %w(prod stg int tint kint test jint) class GceHelper def self.list_hosts() @@ -105,10 +106,7 @@ module OpenShift @inventory = 'inventory/hosts' if @inventory.nil? # This is used instead of passing in the json on the cli to avoid quoting problems - tmpfile = Tempfile.new('extra_vars') - tmpfile.write(@extra_vars.to_json) - tmpfile.sync() - tmpfile.close() + tmpfile = Tempfile.open('extra_vars') { |f| f.write(@extra_vars.to_json); f} cmds = [] @@ -121,18 +119,21 @@ module OpenShift # We need pipelining off so that we can do sudo to enable the root account cmds << %Q[export ANSIBLE_SSH_PIPELINING='#{@pipelining.to_s}'] - - ssh_key_arg = %q[--private-key=~/.ssh/mmcgrath_libra] if File.file?(ENV['HOME']+'/.ssh/mmcgrath_libra.pem') - - cmds << %Q[time -p ansible-playbook -i #{@inventory} #{@verbosity} #{playbook} #{ssh_key_arg} --extra-vars '@#{tmpfile.path}'] + cmds << %Q[time -p ansible-playbook -i #{@inventory} #{@verbosity} #{playbook} --extra-vars '@#{tmpfile.path}'] cmd = cmds.join(' ; ') - unless system(cmd) - puts %Q[Following command failed with exit code: #{$?.exitstatus}\n#{cmd}] - puts %Q[extra_vars: #{@extra_vars.to_json}] + stdout, stderr, status = Open3.capture3(cmd) + if 0 != status.exitstatus + raise %Q[Following command failed with exit code: #{status.exitstatus} +#{cmd} +extra_vars: #{@extra_vars.to_json} +stdout: #{stdout} +stderr: #{stderr} +] end - tmpfile.unlink + ensure + tmpfile.unlink if tmpfile end def merge_extra_vars_file(file) @@ -165,9 +166,17 @@ module OpenShift ah.inventory = 'inventory/gce/gce.py' return ah end + + def ignore_bug_6407 + puts + puts %q[ .---- Spurious warning "It is unnecessary to use '{{' in loops" (ansible bug 6407) ----.] + puts %q[ V V] + end + end class GceCommand < Thor + option :type, :required => true, :enum => LaunchHelper.get_gce_host_types, :desc => 'The host type of the new instances.' option :env, :required => true, :aliases => '-e', :enum => OpenShift::Ops::SUPPORTED_ENVS, @@ -199,14 +208,12 @@ module OpenShift puts puts 'Creating instance(s) in GCE...' - puts - puts %q[ .---- Spurious warning "It is unnecessary to use '{{' in loops" (ansible bug 6407) ----.] - puts %q[ V V] - + ah.ignore_bug_6407 ah.run_playbook("playbooks/gce/#{options[:type]}/launch.yml") end + option :name, :required => false, :type => :string, :desc => 'The name of the instance to configure.' option :env, :required => false, :aliases => '-e', :enum => OpenShift::Ops::SUPPORTED_ENVS, @@ -238,13 +245,49 @@ module OpenShift puts puts "Configuring #{options[:type]} instance(s) in GCE..." - puts - puts " .---- Disregard this (ansible bug 6407) ----." - puts " V V" + ah.ignore_bug_6407 ah.run_playbook("playbooks/gce/#{host_type}/config.yml") end + option :name, :required => false, :type => :string, + :desc => 'The name of the instance to terminate.' + option :env, :required => false, :aliases => '-e', :enum => OpenShift::Ops::SUPPORTED_ENVS, + :desc => 'The environment of the new instances.' + option :type, :required => false, :enum => LaunchHelper.get_gce_host_types, + :desc => 'The type of the instances to configure.' + option :confirm, :required => false, :type => :boolean, + :desc => 'Terminate without interactive confirmation' + desc "terminate", 'Terminate instances' + def terminate() + ah = AnsibleHelper.for_gce() + + abort 'Error: you can\'t specify both --name and --type' unless options[:type].nil? || options[:name].nil? + + abort 'Error: you can\'t specify both --name and --env' unless options[:env].nil? || options[:name].nil? + + host_type = nil + if options[:name] + details = GceHelper.get_host_details(options[:name]) + ah.extra_vars['oo_host_group_exp'] = options[:name] + ah.extra_vars['oo_env'] = details['env'] + host_type = details['host-type'] + elsif options[:type] && options[:env] + oo_env_host_type_tag = GceHelper.generate_env_host_type_tag_name(options[:env], options[:type]) + ah.extra_vars['oo_host_group_exp'] = "groups['#{oo_env_host_type_tag}']" + ah.extra_vars['oo_env'] = options[:env] + host_type = options[:type] + else + abort 'Error: you need to specify either --name or (--type and --env)' + end + + puts + puts "Terminating #{options[:type]} instance(s) in GCE..." + ah.ignore_bug_6407 + + ah.run_playbook("playbooks/gce/#{host_type}/terminate.yml") + end + desc "list", "Lists instances." def list() hosts = GceHelper.list_hosts() diff --git a/cluster.sh b/cluster.sh new file mode 100755 index 000000000..cd8ba2d87 --- /dev/null +++ b/cluster.sh @@ -0,0 +1,86 @@ +#!/bin/bash -eu + +MINIONS=3 +MASTERS=1 +PROVIDER=gce + +# @formatter:off +function usage { + cat 1>&2 <<-EOT + ${0} : [create|destroy|update|list] {GCE environment tag} + Supported environment tags: + $(grep 'SUPPORTED_ENVS.*=' ./cloud.rb) +EOT +} +# @formatter:on + +function create_cluser { + for (( i = 0; i < $MINIONS; i ++ )); do + ./cloud.rb "${PROVIDER}" launch -e "${ENV}" --type=os3-minion + done + + for (( i = 0; i < $MASTERS; i ++ )); do + ./cloud.rb "${PROVIDER}" launch -e "${ENV}" --type=os3-master + done + update_cluster + echo -n "\nCreated ${MASTERS} masters and ${MINIONS} minions using ${PROVIDER} provider\n" +} + +function update_cluster { + for (( i = 0; i < $MINIONS; i ++ )); do + ./cloud.rb "${PROVIDER}" config -e "${ENV}" --type=os3-minion + done + + for (( i = 0; i < $MASTERS; i ++ )); do + ./cloud.rb "${PROVIDER}" config -e "${ENV}" --type=os3-master + done +} + +function terminate_cluster { + for (( i = 0; i < $MINIONS; i ++ )); do + ./cloud.rb "${PROVIDER}" terminate -e "${ENV}" --type=os3-minion + done + + for (( i = 0; i < $MASTERS; i ++ )); do + ./cloud.rb "${PROVIDER}" terminate -e "${ENV}" --type=os3-master + done +} + +[ -f ./cloud.rb ] || (echo 1 > 2 'Cannot find ./cloud.rb' && exit 1) + +while getopts ':p:m:n:' flag; do + case "${flag}" in + p) PROVIDER="${OPTARG}" ;; + m) MASTERS="${OPTARG}" ;; + n) MINIONS="${OPTARG}" ;; + *) echo -n 2>&1 "unsupported option $OPTARG\n" + usage + exit 1 ;; + esac +done +shift $((OPTIND-1)) + +[ -z "${1:-}" ] && (usage; exit 1) + +case "${1}" in + 'create') + [ -z "${2:-''}" ] && (usage; exit 1) + ENV="${2}" + create_cluser ;; + '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/playbooks/gce/os3-master/terminate.yml b/playbooks/gce/os3-master/terminate.yml new file mode 100644 index 000000000..8a618ecb8 --- /dev/null +++ b/playbooks/gce/os3-master/terminate.yml @@ -0,0 +1,18 @@ +- name: "populate oo_hosts_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_hosts_to_terminate" + with_items: "{{ oo_host_group_exp | default('') }}" + when: oo_host_group_exp is defined + +- name: "Terminate instances" + hosts: localhost + connection: local + tasks: + - name: Terminate master instances + local_action: + module: gce + state: 'absent' + instance_names: "{{ oo_hosts_to_terminate }}" diff --git a/playbooks/gce/os3-minion/terminate.yml b/playbooks/gce/os3-minion/terminate.yml new file mode 100644 index 000000000..8a618ecb8 --- /dev/null +++ b/playbooks/gce/os3-minion/terminate.yml @@ -0,0 +1,18 @@ +- name: "populate oo_hosts_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_hosts_to_terminate" + with_items: "{{ oo_host_group_exp | default('') }}" + when: oo_host_group_exp is defined + +- name: "Terminate instances" + hosts: localhost + connection: local + tasks: + - name: Terminate master instances + local_action: + module: gce + state: 'absent' + instance_names: "{{ oo_hosts_to_terminate }}" -- cgit v1.2.3 From a24bcdcb743e844d9ad738b78cc98dcd9a778659 Mon Sep 17 00:00:00 2001 From: Jhon Honce Date: Mon, 29 Sep 2014 09:33:41 -0700 Subject: WIP Infra - Update reporting in cloud.rb --- cloud.rb | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/cloud.rb b/cloud.rb index 840742b8c..0a6097ee7 100755 --- a/cloud.rb +++ b/cloud.rb @@ -8,6 +8,10 @@ require 'fileutils' require 'parseconfig' require 'open3' +# Don't buffer output to the client +STDOUT.sync = true +STDERR.sync = true + SCRIPT_DIR = File.expand_path(File.dirname(__FILE__)) module OpenShift @@ -102,6 +106,10 @@ module OpenShift @pipelining = true end + def all_eof(files) + files.find { |f| !f.eof }.nil? + end + def run_playbook(playbook) @inventory = 'inventory/hosts' if @inventory.nil? @@ -123,13 +131,15 @@ module OpenShift cmd = cmds.join(' ; ') - stdout, stderr, status = Open3.capture3(cmd) - if 0 != status.exitstatus - raise %Q[Following command failed with exit code: #{status.exitstatus} + pid = spawn(cmd, :out => $stdout, :err => $stderr, :close_others => true) + _, state = Process.wait2(pid) + + if 0 != state.exitstatus + raise %Q[Warning failed with exit code: #{state.exitstatus} + #{cmd} + extra_vars: #{@extra_vars.to_json} -stdout: #{stdout} -stderr: #{stderr} ] end ensure -- cgit v1.2.3 From bc5cd79739f24767120e48ee1fd8680b20e7367b Mon Sep 17 00:00:00 2001 From: Jhon Honce Date: Mon, 29 Sep 2014 15:12:27 -0700 Subject: terminate playbook --- cluster.sh | 22 ++++++++----------- playbooks/gce/os3-master/terminate.yml | 37 +++++++++++++++++++++++++------- playbooks/gce/os3-minion/terminate.yml | 39 ++++++++++++++++++++++++++-------- 3 files changed, 68 insertions(+), 30 deletions(-) diff --git a/cluster.sh b/cluster.sh index cd8ba2d87..50fbe66eb 100755 --- a/cluster.sh +++ b/cluster.sh @@ -8,6 +8,7 @@ PROVIDER=gce function usage { cat 1>&2 <<-EOT ${0} : [create|destroy|update|list] {GCE environment tag} + Supported environment tags: $(grep 'SUPPORTED_ENVS.*=' ./cloud.rb) EOT @@ -23,7 +24,7 @@ function create_cluser { ./cloud.rb "${PROVIDER}" launch -e "${ENV}" --type=os3-master done update_cluster - echo -n "\nCreated ${MASTERS} masters and ${MINIONS} minions using ${PROVIDER} provider\n" + echo -e "\nCreated ${MASTERS} masters and ${MINIONS} minions using ${PROVIDER} provider\n" } function update_cluster { @@ -37,23 +38,18 @@ function update_cluster { } function terminate_cluster { - for (( i = 0; i < $MINIONS; i ++ )); do - ./cloud.rb "${PROVIDER}" terminate -e "${ENV}" --type=os3-minion - done - - for (( i = 0; i < $MASTERS; i ++ )); do - ./cloud.rb "${PROVIDER}" terminate -e "${ENV}" --type=os3-master - done + #./cloud.rb "${PROVIDER}" terminate -e "${ENV}" --type=os3-master + ./cloud.rb "${PROVIDER}" terminate -e "${ENV}" --type=os3-minion } -[ -f ./cloud.rb ] || (echo 1 > 2 'Cannot find ./cloud.rb' && exit 1) +[ -f ./cloud.rb ] || (echo 1>&2 'Cannot find ./cloud.rb' && exit 1) while getopts ':p:m:n:' flag; do case "${flag}" in p) PROVIDER="${OPTARG}" ;; m) MASTERS="${OPTARG}" ;; n) MINIONS="${OPTARG}" ;; - *) echo -n 2>&1 "unsupported option $OPTARG\n" + *) echo -e 2>&1 "unsupported option $OPTARG\n" usage exit 1 ;; esac @@ -64,15 +60,15 @@ shift $((OPTIND-1)) case "${1}" in 'create') - [ -z "${2:-''}" ] && (usage; exit 1) + [ -z "${2:-}" ] && (usage; exit 1) ENV="${2}" create_cluser ;; 'update') - [ -z "${2:-''}" ] && (usage; exit 1) + [ -z "${2:-}" ] && (usage; exit 1) ENV="${2}" update_cluster ;; 'terminate') - [ -z "${2:-''}" ] && (usage; exit 1) + [ -z "${2:-}" ] && (usage; exit 1) ENV="${2}" terminate_cluster ;; 'list') ./cloud.rb "${PROVIDER}" list ;; diff --git a/playbooks/gce/os3-master/terminate.yml b/playbooks/gce/os3-master/terminate.yml index 8a618ecb8..b6a1b38e4 100644 --- a/playbooks/gce/os3-master/terminate.yml +++ b/playbooks/gce/os3-master/terminate.yml @@ -2,17 +2,38 @@ hosts: localhost gather_facts: no tasks: - - name: Evaluate oo_host_group_exp if it's set - add_host: "name={{ item }} groups=oo_hosts_to_terminate" - with_items: "{{ oo_host_group_exp | default('') }}" - when: oo_host_group_exp is defined + - debug: var=oo_host_group_exp -- name: "Terminate instances" + - name: Evaluate oo_host_group_exp if it's set + add_host: "name={{ item }} groups=oo_hosts_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 instances hosts: localhost connection: local tasks: - name: Terminate master instances - local_action: - module: gce + gce: + service_account_email: "{{ gce_service_account_email }}" + pem_file: "{{ gce_pem_file }}" + project_id: "{{ gce_project_id }}" state: 'absent' - instance_names: "{{ oo_hosts_to_terminate }}" + instance_names: "{{ groups['oo_hosts_to_terminate'] }}" + disks: "{{ groups['oo_hosts_to_terminate'] }}" + register: gce + + - debug: var=gce + +# - name: Remove disks of instances +# gce_pd: +# service_account_email: "{{ gce_service_account_email }}" +# pem_file: "{{ gce_pem_file }}" +# project_id: "{{ gce_project_id }}" +# name: "{{ item }}" +# state: deleted +# with_items: gce.instance_names + diff --git a/playbooks/gce/os3-minion/terminate.yml b/playbooks/gce/os3-minion/terminate.yml index 8a618ecb8..d31f175e1 100644 --- a/playbooks/gce/os3-minion/terminate.yml +++ b/playbooks/gce/os3-minion/terminate.yml @@ -2,17 +2,38 @@ hosts: localhost gather_facts: no tasks: - - name: Evaluate oo_host_group_exp if it's set - add_host: "name={{ item }} groups=oo_hosts_to_terminate" - with_items: "{{ oo_host_group_exp | default('') }}" - when: oo_host_group_exp is defined + - debug: var=oo_host_group_exp -- name: "Terminate instances" + - name: Evaluate oo_host_group_exp if it's set + add_host: "name={{ item }} groups=oo_hosts_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 instances hosts: localhost connection: local tasks: - - name: Terminate master instances - local_action: - module: gce + - name: Terminate minion instances + gce: + service_account_email: "{{ gce_service_account_email }}" + pem_file: "{{ gce_pem_file }}" + project_id: "{{ gce_project_id }}" state: 'absent' - instance_names: "{{ oo_hosts_to_terminate }}" + instance_names: "{{ groups['oo_hosts_to_terminate'] }}" + disks: "{{ groups['oo_hosts_to_terminate'] }}" + register: gce + + - debug: var=gce + +# - name: Remove disks of instances +# gce_pd: +# service_account_email: "{{ gce_service_account_email }}" +# pem_file: "{{ gce_pem_file }}" +# project_id: "{{ gce_project_id }}" +# name: "{{ item }}" +# state: deleted +# with_items: gce.instance_names + -- cgit v1.2.3