Warning message

Log in to add comments.

Provisioning VMWare using userdata via Satellite 6.3

Lukas Zapletal published on 2018-10-09T08:00:00+00:00, last updated 2018-10-09T08:23:03+00:00

by William McDonald

This document presents a basic walkthrough of the steps required to configure Red Hat Satellite 6.3 to provision virtual machines against a VMware vSphere 6.7 Vcenter.
In addition to machine provisioning, it illustrates using the upstream Foreman Userdata plug-in to further customise provisioned hosts using cloud-init. This plugin is currently being merged into Foreman core, it will likely appear in future Satellite 6 releases.


  • 8 CPU cores
  • 32GB RAM
  • 200GB of disk, thin provisioned (> 670 GB if thick provisioned)
  • Vmware Workstation 14 or an ESX host capable of running VCSA

Setup Sequence of Events

There are a few moving parts. At a high-level we need to:

  • Deploy a Satellite
  • Deploy VCSA
  • Deploy ESXi
  • Satellite initial configuration
    • Add manifest
    • Configure and sync repositories
    • Create a Lifecycle Environment
    • Create a Content View and add a Repository to it
    • Publish and promote the Content View
    • Create Activation Keys and add Subscription
    • Create a Subnet
    • Create a Compute Resource
    • Create a Compute Profile
    • Create a Hostgroup
    • Configure virt-who (optional)
    • Install the Foreman Userdata Plug-in and restart Satellite
    • Prepare provisioning templates (userdata and cloud-init)
    • Configure the Operating System to use the userdata and cloud-init templates
  • Prepare a VM template
    • Create an empty VM
    • Upload an ISO
    • Install RHEL7
    • Tweak networking (if required)
    • Connect to Satellite temporarily
    • Configure a public key (optional)
    • Install open-vm-tools
    • Install Perl
    • Yum update
    • Create copy (optional but recommended)
    • Install cloud-init
    • Configure cloud-init
    • Create and run clean-up script
    • Bake template
  • Create Image in Satellite
  • Test provisioning

Provisioning Sequence of Events

  • User provisions VM(s) via the UI or hammer
  • Satellite calls Vcenter to clone VM template
    • Satellite userdata provisioning template injects customisation specification identity information
    • Satellite cloud-init provisioning template instructs the VM to callback to Satellite when cloud-init runs post-provision
  • Vcenter clones template to VM
  • Vcenter applies customisation specification (VM identity including hostname, IP and DNS)
  • VM builds, cloud-init is invoked and calls-back to Satellite on port 80 which then redirects to 443

Note: Even if registering the VM to a Capsule, the VM’s cloud-init phone-home always calls the Satellite, not its corresponding capsule. Make sure you take this into consideration in terms of firewall rules.

Network Configuration

The VMs were configured with the following FQDNs, IPs, operating systems and services. Forward and reverse DNS were configured in DNS for all hosts.

Hostname IP OS Notes
dns.example.com RHEL7 External DNS service
satellite.example.com RHEL7 Yum Content, Provisioning, Subscription Management
vcenter.example.com Vmware Photon vCenter
esxi1.example.com ESXi ESX Hypervisor

Management Endpoints

As this is just a demonstration lab, all SSL certificates are self-signed.

URL Purpose
https://satellite.example.com Satellite management UI
https://vcenter.example.com:4580/ VCSA management UI
https://vcenter.example.com/ Vcenter management UI
https://esxi1.example.com/ Self-signed cert must be trusted in order to upload ISOs.

VMware Installation

Installing vCenter and an ESX host or two is not covered in-depth but isn’t terribly onerous.

Vmware Workstation 14 (or a suitably sized ESX host capable of running the VCSA) is recommended in order to correctly install the Vmware 6.7 VCSA. In theory it should be able to be run nested on other platforms but the installer and the OVA have extensive customisation which would need to be worked through.

Satellite Initial Preparation

This walkthrough assumes you have a basic Satellite deployed with an Organization and Location configured, a manifest installed but no other objects created (no products or repositories, content views, activation keys etc.). See Satellite Installation at the end of the document for a more in-depth rundown on a basic Satellite deployment.

The demonstration used Satellite 6.3.3 but this should work for earlier releases too.

Configure upstream Red Hat Repositories, in the Satellite UI under Content and Red Hat Repositories, enable the following: RPMS / Red Hat Enterprise Linux Server / Red Hat Enterprise Linux 7 Server (RPMs) / Red Hat Enterprise Linux 7 Server RPMs x86_64 7Server

Sync the upstream content in the UI, under Content and Sync Status, Expand All, Select All, and Synchronize Now.

Create a lifecycle environment

hammer lifecycle-environment create --description le-eng-rhel7-std-server --prior Library --name le-eng-rhel7-std-server

Create a content view

hammer content-view create --description cv-rhel7-std-server --name cv-rhel7-std-server

List repositories

hammer repository list --order id | awk -F '|' '{ print $1, $2 }'

Add repositories to content view

hammer content-view update --repository-ids 1,2 --name "cv-rhel7-std-server"

Publish Content into Library

hammer content-view publish --name "cv-rhel7-std-server" --async

Promote from the Library into the Lifecycle Environment

hammer content-view version promote --content-view "cv-rhel7-std-server" --to-lifecycle-environment "le-eng-rhel7-std-server" --async

Create Activation Keys

hammer activation-key create --content-view "cv-rhel7-std-server" --lifecycle-environment "le-eng-rhel7-std-server" --name "ak-eng-rhel7-std-server"

Add subscription(s) to activation key

hammer subscription list | awk -F'|' '{ print $1, $3, $9, $10 }'
--- ------------------------------------ ---------- ---------
ID   NAME                                 QUANTITY   CONSUMED
--- ------------------------------------ ---------- ---------
1    Red Hat Satellite (Self-Supported)   1           0
2    Employee SKU                         1           0
--- ------------------------------------ ---------- ---------
hammer activation-key add-subscription --name "ak-eng-rhel7-std-server" --subscription-id 2

Configure the domain

A domain will already have been created during Satellite installation. Add this domain to the default location and organization.

Create a subnet

[root@satellite ~]# hammer subnet create --name "sn-default-servers" --network "" --mask "" --gateway "" --dns-primary "" --domains example.com --locations loc-example --organizations org-example

Compute Resource
Looks like both username@domain and domain\username both work from a compute resource creation perspective.

[root@satellite ~]# hammer compute-resource create --caching-enabled 1 --datacenter "dc-example" --name "cr-vcenter" --password "password"  --provider "Vmware" --server "vcenter.example.com" --user 'vsphere.local\administrator' --locations "loc-example" --organizations "org-example"

[root@satellite ~]# hammer compute-resource create --caching-enabled 1 --datacenter "dc-example" --name "cr-vcenter" --password "password"  --provider "Vmware" --server "vcenter.example.com" --user 'administrator@vsphere.local' --locations "loc-cwl-uk" --organizations "org-example"

Compute profile
This can’t currently be done via hammer. Infrastructure > Compute profile > Create Compute Profile

Name: vmware-small
Select Compute Resource (cr-vcenter)
Cluster: esxi1.example.com
Resource pool: auto populated ‘Resources’
Folder: vm
Guest OS: Red Hat Enterprise Linux 7 (64-bit)
Image: img-rhel7-std-server
Network: VM Network
Data store: datastore1
Thin provision: uncheck

Create a Hostgroup

[root@satellite ~]# hammer hostgroup info --id 1
Id:                   1
Name:                 hg-rhel7-std-server
Title:                hg-rhel7-std-server
Operating System:     RedHat 7.5
Subnet:               sn-default-servers
Domain:               example.com
Architecture:         x86_64
Puppet CA Proxy Id:
Puppet Master Proxy Id:
ComputeProfile:       vmware-small

  kt_activation_keys => ak-eng-rhel7-std-server
Parent Id:
OpenSCAP Proxy:
Content View:
  ID:   2
  Name: cv-rhel7-std-server
Lifecycle Environment:
  ID:   2
  Name: le-eng-rhel7-std-server
Content Source:
  ID:   1
  Name: satellite.example.com
Kickstart Repository:

Virt-who configuration
Given the target compute in this walkthrough is Vmware, it’s likely you will need to configure virt-who for VDC subscription.

[root@satellite ~]# yum install -y virt-who
[root@satellite ~]# hammer virt-who-config create --name vcenter.example.com --organization org-example --interval 60 --filtering-mode none --hypervisor-id hostname --hypervisor-type esx --hypervisor-server vcenter.example.com --hypervisor-username 'administrator@vsphere.local' --hypervisor-password 'password' --satellite-url satellite.example.com
hammer virt-who-config deploy --id 1
systemctl stop virt-who.service
virt-who -d -o

Foreman Plugin Configuration
Enable the Foreman plugin Yum repository

[root@satellite ~]# rpm -q foreman
[root@satellite ~]# cat > /etc/yum.repos.d/foreman-plugins.repo <<EOF
name=Foreman plugins

Install the Foreman Userdata plugin

[root@satellite ~]# yum -y install tfm-rubygem-foreman_userdata

Restart Satellite

[root@satellite ~]# katello-service restart

Create provisioning template files

cat > ~/vmware-cloud-init-template.erb <<EOF
hostname: <%= @host.name %>
fqdn: <%= @host %>
manage_etc_hosts: true
users: {}
- touch ~/cloud-init

  url: <%= foreman_url('built') %>
  post: []
tries: 10

cat > ~/vmware-userdata-template.erb <<EOF
# Template for VMWare customization via open-vm-tools

  domain: <%= @host.domain %>
  hostName: <%= @host.shortname %>
  hwClockUTC: true
  timeZone: <%= @host.params['time-zone'] || 'UTC' %>

  dnsSuffixList: [<%= @host.domain %>]
  <%- @host.interfaces.each do |interface| -%>
  <%- next unless interface.subnet -%>
  dnsServerList: [<%= interface.subnet.dns_primary %>, <%= interface.subnet.dns_secondary %>]
  <%- end -%>

<%- @host.interfaces.each do |interface| -%>
<%- next unless interface.subnet -%>
  - adapter:
    dnsDomain: <%= interface.domain %>
    dnsServerList: [<%= interface.subnet.dns_primary %>, <%= interface.subnet.dns_secondary %>]
    gateway: [<%= interface.subnet.gateway %>]
    ip: <%= interface.ip %>
    subnetMask: <%= interface.subnet.mask %>
<%- end -%>

Install provisioning templates

[root@satellite ~]# hammer template create --name vmware-cloud-init --file ~/vmware-cloud-init-template.erb --locations loc-example --organizations org-example --operatingsystem-ids 1 --type cloud-init
[root@satellite ~]# hammer template create --name vmware-userdata --file ~/vmware-userdata-template.erb --locations loc-example --organizations org-example --operatingsystem-ids 1 --type user_data

Configure the Operating System
Switch the Red Hat 7.5 Operating System to use these templates: Hosts > Operating systems > Red Hat 7.5 > Templates

User data template: vmware-userdata
Cloud-init: vmware-cloud-init
Template Preparation

Create an empty RHEL7 VM container

And upload rhel-server-7.5-x86_64-dvd.iso to a datastore ‘isos’ folder

Note: Log in to the ESXi host directly in a brower to accept its self-signed certificate or ISO upload won’t work

Install RHEL7 minimal from the ISO

Tweak interface connection name and DNS

[root@localhost ~]# nmcli con modify 'System ens192' connection.id ens192
[root@localhost ~]# nmcli con mod ens192 ipv4.method auto
[root@localhost ~]# nmcli con edit ens192
nmcli connection edit ens192
nmcli> remove ipv4.dns
nmcli> set ipv4.ignore-auto-dns yes
nmcli> set ipv4.dns
nmcli> save
nmcli> quit
nmcli device reapply ens192
[root@localhost ~]# hostnamectl set-hostname "localhost.localdomain"

Subscribe to Satellite

[root@localhost ~]# rpm -ivh http://satellite.example.com/pub/katello-ca-consumer-latest.noarch.rpm
[root@localhost ~]# subscription-manager register --org=org-example --activationkey=ak-eng-rhel7-std-server

Setup a public key

mkdir ~/.ssh
chmod 700 ~/.ssh
cat > ~/.ssh/authorized_keys <<EOF
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKmNGClhHO7aprRBeMVOTqXkQJqE1sCSyjrI4pnYT2cXOLwH1qOmsXu3TamvXBIuHf9V4DnXR6wzderoHJpjUceRrZmMwY9uIj0mmZdT1bqwzjqdniLk4ZRhI61WyBSR7Pjf2ieyLuxwWmfAFrdDeq6CY3G9G/eFUW3cW6XJRSCudsBKOr2YLI34qVrHAXtYWFARoNtPVSnith7dm8ohhNv7pohGEEugH8GhU+o7yF1QKzAjTnapc2VWe7Q7WWoMDr/9pJxZ9nK3mXPtFVQU5SOLs5CSRuy194K60N8eFxy0+J9Ei7YddnyFBe1yWga/bj2SW4c6oU0z0bNV+yfbp9 wmcdonald@gmail.com-2016
chmod 600 ~/.ssh/authorized_keys

Install Open VM Tools

[root@localhost ~]# yum -y install open-vm-tools.x86_64

Install Perl (required for open-vm-tools customisation specification)

[root@localhost ~]# yum -y install perl

Yum update the VM

[root@localhost ~]# yum -y update

Note: At this stage, it can be wise to power off and create a copy of the template without cloud-init. cloud-init can be quite invasive, if the template preparation requires multiple iterations this is a good place to restart from.

Power back on and install cloud-init

Install cloud-init

[root@localhost ~]# yum -y install cloud-init

Configure cloud-init to skip network configuration

Note: Satellite will do this via the Vmware customisation specification)

[root@localhost ~]# cat << EOF > /etc/cloud/cloud.cfg.d/01_network.cfg
  config: disabled

Configure cloud-init to call back to Satellite post-provision

[root@localhost ~]# cat << EOF > /etc/cloud/cloud.cfg.d/10_foreman.cfg
datasource_list: [NoCloud]
    seedfrom: http://satellite.example.com/userdata/

Update the cloud-init default cloud-cfg

[root@localhost ~]# cp /etc/cloud/cloud.cfg ~/cloud.cfg.`date -I`
[root@localhost ~]# cat << EOF > /etc/cloud/cloud.cfg
 - bootcmd

 - runcmd

 - scripts-per-once
 - scripts-per-boot
 - scripts-per-instance
 - scripts-user
 - phone-home

  distro: rhel
  cloud_dir: /var/lib/cloud
  templates_dir: /etc/cloud/templates
  ssh_svcname: sshd

# vim:syntax=yaml

Unregister from Satellite

[root@localhost ~]# subscription-manager unregister
Unregistering from: satellite.example.com:443/rhsm
System has been unregistered.
[root@localhost ~]# subscription-manager clean
All local data removed

Create a basic ‘sysprep’ script

[root@localhost ~]# cat > ~/clean.sh <<EOF

# stop logging services
/usr/bin/systemctl stop rsyslog
/usr/bin/systemctl stop auditd

# remove old kernels
# /bin/package-cleanup -oldkernels -count=1

#clean yum cache
/usr/bin/yum clean all

#force logrotate to shrink logspace and remove old logs as well as truncate logs
/usr/sbin/logrotate -f /etc/logrotate.conf
/bin/rm -f /var/log/*-???????? /var/log/*.gz
/bin/rm -f /var/log/dmesg.old
/bin/rm -rf /var/log/anaconda
/bin/cat /dev/null > /var/log/audit/audit.log
/bin/cat /dev/null > /var/log/wtmp
/bin/cat /dev/null > /var/log/lastlog
/bin/cat /dev/null > /var/log/grubby

#remove udev hardware rules
/bin/rm -f /etc/udev/rules.d/70*

#remove uuid from ifcfg scripts
/bin/cat > /etc/sysconfig/network-scripts/ifcfg-ens192 <<EOF

#remove SSH host keys
/bin/rm -f /etc/ssh/*key*

#remove root users shell history
/bin/rm -f ~root/.bash_history

#remove root users SSH history
/bin/rm -rf ~root/.ssh/known_hosts

Clean the system

[root@localhost ~]# sh ~/clean.sh

Power off the VM

[root@localhost ~]# systemctl poweroff

Convert the VM to a template in vCenter ‘template-rhel7-cloudinit’

Create the Satellite Image

[root@satellite ~]# hammer os list; hammer architecture list; hammer compute-resource list
1  | RedHat 7.5 |              | Redhat
1  | x86_64
2  | i386
1  | cr-vcenter | VMware
[root@satellite ~]# hammer compute-resource image create --operatingsystem-id 1 --architecture-id 1 --compute-resource-id 1 --user-data true --uuid template-rhel7-cloudinit --username root --name img-rhel7-std-server

Host Provisioning

[root@satellite ~]# hammer host create --name test-host --organization org-example --location loc-example --hostgroup hg-rhel7-std-server --compute-resource cr-vcenter --provision-method image --image img-rhel7-std-server --enabled true --managed true --compute-profile vmware-small --operatingsystem-id 1 --compute-attributes="start=1" --interface "managed=true,compute_type=VirtualVmxnet3,type=interface,domain_id=1,identifier=ens192,ip=,subnet_id=1,primary=true,compute_network='VM Network'"

Next Steps

In the customer implementation, we have some simple logic in the vmware-cloud-init provisioning template that will install the katello-consumer-ca from the appropriate content host, then run subscription-manager based on the host’s @host.params['kt_activation_keys'].

It’s effectively a case statement that points to the appropriate Satellite or Capsule as required by the VMs network segments. There’s probably a more elegant way to achieve this, though.

Reference Documents

Useful Links

  • https://translate.google.co.uk/translate?hl=en&sl=fr&u=https://www.mchelgham.com/installer-vcsa-6-7-dans-vmware-workstation-fusion/&prev=search
  • https://www.virten.net/2017/02/homelab-downsizing-vcenter-server-appliance-6-5/
  • https://www.starwindsoftware.com/blog/vmware-vcenter-server-appliance-vcsa-and-after-install-tricks
  • http://everything-virtual.com/2016/05/06/creating-a-centos-7-2-vmware-gold-template/
  • https://access.redhat.com/documentation/en-us/red_hat_satellite/6.2/html-single/hammer_cli_guide/index#sect-CLI_Guide-Authentication
  • https://access.redhat.com/documentation/en-us/red_hat_satellite/6.3/html/installation_guide/installing_satellite_server#performing_initial_configuration_sat_server_parent
  • https://access.redhat.com/documentation/en-us/red_hat_satellite/6.3/
  • https://access.redhat.com/documentation/en-us/red_hat_satellite/6.3/html/virtual_instances_guide/

Default cloud-init

 - default

disable_root: 1
ssh_pwauth:   0

mount_default_fields: [~, ~, 'auto', 'defaults,nofail', '0', '2']
resize_rootfs_tmp: /dev
ssh_deletekeys:   0
ssh_genkeytypes:  ~
syslog_fix_perms: ~

 - migrator
 - bootcmd
 - write-files
 - growpart
 - resizefs
 - set_hostname
 - update_hostname
 - update_etc_hosts
 - rsyslog
 - users-groups
 - ssh

 - mounts
 - locale
 - set-passwords
 - rh_subscription
 - yum-add-repo
 - package-update-upgrade-install
 - timezone
 - puppet
 - chef
 - salt-minion
 - mcollective
 - disable-ec2-metadata
 - runcmd

 - rightscale_userdata
 - scripts-per-once
 - scripts-per-boot
 - scripts-per-instance
 - scripts-user
 - ssh-authkey-fingerprints
 - keys-to-console
 - phone-home
 - final-message
 - power-state-change

  name: cloud-user
  lock_passwd: true
  gecos: Cloud User
  groups: [wheel, adm, systemd-journal]
  sudo: ["ALL=(ALL) NOPASSWD:ALL"]
  shell: /bin/bash
  distro: rhel
  cloud_dir: /var/lib/cloud
  templates_dir: /etc/cloud/templates
  ssh_svcname: sshd

# vim:syntax=yaml

About The Author

Lukas Zapletal's picture Red Hat Expert 810 points

Lukas Zapletal

Satellite 6 engineering.

Welcome! Check out the Getting Started with Red Hat page for quick tours and guides for common tasks.