From a662def48c3b9cf28f73968f1656e761620f0361 Mon Sep 17 00:00:00 2001 From: William Graef Date: Fri, 20 Sep 2024 18:28:13 -0400 Subject: [PATCH 1/5] add oci block device name --- ol/block.yml | 1 + ol/build.yml | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/ol/block.yml b/ol/block.yml index 98eaf3e..0fe9448 100644 --- a/ol/block.yml +++ b/ol/block.yml @@ -31,6 +31,7 @@ type: paravirtualized volume_id: "{{ volume_id }}" compartment_id: "{{ my_compartment_id }}" + device: "{{ block_devices[ansible_loop.index] }}" is_read_only: false is_shareable: false retries: 10 diff --git a/ol/build.yml b/ol/build.yml index 74eb009..4bffd3f 100644 --- a/ol/build.yml +++ b/ol/build.yml @@ -78,6 +78,13 @@ - name: Add block storage to an instance ansible.builtin.include_tasks: "block.yml" loop: "{{ query('sequence', 'start=1 end='+(block_count)|string) }}" + vars: + block_devices: + - sdb + - sdc + - sdd + - sde + - sdf - name: Print the public and private ip of the newly created instance ansible.builtin.debug: From f461aa1a8276906fd4ef7943e1f856c0e027117d Mon Sep 17 00:00:00 2001 From: William Graef Date: Fri, 20 Sep 2024 19:37:51 -0400 Subject: [PATCH 2/5] add loop control and index0 --- ol/block.yml | 2 +- ol/build.yml | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ol/block.yml b/ol/block.yml index 0fe9448..2d932cc 100644 --- a/ol/block.yml +++ b/ol/block.yml @@ -31,7 +31,7 @@ type: paravirtualized volume_id: "{{ volume_id }}" compartment_id: "{{ my_compartment_id }}" - device: "{{ block_devices[ansible_loop.index] }}" + device: "/dev/oracleoci/oraclevd{{ block_devices[ansible_loop.index0] }}" is_read_only: false is_shareable: false retries: 10 diff --git a/ol/build.yml b/ol/build.yml index 4bffd3f..f60a86d 100644 --- a/ol/build.yml +++ b/ol/build.yml @@ -78,13 +78,15 @@ - name: Add block storage to an instance ansible.builtin.include_tasks: "block.yml" loop: "{{ query('sequence', 'start=1 end='+(block_count)|string) }}" + loop_control: + extended: true vars: block_devices: - - sdb - - sdc - - sdd - - sde - - sdf + - b + - c + - d + - e + - f - name: Print the public and private ip of the newly created instance ansible.builtin.debug: From 0f4f8c2b0efe0da5aa44e4ed9f173de5d4b3ec49 Mon Sep 17 00:00:00 2001 From: William Graef Date: Fri, 20 Sep 2024 20:18:35 -0400 Subject: [PATCH 3/5] add ocne2 libvirt init --- ocne2/block.yml | 39 +++ ocne2/build.yml | 108 ++++++ ocne2/create_instance.yml | 379 ++++++++++++++++++++++ ocne2/default_vars.yml | 22 ++ ocne2/deploy_ocne_libvirt.yml | 103 ++++++ ocne2/deploy_ocne_none.yml | 15 + ocne2/host_setup.yml | 162 +++++++++ ocne2/requirements.yml | 32 ++ ocne2/templates/egress_security_rules.j2 | 9 + ocne2/templates/ingress_security_rules.j2 | 88 +++++ ocne2/templates/oci_vars.j2 | 10 + ocne2/templates/vm_template.j2 | 58 ++++ ocne2/update_all_rpms.yml | 37 +++ 13 files changed, 1062 insertions(+) create mode 100644 ocne2/block.yml create mode 100644 ocne2/build.yml create mode 100644 ocne2/create_instance.yml create mode 100644 ocne2/default_vars.yml create mode 100644 ocne2/deploy_ocne_libvirt.yml create mode 100644 ocne2/deploy_ocne_none.yml create mode 100644 ocne2/host_setup.yml create mode 100644 ocne2/requirements.yml create mode 100644 ocne2/templates/egress_security_rules.j2 create mode 100644 ocne2/templates/ingress_security_rules.j2 create mode 100644 ocne2/templates/oci_vars.j2 create mode 100644 ocne2/templates/vm_template.j2 create mode 100644 ocne2/update_all_rpms.yml diff --git a/ocne2/block.yml b/ocne2/block.yml new file mode 100644 index 0000000..2d932cc --- /dev/null +++ b/ocne2/block.yml @@ -0,0 +1,39 @@ +--- +# Copyright (c) 2024 Oracle and/or its affiliates. +# This software is made available to you under the terms of the Universal Permissive License (UPL), Version 1.0. +# The Universal Permissive License (UPL), Version 1.0 (see COPYING or https://oss.oracle.com/licenses/upl) +# See LICENSE.TXT for details. + +- name: Add block volumes to the instance + when: + - add_block_storage + block: + - name: Create block volume + oracle.oci.oci_blockstorage_volume: + compartment_id: "{{ my_compartment_id }}" + availability_domain: "{{ my_availability_domain }}" + display_name: "blockvolume-{{ item.value.instance_name | default('instance-'~timestamp) }}" + size_in_gbs: "{{ block_volume_size_in_gbs }}" + register: result + vars: + timestamp: "{{ now().strftime('%Y%m%d-%H%M%S') }}" + retries: 10 + delay: 30 + until: result is not failed + + - name: Set the block volume id + ansible.builtin.set_fact: + volume_id: "{{ result.volume.id }}" + + - name: Attach the block volume + oracle.oci.oci_compute_volume_attachment: + instance_id: "{{ instance_id }}" + type: paravirtualized + volume_id: "{{ volume_id }}" + compartment_id: "{{ my_compartment_id }}" + device: "/dev/oracleoci/oraclevd{{ block_devices[ansible_loop.index0] }}" + is_read_only: false + is_shareable: false + retries: 10 + delay: 30 + until: result is not failed diff --git a/ocne2/build.yml b/ocne2/build.yml new file mode 100644 index 0000000..f60a86d --- /dev/null +++ b/ocne2/build.yml @@ -0,0 +1,108 @@ +--- +# Copyright (c) 2024 Oracle and/or its affiliates. +# This software is made available to you under the terms of the Universal Permissive License (UPL), Version 1.0. +# The Universal Permissive License (UPL), Version 1.0 (see COPYING or https://oss.oracle.com/licenses/upl) +# See LICENSE.TXT for details. + +- name: Launch an instance + oracle.oci.oci_compute_instance: + availability_domain: "{{ my_availability_domain }}" + compartment_id: "{{ my_compartment_id }}" + name: "{{ item.value.instance_name | default('instance-'~timestamp) }}" + image_id: "{{ ol_image_id }}" + shape: "{{ instance_shape }}" + shape_config: + ocpus: "{{ instance_ocpus }}" + memory_in_gbs: "{{ instance_memory }}" + create_vnic_details: + assign_public_ip: true + hostname_label: "{{ item.value.instance_name | default('instance-'~timestamp) }}" + subnet_id: "{{ my_subnet_id }}" + metadata: + ssh_authorized_keys: "{{ lookup('file', lookup('env', 'HOME') + '/.ssh/' + private_key + '.pub') }}" + agent_config: + is_monitoring_disabled: false + is_management_disabled: false + are_all_plugins_disabled: false + plugins_config: + - + name: "OS Management Service Agent" + desired_state: DISABLED + register: result + vars: + timestamp: "{{ now().strftime('%Y%m%d-%H%M%S') }}" + retries: 10 + delay: 30 + until: result is not failed + +- name: Print instance details + ansible.builtin.debug: + msg: + - "Launched a new instance:" + - "{{ result }}" + when: debug_enabled + +- name: Set the compute instance id + ansible.builtin.set_fact: + instance_id: "{{ result.instance.id }}" + +- name: Set the compute instance display_name + ansible.builtin.set_fact: + instance_display_name: "{{ result.instance.display_name }}" + +- name: Get the vnic attachment details of instance + oracle.oci.oci_compute_vnic_attachment_facts: + compartment_id: "{{ my_compartment_id }}" + instance_id: "{{ instance_id }}" + register: result + retries: 10 + delay: 30 + until: result is not failed + +- name: Get vnic details + oracle.oci.oci_network_vnic_facts: + id: "{{ result.vnic_attachments[0].vnic_id }}" + register: result + retries: 10 + delay: 30 + until: result is not failed + +- name: Set the instance private ip address + ansible.builtin.set_fact: + instance_private_ip: "{{ result.vnic.private_ip }}" + +- name: Set the instance public ip address + ansible.builtin.set_fact: + instance_public_ip: "{{ result.vnic.public_ip }}" + +- name: Add block storage to an instance + ansible.builtin.include_tasks: "block.yml" + loop: "{{ query('sequence', 'start=1 end='+(block_count)|string) }}" + loop_control: + extended: true + vars: + block_devices: + - b + - c + - d + - e + - f + +- name: Print the public and private ip of the newly created instance + ansible.builtin.debug: + msg: + - "Instance name: {{ instance_display_name }}" + - " public ip: {{ instance_public_ip }}" + - " private ip: {{ instance_private_ip }}" + when: debug_enabled + +- name: Add host to in-memory host file + ansible.builtin.add_host: + name: "{{ instance_display_name }}" + groups: "{{ item.value.type }}" + ansible_user: opc + ansible_private_key_file: "{{ lookup('env', 'HOME') + '/.ssh/' + private_key }}" + ansible_ssh_common_args: "-o StrictHostKeyChecking=no" + ansible_host: "{{ instance_public_ip }}" + ansible_port: 22 + instance_ocid: "{{ instance_id }}" diff --git a/ocne2/create_instance.yml b/ocne2/create_instance.yml new file mode 100644 index 0000000..4e0133e --- /dev/null +++ b/ocne2/create_instance.yml @@ -0,0 +1,379 @@ +--- +# Copyright (c) 2024 Oracle and/or its affiliates. +# This software is made available to you under the terms of the Universal Permissive License (UPL), Version 1.0. +# The Universal Permissive License (UPL), Version 1.0 (see COPYING or https://oss.oracle.com/licenses/upl) +# See LICENSE.TXT for details. + +- name: Gather facts and create instances + hosts: localhost + vars_files: + - default_vars.yml + vars: + oci_config_section: DEFAULT + ad_placement: 1 + compartment_name: + compartment_id: + compute_instances: + 1: + instance_name: "ol-node-01" + type: "client" + 2: + instance_name: "ol-node-02" + type: "server" + os: "Oracle Linux" + os_version: "8" + instance_shape: "VM.Standard.E4.Flex" + instance_ocpus: 2 + instance_memory: 32 + private_key: "id_rsa" + ansible_python_interpreter: "{{ localhost_python_interpreter | default(omit) }}" + debug_enabled: false + + tasks: + + # - name: Check if state file exists + # ansible.builtin.stat: + # path: /tmp/ansible.state + # register: state_exists + + # - name: Fail if state file already exists + # ansible.builtin.fail: + # msg: "Exit instance creation as a state file already exists." + # when: hosts_exists.stat.exists + + - name: Get location of oci_config + ansible.builtin.set_fact: + oci_config_file: "{{ lookup('env', 'HOME') + '/.oci/config' }}" + + - name: Get tenancy ocid + ansible.builtin.set_fact: + my_tenancy_id: "{{ lookup('ini', 'tenancy section={{ oci_config_section }} file={{ oci_config_file }}') }}" + + - name: Get region id + ansible.builtin.set_fact: + my_region_id: "{{ lookup('ini', 'region section={{ oci_config_section }} file={{ oci_config_file }}') }}" + + - name: Print regions selected + ansible.builtin.debug: + msg: "{{ my_region_id }}" + when: debug_enabled + + - name: Get list availbility domains + oracle.oci.oci_identity_availability_domain_facts: + compartment_id: "{{ my_tenancy_id }}" + region: "{{ my_region_id }}" + register: result + retries: 10 + delay: 30 + until: result is not failed + + - name: Print availability domains + ansible.builtin.debug: + msg: "{{ result }}" + when: debug_enabled + + - name: Set list of availability domains + ansible.builtin.set_fact: + availability_domains: "{{ result.availability_domains }}" + + - name: Set to availability domain from list + ansible.builtin.set_fact: + my_availability_domain: "{{ availability_domains[(lookup('ansible.builtin.vars', 'ad_placement') | int) - 1].name }}" + + - name: Print availability domain ad_placement + ansible.builtin.debug: + msg: "{{ my_availability_domain }}" + when: debug_enabled + + - name: Get compartment id from .oci/config or env OCI_COMPARTMENT_OCID + vars: + env_lookup: "{{ lookup('ansible.builtin.env', 'OCI_COMPARMENT_OCID') }}" + ini_lookup: "{{ lookup('ini', 'compartment-id section={{ oci_config_section }} file={{ oci_config_file }}') }}" + ansible.builtin.set_fact: + my_compartment_id: "{{ compartment_id | default(env_lookup, true) | default(ini_lookup, true) }}" + + - name: Print compartment id + ansible.builtin.debug: + msg: "{{ my_compartment_id }}" + when: debug_enabled + + - name: Fail when compartment_id is not defined + ansible.builtin.fail: + msg: "Variable for compartment_id is not defined." + when: my_compartment_id is not defined + + - name: Generate random hex string + vars: + hex_chars: '0123456789abcdef' + ansible.builtin.set_fact: + vcn_code: "{{ query('community.general.random_string', upper=false, lower=false, override_special=hex_chars, numbers=false) }}" + + - name: Create a virtual cloud network + oracle.oci.oci_network_vcn: + compartment_id: "{{ my_compartment_id }}" + display_name: "Linuxvirt Virtual Cloud Network" + cidr_blocks: "10.0.0.0/16" + dns_label: "vcn" + register: result + retries: 10 + delay: 30 + until: result is not failed + + - name: Set vcn id + ansible.builtin.set_fact: + my_vcn_id: "{{ result.vcn.id }}" + + - name: Create internet_gateway + oracle.oci.oci_network_internet_gateway: + compartment_id: "{{ my_compartment_id }}" + vcn_id: "{{ my_vcn_id }}" + is_enabled: true + display_name: "Linuxvirt Internet Gateway" + state: 'present' + register: result + retries: 10 + delay: 30 + until: result is not failed + + - name: Set internet gateway id + ansible.builtin.set_fact: + my_internet_gateway_id: "{{ result.internet_gateway.id }}" + + - name: Create route_table + oracle.oci.oci_network_route_table: + compartment_id: "{{ my_compartment_id }}" + vcn_id: "{{ my_vcn_id }}" + display_name: "Linuxvirt Route Table" + route_rules: + - network_entity_id: "{{ my_internet_gateway_id }}" + cidr_block: "0.0.0.0/0" + destination_type: CIDR_BLOCK + state: 'present' + register: result + retries: 10 + delay: 30 + until: result is not failed + + - name: Set route table id + ansible.builtin.set_fact: + my_rt_id: "{{ result.route_table.id }}" + + - name: Create ingress rules yaml list + ansible.builtin.template: + src: ingress_security_rules.j2 + dest: /tmp/instance_ingress_security_rules.yaml + mode: "0664" + + - name: Create egress rules yaml list + ansible.builtin.template: + src: egress_security_rules.j2 + dest: /tmp/instance_egress_security_rules.yaml + mode: "0664" + + - name: Load the variables defined in the ingress rules yaml list + ansible.builtin.include_vars: + file: /tmp/instance_ingress_security_rules.yaml + name: loaded_ingress + + - name: Print loaded_ingress + ansible.builtin.debug: + msg: "loaded ingress is {{ loaded_ingress }}" + when: debug_enabled + + - name: Load the variables defined in the egress rules yaml list + ansible.builtin.include_vars: + file: /tmp/instance_egress_security_rules.yaml + name: loaded_egress + + - name: Print loaded_egress + ansible.builtin.debug: + msg: "loaded egress is {{ loaded_egress }}" + when: debug_enabled + + - name: Create security_list + oracle.oci.oci_network_security_list: + display_name: "Linuxvirt Security List" + compartment_id: "{{ my_compartment_id }}" + vcn_id: "{{ my_vcn_id }}" + ingress_security_rules: "{{ loaded_ingress.instance_ingress_security_rules }}" + egress_security_rules: "{{ loaded_egress.instance_egress_security_rules }}" + register: result + retries: 10 + delay: 30 + until: result is not failed + + - name: Set security list id + ansible.builtin.set_fact: + my_security_list_id: "{{ result.security_list.id }}" + + - name: Create subnet + oracle.oci.oci_network_subnet: + compartment_id: "{{ my_compartment_id }}" + vcn_id: "{{ my_vcn_id }}" + cidr_block: "{{ subnet_cidr_block }}" + display_name: "Linuxvirt Subnet" + prohibit_public_ip_on_vnic: false + route_table_id: "{{ my_rt_id }}" + security_list_ids: "{{ my_security_list_id }}" + dns_label: "lv" + register: result + retries: 10 + delay: 30 + until: result is not failed + + - name: Set subnet id + ansible.builtin.set_fact: + my_subnet_id: "{{ result.subnet.id }}" + + - name: Set subnet domain_name + ansible.builtin.set_fact: + my_subnet_domain_name: "{{ result.subnet.subnet_domain_name }}" + + - name: Set oci vars file + ansible.builtin.template: + src: oci_vars.j2 + dest: oci_vars.yml + mode: "0664" + + - name: Get image + oracle.oci.oci_compute_image_facts: + compartment_id: "{{ my_compartment_id }}" + operating_system: "{{ os }}" + operating_system_version: "{{ os_version }}" + shape: "{{ instance_shape }}" + sort_by: TIMECREATED + sort_order: DESC + register: result + retries: 10 + delay: 30 + until: result is not failed + + - name: Print image list + ansible.builtin.debug: + var: result + when: debug_enabled + + - name: Set compute image id + ansible.builtin.set_fact: + ol_image_id: "{{ result.images[0].id }}" + + - name: Build an instance + ansible.builtin.include_tasks: "build.yml" + loop: "{{ lookup('dict', compute_instances, wantlist=True) }}" + +- name: Configure new instances + hosts: all + gather_facts: false + vars_files: + - default_vars.yml + - oci_vars.yml + vars: + username: "oracle" + user_default_password: "oracle" + private_key: "id_rsa" + debug_enabled: false + + tasks: + + - name: Print in-memory inventory + ansible.builtin.debug: + msg: "{{ groups['all'] }}" + delegate_to: localhost + when: + - debug_enabled + - inventory_hostname == ansible_play_hosts_all[0] + + - name: Print all variables/facts known for a host + ansible.builtin.debug: + msg: "{{ hostvars[item] }}" + loop: "{{ groups['all'] | flatten(levels=1) }}" + delegate_to: localhost + when: + - debug_enabled + - inventory_hostname == ansible_play_hosts_all[0] + + - name: Configure instance + ansible.builtin.include_tasks: "host_setup.yml" + + - name: Configure passwordless SSH + ansible.builtin.include_tasks: "passwordless_setup.yml" + when: passwordless_ssh + +- name: Update all rpm packages + ansible.builtin.import_playbook: update_all_rpms.yml + when: update_all + +- name: Install Oracle Cloud Native Environment + vars: + install_type: "{{ ocne_type if ocne_type is defined else (lookup('file', 'default_vars.yml') | from_yaml).ocne_type | default('none') }}" + ansible.builtin.import_playbook: "deploy_ocne_{{ install_type }}.yml" + +- name: Print instances + hosts: all + become: true + gather_facts: false + vars_files: + - ocir_vars.yml + + tasks: + + - name: Print instance details + ansible.builtin.debug: + msg: + - "Instance details:" + - " name: {{ hostvars[inventory_hostname]['ansible_hostname'] }}" + - " public ip: {{ hostvars[inventory_hostname]['ansible_host'] }}" + - " private ip: {{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}" + + - name: Pause play to interact with the servers + ansible.builtin.pause: + prompt: | + Playbook paused... hit to continue or then to abort. + Aborting at this stage requires manual removal of all cloud resources this playbook creates. + +- name: Terminate instances and delete OCI resources + hosts: localhost + vars_files: + - default_vars.yml + vars: + ansible_python_interpreter: "{{ localhost_python_interpreter | default(omit) }}" + + tasks: + + - name: Terminate the instances + oracle.oci.oci_compute_instance: + id: "{{ hostvars[item]['instance_ocid'] }}" + state: absent + loop: "{{ groups['all'] | flatten(levels=1) }}" + + - name: Delete the subnet + oracle.oci.oci_network_subnet: + id: "{{ my_subnet_id }}" + state: absent + + - name: Delete the security list + oracle.oci.oci_network_security_list: + id: "{{ my_security_list_id }}" + state: absent + + - name: Delete the route table + oracle.oci.oci_network_route_table: + id: "{{ my_rt_id }}" + state: absent + + - name: Delete the Internet Gateway + oracle.oci.oci_network_internet_gateway: + id: "{{ my_internet_gateway_id }}" + state: absent + + - name: Delete the VCN + oracle.oci.oci_network_vcn: + vcn_id: "{{ my_vcn_id }}" + state: absent + + - name: Remove artifacts + ansible.builtin.file: + state: absent + path: "{{ item }}" + loop: + - oci_vars.yml diff --git a/ocne2/default_vars.yml b/ocne2/default_vars.yml new file mode 100644 index 0000000..ff00d97 --- /dev/null +++ b/ocne2/default_vars.yml @@ -0,0 +1,22 @@ +compute_instances: + 1: + instance_name: "ol-node-01" + type: "server" +os: "Oracle Linux" +os_version: "8" +instance_shape: "VM.Standard.E4.Flex" +instance_ocpus: 4 +instance_memory: 64 +subnet_cidr_block: "10.0.0.48/28" + +username: "oracle" +usergroup: "{{ username }}" +user_default_password: "oracle" +debug_enabled: false +add_block_storage: false +block_volume_size_in_gbs: 50 +block_count: 1 + +ocne_type: libvirt +install_ocne_rpm: false +update_all: false \ No newline at end of file diff --git a/ocne2/deploy_ocne_libvirt.yml b/ocne2/deploy_ocne_libvirt.yml new file mode 100644 index 0000000..e15eb30 --- /dev/null +++ b/ocne2/deploy_ocne_libvirt.yml @@ -0,0 +1,103 @@ +--- +# Copyright (c) 2024 Oracle and/or its affiliates. +# This software is made available to you under the terms of the Universal Permissive License (UPL), Version 1.0. +# The Universal Permissive License (UPL), Version 1.0 (see COPYING or https://oss.oracle.com/licenses/upl) +# See LICENSE.TXT for details. + +- name: Install a KVM server + hosts: server + vars_files: + - default_vars.yml + become: true + + tasks: + + - name: Install Oracle Linux 8 virtualization packages + ansible.builtin.dnf: + name: + - "@virt" + - virt-install + - virt-viewer + - containers-common + - cockpit + - cockpit-machines + state: present + when: ansible_distribution == 'OracleLinux' and ansible_distribution_major_version == '8' + + - name: Install Oracle Linux 9 virtualization packages + ansible.builtin.dnf: + name: + - qemu-kvm + - libvirt + - virt-install + - virt-viewer + - containers-common + - cockpit + - cockpit-machines + state: present + when: ansible_distribution == 'OracleLinux' and ansible_distribution_major_version == '9' + + - name: Start and enable Oracle Linux 8 monolithic virtualization services + ansible.builtin.systemd: + state: started + name: libvirtd.service + enabled: true + when: ansible_distribution == 'OracleLinux' and ansible_distribution_major_version == '8' + + - name: Start and enable Oracle Linux 9 modular 'ro' virtualization services + ansible.builtin.systemd: + state: started + name: "virt{{ item }}d-ro.socket" + enabled: true + loop: + - qemu + - network + - nodedev + - nwfilter + - secret + - storage + - interface + - proxy + when: ansible_distribution == 'OracleLinux' and ansible_distribution_major_version == '9' + + - name: Start and enable Oracle Linux 9 modular 'admin' virtualization services + ansible.builtin.systemd: + state: started + name: "virt{{ item }}d-admin.socket" + enabled: true + loop: + - qemu + - network + - nodedev + - nwfilter + - secret + - storage + - interface + - proxy + when: ansible_distribution == 'OracleLinux' and ansible_distribution_major_version == '9' + + - name: Start and enable cockkpit + ansible.builtin.systemd: + state: started + name: cockpit.socket + enabled: true + + - name: Open firewall for cockpit and virsh + ansible.posix.firewalld: + zone: public + service: "{{ item }}" + permanent: true + state: enabled + immediate: true + loop: + - libvirt + - libvirt-tls + + - name: Add user to libvirt and qemu group + ansible.builtin.user: + name: "{{ username }}" + groups: libvirt,qemu + append: true + + - name: Reset ssh connection to allow user changes to affect 'current login user' + ansible.builtin.meta: reset_connection \ No newline at end of file diff --git a/ocne2/deploy_ocne_none.yml b/ocne2/deploy_ocne_none.yml new file mode 100644 index 0000000..d44caab --- /dev/null +++ b/ocne2/deploy_ocne_none.yml @@ -0,0 +1,15 @@ +--- +# Copyright (c) 2024 Oracle and/or its affiliates. +# This software is made available to you under the terms of the Universal Permissive License (UPL), Version 1.0. +# The Universal Permissive License (UPL), Version 1.0 (see COPYING or https://oss.oracle.com/licenses/upl) +# See LICENSE.TXT for details. + +- name: Run ocne noop + hosts: operator + become: true + + tasks: + + - name: Print noop message + ansible.builtin.debug: + msg: "This is a noop and does not deploy OCNE." diff --git a/ocne2/host_setup.yml b/ocne2/host_setup.yml new file mode 100644 index 0000000..c77d367 --- /dev/null +++ b/ocne2/host_setup.yml @@ -0,0 +1,162 @@ +--- +# Copyright (c) 2024 Oracle and/or its affiliates. +# This software is made available to you under the terms of the Universal Permissive License (UPL), Version 1.0. +# The Universal Permissive License (UPL), Version 1.0 (see COPYING or https://oss.oracle.com/licenses/upl) +# See LICENSE.TXT for details. + +- name: Group of setup tasks for each instance + vars: + max_retries: "{{ 5 if max_retries is undefined else max_retries | int }}" + retry_delay: "{{ 10 if retry_delay is undefined else retry_delay | int }}" + block: + - name: Increment the retry count + ansible.builtin.set_fact: + retry_count: "{{ 0 if retry_count is undefined else retry_count | int + 1 }}" + + # - name: Wait 300 seconds for port 22 to become open and contain "OpenSSH" + # ansible.builtin.wait_for: + # host: "{{ hostvars[inventory_hostname].ansible_host }}" + # port: 22 + # search_regex: OpenSSH + # delay: 10 + + - name: Wait for system to become reachable + ansible.builtin.wait_for_connection: + vars: + python_version: "/usr/bin/python3" + ansible_python_interpreter: "{{ python_version if localhost_python_interpreter is defined | default(omit) }}" + + # - name: Run ansible adhoc ping module + # ansible.builtin.command: ansible all -i '{{ hostvars[inventory_hostname].ansible_host }},' -m ping + # ignore_errors: false + # register: result + # until: result.rc == 0 + # retries: 10 + # delay: 15 + + - name: Run facts module to get latest information + ansible.builtin.setup: + + - name: Add user account with access to sudo + ansible.builtin.user: + name: "{{ username }}" + password: "{{ user_default_password | password_hash('sha512') }}" + comment: Ansible created user + groups: wheel + append: true + update_password: on_create + become: true + + - name: Set authorized key for user using local public key file + ansible.posix.authorized_key: + user: "{{ username }}" + state: present + key: "{{ lookup('file', lookup('env', 'HOME') + '/.ssh/' + private_key + '.pub') }}" + become: true + + - name: Set user with passwordless sudo access + vars: + sudo_content: "{{ username }} ALL=(ALL:ALL) NOPASSWD: ALL" + ansible.builtin.lineinfile: + path: "/etc/sudoers.d/{{ username }}" + regexp: "{{ username }} ALL=" + line: "{{ sudo_content }}" + state: present + create: true + mode: "0644" + become: true + + - name: Create the ansible tmp directory if it does not exist + ansible.builtin.file: + path: ~/.ansible/tmp + state: directory + mode: '0700' + become: true + become_user: "{{ username }}" + + - name: Add locale settings to .bashrc + ansible.builtin.lineinfile: + dest: ~/.bashrc + line: "{{ item }}" + with_items: + - 'export LC_ALL="en_US.UTF-8"' + - 'export LC_CTYPE="en_US.UTF-8"' + become: true + become_user: "{{ username }}" + + - name: Generate ssh keypair for user + community.crypto.openssh_keypair: + path: ~/.ssh/id_rsa + size: 2048 + comment: ocne ssh keypair + become: true + become_user: "{{ username }}" + + - name: Fetch public key file from server + ansible.builtin.fetch: + src: "~/.ssh/id_rsa.pub" + dest: "buffer/{{ inventory_hostname }}-id_rsa.pub" + flat: true + become: true + become_user: "{{ username }}" + + - name: Copy public key to each destination + ansible.posix.authorized_key: + user: "{{ username }}" + state: present + key: "{{ lookup('file', 'buffer/{{ item }}-id_rsa.pub') }}" + loop: "{{ groups['all'] | flatten(levels=1) }}" + become: true + + - name: Print hostvars for groups + ansible.builtin.debug: + msg: "{{ hostvars[item] }}" + loop: "{{ groups['all'] | flatten(levels=1) }}" + when: debug_enabled + + - name: Print vnc subnet_domain_name + ansible.builtin.debug: + var: my_subnet_domain_name + when: debug_enabled + + - name: Accept new ssh fingerprints + ansible.builtin.shell: | + ssh-keyscan -t ecdsa-sha2-nistp256 \ + {{ hostvars[item].ansible_hostname }},\ + {{ hostvars[item].ansible_default_ipv4.address }},\ + {{ hostvars[item].ansible_hostname + '.' + my_subnet_domain_name }} >> ~/.ssh/known_hosts + with_items: + - "{{ groups['all'] }}" + become: true + become_user: "{{ username }}" + register: result + changed_when: result.rc == 0 + + - name: Configure firewall to log denied packets + ansible.builtin.command: + cmd: firewall-cmd --set-log-denied=all + when: debug_enabled + register: firewall_result + changed_when: firewall_result.rc == 0 + become: true + + # Check denied packets with "journalctl -x -e" or with "dmesg | grep -i REJECT" + + rescue: + - name: Fail message for rescue + ansible.builtin.fail: + msg: Maximum retries of host setup tasks reached + when: retry_count | int == max_retries | int + + - name: Print retry message + ansible.builtin.debug: + msg: "Host setup task group failed, try again..." + + - name: Sleep between retries + ansible.builtin.wait_for: + timeout: "{{ retry_delay }}" # seconds + delegate_to: localhost + become: false + + - name: Retry host setup if there is a failure + ansible.builtin.include_tasks: host_setup.yml diff --git a/ocne2/requirements.yml b/ocne2/requirements.yml new file mode 100644 index 0000000..fa329b2 --- /dev/null +++ b/ocne2/requirements.yml @@ -0,0 +1,32 @@ +--- +# Copyright (c) 2024 Oracle and/or its affiliates. +# This software is made available to you under the terms of the Universal Permissive License (UPL), Version 1.0. +# The Universal Permissive License (UPL), Version 1.0 (see COPYING or https://oss.oracle.com/licenses/upl) +# See LICENSE.TXT for details. + +# roles: + +collections: + - name: https://github.com/ansible-collections/community.general.git + type: git + version: main + + - name: https://github.com/ansible-collections/ansible.posix.git + type: git + version: main + + - name: https://github.com/oracle/oci-ansible-collection.git + type: git + version: master + + - name: https://github.com/ansible-collections/community.postgresql.git + type: git + version: main + + - name: https://github.com/ansible-collections/community.crypto.git + type: git + version: main + + - name: https://github.com/ansible-collections/community.libvirt.git + type: git + version: main \ No newline at end of file diff --git a/ocne2/templates/egress_security_rules.j2 b/ocne2/templates/egress_security_rules.j2 new file mode 100644 index 0000000..f89f2e6 --- /dev/null +++ b/ocne2/templates/egress_security_rules.j2 @@ -0,0 +1,9 @@ +--- +# Copyright (c) 2024 Oracle and/or its affiliates. +# This software is made available to you under the terms of the Universal Permissive License (UPL), Version 1.0. +# The Universal Permissive License (UPL), Version 1.0 (see COPYING or https://oss.oracle.com/licenses/upl) +# See LICENSE.TXT for details. + +instance_egress_security_rules: + - destination: "0.0.0.0/0" + protocol: 6 \ No newline at end of file diff --git a/ocne2/templates/ingress_security_rules.j2 b/ocne2/templates/ingress_security_rules.j2 new file mode 100644 index 0000000..c4f607e --- /dev/null +++ b/ocne2/templates/ingress_security_rules.j2 @@ -0,0 +1,88 @@ +--- +# Copyright (c) 2024 Oracle and/or its affiliates. +# This software is made available to you under the terms of the Universal Permissive License (UPL), Version 1.0. +# The Universal Permissive License (UPL), Version 1.0 (see COPYING or https://oss.oracle.com/licenses/upl) +# See LICENSE.TXT for details. + +instance_ingress_security_rules: + # Allow incoming SSH connections + - source: "0.0.0.0/0" + protocol: 6 + tcp_options: + destination_port_range: + max: 22 + min: 22 +{% if use_haproxy %} + - source: "10.0.0.0/24" + protocol: 6 + tcp_options: + destination_port_range: + max: 8080 + min: 8080 +{% endif %} +{% if use_nginx %} + - source: "0.0.0.0/0" + protocol: 6 + tcp_options: + destination_port_range: + max: 80 + min: 80 + - source: "0.0.0.0/0" + protocol: 6 + tcp_options: + destination_port_range: + max: 443 + min: 443 + - source: "0.0.0.0/0" + protocol: 6 + tcp_options: + destination_port_range: + max: 8080 + min: 8080 +{% endif %} +{% if use_nfs %} + - source: "10.0.0.0/24" + protocol: 6 + tcp_options: + destination_port_range: + max: 2049 + min: 2049 + - source: "10.0.0.0/24" + protocol: 17 + udp_options: + destination_port_range: + max: 2049 + min: 2049 +{% endif %} +{% if use_quay_ha %} + - source: "10.0.0.0/24" + protocol: 6 + tcp_options: + destination_port_range: + max: 2049 + min: 2049 + - source: "10.0.0.0/24" + protocol: 17 + udp_options: + destination_port_range: + max: 2049 + min: 2049 + - source: "10.0.0.0/24" + protocol: 6 + tcp_options: + destination_port_range: + max: 8080 + min: 8080 + - source: "10.0.0.0/24" + protocol: 6 + tcp_options: + destination_port_range: + max: 5432 + min: 5432 + - source: "10.0.0.0/24" + protocol: 6 + tcp_options: + destination_port_range: + max: 6379 + min: 6379 +{% endif %} \ No newline at end of file diff --git a/ocne2/templates/oci_vars.j2 b/ocne2/templates/oci_vars.j2 new file mode 100644 index 0000000..0a4dd0a --- /dev/null +++ b/ocne2/templates/oci_vars.j2 @@ -0,0 +1,10 @@ +--- +# Copyright (c) 2024 Oracle and/or its affiliates. +# This software is made available to you under the terms of the Universal Permissive License (UPL), Version 1.0. +# The Universal Permissive License (UPL), Version 1.0 (see COPYING or https://oss.oracle.com/licenses/upl) +# See LICENSE.TXT for details. + +my_compartment_id: {{ my_compartment_id }} +my_vcn_id: {{ my_vcn_id }} +my_subnet_id: {{ my_subnet_id }} +my_subnet_domain_name: {{ my_subnet_domain_name }} \ No newline at end of file diff --git a/ocne2/templates/vm_template.j2 b/ocne2/templates/vm_template.j2 new file mode 100644 index 0000000..5026200 --- /dev/null +++ b/ocne2/templates/vm_template.j2 @@ -0,0 +1,58 @@ + + + + {{ vm_name }} + {{ vm_ram_mb }} + {{ vm_vcpus }} + + hvm + + + + + + + + + + + + + + + + + + /usr/libexec/qemu-kvm + + + + + + + + + + + + + + + + + + + + + + + + /dev/urandom + + + diff --git a/ocne2/update_all_rpms.yml b/ocne2/update_all_rpms.yml new file mode 100644 index 0000000..d83e466 --- /dev/null +++ b/ocne2/update_all_rpms.yml @@ -0,0 +1,37 @@ +--- +# Copyright (c) 2024 Oracle and/or its affiliates. +# This software is made available to you under the terms of the Universal Permissive License (UPL), Version 1.0. +# The Universal Permissive License (UPL), Version 1.0 (see COPYING or https://oss.oracle.com/licenses/upl) +# See LICENSE.TXT for details. + +- name: Install latest Oracle Linux packages + hosts: server + vars_files: + - default_vars.yml + become: true + + tasks: + + - name: Update all Oracle Linux packages + ansible.builtin.dnf: + name: "*" + state: latest + update_only: true + when: ansible_distribution == 'OracleLinux' + + - name: Check if a reboot is required + ansible.builtin.command: /usr/bin/needs-restarting -r + register: reboot_required + ignore_errors: true + changed_when: false + failed_when: reboot_required.rc == 2 + when: ansible_distribution == 'OracleLinux' + + - name: Print reboot is required + ansible.builtin.debug: + var: reboot_required + when: debug_enabled + + - name: Reboot (if needed) to apply latest kernel and updates + ansible.builtin.reboot: + when: ansible_distribution == 'OracleLinux' and reboot_required.rc == 1 From a505a5bf9600f270c740ec3f077bd808b9d3096d Mon Sep 17 00:00:00 2001 From: William Graef Date: Fri, 20 Sep 2024 20:32:49 -0400 Subject: [PATCH 4/5] default ingress and update hostname --- ocne2/default_vars.yml | 2 +- ocne2/templates/ingress_security_rules.j2 | 76 +---------------------- ocne2/templates/vm_template.j2 | 58 ----------------- 3 files changed, 2 insertions(+), 134 deletions(-) delete mode 100644 ocne2/templates/vm_template.j2 diff --git a/ocne2/default_vars.yml b/ocne2/default_vars.yml index ff00d97..66da95d 100644 --- a/ocne2/default_vars.yml +++ b/ocne2/default_vars.yml @@ -1,6 +1,6 @@ compute_instances: 1: - instance_name: "ol-node-01" + instance_name: "ocne" type: "server" os: "Oracle Linux" os_version: "8" diff --git a/ocne2/templates/ingress_security_rules.j2 b/ocne2/templates/ingress_security_rules.j2 index c4f607e..db769f6 100644 --- a/ocne2/templates/ingress_security_rules.j2 +++ b/ocne2/templates/ingress_security_rules.j2 @@ -11,78 +11,4 @@ instance_ingress_security_rules: tcp_options: destination_port_range: max: 22 - min: 22 -{% if use_haproxy %} - - source: "10.0.0.0/24" - protocol: 6 - tcp_options: - destination_port_range: - max: 8080 - min: 8080 -{% endif %} -{% if use_nginx %} - - source: "0.0.0.0/0" - protocol: 6 - tcp_options: - destination_port_range: - max: 80 - min: 80 - - source: "0.0.0.0/0" - protocol: 6 - tcp_options: - destination_port_range: - max: 443 - min: 443 - - source: "0.0.0.0/0" - protocol: 6 - tcp_options: - destination_port_range: - max: 8080 - min: 8080 -{% endif %} -{% if use_nfs %} - - source: "10.0.0.0/24" - protocol: 6 - tcp_options: - destination_port_range: - max: 2049 - min: 2049 - - source: "10.0.0.0/24" - protocol: 17 - udp_options: - destination_port_range: - max: 2049 - min: 2049 -{% endif %} -{% if use_quay_ha %} - - source: "10.0.0.0/24" - protocol: 6 - tcp_options: - destination_port_range: - max: 2049 - min: 2049 - - source: "10.0.0.0/24" - protocol: 17 - udp_options: - destination_port_range: - max: 2049 - min: 2049 - - source: "10.0.0.0/24" - protocol: 6 - tcp_options: - destination_port_range: - max: 8080 - min: 8080 - - source: "10.0.0.0/24" - protocol: 6 - tcp_options: - destination_port_range: - max: 5432 - min: 5432 - - source: "10.0.0.0/24" - protocol: 6 - tcp_options: - destination_port_range: - max: 6379 - min: 6379 -{% endif %} \ No newline at end of file + min: 22 \ No newline at end of file diff --git a/ocne2/templates/vm_template.j2 b/ocne2/templates/vm_template.j2 deleted file mode 100644 index 5026200..0000000 --- a/ocne2/templates/vm_template.j2 +++ /dev/null @@ -1,58 +0,0 @@ - - - - {{ vm_name }} - {{ vm_ram_mb }} - {{ vm_vcpus }} - - hvm - - - - - - - - - - - - - - - - - - /usr/libexec/qemu-kvm - - - - - - - - - - - - - - - - - - - - - - - - /dev/urandom - - - From 95f2be34fb0d9f97b68872ef658f5f81f98608e1 Mon Sep 17 00:00:00 2001 From: William Graef Date: Fri, 20 Sep 2024 20:37:55 -0400 Subject: [PATCH 5/5] config passwordless ssh as default --- ocne2/create_instance.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ocne2/create_instance.yml b/ocne2/create_instance.yml index 4e0133e..e000af1 100644 --- a/ocne2/create_instance.yml +++ b/ocne2/create_instance.yml @@ -295,10 +295,6 @@ - name: Configure instance ansible.builtin.include_tasks: "host_setup.yml" - - name: Configure passwordless SSH - ansible.builtin.include_tasks: "passwordless_setup.yml" - when: passwordless_ssh - - name: Update all rpm packages ansible.builtin.import_playbook: update_all_rpms.yml when: update_all