Since razor has been re-written to razor-server, I had to re-write Chef broker as well. I modeled (copied) the new Chef broker after the original one as much as I could. There were, however, some natural differences and some new challenges. The biggest issue was that since the broker configuration JSON is stored as one string in the database, I needed to pass the validation file as one line and re-create valid file format on the broker hand off.

What Does It Do

The Chef broker is run after the post-install part of the razoring process. Once post-install is complete, the broker installation is invoked. The install.erb file for the appropriate broker is called, which contains some bash scripting to install all the needed bits. Chef broker installs chef-client on the new node, creates /etc/chef/validation.pem, /etc/chef/client.rb, and /etc/chef/first-boot.json files. In the end, the content of the first-boot file (contains run list) is executed by calling the following command:

chef-client -j /etc/chef/first-boot.json -E <%= broker.environment %>
Input

The new Chef broker still expects the same inputs as the original broker. Let’s take a look at a sample json file for Chef broker (the new razor really likes JSON. JSON all the things!).

{
    "name": "openstack_chef_broker",
    "configuration": {
        "install_sh": "http://opscode.com/chef/install.sh",
        "version_string": "11.4.4",
        "chef_server_url": "https://chef.example.com:443",
        "validation_client_name": "chef-validator",
        "run_list": "role[allinone]",
        "environment": "openstack",
        "chef_client": "chef-client",
        "validation_key": "MIIok0h+mSHr1Pbi+v2950H1/7mzd71hXAcRHbmrdytAR+RjgtyibkkZTdSxjLP6o2qEuji0I7DL8cckHG56AvuAKhYoadu+9J/2ahmYr18CSqOmg4Sbh6CPm5edpqaAVTbE3Ec+1wN0IMl8KWtmGCrjpXzH1MDdaLZpIIYqC9DUVgLbd/i61hbiiYlky5wPdIKlKwilRl7alfsGKTUrVq1DuYiIZsDYrnYoLOERbzZU6yUxWSIasfVPJGpT9LvstChFjyjv/73etmhXwwIDAQABAoIBAHH1p1upllVJNMSAhSmLZfTe6Q9nT8unRFH1egcsni8dPXYyVzDQ1ztV3RFNDLjP01ZThqkjoA4TnkHvRnC90yR049eQNxn+7pctcTNW61aAglomMhBcFt7LlcDiiXfD3dVhoIDv4ijpfsNCDvEVain9Dv+krjGVP+dWKLKr2azZbrAnyJKJjKb8DkwFET7UADFgUiCwJCW7RyAAxL40WE1hyYGq03cum5+M+2MGTcCiiAumqIRjYyTioNl73zf/ckBKRBNb6DkVGa1drAwXqMtA0MAaJlQBoJJF9SehSf7rAKVMvQ+esS9kNXZhECgYEA28FKbU3K4mU2khZ8lJgomfelWV48sjeIH3OEuLK7WdKg2LAnNajiLAOHYi0egKiMJPnNyZ8uvOY0JABLHQXv10QKaNlHGqy+aRiRSb1Ya6SlbCg8hMoT29yWGa8k7AclLJSn20/dg0GAEQtegi/k3EEZq0CgYEA148QtVh4ng80d9P81rJEDkraAkKUNJPHBSKFqo1rNwSDsyxxTEXIzZSPYS1mjsdB4IxraiNm3WDhb+EldcSlXvmBDjYJck1WyLCw1JuyAS2VCEtdc38aPWGYZ157decuzkR8CU2TKw48KGSRTtwL8yYqTknqpAmnqf/KkWfVNi8CgYEA1a0AnX+Cwtf/U9UhlarN78fosxj6k5+DcHF2n9DKcvBnDctalMZ+BKX5wfB1NEyu2FU9T8rEO1DragYPA01+hCXYqVJ73OgSzUXiH31IuIID9u/0LyseTWOWoIxWJzdTh44xJ+wJlwNuYXxgjgVGaVZk2niXWTLxtTNEdCz0RpECgYAlholhGIq+8WSv656bfaMtXciAFjkYwhUmhrEAVOgyRr3qpjT/EzL23wLq5u1ws617OtbEPm984I2+XVKZIuerFgJqh+uzE1WlUGUoTgZ6AAZu0DfvkFPwFZpjfGY/y0QxsmhpcjDJkQvV+FP3h4UpCh7ZTDLl5axjgt0v3QSYDwKBgFde/5TO8N8U6lHr1YX+yY8wbQ9sVWPU8qruL5Qx11an1tm9Ja1Wbg8Sn0/A7h7Y331V4cDmVraUreULiTQwSO7N26IxQ3Rg/MQG3szUgP0MWYmjuG0c8zaFB73rnBpZ8xakF/xcRTt2Pb62dkw1VqFhzNc50bN+QvGmtEosIB9z"

},
    "broker-type": "chef"
}

As you can see, the validation file is on one line, as there is no good way to store formatted files in the database, and creating valid JSON with valid new line characters is also not easy. The whole “configuration” block actually gets flattened to a single line in the database, and as such, parsing must occur at some point. I chose the path of least resistance, one that does not require user to create a valid json from the validation file, rather just strip out new line characters.

Let’s take a look at each line in the configuration file:

"name": "openstack_chef_broker"

Is a name of the broker to be used, and it can be pretty much what you like.

"configuration": {

Is the beginning of configuration for the Chef itself.

"install_sh": "http://opscode.com/chef/install.sh",

This is the omnibus installer to be used for installing Chef on your newly installed server. If you have a closed network or have your own installer, it is likely that you will have a custom installer.

"version_string": "11.4.4"

Chef version to be installed.

"chef_server_url": "https://chef.example.com:443",

This is the URL of YOUR Chef server.

"validation_client_name": "chef-validator",

Client name to be used in node’s communication with the Chef server.

"run_list": "role[allinone]",

Initial run list. This is what is going to run after the chef client is installed on the new node.

"environment": "openstack",

Chef environment to be used in the initial Chef run on the new node.

"chef_client": "chef-client",

Binary name for the Chef client installed on the new node. If custom installer installed chef client in a special place or with a special name, specify that here (example: /usr/local/bin/chef-client)

"validation_key":

The validation.pem file. This file must be turned into a single line, and the broker will construct it into it’s original form. Let me know if you have ideas on how to do this better.

"broker-type": "chef"

If you want a Chef broker, you must specify “chef” here. This is to tell razor-server that that’s the broker to use after the node install.

Usage

First, create broker.json file to contain the json:

{
    "name": "openstack_chef_broker",
    "configuration": {
        "install_sh": "http://opscode.com/chef/install.sh",
        "version_string": "11.4.4",
        "chef_server_url": "https://chef.example.com:443",
        "validation_client_name": "chef-validator",
        "run_list": "role[allinone]",
        "environment": "openstack",
        "chef_client": "chef-client",
        "validation_key": "MIIok0h+mSHr1Pbi+v2950H1/7mzd71hXAcRHbmrdytAR+RjgtyibkkZTdSxjLP6o2qEuji0I7DL8cckHG56AvuAKhYoadu+9J/2ahmYr18CSqOmg4Sbh6CPm5edpqaAVTbE3Ec+1wN0IMl8KWtmGCrjpXzH1MDdaLZpIIYqC9DUVgLbd/i61hbiiYlky5wPdIKlKwilRl7alfsGKTUrVq1DuYiIZsDYrnYoLOERbzZU6yUxWSIasfVPJGpT9LvstChFjyjv/73etmhXwwIDAQABAoIBAHH1p1upllVJNMSAhSmLZfTe6Q9nT8unRFH1egcsni8dPXYyVzDQ1ztV3RFNDLjP01ZThqkjoA4TnkHvRnC90yR049eQNxn+7pctcTNW61aAglomMhBcFt7LlcDiiXfD3dVhoIDv4ijpfsNCDvEVain9Dv+krjGVP+dWKLKr2azZbrAnyJKJjKb8DkwFET7UADFgUiCwJCW7RyAAxL40WE1hyYGq03cum5+M+2MGTcCiiAumqIRjYyTioNl73zf/ckBKRBNb6DkVGa1drAwXqMtA0MAaJlQBoJJF9SehSf7rAKVMvQ+esS9kNXZhECgYEA28FKbU3K4mU2khZ8lJgomfelWV48sjeIH3OEuLK7WdKg2LAnNajiLAOHYi0egKiMJPnNyZ8uvOY0JABLHQXv10QKaNlHGqy+aRiRSb1Ya6SlbCg8hMoT29yWGa8k7AclLJSn20/dg0GAEQtegi/k3EEZq0CgYEA148QtVh4ng80d9P81rJEDkraAkKUNJPHBSKFqo1rNwSDsyxxTEXIzZSPYS1mjsdB4IxraiNm3WDhb+EldcSlXvmBDjYJck1WyLCw1JuyAS2VCEtdc38aPWGYZ157decuzkR8CU2TKw48KGSRTtwL8yYqTknqpAmnqf/KkWfVNi8CgYEA1a0AnX+Cwtf/U9UhlarN78fosxj6k5+DcHF2n9DKcvBnDctalMZ+BKX5wfB1NEyu2FU9T8rEO1DragYPA01+hCXYqVJ73OgSzUXiH31IuIID9u/0LyseTWOWoIxWJzdTh44xJ+wJlwNuYXxgjgVGaVZk2niXWTLxtTNEdCz0RpECgYAlholhGIq+8WSv656bfaMtXciAFjkYwhUmhrEAVOgyRr3qpjT/EzL23wLq5u1ws617OtbEPm984I2+XVKZIuerFgJqh+uzE1WlUGUoTgZ6AAZu0DfvkFPwFZpjfGY/y0QxsmhpcjDJkQvV+FP3h4UpCh7ZTDLl5axjgt0v3QSYDwKBgFde/5TO8N8U6lHr1YX+yY8wbQ9sVWPU8qruL5Qx11an1tm9Ja1Wbg8Sn0/A7h7Y331V4cDmVraUreULiTQwSO7N26IxQ3Rg/MQG3szUgP0MWYmjuG0c8zaFB73rnBpZ8xakF/xcRTt2Pb62dkw1VqFhzNc50bN+QvGmtEosIB9z"

},
    "broker-type": "chef"
}

Create broker on the command line:

razor create-broker --json broker.json

Then, create the policy.json file:

{
  "name": "ubuntu_one",
  "repo": { "name": "ubuntu_server" },
  "task": { "name": "ubuntu" },
  "broker": { "name": "openstack_chef_broker" },
  "enabled": true,
  "hostname": "host${id}",
  "root_password": "secret",
  "max_count": "20",
  "rule_number": "107",
  "tags": [{ "name": "ubuntu_small", "rule": ["=", ["num", ["fact", "processorcount"]], 1]}]
}

Create policy:

razor create-policy --json policy.json

Now, your policy is set to use the new Chef broker.
Happy installing!

-eglute