Home Lab - Using Ansible to configure the router

Share on:

The only components I deployed by hand, was the ESXi and the vCenter Server that will manage the host. Both receive their network over DHCP. The VMs, will be in their own isolated network and will be routed using a Photon OS VM as a router.

This Article will describe how I am using ansible to automate the creation of the router.

Getting started

We first need Ansible and PyVMomi so we can manage the vSphere Environment

1pip3 install ansible
2pip3 install pyvmomi

Prepare the Host

As I don't want to touch the host, or the vCenter manually I will use ansible to create the internal vSwitch and Port Group:

To centralize the environment description I am using a file called secrets.yml to keep my environment variables.

 1---
 2vcenter_hostname: "192.168.2.3"
 3vcenter_username: "administrator@vsphere.local"
 4vcenter_password: "VMware123!"
 5vcenter_datacenter: "Datacenter"
 6datacenter_name: "{{ vcenter_datacenter }}"
 7vcenter_cluster: "nuc"
 8esxi_hostname: "192.168.2.2"
 9esxi_username: "root"
10esxi_password: "VMware123!"
11deploy_datastore: datastore1
12vm_datastore: datastore2
13vm_vswitch: "vSwitch1"
14ext_network: "VM Network"
15vm_network: "Lab Network"
16template_name: "photon4"
17vm_folder: "/Datacenter/vm/Infrastructure"

As a first step I will change the transparent page sharing options on the host.

 1- name: Manage multiple settings for an ESXi host
 2  community.vmware.vmware_host_config_manager:
 3    hostname: '{{ vcenter_hostname }}'
 4    username: '{{ vcenter_username }}'
 5    password: '{{ vcenter_password }}'
 6    cluster_name: nuc
 7    validate_certs: false
 8    options:
 9        'Annotations.WelcomeMessage': 'Managed by Ansible'
10        'Mem.AllocGuestLargePage': 0
11        'Mem.ShareForceSalting': 0
12  delegate_to: localhost

After that we can prepare the networks:

  • Create the vSwitch:
1- name: Add vSwitch1
2community.vmware.vmware_vswitch:
3  hostname: '{{ esxi_hostname }}'
4  username: '{{ esxi_username }}'
5  password: '{{ esxi_password }}'
6  validate_certs: false
7  switch: '{{ vm_vswitch }}'
8delegate_to: localhost
  • Create the internal Port Group
 1- name: Add Lab Network to all hosts in a cluster
 2vmware_portgroup:
 3  hostname: '{{ vcenter_hostname }}'
 4  username: '{{ vcenter_username }}'
 5  password: '{{ vcenter_password }}'
 6  validate_certs: false
 7  cluster_name: '{{ vcenter_cluster }}'
 8  switch: '{{ vm_vswitch }}'
 9  portgroup_name: "{{ vm_network }}"
10  vlan_id: 92

Create the Photon OS Template

First we will import the ova to the vCenter Server:

 1- name: "Import Photon as photon4"
 2  community.vmware.vmware_deploy_ovf:
 3    hostname: '{{ vcenter_hostname }}'
 4    username: '{{ vcenter_username }}'
 5    password: '{{ vcenter_password }}'
 6    datacenter: '{{ vcenter_datacenter }}'
 7    cluster: '{{ vcenter_cluster }}'
 8    datastore: '{{ deploy_datastore }}'
 9    name: photon4
10    validate_certs: no
11    power_on: no
12    ovf: /Volumes/Data/ISOs/photon-uefi-hw13-4.0-d98e681.ova
13  delegate_to: localhost

After the import we will convert the VM to a vSphere Template

 1- name: "Convert photon4 to vSphere template"
 2  community.vmware.vmware_guest:
 3    hostname: "{{ vcenter_hostname }}"
 4    username: "{{ vcenter_username }}"
 5    password: "{{ vcenter_password }}"
 6    datastore: '{{ deploy_datastore }}'
 7    datacenter: '{{ vcenter_datacenter }}'
 8    validate_certs: no
 9    is_template: yes
10    name: photon4

Now we have a Photon OS template we can easily use to create all Linux VMs we need.

Creating the router vm

The following task will create a VM from the Template, add the network interfaces, and power it on.

 1- name: "Deploy router VM based on photon4 template"
 2  community.vmware.vmware_guest:
 3    hostname: "{{ vcenter_hostname }}"
 4    username: "{{ vcenter_username }}"
 5    password: "{{ vcenter_password }}"
 6    datacenter: '{{ vcenter_datacenter }}'
 7    validate_certs: no
 8    name: router
 9    state: poweredon
10    template: "{{ template_name }}"
11    datastore: "{{ vm_datastore }}"
12    folder: "{{ vm_folder }}"
13    hardware:
14      memory_mb: 512
15      num_cpus: 2
16    networks:
17    - name: "{{ ext_network }}"
18      device_type: vmxnet3
19      networks:
20    - name: "{{ vm_network }}"
21      device_type: vmxnet3
22      ip: 10.7.92.254
23      netmask: 255.255.255.0
24    wait_for_ip_address: yes
25  delegate_to: localhost

Change the root password.

I don't want to login to the vm and change the VM so I build some really hacky work around using the vmware_guest_sendkey task.

  1- name: 'typing root'
  2  community.vmware.vmware_guest_sendkey:
  3    validate_certs: no
  4    hostname: "{{ vcenter_hostname }}"
  5    username: "{{ vcenter_username }}"
  6    password: "{{ vcenter_password }}"
  7    datacenter: "{{ datacenter_name }}"
  8    name: "router"
  9    string_send: "root"
 10  delegate_to: localhost
 11  register: keys_num_sent
 12
 13- name: 'hiting ENTER'
 14  community.vmware.vmware_guest_sendkey:
 15    validate_certs: no
 16    hostname: "{{ vcenter_hostname }}"
 17    username: "{{ vcenter_username }}"
 18    password: "{{ vcenter_password }}"
 19    datacenter: "{{ datacenter_name }}"
 20    name: "router"
 21    keys_send:
 22      - ENTER
 23  delegate_to: localhost
 24  register: keys_num_sent
 25
 26- name: 'typing changeme'
 27  community.vmware.vmware_guest_sendkey:
 28    validate_certs: no
 29    hostname: "{{ vcenter_hostname }}"
 30    username: "{{ vcenter_username }}"
 31    password: "{{ vcenter_password }}"
 32    datacenter: "{{ datacenter_name }}"
 33    name: "router"
 34    string_send: "changeme"
 35  delegate_to: localhost
 36  register: keys_num_sent
 37
 38- name: 'hiting ENTER'
 39  community.vmware.vmware_guest_sendkey:
 40    validate_certs: no
 41    hostname: "{{ vcenter_hostname }}"
 42    username: "{{ vcenter_username }}"
 43    password: "{{ vcenter_password }}"
 44    datacenter: "{{ datacenter_name }}"
 45    folder: "{{ vm_folder }}"
 46    name: "router"
 47    keys_send:
 48      - ENTER
 49  delegate_to: localhost
 50  register: keys_num_sent
 51
 52- name: 'typing changeme'
 53  community.vmware.vmware_guest_sendkey:
 54    validate_certs: no
 55    hostname: "{{ vcenter_hostname }}"
 56    username: "{{ vcenter_username }}"
 57    password: "{{ vcenter_password }}"
 58    datacenter: "{{ datacenter_name }}"
 59    name: "router"
 60    string_send: "changeme"
 61  delegate_to: localhost
 62  register: keys_num_sent
 63
 64- name: 'ROUTER hiting ENTER'
 65  community.vmware.vmware_guest_sendkey:
 66    validate_certs: no
 67    hostname: "{{ vcenter_hostname }}"
 68    username: "{{ vcenter_username }}"
 69    password: "{{ vcenter_password }}"
 70    datacenter: "{{ datacenter_name }}"
 71    name: "router"
 72    keys_send:
 73      - ENTER
 74  delegate_to: localhost
 75  register: keys_num_sent
 76
 77- name: 'typing password'
 78  community.vmware.vmware_guest_sendkey:
 79    validate_certs: no
 80    hostname: "{{ vcenter_hostname }}"
 81    username: "{{ vcenter_username }}"
 82    password: "{{ vcenter_password }}"
 83    datacenter: "{{ datacenter_name }}"
 84    name: "router"
 85    string_send: "{{ vcenter_password }}"
 86  delegate_to: localhost
 87  register: keys_num_sent
 88
 89- name: 'hiting ENTER'
 90  community.vmware.vmware_guest_sendkey:
 91    validate_certs: no
 92    hostname: "{{ vcenter_hostname }}"
 93    username: "{{ vcenter_username }}"
 94    password: "{{ vcenter_password }}"
 95    datacenter: "{{ datacenter_name }}"
 96    name: "router"
 97    keys_send:
 98      - ENTER
 99  delegate_to: localhost
100  register: keys_num_sent
101
102- name: 'typing password'
103  community.vmware.vmware_guest_sendkey:
104    validate_certs: no
105    hostname: "{{ vcenter_hostname }}"
106    username: "{{ vcenter_username }}"
107    password: "{{ vcenter_password }}"
108    datacenter: "{{ datacenter_name }}"
109    name: "router"
110    string_send: "{{ vcenter_password }}"
111  delegate_to: localhost
112  register: keys_num_sent
113
114- name: 'hiting ENTER'
115  community.vmware.vmware_guest_sendkey:
116    validate_certs: no
117    hostname: "{{ vcenter_hostname }}"
118    username: "{{ vcenter_username }}"
119    password: "{{ vcenter_password }}"
120    datacenter: "{{ datacenter_name }}"
121    name: "router"
122    keys_send:
123      - ENTER
124  delegate_to: localhost
125  register: keys_num_sent

Configure the Router

Generate a inventory from the vCenter, using the file router.vmware.yml

1plugin: vmware_vm_inventory
2strict: False
3hostname: 192.168.2.3
4username: administrator@vsphere.local
5password: VMware123!
6validate_certs: False
7filters:
8  - guest.ipAddress is defined and (name is match "router*")

Using this Inventory we will run the following play:

1---
2- hosts: all
3  vars_files:
4    - secrets.yml
5  roles:
6    - general-settings
7    - configure-router

The general settings role does not really matter right now, but lets check the configure-router role.

1configure-router
2├── files
3│   └── 99-ip-forward.conf
4└── tasks
5    └── main.yml

First let's check main.yml

 1---
 2- name: copy ipforward config
 3  copy: src=99-ip-forward.conf dest=/etc/sysctl.d/99-ip-forward.conf
 4- name: Create Iptables NAT chain
 5  iptables:
 6    table: nat
 7    chain: POSTROUTING
 8    out_interface: eth0
 9    jump: MASQUERADE
10- name: Save Iptables
11  shell:
12    cmd: iptables-save >/etc/systemd/scripts/ip4save

The file 99-ip-forward.conf is looking like this:

1# Enabe IPv$ forwarding
2net.ipv4.ip_forward = 1