diff --git a/README.md b/README.md index ca068e856..963f356f8 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ dnf -y install ansible-collection-redhatci-ocp Name | Description --- | --- [redhatci.ocp.acm_hypershift](https://github.com/redhatci/ansible-collection-redhatci-ocp/blob/main/roles/acm_hypershift/README.md) | Deployment of Hypershift (Hosted Control Planes) through ACM (Advanced Cluster Management). +[redhatci.ocp.setup_acm_agents](https://github.com/redhatci/ansible-collection-redhatci-ocp/blob/main/roles/setup_acm_agents/README.md) | This role allows to setup ACM agents used for Bare-metal deployments. [redhatci.ocp.acm_setup](https://github.com/redhatci/ansible-collection-redhatci-ocp/blob/main/roles/acm_setup/README.md) | Performs the Advanced Cluster Management (ACM) post-installation tasks [redhatci.ocp.acm_sno](https://github.com/redhatci/ansible-collection-redhatci-ocp/blob/main/roles/acm_sno/README.md) | Deployment of SNO (Single Node OpenShift) instances using ACM (Advanced Cluster Management) [redhatci.ocp.acm_spoke_mgmt](https://github.com/redhatci/ansible-collection-redhatci-ocp/blob/main/roles/acm_spoke_mgmt/README.md) | This role allows to perform multiple management operations related to a spoke cluster,e.g. attach a spoke cluster to a given hub cluster, or detach a spoke cluster from a given hub cluster. diff --git a/roles/setup_acm_agents/README.md b/roles/setup_acm_agents/README.md new file mode 100644 index 000000000..2bb604d7e --- /dev/null +++ b/roles/setup_acm_agents/README.md @@ -0,0 +1,53 @@ +setup_acm_agents +========= + +This role prepare prepares agents running from an on-premise inventory (bare metal or virtualized) to be provisioned. The nodes must be reachable via Virtual Media. + +Requirements +------------ + +* The nodes must be reachable via Virtual Media. +* Access to an OpenShift cluster with ACM and MCE operators +* Access to a valid kubeconfig file available using the `KUBECONFIG` environment variable. +* AgentServiceConfig and Provisioning configured on the host cluster + +Role Variables +-------------- + +The following variables can be set to customize the role behavior: + +### Required Variables + +| Variable Name | Type | Required | Default Value | Description +| --------------------------------------- | --------- | -------- | -------------------------------------- | -------------- +| setup_acm_agents_inventory | List | Yes | [] | Inventory of bare metal hosts. It must contain the BMC credentials. See [Usage examples](#usage-examples) +| setup_acm_agents_infraenv_name | String | Yes | | Target the infrastructure environment +| setup_acm_agents_inject_dns | Boolean | No | false | Enables custom DNS injection. Set to true to pass custom DNS configuration; false disables it +| setup_acm_agents_inject_dns_nameserver | String | No | | Specifies the custom DNS server(s) to use when `setup_acm_agent_inject_dns` is set to true +| setup_acm_agents_location_label | String | No | "" | Location label +| setup_acm_agents_no_log | Boolean | No | `false` | Role's logging configuration + +Usage examples +---------------- + +```yaml +--- +- hosts: localhost + tasks: + - name: Setup ACM Agents + include_role: + name: setup_acm_agents + vars: + setup_acm_agents_infraenv_name: + setup_acm_agent_inventory: + - name: + address: idrac-virtualmedia:///redfish/v1/Systems/System.Embedded.1 + bootMACAddress: + username: + password: + - name: + address: idrac-virtualmedia:///redfish/v1/Systems/System.Embedded.1 + bootMACAddress: + username: + password: +``` diff --git a/roles/setup_acm_agents/defaults/main.yml b/roles/setup_acm_agents/defaults/main.yml new file mode 100644 index 000000000..149155837 --- /dev/null +++ b/roles/setup_acm_agents/defaults/main.yml @@ -0,0 +1,6 @@ +--- +setup_acm_agents_location_label: "" +setup_acm_agents_inject_dns: false +setup_acm_agents_no_log: false +setup_acm_inject_dns: false +... diff --git a/roles/setup_acm_agents/tasks/create-agent.yml b/roles/setup_acm_agents/tasks/create-agent.yml new file mode 100644 index 000000000..8ee367dc3 --- /dev/null +++ b/roles/setup_acm_agents/tasks/create-agent.yml @@ -0,0 +1,209 @@ +--- +- name: Create a namespace for Agents + community.kubernetes.k8s: + api_version: v1 + kind: Namespace + name: "{{ setup_acm_agents_infraenv_name }}" + +- name: Get hub cluster pull_secret details + community.kubernetes.k8s_info: + api: v1 + kind: Secret + name: "pull-secret" + namespace: openshift-config + register: _setup_acm_agents_acm_pull_secret + +- name: Get current master's MCP + community.kubernetes.k8s_info: + api_version: machineconfiguration.openshift.io/v1 + kind: MachineConfigPool + name: master + register: _setup_acm_agents_worker_mcp + +- name: Get current worker's Machine config Pools + ansible.builtin.set_fact: + setup_acm_agents_acm_mc: "{{ _setup_acm_agents_worker_mcp.resources[0].spec.configuration.name }}" + +- name: Get current worker's Machine configs + community.kubernetes.k8s_info: + api_version: machineconfiguration.openshift.io/v1 + kind: MachineConfig + name: "{{ setup_acm_agents_acm_mc }}" + register: _setup_acm_agents_worker_mc + +- name: Setting config facts based on Hub Cluster configs + ansible.builtin.set_fact: + setup_acm_agents_sshkey: "{{ _setup_acm_agents_worker_mc.resources[0].spec.config.passwd.users[0].sshAuthorizedKeys[0] | + regex_replace('\n', '') }}" + setup_acm_agents_pull_secret: '{{ _setup_acm_agents_acm_pull_secret.resources[0].data[".dockerconfigjson"] }}' + +- name: Save the pull secret to a file to be used later by hcp client + ansible.builtin.copy: + content: "{{ setup_acm_agents_pull_secret | b64decode }}" + dest: "{{ setup_acm_agents_working_dir }}/openshift_pull.json" + mode: "0644" + no_log: "{{ setup_acm_agents_no_log | bool }}" + +- name: Save the public ssh key to a file to be used later by hcp client + ansible.builtin.copy: + content: "{{ setup_acm_agents_sshkey }}" + dest: "{{ setup_acm_agents_working_dir }}/id_rsa.pub" + mode: "0644" + no_log: "{{ setup_acm_agents_no_log | bool }}" + +- name: Set pull secret for Assisted installer and Cluster deployment + community.kubernetes.k8s: + kubeconfig: "{{ setup_acm_agents_kubeconfig_file | default(omit) }}" + definition: + apiVersion: v1 + kind: Secret + metadata: + name: "{{ setup_acm_agents_cluster_name }}-pull-secret" + namespace: "{{ setup_acm_agents_infraenv_name }}" + data: + .dockerconfigjson: "{{ setup_acm_agents_pull_secret }}" + type: kubernetes.io/dockerconfigjson + +- name: Define InfraEnv spec without kernelArguments + ansible.builtin.set_fact: + setup_acm_agents_infraenv_spec: + agentLabels: + agentclusterinstalls.extensions.hive.openshift.io/location: "{{ setup_acm_agents_location_label }}" + cpuArchitecture: x86_64 + ipxeScriptType: DiscoveryImageAlways + nmStateConfigLabelSelector: + matchLabels: + infraenvs.agent-install.openshift.io: "{{ setup_acm_agents_infraenv_name }}" + pullSecretRef: + name: "{{ setup_acm_agents_cluster_name }}-pull-secret" + sshAuthorizedKey: "{{ setup_acm_agents_sshkey }}" + +- name: Define InfraEnv spec with kernelArguments + ansible.builtin.set_fact: + setup_acm_agents_infraenv_spec: >- + {{ + setup_acm_agents_infraenv_spec | combine({ + "kernelArguments": [ + { + "operation": "append", + "value": "nameserver=" + setup_acm_agents_inject_dns_nameserver + } + ] + }, recursive=True) + }} + when: setup_acm_agents_inject_dns | bool + +- name: Create InfraEnv YAML file + community.kubernetes.k8s: + kubeconfig: "{{ setup_acm_agents_kubeconfig_file | default(omit) }}" + definition: + apiVersion: agent-install.openshift.io/v1beta1 + kind: InfraEnv + metadata: + annotations: + infraenv.agent-install.openshift.io/enable-ironic-agent: "true" + labels: + agentclusterinstalls.extensions.hive.openshift.io/location: "{{ setup_acm_agents_location_label }}" + networkType: dhcp + name: "{{ setup_acm_agents_infraenv_name }}" + namespace: "{{ setup_acm_agents_infraenv_name }}" + spec: "{{ setup_acm_agents_infraenv_spec }}" + +- name: Pause for sometime before checking for Discovery iso image. + ansible.builtin.pause: + seconds: 20 + +- name: Check if Discovery iso image is Ready + community.kubernetes.k8s_info: + api_version: agent-install.openshift.io/v1beta1 + kind: InfraEnv + kubeconfig: "{{ setup_acm_agents_kubeconfig_file | default(omit) }}" + name: "{{ setup_acm_agents_infraenv_name }}" + namespace: "{{ setup_acm_agents_infraenv_name }}" + register: _setup_acm_agents_infraenv_info + until: + - _setup_acm_agents_infraenv_info != none + - "'resources' in _setup_acm_agents_infraenv_info" + - _setup_acm_agents_infraenv_info.resources != none + - _setup_acm_agents_infraenv_info.resources | length > 0 + - _setup_acm_agents_infraenv_info.resources[0].status.conditions | + json_query("[?type=='ImageCreated' && status=='True']") != none + - _setup_acm_agents_infraenv_info.resources[0].status.conditions | + json_query("[?type=='ImageCreated' && status=='True']") | length > 0 + retries: 3 + delay: 20 + +- name: Create Secrets with creds of hardware inventory + community.kubernetes.k8s: + kubeconfig: "{{ setup_acm_agents_kubeconfig_file | default(omit) }}" + definition: + apiVersion: v1 + kind: Secret + metadata: + name: "{{ bmc.name }}-creds" + namespace: "{{ setup_acm_agents_infraenv_name }}" + type: Opaque + data: + username: "{{ bmc.username | b64encode }}" + password: "{{ bmc.password | b64encode }}" + state: present + loop: "{{ setup_acm_agents_inventory }}" + loop_control: + loop_var: bmc + +- name: Set initial annotations for bmh without installer-args + ansible.builtin.set_fact: + setup_acm_agents_dynamic_annotation: + 'inspect.metal3.io': 'disabled' + +- name: Add installer-args annotation incase custom dns server is used + ansible.builtin.set_fact: + setup_acm_agents_dynamic_annotation: | + {{ + setup_acm_agents_dynamic_annotation | combine({ + 'bmac.agent-install.openshift.io/installer-args': + '["--append-karg", "nameserver=' ~ setup_acm_agents_inject_dns_nameserver ~ '"]' + }) + }} + when: setup_acm_agents_inject_dns | bool + +- name: Loop through bm_inventory and create BareMetalHost resources + community.kubernetes.k8s: + kubeconfig: "{{ setup_acm_agents_kubeconfig_file | default(omit) }}" + definition: + apiVersion: metal3.io/v1alpha1 + kind: BareMetalHost + metadata: + annotations: "{{ setup_acm_agents_dynamic_annotation }}" + labels: + infraenvs.agent-install.openshift.io: "{{ setup_acm_agents_infraenv_name }}" + name: "{{ bmc.name }}" + namespace: "{{ setup_acm_agents_infraenv_name }}" + spec: + automatedCleaningMode: disabled + bmc: + address: "{{ bmc.address }}" + credentialsName: "{{ bmc.name }}-creds" + disableCertificateVerification: true + bootMACAddress: "{{ bmc.bootMACAddress }}" + customDeploy: + method: start_assisted_install + online: true + state: present + loop: "{{ setup_acm_agents_inventory }}" + loop_control: + loop_var: bmc + +- name: Check if the desired agents appear + community.kubernetes.k8s_info: + api_version: agent-install.openshift.io/v1beta1 + kind: Agent + kubeconfig: "{{ setup_acm_agents_kubeconfig_file | default(omit) }}" + namespace: "{{ setup_acm_agents_infraenv_name }}" + register: _setup_acm_agents_agent_info + until: + - "'resources' in _setup_acm_agents_agent_info" + - _setup_acm_agents_agent_info.resources | length == setup_acm_agents_inventory | length + retries: 20 + delay: 60 +... diff --git a/roles/setup_acm_agents/tasks/main.yml b/roles/setup_acm_agents/tasks/main.yml new file mode 100644 index 000000000..586945cdf --- /dev/null +++ b/roles/setup_acm_agents/tasks/main.yml @@ -0,0 +1,7 @@ +--- +- name: Pre run validations + ansible.builtin.include_tasks: validations.yml + +- name: Boot hosts with a discovery image, ready to be provisioned + ansible.builtin.include_tasks: create-agent.yml +... diff --git a/roles/setup_acm_agents/tasks/validations.yml b/roles/setup_acm_agents/tasks/validations.yml new file mode 100644 index 000000000..2349a2f43 --- /dev/null +++ b/roles/setup_acm_agents/tasks/validations.yml @@ -0,0 +1,10 @@ +--- +- name: "Assert parameters" + ansible.builtin.assert: + that: + - setup_acm_agents_inventory is defined + - setup_acm_agents_inventory | type_debug == "list" + - setup_acm_agents_inventory | length > 0 + - setup_acm_agents_infraenv_name is defined + fail_msg: "At least one of the parameters requirements is missing" +...