Writing a Chef Ohai plugin for the Windows Azure IaaS cloud

Chef is an open-source systems management and cloud infrastructure automation framework created by Opscode. It helps in managing your IT infrastructure and applications as code. It gives you a way to automate your infrastructure and processes.

Knife is a CLI to create, update, search and delete the entities or manage actions on entities in your infrastructure like node (hosts), cloud resources, metadata (roles, environments) and code for infrastructure (recipes, cookbooks), etc. A Knife plug-in is a set of one (or more) subcommands that can be added to Knife to support additional functionality that is not built-in to the base set of Knife subcommands.

Ohai, Ohai plugins and the hints system:
Ohai is a tool that is used to detect certain properties about a node’s environment and provide them to the chef-client during every Chef run. The types of properties Ohai reports on include:

  • Platform details
  • Networking usage
  • Memory usage
  • Processor usage
  • Kernel data
  • Host names
  • Fully qualified domain names (FQDN)
  • Other configuration details
  • When additional data about a system infrastructure is required, a custom Ohai plugin can be used to gather that information. An Ohai plugin is a Ruby DSL. There are several community OHAI cloud plugins providing cloud specific information.

Writing OHAI plug-in for the Azure IaaS cloud:

In simple words Ohai plug-in is a ruby DSL that populates and returns a Mash object to upload nested data. It can be as simple as:

							provides “azure”

azure Mash.new

azure[:version] = “1.2.3”

azure[:description] = “VM created on azure”

And you are done!! Well practically you would populate this programmatically. This plug-in is now ready and when the chef client runs, you would see these attributes set for the node. More on how to setup the custom plug-ins.

Additionally Ohai includes a hinting system that allows a plugin to receive a hint by the existence of a file. These files are in the JSON format to allow passing additional information about the environment at bootstrap time, such as region or datacenter. This information can then be used by ohai plug-ins to identify the type of cloud the node is created on and additionally any cloud attributes that should be set on the node.

Let’s consider a case where you create a virtual machine instance on the Microsoft Windows Azure IaaS Cloud using the knife-azure plugin. Typically, once the VM is created and successfully bootstrapped, we can use knife ssh to secure shell into the VM and run commands. To secure shell into the VM the public IP or FQDN should be set as an attribute. Incase of Azure, the public FQDN can only be retrieved by querying azure management API which can add a lot of overhead to Ohai.

Alternatively we can handle this using OHAI hint system, where the knife azure plug-in can figure out the public FQDN as part of VM creation. and pass on this information to VM. Then a OHAI plug-in can be written which reads the hints file and determines the public IP address. Let’s see how to achieve this:

The hints data can be generated by any cloud plug-in and sent over to node during bootstrap. For example say the knife-azure plug-in sets few attributes within plug-in code before bootstrap:

						Chef::Config[:knife][:hints]["azure"]  ||= cloud_attributes

Where “cloud_attributes” is hash containing the attributes to be set on node using azure ohai plug-in.


You can also have this information passed as a json file to the plug-in if it’s not feasible to modify the plug-in code and the data is available before knife command execution so that it can be passed as CLI option:

						"--hint HINT_NAME[=HINT_FILE]"   "Specify Ohai Hint to be set on the bootstrap target.  Use multiple --hint options to specify multiple hints."

The corresponding ohai plug-ins to load this information and set the attributes can be seen here: https://github.com/opscode/ohai/blob/master/lib/ohai/plugins/cloud.rb#L234

Taking the above scenario, this will load attribute like cloud.public_fqdn in the node which can then be used by knife ssh command or for any other purpose.

Knife SSH example: Once the attributes are populated on chef node we can use knife ssh command as follows:

						$ knife ssh 'name:nodename' 'sudo chef-client -v' -a 'cloud.public_fqdn' 
--identity-file test.pem --ssh-user foo --ssh-port 22

my-hosted-svc.cloudapp.net Chef: 11.4.4
						$ knife ssh 'name:nodename' 'sudo chef-client -v' -a 'cloud.public_fqdn' 
--identity-file test.pem --ssh-user foo --ssh-port 22

my-hosted-svc.cloudapp.net Chef: 11.4.4

*Note the use of attribute ‘cloud.public_fqdn’ which is populated using the ohai hint system from the json.

This post is meant to explain the basics and showcase a real world example of the Ohai plugins and the hints system.