When we provision a virtual machine using the native provider manager—VMware vSphere or the Red Hat Enterprise Virtualization Manager, for example—we must provide the name of the new virtual machine to be created. One of the benefits of a cloud management platform like CloudForms is that we can partially or fully automate the creation of virtual machine names as part of the provisioning workflow.
CloudForms has a very flexible way of letting us assign names to virtual machines at provisioning time, in a process known as naming. It allows us to explicitly name the VM (fine for single-VM provisioning operations) or to auto-append a zero-padded number for multi-VM provisioning requests. It also allows us to use or create a custom naming policy whereby CloudForms autogenerates VM names based on a number of factors, including a common prefix, tags, or group membership, for example.
The naming process has several inputs and usually two outputs. The inputs to the naming process are a number of variables and symbols that are set (and we can customize) during the provisioning dialog, or defined in the Naming class schema. The outputs from the naming process are the VM name and optionally the hostname (i.e., fully qualified domain name [FQDN] first part) to be applied to the VM’s operating system.
The following subsections detail the variables and symbols used as inputs to the VM naming logic.
vm_name
is given the value from the VM Name box in Provision Virtual Machines → Catalog (see Figure 23-1).
The symbol is added to the request options hash as:
miq_provision_request
.
options
[
:vm_name
]
vm_prefix
can be used to build a custom VM name and is read from the vm_prefix
variable in the naming instance schema; the default is cfme
, but we can define our own if required (see Figure 23-2).
Alternatively, we can set a value in the request options hash:
miq_provision_request
.
options
[
:vm_prefix
]
hostname
is given the value of the Host Name box in Provision Virtual Machines → Customize (see Figure 23-3).
The symbol is added to the request options hash as:
miq_provision_request
.
options
[
:hostname
]
If a VMware customization specification for Linux is used, linux_host_name
is the specific name extracted from the template. The naming logic uses it to set the operating system hostname.
The symbol is added to the request options hash as:
miq_provision_request
.
options
[
:linux_host_name
]
If a VMware customization specification for Windows is used, sysprep_computer_name
is the specific name extracted from the template. CloudForms naming uses it as input to the sysprep process to set the NetBIOS name.
The symbol is added to the request options hash as:
miq_provision_request
.
options
[
:sysprep_computer_name
]
The symbols discussed in the folliowing subsections are derived by the VM naming method and added to the task options hash.
Much of the VM naming logic happens in the Rails code that is not exposed to the Automation Engine. This code does, however, call the naming instance/method defined in the provisioning group profile (the vmname field), and we can use this to add our own customizations. The profile-defined naming method writes its suggested name into $evm.object['vmname']
, which is propagated back to the internal Rails method via a collect.
If the profile-defined naming method suggests a name that should be numerically suffixed (e.g., #{vm_name}$n{3}
), then the backend Rails code will allocate the next free number in the sequence and form the VM name accordingly.
The default profile-defined naming method for infrastructure VMs in CloudForms 4.0 is /Infrastructure/VM/Provisioning/Naming/vmname. It is a relatively simple method, as follows:
#
# Description: This is the default vmnaming method
# 1. If VM name was not chosen during dialog processing then use vm_prefix
# from dialog; else use model and [:environment] tag to generate name
# 2. Else use VM name chosen in dialog
# 3. Then add 3-digit suffix to vm_name
# 4. Added support for dynamic service naming
#
$evm
.
log
(
"info"
,
"Detected vmdb_object_type:<
#{
$evm
.
root
[
'vmdb_object_type'
]
}
>"
)
prov
=
$evm
.
root
[
'miq_provision_request'
]
||
$evm
.
root
[
'miq_provision'
]
||
$evm
.
root
[
'miq_provision_request_template'
]
vm_name
=
prov
.
get_option
(
:vm_name
)
.
to_s
.
strip
number_of_vms_being_provisioned
=
prov
.
get_option
(
:number_of_vms
)
diamethod
=
prov
.
get_option
(
:vm_prefix
)
.
to_s
.
strip
# If no VM name was chosen during dialog
if
vm_name
.
blank?
||
vm_name
==
'changeme'
vm_prefix
=
nil
vm_prefix
||=
$evm
.
object
[
'vm_prefix'
]
$evm
.
log
(
"info"
,
"vm_name from dialog:<
#{
vm_name
.
inspect
}
>
vm_prefix from dialog:<
#{
diamethod
.
inspect
}
>
vm_prefix from model:<
#{
vm_prefix
.
inspect
}
>"
)
# Get provisioning tags for VM name
tags
=
prov
.
get_tags
$evm
.
log
(
"info"
,
"Provisioning Object Tags:
#{
tags
.
inspect
}
"
)
# Set a prefix for VM naming
if
diamethod
.
blank?
vm_name
=
vm_prefix
else
vm_name
=
diamethod
end
$evm
.
log
(
"info"
,
"VM Naming Prefix: <
#{
vm_name
}
>"
)
# Check :environment tag
env
=
tags
[
:environment
]
# If environment tag is not nil
unless
env
.
nil?
$evm
.
log
(
"info"
,
"Environment Tag: <
#{
env
}
> detected"
)
# Get the first 3 characters of the :environment tag
env_first
=
env
[
0
,
3
]
vm_name
=
"
#{
vm_name
}#{
env_first
}
"
$evm
.
log
(
"info"
,
"Updating VM Name: <
#{
vm_name
}
>"
)
end
derived_name
=
"
#{
vm_name
}
$n{3}"
else
if
number_of_vms_being_provisioned
==
1
derived_name
=
"
#{
vm_name
}
"
else
derived_name
=
"
#{
vm_name
}
$n{3}"
end
end
$evm
.
object
[
'vmname'
]
=
derived_name
$evm
.
log
(
"info"
,
"VM Name: <
#{
derived_name
}
>"
)
If we examine this code we can start to see the logic that the virtual machine naming methods use to determine names. There are two main conditions, as follows.
Provisioning a single VM from either Infrastructure → Virtual Machines → Lifecycle → Provision VMs or from a service catalog will result in the VM being given the value of :vm_name
, unless :vm_name
is blank or has the value changeme
. If :vm_name
is blank or changeme
, then we loop through the logic in the Automation Engine naming method, which assembles a VM name by combining the value of :vm_prefix
with the first three characters of the :environment
tag (if it exists) and appending three zero-padded digits.
Provisioning multiple servers from a service catalog will result in the :miq_force_unique_name
symbol being set to true
for each task. If :vm_name
is not blank or changeme
, then the servers will be named as :vm_name
with _n{4}
appended—for example, server_0001, server_0002, and so on—according to the logic in the internal Rails class MiqProvision::Naming
. In this scenario the profile-defined naming method is not used.
Provisioning multiple servers from Infrastructure → Virtual Machines → Lifecycle → Provision VMs will not result in :miq_force_unique_name
being set to true
, and the VM naming logic in the profile-defined naming method will apply. The servers will be given the value of :vm_name
, appended by three zero-padded digits—for example, server001, server002, and so on.
We often wish to customize the naming process to our own requirements. For example, we might wish to name all servers using a fixed prefix (:vm_prefix
), followed by the value of the server_role
tag, followed by a zero-padded digit extension. We can do this using a slight modification of the profile-defined naming method, in conjunction with tagging the servers that we wish to special-case:
.
.
.
prefix
=
prov
.
get_option
(
:vm_prefix
)
.
to_s
.
strip
#
# Special-case the any servers tagged with "server_role" - pemcg
#
# Get provisioning tags for VM name
tags
=
prov
.
get_tags
#
# Check :server_role tag
#
server_role
=
tags
[
:server_role
]
unless
server_role
.
nil?
derived_name
=
"
#{
prefix
}#{
server_role
}
$n{2}"
$evm
.
object
[
'vmname'
]
=
derived_name
$evm
.
log
(
"info"
,
"
#{
@method
}
- VM Name: <
#{
derived_name
}
>"
)
if
@debug
#
# Exit method
#
$evm
.
log
(
"info"
,
"
#{
@method
}
- EVM Automate Method Ended"
)
exit
MIQ_OK
end
#
# End of special case for servers tagged with "server_role"
#
.
.
.
We copy the /Infrastructure/VM/Provisioning/Naming/default instance and /Infrastructure/VM/Provisioning/Naming/vmname method into our own domain and editing the schema or method accordingly.
As we have seen, the naming process for virtual machines is very flexible and allows us to create a custom naming scheme for our cloud or virtual infrastructure. The naming logic is called during the processing of the group profile during provisioning, so different user groups can have entirely different VM naming schemes if we wish.
We have also seen that the naming process generates operating system hostnames as well as the virtual machine names. Setting a hostname is an operating system (rather than virtual machine container) function, so we must pass this value to some other process for it to be set.
If we are PXE-booting our new Red Hat virtual machines and performing a kickstart installation, then we can inject the hostname value into the kickstart script at run-time. If we are provisioning from fully configured templates, then we need to use a VMware customization specification or cloud-init script to perform the hostname injection.
3.141.28.107