add a module to resolve hostnames and call harvest if they are not resolvable

Change-Id: Id20780d6ff923b8a089ec163a0f5a6c3756ca62b
(cherry picked from commit d955d33631e79e9c151d733d778ea95987a16cde)
diff --git a/roles/create-vms/library/host_dns_check.py b/roles/create-vms/library/host_dns_check.py
new file mode 100755
index 0000000..20413ab
--- /dev/null
+++ b/roles/create-vms/library/host_dns_check.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+
+import sys
+import json
+import shlex
+import subprocess
+
+# Assume nothing has changed
+result = {
+    "changed" : False,
+    "everyone" : "OK"
+}
+
+# read the argument string from the arguments file
+args_file = sys.argv[1]
+args_data = file(args_file).read()
+
+# Variables for the task options
+host_list = []
+command_on_fail = None
+
+# parse the task options
+arguments = shlex.split(args_data)
+
+for arg in arguments:
+    # ignore any arguments without an equals in it
+    if "=" in arg:
+        (key, value) = arg.split("=")
+
+    if key == "hosts":
+        # The list of hosts comes as a string that looks sort of like a python list,
+        # so some replace magic so we can parse it in to a real list
+        try:
+            value = value.replace("u'", "").replace("'", "")
+            value = json.loads(value)
+            host_list = value
+        except Exception as e:
+            result["everyone"] = "Not OK"
+            result["failed"] = True
+            result["msg"] = "Unable to parse 'hosts' argument to module : '%s'" % (e)
+            print json.dumps(result)
+            sys.stdout.flush()
+            sys.exit(1)
+    if key == "command_on_fail":
+        command_on_fail = value
+
+for host in  host_list:
+    # Attempt to resolve hostname, if a host can't be resolved then fail the task
+    try:
+        if subprocess.check_output(["dig", "+short", "+search", host]) == '':
+            result["everyone"] = "Not OK"
+            result["failed"] = True
+            result["msg"] = "Unable to resolve host '%s'" % (host)
+    except Exception as e:
+        result["everyone"] = "Not OK"
+        result["failed"] = True
+        result["msg"] = "Error encountered while resolving '%s' : '%s'" % (host, e)
+        print json.dumps(result)
+        sys.stdout.flush()
+        sys.exit(1)
+
+# If not all hosts were resolved and a failure command was specified then call that
+# command and capture the results.
+if command_on_fail != None:
+    result["command_on_fail"] = {}
+    result["command_on_fail"]["command"] = command_on_fail
+    try:
+        cmd_out = subprocess.check_output(shlex.split(command_on_fail), shell=True, stderr=subprocess.STDOUT)
+        result["command_on_fail"]["retcode"] = 0
+        result["command_on_fail"]["out"] = cmd_out
+    except subprocess.CalledProcessError as e:
+        result["command_on_fail"]["retcode"] = e.returncode
+        result["command_on_fail"]["out"] = e.output
+
+# Output the results
+print json.dumps(result)
+
+if result["failed"]:
+    sys.exit(1)
diff --git a/roles/create-vms/tasks/main.yml b/roles/create-vms/tasks/main.yml
index 09d23d3..038a5ce 100644
--- a/roles/create-vms/tasks/main.yml
+++ b/roles/create-vms/tasks/main.yml
@@ -14,6 +14,29 @@
     command=autostart
   with_items: "{{ head_vm_list }}"
 
+- name: fetch IP of DHCP harvester
+  command: docker-ip harvester
+  register: harvester_ip
+  changed_when: False
+  when: on_maas
+
+- name: force a harvest to get VM name resolution
+  uri:
+    url: http://{{ harvester_ip.stdout }}:8954/harvest
+    method: POST
+  when: on_maas
+
+- name: wait for VM name resolution
+  host_dns_check:
+    hosts: "{{ head_vm_list | map(attribute='name') | list }}"
+    command_on_fail: "curl -sS --connect-timeout 3 -XPOST http://{{ harvester_ip.stdout }}:8954/harvest"
+  register: all_resolved
+  until: all_resolved.everyone == "OK"
+  retries: 5
+  delay: 10
+  failed_when: all_resolved.everyone != "OK"
+  when: on_maas
+
 - name: wait for VM's to come up
   wait_for:
     host={{ item.name }}