first commit
This commit is contained in:
BIN
ansible-posix-2.1.0.tar.gz
Normal file
BIN
ansible-posix-2.1.0.tar.gz
Normal file
Binary file not shown.
BIN
apache.tar.gz
Normal file
BIN
apache.tar.gz
Normal file
Binary file not shown.
BIN
community-general-12.1.0.tar.gz
Normal file
BIN
community-general-12.1.0.tar.gz
Normal file
Binary file not shown.
575
create-lab.yml
Normal file
575
create-lab.yml
Normal file
@@ -0,0 +1,575 @@
|
|||||||
|
---
|
||||||
|
###############################################################################
|
||||||
|
# Combined Ansible Playbook
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Play 1: Deploy multiple KubeVirt VMs from Block PVC template with cloud-init
|
||||||
|
###############################################################################
|
||||||
|
- name: Deploy multiple VMs from Block template PVC with cloud-init ISO
|
||||||
|
hosts: localhost
|
||||||
|
gather_facts: false
|
||||||
|
collections:
|
||||||
|
- kubernetes.core
|
||||||
|
|
||||||
|
vars:
|
||||||
|
namespace: default
|
||||||
|
vm_domain: lab.example.com
|
||||||
|
|
||||||
|
rootdisk_size: 64Gi
|
||||||
|
disk2_size: 2Gi
|
||||||
|
disk3_size: 1Gi
|
||||||
|
|
||||||
|
vm_list:
|
||||||
|
- name: controller
|
||||||
|
ip: 10.4.0.100
|
||||||
|
source_pvc: rhce-template
|
||||||
|
- name: node1
|
||||||
|
ip: 10.4.0.101
|
||||||
|
source_pvc: rhce-template
|
||||||
|
- name: node2
|
||||||
|
ip: 10.4.0.102
|
||||||
|
source_pvc: rhce-template
|
||||||
|
- name: node3
|
||||||
|
ip: 10.4.0.103
|
||||||
|
source_pvc: rhce-template
|
||||||
|
- name: node4
|
||||||
|
ip: 10.4.0.104
|
||||||
|
source_pvc: rhce-template
|
||||||
|
- name: node5
|
||||||
|
ip: 10.4.0.105
|
||||||
|
source_pvc: rhce-template
|
||||||
|
- name: utility
|
||||||
|
ip: 10.4.0.106
|
||||||
|
source_pvc: utility-template
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
###########################################################################
|
||||||
|
# Create PVCs
|
||||||
|
###########################################################################
|
||||||
|
- name: Create rootdisk PVC from template
|
||||||
|
k8s:
|
||||||
|
state: present
|
||||||
|
definition:
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: "{{ item.name }}-rootdisk"
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
spec:
|
||||||
|
storageClassName: ocs-storagecluster-ceph-rbd-virtualization
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteMany
|
||||||
|
volumeMode: Block
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: "{{ rootdisk_size }}"
|
||||||
|
dataSource:
|
||||||
|
name: "{{ item.source_pvc }}"
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
apiGroup: ""
|
||||||
|
loop: "{{ vm_list }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item.name }}"
|
||||||
|
|
||||||
|
- name: Create disk2 PVC (2Gi)
|
||||||
|
k8s:
|
||||||
|
state: present
|
||||||
|
definition:
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: "{{ item.name }}-disk2"
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
spec:
|
||||||
|
storageClassName: ocs-storagecluster-ceph-rbd-virtualization
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteMany
|
||||||
|
volumeMode: Block
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: "{{ disk2_size }}"
|
||||||
|
loop: "{{ vm_list }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item.name }}-disk2"
|
||||||
|
|
||||||
|
- name: Create disk3 PVC (1Gi)
|
||||||
|
k8s:
|
||||||
|
state: present
|
||||||
|
definition:
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: "{{ item.name }}-disk3"
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
spec:
|
||||||
|
storageClassName: ocs-storagecluster-ceph-rbd-virtualization
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteMany
|
||||||
|
volumeMode: Block
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: "{{ disk3_size }}"
|
||||||
|
loop: "{{ vm_list }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item.name }}-disk3"
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
# Wait for PVCs
|
||||||
|
###########################################################################
|
||||||
|
- name: Wait for all PVCs to be bound
|
||||||
|
k8s_info:
|
||||||
|
api_version: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
name: "{{ item.0.name }}-{{ item.1 }}"
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
register: pvc_status
|
||||||
|
until: pvc_status.resources[0].status.phase == "Bound"
|
||||||
|
retries: 30
|
||||||
|
delay: 5
|
||||||
|
loop: "{{ vm_list | product(['rootdisk', 'disk2', 'disk3']) | list }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item.0.name }}-{{ item.1 }}"
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
# Create VirtualMachines
|
||||||
|
###########################################################################
|
||||||
|
- name: Create VirtualMachine with additional raw disks
|
||||||
|
k8s:
|
||||||
|
state: present
|
||||||
|
definition:
|
||||||
|
apiVersion: kubevirt.io/v1
|
||||||
|
kind: VirtualMachine
|
||||||
|
metadata:
|
||||||
|
name: "{{ item.name }}"
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
spec:
|
||||||
|
running: true
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
kubevirt.io/domain: "{{ item.name }}"
|
||||||
|
spec:
|
||||||
|
domain:
|
||||||
|
cpu:
|
||||||
|
cores: 1
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: 2Gi
|
||||||
|
devices:
|
||||||
|
disks:
|
||||||
|
- name: rootdisk
|
||||||
|
disk:
|
||||||
|
bus: virtio
|
||||||
|
- name: disk2
|
||||||
|
disk:
|
||||||
|
bus: virtio
|
||||||
|
- name: disk3
|
||||||
|
disk:
|
||||||
|
bus: virtio
|
||||||
|
- name: cloudinitdisk
|
||||||
|
disk:
|
||||||
|
bus: virtio
|
||||||
|
interfaces:
|
||||||
|
- name: default
|
||||||
|
bridge: {}
|
||||||
|
networks:
|
||||||
|
- name: default
|
||||||
|
multus:
|
||||||
|
networkName: rhce
|
||||||
|
volumes:
|
||||||
|
- name: rootdisk
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: "{{ item.name }}-rootdisk"
|
||||||
|
- name: disk2
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: "{{ item.name }}-disk2"
|
||||||
|
- name: disk3
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: "{{ item.name }}-disk3"
|
||||||
|
- name: cloudinitdisk
|
||||||
|
cloudInitNoCloud:
|
||||||
|
hostname: "{{ item.name }}"
|
||||||
|
fqdn: "{{ item.name }}.{{ vm_domain }}"
|
||||||
|
manage_etc_hosts: true
|
||||||
|
networkData: |
|
||||||
|
version: 2
|
||||||
|
ethernets:
|
||||||
|
enp1s0:
|
||||||
|
dhcp4: false
|
||||||
|
addresses:
|
||||||
|
- "{{ item.ip }}/24"
|
||||||
|
gateway4: 10.4.0.1
|
||||||
|
nameservers:
|
||||||
|
search:
|
||||||
|
- "{{ vm_domain }}"
|
||||||
|
addresses:
|
||||||
|
- 10.1.0.1
|
||||||
|
userData: |
|
||||||
|
#cloud-config
|
||||||
|
users:
|
||||||
|
- name: redhat
|
||||||
|
sudo: ALL=(ALL) NOPASSWD:ALL
|
||||||
|
lock_passwd: false
|
||||||
|
chpasswd:
|
||||||
|
list: |
|
||||||
|
redhat:redhat
|
||||||
|
expire: false
|
||||||
|
ssh_pwauth: true
|
||||||
|
user: redhat
|
||||||
|
password: redhat
|
||||||
|
loop: "{{ vm_list }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item.name }}"
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Play 2: Add static DNS entries to dnsmasq on OPNsense
|
||||||
|
###############################################################################
|
||||||
|
- name: Add static DNS entries to dnsmasq on OPNsense
|
||||||
|
hosts: opnsense.lab.cudanet.org
|
||||||
|
become: true
|
||||||
|
remote_user: root
|
||||||
|
gather_facts: false
|
||||||
|
|
||||||
|
vars:
|
||||||
|
ansible_python_interpreter: /usr/local/bin/python3
|
||||||
|
dnsmasq_hosts_file: /usr/local/etc/dnsmasq.conf.d/lab.conf
|
||||||
|
vms:
|
||||||
|
- ip: "10.4.0.100"
|
||||||
|
hostname: "controller.lab.example.com"
|
||||||
|
- ip: "10.4.0.101"
|
||||||
|
hostname: "node1.lab.example.com"
|
||||||
|
- ip: "10.4.0.102"
|
||||||
|
hostname: "node2.lab.example.com"
|
||||||
|
- ip: "10.4.0.103"
|
||||||
|
hostname: "node3.lab.example.com"
|
||||||
|
- ip: "10.4.0.104"
|
||||||
|
hostname: "node4.lab.example.com"
|
||||||
|
- ip: "10.4.0.105"
|
||||||
|
hostname: "node5.lab.example.com"
|
||||||
|
- ip: "10.4.0.106"
|
||||||
|
hostname: "utility.lab.example.com"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Ensure dnsmasq hosts file exists
|
||||||
|
file:
|
||||||
|
path: "{{ dnsmasq_hosts_file }}"
|
||||||
|
state: touch
|
||||||
|
owner: root
|
||||||
|
group: wheel
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Add static DNS entries to dnsmasq hosts file
|
||||||
|
lineinfile:
|
||||||
|
path: "{{ dnsmasq_hosts_file }}"
|
||||||
|
line: "address=/{{ item.hostname }}/{{ item.ip }}"
|
||||||
|
state: present
|
||||||
|
create: yes
|
||||||
|
backup: yes
|
||||||
|
loop: "{{ vms }}"
|
||||||
|
|
||||||
|
- name: Reload dnsmasq service
|
||||||
|
ansible.builtin.shell: pluginctl dns
|
||||||
|
|
||||||
|
- name: Ping each host from OPNsense to verify connectivity
|
||||||
|
ansible.builtin.shell: ping -c 3 {{ item.ip }}
|
||||||
|
register: ping_result
|
||||||
|
ignore_errors: yes
|
||||||
|
loop: "{{ vms }}"
|
||||||
|
|
||||||
|
- name: Show ping results
|
||||||
|
debug:
|
||||||
|
msg: |
|
||||||
|
Ping to {{ item.item.hostname }} returned (rc={{ item.rc }}):
|
||||||
|
{{ item.stdout }}
|
||||||
|
loop: "{{ ping_result.results }}"
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Play 3: Register system, configure services, and mirror EE to local registry
|
||||||
|
###############################################################################
|
||||||
|
- name: Register system, configure services, and mirror EE to local registry
|
||||||
|
hosts: utility
|
||||||
|
become: true
|
||||||
|
|
||||||
|
vars:
|
||||||
|
sat_user: "{{ vault_sat_user }}"
|
||||||
|
sat_passwd: "{{ vault_sat_passwd }}"
|
||||||
|
sat_orgid: "{{ vault_sat_orgid }}"
|
||||||
|
redhat_env: "{{ vault_redhat_env }}"
|
||||||
|
registry_host: utility.lab.example.com
|
||||||
|
registry_port: 5000
|
||||||
|
host_port: 5000
|
||||||
|
registry_image: docker.io/library/registry:2
|
||||||
|
podman_user: "{{ vault_podman_user }}"
|
||||||
|
podman_passwd: "{{ vault_podman_passwd }}"
|
||||||
|
ee_source_image: registry.redhat.io/ansible-automation-platform-25/ee-supported-rhel9:latest
|
||||||
|
ee_target_image: "{{ registry_host }}:{{ registry_port }}/ee-supported-rhel9:latest"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Register system with Red Hat Subscription Management
|
||||||
|
community.general.redhat_subscription:
|
||||||
|
username: "{{ sat_user }}"
|
||||||
|
password: "{{ sat_passwd }}"
|
||||||
|
org_id: "{{ sat_orgid }}"
|
||||||
|
environment: "{{ redhat_env }}"
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Install required packages
|
||||||
|
ansible.builtin.dnf:
|
||||||
|
name:
|
||||||
|
- httpd
|
||||||
|
- firewalld
|
||||||
|
- podman
|
||||||
|
- policycoreutils-python-utils
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Enable and start httpd
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: httpd
|
||||||
|
state: started
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
- name: Enable and start firewalld
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: firewalld
|
||||||
|
state: started
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
- name: Allow HTTP service through firewall
|
||||||
|
ansible.posix.firewalld:
|
||||||
|
service: http
|
||||||
|
permanent: true
|
||||||
|
state: enabled
|
||||||
|
immediate: true
|
||||||
|
|
||||||
|
- name: Allow registry port through firewall
|
||||||
|
ansible.posix.firewalld:
|
||||||
|
port: "{{ registry_port }}/tcp"
|
||||||
|
permanent: true
|
||||||
|
state: enabled
|
||||||
|
immediate: true
|
||||||
|
|
||||||
|
- name: Ensure correct permissions on web root
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /var/www/html
|
||||||
|
recurse: true
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: Set SELinux context for Ansible Automation Platform content
|
||||||
|
community.general.sefcontext:
|
||||||
|
target: "/var/www/html/ansible-automation-platform(/.*)?"
|
||||||
|
setype: httpd_sys_content_t
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Set SELinux context for RHEL 9 content
|
||||||
|
community.general.sefcontext:
|
||||||
|
target: "/var/www/html/rhel9(/.*)?"
|
||||||
|
setype: httpd_sys_content_t
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Set SELinux context for files
|
||||||
|
community.general.sefcontext:
|
||||||
|
target: "/var/www/html/files(/.*)?"
|
||||||
|
setype: httpd_sys_content_t
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Restore SELinux contexts
|
||||||
|
ansible.builtin.command: restorecon -Rv /var/www/html
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Create registry quadlet file
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /etc/containers/systemd/registry.container
|
||||||
|
mode: "0644"
|
||||||
|
content: |
|
||||||
|
[Unit]
|
||||||
|
Description=Registry
|
||||||
|
|
||||||
|
[Container]
|
||||||
|
ContainerName=registry
|
||||||
|
Image={{ registry_image }}
|
||||||
|
PublishPort={{ registry_port }}:{{ host_port }}
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
|
||||||
|
- name: Reload Systemd Daemons
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
daemon_reload: yes
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Start registry.service
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: registry.service
|
||||||
|
state: started
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Create containers config directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /root/.config/containers
|
||||||
|
state: directory
|
||||||
|
mode: "0700"
|
||||||
|
|
||||||
|
- name: Configure insecure registry
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /root/.config/containers/registries.conf
|
||||||
|
mode: "0600"
|
||||||
|
content: |
|
||||||
|
[[registry]]
|
||||||
|
location = "{{ registry_host }}:{{ registry_port }}"
|
||||||
|
insecure = true
|
||||||
|
|
||||||
|
- name: Login to Red Hat registry
|
||||||
|
containers.podman.podman_login:
|
||||||
|
username: "{{ podman_user }}"
|
||||||
|
password: "{{ podman_passwd }}"
|
||||||
|
registry: registry.redhat.io
|
||||||
|
|
||||||
|
- name: Pull Execution Environment image
|
||||||
|
containers.podman.podman_image:
|
||||||
|
name: "{{ ee_source_image }}"
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Tag EE image for local registry
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: podman tag {{ ee_source_image }} {{ ee_target_image }}
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
- name: Push EE image to local registry
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: podman push --remove-signatures {{ ee_target_image }}
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
- name: Install chrony package
|
||||||
|
ansible.builtin.package:
|
||||||
|
name: chrony
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Configure chrony as NTP server
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: /etc/chrony.conf
|
||||||
|
regexp: '^allow'
|
||||||
|
line: 'allow 0.0.0.0/0'
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Ensure chrony service is enabled and started
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: chronyd
|
||||||
|
state: started
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
- name: Open NTP service in firewall
|
||||||
|
ansible.builtin.firewalld:
|
||||||
|
service: ntp
|
||||||
|
permanent: true
|
||||||
|
state: enabled
|
||||||
|
immediate: true
|
||||||
|
when: ansible_facts.services['firewalld.service'] is defined
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Play 4: Configure the Controller node
|
||||||
|
###############################################################################
|
||||||
|
- name: Configure the Controller node
|
||||||
|
hosts: controller
|
||||||
|
become: true
|
||||||
|
|
||||||
|
vars:
|
||||||
|
registry_host: utility.lab.example.com
|
||||||
|
registry_port: 5000
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Create repo file
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
[ansible-automation-platform-2.5]
|
||||||
|
name=Ansible Automation Platform 2.5
|
||||||
|
metadata_expire=-1
|
||||||
|
gpgcheck=1
|
||||||
|
enabled=1
|
||||||
|
baseurl=http://utility.lab.example.com/ansible-automation-platform/2.5
|
||||||
|
gpgkey=http://utility.lab.example.com/rhel9/RPM-GPG-KEY-redhat-release
|
||||||
|
|
||||||
|
[BaseOS]
|
||||||
|
name=BaseOS Packages Red Hat Enterprise Linux 9
|
||||||
|
metadata_expire=-1
|
||||||
|
gpgcheck=1
|
||||||
|
enabled=1
|
||||||
|
baseurl=http://utility.lab.example.com/rhel9/BaseOS
|
||||||
|
gpgkey=http://utility.lab.example.com/rhel9/RPM-GPG-KEY-redhat-release
|
||||||
|
|
||||||
|
[AppStream]
|
||||||
|
name=AppStream Packages Red Hat Enterprise Linux 9
|
||||||
|
metadata_expire=-1
|
||||||
|
gpgcheck=1
|
||||||
|
enabled=1
|
||||||
|
baseurl=http://utility.lab.example.com/rhel9/AppStream/
|
||||||
|
gpgkey=http://utility.lab.example.com/rhel9/rpm-gpg/RPM-GPG-KEY-redhat-release
|
||||||
|
dest: /etc/yum.repos.d/rhce.repo
|
||||||
|
|
||||||
|
- name: Install required packages
|
||||||
|
ansible.builtin.dnf:
|
||||||
|
name:
|
||||||
|
- podman
|
||||||
|
- ansible-core
|
||||||
|
- ansible-navigator
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Create directories
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ item }}"
|
||||||
|
state: directory
|
||||||
|
mode: "0700"
|
||||||
|
owner: ansible
|
||||||
|
group: ansible
|
||||||
|
loop:
|
||||||
|
- /home/ansible/.config
|
||||||
|
- /home/ansible/.config/containers
|
||||||
|
- /home/ansible/ansible
|
||||||
|
- /home/ansible/ansible/roles
|
||||||
|
- /home/ansible/ansible/mycollections
|
||||||
|
|
||||||
|
- name: Configure insecure registry
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /home/ansible/.config/containers/registries.conf
|
||||||
|
mode: "0600"
|
||||||
|
content: |
|
||||||
|
[[registry]]
|
||||||
|
location = "{{ registry_host }}:{{ registry_port }}"
|
||||||
|
insecure = true
|
||||||
|
owner: ansible
|
||||||
|
group: ansible
|
||||||
|
|
||||||
|
- name: Configure ansible.cfg
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /home/ansible/ansible/ansible.cfg
|
||||||
|
content: |
|
||||||
|
[defaults]
|
||||||
|
inventory = /home/ansible/ansible/inventory
|
||||||
|
remote_user = ansible
|
||||||
|
roles_path = /home/ansible/ansible/roles
|
||||||
|
collections_path = /home/ansible/ansible/mycollections
|
||||||
|
|
||||||
|
- name: Configure ansible-navigator.yml
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /home/ansible/ansible/ansible-navigator.yml
|
||||||
|
content: |
|
||||||
|
---
|
||||||
|
ansible-navigator:
|
||||||
|
execution-environment:
|
||||||
|
image: utility.lab.example.com:5000/ee-supported-rhel9:latest
|
||||||
|
pull:
|
||||||
|
policy: missing
|
||||||
|
playbook-artifact:
|
||||||
|
enable: false
|
||||||
|
|
||||||
|
- name: Create test.yml
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /home/ansible/ansible/test.yml
|
||||||
|
content: |
|
||||||
|
---
|
||||||
|
- name: A simple playbook to test that Ansible is configured
|
||||||
|
hosts: localhost
|
||||||
|
tasks:
|
||||||
|
- name: Run test playbook
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "If you're reading this, Ansible is configured on your system."
|
||||||
9
debug.yml
Normal file
9
debug.yml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
- name: Print facts
|
||||||
|
hosts: jump01.lab.cudanet.org
|
||||||
|
gather_facts: true
|
||||||
|
remote_user: root
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: print facts
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "The default IPv4 address for {{ inventory_hostname }} is {{ ansible_default_ipv4.address }}"
|
||||||
69
destroy-lab.yml
Normal file
69
destroy-lab.yml
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
---
|
||||||
|
- name: Delete VMs and all associated disks (PVCs)
|
||||||
|
hosts: localhost
|
||||||
|
gather_facts: false
|
||||||
|
collections:
|
||||||
|
- kubernetes.core
|
||||||
|
|
||||||
|
vars:
|
||||||
|
namespace: default
|
||||||
|
|
||||||
|
vm_names:
|
||||||
|
- controller
|
||||||
|
- node1
|
||||||
|
- node2
|
||||||
|
- node3
|
||||||
|
- node4
|
||||||
|
- node5
|
||||||
|
- utility
|
||||||
|
|
||||||
|
disks:
|
||||||
|
- rootdisk
|
||||||
|
- disk2
|
||||||
|
- disk3
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
###########################################################################
|
||||||
|
# Delete VMs
|
||||||
|
###########################################################################
|
||||||
|
- name: Delete VirtualMachines
|
||||||
|
k8s:
|
||||||
|
api_version: kubevirt.io/v1
|
||||||
|
kind: VirtualMachine
|
||||||
|
name: "{{ item }}"
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
state: absent
|
||||||
|
loop: "{{ vm_names }}"
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
# Wait until VMs are actually gone (IMPORTANT)
|
||||||
|
###########################################################################
|
||||||
|
- name: Wait for VMs to be fully deleted
|
||||||
|
k8s_info:
|
||||||
|
api_version: kubevirt.io/v1
|
||||||
|
kind: VirtualMachine
|
||||||
|
name: "{{ item }}"
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
register: vm_check
|
||||||
|
until: vm_check.resources | length == 0
|
||||||
|
retries: 30
|
||||||
|
delay: 5
|
||||||
|
loop: "{{ vm_names }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item }}"
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
# Delete PVCs (no pre-check, safe & idempotent)
|
||||||
|
###########################################################################
|
||||||
|
- name: Delete PVCs for all VM disks
|
||||||
|
k8s:
|
||||||
|
api_version: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
name: "{{ item.0 }}-{{ item.1 }}"
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
state: absent
|
||||||
|
loop: "{{ vm_names | product(disks) | list }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item.0 }}-{{ item.1 }}"
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
BIN
haproxy.tar.gz
Normal file
BIN
haproxy.tar.gz
Normal file
Binary file not shown.
7
hwreport.empty
Normal file
7
hwreport.empty
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
HOST=
|
||||||
|
BIOS=
|
||||||
|
MEMORY=
|
||||||
|
VDB=
|
||||||
|
VDC=
|
||||||
|
VDE=
|
||||||
|
|
||||||
14
inventory
Normal file
14
inventory
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[satellite]
|
||||||
|
satellite.lab.cudanet.org
|
||||||
|
|
||||||
|
[workstation]
|
||||||
|
jump01.lab.cudanet.org
|
||||||
|
|
||||||
|
[routers]
|
||||||
|
opnsense.lab.cudanet.org
|
||||||
|
|
||||||
|
[utility]
|
||||||
|
utility.lab.example.com
|
||||||
|
|
||||||
|
[controller]
|
||||||
|
controller.lab.example.com
|
||||||
2
myhosts.txt
Normal file
2
myhosts.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
|
||||||
|
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
|
||||||
BIN
phpinfo.tar.gz
Normal file
BIN
phpinfo.tar.gz
Normal file
Binary file not shown.
BIN
redhat-rhel_system_roles-1.108.6.tar.gz
Normal file
BIN
redhat-rhel_system_roles-1.108.6.tar.gz
Normal file
Binary file not shown.
9
salaries.yml
Normal file
9
salaries.yml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
$ANSIBLE_VAULT;1.1;AES256
|
||||||
|
32373538383562646335653030373731386462393436643032363863653637396334376537386337
|
||||||
|
3434323231616637643462373664313661363037343534660a373236663364363138376435646231
|
||||||
|
39666263666362623536393261303966393434316130336436613636393137656233616364396532
|
||||||
|
3036366663333263650a356561386439356364383131356533313834653164346262353934316238
|
||||||
|
64323934376437663435636666326465393336663535353335353864353663333064343031383264
|
||||||
|
30393361336533383533316538386539333437316165303964313665353466346164326638326132
|
||||||
|
33333830646262333662653739306662613662653032626166373730623062373936333239643532
|
||||||
|
61353739353830626137
|
||||||
8
solutions/ansible-navigator.yml
Normal file
8
solutions/ansible-navigator.yml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
ansible-navigator:
|
||||||
|
execution-environment:
|
||||||
|
image: utility.lab.example.com:5000/ee-supported-rhel9:latest
|
||||||
|
pull:
|
||||||
|
policy: missing
|
||||||
|
playbook-artifact:
|
||||||
|
enable: false
|
||||||
21
solutions/ansible.cfg
Normal file
21
solutions/ansible.cfg
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
[defaults]
|
||||||
|
inventory = ./inventory
|
||||||
|
interpreter_python = /usr/bin/python3
|
||||||
|
remote_user = ansible
|
||||||
|
host_key_checking = false
|
||||||
|
roles_path = /root/ansible/roles
|
||||||
|
|
||||||
|
[galaxy]
|
||||||
|
server_list = automation_hub
|
||||||
|
|
||||||
|
[galaxy_server.automation_hub]
|
||||||
|
url = https://console.redhat.com/api/automation-hub/
|
||||||
|
auth_url = https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token
|
||||||
|
token = "eyJhbGciOiJIUzUxMiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0NzQzYTkzMC03YmJiLTRkZGQtOTgzMS00ODcxNGRlZDc0YjUifQ.eyJpYXQiOjE3NjYzMzM3MDgsImp0aSI6ImYzMGQ4ZDQ4LTJlYTAtNGI2OS1iZmFhLWViZTNhOGIxZDA0MyIsImlzcyI6Imh0dHBzOi8vc3NvLnJlZGhhdC5jb20vYXV0aC9yZWFsbXMvcmVkaGF0LWV4dGVybmFsIiwiYXVkIjoiaHR0cHM6Ly9zc28ucmVkaGF0LmNvbS9hdXRoL3JlYWxtcy9yZWRoYXQtZXh0ZXJuYWwiLCJzdWIiOiI1NDY5MjM3NiIsInR5cCI6Ik9mZmxpbmUiLCJhenAiOiJjbG91ZC1zZXJ2aWNlcyIsIm5vbmNlIjoiODI2YWZmNTktOTZmNC00ODcyLTg0MDUtNWYzODY0M2M3YzMwIiwic2lkIjoiMjdiZWY4NjMtOGFiZS00YWFlLTk4NGUtN2M5YzU3ODVmM2Y3Iiwic2NvcGUiOiJvcGVuaWQgYXBpLmNvbnNvbGUgYmFzaWMgcm9sZXMgd2ViLW9yaWdpbnMgY2xpZW50X3R5cGUucHJlX2tjMjUgYXBpLmFza19yZWRfaGF0IG9mZmxpbmVfYWNjZXNzIn0.75q6N-IJiOGSxWmMOraXYmeJxmPU4p6iSFJj99jqhOOpKvgDk9_gD-MnM8FU_AGvuifbYn8_zj2QgTSaLlo8hw"
|
||||||
|
|
||||||
|
[galaxy_server.galaxy_hub]
|
||||||
|
url=https://galaxy.ansible.com/
|
||||||
|
|
||||||
|
[privilege_escalation]
|
||||||
|
become = true
|
||||||
|
become_method = sudo
|
||||||
7
solutions/apache.yml
Normal file
7
solutions/apache.yml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# apache_role.yml
|
||||||
|
---
|
||||||
|
- name: Configure Apache web servers
|
||||||
|
hosts: dev
|
||||||
|
become: true
|
||||||
|
roles:
|
||||||
|
- apache
|
||||||
49
solutions/hwreport.yml
Normal file
49
solutions/hwreport.yml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
---
|
||||||
|
- name: Generate hardware report
|
||||||
|
hosts: all
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Download empty hwreport file
|
||||||
|
get_url:
|
||||||
|
url: http://utility.lab.example.com/files/hwreport.empty
|
||||||
|
dest: /root/hwreport.txt
|
||||||
|
mode: '0644'
|
||||||
|
|
||||||
|
- name: Set hostname
|
||||||
|
lineinfile:
|
||||||
|
path: /root/hwreport.txt
|
||||||
|
regexp: '^HOST='
|
||||||
|
line: "HOST={{ ansible_hostname }}"
|
||||||
|
|
||||||
|
- name: Set BIOS version
|
||||||
|
lineinfile:
|
||||||
|
path: /root/hwreport.txt
|
||||||
|
regexp: '^BIOS='
|
||||||
|
line: "BIOS={{ ansible_bios_version | default('NONE') }}"
|
||||||
|
|
||||||
|
- name: Set memory size
|
||||||
|
lineinfile:
|
||||||
|
path: /root/hwreport.txt
|
||||||
|
regexp: '^MEMORY='
|
||||||
|
line: "MEMORY={{ ansible_memtotal_mb }} MB"
|
||||||
|
|
||||||
|
- name: Set vdb disk size
|
||||||
|
lineinfile:
|
||||||
|
path: /root/hwreport.txt
|
||||||
|
regexp: '^VDB='
|
||||||
|
line: "VDB={{ ansible_devices.vdb.size | default('NONE') }}"
|
||||||
|
|
||||||
|
- name: Set vdc disk size
|
||||||
|
lineinfile:
|
||||||
|
path: /root/hwreport.txt
|
||||||
|
regexp: '^VDC='
|
||||||
|
line: "VDC={{ ansible_devices.vdc.size | default('NONE') }}"
|
||||||
|
|
||||||
|
- name: Set vdd disk size (NONE if missing)
|
||||||
|
lineinfile:
|
||||||
|
path: /root/hwreport.txt
|
||||||
|
regexp: '^VDD='
|
||||||
|
line: >-
|
||||||
|
VDD={{ ansible_devices.vdd.size if 'vdd' in ansible_devices else 'NONE' }}
|
||||||
|
|
||||||
20
solutions/install.yml
Normal file
20
solutions/install.yml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# playbook.yml
|
||||||
|
- name: Install Packages and Groups
|
||||||
|
hosts: all
|
||||||
|
|
||||||
|
become: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Install packages on test group
|
||||||
|
ansible.builtin.dnf:
|
||||||
|
name:
|
||||||
|
- httpd
|
||||||
|
- php
|
||||||
|
state: latest
|
||||||
|
when: inventory_hostname in groups['test']
|
||||||
|
|
||||||
|
- name: Install RPM Development Tools group on dev group
|
||||||
|
ansible.builtin.dnf:
|
||||||
|
name: "@RPM Development Tools"
|
||||||
|
state: latest
|
||||||
|
when: inventory_hostname in groups['dev']
|
||||||
16
solutions/inventory
Normal file
16
solutions/inventory
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
[dev]
|
||||||
|
node1
|
||||||
|
|
||||||
|
[test]
|
||||||
|
node2
|
||||||
|
|
||||||
|
[prod]
|
||||||
|
node3
|
||||||
|
node4
|
||||||
|
|
||||||
|
[balancers]
|
||||||
|
node5
|
||||||
|
|
||||||
|
[webservers:children]
|
||||||
|
prod
|
||||||
|
|
||||||
28
solutions/issue.yml
Normal file
28
solutions/issue.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
- name: Automatically populate /etc/issue with environment name
|
||||||
|
hosts:
|
||||||
|
- dev
|
||||||
|
- test
|
||||||
|
- prod
|
||||||
|
become: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Determine environment name from inventory groups
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
env_name: >-
|
||||||
|
{% if 'prod' in group_names %}
|
||||||
|
Production
|
||||||
|
{% elif 'test' in group_names %}
|
||||||
|
Testing
|
||||||
|
{% elif 'dev' in group_names %}
|
||||||
|
Development
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
- name: Populate /etc/issue
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /etc/issue
|
||||||
|
content: |
|
||||||
|
{{ env_name }}
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0644'
|
||||||
74
solutions/partition.yml
Normal file
74
solutions/partition.yml
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
---
|
||||||
|
- name: Configure disk partitions and mounts
|
||||||
|
hosts: all
|
||||||
|
become: true
|
||||||
|
gather_facts: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
####################################################################
|
||||||
|
# /dev/vdb — always create 1500MB partition mounted at /devmount
|
||||||
|
####################################################################
|
||||||
|
- name: Create 1500MB partition on /dev/vdb
|
||||||
|
community.general.parted:
|
||||||
|
device: /dev/vdb
|
||||||
|
number: 1
|
||||||
|
state: present
|
||||||
|
part_end: 1500MiB
|
||||||
|
|
||||||
|
- name: Create XFS filesystem on /dev/vdb1
|
||||||
|
ansible.builtin.filesystem:
|
||||||
|
fstype: xfs
|
||||||
|
dev: /dev/vdb1
|
||||||
|
|
||||||
|
- name: Mount /dev/vdb1 at /devmount
|
||||||
|
ansible.builtin.mount:
|
||||||
|
path: /devmount
|
||||||
|
src: /dev/vdb1
|
||||||
|
fstype: xfs
|
||||||
|
state: mounted
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
# /dev/vdc — size-based logic (1500MB or 800MB)
|
||||||
|
####################################################################
|
||||||
|
- name: Determine size of /dev/vdc partition
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
vdc_part_size: >-
|
||||||
|
{{ '1500MiB'
|
||||||
|
if (ansible_facts.devices.vdc.sectors | int *
|
||||||
|
ansible_facts.devices.vdc.sectorsize | int) >= (1500 * 1024 * 1024)
|
||||||
|
else '800MiB' }}
|
||||||
|
when: "'vdc' in ansible_facts.devices"
|
||||||
|
|
||||||
|
- name: Create partition on /dev/vdc
|
||||||
|
community.general.parted:
|
||||||
|
device: /dev/vdc
|
||||||
|
number: 1
|
||||||
|
state: present
|
||||||
|
part_end: "{{ vdc_part_size }}"
|
||||||
|
when: "'vdc' in ansible_facts.devices"
|
||||||
|
|
||||||
|
- name: Create XFS filesystem on /dev/vdc1
|
||||||
|
ansible.builtin.filesystem:
|
||||||
|
fstype: xfs
|
||||||
|
dev: /dev/vdc1
|
||||||
|
when: "'vdc' in ansible_facts.devices"
|
||||||
|
|
||||||
|
- name: Mount /dev/vdc1
|
||||||
|
ansible.builtin.mount:
|
||||||
|
path: >-
|
||||||
|
{{ '/devmount1'
|
||||||
|
if vdc_part_size == '1500MiB'
|
||||||
|
else '/dev/mount' }}
|
||||||
|
src: /dev/vdc1
|
||||||
|
fstype: xfs
|
||||||
|
state: mounted
|
||||||
|
when: "'vdc' in ansible_facts.devices"
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
# /dev/vde presence check
|
||||||
|
####################################################################
|
||||||
|
- name: Warn if /dev/vde is not present
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "Disk /dev/vde is not present"
|
||||||
|
when: "'vde' not in ansible_facts.devices"
|
||||||
|
|
||||||
27
solutions/repos.yml
Normal file
27
solutions/repos.yml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
# repos.yml
|
||||||
|
- name: Add BaseOS and AppStream repos to all hosts
|
||||||
|
hosts: all
|
||||||
|
become: true
|
||||||
|
|
||||||
|
vars:
|
||||||
|
repos:
|
||||||
|
- BaseOS
|
||||||
|
- AppStream
|
||||||
|
|
||||||
|
baseurl: http://utility.lab.example.com/rhel9
|
||||||
|
gpgkey_url: http://utility.lab.example.com/rhel9/RPM-GPG-KEY-redhat-release
|
||||||
|
repo_file: /etc/yum.repos.d/rhce
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Add {{ item }} repository
|
||||||
|
ansible.builtin.yum_repository:
|
||||||
|
name: "EX294_{{ item }}"
|
||||||
|
description: "EX294 {{ item }} Repository"
|
||||||
|
baseurl: "{{ baseurl }}/{{ item }}"
|
||||||
|
enabled: true
|
||||||
|
gpgcheck: true
|
||||||
|
gpgkey: "{{ gpgkey_url }}"
|
||||||
|
file: "{{ repo_file }}"
|
||||||
|
loop: "{{ repos }}"
|
||||||
|
|
||||||
23
solutions/requirements.yml
Normal file
23
solutions/requirements.yml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# requirements.yml
|
||||||
|
---
|
||||||
|
roles:
|
||||||
|
- name: phpinfo
|
||||||
|
src: http://utility.lab.example.com/files/phpinfo.tar.gz
|
||||||
|
path: /home/ansible/ansible/roles
|
||||||
|
|
||||||
|
- name: balancer
|
||||||
|
src: http://utility.lab.example.com/files/haproxy.tar.gz
|
||||||
|
path: /home/ansible/ansible/roles
|
||||||
|
|
||||||
|
collections:
|
||||||
|
- name: ansible.posix
|
||||||
|
source: http://utility.lab.example.com/files/ansible-posix-2.1.0.tar.gz
|
||||||
|
type: url
|
||||||
|
|
||||||
|
- name: redhat.rhel_system_roles
|
||||||
|
source: http://utility.lab.example.com/files/redhat-rhel_system_roles-1.108.6.tar.gz
|
||||||
|
type: url
|
||||||
|
|
||||||
|
- name: community.general
|
||||||
|
source: http://utility.lab.example.com/files/community-general-12.1.0.tar.gz
|
||||||
|
type: url
|
||||||
15
solutions/rhce.repo
Normal file
15
solutions/rhce.repo
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
[BaseOS]
|
||||||
|
name=BaseOS Packages Red Hat Enterprise Linux 9
|
||||||
|
metadata_expire=-1
|
||||||
|
gpgcheck=1
|
||||||
|
enabled=1
|
||||||
|
baseurl=http://utility.lab.example.com/rhel9/BaseOS
|
||||||
|
gpgkey=http://utility.lab.example.com/rhel9/RPM-GPG-KEY-redhat-release
|
||||||
|
|
||||||
|
[AppStream]
|
||||||
|
name=AppStream Packages Red Hat Enterprise Linux 9
|
||||||
|
metadata_expire=-1
|
||||||
|
gpgcheck=1
|
||||||
|
enabled=1
|
||||||
|
baseurl=http://utility.lab.example.com/rhel9/AppStream/
|
||||||
|
gpgkey=http://utility.lab.example.com/rhel9/rpm-gpg/RPM-GPG-KEY-redhat-release
|
||||||
13
solutions/roles.yml
Normal file
13
solutions/roles.yml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# roles.yml
|
||||||
|
---
|
||||||
|
- name: Configure load balancer
|
||||||
|
hosts: balancers
|
||||||
|
become: yes
|
||||||
|
roles:
|
||||||
|
- balancer
|
||||||
|
|
||||||
|
- name: Configure web servers
|
||||||
|
hosts: webservers
|
||||||
|
become: yes
|
||||||
|
roles:
|
||||||
|
- phpinfo
|
||||||
38
solutions/roles/apache/README.md
Normal file
38
solutions/roles/apache/README.md
Normal file
@@ -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).
|
||||||
5
solutions/roles/apache/defaults/main.yml
Normal file
5
solutions/roles/apache/defaults/main.yml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# defaults/main.yml
|
||||||
|
---
|
||||||
|
apache_packages:
|
||||||
|
- httpd
|
||||||
|
- firewalld
|
||||||
6
solutions/roles/apache/handlers/main.yml
Normal file
6
solutions/roles/apache/handlers/main.yml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# handlers/main.yml
|
||||||
|
---
|
||||||
|
- name: restart httpd
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: httpd
|
||||||
|
state: restarted
|
||||||
52
solutions/roles/apache/meta/main.yml
Normal file
52
solutions/roles/apache/meta/main.yml
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
galaxy_info:
|
||||||
|
author: your name
|
||||||
|
description: your role description
|
||||||
|
company: your company (optional)
|
||||||
|
|
||||||
|
# If the issue tracker for your role is not on github, uncomment the
|
||||||
|
# next line and provide a value
|
||||||
|
# issue_tracker_url: http://example.com/issue/tracker
|
||||||
|
|
||||||
|
# Choose a valid license ID from https://spdx.org - some suggested licenses:
|
||||||
|
# - BSD-3-Clause (default)
|
||||||
|
# - MIT
|
||||||
|
# - GPL-2.0-or-later
|
||||||
|
# - GPL-3.0-only
|
||||||
|
# - Apache-2.0
|
||||||
|
# - CC-BY-4.0
|
||||||
|
license: license (GPL-2.0-or-later, MIT, etc)
|
||||||
|
|
||||||
|
min_ansible_version: 2.1
|
||||||
|
|
||||||
|
# If this a Container Enabled role, provide the minimum Ansible Container version.
|
||||||
|
# min_ansible_container_version:
|
||||||
|
|
||||||
|
#
|
||||||
|
# Provide a list of supported platforms, and for each platform a list of versions.
|
||||||
|
# If you don't wish to enumerate all versions for a particular platform, use 'all'.
|
||||||
|
# To view available platforms and versions (or releases), visit:
|
||||||
|
# https://galaxy.ansible.com/api/v1/platforms/
|
||||||
|
#
|
||||||
|
# platforms:
|
||||||
|
# - name: Fedora
|
||||||
|
# versions:
|
||||||
|
# - all
|
||||||
|
# - 25
|
||||||
|
# - name: SomePlatform
|
||||||
|
# versions:
|
||||||
|
# - all
|
||||||
|
# - 1.0
|
||||||
|
# - 7
|
||||||
|
# - 99.99
|
||||||
|
|
||||||
|
galaxy_tags: []
|
||||||
|
# List tags for your role here, one per line. A tag is a keyword that describes
|
||||||
|
# and categorizes the role. Users find roles by searching for tags. Be sure to
|
||||||
|
# remove the '[]' above, if you add tags to this list.
|
||||||
|
#
|
||||||
|
# NOTE: A tag is limited to a single word comprised of alphanumeric characters.
|
||||||
|
# Maximum 20 tags per role.
|
||||||
|
|
||||||
|
dependencies: []
|
||||||
|
# List your role dependencies here, one per line. Be sure to remove the '[]' above,
|
||||||
|
# if you add dependencies to this list.
|
||||||
34
solutions/roles/apache/tasks/main.yml
Normal file
34
solutions/roles/apache/tasks/main.yml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# tasks/main.yml
|
||||||
|
---
|
||||||
|
- name: Install httpd and firewalld
|
||||||
|
ansible.builtin.package:
|
||||||
|
name: "{{ apache_packages }}"
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Enable and start firewalld
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: firewalld
|
||||||
|
state: started
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
- name: Enable and start httpd
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: httpd
|
||||||
|
state: started
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
- name: Allow HTTP service through firewalld
|
||||||
|
ansible.posix.firewalld:
|
||||||
|
service: http
|
||||||
|
permanent: true
|
||||||
|
state: enabled
|
||||||
|
immediate: true
|
||||||
|
|
||||||
|
- name: Deploy index.html with FQDN and IPv4
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: index.html.j2
|
||||||
|
dest: /var/www/html/index.html
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0644'
|
||||||
|
notify: restart httpd
|
||||||
12
solutions/roles/apache/templates/index.html.j2
Normal file
12
solutions/roles/apache/templates/index.html.j2
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# templates/index.html.j2
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Apache Test Page</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Apache is working</h1>
|
||||||
|
<p><strong>FQDN:</strong> {{ ansible_facts.fqdn }}</p>
|
||||||
|
<p><strong>IPv4 Address:</strong> {{ ansible_facts.default_ipv4.address }}</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
2
solutions/roles/apache/tests/inventory
Normal file
2
solutions/roles/apache/tests/inventory
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
localhost
|
||||||
|
|
||||||
5
solutions/roles/apache/tests/test.yml
Normal file
5
solutions/roles/apache/tests/test.yml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
- hosts: localhost
|
||||||
|
remote_user: root
|
||||||
|
roles:
|
||||||
|
- apache
|
||||||
2
solutions/roles/apache/vars/main.yml
Normal file
2
solutions/roles/apache/vars/main.yml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
---
|
||||||
|
# vars file for apache
|
||||||
19
solutions/roles/balancer/MANIFEST.json
Normal file
19
solutions/roles/balancer/MANIFEST.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"collection_info": null,
|
||||||
|
"dependencies": [],
|
||||||
|
"format": 1,
|
||||||
|
"license": "MIT",
|
||||||
|
"license_file": null,
|
||||||
|
"name": "balancer",
|
||||||
|
"namespace": "local",
|
||||||
|
"readme": "README.md",
|
||||||
|
"repository": null,
|
||||||
|
"tags": [
|
||||||
|
"haproxy",
|
||||||
|
"loadbalancer",
|
||||||
|
"networking",
|
||||||
|
"web"
|
||||||
|
],
|
||||||
|
"version": "1.0.0"
|
||||||
|
}
|
||||||
|
|
||||||
11
solutions/roles/balancer/defaults/main.yml
Normal file
11
solutions/roles/balancer/defaults/main.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
haproxy_frontend_port: 80
|
||||||
|
|
||||||
|
haproxy_backend_servers:
|
||||||
|
- name: node3
|
||||||
|
address: node3
|
||||||
|
port: 80
|
||||||
|
- name: node4
|
||||||
|
address: node4
|
||||||
|
port: 80
|
||||||
|
|
||||||
6
solutions/roles/balancer/handlers/main.yml
Normal file
6
solutions/roles/balancer/handlers/main.yml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
- name: Restart haproxy
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: haproxy
|
||||||
|
state: restarted
|
||||||
|
|
||||||
2
solutions/roles/balancer/meta/.galaxy_install_info
Normal file
2
solutions/roles/balancer/meta/.galaxy_install_info
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
install_date: 'Tue 30 Dec 2025 12:53:11 AM '
|
||||||
|
version: ''
|
||||||
21
solutions/roles/balancer/meta/main.yml
Normal file
21
solutions/roles/balancer/meta/main.yml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
galaxy_info:
|
||||||
|
role_name: balancer
|
||||||
|
author: lab
|
||||||
|
description: Installs and configures HAProxy to load balance Apache servers
|
||||||
|
license: MIT
|
||||||
|
min_ansible_version: "2.9"
|
||||||
|
|
||||||
|
platforms:
|
||||||
|
- name: EL
|
||||||
|
versions:
|
||||||
|
- "9"
|
||||||
|
|
||||||
|
galaxy_tags:
|
||||||
|
- haproxy
|
||||||
|
- loadbalancer
|
||||||
|
- networking
|
||||||
|
- web
|
||||||
|
|
||||||
|
dependencies: []
|
||||||
|
|
||||||
28
solutions/roles/balancer/tasks/main.yml
Normal file
28
solutions/roles/balancer/tasks/main.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
- name: Install HAProxy
|
||||||
|
ansible.builtin.dnf:
|
||||||
|
name: haproxy
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Enable and start HAProxy
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: haproxy
|
||||||
|
state: started
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
- name: Deploy HAProxy configuration
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: haproxy.cfg.j2
|
||||||
|
dest: /etc/haproxy/haproxy.cfg
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0644'
|
||||||
|
notify: Restart haproxy
|
||||||
|
|
||||||
|
- name: Allow port 80 through firewalld
|
||||||
|
ansible.posix.firewalld:
|
||||||
|
service: http
|
||||||
|
permanent: true
|
||||||
|
immediate: true
|
||||||
|
state: enabled
|
||||||
|
|
||||||
25
solutions/roles/balancer/templates/haproxy.cfg.j2
Normal file
25
solutions/roles/balancer/templates/haproxy.cfg.j2
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
global
|
||||||
|
log /dev/log local0
|
||||||
|
log /dev/log local1 notice
|
||||||
|
daemon
|
||||||
|
maxconn 2048
|
||||||
|
|
||||||
|
defaults
|
||||||
|
log global
|
||||||
|
mode http
|
||||||
|
option httplog
|
||||||
|
option dontlognull
|
||||||
|
timeout connect 5s
|
||||||
|
timeout client 50s
|
||||||
|
timeout server 50s
|
||||||
|
|
||||||
|
frontend http_front
|
||||||
|
bind *:80
|
||||||
|
default_backend webservers
|
||||||
|
|
||||||
|
backend webservers
|
||||||
|
balance roundrobin
|
||||||
|
option httpchk
|
||||||
|
server node3 node3:80 check
|
||||||
|
server node4 node4:80 check
|
||||||
|
|
||||||
17
solutions/roles/phpinfo/README.md
Normal file
17
solutions/roles/phpinfo/README.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# phpinfo Role
|
||||||
|
|
||||||
|
This role installs Apache, PHP, and Firewalld, opens HTTP access, fixes SELinux
|
||||||
|
contexts, and deploys a PHP info page.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
- RHEL / Rocky / Alma 9
|
||||||
|
- SELinux enforcing
|
||||||
|
- firewalld enabled
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
```yaml
|
||||||
|
- hosts: web
|
||||||
|
become: true
|
||||||
|
roles:
|
||||||
|
- phpinfo
|
||||||
|
|
||||||
4
solutions/roles/phpinfo/defaults/main.yml
Normal file
4
solutions/roles/phpinfo/defaults/main.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
phpinfo_webroot: /var/www/html
|
||||||
|
phpinfo_file: index.php
|
||||||
|
|
||||||
6
solutions/roles/phpinfo/handlers/main.yml
Normal file
6
solutions/roles/phpinfo/handlers/main.yml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
- name: Restart httpd
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: httpd
|
||||||
|
state: restarted
|
||||||
|
|
||||||
2
solutions/roles/phpinfo/meta/.galaxy_install_info
Normal file
2
solutions/roles/phpinfo/meta/.galaxy_install_info
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
install_date: 'Tue 30 Dec 2025 12:53:11 AM '
|
||||||
|
version: ''
|
||||||
22
solutions/roles/phpinfo/meta/main.yml
Normal file
22
solutions/roles/phpinfo/meta/main.yml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
galaxy_info:
|
||||||
|
role_name: phpinfo
|
||||||
|
author: lab
|
||||||
|
description: Installs Apache, PHP, configures firewalld, fixes SELinux, and deploys a PHP info page
|
||||||
|
license: MIT
|
||||||
|
min_ansible_version: "2.9"
|
||||||
|
|
||||||
|
platforms:
|
||||||
|
- name: EL
|
||||||
|
versions:
|
||||||
|
- "9"
|
||||||
|
|
||||||
|
galaxy_tags:
|
||||||
|
- php
|
||||||
|
- httpd
|
||||||
|
- firewalld
|
||||||
|
- selinux
|
||||||
|
- web
|
||||||
|
|
||||||
|
dependencies: []
|
||||||
|
|
||||||
41
solutions/roles/phpinfo/tasks/main.yml
Normal file
41
solutions/roles/phpinfo/tasks/main.yml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
- name: Install required packages
|
||||||
|
ansible.builtin.dnf:
|
||||||
|
name:
|
||||||
|
- httpd
|
||||||
|
- firewalld
|
||||||
|
- php
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Enable and start httpd
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: httpd
|
||||||
|
state: started
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
- name: Enable and start firewalld
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: firewalld
|
||||||
|
state: started
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
- name: Allow HTTP traffic through firewalld (persistent and immediate)
|
||||||
|
ansible.posix.firewalld:
|
||||||
|
service: http
|
||||||
|
state: enabled
|
||||||
|
permanent: true
|
||||||
|
immediate: true
|
||||||
|
|
||||||
|
- name: Fix SELinux context on webroot
|
||||||
|
ansible.builtin.command: restorecon -Rv {{ phpinfo_webroot }}
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Deploy PHP info page
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: index.php.j2
|
||||||
|
dest: "{{ phpinfo_webroot }}/{{ phpinfo_file }}"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0644'
|
||||||
|
notify: Restart httpd
|
||||||
|
|
||||||
4
solutions/roles/phpinfo/templates/index.php.j2
Normal file
4
solutions/roles/phpinfo/templates/index.php.j2
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?php
|
||||||
|
phpinfo();
|
||||||
|
?>
|
||||||
|
|
||||||
2
solutions/roles/phpinfo/tests/inventory
Normal file
2
solutions/roles/phpinfo/tests/inventory
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
localhost
|
||||||
|
|
||||||
5
solutions/roles/phpinfo/tests/test.yml
Normal file
5
solutions/roles/phpinfo/tests/test.yml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
- hosts: localhost
|
||||||
|
remote_user: root
|
||||||
|
roles:
|
||||||
|
- phpinfo
|
||||||
2
solutions/roles/phpinfo/vars/main.yml
Normal file
2
solutions/roles/phpinfo/vars/main.yml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
---
|
||||||
|
# vars file for phpinfo
|
||||||
17
solutions/selinux.yml
Normal file
17
solutions/selinux.yml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
- name: Ensure SELinux is enabled and enforcing
|
||||||
|
hosts: all
|
||||||
|
become: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Set SELinux to enforcing
|
||||||
|
ansible.posix.selinux:
|
||||||
|
policy: targeted
|
||||||
|
state: enforcing
|
||||||
|
notify: Reboot if SELinux state changed
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
- name: Reboot if SELinux state changed
|
||||||
|
ansible.builtin.reboot:
|
||||||
|
msg: "Rebooting to apply SELinux changes"
|
||||||
|
reboot_timeout: 600
|
||||||
7
test.yml
Normal file
7
test.yml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
- name: A simple playbook to test that Ansible is configured
|
||||||
|
hosts: localhost
|
||||||
|
tasks:
|
||||||
|
- name: Run test playbook
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "If you're reading this, Ansible is configured on your system."
|
||||||
12
user_list.yml
Normal file
12
user_list.yml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
users:
|
||||||
|
- name: Fred
|
||||||
|
role: manager
|
||||||
|
|
||||||
|
- name: Wilma
|
||||||
|
role: manager
|
||||||
|
|
||||||
|
- name: Barney
|
||||||
|
role: developer
|
||||||
|
|
||||||
|
- name: Betty
|
||||||
|
role: developer
|
||||||
1
vault-password
Normal file
1
vault-password
Normal file
@@ -0,0 +1 @@
|
|||||||
|
redhat
|
||||||
51
vault.yml
Normal file
51
vault.yml
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
$ANSIBLE_VAULT;1.1;AES256
|
||||||
|
62613361613532643339306531396533643738343365376535346463663731306536373139306163
|
||||||
|
6138386139623031656265326165386634323435353261610a303939356634386436366132306663
|
||||||
|
65616566386162616435626464373063393463666435623832303533333662303966386636613737
|
||||||
|
3365656432323739620a313463343436326463323632333337373437386237353862353564343438
|
||||||
|
63346634393830386233343536396563306138626264306330623765393530373763323764363534
|
||||||
|
38323666633631646666663966303365646266373830636664373366613330346662363134623235
|
||||||
|
65356537306462643735363033306537613462313236623062623633356132343161373032613264
|
||||||
|
34323865373564336532663361336239363939333239346539326434316435366362373734303337
|
||||||
|
32343835373063376530646161333365626138366530313430623265306466353430366537353937
|
||||||
|
39313032616265616633383061363432366236353434663639343463366435633839363733366134
|
||||||
|
31356231653162653362303535643666633839633031633763346336376465383030303961393662
|
||||||
|
38353261313935626565303961663065323030303265626562393830323430353331663361333232
|
||||||
|
61373664313930363033303334653238666237373562343664366463646338316434346131663230
|
||||||
|
32303364646432313039383833656436633637633631376335333962633966326332353061393761
|
||||||
|
65396436636266336662303234663735333838303961373365656132363162353332613133386633
|
||||||
|
33303633323030383236383630616335663430336363613234643938623962316433646637613032
|
||||||
|
63323935613766623031303536383663623065353261663132303339626130393635393934363539
|
||||||
|
63653733353635663664323334346138336231396333366233323766383931313236373365373432
|
||||||
|
37393934666661373263373538366663636430623131363664333063373338633639623264323334
|
||||||
|
38623330663531383639323464623933306431373764386461326136323964623465663630663335
|
||||||
|
38623361633239356637616637393438393139636431373266383330343039666663666366393036
|
||||||
|
34373239313638623861393663366535613133323036366634336131316537333734636538396138
|
||||||
|
63393963346536623831373765626232356130323361383936636661323966653764376439653032
|
||||||
|
64326439643036653534383236623735353336316666623037366338336466323662353065613835
|
||||||
|
32663566323538346463323033306430643834333330393966653437356564653065613637323836
|
||||||
|
61666262306265313362383130346636333136396635636234653830333038616566313736633838
|
||||||
|
65353062613538613761626164346534656161356435313562353130626662366530363037626461
|
||||||
|
61656461326239633739393564343665346364303437323532343533346537316333333561636331
|
||||||
|
34613866646562373833313161636431393532313465366562383037396435333366613264343662
|
||||||
|
35356431313232646162663665316563653461623266613631646435383033343632386166636233
|
||||||
|
35323934383466323734633230653164373231383861346336316566663231376133653763346130
|
||||||
|
61373135373738653831363963383831646663383532363038333636303934666333623061373337
|
||||||
|
31363137366136313937376437663963373963646331393564393661363565346234646230383239
|
||||||
|
65323564613334623238346638636132346437306637666230646438623236373035313263306163
|
||||||
|
61616335653164313466386435376437386561333531343632366463313931323366353261613738
|
||||||
|
62646236333932356433633864313138343764333065396537353438623336616235643536333938
|
||||||
|
66326137313033333334626437613132323336613335636439333964626631306337383862363730
|
||||||
|
64396466303064343863336639323335313165303339386639306431633135636665666433623433
|
||||||
|
36623239623466343163316563386435313136333662643564656566303036386430656637646633
|
||||||
|
33366139323630653936336463333031613433373139663631306638656463626431383535626237
|
||||||
|
31386264396461373865353033333237643365653933663532613465613564326333613335383130
|
||||||
|
32643965393736363236366432353733373764643731373536336633343139366365666366373437
|
||||||
|
63313664316562623566306663306132376461376433326361626135653933366232303430333933
|
||||||
|
63373537633764636463326538663939396431353732376239373166316236363431393230353631
|
||||||
|
65613739366265353637633031646532643934353839393334383332353865343330363537323462
|
||||||
|
64393662646335366133646239376166633833393861343561353165616132363330626537336461
|
||||||
|
33353761663134643934393866393235613532316139356335633233326537333163633931356162
|
||||||
|
65653264333164303438646130636435373261396333366531393432366231633661303534643961
|
||||||
|
39353939323937643934373332316461353361323863616164373038633261343034636632313362
|
||||||
|
3931653566633839386332373363663365333765306639353961
|
||||||
Reference in New Issue
Block a user