From 81628f94bad4b303212bf77752f62c03728e0168 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Tue, 17 Mar 2015 11:09:12 -0400 Subject: Fix hostname handling - always set hostname if hostname does not match openshift_hostname - Use local IP instead of public IP as hostname for workaround --- roles/openshift_common/README.md | 1 - roles/openshift_common/defaults/main.yml | 3 +-- roles/openshift_common/tasks/main.yml | 6 ++---- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/roles/openshift_common/README.md b/roles/openshift_common/README.md index c2ae609ff..79076ed19 100644 --- a/roles/openshift_common/README.md +++ b/roles/openshift_common/README.md @@ -14,7 +14,6 @@ Role Variables | Name | Default value | | |-------------------------------|------------------------------|----------------------------------------| -| openshift_bind_ip | ansible_default_ipv4.address | IP to use for local binding | | openshift_debug_level | 0 | Global openshift debug log verbosity | | openshift_hostname_workaround | True | Workaround needed to set hostname to IP address | | openshift_hostname | openshift_public_ip if openshift_hostname_workaround else ansible_fqdn | hostname to use for this instance | diff --git a/roles/openshift_common/defaults/main.yml b/roles/openshift_common/defaults/main.yml index a541591fb..eb6edbc03 100644 --- a/roles/openshift_common/defaults/main.yml +++ b/roles/openshift_common/defaults/main.yml @@ -1,8 +1,7 @@ --- -openshift_bind_ip: "{{ ansible_default_ipv4.address }}" openshift_debug_level: 0 # TODO: Once openshift stops resolving hostnames for node queries remove # this... openshift_hostname_workaround: true -openshift_hostname: "{{ openshift_public_ip if openshift_hostname_workaround else ansible_fqdn }}" +openshift_hostname: "{{ ansible_default_ipv4.address if openshift_hostname_workaround else ansible_fqdn }}" diff --git a/roles/openshift_common/tasks/main.yml b/roles/openshift_common/tasks/main.yml index 728bba4e4..07737a71f 100644 --- a/roles/openshift_common/tasks/main.yml +++ b/roles/openshift_common/tasks/main.yml @@ -1,8 +1,6 @@ --- -# fixme: Once openshift stops resolving hostnames for node queries remove this... -- name: Set hostname to IP Addr (WORKAROUND) - hostname: name={{ openshift_bind_ip }} - when: openshift_hostname_workaround +- name: Set hostname + hostname: name={{ openshift_hostname }} - name: Configure local facts file file: path=/etc/ansible/facts.d/ state=directory mode=0750 -- cgit v1.2.3 From 7035459d20dd2d278b0a0e6ff96421639f6e0e34 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Wed, 18 Mar 2015 00:05:51 -0400 Subject: Register node fixes - Set --hostname flag in node config in openshift_node role - Support some additional node attributes in openshift_node role - podCIDR - labels - annotations - Support both output types for openshift ex config view in openshift_register_node module - Support multiple api versions in openshift_register_node module - Support additional attributes in openshift_register_node module - annotations - labels - pod_cidr - external_ips (v1beta3, will be available after next kube rebase) - internal_ips (v1beta3, will be available after next kube rebase) - hostnames (v1beta3, will be available after next kube rebase) - external_id (v1beta3, will be available after next kube rebase) --- roles/openshift_node/defaults/main.yml | 8 +- .../library/openshift_register_node.py | 453 ++++++++++++++------- roles/openshift_node/tasks/main.yml | 14 +- 3 files changed, 333 insertions(+), 142 deletions(-) diff --git a/roles/openshift_node/defaults/main.yml b/roles/openshift_node/defaults/main.yml index c45524f16..e4d5ebfee 100644 --- a/roles/openshift_node/defaults/main.yml +++ b/roles/openshift_node/defaults/main.yml @@ -5,6 +5,8 @@ os_firewall_allow: - service: OpenShift kubelet port: 10250/tcp openshift_node_resources: - capacity: - cpu: - memory: + cpu: + memory: + cidr: +openshift_node_labels: {} +openshift_node_annotations: {} diff --git a/roles/openshift_node/library/openshift_register_node.py b/roles/openshift_node/library/openshift_register_node.py index 63079e59b..4922585d7 100644 --- a/roles/openshift_node/library/openshift_register_node.py +++ b/roles/openshift_node/library/openshift_register_node.py @@ -6,78 +6,315 @@ import os import multiprocessing import socket from subprocess import check_output, Popen +from decimal import * DOCUMENTATION = ''' --- -module: openshift_register_node -short_description: This module registers an openshift-node with an openshift-master -author: Jason DeTiberus -requirements: [ openshift-node ] -notes: Node resources can be specified using either the resources option or the following options: cpu, memory +module: kubernetes_register_node +short_description: Registers a kubernetes node with a master +description: + - Registers a kubernetes node with a master options: name: + default: null description: - - id for this node (usually the node fqdn) + - Identifier for this node (usually the node fqdn). required: true - hostIP: + api_verison: + choices: ['v1beta1', 'v1beta3'] + default: 'v1beta1' description: - - ip address for this node + - Kubernetes API version to use + required: true + host_ip: + default: null + description: + - IP Address to associate with the node when registering. + Available in the following API versions: v1beta1. required: false - cpu: + hostnames: + default: [] description: - - number of CPUs for this node + - Valid hostnames for this node. Available in the following API + versions: v1beta3. required: false - default: number of logical CPUs detected - memory: + external_ips: + default: [] description: - - Memory available for this node in bytes + - External IP Addresses for this node. Available in the following API + versions: v1beta3. required: false - default: 80% MemTotal - resources: + internal_ips: + default: [] description: - - A json string representing Node resources + - Internal IP Addresses for this node. Available in the following API + versions: v1beta3. + required: false + cpu: + default: null + description: + - Number of CPUs to allocate for this node. If not provided, then + the node will be registered to advertise the number of logical + CPUs available. When using the v1beta1 API, you must specify the + CPU count as a floating point number with no more than 3 decimal + places. API version v1beta3 and newer accepts arbitrary float + values. + required: false + memory: + default: null + description: + - Memory available for this node. If not provided, then the node + will be registered to advertise 80% of MemTotal as available + memory. When using the v1beta1 API, you must specify the memory + size in bytes. API version v1beta3 and newer accepts binary SI + and decimal SI values. required: false ''' EXAMPLES = ''' # Minimal node registration - openshift_register_node: name=ose3.node.example.com -# Node registration with all options (using cpu and memory options) +# Node registration using the v1beta1 API and assigning 1 CPU core and 10 GB of +# Memory - openshift_register_node: name: ose3.node.example.com + api_version: v1beta1 hostIP: 192.168.1.1 - apiVersion: v1beta1 cpu: 1 - memory: 1073741824 + memory: 500000000 -# Node registration with all options (using resources option) +# Node registration using the v1beta3 API, setting an alternate hostname, +# internalIP, externalIP and assigning 3.5 CPU cores and 1 TiB of Memory - openshift_register_node: name: ose3.node.example.com - hostIP: 192.168.1.1 - apiVersion: v1beta1 - resources: - capacity: - cpu: 1 - memory: 1073741824 + api_version: v1beta3 + external_ips: ['192.168.1.5'] + internal_ips: ['10.0.0.5'] + hostnames: ['ose2.node.internal.local'] + cpu: 3.5 + memory: 1Ti ''' + +class ClientConfigException(Exception): + pass + +class ClientConfig: + def __init__(self, client_opts, module): + _, output, error = module.run_command(["/usr/bin/openshift", "ex", + "config", "view", "-o", + "json"] + client_opts, + check_rc = True) + self.config = json.loads(output) + + if not (bool(self.config['clusters']) or + bool(self.config['contexts']) or + bool(self.config['current-context']) or + bool(self.config['users'])): + raise ClientConfigException(msg="Client config missing required " \ + "values", + output=output) + + def current_context(self): + return self.config['current-context'] + + def section_has_value(self, section_name, value): + section = self.config[section_name] + if isinstance(section, dict): + return value in section + else: + val = next((item for item in section + if item['name'] == value), None) + return val is not None + + def has_context(self, context): + return self.section_has_value('contexts', context) + + def has_user(self, user): + return self.section_has_value('users', user) + + def has_cluster(self, cluster): + return self.section_has_value('clusters', cluster) + + def get_value_for_context(self, context, attribute): + contexts = self.config['contexts'] + if isinstance(contexts, dict): + return contexts[context][attribute] + else: + return next((c['context'][attribute] for c in contexts + if c['name'] == context), None) + + def get_user_for_context(self, context): + return self.get_value_for_context(context, 'user') + + def get_cluster_for_context(self, context): + return self.get_value_for_context(context, 'cluster') + +class Util: + @staticmethod + def getLogicalCores(): + return multiprocessing.cpu_count() + + @staticmethod + def getMemoryPct(pct): + with open('/proc/meminfo', 'r') as mem: + for line in mem: + entries = line.split() + if str(entries.pop(0)) == 'MemTotal:': + mem_total_kb = Decimal(entries.pop(0)) + mem_capacity_kb = mem_total_kb * Decimal(pct) + return str(mem_capacity_kb.to_integral_value() * 1024) + + return "" + + @staticmethod + def remove_empty_elements(mapping): + if isinstance(mapping, dict): + m = mapping.copy() + for key, val in mapping.iteritems(): + if not val: + del m[key] + return m + else: + return mapping + +class NodeResources: + def __init__(self, version, cpu=None, memory=None): + if version == 'v1beta1': + self.resources = dict(capacity=dict()) + self.resources['capacity']['cpu'] = cpu if cpu else Util.getLogicalCores() + self.resources['capacity']['memory'] = memory if cpu else Util.getMemoryPct(.75) + + def get_resources(self): + return Util.remove_empty_elements(self.resources) + +class NodeSpec: + def __init__(self, version, cpu=None, memory=None, cidr=None, externalID=None): + if version == 'v1beta3': + self.spec = dict(podCIDR=cidr, externalID=externalID, + capacity=dict()) + self.spec['capacity']['cpu'] = cpu if cpu else Util.getLogicalCores() + self.spec['capacity']['memory'] = memory if memory else Util.getMemoryPct(.75) + + def get_spec(self): + return Util.remove_empty_elements(self.spec) + +class NodeStatus: + def addAddresses(self, addressType, addresses): + addressList = [] + for address in addresses: + addressList.append(dict(type=addressType, address=address)) + return addressList + + def __init__(self, version, externalIPs = [], internalIPs = [], + hostnames = []): + if version == 'v1beta3': + self.status = dict(addresses = addAddresses('ExternalIP', + externalIPs) + + addAddresses('InternalIP', + internalIPs) + + addAddresses('Hostname', + hostnames)) + + def get_status(self): + return Util.remove_empty_elements(self.status) + +class Node: + def __init__(self, module, client_opts, version='v1beta1', name=None, + hostIP = None, hostnames=[], externalIPs=[], internalIPs=[], + cpu=None, memory=None, labels=dict(), annotations=dict(), + podCIDR=None, externalID=None): + self.module = module + self.client_opts = client_opts + if version == 'v1beta1': + self.node = dict(id = name, + kind = 'Node', + apiVersion = version, + hostIP = hostIP, + resources = NodeResources(version, cpu, memory), + cidr = podCIDR, + labels = labels, + annotations = annotations + ) + elif version == 'v1beta3': + metadata = dict(name = name, + labels = labels, + annotations = annotations + ) + self.node = dict(kind = 'Node', + apiVersion = version, + metadata = metadata, + spec = NodeSpec(version, cpu, memory, podCIDR, + externalID), + status = NodeStatus(version, externalIPs, + internalIPs, hostnames), + ) + + def get_name(self): + if self.node['apiVersion'] == 'v1beta1': + return self.node['id'] + elif self.node['apiVersion'] == 'v1beta3': + return self.node['name'] + + def get_node(self): + node = self.node.copy() + if self.node['apiVersion'] == 'v1beta1': + node['resources'] = self.node['resources'].get_resources() + elif self.node['apiVersion'] == 'v1beta3': + node['spec'] = self.node['spec'].get_spec() + node['status'] = self.node['status'].get_status() + return Util.remove_empty_elements(node) + + def exists(self): + _, output, error = self.module.run_command(["/usr/bin/osc", "get", + "nodes"] + self.client_opts, + check_rc = True) + if re.search(self.module.params['name'], output, re.MULTILINE): + return True + return False + + def create(self): + cmd = ['/usr/bin/osc'] + self.client_opts + ['create', 'node', '-f', '-'] + rc, output, error = self.module.run_command(cmd, + data=self.module.jsonify(self.get_node())) + if rc != 0: + if re.search("minion \"%s\" already exists" % self.get_name(), + error): + self.module.exit_json(changed=False, + msg="node definition already exists", + node=self.get_node()) + else: + self.module.fail_json(msg="Node creation failed.", rc=rc, + output=output, error=error, + node=self.get_node()) + else: + return True + def main(): module = AnsibleModule( argument_spec = dict( - name = dict(required = True), - hostIP = dict(), - apiVersion = dict(), - cpu = dict(), - memory = dict(), - resources = dict(), - client_config = dict(), - client_cluster = dict(default = 'master'), - client_context = dict(default = 'master'), - client_user = dict(default = 'admin') + name = dict(required = True, type = 'str'), + host_ip = dict(type = 'str'), + hostnames = dict(type = 'list', default = []), + external_ips = dict(type = 'list', default = []), + internal_ips = dict(type = 'list', default = []), + api_version = dict(type = 'str', default = 'v1beta1', # TODO: after kube rebase, we can default to v1beta3 + choices = ['v1beta1', 'v1beta3']), + cpu = dict(type = 'str'), + memory = dict(type = 'str'), + labels = dict(type = 'dict', default = {}), # TODO: needs documented + annotations = dict(type = 'dict', default = {}), # TODO: needs documented + pod_cidr = dict(type = 'str'), # TODO: needs documented + external_id = dict(type = 'str'), # TODO: needs documented + client_config = dict(type = 'str'), # TODO: needs documented + client_cluster = dict(type = 'str', default = 'master'), # TODO: needs documented + client_context = dict(type = 'str', default = 'master'), # TODO: needs documented + client_user = dict(type = 'str', default = 'admin') # TODO: needs documented ), mutually_exclusive = [ - ['resources', 'cpu'], - ['resources', 'memory'] + ['host_ip', 'external_ips'], + ['host_ip', 'internal_ips'], + ['host_ip', 'hostnames'], ], supports_check_mode=True ) @@ -93,119 +330,61 @@ def main(): client_opts.append("--kubeconfig=%s" % module.params['client_config']) try: - output = check_output(["/usr/bin/openshift", "ex", "config", "view", - "-o", "json"] + client_opts, - stderr=subprocess.STDOUT) - except subprocess.CalledProcessError as e: - module.fail_json(msg="Failed to get client configuration", - command=e.cmd, returncode=e.returncode, output=e.output) - - config = json.loads(output) - if not (bool(config['clusters']) or bool(config['contexts']) or - bool(config['current-context']) or bool(config['users'])): - module.fail_json(msg="Client config missing required values", - output=output) + config = ClientConfig(client_opts, module) + except ClientConfigException as e: + module.fail_json(msg="Failed to get client configuration", exception=e) client_context = module.params['client_context'] - if client_context: - config_context = next((context for context in config['contexts'] - if context['name'] == client_context), None) - if not config_context: - module.fail_json(msg="Context %s not found in client config" % - client_context) - if not config['current-context'] or config['current-context'] != client_context: + if config.has_context(client_context): + if client_context != config.current_context(): client_opts.append("--context=%s" % client_context) + else: + module.fail_json(msg="Context %s not found in client config" % + client_context) client_user = module.params['client_user'] - if client_user: - config_user = next((user for user in config['users'] - if user['name'] == client_user), None) - if not config_user: - module.fail_json(msg="User %s not found in client config" % - client_user) - if client_user != config_context['context']['user']: + if config.has_user(client_user): + if client_user != config.get_user_for_context(client_context): client_opts.append("--user=%s" % client_user) + else: + module.fail_json(msg="User %s not found in client config" % + client_user) client_cluster = module.params['client_cluster'] - if client_cluster: - config_cluster = next((cluster for cluster in config['clusters'] - if cluster['name'] == client_cluster), None) - if not client_cluster: - module.fail_json(msg="Cluster %s not found in client config" % - client_cluster) - if client_cluster != config_context['context']['cluster']: + if config.has_cluster(client_cluster): + if client_cluster != config.get_cluster_for_context(client_cluster): client_opts.append("--cluster=%s" % client_cluster) + else: + module.fail_json(msg="Cluster %s not found in client config" % + client_cluster) - node_def = dict( - id = module.params['name'], - kind = 'Node', - apiVersion = 'v1beta1', - resources = dict( - capacity = dict() - ) - ) - - for key, value in module.params.iteritems(): - if key in ['cpu', 'memory']: - node_def['resources']['capacity'][key] = value - elif key == 'name': - node_def['id'] = value - elif key != 'client_config': - if value: - node_def[key] = value + # TODO: provide sane defaults for some (like hostname, externalIP, + # internalIP, etc) + node = Node(module, client_opts, module.params['api_version'], + module.params['name'], module.params['host_ip'], + module.params['hostnames'], module.params['external_ips'], + module.params['internal_ips'], module.params['cpu'], + module.params['memory'], module.params['labels'], + module.params['annotations'], module.params['pod_cidr'], + module.params['external_id']) - if not node_def['resources']['capacity']['cpu']: - node_def['resources']['capacity']['cpu'] = multiprocessing.cpu_count() - - if not node_def['resources']['capacity']['memory']: - with open('/proc/meminfo', 'r') as mem: - for line in mem: - entries = line.split() - if str(entries.pop(0)) == 'MemTotal:': - mem_total_kb = int(entries.pop(0)) - mem_capacity = int(mem_total_kb * 1024 * .75) - node_def['resources']['capacity']['memory'] = mem_capacity - break - - try: - output = check_output(["/usr/bin/osc", "get", "nodes"] + client_opts, - stderr=subprocess.STDOUT) - except subprocess.CalledProcessError as e: - module.fail_json(msg="Failed to get node list", command=e.cmd, - returncode=e.returncode, output=e.output) - - if re.search(module.params['name'], output, re.MULTILINE): - module.exit_json(changed=False, node_def=node_def) + # TODO: attempt to support changing node settings where possible and/or + # modifying node resources + if node.exists(): + module.exit_json(changed=False, node=node.get_node()) elif module.check_mode: - module.exit_json(changed=True, node_def=node_def) - - config_def = dict( - metadata = dict( - name = "add-node-%s" % module.params['name'] - ), - kind = 'Config', - apiVersion = 'v1beta1', - items = [node_def] - ) - - p = Popen(["/usr/bin/osc"] + client_opts + ["create", "node"] + ["-f", "-"], - stdin=subprocess.PIPE, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, close_fds=True) - (out, err) = p.communicate(module.jsonify(config_def)) - ret = p.returncode - - if ret != 0: - if re.search("minion \"%s\" already exists" % module.params['name'], - err): - module.exit_json(changed=False, - msg="node definition already exists", config_def=config_def) + module.exit_json(changed=True, node=node.get_node()) + else: + if node.create(): + module.exit_json(changed=True, + msg="Node created successfully", + node=node.get_node()) else: - module.fail_json(msg="Node creation failed.", ret=ret, out=out, - err=err, config_def=config_def) + module.fail_json(msg="Unknown error creating node", + node=node.get_node()) - module.exit_json(changed=True, out=out, err=err, ret=ret, - node_def=config_def) # import module snippets from ansible.module_utils.basic import * -main() +if __name__ == '__main__': + main() diff --git a/roles/openshift_node/tasks/main.yml b/roles/openshift_node/tasks/main.yml index 6721c7401..e380ba1fb 100644 --- a/roles/openshift_node/tasks/main.yml +++ b/roles/openshift_node/tasks/main.yml @@ -21,7 +21,7 @@ lineinfile: dest: /etc/sysconfig/openshift-node regexp: '^OPTIONS=' - line: "OPTIONS=\"--master=https://{{ openshift_master_ips[0] }}:8443 --loglevel={{ openshift_node_debug_level }}\"" + line: "OPTIONS=\"--master=https://{{ openshift_master_ips[0] }}:8443 --hostname={{ openshift_hostname }} --loglevel={{ openshift_node_debug_level }}\"" notify: - restart openshift-node @@ -75,4 +75,14 @@ - name: Register node (if not already registered) openshift_register_node: name: "{{ openshift_hostname }}" - resources: "{{ openshift_node_resources }}" + api_version: v1beta1 + cpu: "{{ openshift_node_resources.cpu }}" + memory: "{{ openshift_node_resources.memory }}" + pod_cidr: "{{ openshift_node_resources.cidr }}" + host_ip: "{{ ansible_default_ipv4.address }}" + labels: "{{ openshift_node_labels }}" + annotations: "{{ openshift_node_annotations }}" + # TODO: support customizing other attributes such as: client_config, + # client_cluster, client_context, client_user + # TODO: updated for v1beta3 changes after rebase: hostnames, external_ips, + # internal_ips, external_id -- cgit v1.2.3 From 8613b70503d2d1cbe57ddebc11919edeb26eaadc Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Wed, 18 Mar 2015 17:15:19 -0400 Subject: Rename repos role to openshift_repos - Rename repos role to openshift_repos - Make openshift_repos a dependency of openshift_common - Add README and metadata for openshift_repos - Playbook updates for role rename - Verify libselinux-python is installed, otherwise some of the bulit-in modules we use fail --- playbooks/aws/openshift-master/config.yml | 1 - playbooks/aws/openshift-node/config.yml | 3 +- playbooks/gce/openshift-master/config.yml | 1 - playbooks/gce/openshift-node/config.yml | 3 +- roles/openshift_common/README.md | 1 + roles/openshift_common/meta/main.yml | 1 + roles/openshift_repos/README.md | 38 +++++++++++++ roles/openshift_repos/defaults/main.yaml | 5 ++ .../files/online/RPM-GPG-KEY-redhat-beta | 61 +++++++++++++++++++++ .../files/online/RPM-GPG-KEY-redhat-release | 63 ++++++++++++++++++++++ .../files/online/epel7-kubernetes.repo | 6 +++ .../files/online/epel7-openshift.repo | 6 +++ .../files/online/oso-rhui-rhel-7-extras.repo | 23 ++++++++ .../files/online/oso-rhui-rhel-7-server.repo | 21 ++++++++ .../files/online/rhel-7-libra-candidate.repo | 11 ++++ roles/openshift_repos/meta/main.yml | 14 +++++ roles/openshift_repos/tasks/main.yaml | 46 ++++++++++++++++ roles/openshift_repos/templates/yum_repo.j2 | 15 ++++++ roles/openshift_repos/vars/main.yml | 2 + roles/repos/defaults/main.yaml | 5 -- roles/repos/files/online/RPM-GPG-KEY-redhat-beta | 61 --------------------- .../repos/files/online/RPM-GPG-KEY-redhat-release | 63 ---------------------- roles/repos/files/online/epel7-kubernetes.repo | 6 --- roles/repos/files/online/epel7-openshift.repo | 6 --- .../repos/files/online/oso-rhui-rhel-7-extras.repo | 23 -------- .../repos/files/online/oso-rhui-rhel-7-server.repo | 21 -------- .../repos/files/online/rhel-7-libra-candidate.repo | 11 ---- roles/repos/tasks/main.yaml | 41 -------------- roles/repos/templates/yum_repo.j2 | 15 ------ roles/repos/vars/main.yml | 2 - 30 files changed, 315 insertions(+), 260 deletions(-) create mode 100644 roles/openshift_repos/README.md create mode 100644 roles/openshift_repos/defaults/main.yaml create mode 100644 roles/openshift_repos/files/online/RPM-GPG-KEY-redhat-beta create mode 100644 roles/openshift_repos/files/online/RPM-GPG-KEY-redhat-release create mode 100644 roles/openshift_repos/files/online/epel7-kubernetes.repo create mode 100644 roles/openshift_repos/files/online/epel7-openshift.repo create mode 100644 roles/openshift_repos/files/online/oso-rhui-rhel-7-extras.repo create mode 100644 roles/openshift_repos/files/online/oso-rhui-rhel-7-server.repo create mode 100644 roles/openshift_repos/files/online/rhel-7-libra-candidate.repo create mode 100644 roles/openshift_repos/meta/main.yml create mode 100644 roles/openshift_repos/tasks/main.yaml create mode 100644 roles/openshift_repos/templates/yum_repo.j2 create mode 100644 roles/openshift_repos/vars/main.yml delete mode 100644 roles/repos/defaults/main.yaml delete mode 100644 roles/repos/files/online/RPM-GPG-KEY-redhat-beta delete mode 100644 roles/repos/files/online/RPM-GPG-KEY-redhat-release delete mode 100644 roles/repos/files/online/epel7-kubernetes.repo delete mode 100644 roles/repos/files/online/epel7-openshift.repo delete mode 100644 roles/repos/files/online/oso-rhui-rhel-7-extras.repo delete mode 100644 roles/repos/files/online/oso-rhui-rhel-7-server.repo delete mode 100644 roles/repos/files/online/rhel-7-libra-candidate.repo delete mode 100644 roles/repos/tasks/main.yaml delete mode 100644 roles/repos/templates/yum_repo.j2 delete mode 100644 roles/repos/vars/main.yml diff --git a/playbooks/aws/openshift-master/config.yml b/playbooks/aws/openshift-master/config.yml index 454cd6f24..3d6238360 100644 --- a/playbooks/aws/openshift-master/config.yml +++ b/playbooks/aws/openshift-master/config.yml @@ -31,7 +31,6 @@ vars_files: - vars.yml roles: - - repos - { role: openshift_master, openshift_node_ips: "{{ hostvars['localhost'].openshift_node_ips | default(['']) }}", diff --git a/playbooks/aws/openshift-node/config.yml b/playbooks/aws/openshift-node/config.yml index 9662168c4..d39ad781f 100644 --- a/playbooks/aws/openshift-node/config.yml +++ b/playbooks/aws/openshift-node/config.yml @@ -37,8 +37,6 @@ vars_files: - vars.yml roles: - - repos - - docker - { role: openshift_node, openshift_master_ips: "{{ hostvars['localhost'].openshift_master_ips | default(['']) }}", @@ -46,4 +44,5 @@ openshift_env: "{{ oo_env }}" openshift_public_ip: "{{ ec2_ip_address }}" } + - docker - os_env_extras diff --git a/playbooks/gce/openshift-master/config.yml b/playbooks/gce/openshift-master/config.yml index ae598b622..a74250d13 100644 --- a/playbooks/gce/openshift-master/config.yml +++ b/playbooks/gce/openshift-master/config.yml @@ -31,7 +31,6 @@ vars_files: - vars.yml roles: - - repos - { role: openshift_master, openshift_node_ips: "{{ hostvars['localhost'].openshift_node_ips | default(['']) }}", diff --git a/playbooks/gce/openshift-node/config.yml b/playbooks/gce/openshift-node/config.yml index 85f34e814..78047cf40 100644 --- a/playbooks/gce/openshift-node/config.yml +++ b/playbooks/gce/openshift-node/config.yml @@ -37,8 +37,6 @@ vars_files: - vars.yml roles: - - repos - - docker - { role: openshift_node, openshift_master_ips: "{{ hostvars['localhost'].openshift_master_ips | default(['']) }}", @@ -46,4 +44,5 @@ openshift_public_ip: "{{ gce_public_ip }}", openshift_env: "{{ oo_env }}", } + - docker - os_env_extras diff --git a/roles/openshift_common/README.md b/roles/openshift_common/README.md index c2ae609ff..a055cb032 100644 --- a/roles/openshift_common/README.md +++ b/roles/openshift_common/README.md @@ -25,6 +25,7 @@ Dependencies ------------ os_firewall +openshift_repos Example Playbook ---------------- diff --git a/roles/openshift_common/meta/main.yml b/roles/openshift_common/meta/main.yml index 88b7677d0..cee4dd337 100644 --- a/roles/openshift_common/meta/main.yml +++ b/roles/openshift_common/meta/main.yml @@ -13,3 +13,4 @@ galaxy_info: - cloud dependencies: - { role: os_firewall } +- { role: openshift_repos } diff --git a/roles/openshift_repos/README.md b/roles/openshift_repos/README.md new file mode 100644 index 000000000..6713e11fc --- /dev/null +++ b/roles/openshift_repos/README.md @@ -0,0 +1,38 @@ +OpenShift Repos +================ + +Configures repositories for an OpenShift installation + +Requirements +------------ + +A RHEL 7.1 host pre-configured with access to the rhel-7-server-rpms, +rhel-7-server-extra-rpms, and rhel-7-server-ose-beta-rpms repos. + +Role Variables +-------------- + +| Name | Default value | | +|-------------------------------|---------------|----------------------------------------------| +| openshift_deployment_type | online | Possible values enterprise, origin, online | +| openshift_additional_repos | {} | TODO | + +Dependencies +------------ + +None. + +Example Playbook +---------------- + +TODO + +License +------- + +Apache License, Version 2.0 + +Author Information +------------------ + +TODO diff --git a/roles/openshift_repos/defaults/main.yaml b/roles/openshift_repos/defaults/main.yaml new file mode 100644 index 000000000..6fe2bf621 --- /dev/null +++ b/roles/openshift_repos/defaults/main.yaml @@ -0,0 +1,5 @@ +--- +# TODO: once we are able to configure/deploy origin using the openshift roles, +# then we should default to origin +openshift_deployment_type: online +openshift_additional_repos: {} diff --git a/roles/openshift_repos/files/online/RPM-GPG-KEY-redhat-beta b/roles/openshift_repos/files/online/RPM-GPG-KEY-redhat-beta new file mode 100644 index 000000000..7b40671a4 --- /dev/null +++ b/roles/openshift_repos/files/online/RPM-GPG-KEY-redhat-beta @@ -0,0 +1,61 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.2.6 (GNU/Linux) + +mQINBEmkAzABEAC2/c7bP1lHQ3XScxbIk0LQWe1YOiibQBRLwf8Si5PktgtuPibT +kKpZjw8p4D+fM7jD1WUzUE0X7tXg2l/eUlMM4dw6XJAQ1AmEOtlwSg7rrMtTvM0A +BEtI7Km6fC6sU6RtBMdcqD1cH/6dbsfh8muznVA7UlX+PRBHVzdWzj6y8h84dBjo +gzcbYu9Hezqgj/lLzicqsSZPz9UdXiRTRAIhp8V30BD8uRaaa0KDDnD6IzJv3D9P +xQWbFM4Z12GN9LyeZqmD7bpKzZmXG/3drvfXVisXaXp3M07t3NlBa3Dt8NFIKZ0D +FRXBz5bvzxRVmdH6DtkDWXDPOt+Wdm1rZrCOrySFpBZQRpHw12eo1M1lirANIov7 +Z+V1Qh/aBxj5EUu32u9ZpjAPPNtQF6F/KjaoHHHmEQAuj4DLex4LY646Hv1rcv2i +QFuCdvLKQGSiFBrfZH0j/IX3/0JXQlZzb3MuMFPxLXGAoAV9UP/Sw/WTmAuTzFVm +G13UYFeMwrToOiqcX2VcK0aC1FCcTP2z4JW3PsWvU8rUDRUYfoXovc7eg4Vn5wHt +0NBYsNhYiAAf320AUIHzQZYi38JgVwuJfFu43tJZE4Vig++RQq6tsEx9Ftz3EwRR +fJ9z9mEvEiieZm+vbOvMvIuimFVPSCmLH+bI649K8eZlVRWsx3EXCVb0nQARAQAB +tDBSZWQgSGF0LCBJbmMuIChiZXRhIGtleSAyKSA8c2VjdXJpdHlAcmVkaGF0LmNv +bT6JAjYEEwECACAFAkpSM+cCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCT +ioDK8hVB6/9tEAC0+KmzeKceXQ/GTUoU6jy9vtkFCFrmv+c7ol4XpdTt0QhqBOwy +6m2mKWwmm8KfYfy0cADQ4y/EcoXl7FtFBwYmkCuEQGXhTDn9DvVjhooIq59LEMBQ +OW879RwwzRIZ8ebbjMUjDPF5MfPQqP2LBu9N4KvXlZp4voykwuuaJ+cbsKZR6pZ6 +0RQKPHKP+NgUFC0fff7XY9cuOZZWFAeKRhLN2K7bnRHKxp+kELWb6R9ZfrYwZjWc +MIPbTd1khE53L4NTfpWfAnJRtkPSDOKEGVlVLtLq4HEAxQt07kbslqISRWyXER3u +QOJj64D1ZiIMz6t6uZ424VE4ry9rBR0Jz55cMMx5O/ni9x3xzFUgH8Su2yM0r3jE +Rf24+tbOaPf7tebyx4OKe+JW95hNVstWUDyGbs6K9qGfI/pICuO1nMMFTo6GqzQ6 +DwLZvJ9QdXo7ujEtySZnfu42aycaQ9ZLC2DOCQCUBY350Hx6FLW3O546TAvpTfk0 +B6x+DV7mJQH7MGmRXQsE7TLBJKjq28Cn4tVp04PmybQyTxZdGA/8zY6pPl6xyVMH +V68hSBKEVT/rlouOHuxfdmZva1DhVvUC6Xj7+iTMTVJUAq/4Uyn31P1OJmA2a0PT +CAqWkbJSgKFccsjPoTbLyxhuMSNkEZFHvlZrSK9vnPzmfiRH0Orx3wYpMQ== +=21pb +-----END PGP PUBLIC KEY BLOCK----- +The following public key can be used to verify RPM packages built and +signed by Red Hat, Inc. for this beta using `rpm -K' using the GNU GPG +package. Questions about this key should be sent to security@redhat.com. + + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.0.6 (GNU/Linux) +Comment: For info see http://www.gnupg.org + +mQGiBDySTqsRBACzc7xuCIp10oj5B2PAV4XzDeVxprv/WTMreSNSK+iC0bEz0IBp +Vnn++qtyiXfH+bGIE9jqZgIEnpttWhUOaU5LhcLFzy+m8NWfngIFP9QfGmGAe9Gd +LFeAdhj4RmSG/vgr7vDd83Hz22dv403Ar/sliWO4vDOrMmZBG57WGYTWtwCgkMsi +UUQuJ6slbzKn82w+bYxOlL0EAIylWJGaTkKOTL5DqVR3ik9aT0Dt3FNVYiuhcKBe +II4E3KOIVA9kO8in1IZjx2gs6K2UV+GsoAVANdfKL7l9O+k+J8OxhE74oycvYJxW +QzCgXMZkNcvW5wyXwEMcr6TVd/5BGztcMw8oT3/l2MtAEG/vn1XaWToRSO1XDMDz ++AjUA/4m0mTkN8S4wjzJG8lqN7+quW3UOaiCe8J3SFrrrhE0XbY9cTJI/9nuXHU1 +VjqOSmXQYH2Db7UOroFTBiWhlAedA4O4yuK52AJnvSsHbnJSEmn9rpo5z1Q8F+qI +mDlzriJdrIrVLeDiUeTlpH3kpG38D7007GhXBV72k1gpMoMcpbQ3UmVkIEhhdCwg +SW5jLiAoQmV0YSBUZXN0IFNvZnR3YXJlKSA8cmF3aGlkZUByZWRoYXQuY29tPohX +BBMRAgAXBQI8l5p/BQsHCgMEAxUDAgMWAgECF4AACgkQ/TcmiYl9oHqdeQCfZjw4 +F9sir3XfRAjVe9kYNcQ8hnIAn0WgyT7H5RriWYTOCfauOmd+cAW4iEYEEBECAAYF +AjyXmqQACgkQIZGAzdtCpg5nDQCfepuRUyuVJvhuQkPWySETYvRw+WoAnjAWhx6q +0npMx4OE1JGFi8ymKXktuQENBDySTq4QBADKL/mK7S8E3synxISlu7R6fUvu07Oc +RoX96n0Di6T+BS99hC44XzHjMDhUX2ZzVvYS88EZXoUDDkB/8g7SwZrOJ/QE1zrI +JmSVciNhSYWwqeT40Evs88ajZUfDiNbS/cSC6oui98iS4vxd7sE7IPY+FSx9vuAR +xOa9vBnJY/dx0wADBQQAosm+Iltt2uigC6LJzxNOoIdB5r0GqTC1o5sHCeNqXJhU +ExAG8m74uzMlYVLOpGZi4y4NwwAWvCWC0MWWnnu+LGFy1wKiJKRjhv5F+WkFutY5 +WHV5L44vp9jSIlBCRG+84jheTh8xqhndM9wOfPwWdYYu1vxrB8Tn6kA17PcYfHSI +RgQYEQIABgUCPJJergAKCRD9NyaJiX2geiCPAJ4nEM4NtI9Uj8lONDk6FU86PmoL +yACfb68fBd2pWEzLKsOk9imIobHHpzE= +=gpIn +-----END PGP PUBLIC KEY BLOCK----- diff --git a/roles/openshift_repos/files/online/RPM-GPG-KEY-redhat-release b/roles/openshift_repos/files/online/RPM-GPG-KEY-redhat-release new file mode 100644 index 000000000..0f83b622d --- /dev/null +++ b/roles/openshift_repos/files/online/RPM-GPG-KEY-redhat-release @@ -0,0 +1,63 @@ +The following public key can be used to verify RPM packages built and +signed by Red Hat, Inc. This key is used for packages in Red Hat +products shipped after November 2009, and for all updates to those +products. + +Questions about this key should be sent to security@redhat.com. + +pub 4096R/FD431D51 2009-10-22 Red Hat, Inc. (release key 2) + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.2.6 (GNU/Linux) + +mQINBErgSTsBEACh2A4b0O9t+vzC9VrVtL1AKvUWi9OPCjkvR7Xd8DtJxeeMZ5eF +0HtzIG58qDRybwUe89FZprB1ffuUKzdE+HcL3FbNWSSOXVjZIersdXyH3NvnLLLF +0DNRB2ix3bXG9Rh/RXpFsNxDp2CEMdUvbYCzE79K1EnUTVh1L0Of023FtPSZXX0c +u7Pb5DI5lX5YeoXO6RoodrIGYJsVBQWnrWw4xNTconUfNPk0EGZtEnzvH2zyPoJh +XGF+Ncu9XwbalnYde10OCvSWAZ5zTCpoLMTvQjWpbCdWXJzCm6G+/hx9upke546H +5IjtYm4dTIVTnc3wvDiODgBKRzOl9rEOCIgOuGtDxRxcQkjrC+xvg5Vkqn7vBUyW +9pHedOU+PoF3DGOM+dqv+eNKBvh9YF9ugFAQBkcG7viZgvGEMGGUpzNgN7XnS1gj +/DPo9mZESOYnKceve2tIC87p2hqjrxOHuI7fkZYeNIcAoa83rBltFXaBDYhWAKS1 +PcXS1/7JzP0ky7d0L6Xbu/If5kqWQpKwUInXtySRkuraVfuK3Bpa+X1XecWi24JY +HVtlNX025xx1ewVzGNCTlWn1skQN2OOoQTV4C8/qFpTW6DTWYurd4+fE0OJFJZQF +buhfXYwmRlVOgN5i77NTIJZJQfYFj38c/Iv5vZBPokO6mffrOTv3MHWVgQARAQAB +tDNSZWQgSGF0LCBJbmMuIChyZWxlYXNlIGtleSAyKSA8c2VjdXJpdHlAcmVkaGF0 +LmNvbT6JAjYEEwECACAFAkrgSTsCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAK +CRAZni+R/UMdUWzpD/9s5SFR/ZF3yjY5VLUFLMXIKUztNN3oc45fyLdTI3+UClKC +2tEruzYjqNHhqAEXa2sN1fMrsuKec61Ll2NfvJjkLKDvgVIh7kM7aslNYVOP6BTf +C/JJ7/ufz3UZmyViH/WDl+AYdgk3JqCIO5w5ryrC9IyBzYv2m0HqYbWfphY3uHw5 +un3ndLJcu8+BGP5F+ONQEGl+DRH58Il9Jp3HwbRa7dvkPgEhfFR+1hI+Btta2C7E +0/2NKzCxZw7Lx3PBRcU92YKyaEihfy/aQKZCAuyfKiMvsmzs+4poIX7I9NQCJpyE +IGfINoZ7VxqHwRn/d5mw2MZTJjbzSf+Um9YJyA0iEEyD6qjriWQRbuxpQXmlAJbh +8okZ4gbVFv1F8MzK+4R8VvWJ0XxgtikSo72fHjwha7MAjqFnOq6eo6fEC/75g3NL +Ght5VdpGuHk0vbdENHMC8wS99e5qXGNDued3hlTavDMlEAHl34q2H9nakTGRF5Ki +JUfNh3DVRGhg8cMIti21njiRh7gyFI2OccATY7bBSr79JhuNwelHuxLrCFpY7V25 +OFktl15jZJaMxuQBqYdBgSay2G0U6D1+7VsWufpzd/Abx1/c3oi9ZaJvW22kAggq +dzdA27UUYjWvx42w9menJwh/0jeQcTecIUd0d0rFcw/c1pvgMMl/Q73yzKgKYw== +=zbHE +-----END PGP PUBLIC KEY BLOCK----- +The following public key can be used to verify RPM packages built and +signed by Red Hat, Inc. This key is a supporting (auxiliary) key for +Red Hat products shipped after November 2006 and for all updates to +those products. + +Questions about this key should be sent to security@redhat.com. + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.2.6 (GNU/Linux) + +mQGiBEVwDGkRBACwPhZIpvkjI8wV9sFTDoqyPLx1ub8Sd/w+YuI5Ovm49mvvEQVT +VLg8FgE5JlST59AbsLDyVtRa9CxIvN5syBVrWWWtHtDnnylFBcqG/A6J3bI4E9/A +UtSL5Zxbav0+utP6f3wOpxQrxc+WIDVgpurdBKAQ3dsobGBqypeX6FXZ5wCgou6C +yZpGIBqosJaDWLzNeOfb/70D/1thLkQyhW3JJ6cHCYJHNfBShvbLWBf6S231mgmu +MyMlt8Kmipc9bw+saaAkSkVsQ/ZbfjrWB7e5kbMruKLVrH+nGhamlHYUGyAPtsPg +Uj/NUSj5BmrCsOkMpn43ngTLssE9MLhSPj2nIHGFv9B+iVLvomDdwnaBRgQ1aK8z +z6MAA/406yf5yVJ/MlTWs1/68VwDhosc9BtU1V5IE0NXgZUAfBJzzfVzzKQq6zJ2 +eZsMLhr96wbsW13zUZt1ing+ulwh2ee4meuJq6h/971JspFY/XBhcfq4qCNqVjsq +SZnWoGdCO6J8CxPIemD2IUHzjoyyeEj3RVydup6pcWZAmhzkKrQzUmVkIEhhdCwg +SW5jLiAoYXV4aWxpYXJ5IGtleSkgPHNlY3VyaXR5QHJlZGhhdC5jb20+iF4EExEC +AB4FAkVwDGkCGwMGCwkIBwMCAxUCAwMWAgECHgECF4AACgkQRWiciC+mWOC1rQCg +ooNLCFOzNPcvhd9Za8C801HmnsYAniCw3yzrCqtjYnxDDxlufH0FVTwX +=d/bm +-----END PGP PUBLIC KEY BLOCK----- + diff --git a/roles/openshift_repos/files/online/epel7-kubernetes.repo b/roles/openshift_repos/files/online/epel7-kubernetes.repo new file mode 100644 index 000000000..1deae2939 --- /dev/null +++ b/roles/openshift_repos/files/online/epel7-kubernetes.repo @@ -0,0 +1,6 @@ +[maxamillion-epel7-kubernetes] +name=Copr repo for epel7-kubernetes owned by maxamillion +baseurl=http://copr-be.cloud.fedoraproject.org/results/maxamillion/epel7-kubernetes/epel-7-$basearch/ +skip_if_unavailable=True +gpgcheck=0 +enabled=1 diff --git a/roles/openshift_repos/files/online/epel7-openshift.repo b/roles/openshift_repos/files/online/epel7-openshift.repo new file mode 100644 index 000000000..c7629872d --- /dev/null +++ b/roles/openshift_repos/files/online/epel7-openshift.repo @@ -0,0 +1,6 @@ +[maxamillion-origin-next] +name=Copr repo for origin-next owned by maxamillion +baseurl=http://copr-be.cloud.fedoraproject.org/results/maxamillion/origin-next/epel-7-$basearch/ +skip_if_unavailable=False +gpgcheck=0 +enabled=1 diff --git a/roles/openshift_repos/files/online/oso-rhui-rhel-7-extras.repo b/roles/openshift_repos/files/online/oso-rhui-rhel-7-extras.repo new file mode 100644 index 000000000..cfe41f691 --- /dev/null +++ b/roles/openshift_repos/files/online/oso-rhui-rhel-7-extras.repo @@ -0,0 +1,23 @@ +[oso-rhui-rhel-server-extras] +name=OpenShift Online RHUI Mirror RH Enterprise Linux - Extras +baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-extras/ + https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-extras/ +enabled=1 +gpgcheck=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release,file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-beta +failovermethod=priority +sslverify=False +sslclientcert=/var/lib/yum/client-cert.pem +sslclientkey=/var/lib/yum/client-key.pem + +[oso-rhui-rhel-server-extras-htb] +name=OpenShift Online RHUI Mirror RH Enterprise Linux - Extras HTB +baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-extras-htb/ + https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-extras-htb/ +enabled=0 +gpgcheck=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release,file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-beta +failovermethod=priority +sslverify=False +sslclientcert=/var/lib/yum/client-cert.pem +sslclientkey=/var/lib/yum/client-key.pem diff --git a/roles/openshift_repos/files/online/oso-rhui-rhel-7-server.repo b/roles/openshift_repos/files/online/oso-rhui-rhel-7-server.repo new file mode 100644 index 000000000..ddc93193d --- /dev/null +++ b/roles/openshift_repos/files/online/oso-rhui-rhel-7-server.repo @@ -0,0 +1,21 @@ +[oso-rhui-rhel-server-releases] +name=OpenShift Online RHUI Mirror RH Enterprise Linux 7 +baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-releases/ + https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-releases/ +enabled=1 +gpgcheck=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release +sslverify=False +sslclientcert=/var/lib/yum/client-cert.pem +sslclientkey=/var/lib/yum/client-key.pem + +[oso-rhui-rhel-server-releases-optional] +name=OpenShift Online RHUI Mirror RH Enterprise Linux 7 - Optional +baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-releases-optional/ + https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-releases-optional/ +enabled=1 +gpgcheck=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release +sslverify=False +sslclientcert=/var/lib/yum/client-cert.pem +sslclientkey=/var/lib/yum/client-key.pem diff --git a/roles/openshift_repos/files/online/rhel-7-libra-candidate.repo b/roles/openshift_repos/files/online/rhel-7-libra-candidate.repo new file mode 100644 index 000000000..b4215679f --- /dev/null +++ b/roles/openshift_repos/files/online/rhel-7-libra-candidate.repo @@ -0,0 +1,11 @@ +[rhel-7-libra-candidate] +name=rhel-7-libra-candidate - \$basearch +baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhel-7-libra-candidate/\$basearch/ + https://mirror.ops.rhcloud.com/libra/rhel-7-libra-candidate/\$basearch/ +gpgkey=https://mirror.ops.rhcloud.com/libra/RPM-GPG-KEY-redhat-openshifthosted +skip_if_unavailable=True +gpgcheck=0 +enabled=1 +sslclientcert=/var/lib/yum/client-cert.pem +sslclientkey=/var/lib/yum/client-key.pem +sslverify=False diff --git a/roles/openshift_repos/meta/main.yml b/roles/openshift_repos/meta/main.yml new file mode 100644 index 000000000..cc18c453c --- /dev/null +++ b/roles/openshift_repos/meta/main.yml @@ -0,0 +1,14 @@ +--- +galaxy_info: + author: TODO + description: OpenShift Repositories + company: Red Hat, Inc. + license: Apache License, Version 2.0 + min_ansible_version: 1.7 + platforms: + - name: EL + versions: + - 7 + categories: + - cloud +dependencies: [] diff --git a/roles/openshift_repos/tasks/main.yaml b/roles/openshift_repos/tasks/main.yaml new file mode 100644 index 000000000..6219c4906 --- /dev/null +++ b/roles/openshift_repos/tasks/main.yaml @@ -0,0 +1,46 @@ +--- +# TODO: Add flag for enabling EPEL repo, default to false + +- assert: + that: openshift_deployment_type in known_openshift_deployment_types + +# TODO: remove this when origin support actually works +- fail: msg="OpenShift Origin support is not currently enabled" + when: openshift_deployment_type == 'origin' + +- name: Ensure libselinux-python is installed + yum: + pkg: libselinux-python + state: present + +- name: Create any additional repos that are defined + template: + src: yum_repo.j2 + dest: /etc/yum.repos.d/openshift_additional.repo + when: openshift_additional_repos | length > 0 + +- name: Remove the additional repos if no longer defined + file: + dest: /etc/yum.repos.d/openshift_additional.repo + state: absent + when: openshift_additional_repos | length == 0 + +- name: Remove any yum repo files for other deployment types + file: + path: "/etc/yum.repos.d/{{ item | basename }}" + state: absent + with_fileglob: + - '*/*' + when: not (item | search("/files/" + openshift_deployment_type + "/")) and (item | search(".repo$")) + +- name: Configure gpg keys if needed + copy: src={{ item }} dest=/etc/pki/rpm-gpg/ + with_fileglob: + - "{{ openshift_deployment_type }}/*" + when: item | basename | match("RPM-GPG-KEY-") + +- name: Configure yum repositories + copy: src={{ item }} dest=/etc/yum.repos.d/ + with_fileglob: + - "{{ openshift_deployment_type }}/*" + when: item | basename | search(".*\.repo$") diff --git a/roles/openshift_repos/templates/yum_repo.j2 b/roles/openshift_repos/templates/yum_repo.j2 new file mode 100644 index 000000000..7ea2c7460 --- /dev/null +++ b/roles/openshift_repos/templates/yum_repo.j2 @@ -0,0 +1,15 @@ +# {{ ansible_managed }} +{% for repo in openshift_additional_repos %} +[{{ repo.id }}] +name={{ repo.name | default(repo.id) }} +baseurl={{ repo.baseurl }} +{% set enable_repo = repo.enabled | default('1') %} +enabled={{ 1 if ( enable_repo == 1 or enable_repo == True ) else 0 }} +{% set enable_gpg_check = repo.gpgcheck | default('1') %} +gpgcheck={{ 1 if ( enable_gpg_check == 1 or enable_gpg_check == True ) else 0 }} +{% for key, value in repo.iteritems() %} +{% if key not in ['id', 'name', 'baseurl', 'enabled', 'gpgcheck'] and value is defined %} +{{ key }}={{ value }} +{% endif %} +{% endfor %} +{% endfor %} diff --git a/roles/openshift_repos/vars/main.yml b/roles/openshift_repos/vars/main.yml new file mode 100644 index 000000000..bbb4c77e7 --- /dev/null +++ b/roles/openshift_repos/vars/main.yml @@ -0,0 +1,2 @@ +--- +known_openshift_deployment_types: ['origin', 'online', 'enterprise'] diff --git a/roles/repos/defaults/main.yaml b/roles/repos/defaults/main.yaml deleted file mode 100644 index 6fe2bf621..000000000 --- a/roles/repos/defaults/main.yaml +++ /dev/null @@ -1,5 +0,0 @@ ---- -# TODO: once we are able to configure/deploy origin using the openshift roles, -# then we should default to origin -openshift_deployment_type: online -openshift_additional_repos: {} diff --git a/roles/repos/files/online/RPM-GPG-KEY-redhat-beta b/roles/repos/files/online/RPM-GPG-KEY-redhat-beta deleted file mode 100644 index 7b40671a4..000000000 --- a/roles/repos/files/online/RPM-GPG-KEY-redhat-beta +++ /dev/null @@ -1,61 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.2.6 (GNU/Linux) - -mQINBEmkAzABEAC2/c7bP1lHQ3XScxbIk0LQWe1YOiibQBRLwf8Si5PktgtuPibT -kKpZjw8p4D+fM7jD1WUzUE0X7tXg2l/eUlMM4dw6XJAQ1AmEOtlwSg7rrMtTvM0A -BEtI7Km6fC6sU6RtBMdcqD1cH/6dbsfh8muznVA7UlX+PRBHVzdWzj6y8h84dBjo -gzcbYu9Hezqgj/lLzicqsSZPz9UdXiRTRAIhp8V30BD8uRaaa0KDDnD6IzJv3D9P -xQWbFM4Z12GN9LyeZqmD7bpKzZmXG/3drvfXVisXaXp3M07t3NlBa3Dt8NFIKZ0D -FRXBz5bvzxRVmdH6DtkDWXDPOt+Wdm1rZrCOrySFpBZQRpHw12eo1M1lirANIov7 -Z+V1Qh/aBxj5EUu32u9ZpjAPPNtQF6F/KjaoHHHmEQAuj4DLex4LY646Hv1rcv2i -QFuCdvLKQGSiFBrfZH0j/IX3/0JXQlZzb3MuMFPxLXGAoAV9UP/Sw/WTmAuTzFVm -G13UYFeMwrToOiqcX2VcK0aC1FCcTP2z4JW3PsWvU8rUDRUYfoXovc7eg4Vn5wHt -0NBYsNhYiAAf320AUIHzQZYi38JgVwuJfFu43tJZE4Vig++RQq6tsEx9Ftz3EwRR -fJ9z9mEvEiieZm+vbOvMvIuimFVPSCmLH+bI649K8eZlVRWsx3EXCVb0nQARAQAB -tDBSZWQgSGF0LCBJbmMuIChiZXRhIGtleSAyKSA8c2VjdXJpdHlAcmVkaGF0LmNv -bT6JAjYEEwECACAFAkpSM+cCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCT -ioDK8hVB6/9tEAC0+KmzeKceXQ/GTUoU6jy9vtkFCFrmv+c7ol4XpdTt0QhqBOwy -6m2mKWwmm8KfYfy0cADQ4y/EcoXl7FtFBwYmkCuEQGXhTDn9DvVjhooIq59LEMBQ -OW879RwwzRIZ8ebbjMUjDPF5MfPQqP2LBu9N4KvXlZp4voykwuuaJ+cbsKZR6pZ6 -0RQKPHKP+NgUFC0fff7XY9cuOZZWFAeKRhLN2K7bnRHKxp+kELWb6R9ZfrYwZjWc -MIPbTd1khE53L4NTfpWfAnJRtkPSDOKEGVlVLtLq4HEAxQt07kbslqISRWyXER3u -QOJj64D1ZiIMz6t6uZ424VE4ry9rBR0Jz55cMMx5O/ni9x3xzFUgH8Su2yM0r3jE -Rf24+tbOaPf7tebyx4OKe+JW95hNVstWUDyGbs6K9qGfI/pICuO1nMMFTo6GqzQ6 -DwLZvJ9QdXo7ujEtySZnfu42aycaQ9ZLC2DOCQCUBY350Hx6FLW3O546TAvpTfk0 -B6x+DV7mJQH7MGmRXQsE7TLBJKjq28Cn4tVp04PmybQyTxZdGA/8zY6pPl6xyVMH -V68hSBKEVT/rlouOHuxfdmZva1DhVvUC6Xj7+iTMTVJUAq/4Uyn31P1OJmA2a0PT -CAqWkbJSgKFccsjPoTbLyxhuMSNkEZFHvlZrSK9vnPzmfiRH0Orx3wYpMQ== -=21pb ------END PGP PUBLIC KEY BLOCK----- -The following public key can be used to verify RPM packages built and -signed by Red Hat, Inc. for this beta using `rpm -K' using the GNU GPG -package. Questions about this key should be sent to security@redhat.com. - - ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.0.6 (GNU/Linux) -Comment: For info see http://www.gnupg.org - -mQGiBDySTqsRBACzc7xuCIp10oj5B2PAV4XzDeVxprv/WTMreSNSK+iC0bEz0IBp -Vnn++qtyiXfH+bGIE9jqZgIEnpttWhUOaU5LhcLFzy+m8NWfngIFP9QfGmGAe9Gd -LFeAdhj4RmSG/vgr7vDd83Hz22dv403Ar/sliWO4vDOrMmZBG57WGYTWtwCgkMsi -UUQuJ6slbzKn82w+bYxOlL0EAIylWJGaTkKOTL5DqVR3ik9aT0Dt3FNVYiuhcKBe -II4E3KOIVA9kO8in1IZjx2gs6K2UV+GsoAVANdfKL7l9O+k+J8OxhE74oycvYJxW -QzCgXMZkNcvW5wyXwEMcr6TVd/5BGztcMw8oT3/l2MtAEG/vn1XaWToRSO1XDMDz -+AjUA/4m0mTkN8S4wjzJG8lqN7+quW3UOaiCe8J3SFrrrhE0XbY9cTJI/9nuXHU1 -VjqOSmXQYH2Db7UOroFTBiWhlAedA4O4yuK52AJnvSsHbnJSEmn9rpo5z1Q8F+qI -mDlzriJdrIrVLeDiUeTlpH3kpG38D7007GhXBV72k1gpMoMcpbQ3UmVkIEhhdCwg -SW5jLiAoQmV0YSBUZXN0IFNvZnR3YXJlKSA8cmF3aGlkZUByZWRoYXQuY29tPohX -BBMRAgAXBQI8l5p/BQsHCgMEAxUDAgMWAgECF4AACgkQ/TcmiYl9oHqdeQCfZjw4 -F9sir3XfRAjVe9kYNcQ8hnIAn0WgyT7H5RriWYTOCfauOmd+cAW4iEYEEBECAAYF -AjyXmqQACgkQIZGAzdtCpg5nDQCfepuRUyuVJvhuQkPWySETYvRw+WoAnjAWhx6q -0npMx4OE1JGFi8ymKXktuQENBDySTq4QBADKL/mK7S8E3synxISlu7R6fUvu07Oc -RoX96n0Di6T+BS99hC44XzHjMDhUX2ZzVvYS88EZXoUDDkB/8g7SwZrOJ/QE1zrI -JmSVciNhSYWwqeT40Evs88ajZUfDiNbS/cSC6oui98iS4vxd7sE7IPY+FSx9vuAR -xOa9vBnJY/dx0wADBQQAosm+Iltt2uigC6LJzxNOoIdB5r0GqTC1o5sHCeNqXJhU -ExAG8m74uzMlYVLOpGZi4y4NwwAWvCWC0MWWnnu+LGFy1wKiJKRjhv5F+WkFutY5 -WHV5L44vp9jSIlBCRG+84jheTh8xqhndM9wOfPwWdYYu1vxrB8Tn6kA17PcYfHSI -RgQYEQIABgUCPJJergAKCRD9NyaJiX2geiCPAJ4nEM4NtI9Uj8lONDk6FU86PmoL -yACfb68fBd2pWEzLKsOk9imIobHHpzE= -=gpIn ------END PGP PUBLIC KEY BLOCK----- diff --git a/roles/repos/files/online/RPM-GPG-KEY-redhat-release b/roles/repos/files/online/RPM-GPG-KEY-redhat-release deleted file mode 100644 index 0f83b622d..000000000 --- a/roles/repos/files/online/RPM-GPG-KEY-redhat-release +++ /dev/null @@ -1,63 +0,0 @@ -The following public key can be used to verify RPM packages built and -signed by Red Hat, Inc. This key is used for packages in Red Hat -products shipped after November 2009, and for all updates to those -products. - -Questions about this key should be sent to security@redhat.com. - -pub 4096R/FD431D51 2009-10-22 Red Hat, Inc. (release key 2) - ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.2.6 (GNU/Linux) - -mQINBErgSTsBEACh2A4b0O9t+vzC9VrVtL1AKvUWi9OPCjkvR7Xd8DtJxeeMZ5eF -0HtzIG58qDRybwUe89FZprB1ffuUKzdE+HcL3FbNWSSOXVjZIersdXyH3NvnLLLF -0DNRB2ix3bXG9Rh/RXpFsNxDp2CEMdUvbYCzE79K1EnUTVh1L0Of023FtPSZXX0c -u7Pb5DI5lX5YeoXO6RoodrIGYJsVBQWnrWw4xNTconUfNPk0EGZtEnzvH2zyPoJh -XGF+Ncu9XwbalnYde10OCvSWAZ5zTCpoLMTvQjWpbCdWXJzCm6G+/hx9upke546H -5IjtYm4dTIVTnc3wvDiODgBKRzOl9rEOCIgOuGtDxRxcQkjrC+xvg5Vkqn7vBUyW -9pHedOU+PoF3DGOM+dqv+eNKBvh9YF9ugFAQBkcG7viZgvGEMGGUpzNgN7XnS1gj -/DPo9mZESOYnKceve2tIC87p2hqjrxOHuI7fkZYeNIcAoa83rBltFXaBDYhWAKS1 -PcXS1/7JzP0ky7d0L6Xbu/If5kqWQpKwUInXtySRkuraVfuK3Bpa+X1XecWi24JY -HVtlNX025xx1ewVzGNCTlWn1skQN2OOoQTV4C8/qFpTW6DTWYurd4+fE0OJFJZQF -buhfXYwmRlVOgN5i77NTIJZJQfYFj38c/Iv5vZBPokO6mffrOTv3MHWVgQARAQAB -tDNSZWQgSGF0LCBJbmMuIChyZWxlYXNlIGtleSAyKSA8c2VjdXJpdHlAcmVkaGF0 -LmNvbT6JAjYEEwECACAFAkrgSTsCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAK -CRAZni+R/UMdUWzpD/9s5SFR/ZF3yjY5VLUFLMXIKUztNN3oc45fyLdTI3+UClKC -2tEruzYjqNHhqAEXa2sN1fMrsuKec61Ll2NfvJjkLKDvgVIh7kM7aslNYVOP6BTf -C/JJ7/ufz3UZmyViH/WDl+AYdgk3JqCIO5w5ryrC9IyBzYv2m0HqYbWfphY3uHw5 -un3ndLJcu8+BGP5F+ONQEGl+DRH58Il9Jp3HwbRa7dvkPgEhfFR+1hI+Btta2C7E -0/2NKzCxZw7Lx3PBRcU92YKyaEihfy/aQKZCAuyfKiMvsmzs+4poIX7I9NQCJpyE -IGfINoZ7VxqHwRn/d5mw2MZTJjbzSf+Um9YJyA0iEEyD6qjriWQRbuxpQXmlAJbh -8okZ4gbVFv1F8MzK+4R8VvWJ0XxgtikSo72fHjwha7MAjqFnOq6eo6fEC/75g3NL -Ght5VdpGuHk0vbdENHMC8wS99e5qXGNDued3hlTavDMlEAHl34q2H9nakTGRF5Ki -JUfNh3DVRGhg8cMIti21njiRh7gyFI2OccATY7bBSr79JhuNwelHuxLrCFpY7V25 -OFktl15jZJaMxuQBqYdBgSay2G0U6D1+7VsWufpzd/Abx1/c3oi9ZaJvW22kAggq -dzdA27UUYjWvx42w9menJwh/0jeQcTecIUd0d0rFcw/c1pvgMMl/Q73yzKgKYw== -=zbHE ------END PGP PUBLIC KEY BLOCK----- -The following public key can be used to verify RPM packages built and -signed by Red Hat, Inc. This key is a supporting (auxiliary) key for -Red Hat products shipped after November 2006 and for all updates to -those products. - -Questions about this key should be sent to security@redhat.com. - ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.2.6 (GNU/Linux) - -mQGiBEVwDGkRBACwPhZIpvkjI8wV9sFTDoqyPLx1ub8Sd/w+YuI5Ovm49mvvEQVT -VLg8FgE5JlST59AbsLDyVtRa9CxIvN5syBVrWWWtHtDnnylFBcqG/A6J3bI4E9/A -UtSL5Zxbav0+utP6f3wOpxQrxc+WIDVgpurdBKAQ3dsobGBqypeX6FXZ5wCgou6C -yZpGIBqosJaDWLzNeOfb/70D/1thLkQyhW3JJ6cHCYJHNfBShvbLWBf6S231mgmu -MyMlt8Kmipc9bw+saaAkSkVsQ/ZbfjrWB7e5kbMruKLVrH+nGhamlHYUGyAPtsPg -Uj/NUSj5BmrCsOkMpn43ngTLssE9MLhSPj2nIHGFv9B+iVLvomDdwnaBRgQ1aK8z -z6MAA/406yf5yVJ/MlTWs1/68VwDhosc9BtU1V5IE0NXgZUAfBJzzfVzzKQq6zJ2 -eZsMLhr96wbsW13zUZt1ing+ulwh2ee4meuJq6h/971JspFY/XBhcfq4qCNqVjsq -SZnWoGdCO6J8CxPIemD2IUHzjoyyeEj3RVydup6pcWZAmhzkKrQzUmVkIEhhdCwg -SW5jLiAoYXV4aWxpYXJ5IGtleSkgPHNlY3VyaXR5QHJlZGhhdC5jb20+iF4EExEC -AB4FAkVwDGkCGwMGCwkIBwMCAxUCAwMWAgECHgECF4AACgkQRWiciC+mWOC1rQCg -ooNLCFOzNPcvhd9Za8C801HmnsYAniCw3yzrCqtjYnxDDxlufH0FVTwX -=d/bm ------END PGP PUBLIC KEY BLOCK----- - diff --git a/roles/repos/files/online/epel7-kubernetes.repo b/roles/repos/files/online/epel7-kubernetes.repo deleted file mode 100644 index 1deae2939..000000000 --- a/roles/repos/files/online/epel7-kubernetes.repo +++ /dev/null @@ -1,6 +0,0 @@ -[maxamillion-epel7-kubernetes] -name=Copr repo for epel7-kubernetes owned by maxamillion -baseurl=http://copr-be.cloud.fedoraproject.org/results/maxamillion/epel7-kubernetes/epel-7-$basearch/ -skip_if_unavailable=True -gpgcheck=0 -enabled=1 diff --git a/roles/repos/files/online/epel7-openshift.repo b/roles/repos/files/online/epel7-openshift.repo deleted file mode 100644 index c7629872d..000000000 --- a/roles/repos/files/online/epel7-openshift.repo +++ /dev/null @@ -1,6 +0,0 @@ -[maxamillion-origin-next] -name=Copr repo for origin-next owned by maxamillion -baseurl=http://copr-be.cloud.fedoraproject.org/results/maxamillion/origin-next/epel-7-$basearch/ -skip_if_unavailable=False -gpgcheck=0 -enabled=1 diff --git a/roles/repos/files/online/oso-rhui-rhel-7-extras.repo b/roles/repos/files/online/oso-rhui-rhel-7-extras.repo deleted file mode 100644 index cfe41f691..000000000 --- a/roles/repos/files/online/oso-rhui-rhel-7-extras.repo +++ /dev/null @@ -1,23 +0,0 @@ -[oso-rhui-rhel-server-extras] -name=OpenShift Online RHUI Mirror RH Enterprise Linux - Extras -baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-extras/ - https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-extras/ -enabled=1 -gpgcheck=1 -gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release,file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-beta -failovermethod=priority -sslverify=False -sslclientcert=/var/lib/yum/client-cert.pem -sslclientkey=/var/lib/yum/client-key.pem - -[oso-rhui-rhel-server-extras-htb] -name=OpenShift Online RHUI Mirror RH Enterprise Linux - Extras HTB -baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-extras-htb/ - https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-extras-htb/ -enabled=0 -gpgcheck=1 -gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release,file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-beta -failovermethod=priority -sslverify=False -sslclientcert=/var/lib/yum/client-cert.pem -sslclientkey=/var/lib/yum/client-key.pem diff --git a/roles/repos/files/online/oso-rhui-rhel-7-server.repo b/roles/repos/files/online/oso-rhui-rhel-7-server.repo deleted file mode 100644 index ddc93193d..000000000 --- a/roles/repos/files/online/oso-rhui-rhel-7-server.repo +++ /dev/null @@ -1,21 +0,0 @@ -[oso-rhui-rhel-server-releases] -name=OpenShift Online RHUI Mirror RH Enterprise Linux 7 -baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-releases/ - https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-releases/ -enabled=1 -gpgcheck=1 -gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release -sslverify=False -sslclientcert=/var/lib/yum/client-cert.pem -sslclientkey=/var/lib/yum/client-key.pem - -[oso-rhui-rhel-server-releases-optional] -name=OpenShift Online RHUI Mirror RH Enterprise Linux 7 - Optional -baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-releases-optional/ - https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-releases-optional/ -enabled=1 -gpgcheck=1 -gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release -sslverify=False -sslclientcert=/var/lib/yum/client-cert.pem -sslclientkey=/var/lib/yum/client-key.pem diff --git a/roles/repos/files/online/rhel-7-libra-candidate.repo b/roles/repos/files/online/rhel-7-libra-candidate.repo deleted file mode 100644 index b4215679f..000000000 --- a/roles/repos/files/online/rhel-7-libra-candidate.repo +++ /dev/null @@ -1,11 +0,0 @@ -[rhel-7-libra-candidate] -name=rhel-7-libra-candidate - \$basearch -baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhel-7-libra-candidate/\$basearch/ - https://mirror.ops.rhcloud.com/libra/rhel-7-libra-candidate/\$basearch/ -gpgkey=https://mirror.ops.rhcloud.com/libra/RPM-GPG-KEY-redhat-openshifthosted -skip_if_unavailable=True -gpgcheck=0 -enabled=1 -sslclientcert=/var/lib/yum/client-cert.pem -sslclientkey=/var/lib/yum/client-key.pem -sslverify=False diff --git a/roles/repos/tasks/main.yaml b/roles/repos/tasks/main.yaml deleted file mode 100644 index 43786da41..000000000 --- a/roles/repos/tasks/main.yaml +++ /dev/null @@ -1,41 +0,0 @@ ---- -# TODO: Add flag for enabling EPEL repo, default to false - -- assert: - that: openshift_deployment_type in known_openshift_deployment_types - -# TODO: remove this when origin support actually works -- fail: msg="OpenShift Origin support is not currently enabled" - when: openshift_deployment_type == 'origin' - -- name: Create any additional repos that are defined - template: - src: yum_repo.j2 - dest: /etc/yum.repos.d/openshift_additional.repo - when: openshift_additional_repos | length > 0 - -- name: Remove the additional repos if no longer defined - file: - dest: /etc/yum.repos.d/openshift_additional.repo - state: absent - when: openshift_additional_repos | length == 0 - -- name: Remove any yum repo files for other deployment types - file: - path: "/etc/yum.repos.d/{{ item | basename }}" - state: absent - with_fileglob: - - '*/*' - when: not (item | search("/files/" + openshift_deployment_type + "/")) and (item | search(".repo$")) - -- name: Configure gpg keys if needed - copy: src={{ item }} dest=/etc/pki/rpm-gpg/ - with_fileglob: - - "{{ openshift_deployment_type }}/*" - when: item | basename | match("RPM-GPG-KEY-") - -- name: Configure yum repositories - copy: src={{ item }} dest=/etc/yum.repos.d/ - with_fileglob: - - "{{ openshift_deployment_type }}/*" - when: item | basename | search(".*\.repo$") diff --git a/roles/repos/templates/yum_repo.j2 b/roles/repos/templates/yum_repo.j2 deleted file mode 100644 index 7ea2c7460..000000000 --- a/roles/repos/templates/yum_repo.j2 +++ /dev/null @@ -1,15 +0,0 @@ -# {{ ansible_managed }} -{% for repo in openshift_additional_repos %} -[{{ repo.id }}] -name={{ repo.name | default(repo.id) }} -baseurl={{ repo.baseurl }} -{% set enable_repo = repo.enabled | default('1') %} -enabled={{ 1 if ( enable_repo == 1 or enable_repo == True ) else 0 }} -{% set enable_gpg_check = repo.gpgcheck | default('1') %} -gpgcheck={{ 1 if ( enable_gpg_check == 1 or enable_gpg_check == True ) else 0 }} -{% for key, value in repo.iteritems() %} -{% if key not in ['id', 'name', 'baseurl', 'enabled', 'gpgcheck'] and value is defined %} -{{ key }}={{ value }} -{% endif %} -{% endfor %} -{% endfor %} diff --git a/roles/repos/vars/main.yml b/roles/repos/vars/main.yml deleted file mode 100644 index bbb4c77e7..000000000 --- a/roles/repos/vars/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -known_openshift_deployment_types: ['origin', 'online', 'enterprise'] -- cgit v1.2.3 From 3d4144c56731d3efdfd0c34083256e139f8e9571 Mon Sep 17 00:00:00 2001 From: liangxia Date: Thu, 19 Mar 2015 07:35:21 +0000 Subject: minor fix --- playbooks/aws/openshift-master/config.yml | 2 +- playbooks/aws/openshift-node/config.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/playbooks/aws/openshift-master/config.yml b/playbooks/aws/openshift-master/config.yml index 454cd6f24..0d0e6d5bf 100644 --- a/playbooks/aws/openshift-master/config.yml +++ b/playbooks/aws/openshift-master/config.yml @@ -35,7 +35,7 @@ - { role: openshift_master, openshift_node_ips: "{{ hostvars['localhost'].openshift_node_ips | default(['']) }}", - openshift_env: "{{ oo_env }}" + openshift_env: "{{ oo_env }}", openshift_public_ip: "{{ ec2_ip_address }}" } - pods diff --git a/playbooks/aws/openshift-node/config.yml b/playbooks/aws/openshift-node/config.yml index 9662168c4..317785c84 100644 --- a/playbooks/aws/openshift-node/config.yml +++ b/playbooks/aws/openshift-node/config.yml @@ -43,7 +43,7 @@ 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_env: "{{ oo_env }}", openshift_public_ip: "{{ ec2_ip_address }}" } - os_env_extras -- cgit v1.2.3 From a90bbd30c6eb962eb9b4cd281823312ee3a95416 Mon Sep 17 00:00:00 2001 From: Dan McPherson Date: Mon, 23 Mar 2015 09:54:34 -0400 Subject: Update README_GCE.md --- README_GCE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_GCE.md b/README_GCE.md index b00598113..85736e293 100644 --- a/README_GCE.md +++ b/README_GCE.md @@ -4,7 +4,7 @@ GCE Setup Instructions Get a gce service key --------------------- -1. ask your GCE project administrator for a GCE service key +1. Ask your GCE project administrator for a GCE service key Note: If your GCE project does not show a Service Account under /APIs & auth/Credentials, you will need to use "Create new Client ID" to create a Service Account before your administrator can create the service key for you. -- cgit v1.2.3 From fceb54d257ec0e645533e9f20d002f559433662a Mon Sep 17 00:00:00 2001 From: Dan McPherson Date: Mon, 23 Mar 2015 10:14:26 -0400 Subject: Update README_GCE.md --- README_GCE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_GCE.md b/README_GCE.md index 85736e293..209705113 100644 --- a/README_GCE.md +++ b/README_GCE.md @@ -72,5 +72,5 @@ Test The Setup 3. Try to create an instance: ``` - ./cloud.rb gce launch -n ${USER}-node1 -e int --type os3-node + ./cloud.rb gce launch -e int --type openshift-node ``` -- cgit v1.2.3 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 ++++++++++++++++++++++++++++++++++ rel-eng/packages/.readme | 3 +++ rel-eng/tito.props | 5 +++++ 3 files changed, 42 insertions(+) create mode 100644 bin/openshift-ansible-cmds.spec create mode 100644 rel-eng/packages/.readme create mode 100644 rel-eng/tito.props 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 diff --git a/rel-eng/packages/.readme b/rel-eng/packages/.readme new file mode 100644 index 000000000..8999c8dbc --- /dev/null +++ b/rel-eng/packages/.readme @@ -0,0 +1,3 @@ +the rel-eng/packages directory contains metadata files +named after their packages. Each file has the latest tagged +version and the project's relative directory. diff --git a/rel-eng/tito.props b/rel-eng/tito.props new file mode 100644 index 000000000..eab3f190d --- /dev/null +++ b/rel-eng/tito.props @@ -0,0 +1,5 @@ +[buildconfig] +builder = tito.builder.Builder +tagger = tito.tagger.VersionTagger +changelog_do_not_remove_cherrypick = 0 +changelog_format = %s (%ae) -- 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 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(-) 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 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(-) 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 33dda93c3920d9f2df371d71393fb35829c1bdd1 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Fri, 13 Mar 2015 03:49:43 -0400 Subject: add oo_prepend_strings_in_list filter --- filter_plugins/oo_filters.py | 106 +++++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 44 deletions(-) diff --git a/filter_plugins/oo_filters.py b/filter_plugins/oo_filters.py index b57056375..caf1fd1f0 100644 --- a/filter_plugins/oo_filters.py +++ b/filter_plugins/oo_filters.py @@ -1,39 +1,42 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# vim: expandtab:tabstop=4:shiftwidth=4 + from ansible import errors, runner import json import pdb def oo_pdb(arg): - ''' This pops you into a pdb instance where arg is the data passed in from the filter. + ''' This pops you into a pdb instance where arg is the data passed in from the filter. Ex: "{{ hostvars | oo_pdb }}" - ''' - pdb.set_trace() - return arg + ''' + pdb.set_trace() + return arg def oo_len(arg): - ''' This returns the length of the argument + ''' This returns the length of the argument Ex: "{{ hostvars | oo_len }}" - ''' - return len(arg) + ''' + return len(arg) def get_attr(data, attribute=None): - ''' This looks up dictionary attributes of the form a.b.c and returns the value. + ''' This looks up dictionary attributes of the form a.b.c and returns the value. Ex: data = {'a': {'b': {'c': 5}}} attribute = "a.b.c" returns 5 - ''' - - if not attribute: - raise errors.AnsibleFilterError("|failed expects attribute to be set") + ''' + if not attribute: + raise errors.AnsibleFilterError("|failed expects attribute to be set") - ptr = data - for attr in attribute.split('.'): - ptr = ptr[attr] + ptr = data + for attr in attribute.split('.'): + ptr = ptr[attr] - return ptr + return ptr def oo_collect(data, attribute=None, filters={}): - ''' This takes a list of dict and collects all attributes specified into a list - If filter is specified then we will include all items that match _ALL_ of filters. + ''' This takes a list of dict and collects all attributes specified into a list + If filter is specified then we will include all items that match _ALL_ of filters. Ex: data = [ {'a':1, 'b':5, 'z': 'z'}, # True, return {'a':2, 'z': 'z'}, # True, return {'a':3, 'z': 'z'}, # True, return @@ -42,44 +45,59 @@ def oo_collect(data, attribute=None, filters={}): attribute = 'a' filters = {'z': 'z'} returns [1, 2, 3] - ''' + ''' - if not issubclass(type(data), list): - raise errors.AnsibleFilterError("|failed expects to filter on a List") + if not issubclass(type(data), list): + raise errors.AnsibleFilterError("|failed expects to filter on a List") - if not attribute: - raise errors.AnsibleFilterError("|failed expects attribute to be set") + if not attribute: + raise errors.AnsibleFilterError("|failed expects attribute to be set") - if filters: - retval = [get_attr(d, attribute) for d in data if all([ d[key] == filters[key] for key in filters ]) ] - else: - retval = [get_attr(d, attribute) for d in data] + if filters: + retval = [get_attr(d, attribute) for d in data if all([ d[key] == filters[key] for key in filters ]) ] + else: + retval = [get_attr(d, attribute) for d in data] - return retval + return retval def oo_select_keys(data, keys): - ''' This returns a list, which contains the value portions for the keys + ''' This returns a list, which contains the value portions for the keys Ex: data = { 'a':1, 'b':2, 'c':3 } keys = ['a', 'c'] returns [1, 3] - ''' + ''' + + if not issubclass(type(data), dict): + raise errors.AnsibleFilterError("|failed expects to filter on a Dictionary") - if not issubclass(type(data), dict): - raise errors.AnsibleFilterError("|failed expects to filter on a Dictionary") + if not issubclass(type(keys), list): + raise errors.AnsibleFilterError("|failed expects first param is a list") - if not issubclass(type(keys), list): - raise errors.AnsibleFilterError("|failed expects first param is a list") + # Gather up the values for the list of keys passed in + retval = [data[key] for key in keys] - # Gather up the values for the list of keys passed in - retval = [data[key] for key in keys] + return retval - return retval +def oo_prepend_strings_in_list(data, prepend): + ''' This takes a list of strings and prepends a string to each item in the + list + Ex: data = ['cart', 'tree'] + prepend = 'apple-' + returns ['apple-cart', 'apple-tree'] + ''' + if not issubclass(type(data), list): + raise errors.AnsibleFilterError("|failed expects first param is a list") + if not all(isinstance(x, basestring) for x in data): + raise errors.AnsibleFilterError("|failed expects first param is a list of strings") + retval = [prepend + s for s in data] + return retval class FilterModule (object): - def filters(self): - return { - "oo_select_keys": oo_select_keys, - "oo_collect": oo_collect, - "oo_len": oo_len, - "oo_pdb": oo_pdb - } + def filters(self): + return { + "oo_select_keys": oo_select_keys, + "oo_collect": oo_collect, + "oo_len": oo_len, + "oo_pdb": oo_pdb, + "oo_prepend_strings_in_list": oo_prepend_strings_in_list + } -- cgit v1.2.3 From 66332175b61a5a538aa73b76cbcf151e1882a52c Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Fri, 13 Mar 2015 03:55:04 -0400 Subject: Move yum update * to new os_update_latest role --- roles/openshift_common/tasks/main.yml | 3 --- roles/os_update_latest/tasks/main.yml | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 roles/os_update_latest/tasks/main.yml diff --git a/roles/openshift_common/tasks/main.yml b/roles/openshift_common/tasks/main.yml index 656a3880d..07737a71f 100644 --- a/roles/openshift_common/tasks/main.yml +++ b/roles/openshift_common/tasks/main.yml @@ -2,9 +2,6 @@ - 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 diff --git a/roles/os_update_latest/tasks/main.yml b/roles/os_update_latest/tasks/main.yml new file mode 100644 index 000000000..4a2c3d47a --- /dev/null +++ b/roles/os_update_latest/tasks/main.yml @@ -0,0 +1,3 @@ +--- +- name: Update all packages + yum: name=* state=latest -- cgit v1.2.3 From e337235d471468b400acadcbd56ad14f39a2a222 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Fri, 13 Mar 2015 03:56:01 -0400 Subject: add roles symlink to playbooks/gce/openshift-cluster to allow launch to call os_update_latest role --- playbooks/gce/openshift-cluster/roles | 1 + 1 file changed, 1 insertion(+) create mode 120000 playbooks/gce/openshift-cluster/roles diff --git a/playbooks/gce/openshift-cluster/roles b/playbooks/gce/openshift-cluster/roles new file mode 120000 index 000000000..20c4c58cf --- /dev/null +++ b/playbooks/gce/openshift-cluster/roles @@ -0,0 +1 @@ +../../../roles \ No newline at end of file -- cgit v1.2.3 From 9199379f94f6b11a4841e31f6c58a11c1e9f8c3a Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Fri, 13 Mar 2015 03:58:23 -0400 Subject: Various fixes - playbooks/gce/openshift-cluster: - Remove some stray debugging statements - Some minor formatting fixes - removing un-necessary quotes - cleaning up some jinja templates for readability - add a play to the launch playbook to apply the os_update_latest role on all hosts in the new environment - improve setting groups and gce_public_ip when using add_host module - set gce_public_ip as a variable for the host using the returned gce instance_data - add a group for each tag configured on the host (pre-pending tag_ to the tag name) - update the openshift-master/config.yml and openshift-node/config.yml includes to use the tag_env-host-type groups - openshift-{master,node}/config.yml - Some cleanup - remove some extraneous quotes - remove connection: ssh from remote hosts, since it is the default - remove user: root and instead set ansible_ssh_user in inventory/gce/group_vars/all - set openshift_public_ip and openshift_env to templated values in inventory/gce/group_vars/all as well - no longer set openshift_node_ips for the master host, since nodes will register themselves now when they are configured (prevent reboot on adding nodes) - move setting openshift_master_ips and openshift_public_master_ips using set_fact and instead use the vars: of the 'Configure Instances' play --- inventory/gce/group_vars/all | 4 + playbooks/gce/openshift-cluster/launch.yml | 22 +-- .../gce/openshift-cluster/launch_instances.yml | 8 +- playbooks/gce/openshift-master/config.yml | 40 +----- playbooks/gce/openshift-node/config.yml | 148 +++++++++++++++------ 5 files changed, 133 insertions(+), 89 deletions(-) create mode 100644 inventory/gce/group_vars/all diff --git a/inventory/gce/group_vars/all b/inventory/gce/group_vars/all new file mode 100644 index 000000000..4cd94c509 --- /dev/null +++ b/inventory/gce/group_vars/all @@ -0,0 +1,4 @@ +--- +ansible_ssh_user: root +openshift_public_ip: "{{ gce_public_ip }}" +openshift_env: "{{ oo_env }}" diff --git a/playbooks/gce/openshift-cluster/launch.yml b/playbooks/gce/openshift-cluster/launch.yml index ba9d58a74..c70c199c6 100644 --- a/playbooks/gce/openshift-cluster/launch.yml +++ b/playbooks/gce/openshift-cluster/launch.yml @@ -3,21 +3,19 @@ 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) }}" + - 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 %}" + instance_names_string: "{% for item in instance_names_output.results %}{{ item.ansible_facts.scratch }} {% endfor %}" - set_fact: master_names: "{{ instance_names_string.strip().split(' ') }}" @@ -31,14 +29,14 @@ - set_fact: k8s_type="node" - - name: "Generate node instance names(s)" - set_fact: scratch="{{ cluster_id }}-{{ k8s_type }}-{{ '%05x' |format( 1048576 |random) }}" + - 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 %}" + instance_names_string: "{% for item in instance_names_output.results %}{{ item.ansible_facts.scratch }} {% endfor %}" - set_fact: node_names: "{{ instance_names_string.strip().split(' ') }}" @@ -48,15 +46,17 @@ instances: "{{ node_names }}" cluster: "{{ cluster_id }}" type: "{{ k8s_type }}" - group_name: "tag_env-host-type-{{ cluster_id }}-openshift-node" +- hosts: "tag_env-{{ cluster_id }}" + roles: + - os_update_latest - include: ../openshift-master/config.yml vars: - oo_host_group_exp: "{{ master_names }}" + 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: "{{ node_names }}" + oo_host_group_exp: "groups[\"tag_env-host-type-{{ cluster_id }}-openshift-node\"]" oo_env: "{{ cluster_id }}" diff --git a/playbooks/gce/openshift-cluster/launch_instances.yml b/playbooks/gce/openshift-cluster/launch_instances.yml index ff19b94d8..443e763de 100644 --- a/playbooks/gce/openshift-cluster/launch_instances.yml +++ b/playbooks/gce/openshift-cluster/launch_instances.yml @@ -19,15 +19,17 @@ register: gce - name: Add new instances public IPs - add_host: "hostname={{ item.name }} ansible_ssh_host={{ item.public_ip }} groups={{ group_name }}" + 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 }}" 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/config.yml b/playbooks/gce/openshift-master/config.yml index 5581e8401..812dcb91b 100644 --- a/playbooks/gce/openshift-master/config.yml +++ b/playbooks/gce/openshift-master/config.yml @@ -1,50 +1,20 @@ -- name: "master/config.yml, populate oo_hosts_to_config host group if needed" +- 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_hosts_to_config" + add_host: "name={{ item }} groups=oo_masters_to_config" 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: "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 - 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" - hosts: oo_hosts_to_config - connection: ssh - user: root + hosts: oo_masters_to_config vars_files: - - vars.yml + - vars.yml roles: - - { - role: openshift_master, - openshift_node_ips: "{{ hostvars['localhost'].openshift_node_ips | default(['']) }}", - openshift_public_ip: "{{ gce_public_ip }}", - openshift_env: "{{ oo_env }}", - } + - openshift_master - pods - os_env_extras diff --git a/playbooks/gce/openshift-node/config.yml b/playbooks/gce/openshift-node/config.yml index 57b9e3198..17631d578 100644 --- a/playbooks/gce/openshift-node/config.yml +++ b/playbooks/gce/openshift-node/config.yml @@ -1,56 +1,124 @@ -- name: "node/config.yml, populate oo_hosts_to_config host group if needed" +- 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 - add_host: "name={{ item }} groups=oo_hosts_to_config" + 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'] -- name: "Gather facts for masters in {{ oo_env }}" +- name: Gather facts for masters in {{ oo_env }} 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 }}" + - 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: "Set OO sepcific facts on localhost (for later use)" - hosts: localhost - gather_facts: no +- name: Gather facts for hosts to configure + hosts: tag_env-host-type-{{ oo_env }}-openshift-node 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='gce_public_ip') }}" - when: groups['tag_env-host-type-' + oo_env + '-openshift-master'] is defined - -- name: "Configure instances" - hosts: oo_hosts_to_config - connection: ssh - user: root - vars_files: - - vars.yml + - 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 {} }}" +- name: Register nodes + hosts: tag_env-host-type-{{ oo_env }}-openshift-master[0] + 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: + roles: + - openshift_register_nodes tasks: - - debug: var=gce_public_ip + - 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 }}" + +# 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') }}" + cert_parent_rel_path: openshift.local.certificates + cert_rel_path: "{{ cert_parent_rel_path }}/node-{{ openshift_node_name }}" + 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: 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 + src: "{{ item.src }}" + dest: "{{ item.dest }}" + owner: no + group: no + with_items: + - src: "{{ hostvars[groups[openshift_master_group][0]].mktemp.stdout }}/{{ cert_rel_path }}" + dest: "{{ cert_parent_path }}" + - src: "{{ hostvars[groups[openshift_master_group][0]].mktemp.stdout }}/{{ 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 + 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_public_ip: "{{ gce_public_ip }}", - openshift_env: "{{ oo_env }}", - } - - docker + - openshift_node - os_env_extras + - os_env_extras_node + -- cgit v1.2.3 From 3324b6c8889074ee17d7be05588de8b58aa3774f 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) --- playbooks/gce/openshift-node/config.yml | 1 + roles/openshift_common/tasks/main.yml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/playbooks/gce/openshift-node/config.yml b/playbooks/gce/openshift-node/config.yml index 17631d578..7f80b90a7 100644 --- a/playbooks/gce/openshift-node/config.yml +++ b/playbooks/gce/openshift-node/config.yml @@ -53,6 +53,7 @@ roles: - openshift_register_nodes tasks: + tasks: - name: Create local temp directory for syncing certs local_action: command /usr/bin/mktemp -d /tmp/openshift-ansible-XXXXXXX register: mktemp 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 12745f3eb1f4eb99a27f03d6b7a60cd376add580 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Mon, 16 Mar 2015 15:12:10 -0400 Subject: Use env for gce params --- playbooks/gce/openshift-cluster/terminate.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/playbooks/gce/openshift-cluster/terminate.yml b/playbooks/gce/openshift-cluster/terminate.yml index eff52a807..ee536be69 100644 --- a/playbooks/gce/openshift-cluster/terminate.yml +++ b/playbooks/gce/openshift-cluster/terminate.yml @@ -13,13 +13,13 @@ - 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" + gce_service_account_email: "{{ lookup('env', 'gce_service_account_email_address') }}" + gce_pem_file: "{{ lookup('env', 'gce_service_account_pem_file_path') }}" + gce_project_id: "{{ lookup('env', 'gce_project_id') }}" - 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" + gce_service_account_email: "{{ lookup('env', 'gce_service_account_email_address') }}" + gce_pem_file: "{{ lookup('env', 'gce_service_account_pem_file_path') }}" + gce_project_id: "{{ lookup('env', 'gce_project_id') }}" -- cgit v1.2.3 From 6ad94864f7d985f1bb671536bd398ea4bcd0f163 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Mon, 16 Mar 2015 15:13:12 -0400 Subject: add repos role to gce cluster launch so that we are applying os_update_latest after repo config --- playbooks/gce/openshift-cluster/launch.yml | 1 + roles/openshift_common/tasks/main.yml | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/playbooks/gce/openshift-cluster/launch.yml b/playbooks/gce/openshift-cluster/launch.yml index c70c199c6..70025e103 100644 --- a/playbooks/gce/openshift-cluster/launch.yml +++ b/playbooks/gce/openshift-cluster/launch.yml @@ -49,6 +49,7 @@ - hosts: "tag_env-{{ cluster_id }}" roles: + - repos - os_update_latest - include: ../openshift-master/config.yml diff --git a/roles/openshift_common/tasks/main.yml b/roles/openshift_common/tasks/main.yml index 656a3880d..07737a71f 100644 --- a/roles/openshift_common/tasks/main.yml +++ b/roles/openshift_common/tasks/main.yml @@ -2,9 +2,6 @@ - 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 13dc8505feb93adc311a4a2d8e714c7d1e61cf1f Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Mon, 16 Mar 2015 15:15:03 -0400 Subject: Fix openshift_master_ips and openshift_master_public_ips resolution - don't use set_fact on localhost for openshift_master_ips and openshift_master_public_ips - we are only using it for the configure play - move definition to vars section of configure play - otherwise we'd have to set openshift_master_ips and openshift_master_public_ips from hostvars['localhost'] and since we aren't refrerencing it anywhere else, might as well just do it in vars instead of set_fact on locahost. --- playbooks/gce/openshift-node/config.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/playbooks/gce/openshift-node/config.yml b/playbooks/gce/openshift-node/config.yml index 7f80b90a7..9d87c4e8f 100644 --- a/playbooks/gce/openshift-node/config.yml +++ b/playbooks/gce/openshift-node/config.yml @@ -53,7 +53,6 @@ roles: - openshift_register_nodes tasks: - tasks: - name: Create local temp directory for syncing certs local_action: command /usr/bin/mktemp -d /tmp/openshift-ansible-XXXXXXX register: mktemp @@ -69,7 +68,7 @@ # - name: Configure instances hosts: oo_nodes_to_config - vars_files: +vars_files: - vars.yml vars: openshift_master_group: tag_env-host-type-{{ oo_env }}-openshift-master -- cgit v1.2.3 From 9575258e5a1b8f9ee8ec7ffc7ad74fa5dfeabc00 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Wed, 18 Mar 2015 13:25:18 -0400 Subject: replace oo_hosts_to_config with oo_nodes_to_config and oo_masters_to_config --- playbooks/aws/openshift-master/config.yml | 6 +++--- playbooks/aws/openshift-master/launch.yml | 4 ++-- playbooks/aws/openshift-node/config.yml | 6 +++--- playbooks/aws/openshift-node/launch.yml | 4 ++-- playbooks/gce/openshift-master/launch.yml | 4 ++-- playbooks/gce/openshift-node/config.yml | 1 - playbooks/gce/openshift-node/launch.yml | 8 ++++---- 7 files changed, 16 insertions(+), 17 deletions(-) diff --git a/playbooks/aws/openshift-master/config.yml b/playbooks/aws/openshift-master/config.yml index b3227afa9..bbf1f654a 100644 --- a/playbooks/aws/openshift-master/config.yml +++ b/playbooks/aws/openshift-master/config.yml @@ -1,10 +1,10 @@ --- -- name: "populate oo_hosts_to_config host group if needed" +- name: "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_hosts_to_config" + add_host: "name={{ item }} groups=oo_masters_to_config" with_items: "{{ oo_host_group_exp | default('') }}" when: oo_host_group_exp is defined @@ -25,7 +25,7 @@ when: groups['tag_env-host-type_' + oo_env + '-openshift-node'] is defined - name: "Configure instances" - hosts: oo_hosts_to_config + hosts: oo_masters_to_config connection: ssh user: root vars_files: diff --git a/playbooks/aws/openshift-master/launch.yml b/playbooks/aws/openshift-master/launch.yml index a889b93be..3d5a7f579 100644 --- a/playbooks/aws/openshift-master/launch.yml +++ b/playbooks/aws/openshift-master/launch.yml @@ -45,8 +45,8 @@ args: tags: "{{ oo_new_inst_tags }}" - - name: Add new instances public IPs to oo_hosts_to_config - add_host: "hostname={{ item.0 }} ansible_ssh_host={{ item.1.dns_name }} groupname=oo_hosts_to_config" + - 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" with_together: - oo_new_inst_names - ec2.instances diff --git a/playbooks/aws/openshift-node/config.yml b/playbooks/aws/openshift-node/config.yml index 21807b1cf..822b66464 100644 --- a/playbooks/aws/openshift-node/config.yml +++ b/playbooks/aws/openshift-node/config.yml @@ -1,10 +1,10 @@ --- -- name: "populate oo_hosts_to_config host group if needed" +- name: "populate oo_nodes_to_config host group if needed" hosts: localhost gather_facts: no tasks: - name: Evaluate oo_host_group_exp - add_host: "name={{ item }} groups=oo_hosts_to_config" + add_host: "name={{ item }} groups=oo_nodes_to_config" with_items: "{{ oo_host_group_exp | default('') }}" when: oo_host_group_exp is defined @@ -31,7 +31,7 @@ when: groups['tag_env-host-type-' + oo_env + '-openshift-master'] is defined - name: "Configure instances" - hosts: oo_hosts_to_config + hosts: oo_nodes_to_config connection: ssh user: root vars_files: diff --git a/playbooks/aws/openshift-node/launch.yml b/playbooks/aws/openshift-node/launch.yml index a889b93be..4745fc658 100644 --- a/playbooks/aws/openshift-node/launch.yml +++ b/playbooks/aws/openshift-node/launch.yml @@ -45,8 +45,8 @@ args: tags: "{{ oo_new_inst_tags }}" - - name: Add new instances public IPs to oo_hosts_to_config - add_host: "hostname={{ item.0 }} ansible_ssh_host={{ item.1.dns_name }} groupname=oo_hosts_to_config" + - 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" with_together: - oo_new_inst_names - ec2.instances diff --git a/playbooks/gce/openshift-master/launch.yml b/playbooks/gce/openshift-master/launch.yml index f2800b061..3512274cc 100644 --- a/playbooks/gce/openshift-master/launch.yml +++ b/playbooks/gce/openshift-master/launch.yml @@ -24,8 +24,8 @@ tags: "{{ oo_new_inst_tags }}" register: gce - - name: Add new instances public IPs to oo_hosts_to_config - add_host: "hostname={{ item.name }} ansible_ssh_host={{ item.public_ip }} groupname=oo_hosts_to_config" + - 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" with_items: gce.instance_data - name: Wait for ssh diff --git a/playbooks/gce/openshift-node/config.yml b/playbooks/gce/openshift-node/config.yml index 9d87c4e8f..d24acb8fa 100644 --- a/playbooks/gce/openshift-node/config.yml +++ b/playbooks/gce/openshift-node/config.yml @@ -121,4 +121,3 @@ vars_files: - 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 935599efd..ca2914d8a 100644 --- a/playbooks/gce/openshift-node/launch.yml +++ b/playbooks/gce/openshift-node/launch.yml @@ -24,8 +24,8 @@ tags: "{{ oo_new_inst_tags }}" register: gce - - name: Add new instances public IPs to oo_hosts_to_config - add_host: "hostname={{ item.name }} ansible_ssh_host={{ item.public_ip }} groupname=oo_hosts_to_config" + - 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" with_items: gce.instance_data - name: Wait for ssh @@ -48,10 +48,10 @@ # Always bounce service to pick up new credentials #- name: "Restart instances" -# hosts: oo_hosts_to_config +# hosts: oo_nodes_to_config # connection: ssh # user: root # tasks: -# - debug: var=groups.oo_hosts_to_config +# - debug: var=groups.oo_nodes_to_config # - name: Restart OpenShift # service: name=openshift-node enabled=yes state=restarted -- cgit v1.2.3 From 011ff923489fd1dd5fa072a685ce881ab69b8f1c Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Wed, 18 Mar 2015 13:26:46 -0400 Subject: use more specific variable names in gce/openshift-cluster/launch.yml --- playbooks/gce/openshift-cluster/launch.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/playbooks/gce/openshift-cluster/launch.yml b/playbooks/gce/openshift-cluster/launch.yml index 70025e103..b30452725 100644 --- a/playbooks/gce/openshift-cluster/launch.yml +++ b/playbooks/gce/openshift-cluster/launch.yml @@ -10,15 +10,15 @@ - name: Generate master instance names(s) set_fact: scratch={{ cluster_id }}-{{ k8s_type }}-{{ '%05x' |format( 1048576 |random) }} - register: instance_names_output + register: master_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 %}" + master_names_string: "{% for item in master_names_output.results %}{{ item.ansible_facts.scratch }} {% endfor %}" - set_fact: - master_names: "{{ instance_names_string.strip().split(' ') }}" + master_names: "{{ master_names_string.strip().split(' ') }}" - include: launch_instances.yml vars: @@ -31,15 +31,15 @@ - name: Generate node instance names(s) set_fact: scratch={{ cluster_id }}-{{ k8s_type }}-{{ '%05x' |format( 1048576 |random) }} - register: instance_names_output + register: node_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 %}" + node_names_string: "{% for item in node_names_output.results %}{{ item.ansible_facts.scratch }} {% endfor %}" - set_fact: - node_names: "{{ instance_names_string.strip().split(' ') }}" + node_names: "{{ node_names_string.strip().split(' ') }}" - include: launch_instances.yml vars: -- cgit v1.2.3 From 85e6948fca954d3c066bf5a6123ada6b96adf45c Mon Sep 17 00:00:00 2001 From: Jhon Honce Date: Thu, 19 Mar 2015 15:06:38 -0700 Subject: * Add DOCKER chain to iptables --- README.md | 2 +- playbooks/gce/openshift-cluster/terminate.yml | 5 ----- roles/os_firewall/tasks/firewall/iptables.yml | 14 ++++++++++++++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ffdfee6f2..906d2e3f2 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Setup - Directory Structure: - [cloud.rb](cloud.rb) - light wrapper around Ansible - - [cluster.sh](cluster.sh) - easily create OpenShift 3 clusters + - [bin/cluster](bin/cluster) - python script to easily create OpenShift 3 clusters - [filter_plugins/](filter_plugins) - custom filters used to manipulate data in Ansible - [inventory/](inventory) - houses Ansible dynamic inventory scripts - [lib/](lib) - library components of cloud.rb diff --git a/playbooks/gce/openshift-cluster/terminate.yml b/playbooks/gce/openshift-cluster/terminate.yml index ee536be69..0281ae953 100644 --- a/playbooks/gce/openshift-cluster/terminate.yml +++ b/playbooks/gce/openshift-cluster/terminate.yml @@ -5,11 +5,6 @@ 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"]' diff --git a/roles/os_firewall/tasks/firewall/iptables.yml b/roles/os_firewall/tasks/firewall/iptables.yml index 87e77c083..3d46d6e2d 100644 --- a/roles/os_firewall/tasks/firewall/iptables.yml +++ b/roles/os_firewall/tasks/firewall/iptables.yml @@ -41,6 +41,20 @@ changed_when: "'firewalld' in result.stdout" when: pkg_check.rc == 0 +- name: Check for DOCKER chain + shell: iptables -L |grep '^Chain DOCKER' + ignore_errors: yes + register: check_for_chain + +- name: Create DOCKER chain + command: iptables -N DOCKER + register: create_chain + when: check_for_chain.rc != 0 + +- name: Persist DOCKER chain + command: service iptables save + when: create_chain.rc == 0 + - name: Add iptables allow rules os_firewall_manage_iptables: name: "{{ item.service }}" -- cgit v1.2.3 From 9fb5bbc79a6753c6125e4f3ea007040dad0482ef Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Thu, 19 Mar 2015 23:04:21 -0400 Subject: Add verify_chain action to os_firewall_manage_iptables module - Add verify_chain action to os_firewall_manage_iptables module - Update os_firewall module to use os_firewall_manage_iptables for creating the DOCKER chain. --- .../library/os_firewall_manage_iptables.py | 62 ++++++++++++++-------- roles/os_firewall/tasks/firewall/iptables.yml | 20 +++---- 2 files changed, 47 insertions(+), 35 deletions(-) diff --git a/roles/os_firewall/library/os_firewall_manage_iptables.py b/roles/os_firewall/library/os_firewall_manage_iptables.py index fef710055..6a018d022 100644 --- a/roles/os_firewall/library/os_firewall_manage_iptables.py +++ b/roles/os_firewall/library/os_firewall_manage_iptables.py @@ -51,11 +51,13 @@ class IpTablesCreateJumpRuleError(IpTablesError): # exception was thrown later. for example, when the chain is created # successfully, but the add/remove rule fails. class IpTablesManager: - def __init__(self, module, ip_version, check_mode, chain): + def __init__(self, module): self.module = module - self.ip_version = ip_version - self.check_mode = check_mode - self.chain = chain + self.ip_version = module.params['ip_version'] + self.check_mode = module.check_mode + self.chain = module.params['chain'] + self.create_jump_rule = module.params['create_jump_rule'] + self.jump_rule_chain = module.params['jump_rule_chain'] self.cmd = self.gen_cmd() self.save_cmd = self.gen_save_cmd() self.output = [] @@ -70,13 +72,16 @@ class IpTablesManager: msg="Failed to save iptables rules", cmd=e.cmd, exit_code=e.returncode, output=e.output) + def verify_chain(self): + if not self.chain_exists(): + self.create_chain() + if self.create_jump_rule and not self.jump_rule_exists(): + self.create_jump() + def add_rule(self, port, proto): rule = self.gen_rule(port, proto) if not self.rule_exists(rule): - if not self.chain_exists(): - self.create_chain() - if not self.jump_rule_exists(): - self.create_jump_rule() + self.verify_chain() if self.check_mode: self.changed = True @@ -121,13 +126,13 @@ class IpTablesManager: return [self.chain, '-p', proto, '-m', 'state', '--state', 'NEW', '-m', proto, '--dport', str(port), '-j', 'ACCEPT'] - def create_jump_rule(self): + def create_jump(self): if self.check_mode: self.changed = True self.output.append("Create jump rule for chain %s" % self.chain) else: try: - cmd = self.cmd + ['-L', 'INPUT', '--line-numbers'] + cmd = self.cmd + ['-L', self.jump_rule_chain, '--line-numbers'] output = check_output(cmd, stderr=subprocess.STDOUT) # break the input rules into rows and columns @@ -144,11 +149,11 @@ class IpTablesManager: continue last_rule_target = rule[1] - # Raise an exception if we do not find a valid INPUT rule + # Raise an exception if we do not find a valid rule if not last_rule_num or not last_rule_target: raise IpTablesCreateJumpRuleError( chain=self.chain, - msg="Failed to find existing INPUT rules", + msg="Failed to find existing %s rules" % self.jump_rule_chain, cmd=None, exit_code=None, output=None) # Naively assume that if the last row is a REJECT rule, then @@ -156,19 +161,20 @@ class IpTablesManager: # assume that we can just append the rule. if last_rule_target == 'REJECT': # insert rule - cmd = self.cmd + ['-I', 'INPUT', str(last_rule_num)] + cmd = self.cmd + ['-I', self.jump_rule_chain, str(last_rule_num)] else: # append rule - cmd = self.cmd + ['-A', 'INPUT'] + cmd = self.cmd + ['-A', self.jump_rule_chain] cmd += ['-j', self.chain] output = check_output(cmd, stderr=subprocess.STDOUT) changed = True self.output.append(output) + self.save() except subprocess.CalledProcessError as e: if '--line-numbers' in e.cmd: raise IpTablesCreateJumpRuleError( chain=self.chain, - msg="Failed to query existing INPUT rules to " + msg="Failed to query existing %s rules to " % self.jump_rule_chain + "determine jump rule location", cmd=e.cmd, exit_code=e.returncode, output=e.output) @@ -192,6 +198,7 @@ class IpTablesManager: self.changed = True self.output.append("Successfully created chain %s" % self.chain) + self.save() except subprocess.CalledProcessError as e: raise IpTablesCreateChainError( chain=self.chain, @@ -200,7 +207,7 @@ class IpTablesManager: ) def jump_rule_exists(self): - cmd = self.cmd + ['-C', 'INPUT', '-j', self.chain] + cmd = self.cmd + ['-C', self.jump_rule_chain, '-j', self.chain] return True if subprocess.call(cmd) == 0 else False def chain_exists(self): @@ -220,9 +227,12 @@ def main(): module = AnsibleModule( argument_spec=dict( name=dict(required=True), - action=dict(required=True, choices=['add', 'remove']), - protocol=dict(required=True, choices=['tcp', 'udp']), - port=dict(required=True, type='int'), + action=dict(required=True, choices=['add', 'remove', 'verify_chain']), + chain=dict(required=False, default='OS_FIREWALL_ALLOW'), + create_jump_rule=dict(required=False, type='bool', default=True), + jump_rule_chain=dict(required=False, default='INPUT'), + protocol=dict(required=False, choices=['tcp', 'udp']), + port=dict(required=False, type='int'), ip_version=dict(required=False, default='ipv4', choices=['ipv4', 'ipv6']), ), @@ -232,16 +242,24 @@ def main(): action = module.params['action'] protocol = module.params['protocol'] port = module.params['port'] - ip_version = module.params['ip_version'] - chain = 'OS_FIREWALL_ALLOW' - iptables_manager = IpTablesManager(module, ip_version, module.check_mode, chain) + if action in ['add', 'remove']: + if not protocol: + error = "protocol is required when action is %s" % action + module.fail_json(msg=error) + if not port: + error = "port is required when action is %s" % action + module.fail_json(msg=error) + + iptables_manager = IpTablesManager(module) try: if action == 'add': iptables_manager.add_rule(port, protocol) elif action == 'remove': iptables_manager.remove_rule(port, protocol) + elif action == 'verify_chain': + iptables_manager.verify_chain() except IpTablesError as e: module.fail_json(msg=e.msg) diff --git a/roles/os_firewall/tasks/firewall/iptables.yml b/roles/os_firewall/tasks/firewall/iptables.yml index 3d46d6e2d..72a3401cf 100644 --- a/roles/os_firewall/tasks/firewall/iptables.yml +++ b/roles/os_firewall/tasks/firewall/iptables.yml @@ -41,19 +41,13 @@ changed_when: "'firewalld' in result.stdout" when: pkg_check.rc == 0 -- name: Check for DOCKER chain - shell: iptables -L |grep '^Chain DOCKER' - ignore_errors: yes - register: check_for_chain - -- name: Create DOCKER chain - command: iptables -N DOCKER - register: create_chain - when: check_for_chain.rc != 0 - -- name: Persist DOCKER chain - command: service iptables save - when: create_chain.rc == 0 +# Workaround for Docker 1.4 to create DOCKER chain +- name: Add DOCKER chain + os_firewall_manage_iptables: + name: "DOCKER chain" + action: verify_chain + create_jump_rule: no +# End of Docker 1.4 workaround - name: Add iptables allow rules os_firewall_manage_iptables: -- 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(-) 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(-) 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 8f35aff7245246de4116fcf3c81e7f095cf1be3a Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Sun, 22 Mar 2015 22:11:22 -0400 Subject: Add new role os_env_extras_node that is a subset of the docker role - Does not install or start docker, since the openshift-node role will handle that for us - Only add root to the dockerroot group and configures the enter-container script. --- playbooks/aws/openshift-node/config.yml | 2 +- roles/os_env_extras_node/README.md | 38 +++++++ roles/os_env_extras_node/files/enter-container.sh | 13 +++ roles/os_env_extras_node/meta/main.yml | 124 ++++++++++++++++++++++ roles/os_env_extras_node/tasks/main.yml | 7 ++ 5 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 roles/os_env_extras_node/README.md create mode 100755 roles/os_env_extras_node/files/enter-container.sh create mode 100644 roles/os_env_extras_node/meta/main.yml create mode 100644 roles/os_env_extras_node/tasks/main.yml diff --git a/playbooks/aws/openshift-node/config.yml b/playbooks/aws/openshift-node/config.yml index 822b66464..3cf2c58b2 100644 --- a/playbooks/aws/openshift-node/config.yml +++ b/playbooks/aws/openshift-node/config.yml @@ -44,5 +44,5 @@ openshift_env: "{{ oo_env }}", openshift_public_ip: "{{ ec2_ip_address }}" } - - docker - os_env_extras + - os_env_extras_node diff --git a/roles/os_env_extras_node/README.md b/roles/os_env_extras_node/README.md new file mode 100644 index 000000000..225dd44b9 --- /dev/null +++ b/roles/os_env_extras_node/README.md @@ -0,0 +1,38 @@ +Role Name +========= + +A brief description of the role goes here. + +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. + +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. + +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. + +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 } + +License +------- + +BSD + +Author Information +------------------ + +An optional section for the role authors to include contact information, or a website (HTML is not allowed). diff --git a/roles/os_env_extras_node/files/enter-container.sh b/roles/os_env_extras_node/files/enter-container.sh new file mode 100755 index 000000000..7cf5b8d83 --- /dev/null +++ b/roles/os_env_extras_node/files/enter-container.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +if [ $# -ne 1 ] +then + echo + echo "Usage: $(basename $0) " + echo + exit 1 +fi + +PID=$(docker inspect --format '{{.State.Pid}}' $1) + +nsenter --target $PID --mount --uts --ipc --net --pid diff --git a/roles/os_env_extras_node/meta/main.yml b/roles/os_env_extras_node/meta/main.yml new file mode 100644 index 000000000..c5c362c60 --- /dev/null +++ b/roles/os_env_extras_node/meta/main.yml @@ -0,0 +1,124 @@ +--- +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: 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. + 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..065f71f74 --- /dev/null +++ b/roles/os_env_extras_node/tasks/main.yml @@ -0,0 +1,7 @@ +--- +- copy: src=enter-container.sh dest=/usr/local/bin/enter-container.sh mode=0755 + +# 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 -- cgit v1.2.3 From 70c5a715debc1c1a900c6dcfe178b36b2a014ab4 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Sun, 22 Mar 2015 22:14:17 -0400 Subject: Use docker as package name instead of docker-io --- roles/docker/tasks/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/docker/tasks/main.yml b/roles/docker/tasks/main.yml index ca700db17..593c4c877 100644 --- a/roles/docker/tasks/main.yml +++ b/roles/docker/tasks/main.yml @@ -1,7 +1,7 @@ --- # tasks file for docker - name: Install docker - yum: pkg=docker-io + yum: pkg=docker - name: enable and start the docker service service: name=docker enabled=yes state=started -- cgit v1.2.3 From 8b68846806d5294b5f43d14772d59aa2b8cf5e73 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Sun, 22 Mar 2015 22:43:00 -0400 Subject: remove os_firewall creation of DOCKER chain --- roles/os_firewall/tasks/firewall/iptables.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/roles/os_firewall/tasks/firewall/iptables.yml b/roles/os_firewall/tasks/firewall/iptables.yml index 72a3401cf..87e77c083 100644 --- a/roles/os_firewall/tasks/firewall/iptables.yml +++ b/roles/os_firewall/tasks/firewall/iptables.yml @@ -41,14 +41,6 @@ changed_when: "'firewalld' in result.stdout" when: pkg_check.rc == 0 -# Workaround for Docker 1.4 to create DOCKER chain -- name: Add DOCKER chain - os_firewall_manage_iptables: - name: "DOCKER chain" - action: verify_chain - create_jump_rule: no -# End of Docker 1.4 workaround - - name: Add iptables allow rules os_firewall_manage_iptables: name: "{{ item.service }}" -- 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(-) 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 461f6c1e07f36238729944a5f769600077ebf0b0 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Wed, 18 Mar 2015 17:15:19 -0400 Subject: Rename repos role to openshift_repos - Rename repos role to openshift_repos - Make openshift_repos a dependency of openshift_common - Add README and metadata for openshift_repos - Playbook updates for role rename - Verify libselinux-python is installed, otherwise some of the bulit-in modules we use fail --- playbooks/gce/openshift-master/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playbooks/gce/openshift-master/config.yml b/playbooks/gce/openshift-master/config.yml index 812dcb91b..e405e2fb4 100644 --- a/playbooks/gce/openshift-master/config.yml +++ b/playbooks/gce/openshift-master/config.yml @@ -7,7 +7,7 @@ with_items: "{{ oo_host_group_exp | default('') }}" when: oo_host_group_exp is defined -- name: "Gather facts for nodes in {{ oo_env }}" +- name: Gather facts for nodes in {{ oo_env }} hosts: "tag_env-host-type-{{ oo_env }}-openshift-node" - name: "Configure instances" -- cgit v1.2.3 From d67c5b8f79609d2d3b07cc009f58e3dc988782c5 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Mon, 23 Mar 2015 16:30:49 -0400 Subject: node registration changes - Remove default value for openshift_hostname and make it required - Remove workarounds that are no longer needed - Remove resources parameter from openshift_register_node module - pre-create node certificates for each node before registering node - distribute created node certificates to each node - Move node registration logic to a new openshift_register_nodes role - This is because we now have to run the steps on a master as opposed to on the nodes like we were previously doing. - Rename openshift_register_node module to kubernetes_register_node, one more step to genericizing enough for upstreaming, however there are still plenty of openshift specific commands that still need to be genericized. --- roles/openshift_common/README.md | 2 +- roles/openshift_common/defaults/main.yml | 2 +- roles/openshift_master/README.md | 2 +- roles/openshift_master/tasks/main.yml | 35 +- roles/openshift_node/README.md | 3 +- roles/openshift_node/defaults/main.yml | 6 - .../library/openshift_register_node.py | 390 --------------------- roles/openshift_node/tasks/main.yml | 68 +--- roles/openshift_register_nodes/README.md | 38 ++ roles/openshift_register_nodes/defaults/main.yml | 5 + .../library/kubernetes_register_node.py | 370 +++++++++++++++++++ roles/openshift_register_nodes/meta/main.yml | 128 +++++++ roles/openshift_register_nodes/tasks/main.yml | 71 ++++ roles/openshift_sdn_node/README.md | 2 +- 14 files changed, 641 insertions(+), 481 deletions(-) delete mode 100644 roles/openshift_node/library/openshift_register_node.py create mode 100644 roles/openshift_register_nodes/README.md create mode 100644 roles/openshift_register_nodes/defaults/main.yml create mode 100644 roles/openshift_register_nodes/library/kubernetes_register_node.py create mode 100644 roles/openshift_register_nodes/meta/main.yml create mode 100644 roles/openshift_register_nodes/tasks/main.yml diff --git a/roles/openshift_common/README.md b/roles/openshift_common/README.md index fce79047c..592a276f9 100644 --- a/roles/openshift_common/README.md +++ b/roles/openshift_common/README.md @@ -16,7 +16,7 @@ Role Variables |-------------------------------|------------------------------|----------------------------------------| | openshift_debug_level | 0 | Global openshift debug log verbosity | | openshift_hostname_workaround | True | Workaround needed to set hostname to IP address | -| openshift_hostname | openshift_public_ip if openshift_hostname_workaround else ansible_fqdn | hostname to use for this instance | +| 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 | diff --git a/roles/openshift_common/defaults/main.yml b/roles/openshift_common/defaults/main.yml index eb6edbc03..86351f6f6 100644 --- a/roles/openshift_common/defaults/main.yml +++ b/roles/openshift_common/defaults/main.yml @@ -4,4 +4,4 @@ openshift_debug_level: 0 # TODO: Once openshift stops resolving hostnames for node queries remove # this... openshift_hostname_workaround: true -openshift_hostname: "{{ ansible_default_ipv4.address if openshift_hostname_workaround else ansible_fqdn }}" + diff --git a/roles/openshift_master/README.md b/roles/openshift_master/README.md index 5a1b889b2..2f03b4990 100644 --- a/roles/openshift_master/README.md +++ b/roles/openshift_master/README.md @@ -27,7 +27,7 @@ From openshift_common: | openshift_debug_level | 0 | Global openshift debug log verbosity | | openshift_hostname_workaround | True | | | openshift_public_ip | UNDEF (Required) | Public IP address to use for this host | -| openshift_hostname | openshift_public_ip if openshift_hostname_workaround else ansible_fqdn | hostname to use for this instance | +| openshift_hostname | UNDEF (Required) | hostname to use for this instance | Dependencies ------------ diff --git a/roles/openshift_master/tasks/main.yml b/roles/openshift_master/tasks/main.yml index d5f4776dc..52f5f694c 100644 --- a/roles/openshift_master/tasks/main.yml +++ b/roles/openshift_master/tasks/main.yml @@ -1,4 +1,8 @@ --- +# 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 + - name: Install OpenShift Master package yum: pkg=openshift-master state=installed @@ -6,9 +10,7 @@ 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=\"--public-master={{ openshift_hostname }} {% if openshift_node_ips %} --nodes={{ openshift_node_ips | join(',') }} {% endif %} --loglevel={{ openshift_master_debug_level }}\"" notify: - restart openshift-master @@ -34,42 +36,15 @@ option: externally_managed value: "{{ openshift_master_manage_service_externally }}" -# TODO: remove this when origin PR #1298 has landed in OSE -- name: Workaround for openshift-master taking longer than 90 seconds to issue sdNotify signal - command: cp /usr/lib/systemd/system/openshift-master.service /etc/systemd/system/ - args: - creates: /etc/systemd/system/openshift-master.service -- ini_file: - dest: /etc/systemd/system/openshift-master.service - option: TimeoutStartSec - section: Service - value: 300 - state: present - register: result -- command: systemctl daemon-reload - when: result | changed -# End of workaround pending PR #1298 - - name: Start and enable openshift-master service: name=openshift-master enabled=yes state=started when: not openshift_master_manage_service_externally register: result -#TODO: remove this when origin PR #1204 has landed in OSE -- name: need to pause here, otherwise we attempt to copy certificates generated by the master before they are generated - pause: seconds=30 - when: result | changed -# End of workaround pending PR #1204 - - name: Disable openshift-master if openshift-master is managed externally service: name=openshift-master enabled=false when: openshift_master_manage_service_externally -# TODO: create an os_vars role that has generic env related config and move -# the root kubeconfig setting there, cannot use dependencies to force ordering -# with openshift_node and openshift_master because the way conditional -# dependencies work with current ansible would also exclude the -# openshift_common dependency. - name: Create .kube directory file: path: /root/.kube diff --git a/roles/openshift_node/README.md b/roles/openshift_node/README.md index 9210bab16..d537a35a5 100644 --- a/roles/openshift_node/README.md +++ b/roles/openshift_node/README.md @@ -21,7 +21,6 @@ From this role: | 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 | -| openshift_node_resources | { capacity: { cpu: , memory: } } | Resource specification for this node, cpu is the number of CPUs to advertise and memory is the amount of memory in bytes to advertise. Default values chosen when not set are the number of logical CPUs for the host and 75% of total system memory | From openshift_common: | Name | Default Value | | @@ -29,7 +28,7 @@ From openshift_common: | openshift_debug_level | 0 | Global openshift debug log verbosity | | openshift_hostname_workaround | True | | | openshift_public_ip | UNDEF (Required) | Public IP address to use for this host | -| openshift_hostname | openshift_public_ip if openshift_hostname_workaround else ansible_fqdn | hostname to use for this instance | +| openshift_hostname | UNDEF (Required) | hostname to use for this instance | Dependencies ------------ diff --git a/roles/openshift_node/defaults/main.yml b/roles/openshift_node/defaults/main.yml index e4d5ebfee..6dc73a96e 100644 --- a/roles/openshift_node/defaults/main.yml +++ b/roles/openshift_node/defaults/main.yml @@ -4,9 +4,3 @@ openshift_node_debug_level: "{{ openshift_debug_level | default(0) }}" os_firewall_allow: - service: OpenShift kubelet port: 10250/tcp -openshift_node_resources: - cpu: - memory: - cidr: -openshift_node_labels: {} -openshift_node_annotations: {} diff --git a/roles/openshift_node/library/openshift_register_node.py b/roles/openshift_node/library/openshift_register_node.py deleted file mode 100644 index 4922585d7..000000000 --- a/roles/openshift_node/library/openshift_register_node.py +++ /dev/null @@ -1,390 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# vim: expandtab:tabstop=4:shiftwidth=4 - -import os -import multiprocessing -import socket -from subprocess import check_output, Popen -from decimal import * - -DOCUMENTATION = ''' ---- -module: kubernetes_register_node -short_description: Registers a kubernetes node with a master -description: - - Registers a kubernetes node with a master -options: - name: - default: null - description: - - Identifier for this node (usually the node fqdn). - required: true - api_verison: - choices: ['v1beta1', 'v1beta3'] - default: 'v1beta1' - description: - - Kubernetes API version to use - required: true - host_ip: - default: null - description: - - IP Address to associate with the node when registering. - Available in the following API versions: v1beta1. - required: false - hostnames: - default: [] - description: - - Valid hostnames for this node. Available in the following API - versions: v1beta3. - required: false - external_ips: - default: [] - description: - - External IP Addresses for this node. Available in the following API - versions: v1beta3. - required: false - internal_ips: - default: [] - description: - - Internal IP Addresses for this node. Available in the following API - versions: v1beta3. - required: false - cpu: - default: null - description: - - Number of CPUs to allocate for this node. If not provided, then - the node will be registered to advertise the number of logical - CPUs available. When using the v1beta1 API, you must specify the - CPU count as a floating point number with no more than 3 decimal - places. API version v1beta3 and newer accepts arbitrary float - values. - required: false - memory: - default: null - description: - - Memory available for this node. If not provided, then the node - will be registered to advertise 80% of MemTotal as available - memory. When using the v1beta1 API, you must specify the memory - size in bytes. API version v1beta3 and newer accepts binary SI - and decimal SI values. - required: false -''' -EXAMPLES = ''' -# Minimal node registration -- openshift_register_node: name=ose3.node.example.com - -# Node registration using the v1beta1 API and assigning 1 CPU core and 10 GB of -# Memory -- openshift_register_node: - name: ose3.node.example.com - api_version: v1beta1 - hostIP: 192.168.1.1 - cpu: 1 - memory: 500000000 - -# Node registration using the v1beta3 API, setting an alternate hostname, -# internalIP, externalIP and assigning 3.5 CPU cores and 1 TiB of Memory -- openshift_register_node: - name: ose3.node.example.com - api_version: v1beta3 - external_ips: ['192.168.1.5'] - internal_ips: ['10.0.0.5'] - hostnames: ['ose2.node.internal.local'] - cpu: 3.5 - memory: 1Ti -''' - - -class ClientConfigException(Exception): - pass - -class ClientConfig: - def __init__(self, client_opts, module): - _, output, error = module.run_command(["/usr/bin/openshift", "ex", - "config", "view", "-o", - "json"] + client_opts, - check_rc = True) - self.config = json.loads(output) - - if not (bool(self.config['clusters']) or - bool(self.config['contexts']) or - bool(self.config['current-context']) or - bool(self.config['users'])): - raise ClientConfigException(msg="Client config missing required " \ - "values", - output=output) - - def current_context(self): - return self.config['current-context'] - - def section_has_value(self, section_name, value): - section = self.config[section_name] - if isinstance(section, dict): - return value in section - else: - val = next((item for item in section - if item['name'] == value), None) - return val is not None - - def has_context(self, context): - return self.section_has_value('contexts', context) - - def has_user(self, user): - return self.section_has_value('users', user) - - def has_cluster(self, cluster): - return self.section_has_value('clusters', cluster) - - def get_value_for_context(self, context, attribute): - contexts = self.config['contexts'] - if isinstance(contexts, dict): - return contexts[context][attribute] - else: - return next((c['context'][attribute] for c in contexts - if c['name'] == context), None) - - def get_user_for_context(self, context): - return self.get_value_for_context(context, 'user') - - def get_cluster_for_context(self, context): - return self.get_value_for_context(context, 'cluster') - -class Util: - @staticmethod - def getLogicalCores(): - return multiprocessing.cpu_count() - - @staticmethod - def getMemoryPct(pct): - with open('/proc/meminfo', 'r') as mem: - for line in mem: - entries = line.split() - if str(entries.pop(0)) == 'MemTotal:': - mem_total_kb = Decimal(entries.pop(0)) - mem_capacity_kb = mem_total_kb * Decimal(pct) - return str(mem_capacity_kb.to_integral_value() * 1024) - - return "" - - @staticmethod - def remove_empty_elements(mapping): - if isinstance(mapping, dict): - m = mapping.copy() - for key, val in mapping.iteritems(): - if not val: - del m[key] - return m - else: - return mapping - -class NodeResources: - def __init__(self, version, cpu=None, memory=None): - if version == 'v1beta1': - self.resources = dict(capacity=dict()) - self.resources['capacity']['cpu'] = cpu if cpu else Util.getLogicalCores() - self.resources['capacity']['memory'] = memory if cpu else Util.getMemoryPct(.75) - - def get_resources(self): - return Util.remove_empty_elements(self.resources) - -class NodeSpec: - def __init__(self, version, cpu=None, memory=None, cidr=None, externalID=None): - if version == 'v1beta3': - self.spec = dict(podCIDR=cidr, externalID=externalID, - capacity=dict()) - self.spec['capacity']['cpu'] = cpu if cpu else Util.getLogicalCores() - self.spec['capacity']['memory'] = memory if memory else Util.getMemoryPct(.75) - - def get_spec(self): - return Util.remove_empty_elements(self.spec) - -class NodeStatus: - def addAddresses(self, addressType, addresses): - addressList = [] - for address in addresses: - addressList.append(dict(type=addressType, address=address)) - return addressList - - def __init__(self, version, externalIPs = [], internalIPs = [], - hostnames = []): - if version == 'v1beta3': - self.status = dict(addresses = addAddresses('ExternalIP', - externalIPs) + - addAddresses('InternalIP', - internalIPs) + - addAddresses('Hostname', - hostnames)) - - def get_status(self): - return Util.remove_empty_elements(self.status) - -class Node: - def __init__(self, module, client_opts, version='v1beta1', name=None, - hostIP = None, hostnames=[], externalIPs=[], internalIPs=[], - cpu=None, memory=None, labels=dict(), annotations=dict(), - podCIDR=None, externalID=None): - self.module = module - self.client_opts = client_opts - if version == 'v1beta1': - self.node = dict(id = name, - kind = 'Node', - apiVersion = version, - hostIP = hostIP, - resources = NodeResources(version, cpu, memory), - cidr = podCIDR, - labels = labels, - annotations = annotations - ) - elif version == 'v1beta3': - metadata = dict(name = name, - labels = labels, - annotations = annotations - ) - self.node = dict(kind = 'Node', - apiVersion = version, - metadata = metadata, - spec = NodeSpec(version, cpu, memory, podCIDR, - externalID), - status = NodeStatus(version, externalIPs, - internalIPs, hostnames), - ) - - def get_name(self): - if self.node['apiVersion'] == 'v1beta1': - return self.node['id'] - elif self.node['apiVersion'] == 'v1beta3': - return self.node['name'] - - def get_node(self): - node = self.node.copy() - if self.node['apiVersion'] == 'v1beta1': - node['resources'] = self.node['resources'].get_resources() - elif self.node['apiVersion'] == 'v1beta3': - node['spec'] = self.node['spec'].get_spec() - node['status'] = self.node['status'].get_status() - return Util.remove_empty_elements(node) - - def exists(self): - _, output, error = self.module.run_command(["/usr/bin/osc", "get", - "nodes"] + self.client_opts, - check_rc = True) - if re.search(self.module.params['name'], output, re.MULTILINE): - return True - return False - - def create(self): - cmd = ['/usr/bin/osc'] + self.client_opts + ['create', 'node', '-f', '-'] - rc, output, error = self.module.run_command(cmd, - data=self.module.jsonify(self.get_node())) - if rc != 0: - if re.search("minion \"%s\" already exists" % self.get_name(), - error): - self.module.exit_json(changed=False, - msg="node definition already exists", - node=self.get_node()) - else: - self.module.fail_json(msg="Node creation failed.", rc=rc, - output=output, error=error, - node=self.get_node()) - else: - return True - -def main(): - module = AnsibleModule( - argument_spec = dict( - name = dict(required = True, type = 'str'), - host_ip = dict(type = 'str'), - hostnames = dict(type = 'list', default = []), - external_ips = dict(type = 'list', default = []), - internal_ips = dict(type = 'list', default = []), - api_version = dict(type = 'str', default = 'v1beta1', # TODO: after kube rebase, we can default to v1beta3 - choices = ['v1beta1', 'v1beta3']), - cpu = dict(type = 'str'), - memory = dict(type = 'str'), - labels = dict(type = 'dict', default = {}), # TODO: needs documented - annotations = dict(type = 'dict', default = {}), # TODO: needs documented - pod_cidr = dict(type = 'str'), # TODO: needs documented - external_id = dict(type = 'str'), # TODO: needs documented - client_config = dict(type = 'str'), # TODO: needs documented - client_cluster = dict(type = 'str', default = 'master'), # TODO: needs documented - client_context = dict(type = 'str', default = 'master'), # TODO: needs documented - client_user = dict(type = 'str', default = 'admin') # TODO: needs documented - ), - mutually_exclusive = [ - ['host_ip', 'external_ips'], - ['host_ip', 'internal_ips'], - ['host_ip', 'hostnames'], - ], - supports_check_mode=True - ) - - user_has_client_config = os.path.exists(os.path.expanduser('~/.kube/.kubeconfig')) - if not (user_has_client_config or module.params['client_config']): - module.fail_json(msg="Could not locate client configuration, " - "client_config must be specified if " - "~/.kube/.kubeconfig is not present") - - client_opts = [] - if module.params['client_config']: - client_opts.append("--kubeconfig=%s" % module.params['client_config']) - - try: - config = ClientConfig(client_opts, module) - except ClientConfigException as e: - module.fail_json(msg="Failed to get client configuration", exception=e) - - client_context = module.params['client_context'] - if config.has_context(client_context): - if client_context != config.current_context(): - client_opts.append("--context=%s" % client_context) - else: - module.fail_json(msg="Context %s not found in client config" % - client_context) - - client_user = module.params['client_user'] - if config.has_user(client_user): - if client_user != config.get_user_for_context(client_context): - client_opts.append("--user=%s" % client_user) - else: - module.fail_json(msg="User %s not found in client config" % - client_user) - - client_cluster = module.params['client_cluster'] - if config.has_cluster(client_cluster): - if client_cluster != config.get_cluster_for_context(client_cluster): - client_opts.append("--cluster=%s" % client_cluster) - else: - module.fail_json(msg="Cluster %s not found in client config" % - client_cluster) - - # TODO: provide sane defaults for some (like hostname, externalIP, - # internalIP, etc) - node = Node(module, client_opts, module.params['api_version'], - module.params['name'], module.params['host_ip'], - module.params['hostnames'], module.params['external_ips'], - module.params['internal_ips'], module.params['cpu'], - module.params['memory'], module.params['labels'], - module.params['annotations'], module.params['pod_cidr'], - module.params['external_id']) - - # TODO: attempt to support changing node settings where possible and/or - # modifying node resources - if node.exists(): - module.exit_json(changed=False, node=node.get_node()) - elif module.check_mode: - module.exit_json(changed=True, node=node.get_node()) - else: - if node.create(): - module.exit_json(changed=True, - msg="Node created successfully", - node=node.get_node()) - else: - module.fail_json(msg="Unknown error creating node", - node=node.get_node()) - - -# import module snippets -from ansible.module_utils.basic import * -if __name__ == '__main__': - main() diff --git a/roles/openshift_node/tasks/main.yml b/roles/openshift_node/tasks/main.yml index e380ba1fb..c039e3f05 100644 --- a/roles/openshift_node/tasks/main.yml +++ b/roles/openshift_node/tasks/main.yml @@ -1,27 +1,29 @@ --- +- name: Test if node certs and config exist + stat: path={{ item }} + failed_when: not result.stat.exists + register: result + with_items: + - "{{ cert_path }}" + - "{{ cert_path }}/cert.crt" + - "{{ cert_path }}/key.key" + - "{{ cert_path }}/.kubeconfig" + - "{{ cert_path }}/server.crt" + - "{{ cert_path }}/server.key" + - "{{ cert_parent_path }}/ca/cert.crt" + #- "{{ cert_path }}/node.yaml" + - name: Install OpenShift Node package yum: pkg=openshift-node state=installed -- local_action: command /usr/bin/mktemp -d /tmp/openshift-ansible-XXXXXXX - register: mktemp - -- name: Retrieve OpenShift Master credentials - local_action: command /usr/bin/rsync --compress --archive --rsh 'ssh -S none -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' root@{{ openshift_master_public_ips[0] }}:/var/lib/openshift/openshift.local.certificates/admin/ {{ mktemp.stdout }} - ignore_errors: yes - -- file: path=/var/lib/openshift/openshift.local.certificates/admin state=directory - -- name: Store OpenShift Master credentials - local_action: command /usr/bin/rsync --compress --archive --rsh 'ssh -S none -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' {{ mktemp.stdout }}/ root@{{ openshift_public_ip }}:/var/lib/openshift/openshift.local.certificates/admin - ignore_errors: yes - -- local_action: file name={{ mktemp.stdout }} state=absent - +# --create-certs=false is a temporary workaround until +# https://github.com/openshift/origin/pull/1361 is merged upstream and it is +# the default for nodes - name: Configure OpenShift Node settings lineinfile: dest: /etc/sysconfig/openshift-node regexp: '^OPTIONS=' - line: "OPTIONS=\"--master=https://{{ openshift_master_ips[0] }}:8443 --hostname={{ openshift_hostname }} --loglevel={{ openshift_node_debug_level }}\"" + line: "OPTIONS=\"--hostname={{ openshift_hostname }} --loglevel={{ openshift_node_debug_level }} --create-certs=false\"" notify: - restart openshift-node @@ -47,42 +49,10 @@ option: externally_managed value: "{{ openshift_node_manage_service_externally }}" -# 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-node - service: name=openshift-node enabled=yes state=restarted + service: name=openshift-node enabled=yes state=started when: not openshift_node_manage_service_externally - name: Disable openshift-node if openshift-node is managed externally service: name=openshift-node enabled=false when: openshift_node_manage_service_externally - -# TODO: create an os_vars role that has generic env related config and move -# the root kubeconfig setting there, cannot use dependencies to force ordering -# with openshift_node and openshift_master because the way conditional -# dependencies work with current ansible would also exclude the -# openshift_common dependency. -- name: Create .kube directory - file: - path: /root/.kube - state: directory - mode: 0700 -- name: Configure root user kubeconfig - command: cp /var/lib/openshift/openshift.local.certificates/admin/.kubeconfig /root/.kube/.kubeconfig - args: - creates: /root/.kube/.kubeconfig - -- name: Register node (if not already registered) - openshift_register_node: - name: "{{ openshift_hostname }}" - api_version: v1beta1 - cpu: "{{ openshift_node_resources.cpu }}" - memory: "{{ openshift_node_resources.memory }}" - pod_cidr: "{{ openshift_node_resources.cidr }}" - host_ip: "{{ ansible_default_ipv4.address }}" - labels: "{{ openshift_node_labels }}" - annotations: "{{ openshift_node_annotations }}" - # TODO: support customizing other attributes such as: client_config, - # client_cluster, client_context, client_user - # TODO: updated for v1beta3 changes after rebase: hostnames, external_ips, - # internal_ips, external_id diff --git a/roles/openshift_register_nodes/README.md b/roles/openshift_register_nodes/README.md new file mode 100644 index 000000000..225dd44b9 --- /dev/null +++ b/roles/openshift_register_nodes/README.md @@ -0,0 +1,38 @@ +Role Name +========= + +A brief description of the role goes here. + +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. + +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. + +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. + +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 } + +License +------- + +BSD + +Author Information +------------------ + +An optional section for the role authors to include contact information, or a website (HTML is not allowed). diff --git a/roles/openshift_register_nodes/defaults/main.yml b/roles/openshift_register_nodes/defaults/main.yml new file mode 100644 index 000000000..3501e8922 --- /dev/null +++ b/roles/openshift_register_nodes/defaults/main.yml @@ -0,0 +1,5 @@ +--- +openshift_kube_api_version: v1beta1 +openshift_cert_dir: openshift.local.certificates +openshift_cert_dir_parent: /var/lib/openshift +openshift_cert_dir_abs: "{{ openshift_cert_dir_parent ~ '/' ~ openshift_cert_dir }}" diff --git a/roles/openshift_register_nodes/library/kubernetes_register_node.py b/roles/openshift_register_nodes/library/kubernetes_register_node.py new file mode 100644 index 000000000..409215616 --- /dev/null +++ b/roles/openshift_register_nodes/library/kubernetes_register_node.py @@ -0,0 +1,370 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# vim: expandtab:tabstop=4:shiftwidth=4 + +import os +import multiprocessing +import socket +from subprocess import check_output, Popen +from decimal import * + +DOCUMENTATION = ''' +--- +module: kubernetes_register_node +short_description: Registers a kubernetes node with a master +description: + - Registers a kubernetes node with a master +options: + name: + default: null + description: + - Identifier for this node (usually the node fqdn). + required: true + api_verison: + choices: ['v1beta1', 'v1beta3'] + default: 'v1beta1' + description: + - Kubernetes API version to use + required: true + host_ip: + default: null + description: + - IP Address to associate with the node when registering. + Available in the following API versions: v1beta1. + required: false + hostnames: + default: [] + description: + - Valid hostnames for this node. Available in the following API + versions: v1beta3. + required: false + external_ips: + default: [] + description: + - External IP Addresses for this node. Available in the following API + versions: v1beta3. + required: false + internal_ips: + default: [] + description: + - Internal IP Addresses for this node. Available in the following API + versions: v1beta3. + required: false + cpu: + default: null + description: + - Number of CPUs to allocate for this node. When using the v1beta1 + API, you must specify the CPU count as a floating point number + with no more than 3 decimal places. API version v1beta3 and newer + accepts arbitrary float values. + required: false + memory: + default: null + description: + - Memory available for this node. When using the v1beta1 API, you + must specify the memory size in bytes. API version v1beta3 and + newer accepts binary SI and decimal SI values. + required: false +''' +EXAMPLES = ''' +# Minimal node registration +- openshift_register_node: name=ose3.node.example.com + +# Node registration using the v1beta1 API and assigning 1 CPU core and 10 GB of +# Memory +- openshift_register_node: + name: ose3.node.example.com + api_version: v1beta1 + hostIP: 192.168.1.1 + cpu: 1 + memory: 500000000 + +# Node registration using the v1beta3 API, setting an alternate hostname, +# internalIP, externalIP and assigning 3.5 CPU cores and 1 TiB of Memory +- openshift_register_node: + name: ose3.node.example.com + api_version: v1beta3 + external_ips: ['192.168.1.5'] + internal_ips: ['10.0.0.5'] + hostnames: ['ose2.node.internal.local'] + cpu: 3.5 + memory: 1Ti +''' + + +class ClientConfigException(Exception): + pass + +class ClientConfig: + def __init__(self, client_opts, module): + _, output, error = module.run_command(["/usr/bin/openshift", "ex", + "config", "view", "-o", + "json"] + client_opts, + check_rc = True) + self.config = json.loads(output) + + if not (bool(self.config['clusters']) or + bool(self.config['contexts']) or + bool(self.config['current-context']) or + bool(self.config['users'])): + raise ClientConfigException(msg="Client config missing required " \ + "values", + output=output) + + def current_context(self): + return self.config['current-context'] + + def section_has_value(self, section_name, value): + section = self.config[section_name] + if isinstance(section, dict): + return value in section + else: + val = next((item for item in section + if item['name'] == value), None) + return val is not None + + def has_context(self, context): + return self.section_has_value('contexts', context) + + def has_user(self, user): + return self.section_has_value('users', user) + + def has_cluster(self, cluster): + return self.section_has_value('clusters', cluster) + + def get_value_for_context(self, context, attribute): + contexts = self.config['contexts'] + if isinstance(contexts, dict): + return contexts[context][attribute] + else: + return next((c['context'][attribute] for c in contexts + if c['name'] == context), None) + + def get_user_for_context(self, context): + return self.get_value_for_context(context, 'user') + + def get_cluster_for_context(self, context): + return self.get_value_for_context(context, 'cluster') + +class Util: + @staticmethod + def remove_empty_elements(mapping): + if isinstance(mapping, dict): + m = mapping.copy() + for key, val in mapping.iteritems(): + if not val: + del m[key] + return m + else: + return mapping + +class NodeResources: + def __init__(self, version, cpu=None, memory=None): + if version == 'v1beta1': + self.resources = dict(capacity=dict()) + self.resources['capacity']['cpu'] = cpu + self.resources['capacity']['memory'] = memory + + def get_resources(self): + return Util.remove_empty_elements(self.resources) + +class NodeSpec: + def __init__(self, version, cpu=None, memory=None, cidr=None, externalID=None): + if version == 'v1beta3': + self.spec = dict(podCIDR=cidr, externalID=externalID, + capacity=dict()) + self.spec['capacity']['cpu'] = cpu + self.spec['capacity']['memory'] = memory + + def get_spec(self): + return Util.remove_empty_elements(self.spec) + +class NodeStatus: + def addAddresses(self, addressType, addresses): + addressList = [] + for address in addresses: + addressList.append(dict(type=addressType, address=address)) + return addressList + + def __init__(self, version, externalIPs = [], internalIPs = [], + hostnames = []): + if version == 'v1beta3': + self.status = dict(addresses = addAddresses('ExternalIP', + externalIPs) + + addAddresses('InternalIP', + internalIPs) + + addAddresses('Hostname', + hostnames)) + + def get_status(self): + return Util.remove_empty_elements(self.status) + +class Node: + def __init__(self, module, client_opts, version='v1beta1', name=None, + hostIP = None, hostnames=[], externalIPs=[], internalIPs=[], + cpu=None, memory=None, labels=dict(), annotations=dict(), + podCIDR=None, externalID=None): + self.module = module + self.client_opts = client_opts + if version == 'v1beta1': + self.node = dict(id = name, + kind = 'Node', + apiVersion = version, + hostIP = hostIP, + resources = NodeResources(version, cpu, memory), + cidr = podCIDR, + labels = labels, + annotations = annotations + ) + elif version == 'v1beta3': + metadata = dict(name = name, + labels = labels, + annotations = annotations + ) + self.node = dict(kind = 'Node', + apiVersion = version, + metadata = metadata, + spec = NodeSpec(version, cpu, memory, podCIDR, + externalID), + status = NodeStatus(version, externalIPs, + internalIPs, hostnames), + ) + + def get_name(self): + if self.node['apiVersion'] == 'v1beta1': + return self.node['id'] + elif self.node['apiVersion'] == 'v1beta3': + return self.node['name'] + + def get_node(self): + node = self.node.copy() + if self.node['apiVersion'] == 'v1beta1': + node['resources'] = self.node['resources'].get_resources() + elif self.node['apiVersion'] == 'v1beta3': + node['spec'] = self.node['spec'].get_spec() + node['status'] = self.node['status'].get_status() + return Util.remove_empty_elements(node) + + def exists(self): + _, output, error = self.module.run_command(["/usr/bin/osc", "get", + "nodes"] + self.client_opts, + check_rc = True) + if re.search(self.module.params['name'], output, re.MULTILINE): + return True + return False + + def create(self): + cmd = ['/usr/bin/osc'] + self.client_opts + ['create', 'node', '-f', '-'] + rc, output, error = self.module.run_command(cmd, + data=self.module.jsonify(self.get_node())) + if rc != 0: + if re.search("minion \"%s\" already exists" % self.get_name(), + error): + self.module.exit_json(changed=False, + msg="node definition already exists", + node=self.get_node()) + else: + self.module.fail_json(msg="Node creation failed.", rc=rc, + output=output, error=error, + node=self.get_node()) + else: + return True + +def main(): + module = AnsibleModule( + argument_spec = dict( + name = dict(required = True, type = 'str'), + host_ip = dict(type = 'str'), + hostnames = dict(type = 'list', default = []), + external_ips = dict(type = 'list', default = []), + internal_ips = dict(type = 'list', default = []), + api_version = dict(type = 'str', default = 'v1beta1', # TODO: after kube rebase, we can default to v1beta3 + choices = ['v1beta1', 'v1beta3']), + cpu = dict(type = 'str'), + memory = dict(type = 'str'), + labels = dict(type = 'dict', default = {}), # TODO: needs documented + annotations = dict(type = 'dict', default = {}), # TODO: needs documented + pod_cidr = dict(type = 'str'), # TODO: needs documented + external_id = dict(type = 'str'), # TODO: needs documented + client_config = dict(type = 'str'), # TODO: needs documented + client_cluster = dict(type = 'str', default = 'master'), # TODO: needs documented + client_context = dict(type = 'str', default = 'master'), # TODO: needs documented + client_user = dict(type = 'str', default = 'admin') # TODO: needs documented + ), + mutually_exclusive = [ + ['host_ip', 'external_ips'], + ['host_ip', 'internal_ips'], + ['host_ip', 'hostnames'], + ], + supports_check_mode=True + ) + + user_has_client_config = os.path.exists(os.path.expanduser('~/.kube/.kubeconfig')) + if not (user_has_client_config or module.params['client_config']): + module.fail_json(msg="Could not locate client configuration, " + "client_config must be specified if " + "~/.kube/.kubeconfig is not present") + + client_opts = [] + if module.params['client_config']: + client_opts.append("--kubeconfig=%s" % module.params['client_config']) + + try: + config = ClientConfig(client_opts, module) + except ClientConfigException as e: + module.fail_json(msg="Failed to get client configuration", exception=e) + + client_context = module.params['client_context'] + if config.has_context(client_context): + if client_context != config.current_context(): + client_opts.append("--context=%s" % client_context) + else: + module.fail_json(msg="Context %s not found in client config" % + client_context) + + client_user = module.params['client_user'] + if config.has_user(client_user): + if client_user != config.get_user_for_context(client_context): + client_opts.append("--user=%s" % client_user) + else: + module.fail_json(msg="User %s not found in client config" % + client_user) + + client_cluster = module.params['client_cluster'] + if config.has_cluster(client_cluster): + if client_cluster != config.get_cluster_for_context(client_cluster): + client_opts.append("--cluster=%s" % client_cluster) + else: + module.fail_json(msg="Cluster %s not found in client config" % + client_cluster) + + # TODO: provide sane defaults for some (like hostname, externalIP, + # internalIP, etc) + node = Node(module, client_opts, module.params['api_version'], + module.params['name'], module.params['host_ip'], + module.params['hostnames'], module.params['external_ips'], + module.params['internal_ips'], module.params['cpu'], + module.params['memory'], module.params['labels'], + module.params['annotations'], module.params['pod_cidr'], + module.params['external_id']) + + # TODO: attempt to support changing node settings where possible and/or + # modifying node resources + if node.exists(): + module.exit_json(changed=False, node=node.get_node()) + elif module.check_mode: + module.exit_json(changed=True, node=node.get_node()) + else: + if node.create(): + module.exit_json(changed=True, + msg="Node created successfully", + node=node.get_node()) + else: + module.fail_json(msg="Unknown error creating node", + node=node.get_node()) + + +# import module snippets +from ansible.module_utils.basic import * +if __name__ == '__main__': + main() diff --git a/roles/openshift_register_nodes/meta/main.yml b/roles/openshift_register_nodes/meta/main.yml new file mode 100644 index 000000000..7b1f0ef0a --- /dev/null +++ b/roles/openshift_register_nodes/meta/main.yml @@ -0,0 +1,128 @@ +--- +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. + diff --git a/roles/openshift_register_nodes/tasks/main.yml b/roles/openshift_register_nodes/tasks/main.yml new file mode 100644 index 000000000..59216fc87 --- /dev/null +++ b/roles/openshift_register_nodes/tasks/main.yml @@ -0,0 +1,71 @@ +--- +# TODO: support configuration for multiple masters, currently hardcoding +# the info from the first master + +# 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(",") }} + args: + chdir: "{{ openshift_cert_dir_parent }}" + creates: "{{ openshift_cert_dir_abs }}/node-{{ item.openshift_node_hostname }}/server.crt" + with_items: openshift_nodes + register: server_cert_result + +# TODO: create a failed_when condition +- name: Create node client certificates + 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 }} + args: + chdir: "{{ openshift_cert_dir_parent }}" + creates: "{{ openshift_cert_dir_abs }}/node-{{ item.openshift_node_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] }} + args: + chdir: "{{ openshift_cert_dir_parent }}" + creates: "{{ openshift_cert_dir_abs }}/node-{{ item.openshift_node_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 }}" + 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 {} }}" + # 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, + # internal_ips, external_id + with_items: openshift_nodes + register: register_result diff --git a/roles/openshift_sdn_node/README.md b/roles/openshift_sdn_node/README.md index 294550219..33197c241 100644 --- a/roles/openshift_sdn_node/README.md +++ b/roles/openshift_sdn_node/README.md @@ -29,7 +29,7 @@ From openshift_common: | openshift_debug_level | 0 | Global openshift debug log verbosity | | openshift_hostname_workaround | True | | | openshift_public_ip | UNDEF (Required) | Public IP address to use for this host | -| openshift_hostname | openshift_public_ip if openshift_hostname_workaround else ansible_fqdn | hostname to use for this instance | +| openshift_hostname | UNDEF (Required) | hostname to use for this instance | Dependencies ------------ -- cgit v1.2.3 From de1391db4309f020b5c8467597eef527b560bbaa Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Mon, 23 Mar 2015 23:36:08 -0400 Subject: remove openshift_hostname_workaround var for openshift_common, rather rely on inventory/playbook variables for openshift_hostname --- roles/openshift_common/README.md | 1 - roles/openshift_common/defaults/main.yml | 5 ----- roles/openshift_master/README.md | 1 - roles/openshift_node/README.md | 1 - roles/openshift_sdn_node/README.md | 1 - 5 files changed, 9 deletions(-) diff --git a/roles/openshift_common/README.md b/roles/openshift_common/README.md index 592a276f9..880d66e2c 100644 --- a/roles/openshift_common/README.md +++ b/roles/openshift_common/README.md @@ -15,7 +15,6 @@ Role Variables | Name | Default value | | |-------------------------------|------------------------------|----------------------------------------| | openshift_debug_level | 0 | Global openshift debug log verbosity | -| openshift_hostname_workaround | True | Workaround needed to set hostname to IP address | | 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 | diff --git a/roles/openshift_common/defaults/main.yml b/roles/openshift_common/defaults/main.yml index 86351f6f6..22b2c6ffd 100644 --- a/roles/openshift_common/defaults/main.yml +++ b/roles/openshift_common/defaults/main.yml @@ -1,7 +1,2 @@ --- openshift_debug_level: 0 - -# TODO: Once openshift stops resolving hostnames for node queries remove -# this... -openshift_hostname_workaround: true - diff --git a/roles/openshift_master/README.md b/roles/openshift_master/README.md index 2f03b4990..2d898bc3b 100644 --- a/roles/openshift_master/README.md +++ b/roles/openshift_master/README.md @@ -25,7 +25,6 @@ From openshift_common: | Name | Default Value | | |-------------------------------|---------------------|---------------------| | openshift_debug_level | 0 | Global openshift debug log verbosity | -| openshift_hostname_workaround | True | | | openshift_public_ip | UNDEF (Required) | Public IP address to use for this host | | openshift_hostname | UNDEF (Required) | hostname to use for this instance | diff --git a/roles/openshift_node/README.md b/roles/openshift_node/README.md index d537a35a5..c9b4eab34 100644 --- a/roles/openshift_node/README.md +++ b/roles/openshift_node/README.md @@ -26,7 +26,6 @@ From openshift_common: | Name | Default Value | | |-------------------------------|---------------------|---------------------| | openshift_debug_level | 0 | Global openshift debug log verbosity | -| openshift_hostname_workaround | True | | | openshift_public_ip | UNDEF (Required) | Public IP address to use for this host | | openshift_hostname | UNDEF (Required) | hostname to use for this instance | diff --git a/roles/openshift_sdn_node/README.md b/roles/openshift_sdn_node/README.md index 33197c241..2da2d74eb 100644 --- a/roles/openshift_sdn_node/README.md +++ b/roles/openshift_sdn_node/README.md @@ -27,7 +27,6 @@ From openshift_common: | Name | Default value | | |-------------------------------|---------------------|----------------------------------------| | openshift_debug_level | 0 | Global openshift debug log verbosity | -| openshift_hostname_workaround | True | | | openshift_public_ip | UNDEF (Required) | Public IP address to use for this host | | openshift_hostname | UNDEF (Required) | hostname to use for this instance | -- cgit v1.2.3 From 01ee65e99d39265f7d8db3ddbeca5d59ddfa2038 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Mon, 23 Mar 2015 23:37:19 -0400 Subject: gce inventory/playbook updates for node registration changes --- inventory/gce/group_vars/all | 3 +++ inventory/gce/group_vars/tag_host-type-master | 5 +++++ inventory/gce/group_vars/tag_host-type-node | 6 ++++++ inventory/gce/group_vars/tag_host-type-openshift-master | 1 + inventory/gce/group_vars/tag_host-type-openshift-node | 1 + playbooks/gce/openshift-node/config.yml | 6 +++--- 6 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 inventory/gce/group_vars/tag_host-type-master create mode 100644 inventory/gce/group_vars/tag_host-type-node create mode 120000 inventory/gce/group_vars/tag_host-type-openshift-master create mode 120000 inventory/gce/group_vars/tag_host-type-openshift-node diff --git a/inventory/gce/group_vars/all b/inventory/gce/group_vars/all index 4cd94c509..3e969df63 100644 --- a/inventory/gce/group_vars/all +++ b/inventory/gce/group_vars/all @@ -1,4 +1,7 @@ --- 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 new file mode 100644 index 000000000..ddbdc650c --- /dev/null +++ b/inventory/gce/group_vars/tag_host-type-master @@ -0,0 +1,5 @@ +--- +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 new file mode 100644 index 000000000..bb95a724d --- /dev/null +++ b/inventory/gce/group_vars/tag_host-type-node @@ -0,0 +1,6 @@ +--- +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 new file mode 120000 index 000000000..c0c4cf370 --- /dev/null +++ b/inventory/gce/group_vars/tag_host-type-openshift-master @@ -0,0 +1 @@ +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 new file mode 120000 index 000000000..ebbce6136 --- /dev/null +++ b/inventory/gce/group_vars/tag_host-type-openshift-node @@ -0,0 +1 @@ +tag_host-type-node \ No newline at end of file diff --git a/playbooks/gce/openshift-node/config.yml b/playbooks/gce/openshift-node/config.yml index d24acb8fa..bf28fc81d 100644 --- a/playbooks/gce/openshift-node/config.yml +++ b/playbooks/gce/openshift-node/config.yml @@ -6,12 +6,12 @@ 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 + - 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'] - name: Gather facts for masters in {{ oo_env }} - hosts: "tag_env-host-type-{{ oo_env }}-openshift-master" + hosts: tag_env-host-type-{{ oo_env }}-openshift-master tasks: - set_fact: openshift_master_ip: "{{ openshift_ip }}" @@ -68,7 +68,7 @@ # - name: Configure instances hosts: oo_nodes_to_config -vars_files: + vars_files: - vars.yml vars: openshift_master_group: tag_env-host-type-{{ oo_env }}-openshift-master -- cgit v1.2.3 From 41740bc6e177e58a0aa817e2d940e60be51d3bfe Mon Sep 17 00:00:00 2001 From: Jhon Honce Date: Tue, 24 Mar 2015 09:43:36 -0700 Subject: Revert "Jwhonce wip/cluster" --- playbooks/gce/openshift-node/config.yml | 1 - roles/docker/tasks/main.yml | 2 +- roles/os_env_extras_node/README.md | 38 ------- roles/os_env_extras_node/files/enter-container.sh | 13 --- roles/os_env_extras_node/meta/main.yml | 124 ---------------------- roles/os_env_extras_node/tasks/main.yml | 7 -- roles/os_firewall/tasks/firewall/iptables.yml | 8 ++ 7 files changed, 9 insertions(+), 184 deletions(-) delete mode 100644 roles/os_env_extras_node/README.md delete mode 100755 roles/os_env_extras_node/files/enter-container.sh delete mode 100644 roles/os_env_extras_node/meta/main.yml delete mode 100644 roles/os_env_extras_node/tasks/main.yml diff --git a/playbooks/gce/openshift-node/config.yml b/playbooks/gce/openshift-node/config.yml index bf28fc81d..e0d074572 100644 --- a/playbooks/gce/openshift-node/config.yml +++ b/playbooks/gce/openshift-node/config.yml @@ -120,4 +120,3 @@ roles: - openshift_node - os_env_extras - - os_env_extras_node diff --git a/roles/docker/tasks/main.yml b/roles/docker/tasks/main.yml index 593c4c877..ca700db17 100644 --- a/roles/docker/tasks/main.yml +++ b/roles/docker/tasks/main.yml @@ -1,7 +1,7 @@ --- # tasks file for docker - name: Install docker - yum: pkg=docker + yum: pkg=docker-io - name: enable and start the docker service service: name=docker enabled=yes state=started diff --git a/roles/os_env_extras_node/README.md b/roles/os_env_extras_node/README.md deleted file mode 100644 index 225dd44b9..000000000 --- a/roles/os_env_extras_node/README.md +++ /dev/null @@ -1,38 +0,0 @@ -Role Name -========= - -A brief description of the role goes here. - -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. - -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. - -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. - -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 } - -License -------- - -BSD - -Author Information ------------------- - -An optional section for the role authors to include contact information, or a website (HTML is not allowed). diff --git a/roles/os_env_extras_node/files/enter-container.sh b/roles/os_env_extras_node/files/enter-container.sh deleted file mode 100755 index 7cf5b8d83..000000000 --- a/roles/os_env_extras_node/files/enter-container.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -if [ $# -ne 1 ] -then - echo - echo "Usage: $(basename $0) " - echo - exit 1 -fi - -PID=$(docker inspect --format '{{.State.Pid}}' $1) - -nsenter --target $PID --mount --uts --ipc --net --pid diff --git a/roles/os_env_extras_node/meta/main.yml b/roles/os_env_extras_node/meta/main.yml deleted file mode 100644 index c5c362c60..000000000 --- a/roles/os_env_extras_node/meta/main.yml +++ /dev/null @@ -1,124 +0,0 @@ ---- -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: 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. - diff --git a/roles/os_env_extras_node/tasks/main.yml b/roles/os_env_extras_node/tasks/main.yml deleted file mode 100644 index 065f71f74..000000000 --- a/roles/os_env_extras_node/tasks/main.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- copy: src=enter-container.sh dest=/usr/local/bin/enter-container.sh mode=0755 - -# 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/tasks/firewall/iptables.yml b/roles/os_firewall/tasks/firewall/iptables.yml index 87e77c083..72a3401cf 100644 --- a/roles/os_firewall/tasks/firewall/iptables.yml +++ b/roles/os_firewall/tasks/firewall/iptables.yml @@ -41,6 +41,14 @@ changed_when: "'firewalld' in result.stdout" when: pkg_check.rc == 0 +# Workaround for Docker 1.4 to create DOCKER chain +- name: Add DOCKER chain + os_firewall_manage_iptables: + name: "DOCKER chain" + action: verify_chain + create_jump_rule: no +# End of Docker 1.4 workaround + - name: Add iptables allow rules os_firewall_manage_iptables: name: "{{ item.service }}" -- cgit v1.2.3 From fa746f02aa275cf8e1cbe9f90ec41fc27806a0bd Mon Sep 17 00:00:00 2001 From: Jhon Honce Date: Tue, 24 Mar 2015 10:49:15 -0700 Subject: * repos role renamed to openshift_repos --- playbooks/gce/openshift-cluster/launch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playbooks/gce/openshift-cluster/launch.yml b/playbooks/gce/openshift-cluster/launch.yml index b30452725..889d92d40 100644 --- a/playbooks/gce/openshift-cluster/launch.yml +++ b/playbooks/gce/openshift-cluster/launch.yml @@ -49,7 +49,7 @@ - hosts: "tag_env-{{ cluster_id }}" roles: - - repos + - openshift_repos - os_update_latest - include: ../openshift-master/config.yml -- 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 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 4dc8ca74f47bcbe0fd6285b0d73cc5b193be17a9 Mon Sep 17 00:00:00 2001 From: Jhon Honce Date: Tue, 24 Mar 2015 12:40:21 -0700 Subject: * Remove DOCKER chain work around --- roles/os_firewall/tasks/firewall/iptables.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/roles/os_firewall/tasks/firewall/iptables.yml b/roles/os_firewall/tasks/firewall/iptables.yml index 72a3401cf..87e77c083 100644 --- a/roles/os_firewall/tasks/firewall/iptables.yml +++ b/roles/os_firewall/tasks/firewall/iptables.yml @@ -41,14 +41,6 @@ changed_when: "'firewalld' in result.stdout" when: pkg_check.rc == 0 -# Workaround for Docker 1.4 to create DOCKER chain -- name: Add DOCKER chain - os_firewall_manage_iptables: - name: "DOCKER chain" - action: verify_chain - create_jump_rule: no -# End of Docker 1.4 workaround - - name: Add iptables allow rules os_firewall_manage_iptables: name: "{{ item.service }}" -- 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 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 43ed89371aa2fce56d5e2b41af35a3ae902e92e6 Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Tue, 24 Mar 2015 16:19:46 -0400 Subject: Automatic commit of package [openshift-ansible-inventory] release [0.0.1-1]. --- inventory/openshift-ansible-inventory.spec | 5 ++++- rel-eng/packages/openshift-ansible-inventory | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 rel-eng/packages/openshift-ansible-inventory diff --git a/inventory/openshift-ansible-inventory.spec b/inventory/openshift-ansible-inventory.spec index 156b81b86..e847df189 100644 --- a/inventory/openshift-ansible-inventory.spec +++ b/inventory/openshift-ansible-inventory.spec @@ -1,6 +1,6 @@ Summary: OpenShift Ansible Inventories Name: openshift-ansible-inventory -Version: 0.0.0 +Version: 0.0.1 Release: 1%{?dist} License: ASL 2.0 URL: https://github.com/openshift/openshift-ansible @@ -35,3 +35,6 @@ cp -p gce/gce.py %{buildroot}/usr/share/ansible/inventory/gce /usr/share/ansible/inventory/gce/gce.py* %changelog +* Tue Mar 24 2015 Thomas Wiest 0.0.1-1 +- new package built with tito + diff --git a/rel-eng/packages/openshift-ansible-inventory b/rel-eng/packages/openshift-ansible-inventory new file mode 100644 index 000000000..21f4631fc --- /dev/null +++ b/rel-eng/packages/openshift-ansible-inventory @@ -0,0 +1 @@ +0.0.1-1 inventory/ -- 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(-) 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 f79f6d649a4c8599121d9cad5492afc579f0425a Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Wed, 25 Mar 2015 16:45:50 -0400 Subject: added the ability to have a config file in /etc/openshift_ansible to multi_ec2.py. --- inventory/multi_ec2.py | 17 +++++++++++++++-- inventory/openshift-ansible-inventory.spec | 6 ++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/inventory/multi_ec2.py b/inventory/multi_ec2.py index 5dee7972b..26c09d712 100755 --- a/inventory/multi_ec2.py +++ b/inventory/multi_ec2.py @@ -12,6 +12,8 @@ import json import pprint +CONFIG_FILE_NAME = 'multi_ec2.yaml' + class MultiEc2(object): def __init__(self): @@ -20,11 +22,22 @@ class MultiEc2(object): self.result = {} self.cache_path = os.path.expanduser('~/.ansible/tmp/multi_ec2_inventory.cache') self.file_path = os.path.join(os.path.dirname(os.path.realpath(__file__))) - self.config_file = os.path.join(self.file_path,"multi_ec2.yaml") + + same_dir_config_file = os.path.join(self.file_path, CONFIG_FILE_NAME) + etc_dir_config_file = os.path.join(os.path.sep, 'etc','ansible', CONFIG_FILE_NAME) + + # Prefer a file in the same directory, fall back to a file in etc + if os.path.isfile(same_dir_config_file): + self.config_file = same_dir_config_file + elif os.path.isfile(etc_dir_config_file): + self.config_file = etc_dir_config_file + else: + self.config_file = None # expect env vars + self.parse_cli_args() # load yaml - if os.path.isfile(self.config_file): + if self.config_file and os.path.isfile(self.config_file): self.config = self.load_yaml_config() elif os.environ.has_key("AWS_ACCESS_KEY_ID") and os.environ.has_key("AWS_SECRET_ACCESS_KEY"): self.config = {} diff --git a/inventory/openshift-ansible-inventory.spec b/inventory/openshift-ansible-inventory.spec index e847df189..9b721818e 100644 --- a/inventory/openshift-ansible-inventory.spec +++ b/inventory/openshift-ansible-inventory.spec @@ -18,18 +18,20 @@ Ansible Inventories used with the openshift-ansible scripts and playbooks. %build %install +mkdir -p %{buildroot}/etc/ansible 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 multi_ec2.py %{buildroot}/usr/share/ansible/inventory +cp -p multi_ec2.yaml.example %{buildroot}/etc/ansible/multi_ec2.yaml 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 +%config(noreplace) /etc/ansible/* %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* -- cgit v1.2.3 From 78a45fc50509eca27164452325529cc46a99cc8c Mon Sep 17 00:00:00 2001 From: Thomas Wiest Date: Thu, 26 Mar 2015 11:14:30 -0400 Subject: Automatic commit of package [openshift-ansible-inventory] release [0.0.2-1]. --- inventory/openshift-ansible-inventory.spec | 10 +++++++++- rel-eng/packages/openshift-ansible-inventory | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/inventory/openshift-ansible-inventory.spec b/inventory/openshift-ansible-inventory.spec index 9b721818e..8267e16f6 100644 --- a/inventory/openshift-ansible-inventory.spec +++ b/inventory/openshift-ansible-inventory.spec @@ -1,6 +1,6 @@ Summary: OpenShift Ansible Inventories Name: openshift-ansible-inventory -Version: 0.0.1 +Version: 0.0.2 Release: 1%{?dist} License: ASL 2.0 URL: https://github.com/openshift/openshift-ansible @@ -37,6 +37,14 @@ cp -p gce/gce.py %{buildroot}/usr/share/ansible/inventory/gce /usr/share/ansible/inventory/gce/gce.py* %changelog +* Thu Mar 26 2015 Thomas Wiest 0.0.2-1 +- added the ability to have a config file in /etc/openshift_ansible to + multi_ec2.py. (twiest@redhat.com) +- Merge pull request #97 from jwhonce/wip/cluster (jhonce@redhat.com) +- gce inventory/playbook updates for node registration changes + (jdetiber@redhat.com) +- Various fixes (jdetiber@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-inventory b/rel-eng/packages/openshift-ansible-inventory index 21f4631fc..cf3ac87ed 100644 --- a/rel-eng/packages/openshift-ansible-inventory +++ b/rel-eng/packages/openshift-ansible-inventory @@ -1 +1 @@ -0.0.1-1 inventory/ +0.0.2-1 inventory/ -- 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 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(-) 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 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(-) 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(-) 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(-) 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 035b498f37cdb5947d3d7c9254c23a20ca77eddd Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Wed, 1 Apr 2015 12:42:03 -0400 Subject: Adding the zabbix module along with a generic playbook to fetch current problem triggers. Also added oo_flatten to filters for arrays of arrays. --- filter_plugins/oo_filters.py | 10 ++ library/zbxapi.py | 257 ++++++++++++++++++++++++++++ playbooks/adhoc/noc/filter_plugins | 1 + playbooks/adhoc/noc/get_zabbix_problems.yml | 39 +++++ playbooks/adhoc/noc/library | 1 + 5 files changed, 308 insertions(+) create mode 100755 library/zbxapi.py create mode 120000 playbooks/adhoc/noc/filter_plugins create mode 100644 playbooks/adhoc/noc/get_zabbix_problems.yml create mode 120000 playbooks/adhoc/noc/library diff --git a/filter_plugins/oo_filters.py b/filter_plugins/oo_filters.py index caf1fd1f0..1cf02218c 100644 --- a/filter_plugins/oo_filters.py +++ b/filter_plugins/oo_filters.py @@ -34,6 +34,15 @@ def get_attr(data, attribute=None): return ptr +def oo_flatten(data): + ''' This filter plugin will flatten a list of lists + ''' + if not issubclass(type(data), list): + raise errors.AnsibleFilterError("|failed expects to flatten a List") + + return [ item for sublist in data for item in sublist ] + + def oo_collect(data, attribute=None, filters={}): ''' This takes a list of dict and collects all attributes specified into a list If filter is specified then we will include all items that match _ALL_ of filters. @@ -97,6 +106,7 @@ class FilterModule (object): return { "oo_select_keys": oo_select_keys, "oo_collect": oo_collect, + "oo_flatten": oo_flatten, "oo_len": oo_len, "oo_pdb": oo_pdb, "oo_prepend_strings_in_list": oo_prepend_strings_in_list diff --git a/library/zbxapi.py b/library/zbxapi.py new file mode 100755 index 000000000..6d752c9f0 --- /dev/null +++ b/library/zbxapi.py @@ -0,0 +1,257 @@ +#!/usr/bin/env python + +import json +import httplib2 +import sys +import os +import re + +class ZabbixAPI(object): + ''' + ZabbixAPI class + ''' + classes = { + 'Triggerprototype': ['get', 'update', 'delete', 'create'], + 'Script': ['getscriptsbyhosts', 'get', 'update', 'delete', 'execute', 'create'], + 'Templatescreenitem': ['get'], + 'Service': ['deletedependencies', 'create', 'isreadable', 'deletetimes', 'getsla', 'get', 'addtimes', 'update', 'delete', 'adddependencies', 'iswritable'], + 'Drule': ['delete', 'isreadable', 'create', 'get', 'update', 'copy', 'iswritable'], + 'Iconmap': ['create', 'update', 'isreadable', 'get', 'iswritable', 'delete'], + 'Dservice': ['get'], + 'History': ['get'], + 'Trigger': ['delete', 'deletedependencies', 'create', 'iswritable', 'isreadable', 'adddependencies', 'get', 'update'], + 'Graph': ['delete', 'get', 'update', 'create'], + 'Usergroup': ['get', 'update', 'create', 'massupdate', 'isreadable', 'delete', 'iswritable', 'massadd'], + 'Map': ['get', 'create', 'delete', 'update', 'isreadable', 'iswritable'], + 'Alert': ['get'], + 'Screenitem': ['updatebyposition', 'iswritable', 'isreadable', 'update', 'get', 'create', 'delete'], + 'Httptest': ['create', 'delete', 'get', 'iswritable', 'update', 'isreadable'], + 'Graphitem': ['get'], + 'Dcheck': ['get'], + 'Template': ['isreadable', 'massupdate', 'delete', 'iswritable', 'massremove', 'massadd', 'create', 'update', 'get'], + 'Templatescreen': ['get', 'create', 'copy', 'delete', 'isreadable', 'update', 'iswritable'], + 'Application': ['update', 'delete', 'massadd', 'get', 'create'], + 'Item': ['delete', 'get', 'iswritable', 'isreadable', 'update', 'create'], + 'Proxy': ['create', 'delete', 'update', 'iswritable', 'isreadable', 'get'], + 'Action': ['get', 'delete', 'update', 'create'], + 'Mediatype': ['update', 'delete', 'get', 'create'], + 'Maintenance': ['get', 'update', 'create', 'delete'], + 'Screen': ['delete', 'update', 'create', 'get'], + 'Dhost': ['get'], + 'Itemprototype': ['delete', 'iswritable', 'get', 'update', 'create', 'isreadable'], + 'Host': ['massadd', 'massremove', 'isreadable', 'get', 'create', 'update', 'delete', 'massupdate', 'iswritable'], + 'Event': ['acknowledge', 'get'], + 'Hostprototype': ['iswritable', 'create', 'update', 'delete', 'get', 'isreadable'], + 'Hostgroup': ['massadd', 'massupdate', 'update', 'isreadable', 'get', 'massremove', 'create', 'delete', 'iswritable'], + 'Image': ['get', 'update', 'delete', 'create'], + 'User': ['delete', 'get', 'updatemedia', 'updateprofile', 'update', 'iswritable', 'logout', 'addmedia', 'create', 'login', 'deletemedia', 'isreadable'], + 'Graphprototype': ['update', 'get', 'delete', 'create'], + 'Hostinterface': ['replacehostinterfaces', 'delete', 'get', 'massadd', 'create', 'update', 'massremove'], + 'Usermacro': ['create', 'deleteglobal', 'updateglobal', 'delete', 'update', 'createglobal', 'get'], + 'Usermedia': ['get'], + 'Configuration': ['import', 'export'], + } + + def __init__(self, data={}): + self.server = data['server'] or None + self.username = data['user'] or None + self.password = data['password'] or None + if any(map(lambda value: value == None, [self.server, self.username, self.password])): + print 'Please specify zabbix server url, username, and password.' + sys.exit(1) + + self.verbose = data.has_key('verbose') + self.use_ssl = data.has_key('use_ssl') + self.auth = None + + for class_name, method_names in self.classes.items(): + #obj = getattr(self, class_name)(self) + #obj.__dict__ + setattr(self, class_name.lower(), getattr(self, class_name)(self)) + + results = self.user.login(user=self.username, password=self.password) + + if results[0]['status'] == '200': + if results[1].has_key('result'): + self.auth = results[1]['result'] + elif results[1].has_key('error'): + print "Unable to authenticate with zabbix server. {0} ".format(results[1]['error']) + sys.exit(1) + else: + print "Error in call to zabbix. Http status: {0}.".format(results[0]['status']) + sys.exit(1) + + def perform(self, method, params): + ''' + This method calls your zabbix server. + + It requires the following parameters in order for a proper request to be processed: + + jsonrpc - the version of the JSON-RPC protocol used by the API; the Zabbix API implements JSON-RPC version 2.0; + method - the API method being called; + params - parameters that will be passed to the API method; + id - an arbitrary identifier of the request; + auth - a user authentication token; since we don't have one yet, it's set to null. + ''' + http_method = "POST" + if params.has_key("http_method"): + http_method = params['http_method'] + + jsonrpc = "2.0" + if params.has_key('jsonrpc'): + jsonrpc = params['jsonrpc'] + + rid = 1 + if params.has_key('id'): + rid = params['id'] + + http = None + if self.use_ssl: + http = httplib2.Http() + else: + http = httplib2.Http( disable_ssl_certificate_validation=True,) + + headers = params.get('headers', {}) + headers["Content-type"] = "application/json" + + body = { + "jsonrpc": jsonrpc, + "method": method, + "params": params, + "id": rid, + 'auth': self.auth, + } + + if method in ['user.login','api.version']: + del body['auth'] + + body = json.dumps(body) + + if self.verbose: + print body + print method + print headers + httplib2.debuglevel = 1 + + response, results = http.request(self.server, http_method, body, headers) + + if self.verbose: + print response + print results + + try: + results = json.loads(results) + except ValueError as e: + results = {"error": e.message} + + return response, results + + ''' + This bit of metaprogramming is where the ZabbixAPI subclasses are created. + For each of ZabbixAPI.classes we create a class from the key and methods + from the ZabbixAPI.classes values. We pass a reference to ZabbixAPI class + to each subclass in order for each to be able to call the perform method. + ''' + @staticmethod + def meta(class_name, method_names): + # This meta method allows a class to add methods to it. + def meta_method(Class, method_name): + # This template method is a stub method for each of the subclass + # methods. + def template_method(self, **params): + return self.parent.perform(class_name.lower()+"."+method_name, params) + template_method.__doc__ = "https://www.zabbix.com/documentation/2.4/manual/api/reference/%s/%s" % (class_name.lower(), method_name) + template_method.__name__ = method_name + # this is where the template method is placed inside of the subclass + # e.g. setattr(User, "create", stub_method) + setattr(Class, template_method.__name__, template_method) + + # This class call instantiates a subclass. e.g. User + Class=type(class_name, (object,), { '__doc__': "https://www.zabbix.com/documentation/2.4/manual/api/reference/%s" % class_name.lower() }) + # This init method gets placed inside of the Class + # to allow it to be instantiated. A reference to the parent class(ZabbixAPI) + # is passed in to allow each class access to the perform method. + def __init__(self, parent): + self.parent = parent + # This attaches the init to the subclass. e.g. Create + setattr(Class, __init__.__name__, __init__) + # For each of our ZabbixAPI.classes dict values + # Create a method and attach it to our subclass. + # e.g. 'User': ['delete', 'get', 'updatemedia', 'updateprofile', + # 'update', 'iswritable', 'logout', 'addmedia', 'create', + # 'login', 'deletemedia', 'isreadable'], + # User.delete + # User.get + for method_name in method_names: + meta_method(Class, method_name) + # Return our subclass with all methods attached + return Class + +# Attach all ZabbixAPI.classes to ZabbixAPI class through metaprogramming +for class_name, method_names in ZabbixAPI.classes.items(): + setattr(ZabbixAPI, class_name, ZabbixAPI.meta(class_name, method_names)) + +def main(): + + module = AnsibleModule( + argument_spec = dict( + server=dict(default='https://localhost/zabbix/api_jsonrpc.php', type='str'), + user=dict(default=None, type='str'), + password=dict(default=None, type='str'), + zbx_class=dict( choices=ZabbixAPI.classes.keys()), + #zbx_class=dict(type='str', require=True), + action=dict(default=None, type='str'), + params=dict(), + debug=dict(default=False, type='bool'), + ), + #supports_check_mode=True + ) + + user = module.params.get('user', None) + if not user: + user = os.environ['ZABBIX_USER'] + + pw = module.params.get('password', None) + if not pw: + pw = os.environ['ZABBIX_PW'] + + server = module.params['server'] + + if module.params['debug']: + options['debug'] = True + + api_data = { + 'user': user, + 'password': pw, + 'server': server, + } + + if not user or not pw or not server: + module.fail_json('Please specify the user, password, and the zabbix server.') + + zapi = ZabbixAPI(api_data) + + zbx_class = module.params.get('zbx_class') + action = module.params.get('action') + params = module.params.get('params', {}) + + + # Get the instance we are trying to call + zbx_class_inst = zapi.__getattribute__(zbx_class.lower()) + # Get the instance's method we are trying to call + zbx_action_method = zapi.__getattribute__(zbx_class.capitalize()).__dict__[action] + # Make the call with the incoming params + results = zbx_action_method(zbx_class_inst, **params) + + # Results Section + changed_state = False + status = results[0]['status'] + if status not in ['200', '201']: + #changed_state = False + module.fail_json(msg="Http response: [%s] - Error: %s" % (str(results[0]), results[1])) + + module.exit_json(**{'results': results[1]['result']}) + +from ansible.module_utils.basic import * + +main() diff --git a/playbooks/adhoc/noc/filter_plugins b/playbooks/adhoc/noc/filter_plugins new file mode 120000 index 000000000..99a95e4ca --- /dev/null +++ b/playbooks/adhoc/noc/filter_plugins @@ -0,0 +1 @@ +../../../filter_plugins \ No newline at end of file diff --git a/playbooks/adhoc/noc/get_zabbix_problems.yml b/playbooks/adhoc/noc/get_zabbix_problems.yml new file mode 100644 index 000000000..6ac5cdcf7 --- /dev/null +++ b/playbooks/adhoc/noc/get_zabbix_problems.yml @@ -0,0 +1,39 @@ +--- +- name: 'Get current hosts who have triggers that are alerting by trigger description' + hosts: localhost + gather_facts: no + tasks: + - assert: + that: oo_desc is defined + + - zbxapi: + server: https://noc2.ops.rhcloud.com/zabbix/api_jsonrpc.php + zbx_class: Trigger + action: get + params: + only_true: true + output: extend + selectHosts: extend + searchWildCardsEnabled: 1 + search: + description: "{{ oo_desc }}" + register: problems + + - debug: var=problems + + - set_fact: + problem_hosts: "{{ problems.results | oo_collect(attribute='hosts') | oo_flatten | oo_collect(attribute='host') | difference(['aggregates']) }}" + + - debug: var=problem_hosts + + - add_host: + name: "{{ item }}" + groups: problem_hosts_group + with_items: problem_hosts + +- name: "Run on problem hosts" + hosts: problem_hosts_group + gather_facts: no + tasks: + - command: "{{ oo_cmd }}" + when: oo_cmd is defined diff --git a/playbooks/adhoc/noc/library b/playbooks/adhoc/noc/library new file mode 120000 index 000000000..ba40d2f56 --- /dev/null +++ b/playbooks/adhoc/noc/library @@ -0,0 +1 @@ +../../../library \ No newline at end of file -- cgit v1.2.3 From 2933a28c400d6c00fa59e1b368d3606f22767576 Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Wed, 1 Apr 2015 12:55:40 -0400 Subject: Adding license --- library/zbxapi.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/library/zbxapi.py b/library/zbxapi.py index 6d752c9f0..198914bcb 100755 --- a/library/zbxapi.py +++ b/library/zbxapi.py @@ -1,5 +1,22 @@ #!/usr/bin/env python +# Copyright 2015 Red Hat Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Purpose: An ansible module to communicate with zabbix. +# + import json import httplib2 import sys -- cgit v1.2.3 From 058832184a7e5b23b7c398e443bc961af0ff3b5f Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Wed, 1 Apr 2015 16:01:50 -0400 Subject: fixing naming of environment variables --- library/zbxapi.py | 70 +++++++++++++++++++++++++++---------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/library/zbxapi.py b/library/zbxapi.py index 198914bcb..94b48ed61 100755 --- a/library/zbxapi.py +++ b/library/zbxapi.py @@ -28,45 +28,45 @@ class ZabbixAPI(object): ZabbixAPI class ''' classes = { - 'Triggerprototype': ['get', 'update', 'delete', 'create'], - 'Script': ['getscriptsbyhosts', 'get', 'update', 'delete', 'execute', 'create'], - 'Templatescreenitem': ['get'], - 'Service': ['deletedependencies', 'create', 'isreadable', 'deletetimes', 'getsla', 'get', 'addtimes', 'update', 'delete', 'adddependencies', 'iswritable'], - 'Drule': ['delete', 'isreadable', 'create', 'get', 'update', 'copy', 'iswritable'], - 'Iconmap': ['create', 'update', 'isreadable', 'get', 'iswritable', 'delete'], - 'Dservice': ['get'], - 'History': ['get'], - 'Trigger': ['delete', 'deletedependencies', 'create', 'iswritable', 'isreadable', 'adddependencies', 'get', 'update'], - 'Graph': ['delete', 'get', 'update', 'create'], - 'Usergroup': ['get', 'update', 'create', 'massupdate', 'isreadable', 'delete', 'iswritable', 'massadd'], - 'Map': ['get', 'create', 'delete', 'update', 'isreadable', 'iswritable'], + 'Action': ['create', 'delete', 'get', 'update'], 'Alert': ['get'], - 'Screenitem': ['updatebyposition', 'iswritable', 'isreadable', 'update', 'get', 'create', 'delete'], - 'Httptest': ['create', 'delete', 'get', 'iswritable', 'update', 'isreadable'], - 'Graphitem': ['get'], + 'Application': ['create', 'delete', 'get', 'massadd', 'update'], + 'Configuration': ['export', 'import'], 'Dcheck': ['get'], - 'Template': ['isreadable', 'massupdate', 'delete', 'iswritable', 'massremove', 'massadd', 'create', 'update', 'get'], - 'Templatescreen': ['get', 'create', 'copy', 'delete', 'isreadable', 'update', 'iswritable'], - 'Application': ['update', 'delete', 'massadd', 'get', 'create'], - 'Item': ['delete', 'get', 'iswritable', 'isreadable', 'update', 'create'], - 'Proxy': ['create', 'delete', 'update', 'iswritable', 'isreadable', 'get'], - 'Action': ['get', 'delete', 'update', 'create'], - 'Mediatype': ['update', 'delete', 'get', 'create'], - 'Maintenance': ['get', 'update', 'create', 'delete'], - 'Screen': ['delete', 'update', 'create', 'get'], 'Dhost': ['get'], - 'Itemprototype': ['delete', 'iswritable', 'get', 'update', 'create', 'isreadable'], - 'Host': ['massadd', 'massremove', 'isreadable', 'get', 'create', 'update', 'delete', 'massupdate', 'iswritable'], + 'Drule': ['copy', 'create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], + 'Dservice': ['get'], 'Event': ['acknowledge', 'get'], - 'Hostprototype': ['iswritable', 'create', 'update', 'delete', 'get', 'isreadable'], - 'Hostgroup': ['massadd', 'massupdate', 'update', 'isreadable', 'get', 'massremove', 'create', 'delete', 'iswritable'], - 'Image': ['get', 'update', 'delete', 'create'], - 'User': ['delete', 'get', 'updatemedia', 'updateprofile', 'update', 'iswritable', 'logout', 'addmedia', 'create', 'login', 'deletemedia', 'isreadable'], - 'Graphprototype': ['update', 'get', 'delete', 'create'], - 'Hostinterface': ['replacehostinterfaces', 'delete', 'get', 'massadd', 'create', 'update', 'massremove'], - 'Usermacro': ['create', 'deleteglobal', 'updateglobal', 'delete', 'update', 'createglobal', 'get'], + 'Graph': ['create', 'delete', 'get', 'update'], + 'Graphitem': ['get'], + 'Graphprototype': ['create', 'delete', 'get', 'update'], + 'History': ['get'], + 'Hostgroup': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massremove', 'massupdate', 'update'], + 'Hostinterface': ['create', 'delete', 'get', 'massadd', 'massremove', 'replacehostinterfaces', 'update'], + 'Host': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massremove', 'massupdate', 'update'], + 'Hostprototype': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], + 'Httptest': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], + 'Iconmap': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], + 'Image': ['create', 'delete', 'get', 'update'], + 'Item': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], + 'Itemprototype': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], + 'Maintenance': ['create', 'delete', 'get', 'update'], + 'Map': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], + 'Mediatype': ['create', 'delete', 'get', 'update'], + 'Proxy': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], + 'Screen': ['create', 'delete', 'get', 'update'], + 'Screenitem': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update', 'updatebyposition'], + 'Script': ['create', 'delete', 'execute', 'get', 'getscriptsbyhosts', 'update'], + 'Service': ['adddependencies', 'addtimes', 'create', 'delete', 'deletedependencies', 'deletetimes', 'get', 'getsla', 'isreadable', 'iswritable', 'update'], + 'Template': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massremove', 'massupdate', 'update'], + 'Templatescreen': ['copy', 'create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], + 'Templatescreenitem': ['get'], + 'Trigger': ['adddependencies', 'create', 'delete', 'deletedependencies', 'get', 'isreadable', 'iswritable', 'update'], + 'Triggerprototype': ['create', 'delete', 'get', 'update'], + 'User': ['addmedia', 'create', 'delete', 'deletemedia', 'get', 'isreadable', 'iswritable', 'login', 'logout', 'update', 'updatemedia', 'updateprofile'], + 'Usergroup': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massupdate', 'update'], + 'Usermacro': ['create', 'createglobal', 'delete', 'deleteglobal', 'get', 'update', 'updateglobal'], 'Usermedia': ['get'], - 'Configuration': ['import', 'export'], } def __init__(self, data={}): @@ -230,7 +230,7 @@ def main(): pw = module.params.get('password', None) if not pw: - pw = os.environ['ZABBIX_PW'] + pw = os.environ['ZABBIX_PASSWORD'] server = module.params['server'] -- cgit v1.2.3 From fe878255f5ac57e75a87bc2af58cedbd21d43501 Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Wed, 1 Apr 2015 16:03:04 -0400 Subject: Cleaned up space and commented code --- library/zbxapi.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/zbxapi.py b/library/zbxapi.py index 94b48ed61..f4f52909b 100755 --- a/library/zbxapi.py +++ b/library/zbxapi.py @@ -215,8 +215,7 @@ def main(): server=dict(default='https://localhost/zabbix/api_jsonrpc.php', type='str'), user=dict(default=None, type='str'), password=dict(default=None, type='str'), - zbx_class=dict( choices=ZabbixAPI.classes.keys()), - #zbx_class=dict(type='str', require=True), + zbx_class=dict(choices=ZabbixAPI.classes.keys()), action=dict(default=None, type='str'), params=dict(), debug=dict(default=False, type='bool'), -- 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 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 8a4888ad30ce7c5898caac47614da2e13a759320 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Sun, 1 Mar 2015 00:27:04 -0500 Subject: Add byo playbooks and enterprise docs - added byo playbooks - added byo (example) inventory - added a README_OSE.md for getting started with Enterprise deployments - Added an ansible.cfg as an example for configuration helpful for playbooks/roles --- README_OSE.md | 142 ++++++++++++++++++++++++++ ansible.cfg | 23 +++++ inventory/byo/group_vars/all | 28 +++++ inventory/byo/hosts | 10 ++ playbooks/byo/config.yml | 6 ++ playbooks/byo/filter_plugins | 1 + playbooks/byo/openshift-master/config.yml | 9 ++ playbooks/byo/openshift-master/filter_plugins | 1 + playbooks/byo/openshift-master/roles | 1 + playbooks/byo/openshift-node/config.yml | 79 ++++++++++++++ playbooks/byo/openshift-node/filter_plugins | 1 + playbooks/byo/openshift-node/roles | 1 + playbooks/byo/roles | 1 + roles/openshift_node/tasks/main.yml | 1 + 14 files changed, 304 insertions(+) create mode 100644 README_OSE.md create mode 100644 ansible.cfg create mode 100644 inventory/byo/group_vars/all create mode 100644 inventory/byo/hosts create mode 100644 playbooks/byo/config.yml create mode 120000 playbooks/byo/filter_plugins create mode 100644 playbooks/byo/openshift-master/config.yml create mode 120000 playbooks/byo/openshift-master/filter_plugins create mode 120000 playbooks/byo/openshift-master/roles create mode 100644 playbooks/byo/openshift-node/config.yml create mode 120000 playbooks/byo/openshift-node/filter_plugins create mode 120000 playbooks/byo/openshift-node/roles create mode 120000 playbooks/byo/roles diff --git a/README_OSE.md b/README_OSE.md new file mode 100644 index 000000000..6ebdb7f99 --- /dev/null +++ b/README_OSE.md @@ -0,0 +1,142 @@ +# Installing OSEv3 from dev puddles using ansible + +* [Requirements](#requirements) +* [Caveats](#caveats) +* [Known Issues](#known-issues) +* [Configuring the host inventory](#configuring-the-host-inventory) +* [Creating the default variables for the hosts and host groups](#creating-the-default-variables-for-the-hosts-and-host-groups) +* [Running the ansible playbooks](#running-the-ansible-playbooks) +* [Post-ansible steps](#post-ansible-steps) + +## Requirements +* ansible + * Tested using ansible-1.8.2-1.fc20.noarch, but should work with version 1.8+ + * Available in Fedora channels + * Available for EL with EPEL and Optional channel +* One or more RHEL 7.1 VMs +* ssh key based auth for the root user needs to be pre-configured from the host + running ansible to the remote hosts +* A checkout of openshift-ansible from https://github.com/openshift/openshift-ansible/ + + ```sh + git clone https://github.com/openshift/openshift-ansible.git + cd openshift-ansible + ``` + +## Caveats +This ansible repo is currently under heavy revision for providing OSE support; +the following items are highly likely to change before the OSE support is +merged into the upstream repo: + * the current git branch for testing + * how the inventory file should be configured + * variables that need to be set + * bootstrapping steps + * other configuration steps + +## Known Issues +* Host subscriptions are not configurable yet, the hosts need to be + pre-registered with subscription-manager or have the RHEL base repo + pre-configured. If using subscription-manager the following commands will + disable all but the rhel-7-server rhel-7-server-extras and + rhel-server7-ose-beta repos: +```sh +subscription-manager repos --disable="*" +subscription-manager repos \ +--enable="rhel-7-server-rpms" \ +--enable="rhel-7-server-extras-rpms" \ +--enable="rhel-server-7-ose-beta-rpms" +``` +* Configuration of router is not automated yet +* Configuration of docker-registry is not automated yet +* End-to-end testing has not been completed yet using this module +* root user is used for all ansible actions; eventually we will support using + a non-root user with sudo. + +## Configuring the host inventory +[Ansible docs](http://docs.ansible.com/intro_inventory.html) + +Example inventory file for configuring one master and two nodes for the test +environment. This can be configured in the default inventory file +(/etc/ansible/hosts), or using a custom file and passing the --inventory +option to ansible-playbook. + +/etc/ansible/hosts: +```ini +# This is an example of a bring your own (byo) host inventory + +# host group for masters +[masters] +ose3-master.example.com + +# host group for nodes +[nodes] +ose3-node[1:2].example.com +``` + +The hostnames above should resolve both from the hosts themselves and +the host where ansible is running (if different). + +## Creating the default variables for the hosts and host groups +[Ansible docs](http://docs.ansible.com/intro_inventory.html#id9) + +#### Group vars for all hosts +/etc/ansible/group_vars/all: +```yaml +--- +# Assume that we want to use the root as the ssh user for all hosts +ansible_ssh_user: root + +# Default debug level for all OpenShift hosts +openshift_debug_level: 4 + +# Set the OpenShift deployment type for all hosts +openshift_deployment_type: enterprise + +# Override the default registry for development +openshift_registry_url: docker-buildvm-rhose.usersys.redhat.com:5000/openshift3_beta/ose-${component}:${version} + +# To use the latest OpenShift Enterprise Errata puddle: +#openshift_additional_repos: +#- id: ose-devel +# name: ose-devel +# baseurl: http://buildvm-devops.usersys.redhat.com/puddle/build/OpenShiftEnterpriseErrata/3.0/latest/RH7-RHOSE-3.0/$basearch/os +# enabled: 1 +# gpgcheck: 0 +# To use the latest OpenShift Enterprise Whitelist puddle: +openshift_additional_repos: +- id: ose-devel + name: ose-devel + baseurl: http://buildvm-devops.usersys.redhat.com/puddle/build/OpenShiftEnterprise/3.0/latest/RH7-RHOSE-3.0/$basearch/os + enabled: 1 + gpgcheck: 0 + +``` + +## Running the ansible playbooks +From the openshift-ansible checkout run: +```sh +ansible-playbook playbooks/byo/config.yml +``` +**Note:** this assumes that the host inventory is /etc/ansible/hosts and the +group_vars are defined in /etc/ansible/group_vars, if using a different +inventory file (and a group_vars directory that is in the same directory as +the directory as the inventory) use the -i option for ansible-playbook. + +## Post-ansible steps +#### Create the default router +On the master host: +```sh +systemctl restart openshift-sdn-master +openshift ex router --create=true \ + --credentials=/var/lib/openshift/openshift.local.certificates/openshift-client/.kubeconfig \ + --images='docker-buildvm-rhose.usersys.redhat.com:5000/openshift3_beta/ose-${component}:${version}' +``` + +#### Create the default docker-registry +On the master host: +```sh +openshift ex registry --create=true \ + --credentials=/var/lib/openshift/openshift.local.certificates/openshift-client/.kubeconfig \ + --images='docker-buildvm-rhose.usersys.redhat.com:5000/openshift3_beta/ose-${component}:${version}' \ + --mount-host=/var/lib/openshift/docker-registry +``` diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 000000000..6a7722ad8 --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,23 @@ +# config file for ansible -- http://ansible.com/ +# ============================================== + +# This config file provides examples for running +# the OpenShift playbooks with the provided +# inventory scripts. Only global defaults are +# left uncommented + +[defaults] +# Add the roles directory to the roles path +roles_path = roles/ + +# Set the log_path +log_path = /tmp/ansible.log + +# Uncomment to use the provided BYO inventory +#hostfile = inventory/byo/hosts + +# Uncomment to use the provided GCE dynamic inventory script +#hostfile = inventory/gce/gce.py + +# Uncomment to use the provided AWS dynamic inventory script +#hostfile = inventory/aws/ec2.py diff --git a/inventory/byo/group_vars/all b/inventory/byo/group_vars/all new file mode 100644 index 000000000..d63e96668 --- /dev/null +++ b/inventory/byo/group_vars/all @@ -0,0 +1,28 @@ +--- +# lets assume that we want to use the root as the ssh user for all hosts +ansible_ssh_user: root + +# default debug level for all OpenShift hosts +openshift_debug_level: 4 + +# set the OpenShift deployment type for all hosts +openshift_deployment_type: enterprise + +# Override the default registry for development +openshift_registry_url: docker-buildvm-rhose.usersys.redhat.com:5000/openshift3_beta/ose-${component}:${version} + +# Use latest Errata puddle as an additional repo: +#openshift_additional_repos: +#- id: ose-devel +# name: ose-devel +# baseurl: http://buildvm-devops.usersys.redhat.com/puddle/build/OpenShiftEnterpriseErrata/3.0/latest/RH7-RHOSE-3.0/$basearch/os +# enabled: 1 +# gpgcheck: 0 + +# Use latest Whitelist puddle as an additional repo: +openshift_additional_repos: +- id: ose-devel + name: ose-devel + baseurl: http://buildvm-devops.usersys.redhat.com/puddle/build/OpenShiftEnterprise/3.0/latest/RH7-RHOSE-3.0/$basearch/os + enabled: 1 + gpgcheck: 0 diff --git a/inventory/byo/hosts b/inventory/byo/hosts new file mode 100644 index 000000000..2dd854778 --- /dev/null +++ b/inventory/byo/hosts @@ -0,0 +1,10 @@ +# This is an example of a bring your own (byo) host inventory + +# host group for masters +[masters] +ose3-master-ansible.test.example.com + +# host group for nodes +[nodes] +ose3-node[1:2]-ansible.test.example.com + diff --git a/playbooks/byo/config.yml b/playbooks/byo/config.yml new file mode 100644 index 000000000..dce49d32f --- /dev/null +++ b/playbooks/byo/config.yml @@ -0,0 +1,6 @@ +--- +- name: Run the openshift-master config playbook + include: openshift-master/config.yml + +- name: Run the openshift-node config playbook + include: openshift-node/config.yml diff --git a/playbooks/byo/filter_plugins b/playbooks/byo/filter_plugins new file mode 120000 index 000000000..a4f518f07 --- /dev/null +++ b/playbooks/byo/filter_plugins @@ -0,0 +1 @@ +../../filter_plugins \ No newline at end of file diff --git a/playbooks/byo/openshift-master/config.yml b/playbooks/byo/openshift-master/config.yml new file mode 100644 index 000000000..706f9285c --- /dev/null +++ b/playbooks/byo/openshift-master/config.yml @@ -0,0 +1,9 @@ +--- +- name: Gather facts for node hosts + hosts: nodes + +- name: Configure master instances + hosts: masters + roles: + - openshift_master + - openshift_sdn_master diff --git a/playbooks/byo/openshift-master/filter_plugins b/playbooks/byo/openshift-master/filter_plugins new file mode 120000 index 000000000..99a95e4ca --- /dev/null +++ b/playbooks/byo/openshift-master/filter_plugins @@ -0,0 +1 @@ +../../../filter_plugins \ No newline at end of file diff --git a/playbooks/byo/openshift-master/roles b/playbooks/byo/openshift-master/roles new file mode 120000 index 000000000..20c4c58cf --- /dev/null +++ b/playbooks/byo/openshift-master/roles @@ -0,0 +1 @@ +../../../roles \ No newline at end of file diff --git a/playbooks/byo/openshift-node/config.yml b/playbooks/byo/openshift-node/config.yml new file mode 100644 index 000000000..69ad7a840 --- /dev/null +++ b/playbooks/byo/openshift-node/config.yml @@ -0,0 +1,79 @@ +--- +- name: Gather facts for node hosts + hosts: nodes + 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: 'node' + local_facts: + hostname: "{{ openshift_hostname | default(None) }}" + 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: masters[0] + vars: + openshift_nodes: "{{ hostvars | oo_select_keys(groups['nodes']) }}" + 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 node instances + hosts: nodes + vars: + sync_tmpdir: "{{ hostvars[groups['masters'][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 }}" + openshift_sdn_master_url: http://{{ hostvars[groups['masters'][0]].openshift.common.hostname }}:4001 + 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 + - openshift_sdn_node diff --git a/playbooks/byo/openshift-node/filter_plugins b/playbooks/byo/openshift-node/filter_plugins new file mode 120000 index 000000000..99a95e4ca --- /dev/null +++ b/playbooks/byo/openshift-node/filter_plugins @@ -0,0 +1 @@ +../../../filter_plugins \ No newline at end of file diff --git a/playbooks/byo/openshift-node/roles b/playbooks/byo/openshift-node/roles new file mode 120000 index 000000000..20c4c58cf --- /dev/null +++ b/playbooks/byo/openshift-node/roles @@ -0,0 +1 @@ +../../../roles \ No newline at end of file diff --git a/playbooks/byo/roles b/playbooks/byo/roles new file mode 120000 index 000000000..b741aa3db --- /dev/null +++ b/playbooks/byo/roles @@ -0,0 +1 @@ +../../roles \ No newline at end of file diff --git a/roles/openshift_node/tasks/main.yml b/roles/openshift_node/tasks/main.yml index 8cfef0e15..e3c04585b 100644 --- a/roles/openshift_node/tasks/main.yml +++ b/roles/openshift_node/tasks/main.yml @@ -1,6 +1,7 @@ --- # 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' -- 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(-) 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(-) 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 b167f7b3c4082a3d990aabeb10faac888e7172b3 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Tue, 7 Apr 2015 22:34:00 -0400 Subject: move zbxapi module to a new os_zabbix role - cleans up repo root a bit --- library/zbxapi.py | 273 ---------------------------- playbooks/adhoc/noc/get_zabbix_problems.yml | 4 +- playbooks/adhoc/noc/library | 1 - playbooks/adhoc/noc/roles | 1 + roles/os_zabbix/library/zbxapi.py | 273 ++++++++++++++++++++++++++++ 5 files changed, 277 insertions(+), 275 deletions(-) delete mode 100755 library/zbxapi.py delete mode 120000 playbooks/adhoc/noc/library create mode 120000 playbooks/adhoc/noc/roles create mode 100755 roles/os_zabbix/library/zbxapi.py diff --git a/library/zbxapi.py b/library/zbxapi.py deleted file mode 100755 index f4f52909b..000000000 --- a/library/zbxapi.py +++ /dev/null @@ -1,273 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2015 Red Hat Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Purpose: An ansible module to communicate with zabbix. -# - -import json -import httplib2 -import sys -import os -import re - -class ZabbixAPI(object): - ''' - ZabbixAPI class - ''' - classes = { - 'Action': ['create', 'delete', 'get', 'update'], - 'Alert': ['get'], - 'Application': ['create', 'delete', 'get', 'massadd', 'update'], - 'Configuration': ['export', 'import'], - 'Dcheck': ['get'], - 'Dhost': ['get'], - 'Drule': ['copy', 'create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], - 'Dservice': ['get'], - 'Event': ['acknowledge', 'get'], - 'Graph': ['create', 'delete', 'get', 'update'], - 'Graphitem': ['get'], - 'Graphprototype': ['create', 'delete', 'get', 'update'], - 'History': ['get'], - 'Hostgroup': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massremove', 'massupdate', 'update'], - 'Hostinterface': ['create', 'delete', 'get', 'massadd', 'massremove', 'replacehostinterfaces', 'update'], - 'Host': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massremove', 'massupdate', 'update'], - 'Hostprototype': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], - 'Httptest': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], - 'Iconmap': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], - 'Image': ['create', 'delete', 'get', 'update'], - 'Item': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], - 'Itemprototype': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], - 'Maintenance': ['create', 'delete', 'get', 'update'], - 'Map': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], - 'Mediatype': ['create', 'delete', 'get', 'update'], - 'Proxy': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], - 'Screen': ['create', 'delete', 'get', 'update'], - 'Screenitem': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update', 'updatebyposition'], - 'Script': ['create', 'delete', 'execute', 'get', 'getscriptsbyhosts', 'update'], - 'Service': ['adddependencies', 'addtimes', 'create', 'delete', 'deletedependencies', 'deletetimes', 'get', 'getsla', 'isreadable', 'iswritable', 'update'], - 'Template': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massremove', 'massupdate', 'update'], - 'Templatescreen': ['copy', 'create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], - 'Templatescreenitem': ['get'], - 'Trigger': ['adddependencies', 'create', 'delete', 'deletedependencies', 'get', 'isreadable', 'iswritable', 'update'], - 'Triggerprototype': ['create', 'delete', 'get', 'update'], - 'User': ['addmedia', 'create', 'delete', 'deletemedia', 'get', 'isreadable', 'iswritable', 'login', 'logout', 'update', 'updatemedia', 'updateprofile'], - 'Usergroup': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massupdate', 'update'], - 'Usermacro': ['create', 'createglobal', 'delete', 'deleteglobal', 'get', 'update', 'updateglobal'], - 'Usermedia': ['get'], - } - - def __init__(self, data={}): - self.server = data['server'] or None - self.username = data['user'] or None - self.password = data['password'] or None - if any(map(lambda value: value == None, [self.server, self.username, self.password])): - print 'Please specify zabbix server url, username, and password.' - sys.exit(1) - - self.verbose = data.has_key('verbose') - self.use_ssl = data.has_key('use_ssl') - self.auth = None - - for class_name, method_names in self.classes.items(): - #obj = getattr(self, class_name)(self) - #obj.__dict__ - setattr(self, class_name.lower(), getattr(self, class_name)(self)) - - results = self.user.login(user=self.username, password=self.password) - - if results[0]['status'] == '200': - if results[1].has_key('result'): - self.auth = results[1]['result'] - elif results[1].has_key('error'): - print "Unable to authenticate with zabbix server. {0} ".format(results[1]['error']) - sys.exit(1) - else: - print "Error in call to zabbix. Http status: {0}.".format(results[0]['status']) - sys.exit(1) - - def perform(self, method, params): - ''' - This method calls your zabbix server. - - It requires the following parameters in order for a proper request to be processed: - - jsonrpc - the version of the JSON-RPC protocol used by the API; the Zabbix API implements JSON-RPC version 2.0; - method - the API method being called; - params - parameters that will be passed to the API method; - id - an arbitrary identifier of the request; - auth - a user authentication token; since we don't have one yet, it's set to null. - ''' - http_method = "POST" - if params.has_key("http_method"): - http_method = params['http_method'] - - jsonrpc = "2.0" - if params.has_key('jsonrpc'): - jsonrpc = params['jsonrpc'] - - rid = 1 - if params.has_key('id'): - rid = params['id'] - - http = None - if self.use_ssl: - http = httplib2.Http() - else: - http = httplib2.Http( disable_ssl_certificate_validation=True,) - - headers = params.get('headers', {}) - headers["Content-type"] = "application/json" - - body = { - "jsonrpc": jsonrpc, - "method": method, - "params": params, - "id": rid, - 'auth': self.auth, - } - - if method in ['user.login','api.version']: - del body['auth'] - - body = json.dumps(body) - - if self.verbose: - print body - print method - print headers - httplib2.debuglevel = 1 - - response, results = http.request(self.server, http_method, body, headers) - - if self.verbose: - print response - print results - - try: - results = json.loads(results) - except ValueError as e: - results = {"error": e.message} - - return response, results - - ''' - This bit of metaprogramming is where the ZabbixAPI subclasses are created. - For each of ZabbixAPI.classes we create a class from the key and methods - from the ZabbixAPI.classes values. We pass a reference to ZabbixAPI class - to each subclass in order for each to be able to call the perform method. - ''' - @staticmethod - def meta(class_name, method_names): - # This meta method allows a class to add methods to it. - def meta_method(Class, method_name): - # This template method is a stub method for each of the subclass - # methods. - def template_method(self, **params): - return self.parent.perform(class_name.lower()+"."+method_name, params) - template_method.__doc__ = "https://www.zabbix.com/documentation/2.4/manual/api/reference/%s/%s" % (class_name.lower(), method_name) - template_method.__name__ = method_name - # this is where the template method is placed inside of the subclass - # e.g. setattr(User, "create", stub_method) - setattr(Class, template_method.__name__, template_method) - - # This class call instantiates a subclass. e.g. User - Class=type(class_name, (object,), { '__doc__': "https://www.zabbix.com/documentation/2.4/manual/api/reference/%s" % class_name.lower() }) - # This init method gets placed inside of the Class - # to allow it to be instantiated. A reference to the parent class(ZabbixAPI) - # is passed in to allow each class access to the perform method. - def __init__(self, parent): - self.parent = parent - # This attaches the init to the subclass. e.g. Create - setattr(Class, __init__.__name__, __init__) - # For each of our ZabbixAPI.classes dict values - # Create a method and attach it to our subclass. - # e.g. 'User': ['delete', 'get', 'updatemedia', 'updateprofile', - # 'update', 'iswritable', 'logout', 'addmedia', 'create', - # 'login', 'deletemedia', 'isreadable'], - # User.delete - # User.get - for method_name in method_names: - meta_method(Class, method_name) - # Return our subclass with all methods attached - return Class - -# Attach all ZabbixAPI.classes to ZabbixAPI class through metaprogramming -for class_name, method_names in ZabbixAPI.classes.items(): - setattr(ZabbixAPI, class_name, ZabbixAPI.meta(class_name, method_names)) - -def main(): - - module = AnsibleModule( - argument_spec = dict( - server=dict(default='https://localhost/zabbix/api_jsonrpc.php', type='str'), - user=dict(default=None, type='str'), - password=dict(default=None, type='str'), - zbx_class=dict(choices=ZabbixAPI.classes.keys()), - action=dict(default=None, type='str'), - params=dict(), - debug=dict(default=False, type='bool'), - ), - #supports_check_mode=True - ) - - user = module.params.get('user', None) - if not user: - user = os.environ['ZABBIX_USER'] - - pw = module.params.get('password', None) - if not pw: - pw = os.environ['ZABBIX_PASSWORD'] - - server = module.params['server'] - - if module.params['debug']: - options['debug'] = True - - api_data = { - 'user': user, - 'password': pw, - 'server': server, - } - - if not user or not pw or not server: - module.fail_json('Please specify the user, password, and the zabbix server.') - - zapi = ZabbixAPI(api_data) - - zbx_class = module.params.get('zbx_class') - action = module.params.get('action') - params = module.params.get('params', {}) - - - # Get the instance we are trying to call - zbx_class_inst = zapi.__getattribute__(zbx_class.lower()) - # Get the instance's method we are trying to call - zbx_action_method = zapi.__getattribute__(zbx_class.capitalize()).__dict__[action] - # Make the call with the incoming params - results = zbx_action_method(zbx_class_inst, **params) - - # Results Section - changed_state = False - status = results[0]['status'] - if status not in ['200', '201']: - #changed_state = False - module.fail_json(msg="Http response: [%s] - Error: %s" % (str(results[0]), results[1])) - - module.exit_json(**{'results': results[1]['result']}) - -from ansible.module_utils.basic import * - -main() diff --git a/playbooks/adhoc/noc/get_zabbix_problems.yml b/playbooks/adhoc/noc/get_zabbix_problems.yml index 6ac5cdcf7..02bffc1d2 100644 --- a/playbooks/adhoc/noc/get_zabbix_problems.yml +++ b/playbooks/adhoc/noc/get_zabbix_problems.yml @@ -2,7 +2,9 @@ - name: 'Get current hosts who have triggers that are alerting by trigger description' hosts: localhost gather_facts: no - tasks: + roles: + - os_zabbix + post_tasks: - assert: that: oo_desc is defined diff --git a/playbooks/adhoc/noc/library b/playbooks/adhoc/noc/library deleted file mode 120000 index ba40d2f56..000000000 --- a/playbooks/adhoc/noc/library +++ /dev/null @@ -1 +0,0 @@ -../../../library \ No newline at end of file diff --git a/playbooks/adhoc/noc/roles b/playbooks/adhoc/noc/roles new file mode 120000 index 000000000..20c4c58cf --- /dev/null +++ b/playbooks/adhoc/noc/roles @@ -0,0 +1 @@ +../../../roles \ No newline at end of file diff --git a/roles/os_zabbix/library/zbxapi.py b/roles/os_zabbix/library/zbxapi.py new file mode 100755 index 000000000..f4f52909b --- /dev/null +++ b/roles/os_zabbix/library/zbxapi.py @@ -0,0 +1,273 @@ +#!/usr/bin/env python + +# Copyright 2015 Red Hat Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Purpose: An ansible module to communicate with zabbix. +# + +import json +import httplib2 +import sys +import os +import re + +class ZabbixAPI(object): + ''' + ZabbixAPI class + ''' + classes = { + 'Action': ['create', 'delete', 'get', 'update'], + 'Alert': ['get'], + 'Application': ['create', 'delete', 'get', 'massadd', 'update'], + 'Configuration': ['export', 'import'], + 'Dcheck': ['get'], + 'Dhost': ['get'], + 'Drule': ['copy', 'create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], + 'Dservice': ['get'], + 'Event': ['acknowledge', 'get'], + 'Graph': ['create', 'delete', 'get', 'update'], + 'Graphitem': ['get'], + 'Graphprototype': ['create', 'delete', 'get', 'update'], + 'History': ['get'], + 'Hostgroup': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massremove', 'massupdate', 'update'], + 'Hostinterface': ['create', 'delete', 'get', 'massadd', 'massremove', 'replacehostinterfaces', 'update'], + 'Host': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massremove', 'massupdate', 'update'], + 'Hostprototype': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], + 'Httptest': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], + 'Iconmap': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], + 'Image': ['create', 'delete', 'get', 'update'], + 'Item': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], + 'Itemprototype': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], + 'Maintenance': ['create', 'delete', 'get', 'update'], + 'Map': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], + 'Mediatype': ['create', 'delete', 'get', 'update'], + 'Proxy': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], + 'Screen': ['create', 'delete', 'get', 'update'], + 'Screenitem': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update', 'updatebyposition'], + 'Script': ['create', 'delete', 'execute', 'get', 'getscriptsbyhosts', 'update'], + 'Service': ['adddependencies', 'addtimes', 'create', 'delete', 'deletedependencies', 'deletetimes', 'get', 'getsla', 'isreadable', 'iswritable', 'update'], + 'Template': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massremove', 'massupdate', 'update'], + 'Templatescreen': ['copy', 'create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], + 'Templatescreenitem': ['get'], + 'Trigger': ['adddependencies', 'create', 'delete', 'deletedependencies', 'get', 'isreadable', 'iswritable', 'update'], + 'Triggerprototype': ['create', 'delete', 'get', 'update'], + 'User': ['addmedia', 'create', 'delete', 'deletemedia', 'get', 'isreadable', 'iswritable', 'login', 'logout', 'update', 'updatemedia', 'updateprofile'], + 'Usergroup': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massupdate', 'update'], + 'Usermacro': ['create', 'createglobal', 'delete', 'deleteglobal', 'get', 'update', 'updateglobal'], + 'Usermedia': ['get'], + } + + def __init__(self, data={}): + self.server = data['server'] or None + self.username = data['user'] or None + self.password = data['password'] or None + if any(map(lambda value: value == None, [self.server, self.username, self.password])): + print 'Please specify zabbix server url, username, and password.' + sys.exit(1) + + self.verbose = data.has_key('verbose') + self.use_ssl = data.has_key('use_ssl') + self.auth = None + + for class_name, method_names in self.classes.items(): + #obj = getattr(self, class_name)(self) + #obj.__dict__ + setattr(self, class_name.lower(), getattr(self, class_name)(self)) + + results = self.user.login(user=self.username, password=self.password) + + if results[0]['status'] == '200': + if results[1].has_key('result'): + self.auth = results[1]['result'] + elif results[1].has_key('error'): + print "Unable to authenticate with zabbix server. {0} ".format(results[1]['error']) + sys.exit(1) + else: + print "Error in call to zabbix. Http status: {0}.".format(results[0]['status']) + sys.exit(1) + + def perform(self, method, params): + ''' + This method calls your zabbix server. + + It requires the following parameters in order for a proper request to be processed: + + jsonrpc - the version of the JSON-RPC protocol used by the API; the Zabbix API implements JSON-RPC version 2.0; + method - the API method being called; + params - parameters that will be passed to the API method; + id - an arbitrary identifier of the request; + auth - a user authentication token; since we don't have one yet, it's set to null. + ''' + http_method = "POST" + if params.has_key("http_method"): + http_method = params['http_method'] + + jsonrpc = "2.0" + if params.has_key('jsonrpc'): + jsonrpc = params['jsonrpc'] + + rid = 1 + if params.has_key('id'): + rid = params['id'] + + http = None + if self.use_ssl: + http = httplib2.Http() + else: + http = httplib2.Http( disable_ssl_certificate_validation=True,) + + headers = params.get('headers', {}) + headers["Content-type"] = "application/json" + + body = { + "jsonrpc": jsonrpc, + "method": method, + "params": params, + "id": rid, + 'auth': self.auth, + } + + if method in ['user.login','api.version']: + del body['auth'] + + body = json.dumps(body) + + if self.verbose: + print body + print method + print headers + httplib2.debuglevel = 1 + + response, results = http.request(self.server, http_method, body, headers) + + if self.verbose: + print response + print results + + try: + results = json.loads(results) + except ValueError as e: + results = {"error": e.message} + + return response, results + + ''' + This bit of metaprogramming is where the ZabbixAPI subclasses are created. + For each of ZabbixAPI.classes we create a class from the key and methods + from the ZabbixAPI.classes values. We pass a reference to ZabbixAPI class + to each subclass in order for each to be able to call the perform method. + ''' + @staticmethod + def meta(class_name, method_names): + # This meta method allows a class to add methods to it. + def meta_method(Class, method_name): + # This template method is a stub method for each of the subclass + # methods. + def template_method(self, **params): + return self.parent.perform(class_name.lower()+"."+method_name, params) + template_method.__doc__ = "https://www.zabbix.com/documentation/2.4/manual/api/reference/%s/%s" % (class_name.lower(), method_name) + template_method.__name__ = method_name + # this is where the template method is placed inside of the subclass + # e.g. setattr(User, "create", stub_method) + setattr(Class, template_method.__name__, template_method) + + # This class call instantiates a subclass. e.g. User + Class=type(class_name, (object,), { '__doc__': "https://www.zabbix.com/documentation/2.4/manual/api/reference/%s" % class_name.lower() }) + # This init method gets placed inside of the Class + # to allow it to be instantiated. A reference to the parent class(ZabbixAPI) + # is passed in to allow each class access to the perform method. + def __init__(self, parent): + self.parent = parent + # This attaches the init to the subclass. e.g. Create + setattr(Class, __init__.__name__, __init__) + # For each of our ZabbixAPI.classes dict values + # Create a method and attach it to our subclass. + # e.g. 'User': ['delete', 'get', 'updatemedia', 'updateprofile', + # 'update', 'iswritable', 'logout', 'addmedia', 'create', + # 'login', 'deletemedia', 'isreadable'], + # User.delete + # User.get + for method_name in method_names: + meta_method(Class, method_name) + # Return our subclass with all methods attached + return Class + +# Attach all ZabbixAPI.classes to ZabbixAPI class through metaprogramming +for class_name, method_names in ZabbixAPI.classes.items(): + setattr(ZabbixAPI, class_name, ZabbixAPI.meta(class_name, method_names)) + +def main(): + + module = AnsibleModule( + argument_spec = dict( + server=dict(default='https://localhost/zabbix/api_jsonrpc.php', type='str'), + user=dict(default=None, type='str'), + password=dict(default=None, type='str'), + zbx_class=dict(choices=ZabbixAPI.classes.keys()), + action=dict(default=None, type='str'), + params=dict(), + debug=dict(default=False, type='bool'), + ), + #supports_check_mode=True + ) + + user = module.params.get('user', None) + if not user: + user = os.environ['ZABBIX_USER'] + + pw = module.params.get('password', None) + if not pw: + pw = os.environ['ZABBIX_PASSWORD'] + + server = module.params['server'] + + if module.params['debug']: + options['debug'] = True + + api_data = { + 'user': user, + 'password': pw, + 'server': server, + } + + if not user or not pw or not server: + module.fail_json('Please specify the user, password, and the zabbix server.') + + zapi = ZabbixAPI(api_data) + + zbx_class = module.params.get('zbx_class') + action = module.params.get('action') + params = module.params.get('params', {}) + + + # Get the instance we are trying to call + zbx_class_inst = zapi.__getattribute__(zbx_class.lower()) + # Get the instance's method we are trying to call + zbx_action_method = zapi.__getattribute__(zbx_class.capitalize()).__dict__[action] + # Make the call with the incoming params + results = zbx_action_method(zbx_class_inst, **params) + + # Results Section + changed_state = False + status = results[0]['status'] + if status not in ['200', '201']: + #changed_state = False + module.fail_json(msg="Http response: [%s] - Error: %s" % (str(results[0]), results[1])) + + module.exit_json(**{'results': results[1]['result']}) + +from ansible.module_utils.basic import * + +main() -- cgit v1.2.3 From 3c521113b4b7a79d69c788600df67c460c887963 Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Wed, 8 Apr 2015 16:53:28 -0400 Subject: Adding yum_repo role for facilitating repository deployment --- roles/yum_repo/README.md | 34 ++++++++++++++++++++++++++++++++++ roles/yum_repo/defaults/main.yml | 5 +++++ roles/yum_repo/handlers/main.yml | 2 ++ roles/yum_repo/meta/main.yml | 8 ++++++++ roles/yum_repo/tasks/main.yml | 8 ++++++++ roles/yum_repo/templates/yumrepo.j2 | 5 +++++ roles/yum_repo/vars/main.yml | 2 ++ 7 files changed, 64 insertions(+) create mode 100644 roles/yum_repo/README.md create mode 100644 roles/yum_repo/defaults/main.yml create mode 100644 roles/yum_repo/handlers/main.yml create mode 100644 roles/yum_repo/meta/main.yml create mode 100644 roles/yum_repo/tasks/main.yml create mode 100644 roles/yum_repo/templates/yumrepo.j2 create mode 100644 roles/yum_repo/vars/main.yml diff --git a/roles/yum_repo/README.md b/roles/yum_repo/README.md new file mode 100644 index 000000000..7f6a615cb --- /dev/null +++ b/roles/yum_repo/README.md @@ -0,0 +1,34 @@ +Role Name +========= + +This role allows easy deployment of yum repository config files. + +Requirements +------------ + +Yum + +Role Variables +-------------- + +Dependencies +------------ + +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 } + +License +------- + +ASL 2.0 + +Author Information +------------------ + +openshift online operations diff --git a/roles/yum_repo/defaults/main.yml b/roles/yum_repo/defaults/main.yml new file mode 100644 index 000000000..95e78af69 --- /dev/null +++ b/roles/yum_repo/defaults/main.yml @@ -0,0 +1,5 @@ +--- +# defaults file for yum-repo +repo_enabled: "1" +repo_gpg_check: "1" + diff --git a/roles/yum_repo/handlers/main.yml b/roles/yum_repo/handlers/main.yml new file mode 100644 index 000000000..a48c89ac2 --- /dev/null +++ b/roles/yum_repo/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for yum-repo diff --git a/roles/yum_repo/meta/main.yml b/roles/yum_repo/meta/main.yml new file mode 100644 index 000000000..e0b53ce7f --- /dev/null +++ b/roles/yum_repo/meta/main.yml @@ -0,0 +1,8 @@ +--- +galaxy_info: + author: openshift operations + description: + company: RedHat + license: ASL 2.0 + min_ansible_version: 1.2 +dependencies: [] diff --git a/roles/yum_repo/tasks/main.yml b/roles/yum_repo/tasks/main.yml new file mode 100644 index 000000000..a56d1f133 --- /dev/null +++ b/roles/yum_repo/tasks/main.yml @@ -0,0 +1,8 @@ +--- +# tasks file for yum-repo + +- name: Installing yum-repo template + template: + src: yumrepo.j2 + dest: /etc/yum.repos.d/{{ repo_tag }}.repo + diff --git a/roles/yum_repo/templates/yumrepo.j2 b/roles/yum_repo/templates/yumrepo.j2 new file mode 100644 index 000000000..b06a6f41a --- /dev/null +++ b/roles/yum_repo/templates/yumrepo.j2 @@ -0,0 +1,5 @@ +[{{ repo_tag }}] +name={{ repo_name }} +baseurl={{ repo_baseurl }} +enabled={{ repo_enabled }} +gpg_check={{ repo_gpg_check }} diff --git a/roles/yum_repo/vars/main.yml b/roles/yum_repo/vars/main.yml new file mode 100644 index 000000000..48182ac8e --- /dev/null +++ b/roles/yum_repo/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for yum-repo -- cgit v1.2.3 From 9f59e1bad63fa3841c9f2a50d4b46dbd35601788 Mon Sep 17 00:00:00 2001 From: Matt Woodson Date: Thu, 9 Apr 2015 09:56:41 -0400 Subject: added more options to the yum repo --- roles/yum_repo/templates/yumrepo.j2 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/roles/yum_repo/templates/yumrepo.j2 b/roles/yum_repo/templates/yumrepo.j2 index b06a6f41a..af879be31 100644 --- a/roles/yum_repo/templates/yumrepo.j2 +++ b/roles/yum_repo/templates/yumrepo.j2 @@ -3,3 +3,7 @@ name={{ repo_name }} baseurl={{ repo_baseurl }} enabled={{ repo_enabled }} gpg_check={{ repo_gpg_check }} +sslverify={{ repo_sslverify }} +sslclientcert={{ repo_client_cert }} +sslclientkey={{ repo_client_key }} +gpgkey={{ repo_gpgkey }} -- 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(-) 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 f28ff57f98140a1a22423df34d6457ee669fe714 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Thu, 9 Apr 2015 12:58:43 -0400 Subject: refactor yum_repo role to handle multiple repos/files - Rename yum_repo role to yum_repos - Update yum_repos to take a more complex datastructure to describe multiple repo files and multiple repos within those files - Update the template to support multiple repos within the repo file - Update the template to allow for any key, value pair passed in instead of a hard coded list. - Add assertions to verify the repo_files variable is properly defined - Convert the legacy variables to the new repo_files variable --- roles/yum_repo/README.md | 34 ----------- roles/yum_repo/defaults/main.yml | 5 -- roles/yum_repo/handlers/main.yml | 2 - roles/yum_repo/meta/main.yml | 8 --- roles/yum_repo/tasks/main.yml | 8 --- roles/yum_repo/templates/yumrepo.j2 | 9 --- roles/yum_repo/vars/main.yml | 2 - roles/yum_repos/README.md | 113 +++++++++++++++++++++++++++++++++++ roles/yum_repos/defaults/main.yml | 3 + roles/yum_repos/meta/main.yml | 8 +++ roles/yum_repos/tasks/main.yml | 47 +++++++++++++++ roles/yum_repos/templates/yumrepo.j2 | 18 ++++++ 12 files changed, 189 insertions(+), 68 deletions(-) delete mode 100644 roles/yum_repo/README.md delete mode 100644 roles/yum_repo/defaults/main.yml delete mode 100644 roles/yum_repo/handlers/main.yml delete mode 100644 roles/yum_repo/meta/main.yml delete mode 100644 roles/yum_repo/tasks/main.yml delete mode 100644 roles/yum_repo/templates/yumrepo.j2 delete mode 100644 roles/yum_repo/vars/main.yml create mode 100644 roles/yum_repos/README.md create mode 100644 roles/yum_repos/defaults/main.yml create mode 100644 roles/yum_repos/meta/main.yml create mode 100644 roles/yum_repos/tasks/main.yml create mode 100644 roles/yum_repos/templates/yumrepo.j2 diff --git a/roles/yum_repo/README.md b/roles/yum_repo/README.md deleted file mode 100644 index 7f6a615cb..000000000 --- a/roles/yum_repo/README.md +++ /dev/null @@ -1,34 +0,0 @@ -Role Name -========= - -This role allows easy deployment of yum repository config files. - -Requirements ------------- - -Yum - -Role Variables --------------- - -Dependencies ------------- - -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 } - -License -------- - -ASL 2.0 - -Author Information ------------------- - -openshift online operations diff --git a/roles/yum_repo/defaults/main.yml b/roles/yum_repo/defaults/main.yml deleted file mode 100644 index 95e78af69..000000000 --- a/roles/yum_repo/defaults/main.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -# defaults file for yum-repo -repo_enabled: "1" -repo_gpg_check: "1" - diff --git a/roles/yum_repo/handlers/main.yml b/roles/yum_repo/handlers/main.yml deleted file mode 100644 index a48c89ac2..000000000 --- a/roles/yum_repo/handlers/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# handlers file for yum-repo diff --git a/roles/yum_repo/meta/main.yml b/roles/yum_repo/meta/main.yml deleted file mode 100644 index e0b53ce7f..000000000 --- a/roles/yum_repo/meta/main.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -galaxy_info: - author: openshift operations - description: - company: RedHat - license: ASL 2.0 - min_ansible_version: 1.2 -dependencies: [] diff --git a/roles/yum_repo/tasks/main.yml b/roles/yum_repo/tasks/main.yml deleted file mode 100644 index a56d1f133..000000000 --- a/roles/yum_repo/tasks/main.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -# tasks file for yum-repo - -- name: Installing yum-repo template - template: - src: yumrepo.j2 - dest: /etc/yum.repos.d/{{ repo_tag }}.repo - diff --git a/roles/yum_repo/templates/yumrepo.j2 b/roles/yum_repo/templates/yumrepo.j2 deleted file mode 100644 index af879be31..000000000 --- a/roles/yum_repo/templates/yumrepo.j2 +++ /dev/null @@ -1,9 +0,0 @@ -[{{ repo_tag }}] -name={{ repo_name }} -baseurl={{ repo_baseurl }} -enabled={{ repo_enabled }} -gpg_check={{ repo_gpg_check }} -sslverify={{ repo_sslverify }} -sslclientcert={{ repo_client_cert }} -sslclientkey={{ repo_client_key }} -gpgkey={{ repo_gpgkey }} diff --git a/roles/yum_repo/vars/main.yml b/roles/yum_repo/vars/main.yml deleted file mode 100644 index 48182ac8e..000000000 --- a/roles/yum_repo/vars/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# vars file for yum-repo diff --git a/roles/yum_repos/README.md b/roles/yum_repos/README.md new file mode 100644 index 000000000..51ecd5d34 --- /dev/null +++ b/roles/yum_repos/README.md @@ -0,0 +1,113 @@ +Yum Repos +========= + +This role allows easy deployment of yum repository config files. + +Requirements +------------ + +Yum + +Role Variables +-------------- + +| Name | Default value | | +|-------------------|---------------|--------------------------------------------| +| repo_files | None | | +| repo_enabled | 1 | Should repos be enabled by default | +| repo_gpgcheck | 1 | Should repo gpgcheck be enabled by default | + +Dependencies +------------ + +Example Playbook +---------------- + +A single repo file containing a single repo: + - hosts: servers + roles: + - role: yum_repos + repo_files: + - id: my_repo + repos: + - id: my_repo + name: My Awesome Repo + baseurl: https://my.awesome.repo/is/available/here + skip_if_unavailable: yes + gpgkey: https://my.awesome.repo/pubkey.gpg + +A single repo file containing a single repo, disabling gpgcheck + - hosts: servers + roles: + - role: yum_repos + repo_files: + - id: my_other_repo + repos: + - id: my_other_repo + name: My Other Awesome Repo + baseurl: https://my.other.awesome.repo/is/available/here + gpgcheck: no + +A single repo file containing a single disabled repo + - hosts: servers + roles: + - role: yum_repos + repo_files: + - id: my_other_repo + repos: + - id: my_other_repo + name: My Other Awesome Repo + baseurl: https://my.other.awesome.repo/is/available/here + enabled: no + +A single repo file containing multiple repos + - hosts: servers + roles: + - role: yum_repos + repo_files: + id: my_repos + repos: + - id: my_repo + name: My Awesome Repo + baseurl: https://my.awesome.repo/is/available/here + gpgkey: https://my.awesome.repo/pubkey.gpg + - id: my_other_repo + name: My Other Awesome Repo + baseurl: https://my.other.awesome.repo/is/available/here + gpgkey: https://my.other.awesome.repo/pubkey.gpg + +Multiple repo files containing multiple repos + - hosts: servers + roles: + - role: yum_repos + repo_files: + - id: my_repos + repos: + - id: my_repo + name: My Awesome Repo + baseurl: https://my.awesome.repo/is/available/here + gpgkey: https://my.awesome.repo/pubkey.gpg + - id: my_other_repo + name: My Other Awesome Repo + baseurl: https://my.other.awesome.repo/is/available/here + gpgkey: https://my.other.awesome.repo/pubkey.gpg + - id: joes_repos + repos: + - id: joes_repo + name: Joe's Less Awesome Repo + baseurl: https://joes.repo/is/here + gpgkey: https://joes.repo/pubkey.gpg + - id: joes_otherrepo + name: Joe's Other Less Awesome Repo + baseurl: https://joes.repo/is/there + gpgkey: https://joes.repo/pubkey.gpg + +License +------- + +ASL 2.0 + +Author Information +------------------ + +openshift online operations diff --git a/roles/yum_repos/defaults/main.yml b/roles/yum_repos/defaults/main.yml new file mode 100644 index 000000000..515fb7a4a --- /dev/null +++ b/roles/yum_repos/defaults/main.yml @@ -0,0 +1,3 @@ +--- +repo_enabled: 1 +repo_gpgcheck: 1 diff --git a/roles/yum_repos/meta/main.yml b/roles/yum_repos/meta/main.yml new file mode 100644 index 000000000..6b8374da9 --- /dev/null +++ b/roles/yum_repos/meta/main.yml @@ -0,0 +1,8 @@ +--- +galaxy_info: + author: openshift operations + description: + company: Red Hat, Inc. + license: ASL 2.0 + min_ansible_version: 1.2 +dependencies: [] diff --git a/roles/yum_repos/tasks/main.yml b/roles/yum_repos/tasks/main.yml new file mode 100644 index 000000000..a9903c6c6 --- /dev/null +++ b/roles/yum_repos/tasks/main.yml @@ -0,0 +1,47 @@ +--- +# Convert old params to new params +- set_fact: + repo_files: + - id: "{{ repo_tag }}" + repos: + - id: "{{ repo_tag }}" + name: "{{ repo_name }}" + baseurl: "{{ repo_baseurl }}" + enabled: "{{ repo_enabled }}" + gpgcheck: "{{ repo_gpg_check | default(repo_gpgcheck) }}" + sslverify: "{{ repo_sslverify | default(None) }}" + sslclientcert: "{{ repo_sslclientcert | default(None) }}" + sslclientkey: "{{ repo_sslclientkey | default(None) }}" + gpgkey: "{{ repo_gpgkey | default(None) }}" + when: repo_files is not defined + +- name: Verify repo_files is a list + assert: + that: + - repo_files is iterable and repo_files is not string and repo_files is not mapping + +- name: Verify repo_files items have an id and a repos list + assert: + that: + - item is mapping + - "'id' in item" + - "'repos' in item" + - item.repos is iterable and item.repos is not string and item.repos is not mapping + with_items: repo_files + +- name: Verify that repo_files.repos have the required keys + assert: + that: + - item.1 is mapping + - "'id' in item.1" + - "'name' in item.1" + - "'baseurl' in item.1" + with_subelements: + - repo_files + - repos + +- name: Installing yum-repo template + template: + src: yumrepo.j2 + dest: /etc/yum.repos.d/{{ item.id }}.repo + with_items: repo_files diff --git a/roles/yum_repos/templates/yumrepo.j2 b/roles/yum_repos/templates/yumrepo.j2 new file mode 100644 index 000000000..0dfdbfe43 --- /dev/null +++ b/roles/yum_repos/templates/yumrepo.j2 @@ -0,0 +1,18 @@ +{% set repos = item.repos %} +{% for repo in repos %} +[{{ repo.id }}] +name={{ repo.name }} +baseurl={{ repo.baseurl }} +{% set repo_enabled_value = repo.enabled | default(repo_enabled) %} +{% set enable_repo = 1 if (repo_enabled_value | int(0) == 1 or repo_enabled_value | lower in ['true', 'yes']) else 0 %} +enabled={{ enable_repo }} +{% set repo_gpgcheck_value = repo.gpgcheck | default(repo_gpgcheck) %} +{% set enable_gpgcheck = 1 if (repo_gpgcheck_value | int(0) == 1 or repo_gpgcheck_value | lower in ['true', 'yes']) else 0 %} +gpgcheck={{ enable_gpgcheck }} +{% for key, value in repo.iteritems() %} +{% if key not in ['id', 'name', 'baseurl', 'enabled', 'gpgcheck'] and value is defined and value != '' %} +{{ key }}={{ value }} +{% endif %} +{% endfor %} + +{% endfor %} -- 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(-) 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 8022525b3c335ecd8213429da428fc04228adcf2 Mon Sep 17 00:00:00 2001 From: Matt Woodson Date: Thu, 9 Apr 2015 15:28:43 -0400 Subject: added sebools for ansible tower config --- roles/ansible_tower/tasks/main.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/roles/ansible_tower/tasks/main.yaml b/roles/ansible_tower/tasks/main.yaml index f58a5b1c2..e9bde9478 100644 --- a/roles/ansible_tower/tasks/main.yaml +++ b/roles/ansible_tower/tasks/main.yaml @@ -25,3 +25,9 @@ - name: Open firewalld port for https firewalld: port=8080/tcp permanent=true state=enabled +- name: Set (httpd_can_network_connect) flag on and keep it persistent across reboots + seboolean: name=httpd_can_network_connect state=yes persistent=yes + +- name: Set (httpd_can_network_connect_db) flag on and keep it persistent across reboots + seboolean: name=httpd_can_network_connect_db state=yes persistent=yes + -- cgit v1.2.3 From 1917cd3f88299c4dc23ef344c0e2aefc7e79db4f Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Thu, 9 Apr 2015 16:43:14 -0400 Subject: Adding a multi_ec2 yaml configure role --- roles/openshift_ansible_inventory/README.md | 41 ++++++++++++++++++++++ .../openshift_ansible_inventory/defaults/main.yml | 4 +++ .../openshift_ansible_inventory/handlers/main.yml | 2 ++ roles/openshift_ansible_inventory/meta/main.yml | 8 +++++ roles/openshift_ansible_inventory/tasks/main.yml | 11 ++++++ .../templates/multi_ec2.yaml.j2 | 11 ++++++ roles/openshift_ansible_inventory/vars/main.yml | 2 ++ 7 files changed, 79 insertions(+) create mode 100644 roles/openshift_ansible_inventory/README.md create mode 100644 roles/openshift_ansible_inventory/defaults/main.yml create mode 100644 roles/openshift_ansible_inventory/handlers/main.yml create mode 100644 roles/openshift_ansible_inventory/meta/main.yml create mode 100644 roles/openshift_ansible_inventory/tasks/main.yml create mode 100644 roles/openshift_ansible_inventory/templates/multi_ec2.yaml.j2 create mode 100644 roles/openshift_ansible_inventory/vars/main.yml diff --git a/roles/openshift_ansible_inventory/README.md b/roles/openshift_ansible_inventory/README.md new file mode 100644 index 000000000..69a07effd --- /dev/null +++ b/roles/openshift_ansible_inventory/README.md @@ -0,0 +1,41 @@ +Openshift Ansible Inventory +========= + +Install and configure openshift-ansible-inventory. + +Requirements +------------ + +None + +Role Variables +-------------- + +oo_inventory_group +oo_inventory_user +oo_inventory_accounts +oo_inventory_cache_max_age + +Dependencies +------------ + +None + +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 } + +License +------- + +ASL 2.0 + +Author Information +------------------ + +Openshift operations, Red Hat, Inc diff --git a/roles/openshift_ansible_inventory/defaults/main.yml b/roles/openshift_ansible_inventory/defaults/main.yml new file mode 100644 index 000000000..f53c00c80 --- /dev/null +++ b/roles/openshift_ansible_inventory/defaults/main.yml @@ -0,0 +1,4 @@ +--- +oo_inventory_group: root +oo_inventory_owner: root +oo_inventory_cache_max_age: 1800 diff --git a/roles/openshift_ansible_inventory/handlers/main.yml b/roles/openshift_ansible_inventory/handlers/main.yml new file mode 100644 index 000000000..e2db43477 --- /dev/null +++ b/roles/openshift_ansible_inventory/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for openshift_ansible_inventory diff --git a/roles/openshift_ansible_inventory/meta/main.yml b/roles/openshift_ansible_inventory/meta/main.yml new file mode 100644 index 000000000..ff3df0a7d --- /dev/null +++ b/roles/openshift_ansible_inventory/meta/main.yml @@ -0,0 +1,8 @@ +--- +galaxy_info: + author: Openshift + description: Install and configure openshift-ansible-inventory + company: Red Hat, Inc + license: ASL 2.0 + min_ansible_version: 1.2 +dependencies: [] diff --git a/roles/openshift_ansible_inventory/tasks/main.yml b/roles/openshift_ansible_inventory/tasks/main.yml new file mode 100644 index 000000000..3990d5750 --- /dev/null +++ b/roles/openshift_ansible_inventory/tasks/main.yml @@ -0,0 +1,11 @@ +--- +- yum: + name: openshift-ansible-inventory + state: present + +- template: + src: multi_ec2.yaml.j2 + dest: /etc/ansible/multi_ec2.yaml + group: "{{ oo_inventory_group }}" + owner: "{{ oo_inventory_owner }}" + mode: "0640" diff --git a/roles/openshift_ansible_inventory/templates/multi_ec2.yaml.j2 b/roles/openshift_ansible_inventory/templates/multi_ec2.yaml.j2 new file mode 100644 index 000000000..23dfe73b8 --- /dev/null +++ b/roles/openshift_ansible_inventory/templates/multi_ec2.yaml.j2 @@ -0,0 +1,11 @@ +# multi ec2 inventory configs +cache_max_age: {{ oo_inventory_cache_max_age }} +accounts: +{% for account in oo_inventory_accounts %} + - name: {{ account.name }} + provider: {{ account.provider }} + env_vars: + AWS_ACCESS_KEY_ID: {{ account.env_vars.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: {{ account.env_vars.AWS_SECRET_ACCESS_KEY }} + +{% endfor %} diff --git a/roles/openshift_ansible_inventory/vars/main.yml b/roles/openshift_ansible_inventory/vars/main.yml new file mode 100644 index 000000000..25c049282 --- /dev/null +++ b/roles/openshift_ansible_inventory/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for openshift_ansible_inventory -- cgit v1.2.3 From 9fbec064d28a72963b1566258b4bcabcd63b2c23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9na=C3=AFc=20Huard?= 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 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 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(-) 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 187e11209d0b7494ffacbabde569c14a8d0ebe2f Mon Sep 17 00:00:00 2001 From: Ricardo Bernardeli Date: Mon, 13 Apr 2015 09:20:38 +1000 Subject: =?UTF-8?q?Add=20extra=20information=20for=20AWS=20README=20Make?= =?UTF-8?q?=20security=20group=20an=20environment=20variable=20with=20defa?= =?UTF-8?q?ult=20to=20=E2=80=98public=E2=80=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README_AWS.md | 22 ++++++++++++++++++++-- .../aws/openshift-cluster/launch_instances.yml | 3 ++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/README_AWS.md b/README_AWS.md index e877f34c6..37f4c5f51 100644 --- a/README_AWS.md +++ b/README_AWS.md @@ -14,7 +14,7 @@ Create a credentials file export AWS_ACCESS_KEY_ID='AKIASTUFF' export AWS_SECRET_ACCESS_KEY='STUFF' ``` -1. source this file +2. source this file ``` source ~/.aws_creds ``` @@ -23,7 +23,7 @@ Note: You must source this file in each shell that you want to run cloud.rb (Optional) Setup your $HOME/.ssh/config file ------------------------------------------- -In case of a cluster creation, or any other case where you don't know the machine hostname in advance, you can use '.ssh/config' +In case of a cluster creation, or any other case where you don't know the machine hostname in advance, you can use '.ssh/config' to setup a private key file to allow ansible to connect to the created hosts. To do so, add the the following entry to your $HOME/.ssh/config file and make it point to the private key file which allows you to login on AWS. @@ -34,6 +34,24 @@ Host *.compute-1.amazonaws.com Alternatively, you can configure your ssh-agent to hold the credentials to connect to your AWS instances. +(Optional) Choose where the cluster will be launched +---------------------------------------------------- + +By default, a cluster is launched with the following configuration: + +- Instance type: m3.large +- AMI: ami-307b3658 +- Region: us-east-1 +- Keypair name: libra +- Security group: public + +If needed, these values can be changed by setting environment variables on your system. + +- export ec2_instance_type='m3.large' +- export ec2_ami='ami-307b3658' +- export ec2_region='us-east-1' +- export ec2_keypair='libra' +- export ec2_security_group='public' Install Dependencies -------------------- diff --git a/playbooks/aws/openshift-cluster/launch_instances.yml b/playbooks/aws/openshift-cluster/launch_instances.yml index e4d5952fd..9d645fbe5 100644 --- a/playbooks/aws/openshift-cluster/launch_instances.yml +++ b/playbooks/aws/openshift-cluster/launch_instances.yml @@ -5,6 +5,7 @@ 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) }}" + security_group: "{{ lookup('env', 'ec2_security_group')|default('public', true) }}" env: "{{ cluster }}" host_type: "{{ type }}" env_host_type: "{{ cluster }}-openshift-{{ type }}" @@ -14,7 +15,7 @@ state: present region: "{{ machine_region }}" keypair: "{{ machine_keypair }}" - group: ['public'] + group: "{{ security_group }}" instance_type: "{{ machine_type }}" image: "{{ machine_image }}" count: "{{ instances | oo_len }}" -- 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(-) 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(-) 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(-) 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 From 6a4b7a5eb6c4b5e747bab795e2428d7c3992f559 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Wed, 1 Apr 2015 15:09:19 -0400 Subject: Configuration updates for latest builds and major refactor Configuration updates for latest builds - Switch to using create-node-config - Switch sdn services to use etcd over SSL - This re-uses the client certificate deployed on each node - Additional node registration changes - Do not assume that metadata service is available in openshift_facts module - Call systemctl daemon-reload after installing openshift-master, openshift-sdn-master, openshift-node, openshift-sdn-node - Fix bug overriding openshift_hostname and openshift_public_hostname in byo playbooks - Start moving generated configs to /etc/openshift - Some custom module cleanup - Add known issue with ansible-1.9 to README_OSE.md - Update to genericize the kubernetes_register_node module - Default to use kubectl for commands - Allow for overriding kubectl_cmd - In openshift_register_node role, override kubectl_cmd to openshift_kube - Set default openshift_registry_url for enterprise when deployment_type is enterprise - Fix openshift_register_node for client config change - Ensure that master certs directory is created - Add roles and filter_plugin symlinks to playbooks/common/openshift-master and node - Allow non-root user with sudo nopasswd access - Updates for README_OSE.md - Update byo inventory for adding additional comments - Updates for node cert/config sync to work with non-root user using sudo - Move node config/certs to /etc/openshift/node - Don't use path for mktemp. addresses: https://github.com/openshift/openshift-ansible/issues/154 Create common playbooks - create common/openshift-master/config.yml - create common/openshift-node/config.yml - update playbooks to use new common playbooks - update launch playbooks to call update playbooks - fix openshift_registry and openshift_node_ip usage Set default deployment type to origin - openshift_repo updates for enabling origin deployments - also separate repo and gpgkey file structure - remove kubernetes repo since it isn't currently needed - full deployment type support for bin/cluster - honor OS_DEPLOYMENT_TYPE env variable - add --deployment-type option, which will override OS_DEPLOYMENT_TYPE if set - if neither OS_DEPLOYMENT_TYPE or --deployment-type is set, defaults to origin installs Additional changes: - Add separate config action to bin/cluster that runs ansible config but does not update packages - Some more duplication reduction in cluster playbooks. - Rename task files in playbooks dirs to have tasks in their name for clarity. - update aws/gce scripts to use a directory for inventory (otherwise when there are no hosts returned from dynamic inventory there is an error) libvirt refactor and update - add libvirt dynamic inventory - updates to use dynamic inventory for libvirt --- README_OSE.md | 191 +++-- README_libvirt.md | 78 +- bin/cluster | 91 ++- filter_plugins/oo_filters.py | 16 +- inventory/aws/ec2.ini | 62 -- inventory/aws/ec2.py | 798 --------------------- inventory/aws/group_vars/all | 2 - inventory/aws/hosts/ec2.ini | 62 ++ inventory/aws/hosts/ec2.py | 798 +++++++++++++++++++++ inventory/aws/hosts/hosts | 1 + inventory/byo/group_vars/all | 28 - inventory/byo/hosts | 26 +- inventory/gce/gce.py | 287 -------- inventory/gce/group_vars/all | 2 - inventory/gce/hosts/gce.py | 287 ++++++++ inventory/gce/hosts/hosts | 1 + inventory/libvirt/group_vars/all | 2 - inventory/libvirt/hosts | 2 - inventory/libvirt/hosts/hosts | 1 + inventory/libvirt/hosts/libvirt.ini | 20 + inventory/libvirt/hosts/libvirt_generic.py | 179 +++++ playbooks/aws/openshift-cluster/config.yml | 36 + playbooks/aws/openshift-cluster/launch.yml | 73 +- .../aws/openshift-cluster/launch_instances.yml | 63 -- playbooks/aws/openshift-cluster/list.yml | 15 +- .../openshift-cluster/tasks/launch_instances.yml | 69 ++ playbooks/aws/openshift-cluster/terminate.yml | 24 +- playbooks/aws/openshift-cluster/update.yml | 25 +- playbooks/aws/openshift-cluster/vars.yml | 19 + playbooks/aws/openshift-master/config.yml | 27 +- playbooks/aws/openshift-master/launch.yml | 8 +- playbooks/aws/openshift-master/terminate.yml | 17 +- playbooks/aws/openshift-master/vars.yml | 3 - playbooks/aws/openshift-node/config.yml | 110 +-- playbooks/aws/openshift-node/launch.yml | 10 +- playbooks/aws/openshift-node/terminate.yml | 17 +- playbooks/aws/openshift-node/vars.yml | 3 - playbooks/byo/openshift-master/config.yml | 20 +- playbooks/byo/openshift-node/config.yml | 90 +-- playbooks/byo/openshift_facts.yml | 10 + playbooks/common/openshift-cluster/config.yml | 4 + playbooks/common/openshift-cluster/filter_plugins | 1 + playbooks/common/openshift-cluster/roles | 1 + .../set_master_launch_facts_tasks.yml | 11 + .../set_node_launch_facts_tasks.yml | 11 + .../update_repos_and_packages.yml | 7 + playbooks/common/openshift-master/config.yml | 19 + playbooks/common/openshift-master/filter_plugins | 1 + playbooks/common/openshift-master/roles | 1 + playbooks/common/openshift-node/config.yml | 121 ++++ playbooks/common/openshift-node/filter_plugins | 1 + playbooks/common/openshift-node/roles | 1 + playbooks/gce/openshift-cluster/config.yml | 37 + playbooks/gce/openshift-cluster/launch.yml | 72 +- .../gce/openshift-cluster/launch_instances.yml | 44 -- playbooks/gce/openshift-cluster/list.yml | 15 +- .../openshift-cluster/tasks/launch_instances.yml | 42 ++ playbooks/gce/openshift-cluster/terminate.yml | 22 +- playbooks/gce/openshift-cluster/update.yml | 25 +- playbooks/gce/openshift-cluster/vars.yml | 14 + playbooks/gce/openshift-master/config.yml | 24 +- playbooks/gce/openshift-master/launch.yml | 6 +- playbooks/gce/openshift-master/terminate.yml | 11 +- playbooks/gce/openshift-master/vars.yml | 3 - playbooks/gce/openshift-node/config.yml | 106 +-- playbooks/gce/openshift-node/launch.yml | 6 +- playbooks/gce/openshift-node/terminate.yml | 11 +- playbooks/gce/openshift-node/vars.yml | 3 - playbooks/libvirt/openshift-cluster/config.yml | 38 + playbooks/libvirt/openshift-cluster/launch.yml | 81 +-- .../libvirt/openshift-cluster/launch_instances.yml | 102 --- playbooks/libvirt/openshift-cluster/list.yml | 50 +- .../openshift-cluster/tasks/configure_libvirt.yml | 6 + .../tasks/configure_libvirt_network.yml | 27 + .../tasks/configure_libvirt_storage_pool.yml | 27 + .../openshift-cluster/tasks/launch_instances.yml | 104 +++ .../libvirt/openshift-cluster/templates/domain.xml | 67 ++ .../libvirt/openshift-cluster/templates/meta-data | 3 + .../openshift-cluster/templates/network.xml | 23 + .../libvirt/openshift-cluster/templates/user-data | 23 + playbooks/libvirt/openshift-cluster/terminate.yml | 69 +- playbooks/libvirt/openshift-cluster/update.yml | 18 + playbooks/libvirt/openshift-cluster/vars.yml | 38 +- 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 - roles/openshift_common/tasks/main.yml | 4 +- roles/openshift_common/vars/main.yml | 4 + roles/openshift_facts/library/openshift_facts.py | 92 ++- roles/openshift_master/tasks/main.yml | 64 +- roles/openshift_master/vars/main.yml | 5 + roles/openshift_node/tasks/main.yml | 32 +- roles/openshift_node/vars/main.yml | 2 + roles/openshift_register_nodes/defaults/main.yml | 3 - .../library/kubernetes_register_node.py | 63 +- roles/openshift_register_nodes/tasks/main.yml | 64 +- roles/openshift_register_nodes/vars/main.yml | 7 + roles/openshift_repos/README.md | 2 +- roles/openshift_repos/defaults/main.yaml | 5 - .../files/online/RPM-GPG-KEY-redhat-beta | 61 -- .../files/online/RPM-GPG-KEY-redhat-release | 63 -- .../files/online/epel7-kubernetes.repo | 6 - .../files/online/epel7-openshift.repo | 6 - .../files/online/gpg_keys/RPM-GPG-KEY-redhat-beta | 61 ++ .../online/gpg_keys/RPM-GPG-KEY-redhat-release | 63 ++ .../files/online/oso-rhui-rhel-7-extras.repo | 23 - .../files/online/oso-rhui-rhel-7-server.repo | 21 - .../files/online/repos/epel7-openshift.repo | 6 + .../files/online/repos/oso-rhui-rhel-7-extras.repo | 23 + .../files/online/repos/oso-rhui-rhel-7-server.repo | 21 + .../files/online/repos/rhel-7-libra-candidate.repo | 11 + .../files/online/rhel-7-libra-candidate.repo | 11 - .../repos/maxamillion-origin-next-epel-7.repo | 7 + roles/openshift_repos/tasks/main.yaml | 14 +- roles/openshift_repos/templates/yum_repo.j2 | 1 - roles/openshift_sdn_master/tasks/main.yml | 11 +- roles/openshift_sdn_node/tasks/main.yml | 11 +- .../library/os_firewall_manage_iptables.py | 3 +- 126 files changed, 3165 insertions(+), 2677 deletions(-) delete mode 100644 inventory/aws/ec2.ini delete mode 100755 inventory/aws/ec2.py delete mode 100644 inventory/aws/group_vars/all create mode 100644 inventory/aws/hosts/ec2.ini create mode 100755 inventory/aws/hosts/ec2.py create mode 100644 inventory/aws/hosts/hosts delete mode 100644 inventory/byo/group_vars/all delete mode 100755 inventory/gce/gce.py delete mode 100644 inventory/gce/group_vars/all create mode 100755 inventory/gce/hosts/gce.py create mode 100644 inventory/gce/hosts/hosts delete mode 100644 inventory/libvirt/group_vars/all delete mode 100644 inventory/libvirt/hosts create mode 100644 inventory/libvirt/hosts/hosts create mode 100644 inventory/libvirt/hosts/libvirt.ini create mode 100755 inventory/libvirt/hosts/libvirt_generic.py create mode 100644 playbooks/aws/openshift-cluster/config.yml delete mode 100644 playbooks/aws/openshift-cluster/launch_instances.yml create mode 100644 playbooks/aws/openshift-cluster/tasks/launch_instances.yml delete mode 100644 playbooks/aws/openshift-master/vars.yml delete mode 100644 playbooks/aws/openshift-node/vars.yml create mode 100644 playbooks/byo/openshift_facts.yml create mode 100644 playbooks/common/openshift-cluster/config.yml create mode 120000 playbooks/common/openshift-cluster/filter_plugins create mode 120000 playbooks/common/openshift-cluster/roles create mode 100644 playbooks/common/openshift-cluster/set_master_launch_facts_tasks.yml create mode 100644 playbooks/common/openshift-cluster/set_node_launch_facts_tasks.yml create mode 100644 playbooks/common/openshift-cluster/update_repos_and_packages.yml create mode 100644 playbooks/common/openshift-master/config.yml create mode 120000 playbooks/common/openshift-master/filter_plugins create mode 120000 playbooks/common/openshift-master/roles create mode 100644 playbooks/common/openshift-node/config.yml create mode 120000 playbooks/common/openshift-node/filter_plugins create mode 120000 playbooks/common/openshift-node/roles create mode 100644 playbooks/gce/openshift-cluster/config.yml delete mode 100644 playbooks/gce/openshift-cluster/launch_instances.yml create mode 100644 playbooks/gce/openshift-cluster/tasks/launch_instances.yml delete mode 100644 playbooks/gce/openshift-master/vars.yml delete mode 100644 playbooks/gce/openshift-node/vars.yml create mode 100644 playbooks/libvirt/openshift-cluster/config.yml delete mode 100644 playbooks/libvirt/openshift-cluster/launch_instances.yml create mode 100644 playbooks/libvirt/openshift-cluster/tasks/configure_libvirt.yml create mode 100644 playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_network.yml create mode 100644 playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_storage_pool.yml create mode 100644 playbooks/libvirt/openshift-cluster/tasks/launch_instances.yml create mode 100644 playbooks/libvirt/openshift-cluster/templates/domain.xml create mode 100644 playbooks/libvirt/openshift-cluster/templates/meta-data create mode 100644 playbooks/libvirt/openshift-cluster/templates/network.xml create mode 100644 playbooks/libvirt/openshift-cluster/templates/user-data create mode 100644 playbooks/libvirt/openshift-cluster/update.yml delete mode 100644 playbooks/libvirt/openshift-master/config.yml delete mode 120000 playbooks/libvirt/openshift-master/filter_plugins delete mode 120000 playbooks/libvirt/openshift-master/roles delete mode 100644 playbooks/libvirt/openshift-master/vars.yml delete mode 100644 playbooks/libvirt/openshift-node/config.yml delete mode 120000 playbooks/libvirt/openshift-node/filter_plugins delete mode 120000 playbooks/libvirt/openshift-node/roles delete mode 100644 playbooks/libvirt/openshift-node/vars.yml delete mode 100644 playbooks/libvirt/templates/domain.xml delete mode 100644 playbooks/libvirt/templates/meta-data delete mode 100644 playbooks/libvirt/templates/user-data create mode 100644 roles/openshift_master/vars/main.yml create mode 100644 roles/openshift_node/vars/main.yml create mode 100644 roles/openshift_register_nodes/vars/main.yml delete mode 100644 roles/openshift_repos/files/online/RPM-GPG-KEY-redhat-beta delete mode 100644 roles/openshift_repos/files/online/RPM-GPG-KEY-redhat-release delete mode 100644 roles/openshift_repos/files/online/epel7-kubernetes.repo delete mode 100644 roles/openshift_repos/files/online/epel7-openshift.repo create mode 100644 roles/openshift_repos/files/online/gpg_keys/RPM-GPG-KEY-redhat-beta create mode 100644 roles/openshift_repos/files/online/gpg_keys/RPM-GPG-KEY-redhat-release delete mode 100644 roles/openshift_repos/files/online/oso-rhui-rhel-7-extras.repo delete mode 100644 roles/openshift_repos/files/online/oso-rhui-rhel-7-server.repo create mode 100644 roles/openshift_repos/files/online/repos/epel7-openshift.repo create mode 100644 roles/openshift_repos/files/online/repos/oso-rhui-rhel-7-extras.repo create mode 100644 roles/openshift_repos/files/online/repos/oso-rhui-rhel-7-server.repo create mode 100644 roles/openshift_repos/files/online/repos/rhel-7-libra-candidate.repo delete mode 100644 roles/openshift_repos/files/online/rhel-7-libra-candidate.repo create mode 100644 roles/openshift_repos/files/origin/repos/maxamillion-origin-next-epel-7.repo diff --git a/README_OSE.md b/README_OSE.md index 6ebdb7f99..6d4a9ba92 100644 --- a/README_OSE.md +++ b/README_OSE.md @@ -7,15 +7,17 @@ * [Creating the default variables for the hosts and host groups](#creating-the-default-variables-for-the-hosts-and-host-groups) * [Running the ansible playbooks](#running-the-ansible-playbooks) * [Post-ansible steps](#post-ansible-steps) +* [Overriding detected ip addresses and hostnames](#overriding-detected-ip-addresses-and-hostnames) ## Requirements * ansible - * Tested using ansible-1.8.2-1.fc20.noarch, but should work with version 1.8+ + * Tested using ansible-1.8.4-1.fc20.noarch, but should work with version 1.8+ + * There is currently a known issue with ansible-1.9.0, you can downgrade to 1.8.4 on Fedora by installing one of the bulids from Koji: http://koji.fedoraproject.org/koji/packageinfo?packageID=13842 * Available in Fedora channels * Available for EL with EPEL and Optional channel * One or more RHEL 7.1 VMs -* ssh key based auth for the root user needs to be pre-configured from the host - running ansible to the remote hosts +* Either ssh key based auth for the root user or ssh key based auth for a user + with sudo access (no password) * A checkout of openshift-ansible from https://github.com/openshift/openshift-ansible/ ```sh @@ -48,9 +50,6 @@ subscription-manager repos \ ``` * Configuration of router is not automated yet * Configuration of docker-registry is not automated yet -* End-to-end testing has not been completed yet using this module -* root user is used for all ansible actions; eventually we will support using - a non-root user with sudo. ## Configuring the host inventory [Ansible docs](http://docs.ansible.com/intro_inventory.html) @@ -64,6 +63,38 @@ option to ansible-playbook. ```ini # This is an example of a bring your own (byo) host inventory +# Create an OSEv3 group that contains the maters and nodes groups +[OSEv3:children] +masters +nodes + +# Set variables common for all OSEv3 hosts +[OSEv3:vars] +# SSH user, this user should allow ssh based auth without requiring a password +ansible_ssh_user=root + +# If ansible_ssh_user is not root, ansible_sudo must be set to true +#ansible_sudo=true + +# To deploy origin, change deployment_type to origin +deployment_type=enterprise + +# Pre-release registry URL +openshift_registry_url=docker-buildvm-rhose.usersys.redhat.com:5000/openshift3_beta/ose-${component}:${version} + +# Pre-release additional repo +openshift_additional_repos=[{'id': 'ose-devel', 'name': 'ose-devel', +'baseurl': +'http://buildvm-devops.usersys.redhat.com/puddle/build/OpenShiftEnterprise/3.0/latest/RH7-RHOSE-3.0/$basearch/os', +'enabled': 1, 'gpgcheck': 0}] + +# Origin copr repo +#openshift_additional_repos=[{'id': 'openshift-origin-copr', 'name': +'OpenShift Origin COPR', 'baseurl': +'https://copr-be.cloud.fedoraproject.org/results/maxamillion/origin-next/epel-7-$basearch/', +'enabled': 1, 'gpgcheck': 1, gpgkey: +'https://copr-be.cloud.fedoraproject.org/results/maxamillion/origin-next/pubkey.gpg'}] + # host group for masters [masters] ose3-master.example.com @@ -76,51 +107,13 @@ ose3-node[1:2].example.com The hostnames above should resolve both from the hosts themselves and the host where ansible is running (if different). -## Creating the default variables for the hosts and host groups -[Ansible docs](http://docs.ansible.com/intro_inventory.html#id9) - -#### Group vars for all hosts -/etc/ansible/group_vars/all: -```yaml ---- -# Assume that we want to use the root as the ssh user for all hosts -ansible_ssh_user: root - -# Default debug level for all OpenShift hosts -openshift_debug_level: 4 - -# Set the OpenShift deployment type for all hosts -openshift_deployment_type: enterprise - -# Override the default registry for development -openshift_registry_url: docker-buildvm-rhose.usersys.redhat.com:5000/openshift3_beta/ose-${component}:${version} - -# To use the latest OpenShift Enterprise Errata puddle: -#openshift_additional_repos: -#- id: ose-devel -# name: ose-devel -# baseurl: http://buildvm-devops.usersys.redhat.com/puddle/build/OpenShiftEnterpriseErrata/3.0/latest/RH7-RHOSE-3.0/$basearch/os -# enabled: 1 -# gpgcheck: 0 -# To use the latest OpenShift Enterprise Whitelist puddle: -openshift_additional_repos: -- id: ose-devel - name: ose-devel - baseurl: http://buildvm-devops.usersys.redhat.com/puddle/build/OpenShiftEnterprise/3.0/latest/RH7-RHOSE-3.0/$basearch/os - enabled: 1 - gpgcheck: 0 - -``` - ## Running the ansible playbooks From the openshift-ansible checkout run: ```sh ansible-playbook playbooks/byo/config.yml ``` -**Note:** this assumes that the host inventory is /etc/ansible/hosts and the -group_vars are defined in /etc/ansible/group_vars, if using a different -inventory file (and a group_vars directory that is in the same directory as -the directory as the inventory) use the -i option for ansible-playbook. +**Note:** this assumes that the host inventory is /etc/ansible/hosts, if using a different +inventory file use the -i option for ansible-playbook. ## Post-ansible steps #### Create the default router @@ -140,3 +133,109 @@ openshift ex registry --create=true \ --images='docker-buildvm-rhose.usersys.redhat.com:5000/openshift3_beta/ose-${component}:${version}' \ --mount-host=/var/lib/openshift/docker-registry ``` + +## Overriding detected ip addresses and hostnames +Some deployments will require that the user override the detected hostnames +and ip addresses for the hosts. To see what the default values will be you can +run the openshift_facts playbook: +```sh +ansible-playbook playbooks/byo/openshift_facts.yml +``` +The output will be similar to: +``` +ok: [10.3.9.45] => { + "result": { + "ansible_facts": { + "openshift": { + "common": { + "hostname": "jdetiber-osev3-ansible-005dcfa6-27c6-463d-9b95-ef059579befd.os1.phx2.redhat.com", + "ip": "172.16.4.79", + "public_hostname": "jdetiber-osev3-ansible-005dcfa6-27c6-463d-9b95-ef059579befd.os1.phx2.redhat.com", + "public_ip": "10.3.9.45", + "use_openshift_sdn": true + }, + "provider": { + ... ... + } + } + }, + "changed": false, + "invocation": { + "module_args": "", + "module_name": "openshift_facts" + } + } +} +ok: [10.3.9.42] => { + "result": { + "ansible_facts": { + "openshift": { + "common": { + "hostname": "jdetiber-osev3-ansible-c6ae8cdc-ba0b-4a81-bb37-14549893f9d3.os1.phx2.redhat.com", + "ip": "172.16.4.75", + "public_hostname": "jdetiber-osev3-ansible-c6ae8cdc-ba0b-4a81-bb37-14549893f9d3.os1.phx2.redhat.com", + "public_ip": "10.3.9.42", + "use_openshift_sdn": true + }, + "provider": { + ...... + } + } + }, + "changed": false, + "invocation": { + "module_args": "", + "module_name": "openshift_facts" + } + } +} +ok: [10.3.9.36] => { + "result": { + "ansible_facts": { + "openshift": { + "common": { + "hostname": "jdetiber-osev3-ansible-bc39a3d3-cdd7-42fe-9c12-9fac9b0ec320.os1.phx2.redhat.com", + "ip": "172.16.4.73", + "public_hostname": "jdetiber-osev3-ansible-bc39a3d3-cdd7-42fe-9c12-9fac9b0ec320.os1.phx2.redhat.com", + "public_ip": "10.3.9.36", + "use_openshift_sdn": true + }, + "provider": { + ...... + } + } + }, + "changed": false, + "invocation": { + "module_args": "", + "module_name": "openshift_facts" + } + } +} +``` +Now, we want to verify the detected common settings to verify that they are +what we expect them to be (if not, we can override them). + +* hostname + * Should resolve to the internal ip from the instances themselves. + * openshift_hostname will override. +* ip + * Should be the internal ip of the instance. + * openshift_ip will override. +* public hostname + * Should resolve to the external ip from hosts outside of the cloud + * provider openshift_public_hostname will override. +* public_ip + * Should be the externally accessible ip associated with the instance + * openshift_public_ip will override +* use_openshift_sdn + * Should be true unless the cloud is GCE. + * openshift_use_openshift_sdn overrides + +To override the the defaults, you can set the variables in your inventory: +``` +...snip... +[masters] +ose3-master.example.com openshift_ip=1.1.1.1 openshift_hostname=ose3-master.example.com openshift_public_ip=2.2.2.2 openshift_public_hostname=ose3-master.public.example.com +...snip... +``` diff --git a/README_libvirt.md b/README_libvirt.md index fd2eb57f6..bcbaf4bd5 100644 --- a/README_libvirt.md +++ b/README_libvirt.md @@ -1,4 +1,3 @@ - LIBVIRT Setup instructions ========================== @@ -9,19 +8,21 @@ This makes `libvirt` useful to develop, test and debug Openshift and openshift-a 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² +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² +8. Configure dns resolution on the host³ #### ¹ 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 ``` @@ -67,12 +68,7 @@ If your `$HOME` is world readable, everything is fine. If your `$HOME` is privat 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. +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: @@ -80,13 +76,55 @@ On Arch: setfacl -m g:kvm:--x ~ ``` -Test the setup +#### ³ Enabling DNS resolution to your guest VMs with NetworkManager + +- Verify NetworkManager is configured to use dnsmasq: + +```sh +$ sudo vi /etc/NetworkManager/NetworkManager.conf +[main] +dns=dnsmasq +``` + +- Configure dnsmasq to use the Virtual Network router for example.com: + +```sh +sudo vi /etc/NetworkManager/dnsmasq.d/libvirt_dnsmasq.conf server=/example.com/192.168.55.1 +``` + +Test The Setup -------------- +1. cd openshift-ansible/ +2. Try to list all instances (Passing an empty string as the cluster_id argument will result in all libvirt instances being listed) + +``` + bin/cluster list libvirt '' ``` -cd openshift-ansible -bin/cluster create -m 1 -n 3 libvirt lenaic +Creating a cluster +------------------ + +1. To create a cluster with one master and two nodes -bin/cluster terminate libvirt lenaic +``` + bin/cluster create libvirt lenaic +``` + +Updating a cluster +------------------ + +1. To update the cluster + +``` + bin/cluster update libvirt lenaic +``` + +Terminating a cluster +--------------------- + +1. To terminate the cluster + +``` + bin/cluster terminate libvirt lenaic ``` diff --git a/bin/cluster b/bin/cluster index ca227721e..79f1f988f 100755 --- a/bin/cluster +++ b/bin/cluster @@ -22,13 +22,28 @@ class Cluster(object): '-o ControlPersist=600s ' ) + def get_deployment_type(self, args): + """ + Get the deployment_type based on the environment variables and the + command line arguments + :param args: command line arguments provided by the user + :return: string representing the deployment type + """ + deployment_type = 'origin' + if args.deployment_type: + deployment_type = args.deployment_type + elif 'OS_DEPLOYMENT_TYPE' in os.environ: + deployment_type = os.environ['OS_DEPLOYMENT_TYPE'] + return deployment_type + def create(self, args): """ Create an OpenShift cluster for given provider :param args: command line arguments provided by user :return: exit status from run command """ - env = {'cluster_id': args.cluster_id} + env = {'cluster_id': args.cluster_id, + 'deployment_type': self.get_deployment_type(args)} playbook = "playbooks/{}/openshift-cluster/launch.yml".format(args.provider) inventory = self.setup_provider(args.provider) @@ -43,7 +58,8 @@ class Cluster(object): :param args: command line arguments provided by user :return: exit status from run command """ - env = {'cluster_id': args.cluster_id} + env = {'cluster_id': args.cluster_id, + 'deployment_type': self.get_deployment_type(args)} playbook = "playbooks/{}/openshift-cluster/terminate.yml".format(args.provider) inventory = self.setup_provider(args.provider) @@ -55,19 +71,34 @@ class Cluster(object): :param args: command line arguments provided by user :return: exit status from run command """ - env = {'cluster_id': args.cluster_id} + env = {'cluster_id': args.cluster_id, + 'deployment_type': self.get_deployment_type(args)} playbook = "playbooks/{}/openshift-cluster/list.yml".format(args.provider) inventory = self.setup_provider(args.provider) return self.action(args, inventory, env, playbook) + def config(self, args): + """ + Configure or reconfigure OpenShift across clustered VMs + :param args: command line arguments provided by user + :return: exit status from run command + """ + env = {'cluster_id': args.cluster_id, + 'deployment_type': self.get_deployment_type(args)} + playbook = "playbooks/{}/openshift-cluster/config.yml".format(args.provider) + inventory = self.setup_provider(args.provider) + + return self.action(args, inventory, env, playbook) + def update(self, args): """ Update to latest OpenShift across clustered VMs :param args: command line arguments provided by user :return: exit status from run command """ - env = {'cluster_id': args.cluster_id} + env = {'cluster_id': args.cluster_id, + 'deployment_type': self.get_deployment_type(args)} playbook = "playbooks/{}/openshift-cluster/update.yml".format(args.provider) inventory = self.setup_provider(args.provider) @@ -81,19 +112,19 @@ class Cluster(object): """ config = ConfigParser.ConfigParser() if 'gce' == provider: - config.readfp(open('inventory/gce/gce.ini')) + config.readfp(open('inventory/gce/hosts/gce.ini')) for key in config.options('gce'): os.environ[key] = config.get('gce', key) - inventory = '-i inventory/gce/gce.py' + inventory = '-i inventory/gce/hosts' elif 'aws' == provider: - config.readfp(open('inventory/aws/ec2.ini')) + config.readfp(open('inventory/aws/hosts/ec2.ini')) for key in config.options('ec2'): os.environ[key] = config.get('ec2', key) - inventory = '-i inventory/aws/ec2.py' + inventory = '-i inventory/aws/hosts' elif 'libvirt' == provider: inventory = '-i inventory/libvirt/hosts' else: @@ -145,29 +176,49 @@ if __name__ == '__main__': 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('-v', '--verbose', action='count', + help='Multiple -v options increase the verbosity') parser.add_argument('--version', action='version', version='%(prog)s 0.2') meta_parser = argparse.ArgumentParser(add_help=False) meta_parser.add_argument('provider', choices=providers, help='provider') meta_parser.add_argument('cluster_id', help='prefix for cluster VM names') - - 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') + meta_parser.add_argument('-t', '--deployment-type', + choices=['origin', 'online', 'enterprise'], + help='Deployment type. (default: origin)') + + action_parser = parser.add_subparsers(dest='action', title='actions', + description='Choose from valid actions') + + create_parser = action_parser.add_parser('create', help='Create a cluster', + parents=[meta_parser]) + create_parser.add_argument('-m', '--masters', default=1, type=int, + help='number of masters to create in cluster') + create_parser.add_argument('-n', '--nodes', default=2, type=int, + help='number of nodes to create in cluster') create_parser.set_defaults(func=cluster.create) - 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') + config_parser = action_parser.add_parser('config', + help='Configure or reconfigure a cluster', + parents=[meta_parser]) + config_parser.set_defaults(func=cluster.config) + + terminate_parser = action_parser.add_parser('terminate', + help='Destroy a cluster', + parents=[meta_parser]) + terminate_parser.add_argument('-f', '--force', action='store_true', + help='Destroy cluster without confirmation') terminate_parser.set_defaults(func=cluster.terminate) - update_parser = action_parser.add_parser('update', help='Update OpenShift across cluster', parents=[meta_parser]) - update_parser.add_argument('-f', '--force', action='store_true', help='Update cluster without confirmation') + update_parser = 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 = action_parser.add_parser('list', help='List VMs in cluster', + parents=[meta_parser]) list_parser.set_defaults(func=cluster.list) args = parser.parse_args() diff --git a/filter_plugins/oo_filters.py b/filter_plugins/oo_filters.py index 1cf02218c..cf30cde9a 100644 --- a/filter_plugins/oo_filters.py +++ b/filter_plugins/oo_filters.py @@ -5,6 +5,7 @@ from ansible import errors, runner import json import pdb +import re def oo_pdb(arg): ''' This pops you into a pdb instance where arg is the data passed in from the filter. @@ -101,6 +102,18 @@ def oo_prepend_strings_in_list(data, prepend): retval = [prepend + s for s in data] return retval +def oo_get_deployment_type_from_groups(data): + ''' This takes a list of groups and returns the associated + deployment-type + ''' + if not issubclass(type(data), list): + raise errors.AnsibleFilterError("|failed expects first param is a list") + regexp = re.compile('^tag_deployment-type[-_]') + matches = filter(regexp.match, data) + if len(matches) > 0: + return regexp.sub('', matches[0]) + return "Unknown" + class FilterModule (object): def filters(self): return { @@ -109,5 +122,6 @@ class FilterModule (object): "oo_flatten": oo_flatten, "oo_len": oo_len, "oo_pdb": oo_pdb, - "oo_prepend_strings_in_list": oo_prepend_strings_in_list + "oo_prepend_strings_in_list": oo_prepend_strings_in_list, + "oo_get_deployment_type_from_groups": oo_get_deployment_type_from_groups } diff --git a/inventory/aws/ec2.ini b/inventory/aws/ec2.ini deleted file mode 100644 index eaab0a410..000000000 --- a/inventory/aws/ec2.ini +++ /dev/null @@ -1,62 +0,0 @@ -# Ansible EC2 external inventory script settings -# - -[ec2] - -# to talk to a private eucalyptus instance uncomment these lines -# and edit edit eucalyptus_host to be the host name of your cloud controller -#eucalyptus = True -#eucalyptus_host = clc.cloud.domain.org - -# AWS regions to make calls to. Set this to 'all' to make request to all regions -# in AWS and merge the results together. Alternatively, set this to a comma -# separated list of regions. E.g. 'us-east-1,us-west-1,us-west-2' -regions = all -regions_exclude = us-gov-west-1,cn-north-1 - -# When generating inventory, Ansible needs to know how to address a server. -# Each EC2 instance has a lot of variables associated with it. Here is the list: -# http://docs.pythonboto.org/en/latest/ref/ec2.html#module-boto.ec2.instance -# Below are 2 variables that are used as the address of a server: -# - destination_variable -# - vpc_destination_variable - -# This is the normal destination variable to use. If you are running Ansible -# from outside EC2, then 'public_dns_name' makes the most sense. If you are -# running Ansible from within EC2, then perhaps you want to use the internal -# address, and should set this to 'private_dns_name'. -destination_variable = public_dns_name - -# For server inside a VPC, using DNS names may not make sense. When an instance -# has 'subnet_id' set, this variable is used. If the subnet is public, setting -# this to 'ip_address' will return the public IP address. For instances in a -# private subnet, this should be set to 'private_ip_address', and Ansible must -# be run from with EC2. -vpc_destination_variable = ip_address - -# To tag instances on EC2 with the resource records that point to them from -# Route53, uncomment and set 'route53' to True. -route53 = False - -# Additionally, you can specify the list of zones to exclude looking up in -# 'route53_excluded_zones' as a comma-separated list. -# route53_excluded_zones = samplezone1.com, samplezone2.com - -# API calls to EC2 are slow. For this reason, we cache the results of an API -# call. Set this to the path you want cache files to be written to. Two files -# will be written to this directory: -# - ansible-ec2.cache -# - ansible-ec2.index -cache_path = ~/.ansible/tmp - -# The number of seconds a cache file is considered valid. After this many -# seconds, a new API call will be made, and the cache file will be updated. -# To disable the cache, set this value to 0 -cache_max_age = 300 - -# These two settings allow flexible ansible host naming based on a format -# string and a comma-separated list of ec2 tags. The tags used must be -# present for all instances, or the code will fail. This overrides both -# destination_variable and vpc_destination_variable. -# destination_format = {0}.{1}.rhcloud.com -# destination_format_tags = Name,environment diff --git a/inventory/aws/ec2.py b/inventory/aws/ec2.py deleted file mode 100755 index f231ff4c2..000000000 --- a/inventory/aws/ec2.py +++ /dev/null @@ -1,798 +0,0 @@ -#!/usr/bin/env python2 - -''' -EC2 external inventory script -================================= - -Generates inventory that Ansible can understand by making API request to -AWS EC2 using the Boto library. - -NOTE: This script assumes Ansible is being executed where the environment -variables needed for Boto have already been set: - export AWS_ACCESS_KEY_ID='AK123' - export AWS_SECRET_ACCESS_KEY='abc123' - -This script also assumes there is an ec2.ini file alongside it. To specify a -different path to ec2.ini, define the EC2_INI_PATH environment variable: - - export EC2_INI_PATH=/path/to/my_ec2.ini - -If you're using eucalyptus you need to set the above variables and -you need to define: - - export EC2_URL=http://hostname_of_your_cc:port/services/Eucalyptus - -For more details, see: http://docs.pythonboto.org/en/latest/boto_config_tut.html - -When run against a specific host, this script returns the following variables: - - ec2_ami_launch_index - - ec2_architecture - - ec2_association - - ec2_attachTime - - ec2_attachment - - ec2_attachmentId - - ec2_client_token - - ec2_deleteOnTermination - - ec2_description - - ec2_deviceIndex - - ec2_dns_name - - ec2_eventsSet - - ec2_group_name - - ec2_hypervisor - - ec2_id - - ec2_image_id - - ec2_instanceState - - ec2_instance_type - - ec2_ipOwnerId - - ec2_ip_address - - ec2_item - - ec2_kernel - - ec2_key_name - - ec2_launch_time - - ec2_monitored - - ec2_monitoring - - ec2_networkInterfaceId - - ec2_ownerId - - ec2_persistent - - ec2_placement - - ec2_platform - - ec2_previous_state - - ec2_private_dns_name - - ec2_private_ip_address - - ec2_publicIp - - ec2_public_dns_name - - ec2_ramdisk - - ec2_reason - - ec2_region - - ec2_requester_id - - ec2_root_device_name - - ec2_root_device_type - - ec2_security_group_ids - - ec2_security_group_names - - ec2_shutdown_state - - ec2_sourceDestCheck - - ec2_spot_instance_request_id - - ec2_state - - ec2_state_code - - ec2_state_reason - - ec2_status - - ec2_subnet_id - - ec2_tenancy - - ec2_virtualization_type - - ec2_vpc_id - -These variables are pulled out of a boto.ec2.instance object. There is a lack of -consistency with variable spellings (camelCase and underscores) since this -just loops through all variables the object exposes. It is preferred to use the -ones with underscores when multiple exist. - -In addition, if an instance has AWS Tags associated with it, each tag is a new -variable named: - - ec2_tag_[Key] = [Value] - -Security groups are comma-separated in 'ec2_security_group_ids' and -'ec2_security_group_names'. -''' - -# (c) 2012, Peter Sankauskas -# -# This file is part of Ansible, -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see . - -###################################################################### - -import sys -import os -import argparse -import re -from time import time -import boto -from boto import ec2 -from boto import rds -from boto import route53 -import ConfigParser -from collections import defaultdict - -try: - import json -except ImportError: - import simplejson as json - - -class Ec2Inventory(object): - def _empty_inventory(self): - return {"_meta" : {"hostvars" : {}}} - - def __init__(self): - ''' Main execution path ''' - - # Inventory grouped by instance IDs, tags, security groups, regions, - # and availability zones - self.inventory = self._empty_inventory() - - # Index of hostname (address) to instance ID - self.index = {} - - # Read settings and parse CLI arguments - self.read_settings() - self.parse_cli_args() - - # Cache - if self.args.refresh_cache: - self.do_api_calls_update_cache() - elif not self.is_cache_valid(): - self.do_api_calls_update_cache() - - # Data to print - if self.args.host: - data_to_print = self.get_host_info() - - elif self.args.list: - # Display list of instances for inventory - if self.inventory == self._empty_inventory(): - data_to_print = self.get_inventory_from_cache() - else: - data_to_print = self.json_format_dict(self.inventory, True) - - print data_to_print - - - def is_cache_valid(self): - ''' Determines if the cache files have expired, or if it is still valid ''' - - if os.path.isfile(self.cache_path_cache): - mod_time = os.path.getmtime(self.cache_path_cache) - current_time = time() - if (mod_time + self.cache_max_age) > current_time: - if os.path.isfile(self.cache_path_index): - return True - - return False - - - def read_settings(self): - ''' Reads the settings from the ec2.ini file ''' - - config = ConfigParser.SafeConfigParser() - ec2_default_ini_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'ec2.ini') - ec2_ini_path = os.environ.get('EC2_INI_PATH', ec2_default_ini_path) - config.read(ec2_ini_path) - - # is eucalyptus? - self.eucalyptus_host = None - self.eucalyptus = False - if config.has_option('ec2', 'eucalyptus'): - self.eucalyptus = config.getboolean('ec2', 'eucalyptus') - if self.eucalyptus and config.has_option('ec2', 'eucalyptus_host'): - self.eucalyptus_host = config.get('ec2', 'eucalyptus_host') - - # Regions - self.regions = [] - configRegions = config.get('ec2', 'regions') - configRegions_exclude = config.get('ec2', 'regions_exclude') - if (configRegions == 'all'): - if self.eucalyptus_host: - self.regions.append(boto.connect_euca(host=self.eucalyptus_host).region.name) - else: - for regionInfo in ec2.regions(): - if regionInfo.name not in configRegions_exclude: - self.regions.append(regionInfo.name) - else: - self.regions = configRegions.split(",") - - # Destination addresses - self.destination_variable = config.get('ec2', 'destination_variable') - self.vpc_destination_variable = config.get('ec2', 'vpc_destination_variable') - - if config.has_option('ec2', 'destination_format') and \ - config.has_option('ec2', 'destination_format_tags'): - self.destination_format = config.get('ec2', 'destination_format') - self.destination_format_tags = config.get('ec2', 'destination_format_tags').split(',') - else: - self.destination_format = None - self.destination_format_tags = None - - # Route53 - self.route53_enabled = config.getboolean('ec2', 'route53') - self.route53_excluded_zones = [] - if config.has_option('ec2', 'route53_excluded_zones'): - self.route53_excluded_zones.extend( - config.get('ec2', 'route53_excluded_zones', '').split(',')) - - # Include RDS instances? - self.rds_enabled = True - if config.has_option('ec2', 'rds'): - self.rds_enabled = config.getboolean('ec2', 'rds') - - # Return all EC2 and RDS instances (if RDS is enabled) - if config.has_option('ec2', 'all_instances'): - self.all_instances = config.getboolean('ec2', 'all_instances') - else: - self.all_instances = False - if config.has_option('ec2', 'all_rds_instances') and self.rds_enabled: - self.all_rds_instances = config.getboolean('ec2', 'all_rds_instances') - else: - self.all_rds_instances = False - - # Cache related - cache_dir = os.path.expanduser(config.get('ec2', 'cache_path')) - if not os.path.exists(cache_dir): - os.makedirs(cache_dir) - - self.cache_path_cache = cache_dir + "/ansible-ec2.cache" - self.cache_path_index = cache_dir + "/ansible-ec2.index" - self.cache_max_age = config.getint('ec2', 'cache_max_age') - - # Configure nested groups instead of flat namespace. - if config.has_option('ec2', 'nested_groups'): - self.nested_groups = config.getboolean('ec2', 'nested_groups') - else: - self.nested_groups = False - - # Configure which groups should be created. - group_by_options = [ - 'group_by_instance_id', - 'group_by_region', - 'group_by_availability_zone', - 'group_by_ami_id', - 'group_by_instance_type', - 'group_by_key_pair', - 'group_by_vpc_id', - 'group_by_security_group', - 'group_by_tag_keys', - 'group_by_tag_none', - 'group_by_route53_names', - 'group_by_rds_engine', - 'group_by_rds_parameter_group', - ] - for option in group_by_options: - if config.has_option('ec2', option): - setattr(self, option, config.getboolean('ec2', option)) - else: - setattr(self, option, True) - - # Do we need to just include hosts that match a pattern? - try: - pattern_include = config.get('ec2', 'pattern_include') - if pattern_include and len(pattern_include) > 0: - self.pattern_include = re.compile(pattern_include) - else: - self.pattern_include = None - except ConfigParser.NoOptionError, e: - self.pattern_include = None - - # Do we need to exclude hosts that match a pattern? - try: - pattern_exclude = config.get('ec2', 'pattern_exclude'); - if pattern_exclude and len(pattern_exclude) > 0: - self.pattern_exclude = re.compile(pattern_exclude) - else: - self.pattern_exclude = None - except ConfigParser.NoOptionError, e: - self.pattern_exclude = None - - # Instance filters (see boto and EC2 API docs). Ignore invalid filters. - self.ec2_instance_filters = defaultdict(list) - if config.has_option('ec2', 'instance_filters'): - for instance_filter in config.get('ec2', 'instance_filters', '').split(','): - instance_filter = instance_filter.strip() - if not instance_filter or '=' not in instance_filter: - continue - filter_key, filter_value = [x.strip() for x in instance_filter.split('=', 1)] - if not filter_key: - continue - self.ec2_instance_filters[filter_key].append(filter_value) - - def parse_cli_args(self): - ''' Command line argument processing ''' - - parser = argparse.ArgumentParser(description='Produce an Ansible Inventory file based on EC2') - parser.add_argument('--list', action='store_true', default=True, - help='List instances (default: True)') - parser.add_argument('--host', action='store', - help='Get all the variables about a specific instance') - parser.add_argument('--refresh-cache', action='store_true', default=False, - help='Force refresh of cache by making API requests to EC2 (default: False - use cache files)') - self.args = parser.parse_args() - - - def do_api_calls_update_cache(self): - ''' Do API calls to each region, and save data in cache files ''' - - if self.route53_enabled: - self.get_route53_records() - - for region in self.regions: - self.get_instances_by_region(region) - if self.rds_enabled: - self.get_rds_instances_by_region(region) - - self.write_to_cache(self.inventory, self.cache_path_cache) - self.write_to_cache(self.index, self.cache_path_index) - - - def get_instances_by_region(self, region): - ''' Makes an AWS EC2 API call to the list of instances in a particular - region ''' - - try: - if self.eucalyptus: - conn = boto.connect_euca(host=self.eucalyptus_host) - conn.APIVersion = '2010-08-31' - else: - conn = ec2.connect_to_region(region) - - # connect_to_region will fail "silently" by returning None if the region name is wrong or not supported - if conn is None: - print("region name: %s likely not supported, or AWS is down. connection to region failed." % region) - sys.exit(1) - - reservations = [] - if self.ec2_instance_filters: - for filter_key, filter_values in self.ec2_instance_filters.iteritems(): - reservations.extend(conn.get_all_instances(filters = { filter_key : filter_values })) - else: - reservations = conn.get_all_instances() - - for reservation in reservations: - for instance in reservation.instances: - self.add_instance(instance, region) - - except boto.exception.BotoServerError, e: - if not self.eucalyptus: - print "Looks like AWS is down again:" - print e - sys.exit(1) - - def get_rds_instances_by_region(self, region): - ''' Makes an AWS API call to the list of RDS instances in a particular - region ''' - - try: - conn = rds.connect_to_region(region) - if conn: - instances = conn.get_all_dbinstances() - for instance in instances: - self.add_rds_instance(instance, region) - except boto.exception.BotoServerError, e: - if not e.reason == "Forbidden": - print "Looks like AWS RDS is down: " - print e - sys.exit(1) - - def get_instance(self, region, instance_id): - ''' Gets details about a specific instance ''' - if self.eucalyptus: - conn = boto.connect_euca(self.eucalyptus_host) - conn.APIVersion = '2010-08-31' - else: - conn = ec2.connect_to_region(region) - - # connect_to_region will fail "silently" by returning None if the region name is wrong or not supported - if conn is None: - print("region name: %s likely not supported, or AWS is down. connection to region failed." % region) - sys.exit(1) - - reservations = conn.get_all_instances([instance_id]) - for reservation in reservations: - for instance in reservation.instances: - return instance - - def add_instance(self, instance, region): - ''' Adds an instance to the inventory and index, as long as it is - addressable ''' - - # Only want running instances unless all_instances is True - if not self.all_instances and instance.state != 'running': - return - - # Select the best destination address - if self.destination_format and self.destination_format_tags: - dest = self.destination_format.format(*[ getattr(instance, 'tags').get(tag, 'nil') for tag in self.destination_format_tags ]) - elif instance.subnet_id: - dest = getattr(instance, self.vpc_destination_variable, None) - if dest is None: - dest = getattr(instance, 'tags').get(self.vpc_destination_variable, None) - else: - dest = getattr(instance, self.destination_variable, None) - if dest is None: - dest = getattr(instance, 'tags').get(self.destination_variable, None) - - if not dest: - # Skip instances we cannot address (e.g. private VPC subnet) - return - - # if we only want to include hosts that match a pattern, skip those that don't - if self.pattern_include and not self.pattern_include.match(dest): - return - - # if we need to exclude hosts that match a pattern, skip those - if self.pattern_exclude and self.pattern_exclude.match(dest): - return - - # Add to index - self.index[dest] = [region, instance.id] - - # Inventory: Group by instance ID (always a group of 1) - if self.group_by_instance_id: - self.inventory[instance.id] = [dest] - if self.nested_groups: - self.push_group(self.inventory, 'instances', instance.id) - - # Inventory: Group by region - if self.group_by_region: - self.push(self.inventory, region, dest) - if self.nested_groups: - self.push_group(self.inventory, 'regions', region) - - # Inventory: Group by availability zone - if self.group_by_availability_zone: - self.push(self.inventory, instance.placement, dest) - if self.nested_groups: - if self.group_by_region: - self.push_group(self.inventory, region, instance.placement) - self.push_group(self.inventory, 'zones', instance.placement) - - # Inventory: Group by Amazon Machine Image (AMI) ID - if self.group_by_ami_id: - ami_id = self.to_safe(instance.image_id) - self.push(self.inventory, ami_id, dest) - if self.nested_groups: - self.push_group(self.inventory, 'images', ami_id) - - # Inventory: Group by instance type - if self.group_by_instance_type: - type_name = self.to_safe('type_' + instance.instance_type) - self.push(self.inventory, type_name, dest) - if self.nested_groups: - self.push_group(self.inventory, 'types', type_name) - - # Inventory: Group by key pair - if self.group_by_key_pair and instance.key_name: - key_name = self.to_safe('key_' + instance.key_name) - self.push(self.inventory, key_name, dest) - if self.nested_groups: - self.push_group(self.inventory, 'keys', key_name) - - # Inventory: Group by VPC - if self.group_by_vpc_id and instance.vpc_id: - vpc_id_name = self.to_safe('vpc_id_' + instance.vpc_id) - self.push(self.inventory, vpc_id_name, dest) - if self.nested_groups: - self.push_group(self.inventory, 'vpcs', vpc_id_name) - - # Inventory: Group by security group - if self.group_by_security_group: - try: - for group in instance.groups: - key = self.to_safe("security_group_" + group.name) - self.push(self.inventory, key, dest) - if self.nested_groups: - self.push_group(self.inventory, 'security_groups', key) - except AttributeError: - print 'Package boto seems a bit older.' - print 'Please upgrade boto >= 2.3.0.' - sys.exit(1) - - # Inventory: Group by tag keys - if self.group_by_tag_keys: - for k, v in instance.tags.iteritems(): - key = self.to_safe("tag_" + k + "=" + v) - self.push(self.inventory, key, dest) - if self.nested_groups: - self.push_group(self.inventory, 'tags', self.to_safe("tag_" + k)) - self.push_group(self.inventory, self.to_safe("tag_" + k), key) - - # Inventory: Group by Route53 domain names if enabled - if self.route53_enabled and self.group_by_route53_names: - route53_names = self.get_instance_route53_names(instance) - for name in route53_names: - self.push(self.inventory, name, dest) - if self.nested_groups: - self.push_group(self.inventory, 'route53', name) - - # Global Tag: instances without tags - if self.group_by_tag_none and len(instance.tags) == 0: - self.push(self.inventory, 'tag_none', dest) - if self.nested_groups: - self.push_group(self.inventory, 'tags', 'tag_none') - - # Global Tag: tag all EC2 instances - self.push(self.inventory, 'ec2', dest) - - self.inventory["_meta"]["hostvars"][dest] = self.get_host_info_dict_from_instance(instance) - - - def add_rds_instance(self, instance, region): - ''' Adds an RDS instance to the inventory and index, as long as it is - addressable ''' - - # Only want available instances unless all_rds_instances is True - if not self.all_rds_instances and instance.status != 'available': - return - - # Select the best destination address - dest = instance.endpoint[0] - - if not dest: - # Skip instances we cannot address (e.g. private VPC subnet) - return - - # Add to index - self.index[dest] = [region, instance.id] - - # Inventory: Group by instance ID (always a group of 1) - if self.group_by_instance_id: - self.inventory[instance.id] = [dest] - if self.nested_groups: - self.push_group(self.inventory, 'instances', instance.id) - - # Inventory: Group by region - if self.group_by_region: - self.push(self.inventory, region, dest) - if self.nested_groups: - self.push_group(self.inventory, 'regions', region) - - # Inventory: Group by availability zone - if self.group_by_availability_zone: - self.push(self.inventory, instance.availability_zone, dest) - if self.nested_groups: - if self.group_by_region: - self.push_group(self.inventory, region, instance.availability_zone) - self.push_group(self.inventory, 'zones', instance.availability_zone) - - # Inventory: Group by instance type - if self.group_by_instance_type: - type_name = self.to_safe('type_' + instance.instance_class) - self.push(self.inventory, type_name, dest) - if self.nested_groups: - self.push_group(self.inventory, 'types', type_name) - - # Inventory: Group by VPC - if self.group_by_vpc_id and instance.subnet_group and instance.subnet_group.vpc_id: - vpc_id_name = self.to_safe('vpc_id_' + instance.subnet_group.vpc_id) - self.push(self.inventory, vpc_id_name, dest) - if self.nested_groups: - self.push_group(self.inventory, 'vpcs', vpc_id_name) - - # Inventory: Group by security group - if self.group_by_security_group: - try: - if instance.security_group: - key = self.to_safe("security_group_" + instance.security_group.name) - self.push(self.inventory, key, dest) - if self.nested_groups: - self.push_group(self.inventory, 'security_groups', key) - - except AttributeError: - print 'Package boto seems a bit older.' - print 'Please upgrade boto >= 2.3.0.' - sys.exit(1) - - # Inventory: Group by engine - if self.group_by_rds_engine: - self.push(self.inventory, self.to_safe("rds_" + instance.engine), dest) - if self.nested_groups: - self.push_group(self.inventory, 'rds_engines', self.to_safe("rds_" + instance.engine)) - - # Inventory: Group by parameter group - if self.group_by_rds_parameter_group: - self.push(self.inventory, self.to_safe("rds_parameter_group_" + instance.parameter_group.name), dest) - if self.nested_groups: - self.push_group(self.inventory, 'rds_parameter_groups', self.to_safe("rds_parameter_group_" + instance.parameter_group.name)) - - # Global Tag: all RDS instances - self.push(self.inventory, 'rds', dest) - - self.inventory["_meta"]["hostvars"][dest] = self.get_host_info_dict_from_instance(instance) - - - def get_route53_records(self): - ''' Get and store the map of resource records to domain names that - point to them. ''' - - r53_conn = route53.Route53Connection() - all_zones = r53_conn.get_zones() - - route53_zones = [ zone for zone in all_zones if zone.name[:-1] - not in self.route53_excluded_zones ] - - self.route53_records = {} - - for zone in route53_zones: - rrsets = r53_conn.get_all_rrsets(zone.id) - - for record_set in rrsets: - record_name = record_set.name - - if record_name.endswith('.'): - record_name = record_name[:-1] - - for resource in record_set.resource_records: - self.route53_records.setdefault(resource, set()) - self.route53_records[resource].add(record_name) - - - def get_instance_route53_names(self, instance): - ''' Check if an instance is referenced in the records we have from - Route53. If it is, return the list of domain names pointing to said - instance. If nothing points to it, return an empty list. ''' - - instance_attributes = [ 'public_dns_name', 'private_dns_name', - 'ip_address', 'private_ip_address' ] - - name_list = set() - - for attrib in instance_attributes: - try: - value = getattr(instance, attrib) - except AttributeError: - continue - - if value in self.route53_records: - name_list.update(self.route53_records[value]) - - return list(name_list) - - - def get_host_info_dict_from_instance(self, instance): - instance_vars = {} - for key in vars(instance): - value = getattr(instance, key) - key = self.to_safe('ec2_' + key) - - # Handle complex types - # state/previous_state changed to properties in boto in https://github.com/boto/boto/commit/a23c379837f698212252720d2af8dec0325c9518 - if key == 'ec2__state': - instance_vars['ec2_state'] = instance.state or '' - instance_vars['ec2_state_code'] = instance.state_code - elif key == 'ec2__previous_state': - instance_vars['ec2_previous_state'] = instance.previous_state or '' - instance_vars['ec2_previous_state_code'] = instance.previous_state_code - elif type(value) in [int, bool]: - instance_vars[key] = value - elif type(value) in [str, unicode]: - instance_vars[key] = value.strip() - elif type(value) == type(None): - instance_vars[key] = '' - elif key == 'ec2_region': - instance_vars[key] = value.name - elif key == 'ec2__placement': - instance_vars['ec2_placement'] = value.zone - elif key == 'ec2_tags': - for k, v in value.iteritems(): - key = self.to_safe('ec2_tag_' + k) - instance_vars[key] = v - elif key == 'ec2_groups': - group_ids = [] - group_names = [] - for group in value: - group_ids.append(group.id) - group_names.append(group.name) - instance_vars["ec2_security_group_ids"] = ','.join([str(i) for i in group_ids]) - instance_vars["ec2_security_group_names"] = ','.join([str(i) for i in group_names]) - else: - pass - # TODO Product codes if someone finds them useful - #print key - #print type(value) - #print value - - return instance_vars - - def get_host_info(self): - ''' Get variables about a specific host ''' - - if len(self.index) == 0: - # Need to load index from cache - self.load_index_from_cache() - - if not self.args.host in self.index: - # try updating the cache - self.do_api_calls_update_cache() - if not self.args.host in self.index: - # host might not exist anymore - return self.json_format_dict({}, True) - - (region, instance_id) = self.index[self.args.host] - - instance = self.get_instance(region, instance_id) - return self.json_format_dict(self.get_host_info_dict_from_instance(instance), True) - - def push(self, my_dict, key, element): - ''' Push an element onto an array that may not have been defined in - the dict ''' - group_info = my_dict.setdefault(key, []) - if isinstance(group_info, dict): - host_list = group_info.setdefault('hosts', []) - host_list.append(element) - else: - group_info.append(element) - - def push_group(self, my_dict, key, element): - ''' Push a group as a child of another group. ''' - parent_group = my_dict.setdefault(key, {}) - if not isinstance(parent_group, dict): - parent_group = my_dict[key] = {'hosts': parent_group} - child_groups = parent_group.setdefault('children', []) - if element not in child_groups: - child_groups.append(element) - - def get_inventory_from_cache(self): - ''' Reads the inventory from the cache file and returns it as a JSON - object ''' - - cache = open(self.cache_path_cache, 'r') - json_inventory = cache.read() - return json_inventory - - - def load_index_from_cache(self): - ''' Reads the index from the cache file sets self.index ''' - - cache = open(self.cache_path_index, 'r') - json_index = cache.read() - self.index = json.loads(json_index) - - - def write_to_cache(self, data, filename): - ''' Writes data in JSON format to a file ''' - - json_data = self.json_format_dict(data, True) - cache = open(filename, 'w') - cache.write(json_data) - cache.close() - - - def to_safe(self, word): - ''' Converts 'bad' characters in a string to underscores so they can be - used as Ansible groups ''' - - return re.sub("[^A-Za-z0-9\-]", "_", word) - - - def json_format_dict(self, data, pretty=False): - ''' Converts a dict to a JSON object and dumps it as a formatted - string ''' - - if pretty: - return json.dumps(data, sort_keys=True, indent=2) - else: - return json.dumps(data) - - -# Run the script -Ec2Inventory() - diff --git a/inventory/aws/group_vars/all b/inventory/aws/group_vars/all deleted file mode 100644 index b22da00de..000000000 --- a/inventory/aws/group_vars/all +++ /dev/null @@ -1,2 +0,0 @@ ---- -ansible_ssh_user: root diff --git a/inventory/aws/hosts/ec2.ini b/inventory/aws/hosts/ec2.ini new file mode 100644 index 000000000..eaab0a410 --- /dev/null +++ b/inventory/aws/hosts/ec2.ini @@ -0,0 +1,62 @@ +# Ansible EC2 external inventory script settings +# + +[ec2] + +# to talk to a private eucalyptus instance uncomment these lines +# and edit edit eucalyptus_host to be the host name of your cloud controller +#eucalyptus = True +#eucalyptus_host = clc.cloud.domain.org + +# AWS regions to make calls to. Set this to 'all' to make request to all regions +# in AWS and merge the results together. Alternatively, set this to a comma +# separated list of regions. E.g. 'us-east-1,us-west-1,us-west-2' +regions = all +regions_exclude = us-gov-west-1,cn-north-1 + +# When generating inventory, Ansible needs to know how to address a server. +# Each EC2 instance has a lot of variables associated with it. Here is the list: +# http://docs.pythonboto.org/en/latest/ref/ec2.html#module-boto.ec2.instance +# Below are 2 variables that are used as the address of a server: +# - destination_variable +# - vpc_destination_variable + +# This is the normal destination variable to use. If you are running Ansible +# from outside EC2, then 'public_dns_name' makes the most sense. If you are +# running Ansible from within EC2, then perhaps you want to use the internal +# address, and should set this to 'private_dns_name'. +destination_variable = public_dns_name + +# For server inside a VPC, using DNS names may not make sense. When an instance +# has 'subnet_id' set, this variable is used. If the subnet is public, setting +# this to 'ip_address' will return the public IP address. For instances in a +# private subnet, this should be set to 'private_ip_address', and Ansible must +# be run from with EC2. +vpc_destination_variable = ip_address + +# To tag instances on EC2 with the resource records that point to them from +# Route53, uncomment and set 'route53' to True. +route53 = False + +# Additionally, you can specify the list of zones to exclude looking up in +# 'route53_excluded_zones' as a comma-separated list. +# route53_excluded_zones = samplezone1.com, samplezone2.com + +# API calls to EC2 are slow. For this reason, we cache the results of an API +# call. Set this to the path you want cache files to be written to. Two files +# will be written to this directory: +# - ansible-ec2.cache +# - ansible-ec2.index +cache_path = ~/.ansible/tmp + +# The number of seconds a cache file is considered valid. After this many +# seconds, a new API call will be made, and the cache file will be updated. +# To disable the cache, set this value to 0 +cache_max_age = 300 + +# These two settings allow flexible ansible host naming based on a format +# string and a comma-separated list of ec2 tags. The tags used must be +# present for all instances, or the code will fail. This overrides both +# destination_variable and vpc_destination_variable. +# destination_format = {0}.{1}.rhcloud.com +# destination_format_tags = Name,environment diff --git a/inventory/aws/hosts/ec2.py b/inventory/aws/hosts/ec2.py new file mode 100755 index 000000000..f231ff4c2 --- /dev/null +++ b/inventory/aws/hosts/ec2.py @@ -0,0 +1,798 @@ +#!/usr/bin/env python2 + +''' +EC2 external inventory script +================================= + +Generates inventory that Ansible can understand by making API request to +AWS EC2 using the Boto library. + +NOTE: This script assumes Ansible is being executed where the environment +variables needed for Boto have already been set: + export AWS_ACCESS_KEY_ID='AK123' + export AWS_SECRET_ACCESS_KEY='abc123' + +This script also assumes there is an ec2.ini file alongside it. To specify a +different path to ec2.ini, define the EC2_INI_PATH environment variable: + + export EC2_INI_PATH=/path/to/my_ec2.ini + +If you're using eucalyptus you need to set the above variables and +you need to define: + + export EC2_URL=http://hostname_of_your_cc:port/services/Eucalyptus + +For more details, see: http://docs.pythonboto.org/en/latest/boto_config_tut.html + +When run against a specific host, this script returns the following variables: + - ec2_ami_launch_index + - ec2_architecture + - ec2_association + - ec2_attachTime + - ec2_attachment + - ec2_attachmentId + - ec2_client_token + - ec2_deleteOnTermination + - ec2_description + - ec2_deviceIndex + - ec2_dns_name + - ec2_eventsSet + - ec2_group_name + - ec2_hypervisor + - ec2_id + - ec2_image_id + - ec2_instanceState + - ec2_instance_type + - ec2_ipOwnerId + - ec2_ip_address + - ec2_item + - ec2_kernel + - ec2_key_name + - ec2_launch_time + - ec2_monitored + - ec2_monitoring + - ec2_networkInterfaceId + - ec2_ownerId + - ec2_persistent + - ec2_placement + - ec2_platform + - ec2_previous_state + - ec2_private_dns_name + - ec2_private_ip_address + - ec2_publicIp + - ec2_public_dns_name + - ec2_ramdisk + - ec2_reason + - ec2_region + - ec2_requester_id + - ec2_root_device_name + - ec2_root_device_type + - ec2_security_group_ids + - ec2_security_group_names + - ec2_shutdown_state + - ec2_sourceDestCheck + - ec2_spot_instance_request_id + - ec2_state + - ec2_state_code + - ec2_state_reason + - ec2_status + - ec2_subnet_id + - ec2_tenancy + - ec2_virtualization_type + - ec2_vpc_id + +These variables are pulled out of a boto.ec2.instance object. There is a lack of +consistency with variable spellings (camelCase and underscores) since this +just loops through all variables the object exposes. It is preferred to use the +ones with underscores when multiple exist. + +In addition, if an instance has AWS Tags associated with it, each tag is a new +variable named: + - ec2_tag_[Key] = [Value] + +Security groups are comma-separated in 'ec2_security_group_ids' and +'ec2_security_group_names'. +''' + +# (c) 2012, Peter Sankauskas +# +# This file is part of Ansible, +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +###################################################################### + +import sys +import os +import argparse +import re +from time import time +import boto +from boto import ec2 +from boto import rds +from boto import route53 +import ConfigParser +from collections import defaultdict + +try: + import json +except ImportError: + import simplejson as json + + +class Ec2Inventory(object): + def _empty_inventory(self): + return {"_meta" : {"hostvars" : {}}} + + def __init__(self): + ''' Main execution path ''' + + # Inventory grouped by instance IDs, tags, security groups, regions, + # and availability zones + self.inventory = self._empty_inventory() + + # Index of hostname (address) to instance ID + self.index = {} + + # Read settings and parse CLI arguments + self.read_settings() + self.parse_cli_args() + + # Cache + if self.args.refresh_cache: + self.do_api_calls_update_cache() + elif not self.is_cache_valid(): + self.do_api_calls_update_cache() + + # Data to print + if self.args.host: + data_to_print = self.get_host_info() + + elif self.args.list: + # Display list of instances for inventory + if self.inventory == self._empty_inventory(): + data_to_print = self.get_inventory_from_cache() + else: + data_to_print = self.json_format_dict(self.inventory, True) + + print data_to_print + + + def is_cache_valid(self): + ''' Determines if the cache files have expired, or if it is still valid ''' + + if os.path.isfile(self.cache_path_cache): + mod_time = os.path.getmtime(self.cache_path_cache) + current_time = time() + if (mod_time + self.cache_max_age) > current_time: + if os.path.isfile(self.cache_path_index): + return True + + return False + + + def read_settings(self): + ''' Reads the settings from the ec2.ini file ''' + + config = ConfigParser.SafeConfigParser() + ec2_default_ini_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'ec2.ini') + ec2_ini_path = os.environ.get('EC2_INI_PATH', ec2_default_ini_path) + config.read(ec2_ini_path) + + # is eucalyptus? + self.eucalyptus_host = None + self.eucalyptus = False + if config.has_option('ec2', 'eucalyptus'): + self.eucalyptus = config.getboolean('ec2', 'eucalyptus') + if self.eucalyptus and config.has_option('ec2', 'eucalyptus_host'): + self.eucalyptus_host = config.get('ec2', 'eucalyptus_host') + + # Regions + self.regions = [] + configRegions = config.get('ec2', 'regions') + configRegions_exclude = config.get('ec2', 'regions_exclude') + if (configRegions == 'all'): + if self.eucalyptus_host: + self.regions.append(boto.connect_euca(host=self.eucalyptus_host).region.name) + else: + for regionInfo in ec2.regions(): + if regionInfo.name not in configRegions_exclude: + self.regions.append(regionInfo.name) + else: + self.regions = configRegions.split(",") + + # Destination addresses + self.destination_variable = config.get('ec2', 'destination_variable') + self.vpc_destination_variable = config.get('ec2', 'vpc_destination_variable') + + if config.has_option('ec2', 'destination_format') and \ + config.has_option('ec2', 'destination_format_tags'): + self.destination_format = config.get('ec2', 'destination_format') + self.destination_format_tags = config.get('ec2', 'destination_format_tags').split(',') + else: + self.destination_format = None + self.destination_format_tags = None + + # Route53 + self.route53_enabled = config.getboolean('ec2', 'route53') + self.route53_excluded_zones = [] + if config.has_option('ec2', 'route53_excluded_zones'): + self.route53_excluded_zones.extend( + config.get('ec2', 'route53_excluded_zones', '').split(',')) + + # Include RDS instances? + self.rds_enabled = True + if config.has_option('ec2', 'rds'): + self.rds_enabled = config.getboolean('ec2', 'rds') + + # Return all EC2 and RDS instances (if RDS is enabled) + if config.has_option('ec2', 'all_instances'): + self.all_instances = config.getboolean('ec2', 'all_instances') + else: + self.all_instances = False + if config.has_option('ec2', 'all_rds_instances') and self.rds_enabled: + self.all_rds_instances = config.getboolean('ec2', 'all_rds_instances') + else: + self.all_rds_instances = False + + # Cache related + cache_dir = os.path.expanduser(config.get('ec2', 'cache_path')) + if not os.path.exists(cache_dir): + os.makedirs(cache_dir) + + self.cache_path_cache = cache_dir + "/ansible-ec2.cache" + self.cache_path_index = cache_dir + "/ansible-ec2.index" + self.cache_max_age = config.getint('ec2', 'cache_max_age') + + # Configure nested groups instead of flat namespace. + if config.has_option('ec2', 'nested_groups'): + self.nested_groups = config.getboolean('ec2', 'nested_groups') + else: + self.nested_groups = False + + # Configure which groups should be created. + group_by_options = [ + 'group_by_instance_id', + 'group_by_region', + 'group_by_availability_zone', + 'group_by_ami_id', + 'group_by_instance_type', + 'group_by_key_pair', + 'group_by_vpc_id', + 'group_by_security_group', + 'group_by_tag_keys', + 'group_by_tag_none', + 'group_by_route53_names', + 'group_by_rds_engine', + 'group_by_rds_parameter_group', + ] + for option in group_by_options: + if config.has_option('ec2', option): + setattr(self, option, config.getboolean('ec2', option)) + else: + setattr(self, option, True) + + # Do we need to just include hosts that match a pattern? + try: + pattern_include = config.get('ec2', 'pattern_include') + if pattern_include and len(pattern_include) > 0: + self.pattern_include = re.compile(pattern_include) + else: + self.pattern_include = None + except ConfigParser.NoOptionError, e: + self.pattern_include = None + + # Do we need to exclude hosts that match a pattern? + try: + pattern_exclude = config.get('ec2', 'pattern_exclude'); + if pattern_exclude and len(pattern_exclude) > 0: + self.pattern_exclude = re.compile(pattern_exclude) + else: + self.pattern_exclude = None + except ConfigParser.NoOptionError, e: + self.pattern_exclude = None + + # Instance filters (see boto and EC2 API docs). Ignore invalid filters. + self.ec2_instance_filters = defaultdict(list) + if config.has_option('ec2', 'instance_filters'): + for instance_filter in config.get('ec2', 'instance_filters', '').split(','): + instance_filter = instance_filter.strip() + if not instance_filter or '=' not in instance_filter: + continue + filter_key, filter_value = [x.strip() for x in instance_filter.split('=', 1)] + if not filter_key: + continue + self.ec2_instance_filters[filter_key].append(filter_value) + + def parse_cli_args(self): + ''' Command line argument processing ''' + + parser = argparse.ArgumentParser(description='Produce an Ansible Inventory file based on EC2') + parser.add_argument('--list', action='store_true', default=True, + help='List instances (default: True)') + parser.add_argument('--host', action='store', + help='Get all the variables about a specific instance') + parser.add_argument('--refresh-cache', action='store_true', default=False, + help='Force refresh of cache by making API requests to EC2 (default: False - use cache files)') + self.args = parser.parse_args() + + + def do_api_calls_update_cache(self): + ''' Do API calls to each region, and save data in cache files ''' + + if self.route53_enabled: + self.get_route53_records() + + for region in self.regions: + self.get_instances_by_region(region) + if self.rds_enabled: + self.get_rds_instances_by_region(region) + + self.write_to_cache(self.inventory, self.cache_path_cache) + self.write_to_cache(self.index, self.cache_path_index) + + + def get_instances_by_region(self, region): + ''' Makes an AWS EC2 API call to the list of instances in a particular + region ''' + + try: + if self.eucalyptus: + conn = boto.connect_euca(host=self.eucalyptus_host) + conn.APIVersion = '2010-08-31' + else: + conn = ec2.connect_to_region(region) + + # connect_to_region will fail "silently" by returning None if the region name is wrong or not supported + if conn is None: + print("region name: %s likely not supported, or AWS is down. connection to region failed." % region) + sys.exit(1) + + reservations = [] + if self.ec2_instance_filters: + for filter_key, filter_values in self.ec2_instance_filters.iteritems(): + reservations.extend(conn.get_all_instances(filters = { filter_key : filter_values })) + else: + reservations = conn.get_all_instances() + + for reservation in reservations: + for instance in reservation.instances: + self.add_instance(instance, region) + + except boto.exception.BotoServerError, e: + if not self.eucalyptus: + print "Looks like AWS is down again:" + print e + sys.exit(1) + + def get_rds_instances_by_region(self, region): + ''' Makes an AWS API call to the list of RDS instances in a particular + region ''' + + try: + conn = rds.connect_to_region(region) + if conn: + instances = conn.get_all_dbinstances() + for instance in instances: + self.add_rds_instance(instance, region) + except boto.exception.BotoServerError, e: + if not e.reason == "Forbidden": + print "Looks like AWS RDS is down: " + print e + sys.exit(1) + + def get_instance(self, region, instance_id): + ''' Gets details about a specific instance ''' + if self.eucalyptus: + conn = boto.connect_euca(self.eucalyptus_host) + conn.APIVersion = '2010-08-31' + else: + conn = ec2.connect_to_region(region) + + # connect_to_region will fail "silently" by returning None if the region name is wrong or not supported + if conn is None: + print("region name: %s likely not supported, or AWS is down. connection to region failed." % region) + sys.exit(1) + + reservations = conn.get_all_instances([instance_id]) + for reservation in reservations: + for instance in reservation.instances: + return instance + + def add_instance(self, instance, region): + ''' Adds an instance to the inventory and index, as long as it is + addressable ''' + + # Only want running instances unless all_instances is True + if not self.all_instances and instance.state != 'running': + return + + # Select the best destination address + if self.destination_format and self.destination_format_tags: + dest = self.destination_format.format(*[ getattr(instance, 'tags').get(tag, 'nil') for tag in self.destination_format_tags ]) + elif instance.subnet_id: + dest = getattr(instance, self.vpc_destination_variable, None) + if dest is None: + dest = getattr(instance, 'tags').get(self.vpc_destination_variable, None) + else: + dest = getattr(instance, self.destination_variable, None) + if dest is None: + dest = getattr(instance, 'tags').get(self.destination_variable, None) + + if not dest: + # Skip instances we cannot address (e.g. private VPC subnet) + return + + # if we only want to include hosts that match a pattern, skip those that don't + if self.pattern_include and not self.pattern_include.match(dest): + return + + # if we need to exclude hosts that match a pattern, skip those + if self.pattern_exclude and self.pattern_exclude.match(dest): + return + + # Add to index + self.index[dest] = [region, instance.id] + + # Inventory: Group by instance ID (always a group of 1) + if self.group_by_instance_id: + self.inventory[instance.id] = [dest] + if self.nested_groups: + self.push_group(self.inventory, 'instances', instance.id) + + # Inventory: Group by region + if self.group_by_region: + self.push(self.inventory, region, dest) + if self.nested_groups: + self.push_group(self.inventory, 'regions', region) + + # Inventory: Group by availability zone + if self.group_by_availability_zone: + self.push(self.inventory, instance.placement, dest) + if self.nested_groups: + if self.group_by_region: + self.push_group(self.inventory, region, instance.placement) + self.push_group(self.inventory, 'zones', instance.placement) + + # Inventory: Group by Amazon Machine Image (AMI) ID + if self.group_by_ami_id: + ami_id = self.to_safe(instance.image_id) + self.push(self.inventory, ami_id, dest) + if self.nested_groups: + self.push_group(self.inventory, 'images', ami_id) + + # Inventory: Group by instance type + if self.group_by_instance_type: + type_name = self.to_safe('type_' + instance.instance_type) + self.push(self.inventory, type_name, dest) + if self.nested_groups: + self.push_group(self.inventory, 'types', type_name) + + # Inventory: Group by key pair + if self.group_by_key_pair and instance.key_name: + key_name = self.to_safe('key_' + instance.key_name) + self.push(self.inventory, key_name, dest) + if self.nested_groups: + self.push_group(self.inventory, 'keys', key_name) + + # Inventory: Group by VPC + if self.group_by_vpc_id and instance.vpc_id: + vpc_id_name = self.to_safe('vpc_id_' + instance.vpc_id) + self.push(self.inventory, vpc_id_name, dest) + if self.nested_groups: + self.push_group(self.inventory, 'vpcs', vpc_id_name) + + # Inventory: Group by security group + if self.group_by_security_group: + try: + for group in instance.groups: + key = self.to_safe("security_group_" + group.name) + self.push(self.inventory, key, dest) + if self.nested_groups: + self.push_group(self.inventory, 'security_groups', key) + except AttributeError: + print 'Package boto seems a bit older.' + print 'Please upgrade boto >= 2.3.0.' + sys.exit(1) + + # Inventory: Group by tag keys + if self.group_by_tag_keys: + for k, v in instance.tags.iteritems(): + key = self.to_safe("tag_" + k + "=" + v) + self.push(self.inventory, key, dest) + if self.nested_groups: + self.push_group(self.inventory, 'tags', self.to_safe("tag_" + k)) + self.push_group(self.inventory, self.to_safe("tag_" + k), key) + + # Inventory: Group by Route53 domain names if enabled + if self.route53_enabled and self.group_by_route53_names: + route53_names = self.get_instance_route53_names(instance) + for name in route53_names: + self.push(self.inventory, name, dest) + if self.nested_groups: + self.push_group(self.inventory, 'route53', name) + + # Global Tag: instances without tags + if self.group_by_tag_none and len(instance.tags) == 0: + self.push(self.inventory, 'tag_none', dest) + if self.nested_groups: + self.push_group(self.inventory, 'tags', 'tag_none') + + # Global Tag: tag all EC2 instances + self.push(self.inventory, 'ec2', dest) + + self.inventory["_meta"]["hostvars"][dest] = self.get_host_info_dict_from_instance(instance) + + + def add_rds_instance(self, instance, region): + ''' Adds an RDS instance to the inventory and index, as long as it is + addressable ''' + + # Only want available instances unless all_rds_instances is True + if not self.all_rds_instances and instance.status != 'available': + return + + # Select the best destination address + dest = instance.endpoint[0] + + if not dest: + # Skip instances we cannot address (e.g. private VPC subnet) + return + + # Add to index + self.index[dest] = [region, instance.id] + + # Inventory: Group by instance ID (always a group of 1) + if self.group_by_instance_id: + self.inventory[instance.id] = [dest] + if self.nested_groups: + self.push_group(self.inventory, 'instances', instance.id) + + # Inventory: Group by region + if self.group_by_region: + self.push(self.inventory, region, dest) + if self.nested_groups: + self.push_group(self.inventory, 'regions', region) + + # Inventory: Group by availability zone + if self.group_by_availability_zone: + self.push(self.inventory, instance.availability_zone, dest) + if self.nested_groups: + if self.group_by_region: + self.push_group(self.inventory, region, instance.availability_zone) + self.push_group(self.inventory, 'zones', instance.availability_zone) + + # Inventory: Group by instance type + if self.group_by_instance_type: + type_name = self.to_safe('type_' + instance.instance_class) + self.push(self.inventory, type_name, dest) + if self.nested_groups: + self.push_group(self.inventory, 'types', type_name) + + # Inventory: Group by VPC + if self.group_by_vpc_id and instance.subnet_group and instance.subnet_group.vpc_id: + vpc_id_name = self.to_safe('vpc_id_' + instance.subnet_group.vpc_id) + self.push(self.inventory, vpc_id_name, dest) + if self.nested_groups: + self.push_group(self.inventory, 'vpcs', vpc_id_name) + + # Inventory: Group by security group + if self.group_by_security_group: + try: + if instance.security_group: + key = self.to_safe("security_group_" + instance.security_group.name) + self.push(self.inventory, key, dest) + if self.nested_groups: + self.push_group(self.inventory, 'security_groups', key) + + except AttributeError: + print 'Package boto seems a bit older.' + print 'Please upgrade boto >= 2.3.0.' + sys.exit(1) + + # Inventory: Group by engine + if self.group_by_rds_engine: + self.push(self.inventory, self.to_safe("rds_" + instance.engine), dest) + if self.nested_groups: + self.push_group(self.inventory, 'rds_engines', self.to_safe("rds_" + instance.engine)) + + # Inventory: Group by parameter group + if self.group_by_rds_parameter_group: + self.push(self.inventory, self.to_safe("rds_parameter_group_" + instance.parameter_group.name), dest) + if self.nested_groups: + self.push_group(self.inventory, 'rds_parameter_groups', self.to_safe("rds_parameter_group_" + instance.parameter_group.name)) + + # Global Tag: all RDS instances + self.push(self.inventory, 'rds', dest) + + self.inventory["_meta"]["hostvars"][dest] = self.get_host_info_dict_from_instance(instance) + + + def get_route53_records(self): + ''' Get and store the map of resource records to domain names that + point to them. ''' + + r53_conn = route53.Route53Connection() + all_zones = r53_conn.get_zones() + + route53_zones = [ zone for zone in all_zones if zone.name[:-1] + not in self.route53_excluded_zones ] + + self.route53_records = {} + + for zone in route53_zones: + rrsets = r53_conn.get_all_rrsets(zone.id) + + for record_set in rrsets: + record_name = record_set.name + + if record_name.endswith('.'): + record_name = record_name[:-1] + + for resource in record_set.resource_records: + self.route53_records.setdefault(resource, set()) + self.route53_records[resource].add(record_name) + + + def get_instance_route53_names(self, instance): + ''' Check if an instance is referenced in the records we have from + Route53. If it is, return the list of domain names pointing to said + instance. If nothing points to it, return an empty list. ''' + + instance_attributes = [ 'public_dns_name', 'private_dns_name', + 'ip_address', 'private_ip_address' ] + + name_list = set() + + for attrib in instance_attributes: + try: + value = getattr(instance, attrib) + except AttributeError: + continue + + if value in self.route53_records: + name_list.update(self.route53_records[value]) + + return list(name_list) + + + def get_host_info_dict_from_instance(self, instance): + instance_vars = {} + for key in vars(instance): + value = getattr(instance, key) + key = self.to_safe('ec2_' + key) + + # Handle complex types + # state/previous_state changed to properties in boto in https://github.com/boto/boto/commit/a23c379837f698212252720d2af8dec0325c9518 + if key == 'ec2__state': + instance_vars['ec2_state'] = instance.state or '' + instance_vars['ec2_state_code'] = instance.state_code + elif key == 'ec2__previous_state': + instance_vars['ec2_previous_state'] = instance.previous_state or '' + instance_vars['ec2_previous_state_code'] = instance.previous_state_code + elif type(value) in [int, bool]: + instance_vars[key] = value + elif type(value) in [str, unicode]: + instance_vars[key] = value.strip() + elif type(value) == type(None): + instance_vars[key] = '' + elif key == 'ec2_region': + instance_vars[key] = value.name + elif key == 'ec2__placement': + instance_vars['ec2_placement'] = value.zone + elif key == 'ec2_tags': + for k, v in value.iteritems(): + key = self.to_safe('ec2_tag_' + k) + instance_vars[key] = v + elif key == 'ec2_groups': + group_ids = [] + group_names = [] + for group in value: + group_ids.append(group.id) + group_names.append(group.name) + instance_vars["ec2_security_group_ids"] = ','.join([str(i) for i in group_ids]) + instance_vars["ec2_security_group_names"] = ','.join([str(i) for i in group_names]) + else: + pass + # TODO Product codes if someone finds them useful + #print key + #print type(value) + #print value + + return instance_vars + + def get_host_info(self): + ''' Get variables about a specific host ''' + + if len(self.index) == 0: + # Need to load index from cache + self.load_index_from_cache() + + if not self.args.host in self.index: + # try updating the cache + self.do_api_calls_update_cache() + if not self.args.host in self.index: + # host might not exist anymore + return self.json_format_dict({}, True) + + (region, instance_id) = self.index[self.args.host] + + instance = self.get_instance(region, instance_id) + return self.json_format_dict(self.get_host_info_dict_from_instance(instance), True) + + def push(self, my_dict, key, element): + ''' Push an element onto an array that may not have been defined in + the dict ''' + group_info = my_dict.setdefault(key, []) + if isinstance(group_info, dict): + host_list = group_info.setdefault('hosts', []) + host_list.append(element) + else: + group_info.append(element) + + def push_group(self, my_dict, key, element): + ''' Push a group as a child of another group. ''' + parent_group = my_dict.setdefault(key, {}) + if not isinstance(parent_group, dict): + parent_group = my_dict[key] = {'hosts': parent_group} + child_groups = parent_group.setdefault('children', []) + if element not in child_groups: + child_groups.append(element) + + def get_inventory_from_cache(self): + ''' Reads the inventory from the cache file and returns it as a JSON + object ''' + + cache = open(self.cache_path_cache, 'r') + json_inventory = cache.read() + return json_inventory + + + def load_index_from_cache(self): + ''' Reads the index from the cache file sets self.index ''' + + cache = open(self.cache_path_index, 'r') + json_index = cache.read() + self.index = json.loads(json_index) + + + def write_to_cache(self, data, filename): + ''' Writes data in JSON format to a file ''' + + json_data = self.json_format_dict(data, True) + cache = open(filename, 'w') + cache.write(json_data) + cache.close() + + + def to_safe(self, word): + ''' Converts 'bad' characters in a string to underscores so they can be + used as Ansible groups ''' + + return re.sub("[^A-Za-z0-9\-]", "_", word) + + + def json_format_dict(self, data, pretty=False): + ''' Converts a dict to a JSON object and dumps it as a formatted + string ''' + + if pretty: + return json.dumps(data, sort_keys=True, indent=2) + else: + return json.dumps(data) + + +# Run the script +Ec2Inventory() + diff --git a/inventory/aws/hosts/hosts b/inventory/aws/hosts/hosts new file mode 100644 index 000000000..6c590ac93 --- /dev/null +++ b/inventory/aws/hosts/hosts @@ -0,0 +1 @@ +localhost ansible_sudo=no ansible_python_interpreter=/usr/bin/python2 diff --git a/inventory/byo/group_vars/all b/inventory/byo/group_vars/all deleted file mode 100644 index d63e96668..000000000 --- a/inventory/byo/group_vars/all +++ /dev/null @@ -1,28 +0,0 @@ ---- -# lets assume that we want to use the root as the ssh user for all hosts -ansible_ssh_user: root - -# default debug level for all OpenShift hosts -openshift_debug_level: 4 - -# set the OpenShift deployment type for all hosts -openshift_deployment_type: enterprise - -# Override the default registry for development -openshift_registry_url: docker-buildvm-rhose.usersys.redhat.com:5000/openshift3_beta/ose-${component}:${version} - -# Use latest Errata puddle as an additional repo: -#openshift_additional_repos: -#- id: ose-devel -# name: ose-devel -# baseurl: http://buildvm-devops.usersys.redhat.com/puddle/build/OpenShiftEnterpriseErrata/3.0/latest/RH7-RHOSE-3.0/$basearch/os -# enabled: 1 -# gpgcheck: 0 - -# Use latest Whitelist puddle as an additional repo: -openshift_additional_repos: -- id: ose-devel - name: ose-devel - baseurl: http://buildvm-devops.usersys.redhat.com/puddle/build/OpenShiftEnterprise/3.0/latest/RH7-RHOSE-3.0/$basearch/os - enabled: 1 - gpgcheck: 0 diff --git a/inventory/byo/hosts b/inventory/byo/hosts index 2dd854778..e9af5e571 100644 --- a/inventory/byo/hosts +++ b/inventory/byo/hosts @@ -1,5 +1,30 @@ # This is an example of a bring your own (byo) host inventory +# Create an OSEv3 group that contains the maters and nodes groups +[OSEv3:children] +masters +nodes + +# Set variables common for all OSEv3 hosts +[OSEv3:vars] +# SSH user, this user should allow ssh based auth without requiring a password +ansible_ssh_user=root + +# If ansible_ssh_user is not root, ansible_sudo must be set to true +#ansible_sudo=true + +# To deploy origin, change deployment_type to origin +deployment_type=enterprise + +# Pre-release registry URL +openshift_registry_url=docker-buildvm-rhose.usersys.redhat.com:5000/openshift3_beta/ose-${component}:${version} + +# Pre-release additional repo +openshift_additional_repos=[{'id': 'ose-devel', 'name': 'ose-devel', 'baseurl': 'http://buildvm-devops.usersys.redhat.com/puddle/build/OpenShiftEnterprise/3.0/latest/RH7-RHOSE-3.0/$basearch/os', 'enabled': 1, 'gpgcheck': 0}] + +# Origin copr repo +#openshift_additional_repos=[{'id': 'openshift-origin-copr', 'name': 'OpenShift Origin COPR', 'baseurl': 'https://copr-be.cloud.fedoraproject.org/results/maxamillion/origin-next/epel-7-$basearch/', 'enabled': 1, 'gpgcheck': 1, gpgkey: 'https://copr-be.cloud.fedoraproject.org/results/maxamillion/origin-next/pubkey.gpg'}] + # host group for masters [masters] ose3-master-ansible.test.example.com @@ -7,4 +32,3 @@ ose3-master-ansible.test.example.com # host group for nodes [nodes] ose3-node[1:2]-ansible.test.example.com - diff --git a/inventory/gce/gce.py b/inventory/gce/gce.py deleted file mode 100755 index 3403f735e..000000000 --- a/inventory/gce/gce.py +++ /dev/null @@ -1,287 +0,0 @@ -#!/usr/bin/env python2 -# Copyright 2013 Google Inc. -# -# This file is part of Ansible -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see . - -''' -GCE external inventory script -================================= - -Generates inventory that Ansible can understand by making API requests -Google Compute Engine via the libcloud library. Full install/configuration -instructions for the gce* modules can be found in the comments of -ansible/test/gce_tests.py. - -When run against a specific host, this script returns the following variables -based on the data obtained from the libcloud Node object: - - gce_uuid - - gce_id - - gce_image - - gce_machine_type - - gce_private_ip - - gce_public_ip - - gce_name - - gce_description - - gce_status - - gce_zone - - gce_tags - - gce_metadata - - gce_network - -When run in --list mode, instances are grouped by the following categories: - - zone: - zone group name examples are us-central1-b, europe-west1-a, etc. - - instance tags: - An entry is created for each tag. For example, if you have two instances - with a common tag called 'foo', they will both be grouped together under - the 'tag_foo' name. - - network name: - the name of the network is appended to 'network_' (e.g. the 'default' - network will result in a group named 'network_default') - - machine type - types follow a pattern like n1-standard-4, g1-small, etc. - - running status: - group name prefixed with 'status_' (e.g. status_running, status_stopped,..) - - image: - when using an ephemeral/scratch disk, this will be set to the image name - used when creating the instance (e.g. debian-7-wheezy-v20130816). when - your instance was created with a root persistent disk it will be set to - 'persistent_disk' since there is no current way to determine the image. - -Examples: - Execute uname on all instances in the us-central1-a zone - $ ansible -i gce.py us-central1-a -m shell -a "/bin/uname -a" - - Use the GCE inventory script to print out instance specific information - $ plugins/inventory/gce.py --host my_instance - -Author: Eric Johnson -Version: 0.0.1 -''' - -USER_AGENT_PRODUCT="Ansible-gce_inventory_plugin" -USER_AGENT_VERSION="v1" - -import sys -import os -import argparse -import ConfigParser - -try: - import json -except ImportError: - import simplejson as json - -try: - from libcloud.compute.types import Provider - from libcloud.compute.providers import get_driver - _ = Provider.GCE -except: - print("GCE inventory script requires libcloud >= 0.13") - sys.exit(1) - - -class GceInventory(object): - def __init__(self): - # Read settings and parse CLI arguments - self.parse_cli_args() - self.driver = self.get_gce_driver() - - # Just display data for specific host - if self.args.host: - print self.json_format_dict(self.node_to_dict( - self.get_instance(self.args.host)), - pretty=self.args.pretty) - sys.exit(0) - - # Otherwise, assume user wants all instances grouped - print(self.json_format_dict(self.group_instances(), - pretty=self.args.pretty)) - sys.exit(0) - - def get_gce_driver(self): - """Determine the GCE authorization settings and return a - libcloud driver. - """ - gce_ini_default_path = os.path.join( - os.path.dirname(os.path.realpath(__file__)), "gce.ini") - gce_ini_path = os.environ.get('GCE_INI_PATH', gce_ini_default_path) - - # Create a ConfigParser. - # This provides empty defaults to each key, so that environment - # variable configuration (as opposed to INI configuration) is able - # to work. - config = ConfigParser.SafeConfigParser(defaults={ - 'gce_service_account_email_address': '', - 'gce_service_account_pem_file_path': '', - 'gce_project_id': '', - 'libcloud_secrets': '', - }) - if 'gce' not in config.sections(): - config.add_section('gce') - config.read(gce_ini_path) - - # Attempt to get GCE params from a configuration file, if one - # exists. - secrets_path = config.get('gce', 'libcloud_secrets') - secrets_found = False - try: - import secrets - args = list(getattr(secrets, 'GCE_PARAMS', [])) - kwargs = getattr(secrets, 'GCE_KEYWORD_PARAMS', {}) - secrets_found = True - except: - pass - - if not secrets_found and secrets_path: - if not secrets_path.endswith('secrets.py'): - err = "Must specify libcloud secrets file as " - err += "/absolute/path/to/secrets.py" - print(err) - sys.exit(1) - sys.path.append(os.path.dirname(secrets_path)) - try: - import secrets - args = list(getattr(secrets, 'GCE_PARAMS', [])) - kwargs = getattr(secrets, 'GCE_KEYWORD_PARAMS', {}) - secrets_found = True - except: - pass - if not secrets_found: - args = [ - config.get('gce','gce_service_account_email_address'), - config.get('gce','gce_service_account_pem_file_path') - ] - kwargs = {'project': config.get('gce', 'gce_project_id')} - - # If the appropriate environment variables are set, they override - # other configuration; process those into our args and kwargs. - args[0] = os.environ.get('GCE_EMAIL', args[0]) - args[1] = os.environ.get('GCE_PEM_FILE_PATH', args[1]) - kwargs['project'] = os.environ.get('GCE_PROJECT', kwargs['project']) - - # Retrieve and return the GCE driver. - gce = get_driver(Provider.GCE)(*args, **kwargs) - gce.connection.user_agent_append( - '%s/%s' % (USER_AGENT_PRODUCT, USER_AGENT_VERSION), - ) - return gce - - def parse_cli_args(self): - ''' Command line argument processing ''' - - parser = argparse.ArgumentParser( - description='Produce an Ansible Inventory file based on GCE') - parser.add_argument('--list', action='store_true', default=True, - help='List instances (default: True)') - parser.add_argument('--host', action='store', - help='Get all information about an instance') - parser.add_argument('--pretty', action='store_true', default=False, - help='Pretty format (default: False)') - self.args = parser.parse_args() - - - def node_to_dict(self, inst): - md = {} - - if inst is None: - return {} - - if inst.extra['metadata'].has_key('items'): - for entry in inst.extra['metadata']['items']: - md[entry['key']] = entry['value'] - - net = inst.extra['networkInterfaces'][0]['network'].split('/')[-1] - return { - 'gce_uuid': inst.uuid, - 'gce_id': inst.id, - 'gce_image': inst.image, - 'gce_machine_type': inst.size, - 'gce_private_ip': inst.private_ips[0], - 'gce_public_ip': inst.public_ips[0], - 'gce_name': inst.name, - 'gce_description': inst.extra['description'], - 'gce_status': inst.extra['status'], - 'gce_zone': inst.extra['zone'].name, - 'gce_tags': inst.extra['tags'], - 'gce_metadata': md, - 'gce_network': net, - # Hosts don't have a public name, so we add an IP - 'ansible_ssh_host': inst.public_ips[0] - } - - def get_instance(self, instance_name): - '''Gets details about a specific instance ''' - try: - return self.driver.ex_get_node(instance_name) - except Exception, e: - return None - - def group_instances(self): - '''Group all instances''' - groups = {} - meta = {} - meta["hostvars"] = {} - - for node in self.driver.list_nodes(): - name = node.name - - meta["hostvars"][name] = self.node_to_dict(node) - - zone = node.extra['zone'].name - if groups.has_key(zone): groups[zone].append(name) - else: groups[zone] = [name] - - tags = node.extra['tags'] - for t in tags: - tag = 'tag_%s' % t - if groups.has_key(tag): groups[tag].append(name) - else: groups[tag] = [name] - - net = node.extra['networkInterfaces'][0]['network'].split('/')[-1] - net = 'network_%s' % net - if groups.has_key(net): groups[net].append(name) - else: groups[net] = [name] - - machine_type = node.size - if groups.has_key(machine_type): groups[machine_type].append(name) - else: groups[machine_type] = [name] - - image = node.image and node.image or 'persistent_disk' - if groups.has_key(image): groups[image].append(name) - else: groups[image] = [name] - - status = node.extra['status'] - stat = 'status_%s' % status.lower() - if groups.has_key(stat): groups[stat].append(name) - else: groups[stat] = [name] - - groups["_meta"] = meta - - return groups - - def json_format_dict(self, data, pretty=False): - ''' Converts a dict to a JSON object and dumps it as a formatted - string ''' - - if pretty: - return json.dumps(data, sort_keys=True, indent=2) - else: - return json.dumps(data) - - -# Run the script -GceInventory() diff --git a/inventory/gce/group_vars/all b/inventory/gce/group_vars/all deleted file mode 100644 index b22da00de..000000000 --- a/inventory/gce/group_vars/all +++ /dev/null @@ -1,2 +0,0 @@ ---- -ansible_ssh_user: root diff --git a/inventory/gce/hosts/gce.py b/inventory/gce/hosts/gce.py new file mode 100755 index 000000000..3403f735e --- /dev/null +++ b/inventory/gce/hosts/gce.py @@ -0,0 +1,287 @@ +#!/usr/bin/env python2 +# Copyright 2013 Google Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +''' +GCE external inventory script +================================= + +Generates inventory that Ansible can understand by making API requests +Google Compute Engine via the libcloud library. Full install/configuration +instructions for the gce* modules can be found in the comments of +ansible/test/gce_tests.py. + +When run against a specific host, this script returns the following variables +based on the data obtained from the libcloud Node object: + - gce_uuid + - gce_id + - gce_image + - gce_machine_type + - gce_private_ip + - gce_public_ip + - gce_name + - gce_description + - gce_status + - gce_zone + - gce_tags + - gce_metadata + - gce_network + +When run in --list mode, instances are grouped by the following categories: + - zone: + zone group name examples are us-central1-b, europe-west1-a, etc. + - instance tags: + An entry is created for each tag. For example, if you have two instances + with a common tag called 'foo', they will both be grouped together under + the 'tag_foo' name. + - network name: + the name of the network is appended to 'network_' (e.g. the 'default' + network will result in a group named 'network_default') + - machine type + types follow a pattern like n1-standard-4, g1-small, etc. + - running status: + group name prefixed with 'status_' (e.g. status_running, status_stopped,..) + - image: + when using an ephemeral/scratch disk, this will be set to the image name + used when creating the instance (e.g. debian-7-wheezy-v20130816). when + your instance was created with a root persistent disk it will be set to + 'persistent_disk' since there is no current way to determine the image. + +Examples: + Execute uname on all instances in the us-central1-a zone + $ ansible -i gce.py us-central1-a -m shell -a "/bin/uname -a" + + Use the GCE inventory script to print out instance specific information + $ plugins/inventory/gce.py --host my_instance + +Author: Eric Johnson +Version: 0.0.1 +''' + +USER_AGENT_PRODUCT="Ansible-gce_inventory_plugin" +USER_AGENT_VERSION="v1" + +import sys +import os +import argparse +import ConfigParser + +try: + import json +except ImportError: + import simplejson as json + +try: + from libcloud.compute.types import Provider + from libcloud.compute.providers import get_driver + _ = Provider.GCE +except: + print("GCE inventory script requires libcloud >= 0.13") + sys.exit(1) + + +class GceInventory(object): + def __init__(self): + # Read settings and parse CLI arguments + self.parse_cli_args() + self.driver = self.get_gce_driver() + + # Just display data for specific host + if self.args.host: + print self.json_format_dict(self.node_to_dict( + self.get_instance(self.args.host)), + pretty=self.args.pretty) + sys.exit(0) + + # Otherwise, assume user wants all instances grouped + print(self.json_format_dict(self.group_instances(), + pretty=self.args.pretty)) + sys.exit(0) + + def get_gce_driver(self): + """Determine the GCE authorization settings and return a + libcloud driver. + """ + gce_ini_default_path = os.path.join( + os.path.dirname(os.path.realpath(__file__)), "gce.ini") + gce_ini_path = os.environ.get('GCE_INI_PATH', gce_ini_default_path) + + # Create a ConfigParser. + # This provides empty defaults to each key, so that environment + # variable configuration (as opposed to INI configuration) is able + # to work. + config = ConfigParser.SafeConfigParser(defaults={ + 'gce_service_account_email_address': '', + 'gce_service_account_pem_file_path': '', + 'gce_project_id': '', + 'libcloud_secrets': '', + }) + if 'gce' not in config.sections(): + config.add_section('gce') + config.read(gce_ini_path) + + # Attempt to get GCE params from a configuration file, if one + # exists. + secrets_path = config.get('gce', 'libcloud_secrets') + secrets_found = False + try: + import secrets + args = list(getattr(secrets, 'GCE_PARAMS', [])) + kwargs = getattr(secrets, 'GCE_KEYWORD_PARAMS', {}) + secrets_found = True + except: + pass + + if not secrets_found and secrets_path: + if not secrets_path.endswith('secrets.py'): + err = "Must specify libcloud secrets file as " + err += "/absolute/path/to/secrets.py" + print(err) + sys.exit(1) + sys.path.append(os.path.dirname(secrets_path)) + try: + import secrets + args = list(getattr(secrets, 'GCE_PARAMS', [])) + kwargs = getattr(secrets, 'GCE_KEYWORD_PARAMS', {}) + secrets_found = True + except: + pass + if not secrets_found: + args = [ + config.get('gce','gce_service_account_email_address'), + config.get('gce','gce_service_account_pem_file_path') + ] + kwargs = {'project': config.get('gce', 'gce_project_id')} + + # If the appropriate environment variables are set, they override + # other configuration; process those into our args and kwargs. + args[0] = os.environ.get('GCE_EMAIL', args[0]) + args[1] = os.environ.get('GCE_PEM_FILE_PATH', args[1]) + kwargs['project'] = os.environ.get('GCE_PROJECT', kwargs['project']) + + # Retrieve and return the GCE driver. + gce = get_driver(Provider.GCE)(*args, **kwargs) + gce.connection.user_agent_append( + '%s/%s' % (USER_AGENT_PRODUCT, USER_AGENT_VERSION), + ) + return gce + + def parse_cli_args(self): + ''' Command line argument processing ''' + + parser = argparse.ArgumentParser( + description='Produce an Ansible Inventory file based on GCE') + parser.add_argument('--list', action='store_true', default=True, + help='List instances (default: True)') + parser.add_argument('--host', action='store', + help='Get all information about an instance') + parser.add_argument('--pretty', action='store_true', default=False, + help='Pretty format (default: False)') + self.args = parser.parse_args() + + + def node_to_dict(self, inst): + md = {} + + if inst is None: + return {} + + if inst.extra['metadata'].has_key('items'): + for entry in inst.extra['metadata']['items']: + md[entry['key']] = entry['value'] + + net = inst.extra['networkInterfaces'][0]['network'].split('/')[-1] + return { + 'gce_uuid': inst.uuid, + 'gce_id': inst.id, + 'gce_image': inst.image, + 'gce_machine_type': inst.size, + 'gce_private_ip': inst.private_ips[0], + 'gce_public_ip': inst.public_ips[0], + 'gce_name': inst.name, + 'gce_description': inst.extra['description'], + 'gce_status': inst.extra['status'], + 'gce_zone': inst.extra['zone'].name, + 'gce_tags': inst.extra['tags'], + 'gce_metadata': md, + 'gce_network': net, + # Hosts don't have a public name, so we add an IP + 'ansible_ssh_host': inst.public_ips[0] + } + + def get_instance(self, instance_name): + '''Gets details about a specific instance ''' + try: + return self.driver.ex_get_node(instance_name) + except Exception, e: + return None + + def group_instances(self): + '''Group all instances''' + groups = {} + meta = {} + meta["hostvars"] = {} + + for node in self.driver.list_nodes(): + name = node.name + + meta["hostvars"][name] = self.node_to_dict(node) + + zone = node.extra['zone'].name + if groups.has_key(zone): groups[zone].append(name) + else: groups[zone] = [name] + + tags = node.extra['tags'] + for t in tags: + tag = 'tag_%s' % t + if groups.has_key(tag): groups[tag].append(name) + else: groups[tag] = [name] + + net = node.extra['networkInterfaces'][0]['network'].split('/')[-1] + net = 'network_%s' % net + if groups.has_key(net): groups[net].append(name) + else: groups[net] = [name] + + machine_type = node.size + if groups.has_key(machine_type): groups[machine_type].append(name) + else: groups[machine_type] = [name] + + image = node.image and node.image or 'persistent_disk' + if groups.has_key(image): groups[image].append(name) + else: groups[image] = [name] + + status = node.extra['status'] + stat = 'status_%s' % status.lower() + if groups.has_key(stat): groups[stat].append(name) + else: groups[stat] = [name] + + groups["_meta"] = meta + + return groups + + def json_format_dict(self, data, pretty=False): + ''' Converts a dict to a JSON object and dumps it as a formatted + string ''' + + if pretty: + return json.dumps(data, sort_keys=True, indent=2) + else: + return json.dumps(data) + + +# Run the script +GceInventory() diff --git a/inventory/gce/hosts/hosts b/inventory/gce/hosts/hosts new file mode 100644 index 000000000..6c590ac93 --- /dev/null +++ b/inventory/gce/hosts/hosts @@ -0,0 +1 @@ +localhost ansible_sudo=no ansible_python_interpreter=/usr/bin/python2 diff --git a/inventory/libvirt/group_vars/all b/inventory/libvirt/group_vars/all deleted file mode 100644 index b22da00de..000000000 --- a/inventory/libvirt/group_vars/all +++ /dev/null @@ -1,2 +0,0 @@ ---- -ansible_ssh_user: root diff --git a/inventory/libvirt/hosts b/inventory/libvirt/hosts deleted file mode 100644 index 6a818f268..000000000 --- a/inventory/libvirt/hosts +++ /dev/null @@ -1,2 +0,0 @@ -# Eventually we'll add the GCE, AWS, etc dynamic inventories, but for now... -localhost ansible_python_interpreter=/usr/bin/python2 diff --git a/inventory/libvirt/hosts/hosts b/inventory/libvirt/hosts/hosts new file mode 100644 index 000000000..9cdc31449 --- /dev/null +++ b/inventory/libvirt/hosts/hosts @@ -0,0 +1 @@ +localhost ansible_sudo=no ansible_python_interpreter=/usr/bin/python2 connection=local diff --git a/inventory/libvirt/hosts/libvirt.ini b/inventory/libvirt/hosts/libvirt.ini new file mode 100644 index 000000000..62ff204dd --- /dev/null +++ b/inventory/libvirt/hosts/libvirt.ini @@ -0,0 +1,20 @@ +# Ansible libvirt external inventory script settings +# + +[libvirt] + +uri = qemu:///system + +# API calls to libvirt can be slow. For this reason, we cache the results of an API +# call. Set this to the path you want cache files to be written to. Two files +# will be written to this directory: +# - ansible-libvirt.cache +# - ansible-libvirt.index +cache_path = /tmp + +# The number of seconds a cache file is considered valid. After this many +# seconds, a new API call will be made, and the cache file will be updated. +cache_max_age = 900 + + + diff --git a/inventory/libvirt/hosts/libvirt_generic.py b/inventory/libvirt/hosts/libvirt_generic.py new file mode 100755 index 000000000..0a98e2af3 --- /dev/null +++ b/inventory/libvirt/hosts/libvirt_generic.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python + +""" +libvirt external inventory script +================================= + +Ansible has a feature where instead of reading from /etc/ansible/hosts +as a text file, it can query external programs to obtain the list +of hosts, groups the hosts are in, and even variables to assign to each host. + +To use this, copy this file over /etc/ansible/hosts and chmod +x the file. +This, more or less, allows you to keep one central database containing +info about all of your managed instances. + +""" + +# (c) 2015, Jason DeTiberus +# +# This file is part of Ansible, +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +###################################################################### + +import argparse +import ConfigParser +import os +import re +import sys +from time import time +import libvirt +import xml.etree.ElementTree as ET + +try: + import json +except ImportError: + import simplejson as json + + +class LibvirtInventory(object): + + def __init__(self): + self.inventory = dict() # A list of groups and the hosts in that group + self.cache = dict() # Details about hosts in the inventory + + # Read settings and parse CLI arguments + self.read_settings() + self.parse_cli_args() + + if self.args.host: + print self.json_format_dict(self.get_host_info(), self.args.pretty) + elif self.args.list: + print self.json_format_dict(self.get_inventory(), self.args.pretty) + else: # default action with no options + print self.json_format_dict(self.get_inventory(), self.args.pretty) + + def read_settings(self): + config = ConfigParser.SafeConfigParser() + config.read( + os.path.dirname(os.path.realpath(__file__)) + '/libvirt.ini' + ) + self.libvirt_uri = config.get('libvirt', 'uri') + + def parse_cli_args(self): + parser = argparse.ArgumentParser( + description='Produce an Ansible Inventory file based on libvirt' + ) + parser.add_argument( + '--list', + action='store_true', + default=True, + help='List instances (default: True)' + ) + parser.add_argument( + '--host', + action='store', + help='Get all the variables about a specific instance' + ) + parser.add_argument( + '--pretty', + action='store_true', + default=False, + help='Pretty format (default: False)' + ) + self.args = parser.parse_args() + + def get_host_info(self): + inventory = self.get_inventory() + if self.args.host in inventory['_meta']['hostvars']: + return inventory['_meta']['hostvars'][self.args.host] + + def get_inventory(self): + inventory = dict(_meta=dict(hostvars=dict())) + + conn = libvirt.openReadOnly(self.libvirt_uri) + if conn is None: + print "Failed to open connection to %s" % libvirt_uri + sys.exit(1) + + domains = conn.listAllDomains() + if domains is None: + print "Failed to list domains for connection %s" % libvirt_uri + sys.exit(1) + + arp_entries = self.parse_arp_entries() + + for domain in domains: + hostvars = dict(libvirt_name=domain.name(), + libvirt_id=domain.ID(), + libvirt_uuid=domain.UUIDString()) + domain_name = domain.name() + + # TODO: add support for guests that are not in a running state + state, _ = domain.state() + # 2 is the state for a running guest + if state != 1: + continue + + hostvars['libvirt_status'] = 'running' + + root = ET.fromstring(domain.XMLDesc()) + ns = {'ansible': 'https://github.com/ansible/ansible'} + for tag_elem in root.findall('./metadata/ansible:tag', ns): + tag = tag_elem.text + self.push(inventory, "tag_%s" % tag, domain_name) + self.push(hostvars, 'libvirt_tags', tag) + + # TODO: support more than one network interface, also support + # interface types other than 'network' + interface = root.find("./devices/interface[@type='network']") + if interface is not None: + mac_elem = interface.find('mac') + if mac_elem is not None: + mac = mac_elem.get('address') + if mac in arp_entries: + ip_address = arp_entries[mac]['ip_address'] + hostvars['ansible_ssh_host'] = ip_address + hostvars['libvirt_ip_address'] = ip_address + + inventory['_meta']['hostvars'][domain_name] = hostvars + + return inventory + + def parse_arp_entries(self): + arp_entries = dict() + with open('/proc/net/arp', 'r') as f: + # throw away the header + f.readline() + + for line in f: + ip_address, _, _, mac, _, device = line.strip().split() + arp_entries[mac] = dict(ip_address=ip_address, device=device) + + return arp_entries + + def push(self, my_dict, key, element): + if key in my_dict: + my_dict[key].append(element) + else: + my_dict[key] = [element] + + def json_format_dict(self, data, pretty=False): + if pretty: + return json.dumps(data, sort_keys=True, indent=2) + else: + return json.dumps(data) + +LibvirtInventory() diff --git a/playbooks/aws/openshift-cluster/config.yml b/playbooks/aws/openshift-cluster/config.yml new file mode 100644 index 000000000..b8961704e --- /dev/null +++ b/playbooks/aws/openshift-cluster/config.yml @@ -0,0 +1,36 @@ +--- +- name: Populate oo_masters_to_config host group + hosts: localhost + gather_facts: no + vars_files: + - vars.yml + tasks: + - name: Evaluate oo_masters_to_config + add_host: + name: "{{ item }}" + groups: oo_masters_to_config + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + with_items: groups["tag_env-host-type_{{ cluster_id }}-openshift-master"] | default([]) + - name: Evaluate oo_nodes_to_config + add_host: + name: "{{ item }}" + groups: oo_nodes_to_config + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + with_items: groups["tag_env-host-type_{{ cluster_id }}-openshift-node"] | default([]) + - name: Evaluate oo_first_master + add_host: + name: "{{ groups['tag_env-host-type_' ~ cluster_id ~ '-openshift-master'][0] }}" + groups: oo_first_master + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + when: "'tag_env-host-type_{{ cluster_id }}-openshift-master' in groups" + +- include: ../../common/openshift-cluster/config.yml + vars: + openshift_cluster_id: "{{ cluster_id }}" + openshift_debug_level: 4 + openshift_deployment_type: "{{ deployment_type }}" + openshift_hostname: "{{ ec2_private_ip_address }}" + openshift_public_hostname: "{{ ec2_ip_address }}" diff --git a/playbooks/aws/openshift-cluster/launch.yml b/playbooks/aws/openshift-cluster/launch.yml index 3561c1803..e7125ea0c 100644 --- a/playbooks/aws/openshift-cluster/launch.yml +++ b/playbooks/aws/openshift-cluster/launch.yml @@ -4,59 +4,26 @@ connection: local gather_facts: no vars_files: - - vars.yml + - 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\"]" + - fail: + msg: Deployment type not supported for libvirt provider yet + when: deployment_type == 'enterprise' + + - include: ../../common/openshift-cluster/set_master_launch_facts_tasks.yml + - include: tasks/launch_instances.yml + vars: + instances: "{{ master_names }}" + cluster: "{{ cluster_id }}" + type: "{{ k8s_type }}" + + - include: ../../common/openshift-cluster/set_node_launch_facts_tasks.yml + - include: tasks/launch_instances.yml + vars: + instances: "{{ node_names }}" + cluster: "{{ cluster_id }}" + type: "{{ k8s_type }}" + +- include: update.yml - include: list.yml diff --git a/playbooks/aws/openshift-cluster/launch_instances.yml b/playbooks/aws/openshift-cluster/launch_instances.yml deleted file mode 100644 index 9d645fbe5..000000000 --- a/playbooks/aws/openshift-cluster/launch_instances.yml +++ /dev/null @@ -1,63 +0,0 @@ ---- -- 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) }}" - security_group: "{{ lookup('env', 'ec2_security_group')|default('public', 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: "{{ security_group }}" - 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 index 08e9e2df4..5c04bc320 100644 --- a/playbooks/aws/openshift-cluster/list.yml +++ b/playbooks/aws/openshift-cluster/list.yml @@ -2,16 +2,23 @@ - name: Generate oo_list_hosts group hosts: localhost gather_facts: no + vars_files: + - vars.yml 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']) + when: cluster_id == '' + - add_host: + name: "{{ item }}" + groups: oo_list_hosts + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + with_items: groups[scratch_group] | default([]) | 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}}" + - debug: + msg: "public ip:{{ hostvars[inventory_hostname].ec2_ip_address }} private ip:{{ hostvars[inventory_hostname].ec2_private_ip_address }} deployment-type: {{ hostvars[inventory_hostname].group_names | oo_get_deployment_type_from_groups }}" diff --git a/playbooks/aws/openshift-cluster/tasks/launch_instances.yml b/playbooks/aws/openshift-cluster/tasks/launch_instances.yml new file mode 100644 index 000000000..58b4082df --- /dev/null +++ b/playbooks/aws/openshift-cluster/tasks/launch_instances.yml @@ -0,0 +1,69 @@ +--- +# TODO: modify machine_image based on deployment_type +- set_fact: + machine_type: "{{ lookup('env', 'ec2_instance_type') | default('m3.large', true) }}" + machine_image: "{{ lookup('env', 'ec2_ami') | default(deployment_vars[deployment_type].image, true) }}" + machine_region: "{{ lookup('env', 'ec2_region') | default(deployment_vars[deployment_type].region, true) }}" + machine_keypair: "{{ lookup('env', 'ec2_keypair')|default('libra', true) }}" + created_by: "{{ lookup('env', 'LOGNAME')|default(cluster, true) }}" + security_group: "{{ lookup('env', 'ec2_security_group')|default('public', 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: "{{ security_group }}" + 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 }}" + deployment-type: "{{ deployment_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 }}, tag_deployment-type_{{ deployment_type }} + +- name: Add new instances groups and variables + add_host: + hostname: "{{ item.0 }}" + ansible_ssh_host: "{{ item.1.dns_name }}" + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + 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 user setup + command: "ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o ConnectTimeout=10 -o UserKnownHostsFile=/dev/null {{ hostvars[item.0].ansible_ssh_user }}@{{ item.1.dns_name }} echo {{ hostvars[item.0].ansible_ssh_user }} user is setup" + register: result + until: result.rc == 0 + retries: 20 + delay: 10 + with_together: + - instances + - ec2.instances diff --git a/playbooks/aws/openshift-cluster/terminate.yml b/playbooks/aws/openshift-cluster/terminate.yml index 39607633a..1d2b60594 100644 --- a/playbooks/aws/openshift-cluster/terminate.yml +++ b/playbooks/aws/openshift-cluster/terminate.yml @@ -1,14 +1,26 @@ --- - name: Terminate instance(s) hosts: localhost - + gather_facts: no vars_files: - - vars.yml + - vars.yml + tasks: + - set_fact: scratch_group=tag_env-host-type_{{ cluster_id }}-openshift-node + - add_host: + name: "{{ item }}" + groups: oo_nodes_to_terminate + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + with_items: groups[scratch_group] | default([]) | difference(['localhost']) + + - set_fact: scratch_group=tag_env-host-type_{{ cluster_id }}-openshift-master + - add_host: + name: "{{ item }}" + groups: oo_masters_to_terminate + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + with_items: groups[scratch_group] | default([]) | difference(['localhost']) - 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 index 90ecdc6ab..5e7ab4e58 100644 --- a/playbooks/aws/openshift-cluster/update.yml +++ b/playbooks/aws/openshift-cluster/update.yml @@ -1,13 +1,18 @@ --- -- hosts: "tag_env_{{ cluster_id }}" - roles: - - openshift_repos - - os_update_latest +- name: Populate oo_hosts_to_update group + hosts: localhost + gather_facts: no + vars_files: + - vars.yml + tasks: + - name: Evaluate oo_hosts_to_update + add_host: + name: "{{ item }}" + groups: oo_hosts_to_update + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + with_items: groups["tag_env-host-type_{{ cluster_id }}-openshift-master"] | union(groups["tag_env-host-type_{{ cluster_id }}-openshift-node"]) | default([]) -- include: ../openshift-master/config.yml - vars: - oo_host_group_exp: "groups[\"tag_env-host-type_{{ cluster_id }}-openshift-master\"]" +- include: ../../common/openshift-cluster/update_repos_and_packages.yml -- include: ../openshift-node/config.yml - vars: - oo_host_group_exp: "groups[\"tag_env-host-type_{{ cluster_id }}-openshift-node\"]" +- include: config.yml diff --git a/playbooks/aws/openshift-cluster/vars.yml b/playbooks/aws/openshift-cluster/vars.yml index ed97d539c..f0df3d6f5 100644 --- a/playbooks/aws/openshift-cluster/vars.yml +++ b/playbooks/aws/openshift-cluster/vars.yml @@ -1 +1,20 @@ --- +deployment_vars: + origin: + # fedora, since centos requires marketplace + image: ami-acd999c4 + region: us-east-1 + ssh_user: fedora + sudo: yes + online: + # private ami + image: ami-307b3658 + region: us-east-1 + ssh_user: root + sudo: no + enterprise: + # rhel-7.1, requires cloud access subscription + image: ami-10663b78 + region: us-east-1 + ssh_user: ec2-user + sudo: yes diff --git a/playbooks/aws/openshift-master/config.yml b/playbooks/aws/openshift-master/config.yml index 1c4060eee..37ab4fbe6 100644 --- a/playbooks/aws/openshift-master/config.yml +++ b/playbooks/aws/openshift-master/config.yml @@ -1,24 +1,19 @@ --- -- name: Populate oo_masters_to_config host group if needed +- name: Populate oo_masters_to_config host group 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: Evaluate oo_masters_to_config + add_host: + name: "{{ item }}" + groups: oo_masters_to_config + ansible_ssh_user: root + with_items: oo_host_group_exp | default([]) -- name: Configure instances - hosts: oo_masters_to_config +- include: ../../common/openshift-master/config.yml vars: + openshift_cluster_id: "{{ cluster_id }}" + openshift_debug_level: 4 + openshift_deployment_type: "{{ deployment_type }}" 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 - roles: - - 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 3d87879a0..6b3751682 100644 --- a/playbooks/aws/openshift-master/launch.yml +++ b/playbooks/aws/openshift-master/launch.yml @@ -4,14 +4,12 @@ connection: local gather_facts: no +# TODO: modify atomic_ami based on deployment_type vars: inst_region: us-east-1 atomic_ami: ami-86781fee user_data_file: user_data.txt - vars_files: - - vars.yml - tasks: - name: Launch instances ec2: @@ -40,7 +38,7 @@ Name: "{{ item.0 }}" - name: Add other tags to instances - ec2_tag: "resource={{ item.id }} region={{ inst_region }} state=present" + ec2_tag: resource={{ item.id }} region={{ inst_region }} state=present with_items: ec2.instances args: tags: "{{ oo_new_inst_tags }}" @@ -57,7 +55,7 @@ - ec2.instances - name: Wait for ssh - wait_for: "port=22 host={{ item.dns_name }}" + wait_for: port=22 host={{ item.dns_name }} with_items: ec2.instances - name: Wait for root user setup diff --git a/playbooks/aws/openshift-master/terminate.yml b/playbooks/aws/openshift-master/terminate.yml index fd15cf00f..a790336b1 100644 --- a/playbooks/aws/openshift-master/terminate.yml +++ b/playbooks/aws/openshift-master/terminate.yml @@ -1,15 +1,15 @@ --- -- name: Populate oo_masters_to_terminate host group if needed +- name: Populate oo_masters_to_terminate host group 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: Evaluate oo_masters_to_terminate + add_host: name={{ item }} groups=oo_masters_to_terminate + with_items: oo_host_group_exp | default([]) -- name: Gather facts for instances to terminate +- name: Gather dynamic inventory variables for hosts to terminate hosts: oo_masters_to_terminate + gather_facts: no - name: Terminate instances hosts: localhost @@ -27,11 +27,12 @@ ignore_errors: yes register: ec2_term with_items: host_vars + when: "'oo_masters_to_terminate' in groups" # 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\")" + when: "'oo_masters_to_terminate' in groups and item.failed and not item.msg | search(\"error: EC2ResponseError: 403 Forbidden\")" with_items: ec2_term.results - name: Stop instance if termination failed @@ -42,6 +43,7 @@ register: ec2_stop when: item.failed with_items: ec2_term.results + when: "'oo_masters_to_terminate' in groups" - name: Rename stopped instances ec2_tag: resource={{ item.item.item.ec2_id }} region={{ item.item.item.ec2_region }} state=present @@ -49,4 +51,5 @@ tags: Name: "{{ item.item.item.ec2_tag_Name }}-terminate" with_items: ec2_stop.results + when: "'oo_masters_to_terminate' in groups" diff --git a/playbooks/aws/openshift-master/vars.yml b/playbooks/aws/openshift-master/vars.yml deleted file mode 100644 index c196b2fca..000000000 --- a/playbooks/aws/openshift-master/vars.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -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 b08ed7571..fc9b397b4 100644 --- a/playbooks/aws/openshift-node/config.yml +++ b/playbooks/aws/openshift-node/config.yml @@ -1,107 +1,25 @@ --- -- name: Populate oo_nodes_to_config host group if needed +- name: Populate oo_nodes_to_config and oo_first_master host groups hosts: localhost gather_facts: no tasks: - - name: Evaluate oo_host_group_exp - 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: Evaluate oo_nodes_to_config + add_host: + name: "{{ item }}" + groups: oo_nodes_to_config + ansible_ssh_user: root + with_items: oo_host_group_exp | default([]) + - name: Evaluate oo_first_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 + ansible_ssh_user: root -- 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: "{{ 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 - vars_files: - - vars.yml +- include: ../../common/openshift-node/config.yml vars: + openshift_cluster_id: "{{ cluster_id }}" + openshift_debug_level: 4 + openshift_deployment_type: "{{ deployment_type }}" 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: - - 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 b7ef593e7..36aee14ff 100644 --- a/playbooks/aws/openshift-node/launch.yml +++ b/playbooks/aws/openshift-node/launch.yml @@ -4,14 +4,12 @@ connection: local gather_facts: no +# TODO: modify atomic_ami based on deployment_type vars: inst_region: us-east-1 atomic_ami: ami-86781fee user_data_file: user_data.txt - vars_files: - - vars.yml - tasks: - name: Launch instances ec2: @@ -33,7 +31,7 @@ with_items: ec2.instances - name: Add Name and environment tags to instances - ec2_tag: "resource={{ item.1.id }} region={{ inst_region }} state=present" + ec2_tag: resource={{ item.1.id }} region={{ inst_region }} state=present with_together: - oo_new_inst_names - ec2.instances @@ -42,7 +40,7 @@ Name: "{{ item.0 }}" - name: Add other tags to instances - ec2_tag: "resource={{ item.id }} region={{ inst_region }} state=present" + ec2_tag: resource={{ item.id }} region={{ inst_region }} state=present with_items: ec2.instances args: tags: "{{ oo_new_inst_tags }}" @@ -59,7 +57,7 @@ - ec2.instances - name: Wait for ssh - wait_for: "port=22 host={{ item.dns_name }}" + wait_for: port=22 host={{ item.dns_name }} with_items: ec2.instances - name: Wait for root user setup diff --git a/playbooks/aws/openshift-node/terminate.yml b/playbooks/aws/openshift-node/terminate.yml index 1c0c77eb7..40ae56f99 100644 --- a/playbooks/aws/openshift-node/terminate.yml +++ b/playbooks/aws/openshift-node/terminate.yml @@ -1,15 +1,15 @@ --- -- name: Populate oo_nodes_to_terminate host group if needed +- name: Populate oo_nodes_to_terminate host group 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: Evaluate oo_nodes_to_terminate + add_host: name={{ item }} groups=oo_nodes_to_terminate + with_items: oo_host_group_exp | default([]) -- name: Gather facts for instances to terminate +- name: Gather dynamic inventory variables for hosts to terminate hosts: oo_nodes_to_terminate + gather_facts: no - name: Terminate instances hosts: localhost @@ -27,11 +27,12 @@ ignore_errors: yes register: ec2_term with_items: host_vars + when: "'oo_nodes_to_terminate' in groups" # 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\")" + when: "'oo_nodes_to_terminate' in groups and item.failed and not item.msg | search(\"error: EC2ResponseError: 403 Forbidden\")" with_items: ec2_term.results - name: Stop instance if termination failed @@ -42,6 +43,7 @@ register: ec2_stop when: item.failed with_items: ec2_term.results + when: "'oo_nodes_to_terminate' in groups" - name: Rename stopped instances ec2_tag: resource={{ item.item.item.ec2_id }} region={{ item.item.item.ec2_region }} state=present @@ -49,4 +51,5 @@ tags: Name: "{{ item.item.item.ec2_tag_Name }}-terminate" with_items: ec2_stop.results + when: "'oo_nodes_to_terminate' in groups" diff --git a/playbooks/aws/openshift-node/vars.yml b/playbooks/aws/openshift-node/vars.yml deleted file mode 100644 index c196b2fca..000000000 --- a/playbooks/aws/openshift-node/vars.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -openshift_debug_level: 4 -openshift_cluster_id: "{{ cluster_id }}" diff --git a/playbooks/byo/openshift-master/config.yml b/playbooks/byo/openshift-master/config.yml index 706f9285c..f61d277c6 100644 --- a/playbooks/byo/openshift-master/config.yml +++ b/playbooks/byo/openshift-master/config.yml @@ -1,9 +1,15 @@ --- -- name: Gather facts for node hosts - hosts: nodes +- name: Populate oo_masters_to_config host group + hosts: localhost + gather_facts: no + tasks: + - add_host: + name: "{{ item }}" + groups: oo_masters_to_config + with_items: groups['masters'] -- name: Configure master instances - hosts: masters - roles: - - openshift_master - - openshift_sdn_master +- include: ../../common/openshift-master/config.yml + vars: + openshift_cluster_id: "{{ cluster_id | default('default') }}" + openshift_debug_level: 4 + openshift_deployment_type: "{{ deployment_type }}" diff --git a/playbooks/byo/openshift-node/config.yml b/playbooks/byo/openshift-node/config.yml index 69ad7a840..d569827b4 100644 --- a/playbooks/byo/openshift-node/config.yml +++ b/playbooks/byo/openshift-node/config.yml @@ -1,79 +1,21 @@ --- -- name: Gather facts for node hosts - hosts: nodes - roles: - - openshift_facts +- name: Populate oo_nodes_to_config and oo_first_master host groups + hosts: localhost + gather_facts: no 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: 'node' - local_facts: - hostname: "{{ openshift_hostname | default(None) }}" - 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: Evaluate oo_nodes_to_config + add_host: + name: "{{ item }}" + groups: oo_nodes_to_config + with_items: groups.nodes + - name: Evaluate oo_first_master + add_host: + name: "{{ groups.masters[0] }}" + groups: oo_first_master -- name: Register nodes - hosts: masters[0] +- include: ../../common/openshift-node/config.yml vars: - openshift_nodes: "{{ hostvars | oo_select_keys(groups['nodes']) }}" - 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 node instances - hosts: nodes - vars: - sync_tmpdir: "{{ hostvars[groups['masters'][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 }}" - openshift_sdn_master_url: http://{{ hostvars[groups['masters'][0]].openshift.common.hostname }}:4001 - 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 - - openshift_sdn_node + openshift_cluster_id: "{{ cluster_id | default('default') }}" + openshift_debug_level: 4 + openshift_deployment_type: "{{ deployment_type }}" diff --git a/playbooks/byo/openshift_facts.yml b/playbooks/byo/openshift_facts.yml new file mode 100644 index 000000000..cd282270f --- /dev/null +++ b/playbooks/byo/openshift_facts.yml @@ -0,0 +1,10 @@ +--- +- name: Gather OpenShift facts + hosts: all + gather_facts: no + roles: + - openshift_facts + tasks: + - openshift_facts: + register: result + - debug: var=result diff --git a/playbooks/common/openshift-cluster/config.yml b/playbooks/common/openshift-cluster/config.yml new file mode 100644 index 000000000..14ffa928f --- /dev/null +++ b/playbooks/common/openshift-cluster/config.yml @@ -0,0 +1,4 @@ +--- +- include: ../openshift-master/config.yml + +- include: ../openshift-node/config.yml diff --git a/playbooks/common/openshift-cluster/filter_plugins b/playbooks/common/openshift-cluster/filter_plugins new file mode 120000 index 000000000..99a95e4ca --- /dev/null +++ b/playbooks/common/openshift-cluster/filter_plugins @@ -0,0 +1 @@ +../../../filter_plugins \ No newline at end of file diff --git a/playbooks/common/openshift-cluster/roles b/playbooks/common/openshift-cluster/roles new file mode 120000 index 000000000..20c4c58cf --- /dev/null +++ b/playbooks/common/openshift-cluster/roles @@ -0,0 +1 @@ +../../../roles \ No newline at end of file diff --git a/playbooks/common/openshift-cluster/set_master_launch_facts_tasks.yml b/playbooks/common/openshift-cluster/set_master_launch_facts_tasks.yml new file mode 100644 index 000000000..118727273 --- /dev/null +++ b/playbooks/common/openshift-cluster/set_master_launch_facts_tasks.yml @@ -0,0 +1,11 @@ +--- +- set_fact: k8s_type="master" + +- name: Generate master instance names(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') }}" diff --git a/playbooks/common/openshift-cluster/set_node_launch_facts_tasks.yml b/playbooks/common/openshift-cluster/set_node_launch_facts_tasks.yml new file mode 100644 index 000000000..162315d46 --- /dev/null +++ b/playbooks/common/openshift-cluster/set_node_launch_facts_tasks.yml @@ -0,0 +1,11 @@ +--- +- set_fact: k8s_type="node" + +- name: Generate node instance names(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') }}" diff --git a/playbooks/common/openshift-cluster/update_repos_and_packages.yml b/playbooks/common/openshift-cluster/update_repos_and_packages.yml new file mode 100644 index 000000000..e92c6f1ee --- /dev/null +++ b/playbooks/common/openshift-cluster/update_repos_and_packages.yml @@ -0,0 +1,7 @@ +--- +- hosts: oo_hosts_to_update + vars: + openshift_deployment_type: "{{ deployment_type }}" + roles: + - openshift_repos + - os_update_latest diff --git a/playbooks/common/openshift-master/config.yml b/playbooks/common/openshift-master/config.yml new file mode 100644 index 000000000..05822d118 --- /dev/null +++ b/playbooks/common/openshift-master/config.yml @@ -0,0 +1,19 @@ +--- +- name: Configure master instances + hosts: oo_masters_to_config + vars: + openshift_sdn_master_url: https://{{ openshift.common.hostname }}:4001 + roles: + - openshift_master + - { role: openshift_sdn_master, when: openshift.common.use_openshift_sdn | bool } + tasks: + - name: Create group for deployment type + group_by: key=oo_masters_deployment_type_{{ openshift.common.deployment_type }} + changed_when: False + +# Additional instance config for online deployments +- name: Additional instance config + hosts: oo_masters_deployment_type_online + roles: + - pods + - os_env_extras diff --git a/playbooks/common/openshift-master/filter_plugins b/playbooks/common/openshift-master/filter_plugins new file mode 120000 index 000000000..99a95e4ca --- /dev/null +++ b/playbooks/common/openshift-master/filter_plugins @@ -0,0 +1 @@ +../../../filter_plugins \ No newline at end of file diff --git a/playbooks/common/openshift-master/roles b/playbooks/common/openshift-master/roles new file mode 120000 index 000000000..e2b799b9d --- /dev/null +++ b/playbooks/common/openshift-master/roles @@ -0,0 +1 @@ +../../../roles/ \ No newline at end of file diff --git a/playbooks/common/openshift-node/config.yml b/playbooks/common/openshift-node/config.yml new file mode 100644 index 000000000..c82d69c28 --- /dev/null +++ b/playbooks/common/openshift-node/config.yml @@ -0,0 +1,121 @@ +--- +- name: Gather and set facts for node hosts + 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: "{{ openshift_hostname | default(None) }}" + public_hostname: "{{ openshift_public_hostname | default(None) }}" + - role: node + local_facts: + external_id: "{{ openshift_node_external_id | default(None) }}" + resources_cpu: "{{ openshift_node_resources_cpu | default(None) }}" + resources_memory: "{{ openshift_node_resources_memory | default(None) }}" + pod_cidr: "{{ openshift_node_pod_cidr | default(None) }}" + labels: "{{ openshift_node_labels | default(None) }}" + annotations: "{{ openshift_node_annotations | default(None) }}" + deployment_type: "{{ openshift_deployment_type }}" + + +- name: Create temp directory for syncing certs + hosts: localhost + gather_facts: no + tasks: + - name: Create local temp directory for syncing certs + local_action: command mktemp -d /tmp/openshift-ansible-XXXXXXX + register: mktemp + changed_when: False + + +- name: Register nodes + hosts: oo_first_master + vars: + openshift_nodes: "{{ hostvars | oo_select_keys(groups['oo_nodes_to_config']) }}" + sync_tmpdir: "{{ hostvars.localhost.mktemp.stdout }}" + roles: + - openshift_register_nodes + tasks: + - name: Create the temp directory on the master + file: + path: "{{ sync_tmpdir }}" + owner: "{{ ansible_ssh_user }}" + mode: 0700 + state: directory + changed_when: False + + - name: Create a tarball of the node config directories + command: tar -czvf {{ sync_tmpdir }}/{{ item.openshift.common.hostname }}.tgz ./ + args: + chdir: "{{ openshift_cert_dir }}/node-{{ item.openshift.common.hostname }}" + with_items: openshift_nodes + changed_when: False + + - name: Retrieve the node config tarballs from the master + fetch: + src: "{{ sync_tmpdir }}/{{ item.openshift.common.hostname }}.tgz" + dest: "{{ sync_tmpdir }}/" + flat: yes + fail_on_missing: yes + validate_checksum: yes + with_items: openshift_nodes + changed_when: False + + - name: Remove the temp directory on the master + file: + path: "{{ sync_tmpdir }}" + state: absent + changed_when: False + + +- name: Configure node instances + hosts: oo_nodes_to_config + gather_facts: no + vars: + sync_tmpdir: "{{ hostvars.localhost.mktemp.stdout }}" + openshift_sdn_master_url: "https://{{ hostvars[groups['oo_first_master'][0]].openshift.common.hostname }}:4001" + pre_tasks: + - name: Ensure certificate directory exists + file: + path: "{{ openshift_node_cert_dir }}" + state: directory + + # 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: Unarchive the tarball on the node + unarchive: + src: "{{ sync_tmpdir }}/{{ openshift.common.hostname }}.tgz" + dest: "{{ openshift_node_cert_dir }}" + roles: + - openshift_node + - { role: openshift_sdn_node, when: openshift.common.use_openshift_sdn | bool } + tasks: + - name: Create group for deployment type + group_by: key=oo_nodes_deployment_type_{{ openshift.common.deployment_type }} + changed_when: False + + +- name: Delete temporary directory + hosts: localhost + gather_facts: no + tasks: + - file: name={{ mktemp.stdout }} state=absent + changed_when: False + + +# Additional config for online type deployments +- name: Additional instance config + hosts: oo_nodes_deployment_type_online + gather_facts: no + roles: + - os_env_extras + - os_env_extras_node diff --git a/playbooks/common/openshift-node/filter_plugins b/playbooks/common/openshift-node/filter_plugins new file mode 120000 index 000000000..99a95e4ca --- /dev/null +++ b/playbooks/common/openshift-node/filter_plugins @@ -0,0 +1 @@ +../../../filter_plugins \ No newline at end of file diff --git a/playbooks/common/openshift-node/roles b/playbooks/common/openshift-node/roles new file mode 120000 index 000000000..e2b799b9d --- /dev/null +++ b/playbooks/common/openshift-node/roles @@ -0,0 +1 @@ +../../../roles/ \ No newline at end of file diff --git a/playbooks/gce/openshift-cluster/config.yml b/playbooks/gce/openshift-cluster/config.yml new file mode 100644 index 000000000..8b8490246 --- /dev/null +++ b/playbooks/gce/openshift-cluster/config.yml @@ -0,0 +1,37 @@ +--- +# TODO: fix firewall related bug with GCE and origin, since GCE is overriding +# /etc/sysconfig/iptables +- name: Populate oo_masters_to_config host group + hosts: localhost + gather_facts: no + vars_files: + - vars.yml + tasks: + - name: Evaluate oo_masters_to_config + add_host: + name: "{{ item }}" + groups: oo_masters_to_config + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user | default(ansible_ssh_user, true) }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + with_items: groups["tag_env-host-type-{{ cluster_id }}-openshift-master"] | default([]) + - name: Evaluate oo_nodes_to_config + add_host: + name: "{{ item }}" + groups: oo_nodes_to_config + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user | default(ansible_ssh_user, true) }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + with_items: groups["tag_env-host-type-{{ cluster_id }}-openshift-node"] | default([]) + - name: Evaluate oo_first_master + add_host: + name: "{{ groups['tag_env-host-type-' ~ cluster_id ~ '-openshift-master'][0] }}" + groups: oo_first_master + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user | default(ansible_ssh_user, true) }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + when: "'tag_env-host-type-{{ cluster_id }}-openshift-master' in groups" + +- include: ../../common/openshift-cluster/config.yml + vars: + openshift_cluster_id: "{{ cluster_id }}" + openshift_debug_level: 4 + openshift_deployment_type: "{{ deployment_type }}" + openshift_hostname: "{{ gce_private_ip }}" diff --git a/playbooks/gce/openshift-cluster/launch.yml b/playbooks/gce/openshift-cluster/launch.yml index 14cdd2537..34a5a0b94 100644 --- a/playbooks/gce/openshift-cluster/launch.yml +++ b/playbooks/gce/openshift-cluster/launch.yml @@ -4,59 +4,25 @@ connection: local gather_facts: no vars_files: - - vars.yml + - 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\"]" + - fail: msg="Deployment type not supported for libvirt provider yet" + when: deployment_type == 'enterprise' + + - include: ../../common/openshift-cluster/set_master_launch_facts_tasks.yml + - include: tasks/launch_instances.yml + vars: + instances: "{{ master_names }}" + cluster: "{{ cluster_id }}" + type: "{{ k8s_type }}" + + - include: ../../common/openshift-cluster/set_node_launch_facts_tasks.yml + - include: tasks/launch_instances.yml + vars: + instances: "{{ node_names }}" + cluster: "{{ cluster_id }}" + type: "{{ k8s_type }}" + +- include: update.yml - include: list.yml diff --git a/playbooks/gce/openshift-cluster/launch_instances.yml b/playbooks/gce/openshift-cluster/launch_instances.yml deleted file mode 100644 index b4f33bd87..000000000 --- a/playbooks/gce/openshift-cluster/launch_instances.yml +++ /dev/null @@ -1,44 +0,0 @@ ---- -# 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) }}" - 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-{{ lookup('env', 'LOGNAME') |default(cluster, true) }}" - - "env-{{ cluster }}" - - "host-type-{{ type }}" - - "env-host-type-{{ cluster }}-openshift-{{ type }}" - register: gce - -- 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 - wait_for: "port=22 host={{ item.public_ip }}" - with_items: gce.instance_data - -- 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/list.yml b/playbooks/gce/openshift-cluster/list.yml index 1124b0ea3..bab2fb9f8 100644 --- a/playbooks/gce/openshift-cluster/list.yml +++ b/playbooks/gce/openshift-cluster/list.yml @@ -2,16 +2,23 @@ - name: Generate oo_list_hosts group hosts: localhost gather_facts: no + vars_files: + - vars.yml 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) + when: cluster_id == '' + - add_host: + name: "{{ item }}" + groups: oo_list_hosts + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user | default(ansible_ssh_user, true) }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + with_items: groups[scratch_group] | default([]) | 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}}" + - debug: + msg: "public ip:{{ hostvars[inventory_hostname].gce_public_ip }} private ip:{{ hostvars[inventory_hostname].gce_private_ip }} deployment-type: {{ hostvars[inventory_hostname].group_names | oo_get_deployment_type_from_groups }}" diff --git a/playbooks/gce/openshift-cluster/tasks/launch_instances.yml b/playbooks/gce/openshift-cluster/tasks/launch_instances.yml new file mode 100644 index 000000000..a68edefae --- /dev/null +++ b/playbooks/gce/openshift-cluster/tasks/launch_instances.yml @@ -0,0 +1,42 @@ +--- +# 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) + gce: + instance_names: "{{ instances }}" + machine_type: "{{ lookup('env', 'gce_machine_type') | default('n1-standard-1', true) }}" + image: "{{ lookup('env', 'gce_machine_image') | default(deployment_vars[deployment_type].image, true) }}" + 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-{{ lookup('env', 'LOGNAME') |default(cluster, true) }} + - env-{{ cluster }} + - host-type-{{ type }} + - env-host-type-{{ cluster }}-openshift-{{ type }} + - deployment-type-{{ deployment_type }} + register: gce + +- name: Add new instances to groups and set variables needed + add_host: + hostname: "{{ item.name }}" + ansible_ssh_host: "{{ item.public_ip }}" + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user | default(ansible_ssh_user, true) }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + 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 + wait_for: port=22 host={{ item.public_ip }} + with_items: gce.instance_data + +- name: Wait for user setup + command: "ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o ConnectTimeout=10 -o UserKnownHostsFile=/dev/null {{ hostvars[item.name].ansible_ssh_user }}@{{ item.public_ip }} echo {{ hostvars[item.name].ansible_ssh_user }} 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 index 0281ae953..abe6a4c95 100644 --- a/playbooks/gce/openshift-cluster/terminate.yml +++ b/playbooks/gce/openshift-cluster/terminate.yml @@ -1,20 +1,34 @@ --- - name: Terminate instance(s) hosts: localhost - + gather_facts: no vars_files: - - vars.yml + - vars.yml + tasks: + - set_fact: scratch_group=tag_env-host-type-{{ cluster_id }}-openshift-node + - add_host: + name: "{{ item }}" + groups: oo_nodes_to_terminate + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user | default(ansible_ssh_user, true) }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + with_items: groups[scratch_group] | default([]) | difference(['localhost']) | difference(groups.status_terminated) + + - set_fact: scratch_group=tag_env-host-type-{{ cluster_id }}-openshift-master + - add_host: + name: "{{ item }}" + groups: oo_masters_to_terminate + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user | default(ansible_ssh_user, true) }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + with_items: groups[scratch_group] | default([]) | difference(['localhost']) | difference(groups.status_terminated) - include: ../openshift-node/terminate.yml vars: - oo_host_group_exp: 'groups["tag_env-host-type-{{ cluster_id }}-openshift-node"]' gce_service_account_email: "{{ lookup('env', 'gce_service_account_email_address') }}" gce_pem_file: "{{ lookup('env', 'gce_service_account_pem_file_path') }}" gce_project_id: "{{ lookup('env', 'gce_project_id') }}" - include: ../openshift-master/terminate.yml vars: - oo_host_group_exp: 'groups["tag_env-host-type-{{ cluster_id }}-openshift-master"]' gce_service_account_email: "{{ lookup('env', 'gce_service_account_email_address') }}" gce_pem_file: "{{ lookup('env', 'gce_service_account_pem_file_path') }}" gce_project_id: "{{ lookup('env', 'gce_project_id') }}" diff --git a/playbooks/gce/openshift-cluster/update.yml b/playbooks/gce/openshift-cluster/update.yml index 973e4c3ef..9ebf39a13 100644 --- a/playbooks/gce/openshift-cluster/update.yml +++ b/playbooks/gce/openshift-cluster/update.yml @@ -1,13 +1,18 @@ --- -- hosts: "tag_env-{{ cluster_id }}" - roles: - - openshift_repos - - os_update_latest +- name: Populate oo_hosts_to_update group + hosts: localhost + gather_facts: no + vars_files: + - vars.yml + tasks: + - name: Evaluate oo_hosts_to_update + add_host: + name: "{{ item }}" + groups: oo_hosts_to_update + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user | default(ansible_ssh_user, true) }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + with_items: groups["tag_env-host-type-{{ cluster_id }}-openshift-master"] | union(groups["tag_env-host-type-{{ cluster_id }}-openshift-node"]) | default([]) -- include: ../openshift-master/config.yml - vars: - oo_host_group_exp: "groups[\"tag_env-host-type-{{ cluster_id }}-openshift-master\"]" +- include: ../../common/openshift-cluster/update_repos_and_packages.yml -- include: ../openshift-node/config.yml - vars: - oo_host_group_exp: "groups[\"tag_env-host-type-{{ cluster_id }}-openshift-node\"]" +- include: config.yml diff --git a/playbooks/gce/openshift-cluster/vars.yml b/playbooks/gce/openshift-cluster/vars.yml index ed97d539c..ae33083b9 100644 --- a/playbooks/gce/openshift-cluster/vars.yml +++ b/playbooks/gce/openshift-cluster/vars.yml @@ -1 +1,15 @@ --- +deployment_vars: + origin: + image: centos-7 + ssh_user: + sudo: yes + online: + image: libra-rhel7 + ssh_user: root + sudo: no + enterprise: + image: rhel-7 + ssh_user: + sudo: yes + diff --git a/playbooks/gce/openshift-master/config.yml b/playbooks/gce/openshift-master/config.yml index 857da0763..af6000bc8 100644 --- a/playbooks/gce/openshift-master/config.yml +++ b/playbooks/gce/openshift-master/config.yml @@ -1,20 +1,18 @@ --- -- name: master/config.yml, populate oo_masters_to_config host group if needed +- name: Populate oo_masters_to_config host group 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: Evaluate oo_masters_to_config + add_host: + name: "{{ item }}" + groups: oo_masters_to_config + ansible_ssh_user: root + with_items: oo_host_group_exp | default([]) -- name: "Configure instances" - hosts: oo_masters_to_config +- include: ../../common/openshift-master/config.yml vars: + openshift_cluster_id: "{{ cluster_id }}" + openshift_debug_level: 4 + openshift_deployment_type: "{{ deployment_type }}" openshift_hostname: "{{ gce_private_ip }}" - vars_files: - - vars.yml - roles: - - openshift_master - - pods - - os_env_extras diff --git a/playbooks/gce/openshift-master/launch.yml b/playbooks/gce/openshift-master/launch.yml index 287596002..ef10b6cf0 100644 --- a/playbooks/gce/openshift-master/launch.yml +++ b/playbooks/gce/openshift-master/launch.yml @@ -8,14 +8,12 @@ connection: local gather_facts: no +# TODO: modify image based on deployment_type vars: inst_names: "{{ oo_new_inst_names }}" machine_type: n1-standard-1 image: libra-rhel7 - vars_files: - - vars.yml - tasks: - name: Launch instances gce: @@ -37,7 +35,7 @@ with_items: gce.instance_data - name: Wait for ssh - wait_for: "port=22 host={{ item.public_ip }}" + wait_for: port=22 host={{ item.public_ip }} with_items: gce.instance_data - name: Wait for root user setup diff --git a/playbooks/gce/openshift-master/terminate.yml b/playbooks/gce/openshift-master/terminate.yml index 8319774f8..452ac5199 100644 --- a/playbooks/gce/openshift-master/terminate.yml +++ b/playbooks/gce/openshift-master/terminate.yml @@ -3,10 +3,9 @@ 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: Evaluate oo_masters_to_terminate + add_host: name={{ item }} groups=oo_masters_to_terminate + with_items: oo_host_group_exp | default([]) - name: Terminate master instances hosts: localhost @@ -22,6 +21,7 @@ instance_names: "{{ groups['oo_masters_to_terminate'] }}" disks: "{{ groups['oo_masters_to_terminate'] }}" register: gce + when: "'oo_masters_to_terminate' in groups" - name: Remove disks of instances gce_pd: @@ -32,5 +32,4 @@ zone: "{{ gce.zone }}" state: absent with_items: gce.instance_names - - + when: "'oo_masters_to_terminate' in groups" diff --git a/playbooks/gce/openshift-master/vars.yml b/playbooks/gce/openshift-master/vars.yml deleted file mode 100644 index c196b2fca..000000000 --- a/playbooks/gce/openshift-master/vars.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -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 771cc3a94..5b1601176 100644 --- a/playbooks/gce/openshift-node/config.yml +++ b/playbooks/gce/openshift-node/config.yml @@ -1,100 +1,24 @@ --- -- name: node/config.yml, populate oo_nodes_to_config host group if needed +- name: Populate oo_nodes_to_config and oo_first_master host groups hosts: localhost gather_facts: no tasks: - - name: Evaluate oo_host_group_exp - 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: Evaluate oo_nodes_to_config + add_host: + name: "{{ item }}" + groups: oo_nodes_to_config + ansible_ssh_user: root + with_items: oo_host_group_exp | default([]) + - name: Evaluate oo_first_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 + ansible_ssh_user: root -- 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: "{{ 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: 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 +- include: ../../common/openshift-node/config.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 + openshift_cluster_id: "{{ cluster_id }}" + openshift_debug_level: 4 + openshift_deployment_type: "{{ deployment_type }}" + openshift_hostname: "{{ gce_private_ip }}" diff --git a/playbooks/gce/openshift-node/launch.yml b/playbooks/gce/openshift-node/launch.yml index 73d0478ab..086ba58bc 100644 --- a/playbooks/gce/openshift-node/launch.yml +++ b/playbooks/gce/openshift-node/launch.yml @@ -8,14 +8,12 @@ connection: local gather_facts: no +# TODO: modify image based on deployment_type vars: inst_names: "{{ oo_new_inst_names }}" machine_type: n1-standard-1 image: libra-rhel7 - vars_files: - - vars.yml - tasks: - name: Launch instances gce: @@ -37,7 +35,7 @@ with_items: gce.instance_data - name: Wait for ssh - wait_for: "port=22 host={{ item.public_ip }}" + wait_for: port=22 host={{ item.public_ip }} with_items: gce.instance_data - name: Wait for root user setup diff --git a/playbooks/gce/openshift-node/terminate.yml b/playbooks/gce/openshift-node/terminate.yml index 7d71dfcab..357e0c295 100644 --- a/playbooks/gce/openshift-node/terminate.yml +++ b/playbooks/gce/openshift-node/terminate.yml @@ -3,10 +3,9 @@ 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: Evaluate oo_nodes_to_terminate + add_host: name={{ item }} groups=oo_nodes_to_terminate + with_items: oo_host_group_exp | default([]) - name: Terminate node instances hosts: localhost @@ -22,6 +21,7 @@ instance_names: "{{ groups['oo_nodes_to_terminate'] }}" disks: "{{ groups['oo_nodes_to_terminate'] }}" register: gce + when: "'oo_nodes_to_terminate' in groups" - name: Remove disks of instances gce_pd: @@ -32,5 +32,4 @@ zone: "{{ gce.zone }}" state: absent with_items: gce.instance_names - - + when: "'oo_nodes_to_terminate' in groups" diff --git a/playbooks/gce/openshift-node/vars.yml b/playbooks/gce/openshift-node/vars.yml deleted file mode 100644 index c196b2fca..000000000 --- a/playbooks/gce/openshift-node/vars.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -openshift_debug_level: 4 -openshift_cluster_id: "{{ cluster_id }}" diff --git a/playbooks/libvirt/openshift-cluster/config.yml b/playbooks/libvirt/openshift-cluster/config.yml new file mode 100644 index 000000000..faf278b10 --- /dev/null +++ b/playbooks/libvirt/openshift-cluster/config.yml @@ -0,0 +1,38 @@ +--- +# TODO: need to figure out a plan for setting hostname, currently the default +# is localhost, so no hostname value (or public_hostname) value is getting +# assigned + +- name: Populate oo_masters_to_config host group + hosts: localhost + gather_facts: no + vars_files: + - vars.yml + tasks: + - name: Evaluate oo_masters_to_config + add_host: + name: "{{ item }}" + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + groups: oo_masters_to_config + with_items: groups["tag_env-host-type-{{ cluster_id }}-openshift-master"] | default([]) + - name: Evaluate oo_nodes_to_config + add_host: + name: "{{ item }}" + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + groups: oo_nodes_to_config + with_items: groups["tag_env-host-type-{{ cluster_id }}-openshift-node"] | default([]) + - name: Evaluate oo_first_master + add_host: + name: "{{ groups['tag_env-host-type-' ~ cluster_id ~ '-openshift-master'][0] }}" + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + groups: oo_first_master + when: "'tag_env-host-type-{{ cluster_id }}-openshift-master' in groups" + +- include: ../../common/openshift-cluster/config.yml + vars: + openshift_cluster_id: "{{ cluster_id }}" + openshift_debug_level: 4 + openshift_deployment_type: "{{ deployment_type }}" diff --git a/playbooks/libvirt/openshift-cluster/launch.yml b/playbooks/libvirt/openshift-cluster/launch.yml index 6f2df33af..a7ddc1e7e 100644 --- a/playbooks/libvirt/openshift-cluster/launch.yml +++ b/playbooks/libvirt/openshift-cluster/launch.yml @@ -1,65 +1,36 @@ +--- - 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 - + - vars.yml + vars: + os_libvirt_storage_pool: "{{ libvirt_storage_pool | default('images') }}" + os_libvirt_storage_pool_path: "{{ libvirt_storage_pool_path | default('/var/lib/libvirt/images') }}" + os_libvirt_network: "{{ libvirt_network | default('default') }}" + image_url: "{{ deployment_vars[deployment_type].image.url }}" + image_sha256: "{{ deployment_vars[deployment_type].image.sha256 }}" + image_name: "{{ deployment_vars[deployment_type].image.name }}" 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 }}' + - fail: msg="Deployment type not supported for libvirt provider yet" + when: deployment_type in ['online', 'enterprise'] - - set_fact: - master_names: "{{ master_names_output.results | oo_collect('ansible_facts') | oo_collect('scratch_name') }}" + - include: tasks/configure_libvirt.yml - - include: launch_instances.yml - vars: - instances: '{{ master_names }}' - cluster: '{{ cluster_id }}' - type: '{{ k8s_type }}' - group_name: 'tag_env-host-type-{{ cluster_id }}-openshift-master' + - include: ../../common/openshift-cluster/set_master_launch_facts_tasks.yml + - include: tasks/launch_instances.yml + vars: + instances: "{{ master_names }}" + cluster: "{{ cluster_id }}" + type: "{{ k8s_type }}" - - set_fact: - k8s_type: node + - include: ../../common/openshift-cluster/set_node_launch_facts_tasks.yml + - include: tasks/launch_instances.yml + vars: + instances: "{{ node_names }}" + cluster: "{{ cluster_id }}" + type: "{{ k8s_type }}" - - 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 }}' +- include: update.yml - - 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 }}' +- include: list.yml diff --git a/playbooks/libvirt/openshift-cluster/launch_instances.yml b/playbooks/libvirt/openshift-cluster/launch_instances.yml deleted file mode 100644 index 3bbcae981..000000000 --- a/playbooks/libvirt/openshift-cluster/launch_instances.yml +++ /dev/null @@ -1,102 +0,0 @@ -- 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 index 6bf07e3c6..25a25f791 100644 --- a/playbooks/libvirt/openshift-cluster/list.yml +++ b/playbooks/libvirt/openshift-cluster/list.yml @@ -1,43 +1,23 @@ +--- - name: Generate oo_list_hosts group hosts: localhost - connection: local gather_facts: no - - vars: - libvirt_uri: 'qemu:///system' - + vars_files: + - vars.yml 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 + - set_fact: scratch_group=tag_env-{{ cluster_id }} + when: cluster_id != '' + - set_fact: scratch_group=all + when: cluster_id == '' + - add_host: + name: "{{ item }}" + groups: oo_list_hosts + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + with_items: groups[scratch_group] | default([]) | difference(['localhost']) - name: List Hosts hosts: oo_list_hosts - tasks: - - debug: - msg: 'public:{{ansible_default_ipv4.address}} private:{{ansible_default_ipv4.address}}' + - debug: + msg: 'public:{{ansible_default_ipv4.address}} private:{{ansible_default_ipv4.address}} deployment-type: {{ hostvars[inventory_hostname].group_names | oo_get_deployment_type_from_groups }}' diff --git a/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt.yml b/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt.yml new file mode 100644 index 000000000..f237c1a60 --- /dev/null +++ b/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt.yml @@ -0,0 +1,6 @@ +--- +- include: configure_libvirt_storage_pool.yml + when: libvirt_storage_pool is defined and libvirt_storage_pool_path is defined + +- include: configure_libvirt_network.yml + when: libvirt_network is defined diff --git a/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_network.yml b/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_network.yml new file mode 100644 index 000000000..1cd83f7be --- /dev/null +++ b/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_network.yml @@ -0,0 +1,27 @@ +--- +- name: Test if libvirt network for openshift already exists + command: "virsh -c {{ libvirt_uri }} net-info {{ libvirt_network }}" + register: net_info_result + changed_when: False + failed_when: "net_info_result.rc != 0 and 'error: Network not found:' not in net_info_result.stderr" + +- name: Create a temp directory for the template xml file + command: "/usr/bin/mktemp -d /tmp/openshift-ansible-XXXXXXX" + register: mktemp + when: net_info_result.rc == 1 + +- name: Create network xml file + template: + src: templates/network.xml + dest: "{{ mktemp.stdout }}/network.xml" + when: net_info_result.rc == 1 + +- name: Create libvirt network for openshift + command: "virsh -c {{ libvirt_uri }} net-create {{ mktemp.stdout }}/network.xml" + when: net_info_result.rc == 1 + +- name: Remove the temp directory + file: + path: "{{ mktemp.stdout }}" + state: absent + when: net_info_result.rc == 1 diff --git a/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_storage_pool.yml b/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_storage_pool.yml new file mode 100644 index 000000000..817acb250 --- /dev/null +++ b/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_storage_pool.yml @@ -0,0 +1,27 @@ +--- +- name: Create libvirt storage directory for openshift + file: + dest: "{{ libvirt_storage_pool_path }}" + state: directory + +- acl: + default: yes + entity: kvm + etype: group + name: "{{ libvirt_storage_pool_path }}" + permissions: rwx + state: present + +- name: Test if libvirt storage pool for openshift already exists + command: "virsh -c {{ libvirt_uri }} pool-info {{ libvirt_storage_pool }}" + register: pool_info_result + changed_when: False + failed_when: "pool_info_result.rc != 0 and 'error: Storage pool not found:' not in pool_info_result.stderr" + +- 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 }}' + when: pool_info_result.rc == 1 + +- name: Refresh the libvirt storage pool for openshift + command: 'virsh -c {{ libvirt_uri }} pool-refresh {{ libvirt_storage_pool }}' + when: pool_info_result.rc == 1 diff --git a/playbooks/libvirt/openshift-cluster/tasks/launch_instances.yml b/playbooks/libvirt/openshift-cluster/tasks/launch_instances.yml new file mode 100644 index 000000000..96d440096 --- /dev/null +++ b/playbooks/libvirt/openshift-cluster/tasks/launch_instances.yml @@ -0,0 +1,104 @@ +--- +# TODO: Add support for choosing base image based on deployment_type and os +# wanted (os wanted needs support added in bin/cluster with sane defaults: +# fedora/centos for origin, rhel for online/enterprise) + +# TODO: create a role to encapsulate some of this complexity, possibly also +# create a module to manage the storage tasks, network tasks, and possibly +# even handle the libvirt tasks to set metadata in the domain xml and be able +# to create/query data about vms without having to use xml the python libvirt +# bindings look like a good candidate for this + +- name: Download Base Cloud image + get_url: + url: '{{ image_url }}' + sha256sum: '{{ image_sha256 }}' + dest: '{{ os_libvirt_storage_pool_path }}/{{ image_name }}' + +- name: Create the cloud-init config drive path + file: + dest: '{{ os_libvirt_storage_pool_path }}/{{ item }}_configdrive/' + state: directory + with_items: instances + +- name: Create the cloud-init config drive files + template: + src: '{{ item[1] }}' + dest: '{{ os_libvirt_storage_pool_path }}/{{ item[0] }}_configdrive/{{ item[1] }}' + with_nested: + - instances + - [ user-data, meta-data ] + +- name: Create the cloud-init config drive + command: 'genisoimage -output {{ os_libvirt_storage_pool_path }}/{{ item }}_cloud-init.iso -volid cidata -joliet -rock user-data meta-data' + args: + chdir: '{{ os_libvirt_storage_pool_path }}/{{ item }}_configdrive/' + creates: '{{ os_libvirt_storage_pool_path }}/{{ item }}_cloud-init.iso' + with_items: instances + +- name: Create VMs drives + command: 'virsh -c {{ libvirt_uri }} vol-create-as {{ os_libvirt_storage_pool }} {{ item }}.qcow2 10G --format qcow2 --backing-vol {{ 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: "{{ deployment_vars[deployment_type].ssh_user }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + 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 openshift user setup + command: 'ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o ConnectTimeout=10 -o UserKnownHostsFile=/dev/null openshift@{{ item.1 }} echo openshift user is setup' + register: result + until: result.rc == 0 + retries: 30 + delay: 1 + with_together: + - instances + - ips diff --git a/playbooks/libvirt/openshift-cluster/templates/domain.xml b/playbooks/libvirt/openshift-cluster/templates/domain.xml new file mode 100644 index 000000000..8cb017367 --- /dev/null +++ b/playbooks/libvirt/openshift-cluster/templates/domain.xml @@ -0,0 +1,67 @@ + + {{ item }} + 1 + + deployment-type-{{ deployment_type }} + env-{{ cluster }} + env-host-type-{{ cluster }}-openshift-{{ type }} + host-type-{{ type }} + + 1 + 2 + + hvm + + + + + + + + + + + + + destroy + restart + restart + + /usr/bin/qemu-system-x86_64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/playbooks/libvirt/openshift-cluster/templates/meta-data b/playbooks/libvirt/openshift-cluster/templates/meta-data new file mode 100644 index 000000000..6b421770d --- /dev/null +++ b/playbooks/libvirt/openshift-cluster/templates/meta-data @@ -0,0 +1,3 @@ +instance-id: {{ item[0] }} +hostname: {{ item[0] }} +local-hostname: {{ item[0] }}.example.com diff --git a/playbooks/libvirt/openshift-cluster/templates/network.xml b/playbooks/libvirt/openshift-cluster/templates/network.xml new file mode 100644 index 000000000..86dcd62bb --- /dev/null +++ b/playbooks/libvirt/openshift-cluster/templates/network.xml @@ -0,0 +1,23 @@ + + openshift-ansible + + + + + + + + + + + + + + + + + + + + + diff --git a/playbooks/libvirt/openshift-cluster/templates/user-data b/playbooks/libvirt/openshift-cluster/templates/user-data new file mode 100644 index 000000000..77b788109 --- /dev/null +++ b/playbooks/libvirt/openshift-cluster/templates/user-data @@ -0,0 +1,23 @@ +#cloud-config +disable_root: true + +hostname: {{ item[0] }} +fqdn: {{ item[0] }}.example.com +manage_etc_hosts: true + +users: + - default + - name: root + ssh_authorized_keys: + - {{ lookup('file', '~/.ssh/id_rsa.pub') }} + +system_info: + default_user: + name: openshift + sudo: ["ALL=(ALL) NOPASSWD: ALL"] + +ssh_authorized_keys: + - {{ lookup('file', '~/.ssh/id_rsa.pub') }} + +bootcmd: + - NETWORK_CONFIG=/etc/sysconfig/network-scripts/ifcfg-eth0; if ! grep DHCP_HOSTNAME ${NETWORK_CONFIG}; then echo 'DHCP_HOSTNAME="{{ item[0] }}.example.com"' >> ${NETWORK_CONFIG}; fi; pkill -9 dhclient; service network restart diff --git a/playbooks/libvirt/openshift-cluster/terminate.yml b/playbooks/libvirt/openshift-cluster/terminate.yml index c609169d3..b173a09dd 100644 --- a/playbooks/libvirt/openshift-cluster/terminate.yml +++ b/playbooks/libvirt/openshift-cluster/terminate.yml @@ -1,41 +1,44 @@ +--- +# TODO: does not handle a non-existant cluster gracefully + - name: Terminate instance(s) hosts: localhost - connection: local gather_facts: no + vars_files: + - vars.yml + tasks: + - set_fact: cluster_group=tag_env-{{ cluster_id }} + - add_host: + name: "{{ item }}" + groups: oo_hosts_to_terminate + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + with_items: groups[cluster_group] | default([]) - vars: - libvirt_storage_pool_path: "{{ lookup('env','HOME') }}/libvirt-storage-pool-openshift" - libvirt_storage_pool: 'openshift' - libvirt_uri: 'qemu:///system' + - name: Destroy VMs + virt: + name: '{{ item[0] }}' + command: '{{ item[1] }}' + uri: '{{ libvirt_uri }}' + with_nested: + - groups['oo_hosts_to_terminate'] + - [ destroy, undefine ] - tasks: - - name: List VMs - virt: - command: list_vms - register: list_vms + - name: Delete VMs drives + command: 'virsh -c {{ libvirt_uri }} vol-delete --pool {{ libvirt_storage_pool }} {{ item }}.qcow2' + args: + removes: '{{ libvirt_storage_pool_path }}/{{ item }}.qcow2' + with_items: groups['oo_hosts_to_terminate'] - - 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 the VM cloud-init image + file: + path: '{{ libvirt_storage_pool_path }}/{{ item }}_cloud-init.iso' + state: absent + with_items: groups['oo_hosts_to_terminate'] - - 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: Remove the cloud-init config directory + file: + path: '{{ libvirt_storage_pool_path }}/{{ item }}_configdrive/' + state: absent + with_items: groups['oo_hosts_to_terminate'] - - 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/update.yml b/playbooks/libvirt/openshift-cluster/update.yml new file mode 100644 index 000000000..57e36db9e --- /dev/null +++ b/playbooks/libvirt/openshift-cluster/update.yml @@ -0,0 +1,18 @@ +--- +- name: Populate oo_hosts_to_update group + hosts: localhost + gather_facts: no + vars_files: + - vars.yml + tasks: + - name: Evaluate oo_hosts_to_update + add_host: + name: "{{ item }}" + groups: oo_hosts_to_update + ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" + ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" + with_items: groups["tag_env-host-type-{{ cluster_id }}-openshift-master"] | union(groups["tag_env-host-type-{{ cluster_id }}-openshift-node"]) | default([]) + +- include: ../../common/openshift-cluster/update_repos_and_packages.yml + +- include: config.yml diff --git a/playbooks/libvirt/openshift-cluster/vars.yml b/playbooks/libvirt/openshift-cluster/vars.yml index 4e4eecd46..65d954fee 100644 --- a/playbooks/libvirt/openshift-cluster/vars.yml +++ b/playbooks/libvirt/openshift-cluster/vars.yml @@ -1,7 +1,33 @@ -# 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 +--- +libvirt_storage_pool_path: "{{ lookup('env','HOME') }}/libvirt-storage-pool-openshift-ansible" +libvirt_storage_pool: 'openshift-ansible' +libvirt_network: openshift-ansible +libvirt_uri: 'qemu:///system' -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 +deployment_vars: + origin: + image: + url: "http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2" + name: CentOS-7-x86_64-GenericCloud.qcow2 + sha256: e324e3ab1d24a1bbf035ddb365e7f9058c0b454acf48d7aa15c5519fae5998ab + ssh_user: openshift + sudo: yes + online: + image: + url: + name: + sha256: + ssh_user: root + sudo: no + enterprise: + image: + url: + name: + sha256: + ssh_user: openshift + sudo: yes +# origin: +# fedora: +# url: "http://download.fedoraproject.org/pub/fedora/linux/releases/21/Cloud/Images/x86_64/Fedora-Cloud-Base-20141203-21.x86_64.qcow2" +# name: Fedora-Cloud-Base-20141203-21.x86_64.qcow2 +# sha256: 3a99bb89f33e3d4ee826c8160053cdb8a72c80cd23350b776ce73cd244467d86 diff --git a/playbooks/libvirt/openshift-master/config.yml b/playbooks/libvirt/openshift-master/config.yml deleted file mode 100644 index dd95fd57f..000000000 --- a/playbooks/libvirt/openshift-master/config.yml +++ /dev/null @@ -1,21 +0,0 @@ -- 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 deleted file mode 120000 index 99a95e4ca..000000000 --- a/playbooks/libvirt/openshift-master/filter_plugins +++ /dev/null @@ -1 +0,0 @@ -../../../filter_plugins \ No newline at end of file diff --git a/playbooks/libvirt/openshift-master/roles b/playbooks/libvirt/openshift-master/roles deleted file mode 120000 index 20c4c58cf..000000000 --- a/playbooks/libvirt/openshift-master/roles +++ /dev/null @@ -1 +0,0 @@ -../../../roles \ No newline at end of file diff --git a/playbooks/libvirt/openshift-master/vars.yml b/playbooks/libvirt/openshift-master/vars.yml deleted file mode 100644 index ad0c0fbe2..000000000 --- a/playbooks/libvirt/openshift-master/vars.yml +++ /dev/null @@ -1 +0,0 @@ -openshift_debug_level: 4 diff --git a/playbooks/libvirt/openshift-node/config.yml b/playbooks/libvirt/openshift-node/config.yml deleted file mode 100644 index 3244a8046..000000000 --- a/playbooks/libvirt/openshift-node/config.yml +++ /dev/null @@ -1,102 +0,0 @@ -- 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 deleted file mode 120000 index 99a95e4ca..000000000 --- a/playbooks/libvirt/openshift-node/filter_plugins +++ /dev/null @@ -1 +0,0 @@ -../../../filter_plugins \ No newline at end of file diff --git a/playbooks/libvirt/openshift-node/roles b/playbooks/libvirt/openshift-node/roles deleted file mode 120000 index 20c4c58cf..000000000 --- a/playbooks/libvirt/openshift-node/roles +++ /dev/null @@ -1 +0,0 @@ -../../../roles \ No newline at end of file diff --git a/playbooks/libvirt/openshift-node/vars.yml b/playbooks/libvirt/openshift-node/vars.yml deleted file mode 100644 index ad0c0fbe2..000000000 --- a/playbooks/libvirt/openshift-node/vars.yml +++ /dev/null @@ -1 +0,0 @@ -openshift_debug_level: 4 diff --git a/playbooks/libvirt/templates/domain.xml b/playbooks/libvirt/templates/domain.xml deleted file mode 100644 index da037d138..000000000 --- a/playbooks/libvirt/templates/domain.xml +++ /dev/null @@ -1,62 +0,0 @@ - - {{ 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 deleted file mode 100644 index 5d779519f..000000000 --- a/playbooks/libvirt/templates/meta-data +++ /dev/null @@ -1,2 +0,0 @@ -instance-id: {{ item[0] }} -local-hostname: {{ item[0] }} diff --git a/playbooks/libvirt/templates/user-data b/playbooks/libvirt/templates/user-data deleted file mode 100644 index 985badc8e..000000000 --- a/playbooks/libvirt/templates/user-data +++ /dev/null @@ -1,10 +0,0 @@ -#cloud-config - -disable_root: 0 - -system_info: - default_user: - name: root - -ssh_authorized_keys: - - {{ lookup('file', '~/.ssh/id_rsa.pub') }} diff --git a/roles/openshift_common/tasks/main.yml b/roles/openshift_common/tasks/main.yml index 941190534..c55677c3f 100644 --- a/roles/openshift_common/tasks/main.yml +++ b/roles/openshift_common/tasks/main.yml @@ -1,7 +1,7 @@ --- - name: Set common OpenShift facts openshift_facts: - role: 'common' + role: common local_facts: cluster_id: "{{ openshift_cluster_id | default('default') }}" debug_level: "{{ openshift_debug_level | default(0) }}" @@ -10,7 +10,7 @@ public_hostname: "{{ openshift_public_hostname | default(None) }}" public_ip: "{{ openshift_public_ip | default(None) }}" use_openshift_sdn: "{{ openshift_use_openshift_sdn | default(None) }}" - + deployment_type: "{{ openshift_deployment_type }}" - name: Set hostname hostname: name={{ openshift.common.hostname }} diff --git a/roles/openshift_common/vars/main.yml b/roles/openshift_common/vars/main.yml index 50816d319..9f657a2c7 100644 --- a/roles/openshift_common/vars/main.yml +++ b/roles/openshift_common/vars/main.yml @@ -5,3 +5,7 @@ # chains with the public zone (or the zone associated with the correct # interfaces) os_firewall_use_firewalld: False + +openshift_cert_parent_dir: /var/lib/openshift +openshift_cert_relative_dir: openshift.local.certificates +openshift_cert_dir: "{{ openshift_cert_parent_dir }}/{{ openshift_cert_relative_dir }}" diff --git a/roles/openshift_facts/library/openshift_facts.py b/roles/openshift_facts/library/openshift_facts.py index 0dd343443..1e0d5c605 100755 --- a/roles/openshift_facts/library/openshift_facts.py +++ b/roles/openshift_facts/library/openshift_facts.py @@ -21,8 +21,11 @@ class OpenShiftFactsUnsupportedRoleError(Exception): class OpenShiftFactsFileWriteError(Exception): pass +class OpenShiftFactsMetadataUnavailableError(Exception): + pass + class OpenShiftFacts(): - known_roles = ['common', 'master', 'node', 'master_sdn', 'node_sdn'] + known_roles = ['common', 'master', 'node', 'master_sdn', 'node_sdn', 'dns'] def __init__(self, role, filename, local_facts): self.changed = False @@ -169,20 +172,18 @@ class OpenShiftFacts(): 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() + ansible_facts = self.get_ansible_facts() defaults = dict() common = dict(use_openshift_sdn=True) - ip = net_facts['default_ipv4']['address'] + ip = ansible_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_values = [hostname_f, ansible_facts['nodename'], ansible_facts['fqdn']] hostname = self.choose_hostname(hostname_values) common['hostname'] = hostname @@ -196,14 +197,14 @@ class OpenShiftFacts(): 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') + etcd_port='4001', portal_net='172.30.17.0/24') 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) + node['resources_cpu'] = ansible_facts['processor_cores'] + node['resources_memory'] = int(int(ansible_facts['memtotal_mb']) * 1024 * 1024 * 0.75) defaults['node'] = node return defaults @@ -226,8 +227,7 @@ class OpenShiftFacts(): 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) + raise OpenShiftFactsMetadataUnavailableError("Metadata unavailable") if expect_json: return module.from_json(r.read()) else: @@ -252,40 +252,27 @@ class OpenShiftFacts(): 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) + try: + if supports_recursive: + metadata = self.query_metadata(metadata_url, headers, expect_json) + else: + metadata = self.walk_metadata(metadata_url, headers, expect_json) + except OpenShiftFactsMetadataUnavailableError as e: + metadata = None 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 get_ansible_facts(self): + if not hasattr(self, 'ansible_facts'): + self.ansible_facts = ansible_facts(module) + return self.ansible_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'] + ansible_facts = self.get_ansible_facts() + product_name = ansible_facts['product_name'] + product_version = ansible_facts['product_version'] + virt_type = ansible_facts['virtualization_type'] + virt_role = ansible_facts['virtualization_role'] provider = None metadata = None @@ -300,8 +287,9 @@ class OpenShiftFacts(): True) # Filter sshKeys and serviceAccounts from gce metadata - metadata['project']['attributes'].pop('sshKeys', None) - metadata['instance'].pop('serviceAccounts', None) + if 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/' @@ -310,12 +298,18 @@ class OpenShiftFacts(): 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) + if metadata: + 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) + + if not metadata['ec2_compat']: + metadata = None + return dict(name=provider, metadata=metadata) def normalize_provider_facts(self, provider, metadata): @@ -479,4 +473,6 @@ def main(): from ansible.module_utils.basic import * from ansible.module_utils.facts import * from ansible.module_utils.urls import * -main() + +if __name__ == '__main__': + main() diff --git a/roles/openshift_master/tasks/main.yml b/roles/openshift_master/tasks/main.yml index aa615df39..1b1210007 100644 --- a/roles/openshift_master/tasks/main.yml +++ b/roles/openshift_master/tasks/main.yml @@ -11,33 +11,67 @@ 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_path: "{{ openshift_master_console_path | 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_port: "{{ openshift_master_etcd_port | default(None) }}" etcd_use_ssl: "{{ openshift_master_etcd_use_ssl | default(None) }}" + portal_net: "{{ openshift_master_portal_net | default(None) }}" + +# TODO: These values need to be configurable +- name: Set dns OpenShift facts + openshift_facts: + role: 'dns' + local_facts: + ip: "{{ openshift.common.ip }}" + domain: local - name: Install OpenShift Master package yum: pkg=openshift-master state=installed + register: install_result + +- name: Reload systemd units + command: systemctl daemon-reload + when: install_result | changed + +- name: Create certificate parent directory if it doesn't exist + file: + path: "{{ openshift_cert_parent_dir }}" + state: directory + +- name: Create config parent directory if it doesn't exist + file: + path: "{{ openshift_master_config | dirname }}" + state: directory + +# TODO: should probably use a template lookup for this +# TODO: should allow for setting --etcd, --kubernetes options +# TODO: recreate config if values change +- name: Use enterprise default for openshift_registry_url if not set + set_fact: + openshift_registry_url: "openshift3_beta/ose-${component}:${version}" + when: openshift.common.deployment_type == 'enterprise' and openshift_registry_url is not defined +- name: Create master config + command: > + /usr/bin/openshift start master --write-config + --config={{ openshift_master_config }} + --portal-net={{ openshift.master.portal_net }} + --master={{ openshift.master.api_url }} + --public-master={{ openshift.master.public_api_url }} + --listen={{ 'https' if openshift.master.api_use_ssl else 'http' }}://0.0.0.0:{{ openshift.master.api_port }} + {{ ('--images=' ~ openshift_registry_url) if openshift_registry_url is defined else '' }} + {{ ('--nodes=' ~ openshift_node_ips | join(',')) if openshift_node_ips is defined else '' }} + args: + chdir: "{{ openshift_cert_parent_dir }}" + creates: "{{ openshift_master_config }}" -# 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=\"--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 - regexp: '^IMAGES=' - line: "IMAGES={{ openshift_registry_url }}" - when: openshift_registry_url is defined + line: "OPTIONS=\"--config={{ openshift_master_config }} --loglevel={{ openshift.master.debug_level }}\"" notify: - restart openshift-master @@ -53,6 +87,6 @@ # 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/openshift-client/.kubeconfig /root/.kube/.kubeconfig + command: cp {{ openshift_cert_dir }}/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 new file mode 100644 index 000000000..c52d957ac --- /dev/null +++ b/roles/openshift_master/vars/main.yml @@ -0,0 +1,5 @@ +--- +openshift_master_config: /etc/openshift/master.yaml +openshift_master_ca_dir: "{{ openshift_cert_dir }}/ca" +openshift_master_ca_cert: "{{ openshift_master_ca_dir }}/cert.crt" +openshift_master_ca_key: "{{ openshift_master_ca_dir }}/key.key" diff --git a/roles/openshift_node/tasks/main.yml b/roles/openshift_node/tasks/main.yml index e3c04585b..3d56bdd67 100644 --- a/roles/openshift_node/tasks/main.yml +++ b/roles/openshift_node/tasks/main.yml @@ -13,17 +13,22 @@ failed_when: not result.stat.exists register: result with_items: - - "{{ cert_path }}" - - "{{ cert_path }}/cert.crt" - - "{{ cert_path }}/key.key" - - "{{ cert_path }}/.kubeconfig" - - "{{ cert_path }}/server.crt" - - "{{ cert_path }}/server.key" - - "{{ cert_parent_path }}/ca/cert.crt" - #- "{{ cert_path }}/node.yaml" + - "{{ openshift_node_cert_dir }}" + - "{{ openshift_node_cert_dir }}/ca.crt" + - "{{ openshift_node_cert_dir }}/client.crt" + - "{{ openshift_node_cert_dir }}/client.key" + - "{{ openshift_node_cert_dir }}/.kubeconfig" + - "{{ openshift_node_cert_dir }}/node-config.yaml" + - "{{ openshift_node_cert_dir }}/server.crt" + - "{{ openshift_node_cert_dir }}/server.key" - name: Install OpenShift Node package yum: pkg=openshift-node state=installed + register: install_result + +- name: Reload systemd units + command: systemctl daemon-reload + when: install_result | changed # --create-certs=false is a temporary workaround until # https://github.com/openshift/origin/pull/1361 is merged upstream and it is @@ -32,16 +37,7 @@ lineinfile: dest: /etc/sysconfig/openshift-node regexp: '^OPTIONS=' - line: "OPTIONS=\"--hostname={{ openshift.common.hostname }} --loglevel={{ openshift.node.debug_level }} --create-certs=false\"" - notify: - - restart openshift-node - -- name: Set default registry url - lineinfile: - dest: /etc/sysconfig/openshift-node - regexp: '^IMAGES=' - line: "IMAGES={{ openshift_registry_url }}" - when: openshift_registry_url is defined + line: "OPTIONS=\"--loglevel={{ openshift.node.debug_level }} --config={{ openshift_node_cert_dir }}/node-config.yaml\"" notify: - restart openshift-node diff --git a/roles/openshift_node/vars/main.yml b/roles/openshift_node/vars/main.yml new file mode 100644 index 000000000..c6be83139 --- /dev/null +++ b/roles/openshift_node/vars/main.yml @@ -0,0 +1,2 @@ +--- +openshift_node_cert_dir: /etc/openshift/node diff --git a/roles/openshift_register_nodes/defaults/main.yml b/roles/openshift_register_nodes/defaults/main.yml index 3501e8922..a0befab44 100644 --- a/roles/openshift_register_nodes/defaults/main.yml +++ b/roles/openshift_register_nodes/defaults/main.yml @@ -1,5 +1,2 @@ --- openshift_kube_api_version: v1beta1 -openshift_cert_dir: openshift.local.certificates -openshift_cert_dir_parent: /var/lib/openshift -openshift_cert_dir_abs: "{{ openshift_cert_dir_parent ~ '/' ~ openshift_cert_dir }}" diff --git a/roles/openshift_register_nodes/library/kubernetes_register_node.py b/roles/openshift_register_nodes/library/kubernetes_register_node.py index 8ebeb087a..1ec977716 100755 --- a/roles/openshift_register_nodes/library/kubernetes_register_node.py +++ b/roles/openshift_register_nodes/library/kubernetes_register_node.py @@ -97,10 +97,8 @@ class ClientConfigException(Exception): class ClientConfig: def __init__(self, client_opts, module): - _, output, error = module.run_command(["/usr/bin/openshift", "ex", - "config", "view", "-o", - "json"] + client_opts, - check_rc = True) + kubectl = module.params['kubectl_cmd'] + _, output, error = module.run_command(kubectl + ["config", "view", "-o", "json"] + client_opts, check_rc = True) self.config = json.loads(output) if not (bool(self.config['clusters']) or @@ -146,6 +144,9 @@ class ClientConfig: def get_cluster_for_context(self, context): return self.get_value_for_context(context, 'cluster') + def get_namespace_for_context(self, context): + return self.get_value_for_context(context, 'namespace') + class Util: @staticmethod def remove_empty_elements(mapping): @@ -247,15 +248,15 @@ class Node: return Util.remove_empty_elements(node) def exists(self): - _, output, error = self.module.run_command(["/usr/bin/osc", "get", - "nodes"] + self.client_opts, - check_rc = True) + kubectl = self.module.params['kubectl_cmd'] + _, output, error = self.module.run_command(kubectl + ["get", "nodes"] + self.client_opts, check_rc = True) if re.search(self.module.params['name'], output, re.MULTILINE): return True return False def create(self): - cmd = ['/usr/bin/osc'] + self.client_opts + ['create', 'node', '-f', '-'] + kubectl = self.module.params['kubectl_cmd'] + cmd = kubectl + self.client_opts + ['create', '-f', '-'] rc, output, error = self.module.run_command(cmd, data=self.module.jsonify(self.get_node())) if rc != 0: @@ -273,24 +274,26 @@ class Node: def main(): module = AnsibleModule( - argument_spec = dict( - name = dict(required = True, type = 'str'), - host_ip = dict(type = 'str'), - hostnames = dict(type = 'list', default = []), - external_ips = dict(type = 'list', default = []), - internal_ips = dict(type = 'list', default = []), - api_version = dict(type = 'str', default = 'v1beta1', # TODO: after kube rebase, we can default to v1beta3 - choices = ['v1beta1', 'v1beta3']), - cpu = dict(type = 'str'), - memory = dict(type = 'str'), - labels = dict(type = 'dict', default = {}), # TODO: needs documented - annotations = dict(type = 'dict', default = {}), # TODO: needs documented - pod_cidr = dict(type = 'str'), # TODO: needs documented - external_id = dict(type = 'str'), # TODO: needs documented - client_config = dict(type = 'str'), # TODO: needs documented - client_cluster = dict(type = 'str', default = 'master'), # TODO: needs documented - client_context = dict(type = 'str', default = 'master'), # TODO: needs documented - client_user = dict(type = 'str', default = 'admin') # TODO: needs documented + argument_spec = dict( + name = dict(required = True, type = 'str'), + host_ip = dict(type = 'str'), + hostnames = dict(type = 'list', default = []), + external_ips = dict(type = 'list', default = []), + internal_ips = dict(type = 'list', default = []), + api_version = dict(type = 'str', default = 'v1beta1', # TODO: after kube rebase, we can default to v1beta3 + choices = ['v1beta1', 'v1beta3']), + cpu = dict(type = 'str'), + memory = dict(type = 'str'), + labels = dict(type = 'dict', default = {}), # TODO: needs documented + annotations = dict(type = 'dict', default = {}), # TODO: needs documented + pod_cidr = dict(type = 'str'), # TODO: needs documented + external_id = dict(type = 'str'), # TODO: needs documented + client_config = dict(type = 'str'), # TODO: needs documented + client_cluster = dict(type = 'str', default = 'master'), # TODO: needs documented + client_context = dict(type = 'str', default = 'default'), # TODO: needs documented + client_namespace = dict(type = 'str', default = 'default'), # TODO: needs documented + client_user = dict(type = 'str', default = 'system:openshift-client'), # TODO: needs documented + kubectl_cmd = dict(type = 'list', default = ['kubectl']) # TODO: needs documented ), mutually_exclusive = [ ['host_ip', 'external_ips'], @@ -333,14 +336,16 @@ def main(): client_cluster = module.params['client_cluster'] if config.has_cluster(client_cluster): - if client_cluster != config.get_cluster_for_context(client_cluster): + if client_cluster != config.get_cluster_for_context(client_context): client_opts.append("--cluster=%s" % client_cluster) else: module.fail_json(msg="Cluster %s not found in client config" % client_cluster) - # TODO: provide sane defaults for some (like hostname, externalIP, - # internalIP, etc) + client_namespace = module.params['client_namespace'] + if client_namespace != config.get_namespace_for_context(client_context): + client_opts.append("--namespace=%s" % client_namespace) + node = Node(module, client_opts, module.params['api_version'], module.params['name'], module.params['host_ip'], module.params['hostnames'], module.params['external_ips'], diff --git a/roles/openshift_register_nodes/tasks/main.yml b/roles/openshift_register_nodes/tasks/main.yml index 7319b88b1..85f490f70 100644 --- a/roles/openshift_register_nodes/tasks/main.yml +++ b/roles/openshift_register_nodes/tasks/main.yml @@ -3,53 +3,37 @@ # 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.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.common.hostname }}/server.crt" - with_items: openshift_nodes - register: server_cert_result - -# TODO: create a failed_when condition -- name: Create node client certificates - command: > - /usr/bin/openshift admin create-node-cert - --overwrite=false - --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.common.hostname }}/cert.crt" - with_items: openshift_nodes - register: node_cert_result +# TODO: use a template lookup here # TODO: create a failed_when condition -- name: Create kubeconfigs for nodes +- name: Use enterprise default for openshift_registry_url if not set + set_fact: + openshift_registry_url: "openshift3_beta/ose-${component}:${version}" + when: openshift.common.deployment_type == 'enterprise' and openshift_registry_url is not defined +- name: Create node config command: > - /usr/bin/openshift admin create-kubeconfig - --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 }} + /usr/bin/openshift admin create-node-config + --node-dir={{ openshift_cert_dir }}/node-{{ item.openshift.common.hostname }} + --node={{ item.openshift.common.hostname }} + --hostnames={{ [item.openshift.common.hostname, item.openshift.common.public_hostname]|unique|join(",") }} + --dns-domain={{ openshift.dns.domain }} + --dns-ip={{ openshift.dns.ip }} + --master={{ openshift.master.api_url }} + --signer-key={{ openshift_master_ca_key }} + --signer-cert={{ openshift_master_ca_cert }} + --certificate-authority={{ openshift_master_ca_cert }} + --signer-serial={{ openshift_master_ca_dir }}/serial.txt + --node-client-certificate-authority={{ openshift_master_ca_cert }} + {{ ('--images=' ~ openshift_registry_url) if openshift_registry_url is defined else '' }} + --listen=https://0.0.0.0:10250 args: - chdir: "{{ openshift_cert_dir_parent }}" - creates: "{{ openshift_cert_dir_abs }}/node-{{ item.openshift.common.hostname }}/.kubeconfig" + chdir: "{{ openshift_cert_parent_dir }}" + creates: "{{ openshift_cert_dir }}/node-{{ item.openshift.common.hostname }}" with_items: openshift_nodes - register: kubeconfig_result - name: Register unregistered nodes kubernetes_register_node: - client_user: openshift-client + kubectl_cmd: ['openshift', 'kube'] name: "{{ item.openshift.common.hostname }}" api_version: "{{ openshift_kube_api_version }}" cpu: "{{ item.openshift.node.resources_cpu | default(None) }}" @@ -61,7 +45,5 @@ 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, - # internal_ips, external_id with_items: openshift_nodes register: register_result diff --git a/roles/openshift_register_nodes/vars/main.yml b/roles/openshift_register_nodes/vars/main.yml new file mode 100644 index 000000000..bd497f08f --- /dev/null +++ b/roles/openshift_register_nodes/vars/main.yml @@ -0,0 +1,7 @@ +--- +openshift_cert_parent_dir: /var/lib/openshift +openshift_cert_relative_dir: openshift.local.certificates +openshift_cert_dir: "{{ openshift_cert_parent_dir }}/{{ openshift_cert_relative_dir }}" +openshift_master_ca_dir: "{{ openshift_cert_dir }}/ca" +openshift_master_ca_cert: "{{ openshift_master_ca_dir }}/cert.crt" +openshift_master_ca_key: "{{ openshift_master_ca_dir }}/key.key" diff --git a/roles/openshift_repos/README.md b/roles/openshift_repos/README.md index 6713e11fc..6bbedd839 100644 --- a/roles/openshift_repos/README.md +++ b/roles/openshift_repos/README.md @@ -14,7 +14,7 @@ Role Variables | Name | Default value | | |-------------------------------|---------------|----------------------------------------------| -| openshift_deployment_type | online | Possible values enterprise, origin, online | +| openshift_deployment_type | None | Possible values enterprise, origin, online | | openshift_additional_repos | {} | TODO | Dependencies diff --git a/roles/openshift_repos/defaults/main.yaml b/roles/openshift_repos/defaults/main.yaml index 1730207f4..7c5a14cd7 100644 --- a/roles/openshift_repos/defaults/main.yaml +++ b/roles/openshift_repos/defaults/main.yaml @@ -1,7 +1,2 @@ --- -# 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/files/online/RPM-GPG-KEY-redhat-beta b/roles/openshift_repos/files/online/RPM-GPG-KEY-redhat-beta deleted file mode 100644 index 7b40671a4..000000000 --- a/roles/openshift_repos/files/online/RPM-GPG-KEY-redhat-beta +++ /dev/null @@ -1,61 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.2.6 (GNU/Linux) - -mQINBEmkAzABEAC2/c7bP1lHQ3XScxbIk0LQWe1YOiibQBRLwf8Si5PktgtuPibT -kKpZjw8p4D+fM7jD1WUzUE0X7tXg2l/eUlMM4dw6XJAQ1AmEOtlwSg7rrMtTvM0A -BEtI7Km6fC6sU6RtBMdcqD1cH/6dbsfh8muznVA7UlX+PRBHVzdWzj6y8h84dBjo -gzcbYu9Hezqgj/lLzicqsSZPz9UdXiRTRAIhp8V30BD8uRaaa0KDDnD6IzJv3D9P -xQWbFM4Z12GN9LyeZqmD7bpKzZmXG/3drvfXVisXaXp3M07t3NlBa3Dt8NFIKZ0D -FRXBz5bvzxRVmdH6DtkDWXDPOt+Wdm1rZrCOrySFpBZQRpHw12eo1M1lirANIov7 -Z+V1Qh/aBxj5EUu32u9ZpjAPPNtQF6F/KjaoHHHmEQAuj4DLex4LY646Hv1rcv2i -QFuCdvLKQGSiFBrfZH0j/IX3/0JXQlZzb3MuMFPxLXGAoAV9UP/Sw/WTmAuTzFVm -G13UYFeMwrToOiqcX2VcK0aC1FCcTP2z4JW3PsWvU8rUDRUYfoXovc7eg4Vn5wHt -0NBYsNhYiAAf320AUIHzQZYi38JgVwuJfFu43tJZE4Vig++RQq6tsEx9Ftz3EwRR -fJ9z9mEvEiieZm+vbOvMvIuimFVPSCmLH+bI649K8eZlVRWsx3EXCVb0nQARAQAB -tDBSZWQgSGF0LCBJbmMuIChiZXRhIGtleSAyKSA8c2VjdXJpdHlAcmVkaGF0LmNv -bT6JAjYEEwECACAFAkpSM+cCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCT -ioDK8hVB6/9tEAC0+KmzeKceXQ/GTUoU6jy9vtkFCFrmv+c7ol4XpdTt0QhqBOwy -6m2mKWwmm8KfYfy0cADQ4y/EcoXl7FtFBwYmkCuEQGXhTDn9DvVjhooIq59LEMBQ -OW879RwwzRIZ8ebbjMUjDPF5MfPQqP2LBu9N4KvXlZp4voykwuuaJ+cbsKZR6pZ6 -0RQKPHKP+NgUFC0fff7XY9cuOZZWFAeKRhLN2K7bnRHKxp+kELWb6R9ZfrYwZjWc -MIPbTd1khE53L4NTfpWfAnJRtkPSDOKEGVlVLtLq4HEAxQt07kbslqISRWyXER3u -QOJj64D1ZiIMz6t6uZ424VE4ry9rBR0Jz55cMMx5O/ni9x3xzFUgH8Su2yM0r3jE -Rf24+tbOaPf7tebyx4OKe+JW95hNVstWUDyGbs6K9qGfI/pICuO1nMMFTo6GqzQ6 -DwLZvJ9QdXo7ujEtySZnfu42aycaQ9ZLC2DOCQCUBY350Hx6FLW3O546TAvpTfk0 -B6x+DV7mJQH7MGmRXQsE7TLBJKjq28Cn4tVp04PmybQyTxZdGA/8zY6pPl6xyVMH -V68hSBKEVT/rlouOHuxfdmZva1DhVvUC6Xj7+iTMTVJUAq/4Uyn31P1OJmA2a0PT -CAqWkbJSgKFccsjPoTbLyxhuMSNkEZFHvlZrSK9vnPzmfiRH0Orx3wYpMQ== -=21pb ------END PGP PUBLIC KEY BLOCK----- -The following public key can be used to verify RPM packages built and -signed by Red Hat, Inc. for this beta using `rpm -K' using the GNU GPG -package. Questions about this key should be sent to security@redhat.com. - - ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.0.6 (GNU/Linux) -Comment: For info see http://www.gnupg.org - -mQGiBDySTqsRBACzc7xuCIp10oj5B2PAV4XzDeVxprv/WTMreSNSK+iC0bEz0IBp -Vnn++qtyiXfH+bGIE9jqZgIEnpttWhUOaU5LhcLFzy+m8NWfngIFP9QfGmGAe9Gd -LFeAdhj4RmSG/vgr7vDd83Hz22dv403Ar/sliWO4vDOrMmZBG57WGYTWtwCgkMsi -UUQuJ6slbzKn82w+bYxOlL0EAIylWJGaTkKOTL5DqVR3ik9aT0Dt3FNVYiuhcKBe -II4E3KOIVA9kO8in1IZjx2gs6K2UV+GsoAVANdfKL7l9O+k+J8OxhE74oycvYJxW -QzCgXMZkNcvW5wyXwEMcr6TVd/5BGztcMw8oT3/l2MtAEG/vn1XaWToRSO1XDMDz -+AjUA/4m0mTkN8S4wjzJG8lqN7+quW3UOaiCe8J3SFrrrhE0XbY9cTJI/9nuXHU1 -VjqOSmXQYH2Db7UOroFTBiWhlAedA4O4yuK52AJnvSsHbnJSEmn9rpo5z1Q8F+qI -mDlzriJdrIrVLeDiUeTlpH3kpG38D7007GhXBV72k1gpMoMcpbQ3UmVkIEhhdCwg -SW5jLiAoQmV0YSBUZXN0IFNvZnR3YXJlKSA8cmF3aGlkZUByZWRoYXQuY29tPohX -BBMRAgAXBQI8l5p/BQsHCgMEAxUDAgMWAgECF4AACgkQ/TcmiYl9oHqdeQCfZjw4 -F9sir3XfRAjVe9kYNcQ8hnIAn0WgyT7H5RriWYTOCfauOmd+cAW4iEYEEBECAAYF -AjyXmqQACgkQIZGAzdtCpg5nDQCfepuRUyuVJvhuQkPWySETYvRw+WoAnjAWhx6q -0npMx4OE1JGFi8ymKXktuQENBDySTq4QBADKL/mK7S8E3synxISlu7R6fUvu07Oc -RoX96n0Di6T+BS99hC44XzHjMDhUX2ZzVvYS88EZXoUDDkB/8g7SwZrOJ/QE1zrI -JmSVciNhSYWwqeT40Evs88ajZUfDiNbS/cSC6oui98iS4vxd7sE7IPY+FSx9vuAR -xOa9vBnJY/dx0wADBQQAosm+Iltt2uigC6LJzxNOoIdB5r0GqTC1o5sHCeNqXJhU -ExAG8m74uzMlYVLOpGZi4y4NwwAWvCWC0MWWnnu+LGFy1wKiJKRjhv5F+WkFutY5 -WHV5L44vp9jSIlBCRG+84jheTh8xqhndM9wOfPwWdYYu1vxrB8Tn6kA17PcYfHSI -RgQYEQIABgUCPJJergAKCRD9NyaJiX2geiCPAJ4nEM4NtI9Uj8lONDk6FU86PmoL -yACfb68fBd2pWEzLKsOk9imIobHHpzE= -=gpIn ------END PGP PUBLIC KEY BLOCK----- diff --git a/roles/openshift_repos/files/online/RPM-GPG-KEY-redhat-release b/roles/openshift_repos/files/online/RPM-GPG-KEY-redhat-release deleted file mode 100644 index 0f83b622d..000000000 --- a/roles/openshift_repos/files/online/RPM-GPG-KEY-redhat-release +++ /dev/null @@ -1,63 +0,0 @@ -The following public key can be used to verify RPM packages built and -signed by Red Hat, Inc. This key is used for packages in Red Hat -products shipped after November 2009, and for all updates to those -products. - -Questions about this key should be sent to security@redhat.com. - -pub 4096R/FD431D51 2009-10-22 Red Hat, Inc. (release key 2) - ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.2.6 (GNU/Linux) - -mQINBErgSTsBEACh2A4b0O9t+vzC9VrVtL1AKvUWi9OPCjkvR7Xd8DtJxeeMZ5eF -0HtzIG58qDRybwUe89FZprB1ffuUKzdE+HcL3FbNWSSOXVjZIersdXyH3NvnLLLF -0DNRB2ix3bXG9Rh/RXpFsNxDp2CEMdUvbYCzE79K1EnUTVh1L0Of023FtPSZXX0c -u7Pb5DI5lX5YeoXO6RoodrIGYJsVBQWnrWw4xNTconUfNPk0EGZtEnzvH2zyPoJh -XGF+Ncu9XwbalnYde10OCvSWAZ5zTCpoLMTvQjWpbCdWXJzCm6G+/hx9upke546H -5IjtYm4dTIVTnc3wvDiODgBKRzOl9rEOCIgOuGtDxRxcQkjrC+xvg5Vkqn7vBUyW -9pHedOU+PoF3DGOM+dqv+eNKBvh9YF9ugFAQBkcG7viZgvGEMGGUpzNgN7XnS1gj -/DPo9mZESOYnKceve2tIC87p2hqjrxOHuI7fkZYeNIcAoa83rBltFXaBDYhWAKS1 -PcXS1/7JzP0ky7d0L6Xbu/If5kqWQpKwUInXtySRkuraVfuK3Bpa+X1XecWi24JY -HVtlNX025xx1ewVzGNCTlWn1skQN2OOoQTV4C8/qFpTW6DTWYurd4+fE0OJFJZQF -buhfXYwmRlVOgN5i77NTIJZJQfYFj38c/Iv5vZBPokO6mffrOTv3MHWVgQARAQAB -tDNSZWQgSGF0LCBJbmMuIChyZWxlYXNlIGtleSAyKSA8c2VjdXJpdHlAcmVkaGF0 -LmNvbT6JAjYEEwECACAFAkrgSTsCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAK -CRAZni+R/UMdUWzpD/9s5SFR/ZF3yjY5VLUFLMXIKUztNN3oc45fyLdTI3+UClKC -2tEruzYjqNHhqAEXa2sN1fMrsuKec61Ll2NfvJjkLKDvgVIh7kM7aslNYVOP6BTf -C/JJ7/ufz3UZmyViH/WDl+AYdgk3JqCIO5w5ryrC9IyBzYv2m0HqYbWfphY3uHw5 -un3ndLJcu8+BGP5F+ONQEGl+DRH58Il9Jp3HwbRa7dvkPgEhfFR+1hI+Btta2C7E -0/2NKzCxZw7Lx3PBRcU92YKyaEihfy/aQKZCAuyfKiMvsmzs+4poIX7I9NQCJpyE -IGfINoZ7VxqHwRn/d5mw2MZTJjbzSf+Um9YJyA0iEEyD6qjriWQRbuxpQXmlAJbh -8okZ4gbVFv1F8MzK+4R8VvWJ0XxgtikSo72fHjwha7MAjqFnOq6eo6fEC/75g3NL -Ght5VdpGuHk0vbdENHMC8wS99e5qXGNDued3hlTavDMlEAHl34q2H9nakTGRF5Ki -JUfNh3DVRGhg8cMIti21njiRh7gyFI2OccATY7bBSr79JhuNwelHuxLrCFpY7V25 -OFktl15jZJaMxuQBqYdBgSay2G0U6D1+7VsWufpzd/Abx1/c3oi9ZaJvW22kAggq -dzdA27UUYjWvx42w9menJwh/0jeQcTecIUd0d0rFcw/c1pvgMMl/Q73yzKgKYw== -=zbHE ------END PGP PUBLIC KEY BLOCK----- -The following public key can be used to verify RPM packages built and -signed by Red Hat, Inc. This key is a supporting (auxiliary) key for -Red Hat products shipped after November 2006 and for all updates to -those products. - -Questions about this key should be sent to security@redhat.com. - ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.2.6 (GNU/Linux) - -mQGiBEVwDGkRBACwPhZIpvkjI8wV9sFTDoqyPLx1ub8Sd/w+YuI5Ovm49mvvEQVT -VLg8FgE5JlST59AbsLDyVtRa9CxIvN5syBVrWWWtHtDnnylFBcqG/A6J3bI4E9/A -UtSL5Zxbav0+utP6f3wOpxQrxc+WIDVgpurdBKAQ3dsobGBqypeX6FXZ5wCgou6C -yZpGIBqosJaDWLzNeOfb/70D/1thLkQyhW3JJ6cHCYJHNfBShvbLWBf6S231mgmu -MyMlt8Kmipc9bw+saaAkSkVsQ/ZbfjrWB7e5kbMruKLVrH+nGhamlHYUGyAPtsPg -Uj/NUSj5BmrCsOkMpn43ngTLssE9MLhSPj2nIHGFv9B+iVLvomDdwnaBRgQ1aK8z -z6MAA/406yf5yVJ/MlTWs1/68VwDhosc9BtU1V5IE0NXgZUAfBJzzfVzzKQq6zJ2 -eZsMLhr96wbsW13zUZt1ing+ulwh2ee4meuJq6h/971JspFY/XBhcfq4qCNqVjsq -SZnWoGdCO6J8CxPIemD2IUHzjoyyeEj3RVydup6pcWZAmhzkKrQzUmVkIEhhdCwg -SW5jLiAoYXV4aWxpYXJ5IGtleSkgPHNlY3VyaXR5QHJlZGhhdC5jb20+iF4EExEC -AB4FAkVwDGkCGwMGCwkIBwMCAxUCAwMWAgECHgECF4AACgkQRWiciC+mWOC1rQCg -ooNLCFOzNPcvhd9Za8C801HmnsYAniCw3yzrCqtjYnxDDxlufH0FVTwX -=d/bm ------END PGP PUBLIC KEY BLOCK----- - diff --git a/roles/openshift_repos/files/online/epel7-kubernetes.repo b/roles/openshift_repos/files/online/epel7-kubernetes.repo deleted file mode 100644 index 1deae2939..000000000 --- a/roles/openshift_repos/files/online/epel7-kubernetes.repo +++ /dev/null @@ -1,6 +0,0 @@ -[maxamillion-epel7-kubernetes] -name=Copr repo for epel7-kubernetes owned by maxamillion -baseurl=http://copr-be.cloud.fedoraproject.org/results/maxamillion/epel7-kubernetes/epel-7-$basearch/ -skip_if_unavailable=True -gpgcheck=0 -enabled=1 diff --git a/roles/openshift_repos/files/online/epel7-openshift.repo b/roles/openshift_repos/files/online/epel7-openshift.repo deleted file mode 100644 index c7629872d..000000000 --- a/roles/openshift_repos/files/online/epel7-openshift.repo +++ /dev/null @@ -1,6 +0,0 @@ -[maxamillion-origin-next] -name=Copr repo for origin-next owned by maxamillion -baseurl=http://copr-be.cloud.fedoraproject.org/results/maxamillion/origin-next/epel-7-$basearch/ -skip_if_unavailable=False -gpgcheck=0 -enabled=1 diff --git a/roles/openshift_repos/files/online/gpg_keys/RPM-GPG-KEY-redhat-beta b/roles/openshift_repos/files/online/gpg_keys/RPM-GPG-KEY-redhat-beta new file mode 100644 index 000000000..7b40671a4 --- /dev/null +++ b/roles/openshift_repos/files/online/gpg_keys/RPM-GPG-KEY-redhat-beta @@ -0,0 +1,61 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.2.6 (GNU/Linux) + +mQINBEmkAzABEAC2/c7bP1lHQ3XScxbIk0LQWe1YOiibQBRLwf8Si5PktgtuPibT +kKpZjw8p4D+fM7jD1WUzUE0X7tXg2l/eUlMM4dw6XJAQ1AmEOtlwSg7rrMtTvM0A +BEtI7Km6fC6sU6RtBMdcqD1cH/6dbsfh8muznVA7UlX+PRBHVzdWzj6y8h84dBjo +gzcbYu9Hezqgj/lLzicqsSZPz9UdXiRTRAIhp8V30BD8uRaaa0KDDnD6IzJv3D9P +xQWbFM4Z12GN9LyeZqmD7bpKzZmXG/3drvfXVisXaXp3M07t3NlBa3Dt8NFIKZ0D +FRXBz5bvzxRVmdH6DtkDWXDPOt+Wdm1rZrCOrySFpBZQRpHw12eo1M1lirANIov7 +Z+V1Qh/aBxj5EUu32u9ZpjAPPNtQF6F/KjaoHHHmEQAuj4DLex4LY646Hv1rcv2i +QFuCdvLKQGSiFBrfZH0j/IX3/0JXQlZzb3MuMFPxLXGAoAV9UP/Sw/WTmAuTzFVm +G13UYFeMwrToOiqcX2VcK0aC1FCcTP2z4JW3PsWvU8rUDRUYfoXovc7eg4Vn5wHt +0NBYsNhYiAAf320AUIHzQZYi38JgVwuJfFu43tJZE4Vig++RQq6tsEx9Ftz3EwRR +fJ9z9mEvEiieZm+vbOvMvIuimFVPSCmLH+bI649K8eZlVRWsx3EXCVb0nQARAQAB +tDBSZWQgSGF0LCBJbmMuIChiZXRhIGtleSAyKSA8c2VjdXJpdHlAcmVkaGF0LmNv +bT6JAjYEEwECACAFAkpSM+cCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCT +ioDK8hVB6/9tEAC0+KmzeKceXQ/GTUoU6jy9vtkFCFrmv+c7ol4XpdTt0QhqBOwy +6m2mKWwmm8KfYfy0cADQ4y/EcoXl7FtFBwYmkCuEQGXhTDn9DvVjhooIq59LEMBQ +OW879RwwzRIZ8ebbjMUjDPF5MfPQqP2LBu9N4KvXlZp4voykwuuaJ+cbsKZR6pZ6 +0RQKPHKP+NgUFC0fff7XY9cuOZZWFAeKRhLN2K7bnRHKxp+kELWb6R9ZfrYwZjWc +MIPbTd1khE53L4NTfpWfAnJRtkPSDOKEGVlVLtLq4HEAxQt07kbslqISRWyXER3u +QOJj64D1ZiIMz6t6uZ424VE4ry9rBR0Jz55cMMx5O/ni9x3xzFUgH8Su2yM0r3jE +Rf24+tbOaPf7tebyx4OKe+JW95hNVstWUDyGbs6K9qGfI/pICuO1nMMFTo6GqzQ6 +DwLZvJ9QdXo7ujEtySZnfu42aycaQ9ZLC2DOCQCUBY350Hx6FLW3O546TAvpTfk0 +B6x+DV7mJQH7MGmRXQsE7TLBJKjq28Cn4tVp04PmybQyTxZdGA/8zY6pPl6xyVMH +V68hSBKEVT/rlouOHuxfdmZva1DhVvUC6Xj7+iTMTVJUAq/4Uyn31P1OJmA2a0PT +CAqWkbJSgKFccsjPoTbLyxhuMSNkEZFHvlZrSK9vnPzmfiRH0Orx3wYpMQ== +=21pb +-----END PGP PUBLIC KEY BLOCK----- +The following public key can be used to verify RPM packages built and +signed by Red Hat, Inc. for this beta using `rpm -K' using the GNU GPG +package. Questions about this key should be sent to security@redhat.com. + + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.0.6 (GNU/Linux) +Comment: For info see http://www.gnupg.org + +mQGiBDySTqsRBACzc7xuCIp10oj5B2PAV4XzDeVxprv/WTMreSNSK+iC0bEz0IBp +Vnn++qtyiXfH+bGIE9jqZgIEnpttWhUOaU5LhcLFzy+m8NWfngIFP9QfGmGAe9Gd +LFeAdhj4RmSG/vgr7vDd83Hz22dv403Ar/sliWO4vDOrMmZBG57WGYTWtwCgkMsi +UUQuJ6slbzKn82w+bYxOlL0EAIylWJGaTkKOTL5DqVR3ik9aT0Dt3FNVYiuhcKBe +II4E3KOIVA9kO8in1IZjx2gs6K2UV+GsoAVANdfKL7l9O+k+J8OxhE74oycvYJxW +QzCgXMZkNcvW5wyXwEMcr6TVd/5BGztcMw8oT3/l2MtAEG/vn1XaWToRSO1XDMDz ++AjUA/4m0mTkN8S4wjzJG8lqN7+quW3UOaiCe8J3SFrrrhE0XbY9cTJI/9nuXHU1 +VjqOSmXQYH2Db7UOroFTBiWhlAedA4O4yuK52AJnvSsHbnJSEmn9rpo5z1Q8F+qI +mDlzriJdrIrVLeDiUeTlpH3kpG38D7007GhXBV72k1gpMoMcpbQ3UmVkIEhhdCwg +SW5jLiAoQmV0YSBUZXN0IFNvZnR3YXJlKSA8cmF3aGlkZUByZWRoYXQuY29tPohX +BBMRAgAXBQI8l5p/BQsHCgMEAxUDAgMWAgECF4AACgkQ/TcmiYl9oHqdeQCfZjw4 +F9sir3XfRAjVe9kYNcQ8hnIAn0WgyT7H5RriWYTOCfauOmd+cAW4iEYEEBECAAYF +AjyXmqQACgkQIZGAzdtCpg5nDQCfepuRUyuVJvhuQkPWySETYvRw+WoAnjAWhx6q +0npMx4OE1JGFi8ymKXktuQENBDySTq4QBADKL/mK7S8E3synxISlu7R6fUvu07Oc +RoX96n0Di6T+BS99hC44XzHjMDhUX2ZzVvYS88EZXoUDDkB/8g7SwZrOJ/QE1zrI +JmSVciNhSYWwqeT40Evs88ajZUfDiNbS/cSC6oui98iS4vxd7sE7IPY+FSx9vuAR +xOa9vBnJY/dx0wADBQQAosm+Iltt2uigC6LJzxNOoIdB5r0GqTC1o5sHCeNqXJhU +ExAG8m74uzMlYVLOpGZi4y4NwwAWvCWC0MWWnnu+LGFy1wKiJKRjhv5F+WkFutY5 +WHV5L44vp9jSIlBCRG+84jheTh8xqhndM9wOfPwWdYYu1vxrB8Tn6kA17PcYfHSI +RgQYEQIABgUCPJJergAKCRD9NyaJiX2geiCPAJ4nEM4NtI9Uj8lONDk6FU86PmoL +yACfb68fBd2pWEzLKsOk9imIobHHpzE= +=gpIn +-----END PGP PUBLIC KEY BLOCK----- diff --git a/roles/openshift_repos/files/online/gpg_keys/RPM-GPG-KEY-redhat-release b/roles/openshift_repos/files/online/gpg_keys/RPM-GPG-KEY-redhat-release new file mode 100644 index 000000000..0f83b622d --- /dev/null +++ b/roles/openshift_repos/files/online/gpg_keys/RPM-GPG-KEY-redhat-release @@ -0,0 +1,63 @@ +The following public key can be used to verify RPM packages built and +signed by Red Hat, Inc. This key is used for packages in Red Hat +products shipped after November 2009, and for all updates to those +products. + +Questions about this key should be sent to security@redhat.com. + +pub 4096R/FD431D51 2009-10-22 Red Hat, Inc. (release key 2) + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.2.6 (GNU/Linux) + +mQINBErgSTsBEACh2A4b0O9t+vzC9VrVtL1AKvUWi9OPCjkvR7Xd8DtJxeeMZ5eF +0HtzIG58qDRybwUe89FZprB1ffuUKzdE+HcL3FbNWSSOXVjZIersdXyH3NvnLLLF +0DNRB2ix3bXG9Rh/RXpFsNxDp2CEMdUvbYCzE79K1EnUTVh1L0Of023FtPSZXX0c +u7Pb5DI5lX5YeoXO6RoodrIGYJsVBQWnrWw4xNTconUfNPk0EGZtEnzvH2zyPoJh +XGF+Ncu9XwbalnYde10OCvSWAZ5zTCpoLMTvQjWpbCdWXJzCm6G+/hx9upke546H +5IjtYm4dTIVTnc3wvDiODgBKRzOl9rEOCIgOuGtDxRxcQkjrC+xvg5Vkqn7vBUyW +9pHedOU+PoF3DGOM+dqv+eNKBvh9YF9ugFAQBkcG7viZgvGEMGGUpzNgN7XnS1gj +/DPo9mZESOYnKceve2tIC87p2hqjrxOHuI7fkZYeNIcAoa83rBltFXaBDYhWAKS1 +PcXS1/7JzP0ky7d0L6Xbu/If5kqWQpKwUInXtySRkuraVfuK3Bpa+X1XecWi24JY +HVtlNX025xx1ewVzGNCTlWn1skQN2OOoQTV4C8/qFpTW6DTWYurd4+fE0OJFJZQF +buhfXYwmRlVOgN5i77NTIJZJQfYFj38c/Iv5vZBPokO6mffrOTv3MHWVgQARAQAB +tDNSZWQgSGF0LCBJbmMuIChyZWxlYXNlIGtleSAyKSA8c2VjdXJpdHlAcmVkaGF0 +LmNvbT6JAjYEEwECACAFAkrgSTsCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAK +CRAZni+R/UMdUWzpD/9s5SFR/ZF3yjY5VLUFLMXIKUztNN3oc45fyLdTI3+UClKC +2tEruzYjqNHhqAEXa2sN1fMrsuKec61Ll2NfvJjkLKDvgVIh7kM7aslNYVOP6BTf +C/JJ7/ufz3UZmyViH/WDl+AYdgk3JqCIO5w5ryrC9IyBzYv2m0HqYbWfphY3uHw5 +un3ndLJcu8+BGP5F+ONQEGl+DRH58Il9Jp3HwbRa7dvkPgEhfFR+1hI+Btta2C7E +0/2NKzCxZw7Lx3PBRcU92YKyaEihfy/aQKZCAuyfKiMvsmzs+4poIX7I9NQCJpyE +IGfINoZ7VxqHwRn/d5mw2MZTJjbzSf+Um9YJyA0iEEyD6qjriWQRbuxpQXmlAJbh +8okZ4gbVFv1F8MzK+4R8VvWJ0XxgtikSo72fHjwha7MAjqFnOq6eo6fEC/75g3NL +Ght5VdpGuHk0vbdENHMC8wS99e5qXGNDued3hlTavDMlEAHl34q2H9nakTGRF5Ki +JUfNh3DVRGhg8cMIti21njiRh7gyFI2OccATY7bBSr79JhuNwelHuxLrCFpY7V25 +OFktl15jZJaMxuQBqYdBgSay2G0U6D1+7VsWufpzd/Abx1/c3oi9ZaJvW22kAggq +dzdA27UUYjWvx42w9menJwh/0jeQcTecIUd0d0rFcw/c1pvgMMl/Q73yzKgKYw== +=zbHE +-----END PGP PUBLIC KEY BLOCK----- +The following public key can be used to verify RPM packages built and +signed by Red Hat, Inc. This key is a supporting (auxiliary) key for +Red Hat products shipped after November 2006 and for all updates to +those products. + +Questions about this key should be sent to security@redhat.com. + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.2.6 (GNU/Linux) + +mQGiBEVwDGkRBACwPhZIpvkjI8wV9sFTDoqyPLx1ub8Sd/w+YuI5Ovm49mvvEQVT +VLg8FgE5JlST59AbsLDyVtRa9CxIvN5syBVrWWWtHtDnnylFBcqG/A6J3bI4E9/A +UtSL5Zxbav0+utP6f3wOpxQrxc+WIDVgpurdBKAQ3dsobGBqypeX6FXZ5wCgou6C +yZpGIBqosJaDWLzNeOfb/70D/1thLkQyhW3JJ6cHCYJHNfBShvbLWBf6S231mgmu +MyMlt8Kmipc9bw+saaAkSkVsQ/ZbfjrWB7e5kbMruKLVrH+nGhamlHYUGyAPtsPg +Uj/NUSj5BmrCsOkMpn43ngTLssE9MLhSPj2nIHGFv9B+iVLvomDdwnaBRgQ1aK8z +z6MAA/406yf5yVJ/MlTWs1/68VwDhosc9BtU1V5IE0NXgZUAfBJzzfVzzKQq6zJ2 +eZsMLhr96wbsW13zUZt1ing+ulwh2ee4meuJq6h/971JspFY/XBhcfq4qCNqVjsq +SZnWoGdCO6J8CxPIemD2IUHzjoyyeEj3RVydup6pcWZAmhzkKrQzUmVkIEhhdCwg +SW5jLiAoYXV4aWxpYXJ5IGtleSkgPHNlY3VyaXR5QHJlZGhhdC5jb20+iF4EExEC +AB4FAkVwDGkCGwMGCwkIBwMCAxUCAwMWAgECHgECF4AACgkQRWiciC+mWOC1rQCg +ooNLCFOzNPcvhd9Za8C801HmnsYAniCw3yzrCqtjYnxDDxlufH0FVTwX +=d/bm +-----END PGP PUBLIC KEY BLOCK----- + diff --git a/roles/openshift_repos/files/online/oso-rhui-rhel-7-extras.repo b/roles/openshift_repos/files/online/oso-rhui-rhel-7-extras.repo deleted file mode 100644 index cfe41f691..000000000 --- a/roles/openshift_repos/files/online/oso-rhui-rhel-7-extras.repo +++ /dev/null @@ -1,23 +0,0 @@ -[oso-rhui-rhel-server-extras] -name=OpenShift Online RHUI Mirror RH Enterprise Linux - Extras -baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-extras/ - https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-extras/ -enabled=1 -gpgcheck=1 -gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release,file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-beta -failovermethod=priority -sslverify=False -sslclientcert=/var/lib/yum/client-cert.pem -sslclientkey=/var/lib/yum/client-key.pem - -[oso-rhui-rhel-server-extras-htb] -name=OpenShift Online RHUI Mirror RH Enterprise Linux - Extras HTB -baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-extras-htb/ - https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-extras-htb/ -enabled=0 -gpgcheck=1 -gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release,file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-beta -failovermethod=priority -sslverify=False -sslclientcert=/var/lib/yum/client-cert.pem -sslclientkey=/var/lib/yum/client-key.pem diff --git a/roles/openshift_repos/files/online/oso-rhui-rhel-7-server.repo b/roles/openshift_repos/files/online/oso-rhui-rhel-7-server.repo deleted file mode 100644 index ddc93193d..000000000 --- a/roles/openshift_repos/files/online/oso-rhui-rhel-7-server.repo +++ /dev/null @@ -1,21 +0,0 @@ -[oso-rhui-rhel-server-releases] -name=OpenShift Online RHUI Mirror RH Enterprise Linux 7 -baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-releases/ - https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-releases/ -enabled=1 -gpgcheck=1 -gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release -sslverify=False -sslclientcert=/var/lib/yum/client-cert.pem -sslclientkey=/var/lib/yum/client-key.pem - -[oso-rhui-rhel-server-releases-optional] -name=OpenShift Online RHUI Mirror RH Enterprise Linux 7 - Optional -baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-releases-optional/ - https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-releases-optional/ -enabled=1 -gpgcheck=1 -gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release -sslverify=False -sslclientcert=/var/lib/yum/client-cert.pem -sslclientkey=/var/lib/yum/client-key.pem diff --git a/roles/openshift_repos/files/online/repos/epel7-openshift.repo b/roles/openshift_repos/files/online/repos/epel7-openshift.repo new file mode 100644 index 000000000..c7629872d --- /dev/null +++ b/roles/openshift_repos/files/online/repos/epel7-openshift.repo @@ -0,0 +1,6 @@ +[maxamillion-origin-next] +name=Copr repo for origin-next owned by maxamillion +baseurl=http://copr-be.cloud.fedoraproject.org/results/maxamillion/origin-next/epel-7-$basearch/ +skip_if_unavailable=False +gpgcheck=0 +enabled=1 diff --git a/roles/openshift_repos/files/online/repos/oso-rhui-rhel-7-extras.repo b/roles/openshift_repos/files/online/repos/oso-rhui-rhel-7-extras.repo new file mode 100644 index 000000000..cfe41f691 --- /dev/null +++ b/roles/openshift_repos/files/online/repos/oso-rhui-rhel-7-extras.repo @@ -0,0 +1,23 @@ +[oso-rhui-rhel-server-extras] +name=OpenShift Online RHUI Mirror RH Enterprise Linux - Extras +baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-extras/ + https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-extras/ +enabled=1 +gpgcheck=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release,file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-beta +failovermethod=priority +sslverify=False +sslclientcert=/var/lib/yum/client-cert.pem +sslclientkey=/var/lib/yum/client-key.pem + +[oso-rhui-rhel-server-extras-htb] +name=OpenShift Online RHUI Mirror RH Enterprise Linux - Extras HTB +baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-extras-htb/ + https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-extras-htb/ +enabled=0 +gpgcheck=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release,file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-beta +failovermethod=priority +sslverify=False +sslclientcert=/var/lib/yum/client-cert.pem +sslclientkey=/var/lib/yum/client-key.pem diff --git a/roles/openshift_repos/files/online/repos/oso-rhui-rhel-7-server.repo b/roles/openshift_repos/files/online/repos/oso-rhui-rhel-7-server.repo new file mode 100644 index 000000000..ddc93193d --- /dev/null +++ b/roles/openshift_repos/files/online/repos/oso-rhui-rhel-7-server.repo @@ -0,0 +1,21 @@ +[oso-rhui-rhel-server-releases] +name=OpenShift Online RHUI Mirror RH Enterprise Linux 7 +baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-releases/ + https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-releases/ +enabled=1 +gpgcheck=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release +sslverify=False +sslclientcert=/var/lib/yum/client-cert.pem +sslclientkey=/var/lib/yum/client-key.pem + +[oso-rhui-rhel-server-releases-optional] +name=OpenShift Online RHUI Mirror RH Enterprise Linux 7 - Optional +baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-releases-optional/ + https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-releases-optional/ +enabled=1 +gpgcheck=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release +sslverify=False +sslclientcert=/var/lib/yum/client-cert.pem +sslclientkey=/var/lib/yum/client-key.pem diff --git a/roles/openshift_repos/files/online/repos/rhel-7-libra-candidate.repo b/roles/openshift_repos/files/online/repos/rhel-7-libra-candidate.repo new file mode 100644 index 000000000..b4215679f --- /dev/null +++ b/roles/openshift_repos/files/online/repos/rhel-7-libra-candidate.repo @@ -0,0 +1,11 @@ +[rhel-7-libra-candidate] +name=rhel-7-libra-candidate - \$basearch +baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhel-7-libra-candidate/\$basearch/ + https://mirror.ops.rhcloud.com/libra/rhel-7-libra-candidate/\$basearch/ +gpgkey=https://mirror.ops.rhcloud.com/libra/RPM-GPG-KEY-redhat-openshifthosted +skip_if_unavailable=True +gpgcheck=0 +enabled=1 +sslclientcert=/var/lib/yum/client-cert.pem +sslclientkey=/var/lib/yum/client-key.pem +sslverify=False diff --git a/roles/openshift_repos/files/online/rhel-7-libra-candidate.repo b/roles/openshift_repos/files/online/rhel-7-libra-candidate.repo deleted file mode 100644 index b4215679f..000000000 --- a/roles/openshift_repos/files/online/rhel-7-libra-candidate.repo +++ /dev/null @@ -1,11 +0,0 @@ -[rhel-7-libra-candidate] -name=rhel-7-libra-candidate - \$basearch -baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhel-7-libra-candidate/\$basearch/ - https://mirror.ops.rhcloud.com/libra/rhel-7-libra-candidate/\$basearch/ -gpgkey=https://mirror.ops.rhcloud.com/libra/RPM-GPG-KEY-redhat-openshifthosted -skip_if_unavailable=True -gpgcheck=0 -enabled=1 -sslclientcert=/var/lib/yum/client-cert.pem -sslclientkey=/var/lib/yum/client-key.pem -sslverify=False diff --git a/roles/openshift_repos/files/origin/repos/maxamillion-origin-next-epel-7.repo b/roles/openshift_repos/files/origin/repos/maxamillion-origin-next-epel-7.repo new file mode 100644 index 000000000..0b21e0a65 --- /dev/null +++ b/roles/openshift_repos/files/origin/repos/maxamillion-origin-next-epel-7.repo @@ -0,0 +1,7 @@ +[maxamillion-origin-next] +name=Copr repo for origin-next owned by maxamillion +baseurl=https://copr-be.cloud.fedoraproject.org/results/maxamillion/origin-next/epel-7-$basearch/ +skip_if_unavailable=True +gpgcheck=1 +gpgkey=https://copr-be.cloud.fedoraproject.org/results/maxamillion/origin-next/pubkey.gpg +enabled=1 diff --git a/roles/openshift_repos/tasks/main.yaml b/roles/openshift_repos/tasks/main.yaml index bb1551d37..12e98b7a1 100644 --- a/roles/openshift_repos/tasks/main.yaml +++ b/roles/openshift_repos/tasks/main.yaml @@ -10,10 +10,6 @@ - assert: that: openshift_deployment_type in known_openshift_deployment_types -# TODO: remove this when origin support actually works -- fail: msg="OpenShift Origin support is not currently enabled" - when: openshift_deployment_type == 'origin' - - name: Ensure libselinux-python is installed yum: pkg: libselinux-python @@ -36,17 +32,15 @@ path: "/etc/yum.repos.d/{{ item | basename }}" state: absent with_fileglob: - - '*/*' - when: not (item | search("/files/" + openshift_deployment_type + "/")) and (item | search(".repo$")) + - '*/repos/*' + when: not (item | search("/files/" ~ openshift_deployment_type ~ "/repos")) - name: Configure gpg keys if needed copy: src={{ item }} dest=/etc/pki/rpm-gpg/ with_fileglob: - - "{{ openshift_deployment_type }}/*" - when: item | basename | match("RPM-GPG-KEY-") + - "{{ openshift_deployment_type }}/gpg_keys/*" - name: Configure yum repositories copy: src={{ item }} dest=/etc/yum.repos.d/ with_fileglob: - - "{{ openshift_deployment_type }}/*" - when: item | basename | search(".*\.repo$") + - "{{ openshift_deployment_type }}/repos/*" diff --git a/roles/openshift_repos/templates/yum_repo.j2 b/roles/openshift_repos/templates/yum_repo.j2 index 7ea2c7460..2d9243545 100644 --- a/roles/openshift_repos/templates/yum_repo.j2 +++ b/roles/openshift_repos/templates/yum_repo.j2 @@ -1,4 +1,3 @@ -# {{ ansible_managed }} {% for repo in openshift_additional_repos %} [{{ repo.id }}] name={{ repo.name | default(repo.id) }} diff --git a/roles/openshift_sdn_master/tasks/main.yml b/roles/openshift_sdn_master/tasks/main.yml index f2d61043b..77e7a80ba 100644 --- a/roles/openshift_sdn_master/tasks/main.yml +++ b/roles/openshift_sdn_master/tasks/main.yml @@ -12,12 +12,21 @@ yum: pkg: openshift-sdn-master state: installed + register: install_result +- name: Reload systemd units + command: systemctl daemon-reload + when: install_result | changed + +# TODO: we should probably generate certs specifically for sdn - name: Configure openshift-sdn-master settings lineinfile: dest: /etc/sysconfig/openshift-sdn-master regexp: '^OPTIONS=' - line: "OPTIONS=\"-v={{ openshift.master_sdn.debug_level }}\"" + line: "OPTIONS=\"-v={{ openshift.master_sdn.debug_level }} -etcd-endpoints={{ openshift_sdn_master_url}} + -etcd-cafile={{ openshift_cert_dir }}/ca/ca.crt + -etcd-certfile={{ openshift_cert_dir }}/openshift-client/cert.crt + -etcd-keyfile={{ openshift_cert_dir }}/openshift-client/key.key\"" notify: - restart openshift-sdn-master diff --git a/roles/openshift_sdn_node/tasks/main.yml b/roles/openshift_sdn_node/tasks/main.yml index 729c28879..c2329dd6f 100644 --- a/roles/openshift_sdn_node/tasks/main.yml +++ b/roles/openshift_sdn_node/tasks/main.yml @@ -9,9 +9,15 @@ yum: pkg: openshift-sdn-node state: installed + register: install_result + +- name: Reload systemd units + command: systemctl daemon-reload + when: install_result | changed # TODO: we are specifying -hostname= for OPTIONS as a workaround for # openshift-sdn-node not properly detecting the hostname. +# TODO: we should probably generate certs specifically for sdn - name: Configure openshift-sdn-node settings lineinfile: dest: /etc/sysconfig/openshift-sdn-node @@ -20,7 +26,10 @@ backrefs: yes with_items: - regex: '^(OPTIONS=)' - line: '\1"-v={{ openshift.node_sdn.debug_level }} -hostname={{ openshift.common.hostname }}"' + line: '\1"-v={{ openshift.node_sdn.debug_level }} -hostname={{ openshift.common.hostname }} + -etcd-cafile={{ openshift_node_cert_dir }}/ca.crt + -etcd-certfile={{ openshift_node_cert_dir }}/client.crt + -etcd-keyfile={{ openshift_node_cert_dir }}/client.key\"' - regex: '^(MASTER_URL=)' line: '\1"{{ openshift_sdn_master_url }}"' - regex: '^(MINION_IP=)' diff --git a/roles/os_firewall/library/os_firewall_manage_iptables.py b/roles/os_firewall/library/os_firewall_manage_iptables.py index 90588d2ae..9d0af497d 100755 --- a/roles/os_firewall/library/os_firewall_manage_iptables.py +++ b/roles/os_firewall/library/os_firewall_manage_iptables.py @@ -270,4 +270,5 @@ def main(): # import module snippets from ansible.module_utils.basic import * -main() +if __name__ == '__main__': + main() -- cgit v1.2.3 From 34326ef782bcba8632738a40d3948bb23a3915dc Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Wed, 15 Apr 2015 09:40:38 -0400 Subject: fix missed absolute path reference to mktemp --- playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_network.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_network.yml b/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_network.yml index 1cd83f7be..a320e681e 100644 --- a/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_network.yml +++ b/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_network.yml @@ -6,7 +6,7 @@ failed_when: "net_info_result.rc != 0 and 'error: Network not found:' not in net_info_result.stderr" - name: Create a temp directory for the template xml file - command: "/usr/bin/mktemp -d /tmp/openshift-ansible-XXXXXXX" + command: "mktemp -d /tmp/openshift-ansible-XXXXXXX" register: mktemp when: net_info_result.rc == 1 -- cgit v1.2.3 From bc0b703b70d9f36b3ad841409454dd21b1934d92 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Wed, 15 Apr 2015 17:09:30 -0400 Subject: explicitly use python2 for libvirt dynamic inventory --- inventory/libvirt/hosts/libvirt_generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inventory/libvirt/hosts/libvirt_generic.py b/inventory/libvirt/hosts/libvirt_generic.py index 0a98e2af3..2e1437903 100755 --- a/inventory/libvirt/hosts/libvirt_generic.py +++ b/inventory/libvirt/hosts/libvirt_generic.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ libvirt external inventory script -- cgit v1.2.3 From 83ed87d41536f7006b3858a65a587263e3fd2b14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9na=C3=AFc=20Huard?= Date: Wed, 15 Apr 2015 23:17:30 +0200 Subject: Move `virsh pool-refresh` The `pool-refresh` command is used to ask libvirt to rescan the content of a volume pool. This is used to make `libvirt` take into account volumes that were created outside of livirt control i.e.: not with a `virsh` command. `pool-refresh` is useless after a `pool-create` as the content is scanned at creation. `pool-refresh` is mandatory after having created files inside an existing pool. --- .../openshift-cluster/tasks/configure_libvirt_storage_pool.yml | 4 ---- playbooks/libvirt/openshift-cluster/tasks/launch_instances.yml | 3 +++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_storage_pool.yml b/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_storage_pool.yml index 817acb250..b49879c6a 100644 --- a/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_storage_pool.yml +++ b/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_storage_pool.yml @@ -21,7 +21,3 @@ - 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 }}' when: pool_info_result.rc == 1 - -- name: Refresh the libvirt storage pool for openshift - command: 'virsh -c {{ libvirt_uri }} pool-refresh {{ libvirt_storage_pool }}' - when: pool_info_result.rc == 1 diff --git a/playbooks/libvirt/openshift-cluster/tasks/launch_instances.yml b/playbooks/libvirt/openshift-cluster/tasks/launch_instances.yml index 96d440096..359d0b2f3 100644 --- a/playbooks/libvirt/openshift-cluster/tasks/launch_instances.yml +++ b/playbooks/libvirt/openshift-cluster/tasks/launch_instances.yml @@ -36,6 +36,9 @@ creates: '{{ os_libvirt_storage_pool_path }}/{{ item }}_cloud-init.iso' with_items: instances +- 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 {{ os_libvirt_storage_pool }} {{ item }}.qcow2 10G --format qcow2 --backing-vol {{ image_name }} --backing-vol-format qcow2' with_items: instances -- cgit v1.2.3 From b71037de41baf06889b7a875a0e8914f940ecc2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9na=C3=AFc=20Huard?= Date: Wed, 15 Apr 2015 23:37:24 +0200 Subject: Make the error message checks locale proof MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On a computer which has a locale set, the error messages look like this: ``` $ virsh net-info foo erreur :impossible de récupérer le réseau « foo » erreur :Réseau non trouvé : no network with matching name 'foo' ``` ``` $ virsh pool-info foo erreur :impossible de récupérer le pool « foo » erreur :Pool de stockage introuvable : no storage pool with matching name 'foo' ``` The classical way to make those tests locale proof is to force a given locale. Like this: ``` $ LANG=POSIX virsh net-info foo error: failed to get network 'foo' error: Réseau non trouvé : no network with matching name 'foo' ``` ``` $ LANG=POSIX virsh pool-info foo error: failed to get pool 'foo' error: Pool de stockage introuvable : no storage pool with matching name 'foo' ``` It looks like the "Network not found" or "Storage pool not found" parts of the message are generated by the `libvirtd` daemon and are not subject to the locale of the `virsh` client. The clean fix consists in patching `libvirt` so that `virsh` sends its locale to the `libvirtd` daemon. But in the mean time, it is safer to have our playbook match the part of the message which is not subject to the daemon locale. --- playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_network.yml | 2 +- .../libvirt/openshift-cluster/tasks/configure_libvirt_storage_pool.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_network.yml b/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_network.yml index a320e681e..3117d9edc 100644 --- a/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_network.yml +++ b/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_network.yml @@ -3,7 +3,7 @@ command: "virsh -c {{ libvirt_uri }} net-info {{ libvirt_network }}" register: net_info_result changed_when: False - failed_when: "net_info_result.rc != 0 and 'error: Network not found:' not in net_info_result.stderr" + failed_when: "net_info_result.rc != 0 and 'no network with matching name' not in net_info_result.stderr" - name: Create a temp directory for the template xml file command: "mktemp -d /tmp/openshift-ansible-XXXXXXX" diff --git a/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_storage_pool.yml b/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_storage_pool.yml index 817acb250..10715f2b5 100644 --- a/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_storage_pool.yml +++ b/playbooks/libvirt/openshift-cluster/tasks/configure_libvirt_storage_pool.yml @@ -16,7 +16,7 @@ command: "virsh -c {{ libvirt_uri }} pool-info {{ libvirt_storage_pool }}" register: pool_info_result changed_when: False - failed_when: "pool_info_result.rc != 0 and 'error: Storage pool not found:' not in pool_info_result.stderr" + failed_when: "pool_info_result.rc != 0 and 'no storage pool with matching name' not in pool_info_result.stderr" - 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 }}' -- cgit v1.2.3 From aaee17b0fc8feddf31d4e5b46a1bfe2f8dabf16b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9na=C3=AFc=20Huard?= Date: Thu, 16 Apr 2015 00:26:45 +0200 Subject: Fix libvirt metadata used to store ansible tags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to https://libvirt.org/formatdomain.html#elementsMetadata , the `metadata` tag can contain only one top-level element per namespace. Because of that, libvirt stored only the `deployment-type-{{ deployment_type }}` tag. As a consequence, the dynamic inventory reported no `env-{{ cluster }}` group. This is problematic for the `terminate.yml` playbook which iterates over `groups['tag-env-{{ cluster-id }}]` The symptom is that `oo_hosts_to_terminate` was not defined. In the end, as Ansible couldn’t iterate on the value of `groups['oo_hosts_to_terminate']`, it iterated on its letters: ``` TASK: [Destroy VMs] *********************************************************** failed: [localhost] => (item=['g', 'destroy']) => {"failed": true, "item": ["g", "destroy"]} msg: virtual machine g not found failed: [localhost] => (item=['g', 'undefine']) => {"failed": true, "item": ["g", "undefine"]} msg: virtual machine g not found failed: [localhost] => (item=['r', 'destroy']) => {"failed": true, "item": ["r", "destroy"]} msg: virtual machine r not found failed: [localhost] => (item=['r', 'undefine']) => {"failed": true, "item": ["r", "undefine"]} msg: virtual machine r not found failed: [localhost] => (item=['o', 'destroy']) => {"failed": true, "item": ["o", "destroy"]} msg: virtual machine o not found failed: [localhost] => (item=['o', 'undefine']) => {"failed": true, "item": ["o", "undefine"]} msg: virtual machine o not found failed: [localhost] => (item=['u', 'destroy']) => {"failed": true, "item": ["u", "destroy"]} msg: virtual machine u not found failed: [localhost] => (item=['u', 'undefine']) => {"failed": true, "item": ["u", "undefine"]} msg: virtual machine u not found failed: [localhost] => (item=['p', 'destroy']) => {"failed": true, "item": ["p", "destroy"]} msg: virtual machine p not found failed: [localhost] => (item=['p', 'undefine']) => {"failed": true, "item": ["p", "undefine"]} msg: virtual machine p not found failed: [localhost] => (item=['s', 'destroy']) => {"failed": true, "item": ["s", "destroy"]} msg: virtual machine s not found failed: [localhost] => (item=['s', 'undefine']) => {"failed": true, "item": ["s", "undefine"]} msg: virtual machine s not found failed: [localhost] => (item=['[', 'destroy']) => {"failed": true, "item": ["[", "destroy"]} msg: virtual machine [ not found failed: [localhost] => (item=['[', 'undefine']) => {"failed": true, "item": ["[", "undefine"]} msg: virtual machine [ not found failed: [localhost] => (item=["'", 'destroy']) => {"failed": true, "item": ["'", "destroy"]} msg: virtual machine ' not found failed: [localhost] => (item=["'", 'undefine']) => {"failed": true, "item": ["'", "undefine"]} msg: virtual machine ' not found failed: [localhost] => (item=['o', 'destroy']) => {"failed": true, "item": ["o", "destroy"]} msg: virtual machine o not found failed: [localhost] => (item=['o', 'undefine']) => {"failed": true, "item": ["o", "undefine"]} msg: virtual machine o not found etc… ``` --- inventory/libvirt/hosts/libvirt_generic.py | 4 ++-- playbooks/libvirt/openshift-cluster/templates/domain.xml | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/inventory/libvirt/hosts/libvirt_generic.py b/inventory/libvirt/hosts/libvirt_generic.py index 0a98e2af3..4652f112e 100755 --- a/inventory/libvirt/hosts/libvirt_generic.py +++ b/inventory/libvirt/hosts/libvirt_generic.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ libvirt external inventory script @@ -131,7 +131,7 @@ class LibvirtInventory(object): root = ET.fromstring(domain.XMLDesc()) ns = {'ansible': 'https://github.com/ansible/ansible'} - for tag_elem in root.findall('./metadata/ansible:tag', ns): + for tag_elem in root.findall('./metadata/ansible:tags/ansible:tag', ns): tag = tag_elem.text self.push(inventory, "tag_%s" % tag, domain_name) self.push(hostvars, 'libvirt_tags', tag) diff --git a/playbooks/libvirt/openshift-cluster/templates/domain.xml b/playbooks/libvirt/openshift-cluster/templates/domain.xml index 8cb017367..7656249da 100644 --- a/playbooks/libvirt/openshift-cluster/templates/domain.xml +++ b/playbooks/libvirt/openshift-cluster/templates/domain.xml @@ -2,10 +2,12 @@ {{ item }} 1 - deployment-type-{{ deployment_type }} - env-{{ cluster }} - env-host-type-{{ cluster }}-openshift-{{ type }} - host-type-{{ type }} + + deployment-type-{{ deployment_type }} + env-{{ cluster }} + env-host-type-{{ cluster }}-openshift-{{ type }} + host-type-{{ type }} + 1 2 -- cgit v1.2.3 From dbb252bc04a6488c1fde05dbc325b246fd4a651e Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Wed, 15 Apr 2015 20:52:38 -0400 Subject: Fixup typos --- playbooks/aws/openshift-cluster/launch.yml | 2 +- playbooks/gce/openshift-cluster/launch.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/playbooks/aws/openshift-cluster/launch.yml b/playbooks/aws/openshift-cluster/launch.yml index e7125ea0c..a0de00fc3 100644 --- a/playbooks/aws/openshift-cluster/launch.yml +++ b/playbooks/aws/openshift-cluster/launch.yml @@ -7,7 +7,7 @@ - vars.yml tasks: - fail: - msg: Deployment type not supported for libvirt provider yet + msg: Deployment type not supported for aws provider yet when: deployment_type == 'enterprise' - include: ../../common/openshift-cluster/set_master_launch_facts_tasks.yml diff --git a/playbooks/gce/openshift-cluster/launch.yml b/playbooks/gce/openshift-cluster/launch.yml index 34a5a0b94..771f51e91 100644 --- a/playbooks/gce/openshift-cluster/launch.yml +++ b/playbooks/gce/openshift-cluster/launch.yml @@ -6,7 +6,7 @@ vars_files: - vars.yml tasks: - - fail: msg="Deployment type not supported for libvirt provider yet" + - fail: msg="Deployment type not supported for gce provider yet" when: deployment_type == 'enterprise' - include: ../../common/openshift-cluster/set_master_launch_facts_tasks.yml -- cgit v1.2.3 From 7ffc6a28edad3f20604dd13e16b8f57cf670b25e Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Thu, 16 Apr 2015 13:08:42 -0400 Subject: Adding ansible-tower-cli rpm to tower --- roles/ansible_tower/tasks/main.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/ansible_tower/tasks/main.yaml b/roles/ansible_tower/tasks/main.yaml index e9bde9478..1d75a95e6 100644 --- a/roles/ansible_tower/tasks/main.yaml +++ b/roles/ansible_tower/tasks/main.yaml @@ -9,6 +9,7 @@ - ansible - telnet - ack + - python-ansible-tower-cli - name: download Tower setup get_url: url=http://releases.ansible.com/ansible-tower/setup/ansible-tower-setup-2.1.1.tar.gz dest=/opt/ force=no -- cgit v1.2.3 From 735355f75ab24d14aadbc30ec334dadc789028db Mon Sep 17 00:00:00 2001 From: Troy Dawson Date: Thu, 16 Apr 2015 16:01:26 -0500 Subject: update tower ami image to latest libra-ops-rhel7 --- playbooks/aws/ansible-tower/launch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playbooks/aws/ansible-tower/launch.yml b/playbooks/aws/ansible-tower/launch.yml index 4c29fa833..56235bc8a 100644 --- a/playbooks/aws/ansible-tower/launch.yml +++ b/playbooks/aws/ansible-tower/launch.yml @@ -6,7 +6,7 @@ vars: inst_region: us-east-1 - rhel7_ami: ami-a24e30ca + rhel7_ami: ami-906240f8 user_data_file: user_data.txt vars_files: -- cgit v1.2.3 From 3d414f3c803139cb7396562bb593cd75c22b80ea Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Mon, 20 Apr 2015 23:39:40 -0400 Subject: Fix typos... master not mater --- README_OSE.md | 2 +- inventory/byo/hosts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README_OSE.md b/README_OSE.md index 6d4a9ba92..cd0b9f7a6 100644 --- a/README_OSE.md +++ b/README_OSE.md @@ -63,7 +63,7 @@ option to ansible-playbook. ```ini # This is an example of a bring your own (byo) host inventory -# Create an OSEv3 group that contains the maters and nodes groups +# Create an OSEv3 group that contains the masters and nodes groups [OSEv3:children] masters nodes diff --git a/inventory/byo/hosts b/inventory/byo/hosts index e9af5e571..98dbb4fd8 100644 --- a/inventory/byo/hosts +++ b/inventory/byo/hosts @@ -1,6 +1,6 @@ # This is an example of a bring your own (byo) host inventory -# Create an OSEv3 group that contains the maters and nodes groups +# Create an OSEv3 group that contains the masters and nodes groups [OSEv3:children] masters nodes -- cgit v1.2.3 From 0ecefd20d06e67823cb033d4ac7ec4b57e613af6 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Mon, 20 Apr 2015 23:45:15 -0400 Subject: Remove deployment-type tags --- playbooks/aws/openshift-cluster/tasks/launch_instances.yml | 3 +-- playbooks/gce/openshift-cluster/tasks/launch_instances.yml | 1 - playbooks/libvirt/openshift-cluster/templates/domain.xml | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/playbooks/aws/openshift-cluster/tasks/launch_instances.yml b/playbooks/aws/openshift-cluster/tasks/launch_instances.yml index 58b4082df..77ee25424 100644 --- a/playbooks/aws/openshift-cluster/tasks/launch_instances.yml +++ b/playbooks/aws/openshift-cluster/tasks/launch_instances.yml @@ -26,7 +26,6 @@ env: "{{ env }}" host-type: "{{ host_type }}" env-host-type: "{{ env_host_type }}" - deployment-type: "{{ deployment_type }}" register: ec2 - name: Add Name tag to instances @@ -39,7 +38,7 @@ 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 }}, tag_deployment-type_{{ deployment_type }} + 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: diff --git a/playbooks/gce/openshift-cluster/tasks/launch_instances.yml b/playbooks/gce/openshift-cluster/tasks/launch_instances.yml index a68edefae..9a9848f05 100644 --- a/playbooks/gce/openshift-cluster/tasks/launch_instances.yml +++ b/playbooks/gce/openshift-cluster/tasks/launch_instances.yml @@ -15,7 +15,6 @@ - env-{{ cluster }} - host-type-{{ type }} - env-host-type-{{ cluster }}-openshift-{{ type }} - - deployment-type-{{ deployment_type }} register: gce - name: Add new instances to groups and set variables needed diff --git a/playbooks/libvirt/openshift-cluster/templates/domain.xml b/playbooks/libvirt/openshift-cluster/templates/domain.xml index 7656249da..df200e374 100644 --- a/playbooks/libvirt/openshift-cluster/templates/domain.xml +++ b/playbooks/libvirt/openshift-cluster/templates/domain.xml @@ -3,7 +3,6 @@ 1 - deployment-type-{{ deployment_type }} env-{{ cluster }} env-host-type-{{ cluster }}-openshift-{{ type }} host-type-{{ type }} -- cgit v1.2.3 From c5d6e5704bb91ada69cea88a07b4562d48f602d8 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Mon, 20 Apr 2015 23:49:17 -0400 Subject: Add TODO for making node certificate sync more efficient --- playbooks/common/openshift-node/config.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/playbooks/common/openshift-node/config.yml b/playbooks/common/openshift-node/config.yml index c82d69c28..d053d959a 100644 --- a/playbooks/common/openshift-node/config.yml +++ b/playbooks/common/openshift-node/config.yml @@ -44,6 +44,9 @@ roles: - openshift_register_nodes tasks: + # TODO: update so that we only sync necessary configs/directories, currently + # we sync for all nodes in oo_nodes_to_config. We will need to inspect the + # configs on the nodes to make the determination on whether to sync or not. - name: Create the temp directory on the master file: path: "{{ sync_tmpdir }}" -- cgit v1.2.3 From 3a49a125d8a34ac1dce3eb56f1de0cb4c415a9a8 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Wed, 15 Apr 2015 11:08:09 -0400 Subject: Fix common node config playbook when ansible is run on the first master --- playbooks/common/openshift-node/config.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/playbooks/common/openshift-node/config.yml b/playbooks/common/openshift-node/config.yml index c82d69c28..75eb5ae1b 100644 --- a/playbooks/common/openshift-node/config.yml +++ b/playbooks/common/openshift-node/config.yml @@ -69,12 +69,6 @@ with_items: openshift_nodes changed_when: False - - name: Remove the temp directory on the master - file: - path: "{{ sync_tmpdir }}" - state: absent - changed_when: False - - name: Configure node instances hosts: oo_nodes_to_config @@ -103,8 +97,17 @@ group_by: key=oo_nodes_deployment_type_{{ openshift.common.deployment_type }} changed_when: False +- name: Delete the temporary directory on the master + hosts: oo_first_master + gather_facts: no + vars: + sync_tmpdir: "{{ hostvars.localhost.mktemp.stdout }}" + tasks: + - file: name={{ sync_tmpdir }} state=absent + changed_when: False + -- name: Delete temporary directory +- name: Delete temporary directory on localhost hosts: localhost gather_facts: no tasks: -- cgit v1.2.3 From 06cfccafd93995a59cf3a620e460d0cb07328188 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Wed, 15 Apr 2015 16:17:09 -0400 Subject: Fix issue with nodes being set to an empty string when generating master config --- roles/openshift_master/tasks/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/openshift_master/tasks/main.yml b/roles/openshift_master/tasks/main.yml index 1b1210007..3ea485610 100644 --- a/roles/openshift_master/tasks/main.yml +++ b/roles/openshift_master/tasks/main.yml @@ -61,8 +61,8 @@ --master={{ openshift.master.api_url }} --public-master={{ openshift.master.public_api_url }} --listen={{ 'https' if openshift.master.api_use_ssl else 'http' }}://0.0.0.0:{{ openshift.master.api_port }} - {{ ('--images=' ~ openshift_registry_url) if openshift_registry_url is defined else '' }} - {{ ('--nodes=' ~ openshift_node_ips | join(',')) if openshift_node_ips is defined else '' }} + {{ ('--images=' ~ openshift_registry_url) if (openshift_registry_url | default('', true) != '') else '' }} + {{ ('--nodes=' ~ openshift_node_ips | join(',')) if (openshift_node_ips | default('', true) != '') else '' }} args: chdir: "{{ openshift_cert_parent_dir }}" creates: "{{ openshift_master_config }}" -- cgit v1.2.3 From ba5ae4dbc7741af1963df36fd92bcd0af03c6b4f Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Thu, 16 Apr 2015 22:44:12 -0400 Subject: aws terminate playbook improvements - Reduce duplication in terminate playbooks between openshift-master and openshift-node (they both now just include playbooks/aws/terminate.yml - update openshift-cluster terminate playbook to include the new shared terminate playbook, also delete all cluster hosts at once instead of treating masters and nodes differently. - remove env, host-type and env-host-type tags from instance before terminating (since most users can't terminate, we are mostly just renaming instances to -terminate and stopping them, so this prevents "terminated" hosts from being returned by the dynamic inventory, at least after the cache is refreshed) --- playbooks/aws/openshift-cluster/terminate.yml | 16 ++----- playbooks/aws/openshift-master/terminate.yml | 55 +---------------------- playbooks/aws/openshift-node/terminate.yml | 55 +---------------------- playbooks/aws/terminate.yml | 64 +++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 121 deletions(-) create mode 100644 playbooks/aws/terminate.yml diff --git a/playbooks/aws/openshift-cluster/terminate.yml b/playbooks/aws/openshift-cluster/terminate.yml index 1d2b60594..617d0d456 100644 --- a/playbooks/aws/openshift-cluster/terminate.yml +++ b/playbooks/aws/openshift-cluster/terminate.yml @@ -5,22 +5,12 @@ vars_files: - vars.yml tasks: - - set_fact: scratch_group=tag_env-host-type_{{ cluster_id }}-openshift-node + - set_fact: scratch_group=tag_env_{{ cluster_id }} - add_host: name: "{{ item }}" - groups: oo_nodes_to_terminate + groups: oo_hosts_to_terminate ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" with_items: groups[scratch_group] | default([]) | difference(['localhost']) - - set_fact: scratch_group=tag_env-host-type_{{ cluster_id }}-openshift-master - - add_host: - name: "{{ item }}" - groups: oo_masters_to_terminate - ansible_ssh_user: "{{ deployment_vars[deployment_type].ssh_user }}" - ansible_sudo: "{{ deployment_vars[deployment_type].sudo }}" - with_items: groups[scratch_group] | default([]) | difference(['localhost']) - -- include: ../openshift-node/terminate.yml - -- include: ../openshift-master/terminate.yml +- include: ../terminate.yml diff --git a/playbooks/aws/openshift-master/terminate.yml b/playbooks/aws/openshift-master/terminate.yml index a790336b1..07d9961bc 100644 --- a/playbooks/aws/openshift-master/terminate.yml +++ b/playbooks/aws/openshift-master/terminate.yml @@ -1,55 +1,2 @@ --- -- name: Populate oo_masters_to_terminate host group - hosts: localhost - gather_facts: no - tasks: - - name: Evaluate oo_masters_to_terminate - add_host: name={{ item }} groups=oo_masters_to_terminate - with_items: oo_host_group_exp | default([]) - -- name: Gather dynamic inventory variables for hosts to terminate - hosts: oo_masters_to_terminate - gather_facts: no - -- 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 - when: "'oo_masters_to_terminate' in groups" - - # 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: "'oo_masters_to_terminate' in groups and 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 - when: "'oo_masters_to_terminate' in groups" - - - 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 - when: "'oo_masters_to_terminate' in groups" - +- include: ../terminate.yml diff --git a/playbooks/aws/openshift-node/terminate.yml b/playbooks/aws/openshift-node/terminate.yml index 40ae56f99..07d9961bc 100644 --- a/playbooks/aws/openshift-node/terminate.yml +++ b/playbooks/aws/openshift-node/terminate.yml @@ -1,55 +1,2 @@ --- -- name: Populate oo_nodes_to_terminate host group - hosts: localhost - gather_facts: no - tasks: - - name: Evaluate oo_nodes_to_terminate - add_host: name={{ item }} groups=oo_nodes_to_terminate - with_items: oo_host_group_exp | default([]) - -- name: Gather dynamic inventory variables for hosts to terminate - hosts: oo_nodes_to_terminate - gather_facts: no - -- 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 - when: "'oo_nodes_to_terminate' in groups" - - # 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: "'oo_nodes_to_terminate' in groups and 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 - when: "'oo_nodes_to_terminate' in groups" - - - 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 - when: "'oo_nodes_to_terminate' in groups" - +- include: ../terminate.yml diff --git a/playbooks/aws/terminate.yml b/playbooks/aws/terminate.yml new file mode 100644 index 000000000..e9767b260 --- /dev/null +++ b/playbooks/aws/terminate.yml @@ -0,0 +1,64 @@ +--- +- name: Populate oo_hosts_to_terminate host group + hosts: localhost + gather_facts: no + tasks: + - name: Evaluate oo_hosts_to_terminate + add_host: name={{ item }} groups=oo_hosts_to_terminate + with_items: oo_host_group_exp | default([]) + +- name: Gather dynamic inventory variables for hosts to terminate + hosts: oo_hosts_to_terminate + gather_facts: no + +- name: Terminate instances + hosts: localhost + connection: local + gather_facts: no + vars: + host_vars: "{{ hostvars + | oo_select_keys(groups['oo_hosts_to_terminate']) }}" + tasks: + - name: Remove tags from instances + ec2_tag: resource={{ item.ec2_id }} region={{ item.ec2_region }} state=absent + args: + tags: + env: "{{ item['ec2_tag_env'] }}" + host-type: "{{ item['ec2_tag_host-type'] }}" + env-host-type: "{{ item['ec2_tag_env-host-type'] }}" + with_items: host_vars + when: "'oo_hosts_to_terminate' in groups" + + - 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 + when: "'oo_hosts_to_terminate' in groups" + + # 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: "'oo_hosts_to_terminate' in groups and 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 + when: "'oo_hosts_to_terminate' in groups" + + - 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 + when: "'oo_hosts_to_terminate' in groups" -- cgit v1.2.3 From 991b232e34f86a6a745bdc34d62b046abd2291e7 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Mon, 20 Apr 2015 22:52:12 -0400 Subject: fixes to better deal with gce image defaults - remove exception if INPUT rules are not found, gce centos-7 image is stripped of default rules - ignore_errors for systemctl mask operation, fails with permission denied on gce centos-7 image. --- roles/os_firewall/library/os_firewall_manage_iptables.py | 9 +-------- roles/os_firewall/tasks/firewall/firewalld.yml | 1 + roles/os_firewall/tasks/firewall/iptables.yml | 1 + 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/roles/os_firewall/library/os_firewall_manage_iptables.py b/roles/os_firewall/library/os_firewall_manage_iptables.py index 9d0af497d..987cc6fc2 100755 --- a/roles/os_firewall/library/os_firewall_manage_iptables.py +++ b/roles/os_firewall/library/os_firewall_manage_iptables.py @@ -150,17 +150,10 @@ class IpTablesManager: continue last_rule_target = rule[1] - # Raise an exception if we do not find a valid rule - if not last_rule_num or not last_rule_target: - raise IpTablesCreateJumpRuleError( - chain=self.chain, - msg="Failed to find existing %s rules" % self.jump_rule_chain, - cmd=None, exit_code=None, output=None) - # Naively assume that if the last row is a REJECT rule, then # we can add insert our rule right before it, otherwise we # assume that we can just append the rule. - if last_rule_target == 'REJECT': + if last_rule_num and last_rule_target and last_rule_target == 'REJECT': # insert rule cmd = self.cmd + ['-I', self.jump_rule_chain, str(last_rule_num)] else: diff --git a/roles/os_firewall/tasks/firewall/firewalld.yml b/roles/os_firewall/tasks/firewall/firewalld.yml index b6bddd5c5..5089eb3e0 100644 --- a/roles/os_firewall/tasks/firewall/firewalld.yml +++ b/roles/os_firewall/tasks/firewall/firewalld.yml @@ -44,6 +44,7 @@ - iptables - ip6tables when: pkg_check.rc == 0 + ignore_errors: yes # TODO: Ansible 1.9 will eliminate the need for separate firewalld tasks for # enabling rules and making them permanent with the immediate flag diff --git a/roles/os_firewall/tasks/firewall/iptables.yml b/roles/os_firewall/tasks/firewall/iptables.yml index 7b5c00a9b..9af9d8d29 100644 --- a/roles/os_firewall/tasks/firewall/iptables.yml +++ b/roles/os_firewall/tasks/firewall/iptables.yml @@ -42,6 +42,7 @@ register: result changed_when: "'firewalld' in result.stdout" when: pkg_check.rc == 0 + ignore_errors: yes - name: Add iptables allow rules os_firewall_manage_iptables: -- cgit v1.2.3 From 656cb873f4a07eefaf7f1180e79378a30af03de0 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Mon, 20 Apr 2015 16:39:52 -0400 Subject: openshift-sdn-node fix to use /etc/sysconfig/docker-network --- roles/openshift_sdn_node/tasks/main.yml | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/roles/openshift_sdn_node/tasks/main.yml b/roles/openshift_sdn_node/tasks/main.yml index c2329dd6f..37a30d019 100644 --- a/roles/openshift_sdn_node/tasks/main.yml +++ b/roles/openshift_sdn_node/tasks/main.yml @@ -34,12 +34,25 @@ line: '\1"{{ openshift_sdn_master_url }}"' - regex: '^(MINION_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: Ensure we aren't setting DOCKER_OPTIONS in /etc/sysconfig/openshift-sdn-node + lineinfile: + dest: /etc/sysconfig/openshift-sdn-node + regexp: '^DOCKER_OPTIONS=' + state: absent + notify: restart openshift-sdn-node + +# TODO lock down the insecure-registry config to a more sane value than +# 0.0.0.0/0 +- name: Configure docker insecure-registry setting + lineinfile: + dest: /etc/sysconfig/docker + regexp: INSECURE_REGISTRY= + line: INSECURE_REGISTRY='--insecure-registry=0.0.0.0/0' + notify: restart openshift-sdn-node + + - name: Start and enable openshift-sdn-node service: name: openshift-sdn-node -- cgit v1.2.3 From 71ff62e46f464916f57345f4945f2e28cf5cdcdc Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Tue, 21 Apr 2015 10:40:55 -0400 Subject: add vpc support to ec2 cluster, add more overrides for variables --- .../openshift-cluster/tasks/launch_instances.yml | 26 +++++++++++++++------- playbooks/aws/openshift-cluster/vars.yml | 15 +++++++++++++ 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/playbooks/aws/openshift-cluster/tasks/launch_instances.yml b/playbooks/aws/openshift-cluster/tasks/launch_instances.yml index 58b4082df..28582c84c 100644 --- a/playbooks/aws/openshift-cluster/tasks/launch_instances.yml +++ b/playbooks/aws/openshift-cluster/tasks/launch_instances.yml @@ -1,25 +1,35 @@ --- -# TODO: modify machine_image based on deployment_type - set_fact: - machine_type: "{{ lookup('env', 'ec2_instance_type') | default('m3.large', true) }}" - machine_image: "{{ lookup('env', 'ec2_ami') | default(deployment_vars[deployment_type].image, true) }}" - machine_region: "{{ lookup('env', 'ec2_region') | default(deployment_vars[deployment_type].region, true) }}" - machine_keypair: "{{ lookup('env', 'ec2_keypair')|default('libra', true) }}" created_by: "{{ lookup('env', 'LOGNAME')|default(cluster, true) }}" - security_group: "{{ lookup('env', 'ec2_security_group')|default('public', true) }}" env: "{{ cluster }}" - host_type: "{{ type }}" env_host_type: "{{ cluster }}-openshift-{{ type }}" + host_type: "{{ type }}" + machine_type: "{{ lookup('env', 'ec2_instance_type') + | default(deployment_vars[deployment_type].type, true) }}" + machine_image: "{{ lookup('env', 'ec2_ami') + | default(deployment_vars[deployment_type].image, true) }}" + machine_region: "{{ lookup('env', 'ec2_region') + | default(deployment_vars[deployment_type].region, true) }}" + machine_keypair: "{{ lookup('env', 'ec2_keypair') + | default(deployment_vars[deployment_type].keypair, true) }}" + machine_subnet: "{{ lookup('env', 'ec2_vpc_subnet') + | default(deployment_vars[deployment_type].vpc_subnet, true) }}" + machine_public_ip: "{{ lookup('env', 'ec2_public_ip') + | default(deployment_vars[deployment_type].assign_public_ip, true) }}" + security_groups: "{{ lookup('env', 'ec2_security_groups') + | default(deployment_vars[deployment_type].security_groups, true) }}" - name: Launch instance(s) ec2: state: present region: "{{ machine_region }}" keypair: "{{ machine_keypair }}" - group: "{{ security_group }}" + group: "{{ security_groups }}" instance_type: "{{ machine_type }}" image: "{{ machine_image }}" count: "{{ instances | oo_len }}" + vpc_subnet_id: "{{ machine_subnet | default(omit, true) }}" + assign_public_ip: "{{ machine_public_ip | default(omit, true) }}" wait: yes instance_tags: created-by: "{{ created_by }}" diff --git a/playbooks/aws/openshift-cluster/vars.yml b/playbooks/aws/openshift-cluster/vars.yml index f0df3d6f5..bd6215869 100644 --- a/playbooks/aws/openshift-cluster/vars.yml +++ b/playbooks/aws/openshift-cluster/vars.yml @@ -6,15 +6,30 @@ deployment_vars: region: us-east-1 ssh_user: fedora sudo: yes + keypair: libra + type: m3.large + security_groups: [ 'public' ] + vpc_subnet: + assign_public_ip: online: # private ami image: ami-307b3658 region: us-east-1 ssh_user: root sudo: no + keypair: libra + type: m3.large + security_groups: [ 'public' ] + vpc_subnet: + assign_public_ip: enterprise: # rhel-7.1, requires cloud access subscription image: ami-10663b78 region: us-east-1 ssh_user: ec2-user sudo: yes + keypair: libra + type: m3.large + security_groups: [ 'public' ] + vpc_subnet: + assign_public_ip: -- cgit v1.2.3 From 263a3d6eab0acb6c5e4761b783d9ce6f57f210ad Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Tue, 21 Apr 2015 11:57:15 -0400 Subject: Update online v3 repo file --- roles/openshift_repos/files/online/repos/enterprise-v3.repo | 9 +++++++++ roles/openshift_repos/files/online/repos/epel7-openshift.repo | 6 ------ roles/openshift_repos/files/removed/repos/epel7-openshift.repo | 0 3 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 roles/openshift_repos/files/online/repos/enterprise-v3.repo delete mode 100644 roles/openshift_repos/files/online/repos/epel7-openshift.repo create mode 100644 roles/openshift_repos/files/removed/repos/epel7-openshift.repo diff --git a/roles/openshift_repos/files/online/repos/enterprise-v3.repo b/roles/openshift_repos/files/online/repos/enterprise-v3.repo new file mode 100644 index 000000000..240183caa --- /dev/null +++ b/roles/openshift_repos/files/online/repos/enterprise-v3.repo @@ -0,0 +1,9 @@ +[enterprise-v3] +name=OpenShift Enterprise Beta3 +baseurl=https://gce-mirror1.ops.rhcloud.com/libra/libra-7-ose-beta3/ + https://mirror.ops.rhcloud.com/libra/libra-7-ose-beta3/ +enabled=1 +gpgcheck=0 +failovermethod=priority +sslverify=False +sslclientcert=/var/lib/yum/client-cert.pem diff --git a/roles/openshift_repos/files/online/repos/epel7-openshift.repo b/roles/openshift_repos/files/online/repos/epel7-openshift.repo deleted file mode 100644 index c7629872d..000000000 --- a/roles/openshift_repos/files/online/repos/epel7-openshift.repo +++ /dev/null @@ -1,6 +0,0 @@ -[maxamillion-origin-next] -name=Copr repo for origin-next owned by maxamillion -baseurl=http://copr-be.cloud.fedoraproject.org/results/maxamillion/origin-next/epel-7-$basearch/ -skip_if_unavailable=False -gpgcheck=0 -enabled=1 diff --git a/roles/openshift_repos/files/removed/repos/epel7-openshift.repo b/roles/openshift_repos/files/removed/repos/epel7-openshift.repo new file mode 100644 index 000000000..e69de29bb -- cgit v1.2.3 From 8acca7f942b1d3328d7eb6cdbfe45b19217cde38 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Tue, 21 Apr 2015 16:28:50 -0400 Subject: pylint --- .../library/os_firewall_manage_iptables.py | 82 ++++++++++++---------- 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/roles/os_firewall/library/os_firewall_manage_iptables.py b/roles/os_firewall/library/os_firewall_manage_iptables.py index 987cc6fc2..1cb539a8c 100755 --- a/roles/os_firewall/library/os_firewall_manage_iptables.py +++ b/roles/os_firewall/library/os_firewall_manage_iptables.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- # vim: expandtab:tabstop=4:shiftwidth=4 - +# pylint: disable=fixme, missing-docstring from subprocess import call, check_output DOCUMENTATION = ''' @@ -17,6 +17,7 @@ EXAMPLES = ''' class IpTablesError(Exception): def __init__(self, msg, cmd, exit_code, output): + super(IpTablesError, self).__init__(msg) self.msg = msg self.cmd = cmd self.exit_code = exit_code @@ -36,13 +37,14 @@ class IpTablesSaveError(IpTablesError): class IpTablesCreateChainError(IpTablesError): - def __init__(self, chain, msg, cmd, exit_code, output): - super(IpTablesCreateChainError, self).__init__(msg, cmd, exit_code, output) + def __init__(self, chain, msg, cmd, exit_code, output): # pylint: disable=too-many-arguments, line-too-long + super(IpTablesCreateChainError, self).__init__(msg, cmd, exit_code, + output) self.chain = chain class IpTablesCreateJumpRuleError(IpTablesError): - def __init__(self, chain, msg, cmd, exit_code, output): + def __init__(self, chain, msg, cmd, exit_code, output): # pylint: disable=too-many-arguments, line-too-long super(IpTablesCreateJumpRuleError, self).__init__(msg, cmd, exit_code, output) self.chain = chain @@ -51,7 +53,7 @@ class IpTablesCreateJumpRuleError(IpTablesError): # TODO: impliment rollbacks for any events that where successful and an # exception was thrown later. for example, when the chain is created # successfully, but the add/remove rule fails. -class IpTablesManager: +class IpTablesManager(object): # pylint: disable=too-many-instance-attributes def __init__(self, module): self.module = module self.ip_version = module.params['ip_version'] @@ -68,10 +70,10 @@ class IpTablesManager: try: self.output.append(check_output(self.save_cmd, stderr=subprocess.STDOUT)) - except subprocess.CalledProcessError as e: + except subprocess.CalledProcessError as ex: raise IpTablesSaveError( msg="Failed to save iptables rules", - cmd=e.cmd, exit_code=e.returncode, output=e.output) + cmd=ex.cmd, exit_code=ex.returncode, output=ex.output) def verify_chain(self): if not self.chain_exists(): @@ -93,13 +95,13 @@ class IpTablesManager: self.output.append(check_output(cmd)) self.changed = True self.save() - except subprocess.CalledProcessError as e: + except subprocess.CalledProcessError as ex: raise IpTablesCreateChainError( chain=self.chain, msg="Failed to create rule for " - "%s %s" % (self.proto, self.port), - cmd=e.cmd, exit_code=e.returncode, - output=e.output) + "%s %s" % (proto, port), + cmd=ex.cmd, exit_code=ex.returncode, + output=ex.output) def remove_rule(self, port, proto): rule = self.gen_rule(port, proto) @@ -113,15 +115,15 @@ class IpTablesManager: self.output.append(check_output(cmd)) self.changed = True self.save() - except subprocess.CalledProcessError as e: - raise IpTablesRemoveChainError( + except subprocess.CalledProcessError as ex: + raise IpTablesRemoveRuleError( chain=self.chain, msg="Failed to remove rule for %s %s" % (proto, port), - cmd=e.cmd, exit_code=e.returncode, output=e.output) + cmd=ex.cmd, exit_code=ex.returncode, output=ex.output) def rule_exists(self, rule): check_cmd = self.cmd + ['-C'] + rule - return True if subprocess.call(check_cmd) == 0 else False + return True if call(check_cmd) == 0 else False def gen_rule(self, port, proto): return [self.chain, '-p', proto, '-m', 'state', '--state', 'NEW', @@ -137,7 +139,7 @@ class IpTablesManager: output = check_output(cmd, stderr=subprocess.STDOUT) # break the input rules into rows and columns - input_rules = map(lambda s: s.split(), output.split('\n')) + input_rules = [s.split() for s in output.split('\n')] # Find the last numbered rule last_rule_num = None @@ -153,32 +155,35 @@ class IpTablesManager: # Naively assume that if the last row is a REJECT rule, then # we can add insert our rule right before it, otherwise we # assume that we can just append the rule. - if last_rule_num and last_rule_target and last_rule_target == 'REJECT': + if (last_rule_num and last_rule_target + and last_rule_target == 'REJECT'): # insert rule - cmd = self.cmd + ['-I', self.jump_rule_chain, str(last_rule_num)] + cmd = self.cmd + ['-I', self.jump_rule_chain, + str(last_rule_num)] else: # append rule cmd = self.cmd + ['-A', self.jump_rule_chain] cmd += ['-j', self.chain] output = check_output(cmd, stderr=subprocess.STDOUT) - changed = True + self.changed = True self.output.append(output) self.save() - except subprocess.CalledProcessError as e: - if '--line-numbers' in e.cmd: + except subprocess.CalledProcessError as ex: + if '--line-numbers' in ex.cmd: raise IpTablesCreateJumpRuleError( chain=self.chain, - msg="Failed to query existing %s rules to " % self.jump_rule_chain + - "determine jump rule location", - cmd=e.cmd, exit_code=e.returncode, - output=e.output) + msg=("Failed to query existing " + + self.jump_rule_chain + + " rules to determine jump rule location"), + cmd=ex.cmd, exit_code=ex.returncode, + output=ex.output) else: raise IpTablesCreateJumpRuleError( chain=self.chain, - msg="Failed to create jump rule for chain %s" % - self.chain, - cmd=e.cmd, exit_code=e.returncode, - output=e.output) + msg=("Failed to create jump rule for chain " + + self.chain), + cmd=ex.cmd, exit_code=ex.returncode, + output=ex.output) def create_chain(self): if self.check_mode: @@ -193,27 +198,26 @@ class IpTablesManager: self.output.append("Successfully created chain %s" % self.chain) self.save() - except subprocess.CalledProcessError as e: + except subprocess.CalledProcessError as ex: raise IpTablesCreateChainError( chain=self.chain, msg="Failed to create chain: %s" % self.chain, - cmd=e.cmd, exit_code=e.returncode, output=e.output + cmd=ex.cmd, exit_code=ex.returncode, output=ex.output ) def jump_rule_exists(self): cmd = self.cmd + ['-C', self.jump_rule_chain, '-j', self.chain] - return True if subprocess.call(cmd) == 0 else False + return True if call(cmd) == 0 else False def chain_exists(self): cmd = self.cmd + ['-L', self.chain] - return True if subprocess.call(cmd) == 0 else False + return True if call(cmd) == 0 else False def gen_cmd(self): cmd = 'iptables' if self.ip_version == 'ipv4' else 'ip6tables' return ["/usr/sbin/%s" % cmd] - def gen_save_cmd(self): - cmd = 'iptables' if self.ip_version == 'ipv4' else 'ip6tables' + def gen_save_cmd(self): # pylint: disable=no-self-use return ['/usr/libexec/iptables/iptables.init', 'save'] @@ -221,7 +225,8 @@ def main(): module = AnsibleModule( argument_spec=dict( name=dict(required=True), - action=dict(required=True, choices=['add', 'remove', 'verify_chain']), + action=dict(required=True, choices=['add', 'remove', + 'verify_chain']), chain=dict(required=False, default='OS_FIREWALL_ALLOW'), create_jump_rule=dict(required=False, type='bool', default=True), jump_rule_chain=dict(required=False, default='INPUT'), @@ -254,13 +259,14 @@ def main(): iptables_manager.remove_rule(port, protocol) elif action == 'verify_chain': iptables_manager.verify_chain() - except IpTablesError as e: - module.fail_json(msg=e.msg) + except IpTablesError as ex: + module.fail_json(msg=ex.msg) return module.exit_json(changed=iptables_manager.changed, output=iptables_manager.output) +# pylint: disable=redefined-builtin, unused-wildcard-import, wildcard-import # import module snippets from ansible.module_utils.basic import * if __name__ == '__main__': -- cgit v1.2.3 From 0b53cf9745e3f64a880dccffa7d18bc9fd1fa2fa Mon Sep 17 00:00:00 2001 From: Wesley Hearn Date: Wed, 22 Apr 2015 10:35:50 -0400 Subject: Remove duplicated repos and fix enterprise-v3 repo --- .../files/online/repos/enterprise-v3.repo | 1 + .../files/online/repos/oso-rhui-rhel-7-extras.repo | 23 ---------------------- .../files/online/repos/oso-rhui-rhel-7-server.repo | 21 -------------------- 3 files changed, 1 insertion(+), 44 deletions(-) delete mode 100644 roles/openshift_repos/files/online/repos/oso-rhui-rhel-7-extras.repo delete mode 100644 roles/openshift_repos/files/online/repos/oso-rhui-rhel-7-server.repo diff --git a/roles/openshift_repos/files/online/repos/enterprise-v3.repo b/roles/openshift_repos/files/online/repos/enterprise-v3.repo index 240183caa..d324c142a 100644 --- a/roles/openshift_repos/files/online/repos/enterprise-v3.repo +++ b/roles/openshift_repos/files/online/repos/enterprise-v3.repo @@ -7,3 +7,4 @@ gpgcheck=0 failovermethod=priority sslverify=False sslclientcert=/var/lib/yum/client-cert.pem +sslclientkey=/var/lib/yum/client-key.pem \ No newline at end of file diff --git a/roles/openshift_repos/files/online/repos/oso-rhui-rhel-7-extras.repo b/roles/openshift_repos/files/online/repos/oso-rhui-rhel-7-extras.repo deleted file mode 100644 index cfe41f691..000000000 --- a/roles/openshift_repos/files/online/repos/oso-rhui-rhel-7-extras.repo +++ /dev/null @@ -1,23 +0,0 @@ -[oso-rhui-rhel-server-extras] -name=OpenShift Online RHUI Mirror RH Enterprise Linux - Extras -baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-extras/ - https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-extras/ -enabled=1 -gpgcheck=1 -gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release,file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-beta -failovermethod=priority -sslverify=False -sslclientcert=/var/lib/yum/client-cert.pem -sslclientkey=/var/lib/yum/client-key.pem - -[oso-rhui-rhel-server-extras-htb] -name=OpenShift Online RHUI Mirror RH Enterprise Linux - Extras HTB -baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-extras-htb/ - https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-extras-htb/ -enabled=0 -gpgcheck=1 -gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release,file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-beta -failovermethod=priority -sslverify=False -sslclientcert=/var/lib/yum/client-cert.pem -sslclientkey=/var/lib/yum/client-key.pem diff --git a/roles/openshift_repos/files/online/repos/oso-rhui-rhel-7-server.repo b/roles/openshift_repos/files/online/repos/oso-rhui-rhel-7-server.repo deleted file mode 100644 index ddc93193d..000000000 --- a/roles/openshift_repos/files/online/repos/oso-rhui-rhel-7-server.repo +++ /dev/null @@ -1,21 +0,0 @@ -[oso-rhui-rhel-server-releases] -name=OpenShift Online RHUI Mirror RH Enterprise Linux 7 -baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-releases/ - https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-releases/ -enabled=1 -gpgcheck=1 -gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release -sslverify=False -sslclientcert=/var/lib/yum/client-cert.pem -sslclientkey=/var/lib/yum/client-key.pem - -[oso-rhui-rhel-server-releases-optional] -name=OpenShift Online RHUI Mirror RH Enterprise Linux 7 - Optional -baseurl=https://gce-mirror1.ops.rhcloud.com/libra/rhui-rhel-server-7-releases-optional/ - https://mirror.ops.rhcloud.com/libra/rhui-rhel-server-7-releases-optional/ -enabled=1 -gpgcheck=1 -gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release -sslverify=False -sslclientcert=/var/lib/yum/client-cert.pem -sslclientkey=/var/lib/yum/client-key.pem -- cgit v1.2.3 From 2823c990eda7abd19447b988131f2c0eb8a9fdcc Mon Sep 17 00:00:00 2001 From: Wesley Hearn Date: Wed, 22 Apr 2015 10:49:29 -0400 Subject: Use docker-registry.ops when deploying as online --- roles/openshift_master/tasks/main.yml | 6 ++++++ roles/openshift_register_nodes/tasks/main.yml | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/roles/openshift_master/tasks/main.yml b/roles/openshift_master/tasks/main.yml index 3ea485610..da184e972 100644 --- a/roles/openshift_master/tasks/main.yml +++ b/roles/openshift_master/tasks/main.yml @@ -53,6 +53,12 @@ set_fact: openshift_registry_url: "openshift3_beta/ose-${component}:${version}" when: openshift.common.deployment_type == 'enterprise' and openshift_registry_url is not defined + +- name: Use online default for openshift_registry_url if not set + set_fact: + openshift_registry_url: "docker-registry.ops.rhcloud.com/openshift3_beta/ose-${component}:${version}" + when: openshift.common.deployment_type == 'online' and openshift_registry_url is not defined + - name: Create master config command: > /usr/bin/openshift start master --write-config diff --git a/roles/openshift_register_nodes/tasks/main.yml b/roles/openshift_register_nodes/tasks/main.yml index 85f490f70..85bead16d 100644 --- a/roles/openshift_register_nodes/tasks/main.yml +++ b/roles/openshift_register_nodes/tasks/main.yml @@ -10,6 +10,12 @@ set_fact: openshift_registry_url: "openshift3_beta/ose-${component}:${version}" when: openshift.common.deployment_type == 'enterprise' and openshift_registry_url is not defined + +- name: Use online default for openshift_registry_url if not set + set_fact: + openshift_registry_url: "docker-registry.ops.rhcloud.com/openshift3_beta/ose-${component}:${version}" + when: openshift.common.deployment_type == 'online' and openshift_registry_url is not defined + - name: Create node config command: > /usr/bin/openshift admin create-node-config -- cgit v1.2.3 From 3d34312d6414e10595a7e7200ee6735a01632b41 Mon Sep 17 00:00:00 2001 From: Wesley Hearn Date: Wed, 22 Apr 2015 10:53:41 -0400 Subject: Update openshift-cluster/vars for online defaults --- playbooks/aws/openshift-cluster/vars.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/playbooks/aws/openshift-cluster/vars.yml b/playbooks/aws/openshift-cluster/vars.yml index bd6215869..f87e7aba3 100644 --- a/playbooks/aws/openshift-cluster/vars.yml +++ b/playbooks/aws/openshift-cluster/vars.yml @@ -13,15 +13,15 @@ deployment_vars: assign_public_ip: online: # private ami - image: ami-307b3658 + image: ami-906240f8 region: us-east-1 ssh_user: root sudo: no - keypair: libra + keypair: mmcgrath_libra type: m3.large - security_groups: [ 'public' ] - vpc_subnet: - assign_public_ip: + security_groups: [ 'int-v3' ] + vpc_subnet: subnet-987c0def + assign_public_ip: yes enterprise: # rhel-7.1, requires cloud access subscription image: ami-10663b78 -- cgit v1.2.3 From 7d441995db0c065942b83297af60f48acfd24a49 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Wed, 22 Apr 2015 15:59:38 -0400 Subject: More repo cleanup - remove previously removed repo files from disk if they still exist - remove gpg keys that are no longer referenced --- .../files/online/gpg_keys/RPM-GPG-KEY-redhat-beta | 61 --------------------- .../online/gpg_keys/RPM-GPG-KEY-redhat-release | 63 ---------------------- .../removed/repos/oso-rhui-rhel-7-extras.repo | 0 .../removed/repos/oso-rhui-rhel-7-server.repo | 0 4 files changed, 124 deletions(-) delete mode 100644 roles/openshift_repos/files/online/gpg_keys/RPM-GPG-KEY-redhat-beta delete mode 100644 roles/openshift_repos/files/online/gpg_keys/RPM-GPG-KEY-redhat-release create mode 100644 roles/openshift_repos/files/removed/repos/oso-rhui-rhel-7-extras.repo create mode 100644 roles/openshift_repos/files/removed/repos/oso-rhui-rhel-7-server.repo diff --git a/roles/openshift_repos/files/online/gpg_keys/RPM-GPG-KEY-redhat-beta b/roles/openshift_repos/files/online/gpg_keys/RPM-GPG-KEY-redhat-beta deleted file mode 100644 index 7b40671a4..000000000 --- a/roles/openshift_repos/files/online/gpg_keys/RPM-GPG-KEY-redhat-beta +++ /dev/null @@ -1,61 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.2.6 (GNU/Linux) - -mQINBEmkAzABEAC2/c7bP1lHQ3XScxbIk0LQWe1YOiibQBRLwf8Si5PktgtuPibT -kKpZjw8p4D+fM7jD1WUzUE0X7tXg2l/eUlMM4dw6XJAQ1AmEOtlwSg7rrMtTvM0A -BEtI7Km6fC6sU6RtBMdcqD1cH/6dbsfh8muznVA7UlX+PRBHVzdWzj6y8h84dBjo -gzcbYu9Hezqgj/lLzicqsSZPz9UdXiRTRAIhp8V30BD8uRaaa0KDDnD6IzJv3D9P -xQWbFM4Z12GN9LyeZqmD7bpKzZmXG/3drvfXVisXaXp3M07t3NlBa3Dt8NFIKZ0D -FRXBz5bvzxRVmdH6DtkDWXDPOt+Wdm1rZrCOrySFpBZQRpHw12eo1M1lirANIov7 -Z+V1Qh/aBxj5EUu32u9ZpjAPPNtQF6F/KjaoHHHmEQAuj4DLex4LY646Hv1rcv2i -QFuCdvLKQGSiFBrfZH0j/IX3/0JXQlZzb3MuMFPxLXGAoAV9UP/Sw/WTmAuTzFVm -G13UYFeMwrToOiqcX2VcK0aC1FCcTP2z4JW3PsWvU8rUDRUYfoXovc7eg4Vn5wHt -0NBYsNhYiAAf320AUIHzQZYi38JgVwuJfFu43tJZE4Vig++RQq6tsEx9Ftz3EwRR -fJ9z9mEvEiieZm+vbOvMvIuimFVPSCmLH+bI649K8eZlVRWsx3EXCVb0nQARAQAB -tDBSZWQgSGF0LCBJbmMuIChiZXRhIGtleSAyKSA8c2VjdXJpdHlAcmVkaGF0LmNv -bT6JAjYEEwECACAFAkpSM+cCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCT -ioDK8hVB6/9tEAC0+KmzeKceXQ/GTUoU6jy9vtkFCFrmv+c7ol4XpdTt0QhqBOwy -6m2mKWwmm8KfYfy0cADQ4y/EcoXl7FtFBwYmkCuEQGXhTDn9DvVjhooIq59LEMBQ -OW879RwwzRIZ8ebbjMUjDPF5MfPQqP2LBu9N4KvXlZp4voykwuuaJ+cbsKZR6pZ6 -0RQKPHKP+NgUFC0fff7XY9cuOZZWFAeKRhLN2K7bnRHKxp+kELWb6R9ZfrYwZjWc -MIPbTd1khE53L4NTfpWfAnJRtkPSDOKEGVlVLtLq4HEAxQt07kbslqISRWyXER3u -QOJj64D1ZiIMz6t6uZ424VE4ry9rBR0Jz55cMMx5O/ni9x3xzFUgH8Su2yM0r3jE -Rf24+tbOaPf7tebyx4OKe+JW95hNVstWUDyGbs6K9qGfI/pICuO1nMMFTo6GqzQ6 -DwLZvJ9QdXo7ujEtySZnfu42aycaQ9ZLC2DOCQCUBY350Hx6FLW3O546TAvpTfk0 -B6x+DV7mJQH7MGmRXQsE7TLBJKjq28Cn4tVp04PmybQyTxZdGA/8zY6pPl6xyVMH -V68hSBKEVT/rlouOHuxfdmZva1DhVvUC6Xj7+iTMTVJUAq/4Uyn31P1OJmA2a0PT -CAqWkbJSgKFccsjPoTbLyxhuMSNkEZFHvlZrSK9vnPzmfiRH0Orx3wYpMQ== -=21pb ------END PGP PUBLIC KEY BLOCK----- -The following public key can be used to verify RPM packages built and -signed by Red Hat, Inc. for this beta using `rpm -K' using the GNU GPG -package. Questions about this key should be sent to security@redhat.com. - - ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.0.6 (GNU/Linux) -Comment: For info see http://www.gnupg.org - -mQGiBDySTqsRBACzc7xuCIp10oj5B2PAV4XzDeVxprv/WTMreSNSK+iC0bEz0IBp -Vnn++qtyiXfH+bGIE9jqZgIEnpttWhUOaU5LhcLFzy+m8NWfngIFP9QfGmGAe9Gd -LFeAdhj4RmSG/vgr7vDd83Hz22dv403Ar/sliWO4vDOrMmZBG57WGYTWtwCgkMsi -UUQuJ6slbzKn82w+bYxOlL0EAIylWJGaTkKOTL5DqVR3ik9aT0Dt3FNVYiuhcKBe -II4E3KOIVA9kO8in1IZjx2gs6K2UV+GsoAVANdfKL7l9O+k+J8OxhE74oycvYJxW -QzCgXMZkNcvW5wyXwEMcr6TVd/5BGztcMw8oT3/l2MtAEG/vn1XaWToRSO1XDMDz -+AjUA/4m0mTkN8S4wjzJG8lqN7+quW3UOaiCe8J3SFrrrhE0XbY9cTJI/9nuXHU1 -VjqOSmXQYH2Db7UOroFTBiWhlAedA4O4yuK52AJnvSsHbnJSEmn9rpo5z1Q8F+qI -mDlzriJdrIrVLeDiUeTlpH3kpG38D7007GhXBV72k1gpMoMcpbQ3UmVkIEhhdCwg -SW5jLiAoQmV0YSBUZXN0IFNvZnR3YXJlKSA8cmF3aGlkZUByZWRoYXQuY29tPohX -BBMRAgAXBQI8l5p/BQsHCgMEAxUDAgMWAgECF4AACgkQ/TcmiYl9oHqdeQCfZjw4 -F9sir3XfRAjVe9kYNcQ8hnIAn0WgyT7H5RriWYTOCfauOmd+cAW4iEYEEBECAAYF -AjyXmqQACgkQIZGAzdtCpg5nDQCfepuRUyuVJvhuQkPWySETYvRw+WoAnjAWhx6q -0npMx4OE1JGFi8ymKXktuQENBDySTq4QBADKL/mK7S8E3synxISlu7R6fUvu07Oc -RoX96n0Di6T+BS99hC44XzHjMDhUX2ZzVvYS88EZXoUDDkB/8g7SwZrOJ/QE1zrI -JmSVciNhSYWwqeT40Evs88ajZUfDiNbS/cSC6oui98iS4vxd7sE7IPY+FSx9vuAR -xOa9vBnJY/dx0wADBQQAosm+Iltt2uigC6LJzxNOoIdB5r0GqTC1o5sHCeNqXJhU -ExAG8m74uzMlYVLOpGZi4y4NwwAWvCWC0MWWnnu+LGFy1wKiJKRjhv5F+WkFutY5 -WHV5L44vp9jSIlBCRG+84jheTh8xqhndM9wOfPwWdYYu1vxrB8Tn6kA17PcYfHSI -RgQYEQIABgUCPJJergAKCRD9NyaJiX2geiCPAJ4nEM4NtI9Uj8lONDk6FU86PmoL -yACfb68fBd2pWEzLKsOk9imIobHHpzE= -=gpIn ------END PGP PUBLIC KEY BLOCK----- diff --git a/roles/openshift_repos/files/online/gpg_keys/RPM-GPG-KEY-redhat-release b/roles/openshift_repos/files/online/gpg_keys/RPM-GPG-KEY-redhat-release deleted file mode 100644 index 0f83b622d..000000000 --- a/roles/openshift_repos/files/online/gpg_keys/RPM-GPG-KEY-redhat-release +++ /dev/null @@ -1,63 +0,0 @@ -The following public key can be used to verify RPM packages built and -signed by Red Hat, Inc. This key is used for packages in Red Hat -products shipped after November 2009, and for all updates to those -products. - -Questions about this key should be sent to security@redhat.com. - -pub 4096R/FD431D51 2009-10-22 Red Hat, Inc. (release key 2) - ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.2.6 (GNU/Linux) - -mQINBErgSTsBEACh2A4b0O9t+vzC9VrVtL1AKvUWi9OPCjkvR7Xd8DtJxeeMZ5eF -0HtzIG58qDRybwUe89FZprB1ffuUKzdE+HcL3FbNWSSOXVjZIersdXyH3NvnLLLF -0DNRB2ix3bXG9Rh/RXpFsNxDp2CEMdUvbYCzE79K1EnUTVh1L0Of023FtPSZXX0c -u7Pb5DI5lX5YeoXO6RoodrIGYJsVBQWnrWw4xNTconUfNPk0EGZtEnzvH2zyPoJh -XGF+Ncu9XwbalnYde10OCvSWAZ5zTCpoLMTvQjWpbCdWXJzCm6G+/hx9upke546H -5IjtYm4dTIVTnc3wvDiODgBKRzOl9rEOCIgOuGtDxRxcQkjrC+xvg5Vkqn7vBUyW -9pHedOU+PoF3DGOM+dqv+eNKBvh9YF9ugFAQBkcG7viZgvGEMGGUpzNgN7XnS1gj -/DPo9mZESOYnKceve2tIC87p2hqjrxOHuI7fkZYeNIcAoa83rBltFXaBDYhWAKS1 -PcXS1/7JzP0ky7d0L6Xbu/If5kqWQpKwUInXtySRkuraVfuK3Bpa+X1XecWi24JY -HVtlNX025xx1ewVzGNCTlWn1skQN2OOoQTV4C8/qFpTW6DTWYurd4+fE0OJFJZQF -buhfXYwmRlVOgN5i77NTIJZJQfYFj38c/Iv5vZBPokO6mffrOTv3MHWVgQARAQAB -tDNSZWQgSGF0LCBJbmMuIChyZWxlYXNlIGtleSAyKSA8c2VjdXJpdHlAcmVkaGF0 -LmNvbT6JAjYEEwECACAFAkrgSTsCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAK -CRAZni+R/UMdUWzpD/9s5SFR/ZF3yjY5VLUFLMXIKUztNN3oc45fyLdTI3+UClKC -2tEruzYjqNHhqAEXa2sN1fMrsuKec61Ll2NfvJjkLKDvgVIh7kM7aslNYVOP6BTf -C/JJ7/ufz3UZmyViH/WDl+AYdgk3JqCIO5w5ryrC9IyBzYv2m0HqYbWfphY3uHw5 -un3ndLJcu8+BGP5F+ONQEGl+DRH58Il9Jp3HwbRa7dvkPgEhfFR+1hI+Btta2C7E -0/2NKzCxZw7Lx3PBRcU92YKyaEihfy/aQKZCAuyfKiMvsmzs+4poIX7I9NQCJpyE -IGfINoZ7VxqHwRn/d5mw2MZTJjbzSf+Um9YJyA0iEEyD6qjriWQRbuxpQXmlAJbh -8okZ4gbVFv1F8MzK+4R8VvWJ0XxgtikSo72fHjwha7MAjqFnOq6eo6fEC/75g3NL -Ght5VdpGuHk0vbdENHMC8wS99e5qXGNDued3hlTavDMlEAHl34q2H9nakTGRF5Ki -JUfNh3DVRGhg8cMIti21njiRh7gyFI2OccATY7bBSr79JhuNwelHuxLrCFpY7V25 -OFktl15jZJaMxuQBqYdBgSay2G0U6D1+7VsWufpzd/Abx1/c3oi9ZaJvW22kAggq -dzdA27UUYjWvx42w9menJwh/0jeQcTecIUd0d0rFcw/c1pvgMMl/Q73yzKgKYw== -=zbHE ------END PGP PUBLIC KEY BLOCK----- -The following public key can be used to verify RPM packages built and -signed by Red Hat, Inc. This key is a supporting (auxiliary) key for -Red Hat products shipped after November 2006 and for all updates to -those products. - -Questions about this key should be sent to security@redhat.com. - ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.2.6 (GNU/Linux) - -mQGiBEVwDGkRBACwPhZIpvkjI8wV9sFTDoqyPLx1ub8Sd/w+YuI5Ovm49mvvEQVT -VLg8FgE5JlST59AbsLDyVtRa9CxIvN5syBVrWWWtHtDnnylFBcqG/A6J3bI4E9/A -UtSL5Zxbav0+utP6f3wOpxQrxc+WIDVgpurdBKAQ3dsobGBqypeX6FXZ5wCgou6C -yZpGIBqosJaDWLzNeOfb/70D/1thLkQyhW3JJ6cHCYJHNfBShvbLWBf6S231mgmu -MyMlt8Kmipc9bw+saaAkSkVsQ/ZbfjrWB7e5kbMruKLVrH+nGhamlHYUGyAPtsPg -Uj/NUSj5BmrCsOkMpn43ngTLssE9MLhSPj2nIHGFv9B+iVLvomDdwnaBRgQ1aK8z -z6MAA/406yf5yVJ/MlTWs1/68VwDhosc9BtU1V5IE0NXgZUAfBJzzfVzzKQq6zJ2 -eZsMLhr96wbsW13zUZt1ing+ulwh2ee4meuJq6h/971JspFY/XBhcfq4qCNqVjsq -SZnWoGdCO6J8CxPIemD2IUHzjoyyeEj3RVydup6pcWZAmhzkKrQzUmVkIEhhdCwg -SW5jLiAoYXV4aWxpYXJ5IGtleSkgPHNlY3VyaXR5QHJlZGhhdC5jb20+iF4EExEC -AB4FAkVwDGkCGwMGCwkIBwMCAxUCAwMWAgECHgECF4AACgkQRWiciC+mWOC1rQCg -ooNLCFOzNPcvhd9Za8C801HmnsYAniCw3yzrCqtjYnxDDxlufH0FVTwX -=d/bm ------END PGP PUBLIC KEY BLOCK----- - diff --git a/roles/openshift_repos/files/removed/repos/oso-rhui-rhel-7-extras.repo b/roles/openshift_repos/files/removed/repos/oso-rhui-rhel-7-extras.repo new file mode 100644 index 000000000..e69de29bb diff --git a/roles/openshift_repos/files/removed/repos/oso-rhui-rhel-7-server.repo b/roles/openshift_repos/files/removed/repos/oso-rhui-rhel-7-server.repo new file mode 100644 index 000000000..e69de29bb -- cgit v1.2.3 From 1be4ce9126cacffaa4335a0579aa134206ec22ba Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Wed, 22 Apr 2015 16:05:50 -0400 Subject: Adding refresh-cache option and cleanup for pylint. Also updated for aws/hosts/ being added. --- inventory/multi_ec2.py | 95 +++++++++++++++++++++------------------- inventory/multi_ec2.yaml.example | 4 +- 2 files changed, 53 insertions(+), 46 deletions(-) diff --git a/inventory/multi_ec2.py b/inventory/multi_ec2.py index 26c09d712..b839a33ea 100755 --- a/inventory/multi_ec2.py +++ b/inventory/multi_ec2.py @@ -1,22 +1,29 @@ #!/usr/bin/env python2 +''' + Fetch and combine multiple ec2 account settings into a single + json hash. +''' # vim: expandtab:tabstop=4:shiftwidth=4 from time import time import argparse import yaml import os -import sys -import pdb import subprocess import json -import pprint CONFIG_FILE_NAME = 'multi_ec2.yaml' class MultiEc2(object): + ''' + MultiEc2 class: + Opens a yaml config file and reads aws credentials. + Stores a json hash of resources in result. + ''' def __init__(self): + self.args = None self.config = None self.all_ec2_results = {} self.result = {} @@ -24,7 +31,7 @@ class MultiEc2(object): self.file_path = os.path.join(os.path.dirname(os.path.realpath(__file__))) same_dir_config_file = os.path.join(self.file_path, CONFIG_FILE_NAME) - etc_dir_config_file = os.path.join(os.path.sep, 'etc','ansible', CONFIG_FILE_NAME) + etc_dir_config_file = os.path.join(os.path.sep, 'etc', 'ansible', CONFIG_FILE_NAME) # Prefer a file in the same directory, fall back to a file in etc if os.path.isfile(same_dir_config_file): @@ -39,12 +46,13 @@ class MultiEc2(object): # load yaml if self.config_file and os.path.isfile(self.config_file): self.config = self.load_yaml_config() - elif os.environ.has_key("AWS_ACCESS_KEY_ID") and os.environ.has_key("AWS_SECRET_ACCESS_KEY"): + elif os.environ.has_key("AWS_ACCESS_KEY_ID") and \ + os.environ.has_key("AWS_SECRET_ACCESS_KEY"): self.config = {} self.config['accounts'] = [ { 'name': 'default', - 'provider': 'aws/ec2.py', + 'provider': 'aws/hosts/ec2.py', 'env_vars': { 'AWS_ACCESS_KEY_ID': os.environ["AWS_ACCESS_KEY_ID"], 'AWS_SECRET_ACCESS_KEY': os.environ["AWS_SECRET_ACCESS_KEY"], @@ -56,13 +64,9 @@ class MultiEc2(object): else: raise RuntimeError("Could not find valid ec2 credentials in the environment.") - if self.args.cache_only: - # get data from disk - result = self.get_inventory_from_cache() - - if not result: - self.get_inventory() - self.write_to_cache() + if self.args.refresh_cache: + self.get_inventory() + self.write_to_cache() # if its a host query, fetch and do not cache elif self.args.host: self.get_inventory() @@ -74,7 +78,7 @@ class MultiEc2(object): # get data from disk self.get_inventory_from_cache() - def load_yaml_config(self,conf_file=None): + def load_yaml_config(self, conf_file=None): """Load a yaml config file with credentials to query the respective cloud for inventory. """ @@ -88,7 +92,7 @@ class MultiEc2(object): return config - def get_provider_tags(self,provider, env={}): + def get_provider_tags(self, provider, env=None): """Call and query all of the tags that are usuable by ansible. If environment is empty use the default env. """ @@ -153,7 +157,8 @@ class MultiEc2(object): self.all_ec2_results[result['name']] = json.loads(result['out']) values = self.all_ec2_results.values() values.insert(0, self.result) - [MultiEc2.merge_destructively(self.result, x) for x in values] + for result in values: + MultiEc2.merge_destructively(self.result, result) else: # For any 0 result, return it count = 0 @@ -165,30 +170,30 @@ class MultiEc2(object): raise RuntimeError("Found > 1 results for --host %s. \ This is an invalid state." % self.args.host) @staticmethod - def merge_destructively(a, b): - "merges b into a" - for key in b: - if key in a: - if isinstance(a[key], dict) and isinstance(b[key], dict): - MultiEc2.merge_destructively(a[key], b[key]) - elif a[key] == b[key]: + def merge_destructively(input_a, input_b): + "merges b into input_a" + for key in input_b: + if key in input_a: + if isinstance(input_a[key], dict) and isinstance(input_b[key], dict): + MultiEc2.merge_destructively(input_a[key], input_b[key]) + elif input_a[key] == input_b[key]: pass # same leaf value # both lists so add each element in b to a if it does ! exist - elif isinstance(a[key], list) and isinstance(b[key],list): - for x in b[key]: - if x not in a[key]: - a[key].append(x) + elif isinstance(input_a[key], list) and isinstance(input_b[key], list): + for result in input_b[key]: + if result not in input_a[key]: + input_a[key].input_append(result) # a is a list and not b - elif isinstance(a[key], list): - if b[key] not in a[key]: - a[key].append(b[key]) - elif isinstance(b[key], list): - a[key] = [a[key]] + [k for k in b[key] if k != a[key]] + elif isinstance(input_a[key], list): + if input_b[key] not in input_a[key]: + input_a[key].append(input_b[key]) + elif isinstance(input_b[key], list): + input_a[key] = [input_a[key]] + [k for k in input_b[key] if k != input_a[key]] else: - a[key] = [a[key],b[key]] + input_a[key] = [input_a[key], input_b[key]] else: - a[key] = b[key] - return a + input_a[key] = input_b[key] + return input_a def is_cache_valid(self): ''' Determines if the cache files have expired, or if it is still valid ''' @@ -204,19 +209,20 @@ class MultiEc2(object): def parse_cli_args(self): ''' Command line argument processing ''' - parser = argparse.ArgumentParser(description='Produce an Ansible Inventory file based on a provider') - parser.add_argument('--cache-only', action='store_true', default=False, - help='Fetch cached only instances (default: False)') + parser = argparse.ArgumentParser( + description='Produce an Ansible Inventory file based on a provider') + parser.add_argument('--refresh-cache', action='store_true', default=False, + help='Fetch cached only instances (default: False)') parser.add_argument('--list', action='store_true', default=True, - help='List instances (default: True)') + help='List instances (default: True)') parser.add_argument('--host', action='store', default=False, - help='Get all the variables about a specific instance') + help='Get all the variables about a specific instance') self.args = parser.parse_args() def write_to_cache(self): ''' Writes data in JSON format to a file ''' - json_data = self.json_format_dict(self.result, True) + json_data = MultiEc2.json_format_dict(self.result, True) with open(self.cache_path, 'w') as cache: cache.write(json_data) @@ -232,7 +238,8 @@ class MultiEc2(object): return True - def json_format_dict(self, data, pretty=False): + @classmethod + def json_format_dict(cls, data, pretty=False): ''' Converts a dict to a JSON object and dumps it as a formatted string ''' @@ -242,9 +249,9 @@ class MultiEc2(object): return json.dumps(data) def result_str(self): + '''Return cache string stored in self.result''' return self.json_format_dict(self.result, True) if __name__ == "__main__": - mi = MultiEc2() - print mi.result_str() + print MultiEc2().result_str() diff --git a/inventory/multi_ec2.yaml.example b/inventory/multi_ec2.yaml.example index 0bd505816..91e7c7970 100644 --- a/inventory/multi_ec2.yaml.example +++ b/inventory/multi_ec2.yaml.example @@ -1,13 +1,13 @@ # multi ec2 inventory configs accounts: - name: aws1 - provider: aws/ec2.py + provider: aws/hosts/ec2.py env_vars: AWS_ACCESS_KEY_ID: XXXXXXXXXXXXXXXXXXXX AWS_SECRET_ACCESS_KEY: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - name: aws2 - provider: aws/ec2.py + provider: aws/hosts/ec2.py env_vars: AWS_ACCESS_KEY_ID: XXXXXXXXXXXXXXXXXXXX AWS_SECRET_ACCESS_KEY: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -- cgit v1.2.3 From 8f0e10e33726db46da1882b03d2e3a6a9689924c Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Wed, 22 Apr 2015 16:15:26 -0400 Subject: Adding commit hooks for jenkins --- git/.pylintrc | 390 +++++++++++++++++++++++++++++++++++++++++++++++++ git/parent.rb | 45 ++++++ git/pylint.sh | 12 ++ git/yaml_validation.rb | 72 +++++++++ 4 files changed, 519 insertions(+) create mode 100644 git/.pylintrc create mode 100755 git/parent.rb create mode 100755 git/pylint.sh create mode 100755 git/yaml_validation.rb diff --git a/git/.pylintrc b/git/.pylintrc new file mode 100644 index 000000000..2d45f867e --- /dev/null +++ b/git/.pylintrc @@ -0,0 +1,390 @@ +[MASTER] + +# Specify a configuration file. +#rcfile= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Profiled execution. +profile=no + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS + +# Pickle collected data for later comparisons. +persistent=no + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + +# Deprecated. It was used to include message's id in output. Use --msg-template +# instead. +#include-ids=no + +# Deprecated. It was used to include symbolic ids of messages in output. Use +# --msg-template instead. +#symbols=no + +# Use multiple processes to speed up Pylint. +jobs=1 + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code +extension-pkg-whitelist= + +# Allow optimization of some AST trees. This will activate a peephole AST +# optimizer, which will apply various small optimizations. For instance, it can +# be used to obtain the result of joining multiple strings with the addition +# operator. Joining a lot of strings can lead to a maximum recursion error in +# Pylint and this flag can prevent that. It has one side effect, the resulting +# AST will be different than the one from reality. +optimize-ast=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time. See also the "--disable" option for examples. +#enable= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +disable=E1608,W1627,E1601,E1603,E1602,E1605,E1604,E1607,E1606,W1621,W1620,W1623,W1622,W1625,W1624,W1609,W1608,W1607,W1606,W1605,W1604,W1603,W1602,W1601,W1639,W1640,I0021,W1638,I0020,W1618,W1619,W1630,W1626,W1637,W1634,W1635,W1610,W1611,W1612,W1613,W1614,W1615,W1616,W1617,W1632,W1633,W0704,W1628,W1629,W1636 + + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html. You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". +files-output=no + +# Tells whether to display a full report or only the messages +reports=no + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Add a comment according to your evaluation note. This is used by the global +# evaluation report (RP0004). +comment=no + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging + + +[BASIC] + +# Required attributes for module, separated by a comma +required-attributes= + +# List of builtins function names that should not be used, separated by a comma +bad-functions=map,filter,input + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,ex,Run,_ + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# Regular expression matching correct function names +function-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for function names +function-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct variable names +variable-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for variable names +variable-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct constant names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Naming hint for constant names +const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Regular expression matching correct attribute names +attr-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for attribute names +attr-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct argument names +argument-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for argument names +argument-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct class attribute names +class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Naming hint for class attribute names +class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Regular expression matching correct inline iteration names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Naming hint for inline iteration names +inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ + +# Regular expression matching correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Naming hint for class names +class-name-hint=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression matching correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Naming hint for module names +module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression matching correct method names +method-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for method names +method-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=__.*__ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=_$|dummy + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_,_cb + + +[TYPECHECK] + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis +ignored-modules= + +# List of classes names for which member attributes should not be checked +# (useful for classes with attributes dynamically set). +ignored-classes=SQLObject + +# When zope mode is activated, add a predefined set of Zope acquired attributes +# to generated-members. +zope=no + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E0201 when accessed. Python regular +# expressions are accepted. +generated-members=REQUEST,acl_users,aq_parent + + +[SPELLING] + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME,XXX,TODO + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=100 + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + +# List of optional constructs for which whitespace checking is disabled +no-space-check=trailing-comma,dict-separator + +# Maximum number of lines in a module +max-module-lines=1000 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=5 + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.* + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of branch for function / method body +max-branches=12 + +# Maximum number of statements in function / method body +max-statements=50 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + + +[CLASSES] + +# List of interface methods to ignore, separated by a comma. This is used for +# instance to not check methods defines in Zope's Interface base class. +ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict,_fields,_replace,_source,_make + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub,TERMIOS,Bastion,rexec + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=Exception diff --git a/git/parent.rb b/git/parent.rb new file mode 100755 index 000000000..2acb127c4 --- /dev/null +++ b/git/parent.rb @@ -0,0 +1,45 @@ +#!/usr/bin/env ruby +# +# +# + +if __FILE__ == $0 + # If we aren't on master we don't need to parent check + branch = 'prod' + exit(0) if ARGV[0] !~ /#{branch}/ + commit_id = ARGV[1] + %x[/usr/bin/git checkout #{branch}] + %x[/usr/bin/git merge #{commit_id}] + + count = 0 + #lines = %x[/usr/bin/git rev-list --left-right stg...master].split("\n") + lines = %x[/usr/bin/git rev-list --left-right remotes/origin/stg...#{branch}].split("\n") + lines.each do |commit| + # next if they are in stage + next if commit =~ /^' + commit = commit[1..-1] + # check if any remote branches contain $commit + results = %x[/usr/bin/git branch -q -r --contains #{commit} 2>/dev/null ] + # if this comes back empty, nothing contains it, we can skip it as + # we have probably created the merge commit here locally + next if results.empty? + + # The results generally contain origin/pr/246/merge and origin/pr/246/head + # this is the pull request which would contain the commit in question. + # + # If the results do not contain origin/stg then stage does not contain + # the commit in question. Therefore we need to alert! + unless results =~ /origin\/stg/ + puts "\nFAILED: (These commits are not in stage.)\n" + puts "\t#{commit}" + count += 1 + end + end + + # Exit with count of commits in #{branch} but not stg + exit(count) +end + +__END__ + diff --git a/git/pylint.sh b/git/pylint.sh new file mode 100755 index 000000000..73d08e00c --- /dev/null +++ b/git/pylint.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + + +OLDREV=$1 +NEWREV=$2 +TRG_BRANCH=$3 + +/usr/bin/git diff --name-only $OLDREV $NEWREV --diff-filter=ACM | \ + grep ".py$" | \ + xargs -r -I{} /usr/bin/python -m pylint --rcfile ${WORKSPACE}/git/.pylintrc {} + +exit $? diff --git a/git/yaml_validation.rb b/git/yaml_validation.rb new file mode 100755 index 000000000..f5ded7a78 --- /dev/null +++ b/git/yaml_validation.rb @@ -0,0 +1,72 @@ +#!/usr/bin/env ruby +# +# +# +require 'yaml' +require 'tmpdir' + +class YamlValidate + def self.yaml_file?(filename) + return filename.end_with?('.yaml') || filename.end_with?('.yml') + end + + def self.short_yaml_ext?(filename) + return filename.end_with?(".yml") + end + + def self.valid_yaml?(filename) + YAML::load_file(filename) + + return true + end +end + +class GitCommit + attr_accessor :oldrev, :newrev, :refname, :tmp + def initialize(oldrev, newrev, refname) + @oldrev = oldrev + @newrev = newrev + @refname = refname + @tmp = Dir.mktmpdir(@newrev) + end + + def get_file_changes() + files = %x[/usr/bin/git diff --name-only #{@oldrev} #{@newrev} --diff-filter=ACM].split("\n") + + # if files is empty we will get a full checkout. This happens on + # a git rm file. If there are no changes then we need to skip the archive + return [] if files.empty? + + # We only want to take the files that changed. Archive will do that when passed + # the filenames. It will export these to a tmp dir + system("/usr/bin/git archive #{@newrev} #{files.join(" ")} | tar x -C #{@tmp}") + return Dir.glob("#{@tmp}/**/*").delete_if { |file| File.directory?(file) } + end +end + +if __FILE__ == $0 + while data = STDIN.gets + oldrev, newrev, refname = data.split + gc = GitCommit.new(oldrev, newrev, refname) + + results = [] + gc.get_file_changes().each do |file| + begin + puts "++++++ Received: #{file}" + + #raise "Yaml file extensions must be .yaml not .yml" if YamlValidate.short_yaml_ext? file + + # skip readme, other files, etc + next unless YamlValidate.yaml_file?(file) + + results << YamlValidate.valid_yaml?(file) + rescue Exception => ex + puts "\n#{ex.message}\n\n" + results << false + end + end + + #puts "RESULTS\n#{results.inspect}\n" + exit 1 if results.include?(false) + end +end -- cgit v1.2.3 From 50acabea188347ae76c5215dd25c08dd02fc0f65 Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Wed, 22 Apr 2015 16:47:34 -0400 Subject: Adding pylint binary call instead of python module --- git/pylint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git/pylint.sh b/git/pylint.sh index 73d08e00c..e070fe7b2 100755 --- a/git/pylint.sh +++ b/git/pylint.sh @@ -7,6 +7,6 @@ TRG_BRANCH=$3 /usr/bin/git diff --name-only $OLDREV $NEWREV --diff-filter=ACM | \ grep ".py$" | \ - xargs -r -I{} /usr/bin/python -m pylint --rcfile ${WORKSPACE}/git/.pylintrc {} + xargs -r -I{} pylint --rcfile ${WORKSPACE}/git/.pylintrc {} exit $? -- cgit v1.2.3 From 6792e2c58ea21bd67a36ff4571301782c9f64009 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Wed, 22 Apr 2015 14:10:15 -0400 Subject: Allow variable overriding for ec2 deployment_vars - users can now override the deployment_vars variables with the assocated ec2_* variables - added deployment_type and env specific vars files that load some ec2_* overrides - added the ability to search for amis by ami_name - this allows us to specify a base name with a wildcard to have the playbook choose the latest available image for that image name - added a copy of the ec2_find_ami module that will be in ansible 2.0 until we can make ansible 2.0 a requirement. --- filter_plugins/oo_filters.py | 83 +++--- playbooks/aws/openshift-cluster/launch.yml | 1 + .../aws/openshift-cluster/library/ec2_ami_find.py | 302 +++++++++++++++++++++ .../openshift-cluster/tasks/launch_instances.yml | 76 ++++-- playbooks/aws/openshift-cluster/vars.defaults.yml | 1 + .../aws/openshift-cluster/vars.online.int.yml | 9 + .../aws/openshift-cluster/vars.online.prod.yml | 9 + .../aws/openshift-cluster/vars.online.stage.yml | 9 + playbooks/aws/openshift-cluster/vars.yml | 13 +- 9 files changed, 445 insertions(+), 58 deletions(-) create mode 100644 playbooks/aws/openshift-cluster/library/ec2_ami_find.py create mode 100644 playbooks/aws/openshift-cluster/vars.defaults.yml create mode 100644 playbooks/aws/openshift-cluster/vars.online.int.yml create mode 100644 playbooks/aws/openshift-cluster/vars.online.prod.yml create mode 100644 playbooks/aws/openshift-cluster/vars.online.stage.yml diff --git a/filter_plugins/oo_filters.py b/filter_plugins/oo_filters.py index cf30cde9a..d22b6d188 100644 --- a/filter_plugins/oo_filters.py +++ b/filter_plugins/oo_filters.py @@ -1,14 +1,17 @@ #!/usr/bin/python # -*- coding: utf-8 -*- # vim: expandtab:tabstop=4:shiftwidth=4 +''' +Custom filters for use in openshift-ansible +''' -from ansible import errors, runner -import json +from ansible import errors +from operator import itemgetter import pdb -import re def oo_pdb(arg): - ''' This pops you into a pdb instance where arg is the data passed in from the filter. + ''' This pops you into a pdb instance where arg is the data passed in + from the filter. Ex: "{{ hostvars | oo_pdb }}" ''' pdb.set_trace() @@ -21,7 +24,8 @@ def oo_len(arg): return len(arg) def get_attr(data, attribute=None): - ''' This looks up dictionary attributes of the form a.b.c and returns the value. + ''' This looks up dictionary attributes of the form a.b.c and returns + the value. Ex: data = {'a': {'b': {'c': 5}}} attribute = "a.b.c" returns 5 @@ -41,12 +45,13 @@ def oo_flatten(data): if not issubclass(type(data), list): raise errors.AnsibleFilterError("|failed expects to flatten a List") - return [ item for sublist in data for item in sublist ] + return [item for sublist in data for item in sublist] -def oo_collect(data, attribute=None, filters={}): - ''' This takes a list of dict and collects all attributes specified into a list - If filter is specified then we will include all items that match _ALL_ of filters. +def oo_collect(data, attribute=None, filters=None): + ''' This takes a list of dict and collects all attributes specified into a + list If filter is specified then we will include all items that match + _ALL_ of filters. Ex: data = [ {'a':1, 'b':5, 'z': 'z'}, # True, return {'a':2, 'z': 'z'}, # True, return {'a':3, 'z': 'z'}, # True, return @@ -56,15 +61,18 @@ def oo_collect(data, attribute=None, filters={}): filters = {'z': 'z'} returns [1, 2, 3] ''' - if not issubclass(type(data), list): raise errors.AnsibleFilterError("|failed expects to filter on a List") if not attribute: raise errors.AnsibleFilterError("|failed expects attribute to be set") - if filters: - retval = [get_attr(d, attribute) for d in data if all([ d[key] == filters[key] for key in filters ]) ] + if filters is not None: + if not issubclass(type(filters), dict): + raise errors.AnsibleFilterError("|fialed expects filter to be a" + " dict") + retval = [get_attr(d, attribute) for d in data if ( + all([d[key] == filters[key] for key in filters]))] else: retval = [get_attr(d, attribute) for d in data] @@ -78,7 +86,7 @@ def oo_select_keys(data, keys): ''' if not issubclass(type(data), dict): - raise errors.AnsibleFilterError("|failed expects to filter on a Dictionary") + raise errors.AnsibleFilterError("|failed expects to filter on a dict") if not issubclass(type(keys), list): raise errors.AnsibleFilterError("|failed expects first param is a list") @@ -98,30 +106,43 @@ def oo_prepend_strings_in_list(data, prepend): if not issubclass(type(data), list): raise errors.AnsibleFilterError("|failed expects first param is a list") if not all(isinstance(x, basestring) for x in data): - raise errors.AnsibleFilterError("|failed expects first param is a list of strings") + raise errors.AnsibleFilterError("|failed expects first param is a list" + " of strings") retval = [prepend + s for s in data] return retval -def oo_get_deployment_type_from_groups(data): - ''' This takes a list of groups and returns the associated - deployment-type +def oo_ami_selector(data, image_name): + ''' This takes a list of amis and an image name and attempts to return + the latest ami. ''' if not issubclass(type(data), list): raise errors.AnsibleFilterError("|failed expects first param is a list") - regexp = re.compile('^tag_deployment-type[-_]') - matches = filter(regexp.match, data) - if len(matches) > 0: - return regexp.sub('', matches[0]) - return "Unknown" -class FilterModule (object): + if not data: + return None + else: + if image_name is None or not image_name.endswith('_*'): + ami = sorted(data, key=itemgetter('name'), reverse=True)[0] + return ami['ami_id'] + else: + ami_info = [(ami, ami['name'].split('_')[-1]) for ami in data] + ami = sorted(ami_info, key=itemgetter(1), reverse=True)[0][0] + return ami['ami_id'] + +# disabling pylint checks for too-few-public-methods and no-self-use since we +# need to expose a FilterModule object that has a filters method that returns +# a mapping of filter names to methods. +# pylint: disable=too-few-public-methods, no-self-use +class FilterModule(object): + ''' FilterModule ''' def filters(self): + ''' returns a mapping of filters to methods ''' return { - "oo_select_keys": oo_select_keys, - "oo_collect": oo_collect, - "oo_flatten": oo_flatten, - "oo_len": oo_len, - "oo_pdb": oo_pdb, - "oo_prepend_strings_in_list": oo_prepend_strings_in_list, - "oo_get_deployment_type_from_groups": oo_get_deployment_type_from_groups - } + "oo_select_keys": oo_select_keys, + "oo_collect": oo_collect, + "oo_flatten": oo_flatten, + "oo_len": oo_len, + "oo_pdb": oo_pdb, + "oo_prepend_strings_in_list": oo_prepend_strings_in_list, + "oo_ami_selector": oo_ami_selector + } diff --git a/playbooks/aws/openshift-cluster/launch.yml b/playbooks/aws/openshift-cluster/launch.yml index a0de00fc3..3eb5496e4 100644 --- a/playbooks/aws/openshift-cluster/launch.yml +++ b/playbooks/aws/openshift-cluster/launch.yml @@ -5,6 +5,7 @@ gather_facts: no vars_files: - vars.yml + - ["vars.{{ deployment_type }}.{{ cluster_id }}.yml", vars.defaults.yml] tasks: - fail: msg: Deployment type not supported for aws provider yet diff --git a/playbooks/aws/openshift-cluster/library/ec2_ami_find.py b/playbooks/aws/openshift-cluster/library/ec2_ami_find.py new file mode 100644 index 000000000..29e594a65 --- /dev/null +++ b/playbooks/aws/openshift-cluster/library/ec2_ami_find.py @@ -0,0 +1,302 @@ +#!/usr/bin/python +#pylint: skip-file +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +DOCUMENTATION = ''' +--- +module: ec2_ami_find +version_added: 2.0 +short_description: Searches for AMIs to obtain the AMI ID and other information +description: + - Returns list of matching AMIs with AMI ID, along with other useful information + - Can search AMIs with different owners + - Can search by matching tag(s), by AMI name and/or other criteria + - Results can be sorted and sliced +author: Tom Bamford +notes: + - This module is not backwards compatible with the previous version of the ec2_search_ami module which worked only for Ubuntu AMIs listed on cloud-images.ubuntu.com. + - See the example below for a suggestion of how to search by distro/release. +options: + region: + description: + - The AWS region to use. + required: true + aliases: [ 'aws_region', 'ec2_region' ] + owner: + description: + - Search AMIs owned by the specified owner + - Can specify an AWS account ID, or one of the special IDs 'self', 'amazon' or 'aws-marketplace' + - If not specified, all EC2 AMIs in the specified region will be searched. + - You can include wildcards in many of the search options. An asterisk (*) matches zero or more characters, and a question mark (?) matches exactly one character. You can escape special characters using a backslash (\) before the character. For example, a value of \*amazon\?\\ searches for the literal string *amazon?\. + required: false + default: null + ami_id: + description: + - An AMI ID to match. + default: null + required: false + ami_tags: + description: + - A hash/dictionary of tags to match for the AMI. + default: null + required: false + architecture: + description: + - An architecture type to match (e.g. x86_64). + default: null + required: false + hypervisor: + description: + - A hypervisor type type to match (e.g. xen). + default: null + required: false + is_public: + description: + - Whether or not the image(s) are public. + choices: ['yes', 'no'] + default: null + required: false + name: + description: + - An AMI name to match. + default: null + required: false + platform: + description: + - Platform type to match. + default: null + required: false + sort: + description: + - Optional attribute which with to sort the results. + - If specifying 'tag', the 'tag_name' parameter is required. + choices: ['name', 'description', 'tag'] + default: null + required: false + sort_tag: + description: + - Tag name with which to sort results. + - Required when specifying 'sort=tag'. + default: null + required: false + sort_order: + description: + - Order in which to sort results. + - Only used when the 'sort' parameter is specified. + choices: ['ascending', 'descending'] + default: 'ascending' + required: false + sort_start: + description: + - Which result to start with (when sorting). + - Corresponds to Python slice notation. + default: null + required: false + sort_end: + description: + - Which result to end with (when sorting). + - Corresponds to Python slice notation. + default: null + required: false + state: + description: + - AMI state to match. + default: 'available' + required: false + virtualization_type: + description: + - Virtualization type to match (e.g. hvm). + default: null + required: false + no_result_action: + description: + - What to do when no results are found. + - "'success' reports success and returns an empty array" + - "'fail' causes the module to report failure" + choices: ['success', 'fail'] + default: 'success' + required: false +requirements: + - boto + +''' + +EXAMPLES = ''' +# Note: These examples do not set authentication details, see the AWS Guide for details. + +# Search for the AMI tagged "project:website" +- ec2_ami_find: + owner: self + tags: + project: website + no_result_action: fail + register: ami_find + +# Search for the latest Ubuntu 14.04 AMI +- ec2_ami_find: + name: "ubuntu/images/ebs/ubuntu-trusty-14.04-amd64-server-*" + owner: 099720109477 + sort: name + sort_order: descending + sort_end: 1 + register: ami_find + +# Launch an EC2 instance +- ec2: + image: "{{ ami_search.results[0].ami_id }}" + instance_type: m3.medium + key_name: mykey + wait: yes +''' + +try: + import boto.ec2 + HAS_BOTO=True +except ImportError: + HAS_BOTO=False + +import json + +def main(): + argument_spec = ec2_argument_spec() + argument_spec.update(dict( + region = dict(required=True, + aliases = ['aws_region', 'ec2_region']), + owner = dict(required=False, default=None), + ami_id = dict(required=False), + ami_tags = dict(required=False, type='dict', + aliases = ['search_tags', 'image_tags']), + architecture = dict(required=False), + hypervisor = dict(required=False), + is_public = dict(required=False), + name = dict(required=False), + platform = dict(required=False), + sort = dict(required=False, default=None, + choices=['name', 'description', 'tag']), + sort_tag = dict(required=False), + sort_order = dict(required=False, default='ascending', + choices=['ascending', 'descending']), + sort_start = dict(required=False), + sort_end = dict(required=False), + state = dict(required=False, default='available'), + virtualization_type = dict(required=False), + no_result_action = dict(required=False, default='success', + choices = ['success', 'fail']), + ) + ) + + module = AnsibleModule( + argument_spec=argument_spec, + ) + + if not HAS_BOTO: + module.fail_json(msg='boto required for this module, install via pip or your package manager') + + ami_id = module.params.get('ami_id') + ami_tags = module.params.get('ami_tags') + architecture = module.params.get('architecture') + hypervisor = module.params.get('hypervisor') + is_public = module.params.get('is_public') + name = module.params.get('name') + owner = module.params.get('owner') + platform = module.params.get('platform') + sort = module.params.get('sort') + sort_tag = module.params.get('sort_tag') + sort_order = module.params.get('sort_order') + sort_start = module.params.get('sort_start') + sort_end = module.params.get('sort_end') + state = module.params.get('state') + virtualization_type = module.params.get('virtualization_type') + no_result_action = module.params.get('no_result_action') + + filter = {'state': state} + + if ami_id: + filter['image_id'] = ami_id + if ami_tags: + for tag in ami_tags: + filter['tag:'+tag] = ami_tags[tag] + if architecture: + filter['architecture'] = architecture + if hypervisor: + filter['hypervisor'] = hypervisor + if is_public: + filter['is_public'] = is_public + if name: + filter['name'] = name + if platform: + filter['platform'] = platform + if virtualization_type: + filter['virtualization_type'] = virtualization_type + + ec2 = ec2_connect(module) + + images_result = ec2.get_all_images(owners=owner, filters=filter) + + if no_result_action == 'fail' and len(images_result) == 0: + module.fail_json(msg="No AMIs matched the attributes: %s" % json.dumps(filter)) + + results = [] + for image in images_result: + data = { + 'ami_id': image.id, + 'architecture': image.architecture, + 'description': image.description, + 'is_public': image.is_public, + 'name': image.name, + 'owner_id': image.owner_id, + 'platform': image.platform, + 'root_device_name': image.root_device_name, + 'root_device_type': image.root_device_type, + 'state': image.state, + 'tags': image.tags, + 'virtualization_type': image.virtualization_type, + } + + if image.kernel_id: + data['kernel_id'] = image.kernel_id + if image.ramdisk_id: + data['ramdisk_id'] = image.ramdisk_id + + results.append(data) + + if sort == 'tag': + if not sort_tag: + module.fail_json(msg="'sort_tag' option must be given with 'sort=tag'") + results.sort(key=lambda e: e['tags'][sort_tag], reverse=(sort_order=='descending')) + elif sort: + results.sort(key=lambda e: e[sort], reverse=(sort_order=='descending')) + + try: + if sort and sort_start and sort_end: + results = results[int(sort_start):int(sort_end)] + elif sort and sort_start: + results = results[int(sort_start):] + elif sort and sort_end: + results = results[:int(sort_end)] + except TypeError: + module.fail_json(msg="Please supply numeric values for sort_start and/or sort_end") + + module.exit_json(results=results) + +# import module snippets +from ansible.module_utils.basic import * +from ansible.module_utils.ec2 import * + +if __name__ == '__main__': + main() + diff --git a/playbooks/aws/openshift-cluster/tasks/launch_instances.yml b/playbooks/aws/openshift-cluster/tasks/launch_instances.yml index 34172396a..39ad9d089 100644 --- a/playbooks/aws/openshift-cluster/tasks/launch_instances.yml +++ b/playbooks/aws/openshift-cluster/tasks/launch_instances.yml @@ -4,32 +4,64 @@ env: "{{ cluster }}" env_host_type: "{{ cluster }}-openshift-{{ type }}" host_type: "{{ type }}" - machine_type: "{{ lookup('env', 'ec2_instance_type') - | default(deployment_vars[deployment_type].type, true) }}" - machine_image: "{{ lookup('env', 'ec2_ami') - | default(deployment_vars[deployment_type].image, true) }}" - machine_region: "{{ lookup('env', 'ec2_region') - | default(deployment_vars[deployment_type].region, true) }}" - machine_keypair: "{{ lookup('env', 'ec2_keypair') - | default(deployment_vars[deployment_type].keypair, true) }}" - machine_subnet: "{{ lookup('env', 'ec2_vpc_subnet') - | default(deployment_vars[deployment_type].vpc_subnet, true) }}" - machine_public_ip: "{{ lookup('env', 'ec2_public_ip') - | default(deployment_vars[deployment_type].assign_public_ip, true) }}" - security_groups: "{{ lookup('env', 'ec2_security_groups') - | default(deployment_vars[deployment_type].security_groups, true) }}" + +- set_fact: + ec2_region: "{{ lookup('env', 'ec2_region') + | default(deployment_vars[deployment_type].region, true) }}" + when: ec2_region is not defined +- set_fact: + ec2_image_name: "{{ lookup('env', 'ec2_image_name') + | default(deployment_vars[deployment_type].image_name, true) }}" + when: ec2_image_name is not defined and ec2_image is not defined +- set_fact: + ec2_image: "{{ lookup('env', 'ec2_image') + | default(deployment_vars[deployment_type].image, true) }}" + when: ec2_image is not defined and not ec2_image_name +- set_fact: + ec2_instance_type: "{{ lookup('env', 'ec2_instance_type') + | default(deployment_vars[deployment_type].type, true) }}" + when: ec2_instance_type is not defined +- set_fact: + ec2_keypair: "{{ lookup('env', 'ec2_keypair') + | default(deployment_vars[deployment_type].keypair, true) }}" + when: ec2_keypair is not defined +- set_fact: + ec2_vpc_subnet: "{{ lookup('env', 'ec2_vpc_subnet') + | default(deployment_vars[deployment_type].vpc_subnet, true) }}" + when: ec2_vpc_subnet is not defined +- set_fact: + ec2_assign_public_ip: "{{ lookup('env', 'ec2_assign_public_ip') + | default(deployment_vars[deployment_type].assign_public_ip, true) }}" + when: ec2_assign_public_ip is not defined +- set_fact: + ec2_security_groups: "{{ lookup('env', 'ec2_security_groups') + | default(deployment_vars[deployment_type].security_groups, true) }}" + when: ec2_security_groups is not defined + +- name: Find amis for deployment_type + ec2_ami_find: + region: "{{ ec2_region }}" + ami_id: "{{ ec2_image | default(omit, true) }}" + name: "{{ ec2_image_name | default(omit, true) }}" + register: ami_result + +- fail: msg="Could not find requested ami" + when: not ami_result.results + +- set_fact: + latest_ami: "{{ ami_result.results | oo_ami_selector(ec2_image_name) }}" - name: Launch instance(s) ec2: state: present - region: "{{ machine_region }}" - keypair: "{{ machine_keypair }}" - group: "{{ security_groups }}" - instance_type: "{{ machine_type }}" - image: "{{ machine_image }}" + region: "{{ ec2_region }}" + keypair: "{{ ec2_keypair }}" + group: "{{ ec2_security_groups }}" + instance_type: "{{ ec2_instance_type }}" + image: "{{ latest_ami }}" count: "{{ instances | oo_len }}" - vpc_subnet_id: "{{ machine_subnet | default(omit, true) }}" - assign_public_ip: "{{ machine_public_ip | default(omit, true) }}" + vpc_subnet_id: "{{ ec2_vpc_subnet | default(omit, true) }}" + assign_public_ip: "{{ ec2_assign_public_ip | default(omit, true) }}" wait: yes instance_tags: created-by: "{{ created_by }}" @@ -39,7 +71,7 @@ register: ec2 - name: Add Name tag to instances - ec2_tag: resource={{ item.1.id }} region={{ machine_region }} state=present + ec2_tag: resource={{ item.1.id }} region={{ ec2_region }} state=present with_together: - instances - ec2.instances diff --git a/playbooks/aws/openshift-cluster/vars.defaults.yml b/playbooks/aws/openshift-cluster/vars.defaults.yml new file mode 100644 index 000000000..ed97d539c --- /dev/null +++ b/playbooks/aws/openshift-cluster/vars.defaults.yml @@ -0,0 +1 @@ +--- diff --git a/playbooks/aws/openshift-cluster/vars.online.int.yml b/playbooks/aws/openshift-cluster/vars.online.int.yml new file mode 100644 index 000000000..12f79a9c1 --- /dev/null +++ b/playbooks/aws/openshift-cluster/vars.online.int.yml @@ -0,0 +1,9 @@ +--- +ec2_image: ami-906240f8 +ec2_image_name: libra-ops-rhel7* +ec2_region: us-east-1 +ec2_keypair: mmcgrath_libra +ec2_instance_type: m3.large +ec2_security_groups: [ 'int-v3' ] +ec2_vpc_subnet: subnet-987c0def +ec2_assign_public_ip: yes diff --git a/playbooks/aws/openshift-cluster/vars.online.prod.yml b/playbooks/aws/openshift-cluster/vars.online.prod.yml new file mode 100644 index 000000000..12f79a9c1 --- /dev/null +++ b/playbooks/aws/openshift-cluster/vars.online.prod.yml @@ -0,0 +1,9 @@ +--- +ec2_image: ami-906240f8 +ec2_image_name: libra-ops-rhel7* +ec2_region: us-east-1 +ec2_keypair: mmcgrath_libra +ec2_instance_type: m3.large +ec2_security_groups: [ 'int-v3' ] +ec2_vpc_subnet: subnet-987c0def +ec2_assign_public_ip: yes diff --git a/playbooks/aws/openshift-cluster/vars.online.stage.yml b/playbooks/aws/openshift-cluster/vars.online.stage.yml new file mode 100644 index 000000000..12f79a9c1 --- /dev/null +++ b/playbooks/aws/openshift-cluster/vars.online.stage.yml @@ -0,0 +1,9 @@ +--- +ec2_image: ami-906240f8 +ec2_image_name: libra-ops-rhel7* +ec2_region: us-east-1 +ec2_keypair: mmcgrath_libra +ec2_instance_type: m3.large +ec2_security_groups: [ 'int-v3' ] +ec2_vpc_subnet: subnet-987c0def +ec2_assign_public_ip: yes diff --git a/playbooks/aws/openshift-cluster/vars.yml b/playbooks/aws/openshift-cluster/vars.yml index f87e7aba3..07e453f89 100644 --- a/playbooks/aws/openshift-cluster/vars.yml +++ b/playbooks/aws/openshift-cluster/vars.yml @@ -3,6 +3,7 @@ deployment_vars: origin: # fedora, since centos requires marketplace image: ami-acd999c4 + image_name: region: us-east-1 ssh_user: fedora sudo: yes @@ -13,18 +14,20 @@ deployment_vars: assign_public_ip: online: # private ami - image: ami-906240f8 + image: ami-7a9e9812 + image_name: openshift-rhel7_* region: us-east-1 ssh_user: root sudo: no - keypair: mmcgrath_libra + keypair: libra type: m3.large - security_groups: [ 'int-v3' ] - vpc_subnet: subnet-987c0def - assign_public_ip: yes + security_groups: [ 'public' ] + vpc_subnet: + assign_public_ip: enterprise: # rhel-7.1, requires cloud access subscription image: ami-10663b78 + image_name: region: us-east-1 ssh_user: ec2-user sudo: yes -- cgit v1.2.3 From 720e1b7155f09a659637cc9564cd2e76042345bf Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Fri, 17 Apr 2015 15:50:30 -0400 Subject: Fixes for latest osc client config changes - also pylint fixes --- roles/openshift_master/tasks/main.yml | 18 +- .../library/kubernetes_register_node.py | 413 ++++++++++++++++----- roles/openshift_register_nodes/tasks/main.yml | 3 +- 3 files changed, 334 insertions(+), 100 deletions(-) diff --git a/roles/openshift_master/tasks/main.yml b/roles/openshift_master/tasks/main.yml index da184e972..28bdda618 100644 --- a/roles/openshift_master/tasks/main.yml +++ b/roles/openshift_master/tasks/main.yml @@ -84,15 +84,23 @@ - name: Start and enable openshift-master service: name=openshift-master enabled=yes state=started -- name: Create .kube directory +- name: Create the OpenShift client config dir(s) file: - path: /root/.kube + path: "~{{ item }}/.config/openshift" state: directory mode: 0700 + owner: "{{ item }}" + group: "{{ item }}" + with_items: + - root + - "{{ ansible_ssh_user }}" # 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 {{ openshift_cert_dir }}/openshift-client/.kubeconfig /root/.kube/.kubeconfig +- name: Create the OpenShift client config(s) + command: cp {{ openshift_cert_dir }}/openshift-client/.kubeconfig ~{{ item }}/.config/openshift/.config args: - creates: /root/.kube/.kubeconfig + creates: ~{{ item }}/.config/openshift/.config + with_items: + - root + - "{{ ansible_ssh_user }}" diff --git a/roles/openshift_register_nodes/library/kubernetes_register_node.py b/roles/openshift_register_nodes/library/kubernetes_register_node.py index 1ec977716..afa9eb27d 100755 --- a/roles/openshift_register_nodes/library/kubernetes_register_node.py +++ b/roles/openshift_register_nodes/library/kubernetes_register_node.py @@ -1,12 +1,21 @@ #!/usr/bin/python # -*- coding: utf-8 -*- # vim: expandtab:tabstop=4:shiftwidth=4 +# +# disable pylint checks +# temporarily disabled until items can be addressed: +# fixme - until all TODO comments have been addressed +# permanently disabled unless someone wants to refactor the object model: +# too-few-public-methods +# no-self-use +# too-many-arguments +# too-many-locals +# too-many-branches +# pylint:disable=fixme, too-many-arguments, no-self-use +# pylint:disable=too-many-locals, too-many-branches, too-few-public-methods +"""Ansible module to register a kubernetes node to the cluster""" import os -import multiprocessing -import socket -from subprocess import check_output, Popen -from decimal import * DOCUMENTATION = ''' --- @@ -93,73 +102,170 @@ EXAMPLES = ''' class ClientConfigException(Exception): + """Client Configuration Exception""" pass -class ClientConfig: +class ClientConfig(object): + """ Representation of a client config + + Attributes: + config (dict): dictionary representing the client configuration + + Args: + client_opts (list of str): client options to use + module (AnsibleModule): + + Raises: + ClientConfigException: + """ def __init__(self, client_opts, module): kubectl = module.params['kubectl_cmd'] - _, output, error = module.run_command(kubectl + ["config", "view", "-o", "json"] + client_opts, check_rc = True) + _, output, _ = module.run_command((kubectl + + ["config", "view", "-o", "json"] + + client_opts), check_rc=True) self.config = json.loads(output) if not (bool(self.config['clusters']) or bool(self.config['contexts']) or bool(self.config['current-context']) or bool(self.config['users'])): - raise ClientConfigException(msg="Client config missing required " \ - "values", - output=output) + raise ClientConfigException( + "Client config missing required values: %s" % output + ) def current_context(self): + """ Gets the current context for the client config + + Returns: + str: The current context as set in the config + """ return self.config['current-context'] def section_has_value(self, section_name, value): + """ Test if specified section contains a value + + Args: + section_name (str): config section to test + value (str): value to test if present + Returns: + bool: True if successful, false otherwise + """ section = self.config[section_name] if isinstance(section, dict): return value in section else: val = next((item for item in section - if item['name'] == value), None) + if item['name'] == value), None) return val is not None def has_context(self, context): + """ Test if specified context exists in config + + Args: + context (str): value to test if present + Returns: + bool: True if successful, false otherwise + """ return self.section_has_value('contexts', context) def has_user(self, user): + """ Test if specified user exists in config + + Args: + context (str): value to test if present + Returns: + bool: True if successful, false otherwise + """ return self.section_has_value('users', user) def has_cluster(self, cluster): + """ Test if specified cluster exists in config + + Args: + context (str): value to test if present + Returns: + bool: True if successful, false otherwise + """ return self.section_has_value('clusters', cluster) def get_value_for_context(self, context, attribute): + """ Get the value of attribute in context + + Args: + context (str): context to search + attribute (str): attribute wanted + Returns: + str: The value for attribute in context + """ contexts = self.config['contexts'] if isinstance(contexts, dict): return contexts[context][attribute] else: return next((c['context'][attribute] for c in contexts - if c['name'] == context), None) + if c['name'] == context), None) def get_user_for_context(self, context): + """ Get the user attribute in context + + Args: + context (str): context to search + Returns: + str: The value for the attribute in context + """ return self.get_value_for_context(context, 'user') def get_cluster_for_context(self, context): + """ Get the cluster attribute in context + + Args: + context (str): context to search + Returns: + str: The value for the attribute in context + """ return self.get_value_for_context(context, 'cluster') def get_namespace_for_context(self, context): + """ Get the namespace attribute in context + + Args: + context (str): context to search + Returns: + str: The value for the attribute in context + """ return self.get_value_for_context(context, 'namespace') -class Util: +class Util(object): + """Utility methods""" @staticmethod def remove_empty_elements(mapping): + """ Recursively removes empty elements from a dict + + Args: + mapping (dict): dict to remove empty attributes from + Returns: + dict: A copy of the dict with empty elements removed + """ if isinstance(mapping, dict): - m = mapping.copy() + copy = mapping.copy() for key, val in mapping.iteritems(): if not val: - del m[key] - return m + del copy[key] + return copy else: return mapping -class NodeResources: +class NodeResources(object): + """ Kubernetes Node Resources + + Attributes: + resources (dict): A dictionary representing the node resources + + Args: + version (str): kubernetes api version + cpu (str): string representation of the cpu resources for the node + memory (str): string representation of the memory resources for the + node + """ def __init__(self, version, cpu=None, memory=None): if version == 'v1beta1': self.resources = dict(capacity=dict()) @@ -167,10 +273,31 @@ class NodeResources: self.resources['capacity']['memory'] = memory def get_resources(self): + """ Get the dict representing the node resources + + Returns: + dict: representation of the node resources with any empty + elements removed + """ return Util.remove_empty_elements(self.resources) -class NodeSpec: - def __init__(self, version, cpu=None, memory=None, cidr=None, externalID=None): +class NodeSpec(object): + """ Kubernetes Node Spec + + Attributes: + spec (dict): A dictionary representing the node resources + + Args: + version (str): kubernetes api version + cpu (str): string representation of the cpu resources for the node + memory (str): string representation of the memory resources for the + node + cidr (str): string representation of the cidr block available for + the node + externalID (str): The external id of the node + """ + def __init__(self, version, cpu=None, memory=None, cidr=None, + externalID=None): if version == 'v1beta3': self.spec = dict(podCIDR=cidr, externalID=externalID, capacity=dict()) @@ -178,67 +305,128 @@ class NodeSpec: self.spec['capacity']['memory'] = memory def get_spec(self): + """ Get the dict representing the node spec + + Returns: + dict: representation of the node spec with any empty elements + removed + """ return Util.remove_empty_elements(self.spec) -class NodeStatus: - def addAddresses(self, addressType, addresses): - addressList = [] +class NodeStatus(object): + """ Kubernetes Node Status + + Attributes: + status (dict): A dictionary representing the node status + + Args: + version (str): kubernetes api version + externalIPs (list, optional): externalIPs for the node + internalIPs (list, optional): internalIPs for the node + hostnames (list, optional): hostnames for the node + """ + def add_addresses(self, address_type, addresses): + """ Adds addresses of the specified type + + Args: + address_type (str): address type + addresses (list): addresses to add + """ + address_list = [] for address in addresses: - addressList.append(dict(type=addressType, address=address)) - return addressList + address_list.append(dict(type=address_type, address=address)) + return address_list - def __init__(self, version, externalIPs = [], internalIPs = [], - hostnames = []): + def __init__(self, version, externalIPs=None, internalIPs=None, + hostnames=None): if version == 'v1beta3': - self.status = dict(addresses = addAddresses('ExternalIP', - externalIPs) + - addAddresses('InternalIP', - internalIPs) + - addAddresses('Hostname', - hostnames)) + addresses = [] + if externalIPs is not None: + addresses += self.add_addresses('ExternalIP', externalIPs) + if internalIPs is not None: + addresses += self.add_addresses('InternalIP', internalIPs) + if hostnames is not None: + addresses += self.add_addresses('Hostname', hostnames) + + self.status = dict(addresses=addresses) def get_status(self): + """ Get the dict representing the node status + + Returns: + dict: representation of the node status with any empty elements + removed + """ return Util.remove_empty_elements(self.status) -class Node: - def __init__(self, module, client_opts, version='v1beta1', name=None, - hostIP = None, hostnames=[], externalIPs=[], internalIPs=[], - cpu=None, memory=None, labels=dict(), annotations=dict(), - podCIDR=None, externalID=None): +class Node(object): + """ Kubernetes Node + + Attributes: + status (dict): A dictionary representing the node + + Args: + module (AnsibleModule): + client_opts (list): client connection options + version (str, optional): kubernetes api version + node_name (str, optional): name for node + hostIP (str, optional): node host ip + hostnames (list, optional): hostnames for the node + externalIPs (list, optional): externalIPs for the node + internalIPs (list, optional): internalIPs for the node + cpu (str, optional): cpu resources for the node + memory (str, optional): memory resources for the node + labels (list, optional): labels for the node + annotations (list, optional): annotations for the node + podCIDR (list, optional): cidr block to use for pods + externalID (str, optional): external id of the node + """ + def __init__(self, module, client_opts, version='v1beta1', node_name=None, + hostIP=None, hostnames=None, externalIPs=None, + internalIPs=None, cpu=None, memory=None, labels=None, + annotations=None, podCIDR=None, externalID=None): self.module = module self.client_opts = client_opts if version == 'v1beta1': - self.node = dict(id = name, - kind = 'Node', - apiVersion = version, - hostIP = hostIP, - resources = NodeResources(version, cpu, memory), - cidr = podCIDR, - labels = labels, - annotations = annotations, - externalID = externalID - ) + self.node = dict(id=node_name, + kind='Node', + apiVersion=version, + hostIP=hostIP, + resources=NodeResources(version, cpu, memory), + cidr=podCIDR, + labels=labels, + annotations=annotations, + externalID=externalID) elif version == 'v1beta3': - metadata = dict(name = name, - labels = labels, - annotations = annotations - ) - self.node = dict(kind = 'Node', - apiVersion = version, - metadata = metadata, - spec = NodeSpec(version, cpu, memory, podCIDR, - externalID), - status = NodeStatus(version, externalIPs, - internalIPs, hostnames), - ) + metadata = dict(name=node_name, + labels=labels, + annotations=annotations) + self.node = dict(kind='Node', + apiVersion=version, + metadata=metadata, + spec=NodeSpec(version, cpu, memory, podCIDR, + externalID), + status=NodeStatus(version, externalIPs, + internalIPs, hostnames)) def get_name(self): + """ Get the name for the node + + Returns: + str: node name + """ if self.node['apiVersion'] == 'v1beta1': return self.node['id'] elif self.node['apiVersion'] == 'v1beta3': return self.node['name'] def get_node(self): + """ Get the dict representing the node + + Returns: + dict: representation of the node with any empty elements + removed + """ node = self.node.copy() if self.node['apiVersion'] == 'v1beta1': node['resources'] = self.node['resources'].get_resources() @@ -248,54 +436,82 @@ class Node: return Util.remove_empty_elements(node) def exists(self): + """ Tests if the node already exists + + Returns: + bool: True if node exists, otherwise False + """ kubectl = self.module.params['kubectl_cmd'] - _, output, error = self.module.run_command(kubectl + ["get", "nodes"] + self.client_opts, check_rc = True) + _, output, _ = self.module.run_command((kubectl + ["get", "nodes"] + + self.client_opts), + check_rc=True) if re.search(self.module.params['name'], output, re.MULTILINE): return True return False def create(self): + """ Creates the node + + Returns: + bool: True if node creation successful + """ kubectl = self.module.params['kubectl_cmd'] cmd = kubectl + self.client_opts + ['create', '-f', '-'] - rc, output, error = self.module.run_command(cmd, - data=self.module.jsonify(self.get_node())) - if rc != 0: + exit_code, output, error = self.module.run_command( + cmd, data=self.module.jsonify(self.get_node()) + ) + if exit_code != 0: if re.search("minion \"%s\" already exists" % self.get_name(), error): - self.module.exit_json(changed=False, - msg="node definition already exists", - node=self.get_node()) + self.module.exit_json(msg="node definition already exists", + changed=False, node=self.get_node()) else: - self.module.fail_json(msg="Node creation failed.", rc=rc, - output=output, error=error, - node=self.get_node()) + self.module.fail_json(msg="Node creation failed.", + exit_code=exit_code, + output=output, error=error, + node=self.get_node()) else: return True def main(): + """ main """ module = AnsibleModule( - argument_spec = dict( - name = dict(required = True, type = 'str'), - host_ip = dict(type = 'str'), - hostnames = dict(type = 'list', default = []), - external_ips = dict(type = 'list', default = []), - internal_ips = dict(type = 'list', default = []), - api_version = dict(type = 'str', default = 'v1beta1', # TODO: after kube rebase, we can default to v1beta3 - choices = ['v1beta1', 'v1beta3']), - cpu = dict(type = 'str'), - memory = dict(type = 'str'), - labels = dict(type = 'dict', default = {}), # TODO: needs documented - annotations = dict(type = 'dict', default = {}), # TODO: needs documented - pod_cidr = dict(type = 'str'), # TODO: needs documented - external_id = dict(type = 'str'), # TODO: needs documented - client_config = dict(type = 'str'), # TODO: needs documented - client_cluster = dict(type = 'str', default = 'master'), # TODO: needs documented - client_context = dict(type = 'str', default = 'default'), # TODO: needs documented - client_namespace = dict(type = 'str', default = 'default'), # TODO: needs documented - client_user = dict(type = 'str', default = 'system:openshift-client'), # TODO: needs documented - kubectl_cmd = dict(type = 'list', default = ['kubectl']) # TODO: needs documented + argument_spec=dict( + name=dict(required=True, type='str'), + host_ip=dict(type='str'), + hostnames=dict(type='list', default=[]), + external_ips=dict(type='list', default=[]), + internal_ips=dict(type='list', default=[]), + api_version=dict(type='str', default='v1beta1', + choices=['v1beta1', 'v1beta3']), + cpu=dict(type='str'), + memory=dict(type='str'), + # TODO: needs documented + labels=dict(type='dict', default={}), + # TODO: needs documented + annotations=dict(type='dict', default={}), + # TODO: needs documented + pod_cidr=dict(type='str'), + # TODO: needs documented + external_id=dict(type='str'), + # TODO: needs documented + client_config=dict(type='str'), + # TODO: needs documented + client_cluster=dict(type='str', default='master'), + # TODO: needs documented + client_context=dict(type='str', default='default'), + # TODO: needs documented + client_namespace=dict(type='str', default='default'), + # TODO: needs documented + client_user=dict(type='str', default='system:openshift-client'), + # TODO: needs documented + kubectl_cmd=dict(type='list', default=['kubectl']), + # TODO: needs documented + kubeconfig_flag=dict(type='str'), + # TODO: needs documented + default_client_config=dict(type='str') ), - mutually_exclusive = [ + mutually_exclusive=[ ['host_ip', 'external_ips'], ['host_ip', 'internal_ips'], ['host_ip', 'hostnames'], @@ -303,7 +519,10 @@ def main(): supports_check_mode=True ) - user_has_client_config = os.path.exists(os.path.expanduser('~/.kube/.kubeconfig')) + client_config = '~/.kube/.kubeconfig' + if 'default_client_config' in module.params: + client_config = module.params['default_client_config'] + user_has_client_config = os.path.exists(os.path.expanduser(client_config)) if not (user_has_client_config or module.params['client_config']): module.fail_json(msg="Could not locate client configuration, " "client_config must be specified if " @@ -311,12 +530,17 @@ def main(): client_opts = [] if module.params['client_config']: - client_opts.append("--kubeconfig=%s" % module.params['client_config']) + kubeconfig_flag = '--kubeconfig' + if 'kubeconfig_flag' in module.params: + kubeconfig_flag = module.params['kubeconfig_flag'] + client_opts.append(kubeconfig_flag + '=' + + os.path.expanduser(module.params['client_config'])) try: config = ClientConfig(client_opts, module) - except ClientConfigException as e: - module.fail_json(msg="Failed to get client configuration", exception=e) + except ClientConfigException as ex: + module.fail_json(msg="Failed to get client configuration", + exception=str(ex)) client_context = module.params['client_context'] if config.has_context(client_context): @@ -369,7 +593,8 @@ def main(): module.fail_json(msg="Unknown error creating node", node=node.get_node()) - +# ignore pylint errors related to the module_utils import +# pylint: disable=redefined-builtin, unused-wildcard-import, wildcard-import # import module snippets from ansible.module_utils.basic import * if __name__ == '__main__': diff --git a/roles/openshift_register_nodes/tasks/main.yml b/roles/openshift_register_nodes/tasks/main.yml index 85bead16d..d4d72d126 100644 --- a/roles/openshift_register_nodes/tasks/main.yml +++ b/roles/openshift_register_nodes/tasks/main.yml @@ -39,7 +39,8 @@ - name: Register unregistered nodes kubernetes_register_node: - kubectl_cmd: ['openshift', 'kube'] + kubectl_cmd: ['osc'] + default_client_config: '~/.config/openshift/.config' name: "{{ item.openshift.common.hostname }}" api_version: "{{ openshift_kube_api_version }}" cpu: "{{ item.openshift.node.resources_cpu | default(None) }}" -- cgit v1.2.3 From e36ca950f0bc83c844e3c368bb64845ea51f3ea2 Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Wed, 22 Apr 2015 17:16:46 -0400 Subject: Testing jenkins hooks --- git/pylint.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/git/pylint.sh b/git/pylint.sh index e070fe7b2..286747565 100755 --- a/git/pylint.sh +++ b/git/pylint.sh @@ -5,8 +5,10 @@ OLDREV=$1 NEWREV=$2 TRG_BRANCH=$3 +PYTHON=/var/lib/jenkins/python27/bin/python + /usr/bin/git diff --name-only $OLDREV $NEWREV --diff-filter=ACM | \ grep ".py$" | \ - xargs -r -I{} pylint --rcfile ${WORKSPACE}/git/.pylintrc {} + xargs -r -I{} ${PYTHON} -m pylint --rcfile ${WORKSPACE}/git/.pylintrc {} exit $? -- cgit v1.2.3 From 378e8a8c9d7e7be7f52691e957f07096ee0b2c82 Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Thu, 16 Apr 2015 01:49:29 -0400 Subject: lvm-direct support for aws - Create a separate docker volume in aws openshift-cluster playbooks - default to using ephemeral storage, but allow to be overriden - allow root volume settingsto be overriden as well - add user-data cloud-config to bootstrap the installation/configuration of docker-storage-setup - pylint cleanup for oo_filters.py - remove left over traces to the deployment_type tags which were previously removed - oo_get_deployment_type_from_groups filter in oo_filters.py - cluster list playbooks references to oo_get_deployment_type_from_groups filter --- README_AWS.md | 21 ++++++++- filter_plugins/oo_filters.py | 50 +++++++++++++++++++++- playbooks/aws/openshift-cluster/list.yml | 2 +- .../openshift-cluster/tasks/launch_instances.yml | 22 ++++++++++ .../aws/openshift-cluster/templates/user_data.j2 | 29 +++++++++++++ playbooks/gce/openshift-cluster/list.yml | 2 +- playbooks/libvirt/openshift-cluster/list.yml | 2 +- 7 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 playbooks/aws/openshift-cluster/templates/user_data.j2 diff --git a/README_AWS.md b/README_AWS.md index 37f4c5f51..888abe939 100644 --- a/README_AWS.md +++ b/README_AWS.md @@ -40,11 +40,25 @@ Alternatively, you can configure your ssh-agent to hold the credentials to conne By default, a cluster is launched with the following configuration: - Instance type: m3.large -- AMI: ami-307b3658 +- AMI: ami-307b3658 (for online deployments, ami-acd999c4 for origin deployments and ami-10663b78 for enterprise deployments) - Region: us-east-1 - Keypair name: libra - Security group: public +Master specific defaults: +- Master root volume size: 10 (in GiBs) +- Master root volume type: gp2 +- Master root volume iops: 500 (only applicable when volume type is io1) + +Node specific defaults: +- Node root volume size: 10 (in GiBs) +- Node root volume type: gp2 +- Node root volume iops: 500 (only applicable when volume type is io1) +- Docker volume size: 25 (in GiBs) +- Docker volume ephemeral: true (Whether the docker volume is ephemeral) +- Docker volume type: gp2 (only applicable if ephemeral is false) +- Docker volume iops: 500 (only applicable when volume type is io1) + If needed, these values can be changed by setting environment variables on your system. - export ec2_instance_type='m3.large' @@ -52,6 +66,11 @@ If needed, these values can be changed by setting environment variables on your - export ec2_region='us-east-1' - export ec2_keypair='libra' - export ec2_security_group='public' +- export os_master_root_vol_size='20' +- export os_master_root_vol_type='standard' +- export os_node_root_vol_size='15' +- export os_docker_vol_size='50' +- export os_docker_vol_ephemeral='false' Install Dependencies -------------------- diff --git a/filter_plugins/oo_filters.py b/filter_plugins/oo_filters.py index d22b6d188..097038450 100644 --- a/filter_plugins/oo_filters.py +++ b/filter_plugins/oo_filters.py @@ -129,6 +129,53 @@ def oo_ami_selector(data, image_name): ami = sorted(ami_info, key=itemgetter(1), reverse=True)[0][0] return ami['ami_id'] +def oo_ec2_volume_definition(data, host_type, docker_ephemeral=False): + ''' This takes a dictionary of volume definitions and returns a valid ec2 + volume definition based on the host_type and the values in the + dictionary. + The dictionary should look similar to this: + { 'master': + { 'root': + { 'volume_size': 10, 'device_type': 'gp2', + 'iops': 500 + } + }, + 'node': + { 'root': + { 'volume_size': 10, 'device_type': 'io1', + 'iops': 1000 + }, + 'docker': + { 'volume_size': 40, 'device_type': 'gp2', + 'iops': 500, 'ephemeral': 'true' + } + } + } + ''' + if not issubclass(type(data), dict): + raise errors.AnsibleFilterError("|failed expects first param is a dict") + if host_type not in ['master', 'node']: + raise errors.AnsibleFilterError("|failed expects either master or node" + " host type") + + root_vol = data[host_type]['root'] + root_vol['device_name'] = '/dev/sda1' + root_vol['delete_on_termination'] = True + if root_vol['device_type'] != 'io1': + root_vol.pop('iops', None) + if host_type == 'node': + docker_vol = data[host_type]['docker'] + docker_vol['device_name'] = '/dev/xvdb' + docker_vol['delete_on_termination'] = True + if docker_vol['device_type'] != 'io1': + docker_vol.pop('iops', None) + if docker_ephemeral: + docker_vol.pop('device_type', None) + docker_vol.pop('delete_on_termination', None) + docker_vol['ephemeral'] = 'ephemeral0' + return [root_vol, docker_vol] + return [root_vol] + # disabling pylint checks for too-few-public-methods and no-self-use since we # need to expose a FilterModule object that has a filters method that returns # a mapping of filter names to methods. @@ -144,5 +191,6 @@ class FilterModule(object): "oo_len": oo_len, "oo_pdb": oo_pdb, "oo_prepend_strings_in_list": oo_prepend_strings_in_list, - "oo_ami_selector": oo_ami_selector + "oo_ami_selector": oo_ami_selector, + "oo_ec2_volume_definition": oo_ec2_volume_definition } diff --git a/playbooks/aws/openshift-cluster/list.yml b/playbooks/aws/openshift-cluster/list.yml index 5c04bc320..04fcdc0a1 100644 --- a/playbooks/aws/openshift-cluster/list.yml +++ b/playbooks/aws/openshift-cluster/list.yml @@ -21,4 +21,4 @@ gather_facts: no tasks: - debug: - msg: "public ip:{{ hostvars[inventory_hostname].ec2_ip_address }} private ip:{{ hostvars[inventory_hostname].ec2_private_ip_address }} deployment-type: {{ hostvars[inventory_hostname].group_names | oo_get_deployment_type_from_groups }}" + msg: "public ip:{{ hostvars[inventory_hostname].ec2_ip_address }} private ip:{{ hostvars[inventory_hostname].ec2_private_ip_address }}" diff --git a/playbooks/aws/openshift-cluster/tasks/launch_instances.yml b/playbooks/aws/openshift-cluster/tasks/launch_instances.yml index 39ad9d089..666a8d1fb 100644 --- a/playbooks/aws/openshift-cluster/tasks/launch_instances.yml +++ b/playbooks/aws/openshift-cluster/tasks/launch_instances.yml @@ -1,6 +1,7 @@ --- - set_fact: created_by: "{{ lookup('env', 'LOGNAME')|default(cluster, true) }}" + docker_vol_ephemeral: "{{ lookup('env', 'os_docker_vol_ephemeral') | default(false, true) }}" env: "{{ cluster }}" env_host_type: "{{ cluster }}-openshift-{{ type }}" host_type: "{{ type }}" @@ -50,6 +51,25 @@ - set_fact: latest_ami: "{{ ami_result.results | oo_ami_selector(ec2_image_name) }}" + user_data: "{{ lookup('template', '../templates/user_data.j2') if type == 'node' else None | default('omit') }}" + volume_defs: + master: + root: + volume_size: "{{ lookup('env', 'os_master_root_vol_size') | default(25, true) }}" + device_type: "{{ lookup('env', 'os_master_root_vol_type') | default('gp2', true) }}" + iops: "{{ lookup('env', 'os_master_root_vol_iops') | default(500, true) }}" + node: + root: + volume_size: "{{ lookup('env', 'os_node_root_vol_size') | default(25, true) }}" + device_type: "{{ lookup('env', 'os_node_root_vol_type') | default('gp2', true) }}" + iops: "{{ lookup('env', 'os_node_root_vol_iops') | default(500, true) }}" + docker: + volume_size: "{{ lookup('env', 'os_docker_vol_size') | default(32, true) }}" + device_type: "{{ lookup('env', 'os_docker_vol_type') | default('gp2', true) }}" + iops: "{{ lookup('env', 'os_docker_vol_iops') | default(500, true) }}" + +- set_fact: + volumes: "{{ volume_defs | oo_ec2_volume_definition(host_type, docker_vol_ephemeral | bool) }}" - name: Launch instance(s) ec2: @@ -62,12 +82,14 @@ count: "{{ instances | oo_len }}" vpc_subnet_id: "{{ ec2_vpc_subnet | default(omit, true) }}" assign_public_ip: "{{ ec2_assign_public_ip | default(omit, true) }}" + user_data: "{{ user_data }}" wait: yes instance_tags: created-by: "{{ created_by }}" env: "{{ env }}" host-type: "{{ host_type }}" env-host-type: "{{ env_host_type }}" + volumes: "{{ volumes }}" register: ec2 - name: Add Name tag to instances diff --git a/playbooks/aws/openshift-cluster/templates/user_data.j2 b/playbooks/aws/openshift-cluster/templates/user_data.j2 new file mode 100644 index 000000000..7dbc8f552 --- /dev/null +++ b/playbooks/aws/openshift-cluster/templates/user_data.j2 @@ -0,0 +1,29 @@ +#cloud-config +yum_repos: + jdetiber-copr: + name: Copr repo for origin owned by jdetiber + baseurl: https://copr-be.cloud.fedoraproject.org/results/jdetiber/origin/epel-7-$basearch/ + skip_if_unavailable: true + gpgcheck: true + gpgkey: https://copr-be.cloud.fedoraproject.org/results/jdetiber/origin/pubkey.gpg + enabled: true + +packages: +- xfsprogs # can be dropped after docker-storage-setup properly requires it: https://github.com/projectatomic/docker-storage-setup/pull/8 +- docker-storage-setup + +mounts: +- [ xvdb ] +- [ ephemeral0 ] + +write_files: +- content: | + DEVS=/dev/xvdb + VG=docker_vg + path: /etc/sysconfig/docker-storage-setup + owner: root:root + permissions: '0644' + +runcmd: +- systemctl daemon-reload +- systemctl enable lvm2-lvmetad.service docker-storage-setup.service diff --git a/playbooks/gce/openshift-cluster/list.yml b/playbooks/gce/openshift-cluster/list.yml index bab2fb9f8..962381306 100644 --- a/playbooks/gce/openshift-cluster/list.yml +++ b/playbooks/gce/openshift-cluster/list.yml @@ -21,4 +21,4 @@ gather_facts: no tasks: - debug: - msg: "public ip:{{ hostvars[inventory_hostname].gce_public_ip }} private ip:{{ hostvars[inventory_hostname].gce_private_ip }} deployment-type: {{ hostvars[inventory_hostname].group_names | oo_get_deployment_type_from_groups }}" + msg: "public ip:{{ hostvars[inventory_hostname].gce_public_ip }} private ip:{{ hostvars[inventory_hostname].gce_private_ip }}" diff --git a/playbooks/libvirt/openshift-cluster/list.yml b/playbooks/libvirt/openshift-cluster/list.yml index 25a25f791..eaedc4d0d 100644 --- a/playbooks/libvirt/openshift-cluster/list.yml +++ b/playbooks/libvirt/openshift-cluster/list.yml @@ -20,4 +20,4 @@ hosts: oo_list_hosts tasks: - debug: - msg: 'public:{{ansible_default_ipv4.address}} private:{{ansible_default_ipv4.address}} deployment-type: {{ hostvars[inventory_hostname].group_names | oo_get_deployment_type_from_groups }}' + msg: 'public:{{ansible_default_ipv4.address}} private:{{ansible_default_ipv4.address}}' -- cgit v1.2.3 From ba6108268fac802817cda3d3cb420c3b77e70f1f Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Fri, 24 Apr 2015 12:14:36 -0400 Subject: Add ansible_connection=local to localhost in inventory --- inventory/aws/hosts/hosts | 2 +- inventory/gce/hosts/hosts | 2 +- inventory/libvirt/hosts/hosts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/inventory/aws/hosts/hosts b/inventory/aws/hosts/hosts index 6c590ac93..34a4396bd 100644 --- a/inventory/aws/hosts/hosts +++ b/inventory/aws/hosts/hosts @@ -1 +1 @@ -localhost ansible_sudo=no ansible_python_interpreter=/usr/bin/python2 +localhost ansible_connection=local ansible_sudo=no ansible_python_interpreter=/usr/bin/python2 diff --git a/inventory/gce/hosts/hosts b/inventory/gce/hosts/hosts index 6c590ac93..34a4396bd 100644 --- a/inventory/gce/hosts/hosts +++ b/inventory/gce/hosts/hosts @@ -1 +1 @@ -localhost ansible_sudo=no ansible_python_interpreter=/usr/bin/python2 +localhost ansible_connection=local ansible_sudo=no ansible_python_interpreter=/usr/bin/python2 diff --git a/inventory/libvirt/hosts/hosts b/inventory/libvirt/hosts/hosts index 9cdc31449..34a4396bd 100644 --- a/inventory/libvirt/hosts/hosts +++ b/inventory/libvirt/hosts/hosts @@ -1 +1 @@ -localhost ansible_sudo=no ansible_python_interpreter=/usr/bin/python2 connection=local +localhost ansible_connection=local ansible_sudo=no ansible_python_interpreter=/usr/bin/python2 -- cgit v1.2.3