package com.urbancode.terraform.tasks.vmware.chef; import java.io.File; import java.io.IOException; import org.apache.log4j.Logger; import com.urbancode.terraform.tasks.vmware.CloneTask; import com.urbancode.terraform.tasks.vmware.PostCreateTask; public class ChefSoloPostCreateTask extends PostCreateTask { //********************************************************************************************** // CLASS //********************************************************************************************** static private final Logger log = Logger.getLogger(ChefSoloPostCreateTask.class); static protected final String confDirNoSeparator = System.getenv("TERRAFORM_HOME") + File.separator + "conf"; static protected final String confDir = confDirNoSeparator + File.separator; //********************************************************************************************** // INSTANCE //********************************************************************************************** private String cookbookUrl; private String soloRbFile = "solo.rb"; private String nodeJsonFile = "node.json"; private String jsonConfFile = "chef.json"; //---------------------------------------------------------------------------------------------- public ChefSoloPostCreateTask() { super(); } //---------------------------------------------------------------------------------------------- public ChefSoloPostCreateTask(CloneTask cloneTask) { super(); this.cloneTask = cloneTask; } //---------------------------------------------------------------------------------------------- public String getCookbookUrl() { return this.cookbookUrl; } //---------------------------------------------------------------------------------------------- public String getSoloRbFile() { return this.soloRbFile; } //---------------------------------------------------------------------------------------------- public String getNodeJsonFile() { return this.nodeJsonFile; } //---------------------------------------------------------------------------------------------- public String getJsonConfFile() { return this.jsonConfFile; } //---------------------------------------------------------------------------------------------- public void setCookbookUrl(String cookbookUrl) { this.cookbookUrl = cookbookUrl; } //---------------------------------------------------------------------------------------------- public void setSoloRbFile(String soloRbFile) { this.soloRbFile = soloRbFile; } //---------------------------------------------------------------------------------------------- public void setNodeJsonFile(String nodeJsonFile) { this.nodeJsonFile = nodeJsonFile; } //---------------------------------------------------------------------------------------------- public void setJsonConfFile(String jsonConfFile) { this.jsonConfFile = jsonConfFile; } //---------------------------------------------------------------------------------------------- private void runCookbook() throws IOException, InterruptedException { try { copyFileFromHostToGuest(confDir + "chef-install.sh", "/tmp/install.sh"); runCommand(vmUser, vmPassword, "runProgramInGuest", "/bin/bash", "/tmp/install.sh"); } catch(IOException e) { log.info(e); log.info("Chef did not install. Either the command failed or it is already installed."); } //mkdir returns non-zero exit code if dir already exists, so we ignore failures mkdirIgnoreExceptions("/etc/chef"); mkdirIgnoreExceptions("/var/chef"); mkdirIgnoreExceptions("/var/chef/data_bags"); copyFileFromHostToGuest(confDir + soloRbFile, "/etc/chef/solo.rb"); copyFileFromHostToGuest(confDir + nodeJsonFile, "/etc/chef/node.json"); copyFileFromHostToGuest(confDir + jsonConfFile, "/etc/chef/" + jsonConfFile); //attempts to run the cookbook and pipes the output to log.out in /var/chef on the vm runCommand(vmUser, vmPassword, "runProgramInGuest", "/usr/bin/chef-solo", "-r", cookbookUrl, "-j", "/etc/chef/" + jsonConfFile, "-L", "/var/chef/chef.out"); } //---------------------------------------------------------------------------------------------- private void mkdirIgnoreExceptions(String dir) { try { runCommand(vmUser, vmPassword, "runProgramInGuest", "/bin/mkdir", dir); } catch (IOException e) { //swallow } catch (InterruptedException e) { //swallow } } //---------------------------------------------------------------------------------------------- @Override public void create() { this.context = environment.fetchContext(); this.vmToConfig = cloneTask.fetchVm(); try { cloneTask.powerOnVm(); environment.fetchVirtualHost().waitForIp(vmToConfig); runCookbook(); } catch (IOException e) { log.warn("IOException while running Chef Solo cookbook. A VMRun command probably failed." + "Check /var/chef/chef.out on your guest VM, if it exists.", e); } catch (InterruptedException e) { log.warn("InterruptedException while running Chef Solo cookbook.", e); } } //---------------------------------------------------------------------------------------------- @Override public void destroy() { } }