cloudbase-init customization examples – KVM

After we finish the installation process, a directory with a set of files gets created in our installation location. For example, in our VM, a directory called c:\Program Files\Cloudbase Solutions\Cloudbase-init\ was created, and it has the following set of subdirectories:

  • bin: The location where some of the binary files are installed, such as elevate, bsdtar, mcopy, mdir, and so on.
  • conf: The location of three main configuration files that we’re going to work with, which is discussed a bit later.
  • LocalScripts: The default location for PowerShell and similar scripts that we want to run post-boot.
  • Log: The location where we’ll store the cloudbase-init log files by default so that we can debug any issues.
  • Python: The location where local installation of Python is deployed so that we can also use Python for scripting.

Let’s focus on the conf directory, which contains our configuration files:

  • cloudbase-init.conf
  • cloudbase-init-unattend.conf
  • unattend.xml

The way that cloudbase-init works is rather simple – it uses the unattend.xml file during the Windows sysprep phase to execute cloudbase-init with the cloudbase-init-unattend.conf configuration file. The default cloudbase-init-unattend.conf configuration file is easily readable, and we can use the example provided by the cloudbase-init project with the default configuration file explained step by step:

[DEFAULT]
# Name of the user that will get created, group for that user
username=Admin
groups=Administrators
firstlogonbehaviour=no
inject_user_password=true  # Use password from the metadata (not random).

The next part of the config file is about devices – specifically, which devices to inspect for a possible configuration drive (metadata):

config_drive_raw_hhd=true
config_drive_cdrom=true
# Path to tar implementation from Ubuntu.
bsdtar_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\bsdtar.exe
mtools_path= C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\

We need to configure some settings for logging purposes as well:

# Logging level
verbose=true
debug=true
# Where to store logs
logdir=C:\Program Files (x86)\Cloudbase Solutions\Cloudbase-Init\log\
logfile=cloudbase-init-unattend.log
default_log_levels=comtypes=INFO,suds=INFO,iso8601=WARN
logging_serial_port_settings=

The next part of the configuration file is about networking, so we’ll use DHCP to get all the networking settings in our example:

# Use DHCP to get all network and NTP settings
mtu_use_dhcp_config=true
ntp_use_dhcp_config=true

We need to configure the location where the scripts are residing, the same scripts that we can use as a part of the cloudbase-init process:

# Location of scripts to be started during the process
local_scripts_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\LocalScripts\

The last part of the configuration file is about the services and plugins to be loaded, along with some global settings, such as whether to allow the cloudbase-init service to reboot the system or not and how we’re going to approach the cloudbase-init shutdown process (false=graceful service shutdown):

# Services for loading
metadata_services=cloudbaseinit.metadata.services.configdrive.ConfigDriveService, cloudbaseinit.metadata.services.httpservice.HttpService,
cloudbaseinit.metadata.services.ec2service.EC2Service,
cloudbaseinit.metadata.services.maasservice.MaaSHttpService
# Plugins to load
plugins=cloudbaseinit.plugins.common.mtu.MTUPlugin,
        cloudbaseinit.plugins.common.sethostname.SetHostNamePlugin
# Miscellaneous.
allow_reboot=false    # allow the service to reboot the system
stop_service_on_exit=false

Let’s just get a couple of things out of the way from the get-go. Default configuration files already contain some settings that were deprecated, as you’re going to find out soon enough. Specifically, settings such as verbose, logdir and logfile are already deprecated in this release, as you can see from the following screenshot, where cloudbase-init is complaining about those very options:

Figure 10.4 – cloudbase-init complaining about its own default configuration file options

Figure 10.4 – cloudbase-init complaining about its own default configuration file options

If we want to start sysprepping with cloudbase-init by using the default configuration files, we are actually going to get a pretty nicely configured VM – it’s going to be sysprepped, it’s going to reset the administrator password and ask us to change it with the first login, and remove the existing administrator user and its directories. So, before we do this, we need to make sure that we save all of our administrator user settings and data (documents, installers, downloads, and so on) someplace safe. Also, the default configuration files will not reboot the VM by default, which might confuse you. We need to do a manual restart of the VM so that the whole process can start.

The easiest way to work with both cloud-init and cloudbase-init is by writing down a scenario of what needs to be done to the VM as it gets through the initialization process. So, we’ll do just that – pick a load of settings that we want to be configured and create a customization file accordingly. Here are our settings:

  • We want our VM to ask us to change the password post-sysprep and after the cloudbase-init process.
  • We want our VM to take all of its network settings (the IP address, netmask, gateway, DNS servers, and NTP) from DHCP.
  • We want to sysprep the VM so that it’s unique to each scenario and policy.

So, let’s create a cloudbase-init-unattend.conf config file that will do this for us. The first part of the configuration file was taken from the default config file:

[DEFAULT]
username=Admin
groups=Administrators
inject_user_password=true
config_drive_raw_hhd=true
config_drive_cdrom=true
config_drive_vfat=true
bsdtar_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\bsdtar.exe
mtools_path= C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\
debug=true
default_log_levels=comtypes=INFO,suds=INFO,iso8601=WARN
logging_serial_port_settings=
mtu_use_dhcp_config=true
ntp_use_dhcp_config=true

As we decided to use PowerShell for all of the scripting, we created a separate directory for our PowerShell scripts:

local_scripts_path=C:\PS1

The rest of the file was also just copied from the default configuration file:

metadata_services=cloudbaseinit.metadata.services.base.EmptyMetadataService
plugins=cloudbaseinit.plugins.common.mtu.MTUPlugin,
        cloudbaseinit.plugins.common.sethostname.SetHostNamePlugin, cloudbaseinit.plugins.common.localscripts.LocalScriptsPlugin,cloudbaseinit.plugins.common.userdata.UserDataPlugin
allow_reboot=false    
stop_service_on_exit=false

As for the cloudbase-init.conf file, the only change that we made was selecting the correct local script path (reasons to be mentioned shortly), as we will use this path in our next example:

[DEFAULT]
username=Admin
groups=Administrators
inject_user_password=true
config_drive_raw_hhd=true
config_drive_cdrom=true
config_drive_vfat=true

Also, part of our default config file contained paths for tar, mtools, and debugging:

bsdtar_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\bsdtar.exe
mtools_path= C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\
debug=true

This part of the config file was also taken from the default config file, and we only changed local_scripts_path so that it’s set to the directory that we’re using to populate with PowerShell scripts:

first_logon_behaviour=no
default_log_levels=comtypes=INFO,suds=INFO,iso8601=WARN
logging_serial_port_settings=
mtu_use_dhcp_config=true
ntp_use_dhcp_config=true
local_scripts_path=C:\PS1

We can then go back to the cloudbase-init installation screen, check the sysprep option, and click Finish. After starting the sysprep process and going through with it, this is the end result:

Figure 10.5 – When we press Sign in, we are going to be asked to change the administrator's password

Figure 10.5 – When we press Sign in, we are going to be asked to change the administrator’s password

Now, let’s take this a step further and complicate things a bit. Let’s say that you want to do the same process, but with additional PowerShell code that should do some additional configuration. Consider the following example:

  • It should create another two local users called packt1 and packt2, with a predefined password set to Pa$$w0rd.
  • It should create a new local group called students, and add packt1 and packt2 to this group as members.
  • It should set the hostname to Server1.

The PowerShell code that enables us to do this should have the following content:

Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Force
$password = "Pa$$w0rd" | ConvertTo-SecureString -AsPlainText -Force
New-LocalUser -name "packt1" -Password $password
New-LocalUser -name "packt2" -Password $password
New-LocalGroup -name "Students"
Add-LocalGroupMember -group "Students" -Member "packt1","packt2"
Rename-Computer -NewName "Server1" -Restart

Taking a look at the script itself, this is what it does:

  • Sets the PowerShell execution policy to unrestricted so that our host doesn’t stop our script execution, which it would do by default.
  • Creates a password variable from a plaintext string (Pa$$w0rd), which gets converted to a secure string that we can use with the New-LocalUser PowerShell cmdlet to create a local user.
  • New-LocalUser is a PowerShell cmdlet that creates a local user. Mandatory parameters include a username and password, which is why we created a secure string.
  • New-LocalGroup is a PowerShell cmdlet that creates a local group.
  • Add-LocalGroupMember is a PowerShell cmdlet that allows us to create a new local group and add members to it.
  • Rename-Computer is a PowerShell cmdlet that changes the hostname of a Windows computer.

We also need to call this code from cloudbase-init somehow, so we need to add this code as script. Most commonly, we’ll use a directory called LocalScripts in the cloudbase-init installation folder for that. Let’s call this script userdata.ps1, save the content mentioned previously to it in the folder, as defined in the .conf file (c:\PS1), and add a cloudbase-init parameter at the top of the file:

# ps1
$password = "Pa$$w0rd" | ConvertTo-SecureString -AsPlainText -Force
New-LocalUser -name "packt1" -Password $password
New-LocalUser -name "packt2" -Password $password
New-LocalGroup -name "Students"
Add-LocalGroupMember -group "Students" -Member "packt1","packt2"
Rename-Computer -NewName "Server1" –Restart

After starting the cloudbase-init procedure again, which can be achieved by starting the cloudbase-init installation wizard and going through it as we did in the previous example, here’s the end result in terms of users:

Figure 10.6 – The packt1 and packt2 users were created, and added to the group created by our PowerShell script

Figure 10.6 – The packt1 and packt2 users were created, and added to the group created by our PowerShell script

We can clearly see that the packt1 and packt2 users were created, along with a group called Students. We can then see that the Students group has two members – packt1 and packt2. Also, in terms of setting the server name, we have the following:

Figure 10.7 – Slika 1. Changing the server name via PowerShell script also works

Figure 10.7 – Slika 1. Changing the server name via PowerShell script also works

Using cloudbase-init really isn’t simple, and requires a bit of investment in terms of time and tinkering. But afterward, it will make our job much easier – not being forced to do pedestrian tasks such as these over and over again should be a reward enough, which is why we need to talk a little bit about troubleshooting. We’re sure that you’ll run into these issues as you ramp up your cloudbase-init usage.

It will gives you output similar to below:

It will gives you output similar to below:

It will gives you output similar to below:

Related Articles

How to add swap space on Ubuntu 21.04 Operating System

How to add swap space on Ubuntu 21.04 Operating System

The swap space is a unique space on the disk that is used by the system when Physical RAM is full. When a Linux machine runout the RAM it use swap space to move inactive pages from RAM. Swap space can be created into Linux system in two ways, one we can create a...

read more

Lorem ipsum dolor sit amet consectetur

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *

five × 5 =