updated to allow deployment to be driven by a configuration file
diff --git a/build.gradle b/build.gradle
index 826c3b1..dc49de6 100644
--- a/build.gradle
+++ b/build.gradle
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+import org.yaml.snakeyaml.Yaml
 
 ext {
 
@@ -22,6 +23,9 @@
     // The tag used to tag the docker images push to the target registry
     targetTag = project.hasProperty('targetTag') ? project.getProperty('targetTag') : 'candidate'
 
+    // Deployment target config file (yaml format); this can be overwritten from the command line
+    // using the -PdeployConfig=<file-path> syntax.
+    deployConfig = project.hasProperty('deployConfig') ? project.getProperty('deployConfig') : './config/default.yml'
 }
 
 task buildBootstrapImage(type: Exec) {
@@ -98,15 +102,66 @@
 
 // ~~~~~~~~~~~~~~~~~~~ Deployment / Test Tasks  ~~~~~~~~~~~~~~~~~~~~~~~
 
-// This task will invoke the ansible configuration on the vagrant head node. The ansible deployment is
-// executed remotely to the head node as this is a more realistic scenario for a production deployment.
-// The assumption is that this task is executed from the maasdev virtual machine as it access the head 
-// node virtual box over a private network.
-//
-// TODO: Currently the deployment of the head node does not use the locally built docker containers, it
-//       should be modified to do so. This likely means that we need to configure docker on the head node
-//       to access the docker registry on the maasdev virtual box.
-task deployMaas(type: Exec) {
-  commandLine '/usr/bin/ansible-playbook', '-i', '10.100.198.202,', '--skip-tags=switch_support,interface_config', 'dev-head-node.yml', '--extra-vars=external_iface=eth0 fabric_ip=10.1.1.1/24' 
+List.metaClass.asParam = { prefix, sep ->
+  if (delegate.size() == 0) {
+    ""
+  }
+  String result = "--" + prefix + "="
+  String p = ""
+  delegate.each {
+    result += p + "${it}"
+    p = sep
+  }
+  result
 }
 
+List.metaClass.p = { value, name ->
+  if (value != null && value != "") {
+      delegate << name + "=" + value
+  } else {
+      delegate
+  }
+}
+
+List.metaClass.p = { spec ->
+  if (spec != null && spec != "") {
+      delegate += spec
+  } else {
+      delegate
+  }
+}
+
+task deploy (type: Exec) {
+    println "Using deployment config: $deployConfig"
+    File configFile = new File(deployConfig)
+    def yaml = new Yaml()
+    def config = yaml.load(configFile.newReader())
+
+    executable = "ansible-playbook"
+    args = ["-i", config.seedNode.ip + ',']
+
+    if ( config.seedNode.user != null && config.seedNode.user != "" ) {
+        args = args << "--user=$config.seedNode.user"
+    }
+
+    def extraVars = []
+    if (config.seedNode) {
+        extraVars = extraVars.p(config.seedNode.extraVars)
+            .p(config.seedNode.password, "ansible_ssh_pass")
+            .p(config.seedNode.sudoPassword, "ansible_sudo_pass")
+            .p(config.seedNode.fabric_ip, "fabric_ip")
+	    .p(config.seedNode.management_ip, "management_ip")
+	    .p(config.seedNode.external_ip, "external_ip")
+    }
+
+    if (config.otherServers) {
+        extraVars = extraVars.p(config.otherServers.location, "prov_location")
+        .p(config.otherServers.rolesPath, "prov_role_path")
+        .p(config.otherServers.role, "prov_role")
+    }
+
+    def skipTags = [].p(config.seedNode.skipTags)
+
+    args = args.p(skipTags.asParam("skip-tags", ",")).p(extraVars.asParam("extra-vars", " ")) << "head-node.yml"
+    println args
+}
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
new file mode 100644
index 0000000..e73afbe
--- /dev/null
+++ b/buildSrc/build.gradle
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+apply plugin: 'groovy'
+
+repositories {
+    // maven { url 'https://repo.gradle.org/gradle/libs' }
+    maven { url 'https://plugins.gradle.org/m2/' }
+    // mavenCentral()
+}
+
+dependencies {
+    compile gradleApi()
+    compile localGroovy()
+    //compile 'de.gesellix:gradle-docker-plugin:2016-05-05T13-15-11'
+    compile 'org.yaml:snakeyaml:1.10'
+    //compile 'gradle.plugin.com.tmiyamon:gradle-config:0.2.1'
+}
diff --git a/config/default.yml b/config/default.yml
new file mode 100644
index 0000000..78220ef
--- /dev/null
+++ b/config/default.yml
@@ -0,0 +1,35 @@
+# Deployment configuration for VirtualBox based head node.
+#
+# This deployment configuration can be utilized with the head node created
+# via `vargrant up headnode` from the gerrit.opencord.org/maas repository.
+---
+seedNode:
+  ip: '10.100.198.202'
+
+  # User name and password used by Ansible to connect to the host for remote
+  # provisioning
+  user: 'vagrant'
+  password: 'vagrant'
+
+  # Specifies tasks within the head node provisioning not to execute, including:
+  #
+  # switch_support -   don't download the switch ONL images as there are no 
+  #                    switches in this configuration
+  # interface_config - don't update the network configuration of the headnode
+  #                    as it is configured by vagrant to the proper settings
+  skipTags:
+    - 'switch_support'
+    - 'interface_config'
+
+  # Specifies the extra settings required for this configuration
+  #
+  # virtualbox_support - install support for managing virtual box based
+  #                      compute nodes
+  extraVars:
+    - 'virtualbox_support=1'
+
+otherServers:
+  # Specifies the configuration for dynamically added compute nodes
+  location: 'http://gerrit.opencord.org/maas'
+  rolesPath: 'roles'
+  role: 'compute-node'
diff --git a/config/pod5.yml b/config/pod5.yml
new file mode 100644
index 0000000..a380b44
--- /dev/null
+++ b/config/pod5.yml
@@ -0,0 +1,36 @@
+# Deployment configuration for a phyical hardware POD
+---
+seedNode:
+  ip: '47.135.132.21'
+  # User name and password used by Ansible to connect to the host for remote
+  # provisioning
+  user: 'ubuntu'
+  password: 'ubuntu'
+
+  # Network address information for the head node:
+  #
+  # fabric_ip     - the IP address and mask bits to be used to configure the network
+  #                 interface connected to the leaf - spine fabric
+  #
+  # management_ip - the IP address and mask bits to be used to configure the network
+  #                 interface connecting the head node to the POD internal
+  #                 management network. The head node will deliver DHCP addresses to 
+  #                 the other compute nodes over this interface
+  #
+  # external_ip   - the IP address and mask bits to be used to configure the network
+  #                 interface connecting the head node (and the POD) to the 
+  #                 Internet. All traffic in the POD to external hosts will be 
+  #                 NAT-ed through this interface
+  fabric_ip: '10.6.1.1/24'
+  management_ip: '10.6.0.1/24'
+  external_ip: '47.135.132.21/24'
+
+otherNodes:
+  # Experimental
+  #
+  # Specifies the subnet and address range that will be used to allocate IP addresses
+  # to the compute nodes as they are deployed into the POD.
+  fabric:
+    network: 10.6.1.1/24
+    range_low: 10.6.1.2
+    range_high: 10.6.1.253
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..1a644c7
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1 @@
+org.gradle.daemon=true
diff --git a/roles/head-node/files/compute-node.yml.j2 b/roles/head-node/files/compute-node.yml.j2
new file mode 100644
index 0000000..4a6a50d
--- /dev/null
+++ b/roles/head-node/files/compute-node.yml.j2
@@ -0,0 +1,4 @@
+- hosts: all
+  remote_user: ubuntu
+  roles:
+    - {{ provision.role }}
diff --git a/roles/head-node/tasks/main.yml b/roles/head-node/tasks/main.yml
index 3eb2785..a9f5e60 100644
--- a/roles/head-node/tasks/main.yml
+++ b/roles/head-node/tasks/main.yml
@@ -9,7 +9,7 @@
 - name: Ensure Ansible Compute Config Files
   become: yes
   git:
-    repo=http://gerrit.opencord.org/maas
+    repo={{ provision.location }}
     dest=/tmp/ansible.maas
     clone=yes
     force=yes
@@ -17,20 +17,16 @@
 
 - name: Ensure Ansible Roles Exist
   become: yes
-  command: cp -rf /tmp/ansible.maas/{{ item }} /etc/maas/ansible
-  with_items:
-    - roles
+  command: cp -rf /tmp/ansible.maas/{{ provision.role_path }} /etc/maas/ansible
 
 - name: Ensure Ansible Roles Ownership
   become: yes
-  file: dest=/etc/maas/ansible/{{ item }} owner=maas group=maas recurse=yes
-  with_items:
-    - roles
+  file: dest=/etc/maas/ansible/{{ provision.role_path }} owner=maas group=maas recurse=yes
 
 - name: Ensure Compute Node Playbook
   become: yes
-  copy:
-    src=files/compute-node.yml
+  template:
+    src=files/compute-node.yml.j2
     dest=/etc/maas/ansible/compute-node.yml
     owner=maas
     group=maas
diff --git a/roles/head-node/vars/main.yml b/roles/head-node/vars/main.yml
new file mode 100644
index 0000000..e97daf1
--- /dev/null
+++ b/roles/head-node/vars/main.yml
@@ -0,0 +1,9 @@
+provision:
+    # CHANGE:
+    #   'location'   git URL from which to clone a repository that contains the role
+    #                definitions to be used then provisioning a compute node
+    #   'role_path'  directory path within the repo that contains the roles.
+    #   'role'       name of the role to provision for new compute nodes
+    location: "{{ prov_location | default('http://gerrit.opencord.org/maas') }}"
+    role_path: "{{ prov_role_path | default('roles') }}"
+    role: "{{ prov_role | default('compute-node') }}"