This is a demonstration about how to use RHEL Identity Management to automatically join VMs created with OSP7 (OpenStack) Nova, to automatically assign new VMs to hostgroups, and to automatically create DNS records when a floating IP address is assigned to a VM.
NOTE: The demo shows the ipaotp in the server instance metadata. The latest code at https://github.com/richm/rdo-vm-factory/blob/master/rdo-ipa-nova uses the inject_files method to inject a file into the new VM containing the OTP, which means the OTP is not available to be queried, and the VM can erase it as soon as possible.
How it works
OpenStack Nova provides hooks http://docs.openstack.org/developer/nova/hooks.html which allow developers to create custom code using the internal Nova APIs to perform actions based on Nova actions. The demonstration makes use of the build_instance and the instance_network_info hooks. Here is the source of the hook implementation: https://github.com/richm/rdo-vm-factory/blob/master/rdo-ipa-nova/novahooks.py. The build_instance.pre hook calls Identity Management with the host-add command. This will essentially "reserve" a slot for the new host, but the new host will not be fully joined (i.e. able to use Kerberos, SSH, SSSD, etc.) until the ipa-client-install completes. The build_instance.pre hook then creates the parameters that it needs to specify as arguments for the host-add command. It generates a One Time Password (OTP), and stores the OTP as a file named "/tmp/ipaotp" in the list of injected files in the new VM. This allows the VM to specify the OTP as the -w argument of ipa-client-install, then delete the OTP after it has been used. The OTP is used as the userpassword parameter for the host-add call. The ipaclass metadata item was set by using the --property argument with openstack server create. The value of that item is set to be the value of the userclass parameter for the host-add call, which in the demo is used to automatically assign the new VM to a hostgroup. The fully qualified hostname is constructed by using the VM name as the leftmost component of the FQDN, and the domain used is the Nova dhcp_domain setting if available, or an IPA specific domain configuration parameter. The force parameter is set to True because we want host-add to add the host even though we don't have a "real" public IP address yet, only the private IP address assigned by OpenStack networking. The other parameters are provided to show what options are available when calling host-add.
The VM image provided in the demo uses cloud-init, and Nova has been set up to provide certain data for the VM to use with cloud-init to call ipa-client-install with the OTP. The demo sets up the Nova vendordata_jsonfile_path with a JSON file containing the list of Identity Management client packages to install in the VM, and a runcmd to run a shell script that will run ipa-client-install. The build_instance.pre hook has been configured to add that shell script in the list of injected files in the new VM. The shell script extracts the OTP from /tmp/ipaotp, erases the file, then runs ipa-client-install -w $ipaotp -U. Once this command completes successfully, the VM is fully joined to Identity Management, and users can SSH into the new machine.
The instance_network_info.post is called after Nova handles networking related events. If the hook detects that there is a floating IP assignment, it calls dnsrecord-add to add the record for the floating IP address to the host in Identity Management.
The hook uses a file called /etc/nova/ipaclient.conf to store its configuration. It requires the following configuration parameters:
- service_name - The name of the Kerberos principal of the Identity Management HTTP JSON API service
- url - The URL of the Identity Management HTTP JSON API service
- cacert - The name of the file containing the certificate of the CA of the Identity Management HTTP JSON API service
- keytab - The hook requires a user account in Identity Management that has the ability to add hosts and create DNS records. The hook must be provided with a keytab file for this user.
- connect_retries - How many times the hook will retry an API call
- json_rpc_version - The version of the Identity Management HTTP JSON API that the hook is using
- inject_files - Files to inject into the VM. The format is "/localpath/to/file[ /path/to/file/invm]". If /path/to/file/invm is not given, then the path in the VM is assumed to be the same as the path in the local machine.