Initial outline of opencord integration repo

- Vagrantfile to support standardized 'corddev' development environment
- Ansible playbooks to properly bring up devenv
- Gradle build structure
- Gradle plugin to manage docker-based workflow (pull, build, run, tag,
  push, etc.)
- Gradle top-level build file to allow pre-fetching and publishing
  component docker images. Supported main tasks: fetch, publish
- Example to how to manage 'as-is' upstream components
- A cleaner way of handling gradle rules
- Added initial content to README.md
- Added initial content to docs/quickstart.md
- Updated .gitignore
- Placeholder, parametric entry for deploy step
- Placeholder deployment profile config file (config/default.yml)

Change-Id: I0ff82e0aa3a5299422bd500f9ab8e41e4814a7ca
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8e389c9
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,36 @@
+# Java
+*.class
+*.jar
+*.war
+*.oar
+
+# Eclipse
+.project
+.classpath
+.settings
+
+# Idea
+.idea
+*.iml
+*.iws
+*.ipr
+
+# OS
+Thumbs.db
+.DS_Store
+
+# Vagrant
+.vagrant
+
+# Docker registry
+/registry
+
+# Build
+build
+
+# Gradle
+.gradle
+
+# Ansible
+ansible/*.retry
+
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..5c294b6
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright 2014 Open Networking Laboratory
+
+   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.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..83dcd31
--- /dev/null
+++ b/README.md
@@ -0,0 +1,45 @@
+# Welcome to OpenCORD
+
+This repository is an entry point to OpenCORD. It helps you to build and deploy OpenCORD.
+
+
+### What is CORD
+
+CORD (Central Office Reimagined as a Data Center) is a revolutionary concept to
+turn Telco Central Offices (and MSO Head Ends) into a modern mini data-center, a.k.a. POD.
+The POD is made up of commodity servers, switches, and other networking devices.
+The POD is an application deployment platform optimized for both conventional cloud-scale
+applications as well as virtual network functions (VNF).
+
+
+### What is OpenCORD
+
+OpenCORD is a reference implementation of the CORD concept and is comprised of:
+
+- A number of POD hardware specifications, which can serve as reference implementations
+- A software platform that when deployed on the servers implements service-agnostic software infrastructure enabling deployment of sophisticated network services
+- A few sample service implementations that can be readily deployed onto OpenCORD PODs
+- A deployment automation framework that simplifies the installation of the platform layers as well as the sample services
+- An extendable test framework and test suite to verify and characterize the platfrom as well as the sample services
+- Extensive documentatio to work with OpenCORD
+
+
+### Quick Start
+
+If this is your first encounter with OpenCORD, you may consider giving it a quick spin. We made it real easy. You can bring up OpenCORD on a single server or on a few servers (with or without a real fabric) with a few commands.
+
+Please follow our [Quick Start Tutorial](docs/quickstart.md).
+
+
+### Further Topics
+
+* POD Reference Designs [coming]
+* CORD Software Architecure [coming]
+* Customizing CORD [coming]
+
+
+### References
+
+* [Project Home](http://opencord.org)
+* [Jira](http://jira.opencord.org)
+* [Gerrit](http://gerrit.opencord.org)
diff --git a/Vagrantfile b/Vagrantfile
new file mode 100644
index 0000000..917fbaa
--- /dev/null
+++ b/Vagrantfile
@@ -0,0 +1,36 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+Vagrant.configure(2) do |config|
+
+  if (/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
+    config.vm.synced_folder ".", "/opencord", mount_options: ["dmode=700,fmode=600"]
+  else
+    config.vm.synced_folder ".", "/opencord"
+  end
+
+  config.vm.define "corddev" do |d|
+    d.vm.box = "ubuntu/trusty64"
+    d.vm.hostname = "corddev"
+    d.vm.network "private_network", ip: "10.100.198.200"
+    d.vm.provision :shell, path: "scripts/bootstrap_ansible.sh"
+    d.vm.provision :shell, inline: "PYTHONUNBUFFERED=1 ansible-playbook /opencord/ansible/corddev.yml -c local"
+    d.vm.provider "virtualbox" do |v|
+      v.memory = 2048
+    end
+  end
+
+  config.vm.define "prod" do |d|
+    d.vm.box = "ubuntu/trusty64"
+    d.vm.hostname = "prod"
+    d.vm.network "private_network", ip: "10.100.198.201"
+    d.vm.provider "virtualbox" do |v|
+      v.memory = 1024
+    end
+  end
+
+  if Vagrant.has_plugin?("vagrant-cachier")
+    config.cache.scope = :box
+  end
+
+end
diff --git a/ansible/ansible.cfg b/ansible/ansible.cfg
new file mode 100644
index 0000000..bd331b2
--- /dev/null
+++ b/ansible/ansible.cfg
@@ -0,0 +1,9 @@
+[defaults]
+callback_plugins=/etc/ansible/callback_plugins/
+host_key_checking=False
+deprecation_warnings=False
+
+[privilege_escalation]
+become=True
+become_method=sudo
+become_user=root
diff --git a/ansible/corddev.yml b/ansible/corddev.yml
new file mode 100644
index 0000000..5bdfa0b
--- /dev/null
+++ b/ansible/corddev.yml
@@ -0,0 +1,10 @@
+- hosts: localhost
+  remote_user: vagrant
+  serial: 1
+  roles:
+    - common
+    - docker
+    - docker-compose
+    - consul-template
+    - registry
+    - java8-oracle
diff --git a/ansible/group_vars/all b/ansible/group_vars/all
new file mode 100644
index 0000000..5c59599
--- /dev/null
+++ b/ansible/group_vars/all
@@ -0,0 +1,9 @@
+ip: "{{ facter_ipaddress_eth1 }}"
+consul_extra: ""
+proxy_url: http://{{ facter_ipaddress_eth1 }}
+proxy_url2: http://{{ facter_ipaddress_eth1 }}
+registry_url: 10.100.198.200:5000/
+jenkins_ip: 10.100.198.200
+debian_version: trusty
+docker_cfg: docker.cfg
+docker_cfg_dest: /etc/default/docker
diff --git a/ansible/host_vars/10.100.198.200 b/ansible/host_vars/10.100.198.200
new file mode 100644
index 0000000..48505cb
--- /dev/null
+++ b/ansible/host_vars/10.100.198.200
@@ -0,0 +1 @@
+ansible_ssh_private_key_file: /opencord/.vagrant/machines/cd/virtualbox/private_key
diff --git a/ansible/roles/common/defaults/main.yml b/ansible/roles/common/defaults/main.yml
new file mode 100644
index 0000000..4ccfffb
--- /dev/null
+++ b/ansible/roles/common/defaults/main.yml
@@ -0,0 +1,8 @@
+hosts: [
+  { host_ip: "10.100.198.200", host_name: "corddev"},
+  { host_ip: "10.100.198.201", host_name: "prod"},
+]
+
+obsolete_services:
+  - puppet
+  - chef-client
diff --git a/ansible/roles/common/tasks/main.yml b/ansible/roles/common/tasks/main.yml
new file mode 100644
index 0000000..32b60e8
--- /dev/null
+++ b/ansible/roles/common/tasks/main.yml
@@ -0,0 +1,21 @@
+- name: JQ is present
+  apt:
+    name: jq
+    force: yes
+  tags: [common]
+
+- name: Host is present
+  lineinfile:
+    dest: /etc/hosts
+    regexp: "^{{ item.host_ip }}"
+    line: "{{ item.host_ip }} {{ item.host_name }}"
+  with_items: hosts
+  tags: [common]
+
+- name: Services are not running
+  service:
+    name: "{{ item }}"
+    state: stopped
+  ignore_errors: yes
+  with_items: obsolete_services
+  tags: [common]
diff --git a/ansible/roles/consul-template/files/consul-template b/ansible/roles/consul-template/files/consul-template
new file mode 100755
index 0000000..46262c6
--- /dev/null
+++ b/ansible/roles/consul-template/files/consul-template
Binary files differ
diff --git a/ansible/roles/consul-template/files/example.conf.tmpl b/ansible/roles/consul-template/files/example.conf.tmpl
new file mode 100644
index 0000000..fbedd1d
--- /dev/null
+++ b/ansible/roles/consul-template/files/example.conf.tmpl
@@ -0,0 +1 @@
+The address is {{getv "/nginx/nginx"}}
diff --git a/ansible/roles/consul-template/files/example.ctmpl b/ansible/roles/consul-template/files/example.ctmpl
new file mode 100644
index 0000000..8a215ab
--- /dev/null
+++ b/ansible/roles/consul-template/files/example.ctmpl
@@ -0,0 +1,3 @@
+{{range service "nginx"}}
+The address is {{.Address}}:{{.Port}}
+{{end}}
diff --git a/ansible/roles/consul-template/files/example.toml b/ansible/roles/consul-template/files/example.toml
new file mode 100644
index 0000000..4c2d3a1
--- /dev/null
+++ b/ansible/roles/consul-template/files/example.toml
@@ -0,0 +1,6 @@
+[template]
+src = "example.conf.tmpl"
+dest = "/tmp/example.conf"
+keys = [
+    "/nginx/nginx"
+]
\ No newline at end of file
diff --git a/ansible/roles/consul-template/tasks/main.yml b/ansible/roles/consul-template/tasks/main.yml
new file mode 100644
index 0000000..06a5e03
--- /dev/null
+++ b/ansible/roles/consul-template/tasks/main.yml
@@ -0,0 +1,19 @@
+- name: Directory is created
+  file:
+    path: /data/consul-template
+    state: directory
+  tags: [consul-template]
+
+- name: File is copied
+  copy:
+    src: consul-template
+    dest: /usr/local/bin/consul-template
+    mode: 0755
+  tags: [consul-template]
+
+- name: Example template is copied
+  copy:
+    src: example.ctmpl
+    dest: /data/consul-template/example.ctmpl
+    mode: 0644
+  tags: [consul-template]
diff --git a/ansible/roles/docker-compose/tasks/main.yml b/ansible/roles/docker-compose/tasks/main.yml
new file mode 100644
index 0000000..3845f4a
--- /dev/null
+++ b/ansible/roles/docker-compose/tasks/main.yml
@@ -0,0 +1,5 @@
+- name: Executable is present
+  get_url:
+    url: https://github.com/docker/compose/releases/download/1.6.2/docker-compose-Linux-x86_64
+    dest: /usr/local/bin/docker-compose
+    mode: 0755
diff --git a/ansible/roles/docker/defaults/main.yml b/ansible/roles/docker/defaults/main.yml
new file mode 100644
index 0000000..338d16e
--- /dev/null
+++ b/ansible/roles/docker/defaults/main.yml
@@ -0,0 +1,6 @@
+docker_extra: ""
+
+centos_files: [
+  { src: "docker.centos.repo", dest: "/etc/yum.repos.d/docker.repo" },
+  { src: "docker.centos.service", dest: "/lib/systemd/system/docker.service" },
+]
\ No newline at end of file
diff --git a/ansible/roles/docker/files/docker.centos.repo b/ansible/roles/docker/files/docker.centos.repo
new file mode 100644
index 0000000..b472187
--- /dev/null
+++ b/ansible/roles/docker/files/docker.centos.repo
@@ -0,0 +1,6 @@
+[dockerrepo]
+name=Docker Repository
+baseurl=https://yum.dockerproject.org/repo/main/centos/7
+enabled=1
+gpgcheck=1
+gpgkey=https://yum.dockerproject.org/gpg
\ No newline at end of file
diff --git a/ansible/roles/docker/files/docker.centos.service b/ansible/roles/docker/files/docker.centos.service
new file mode 100644
index 0000000..3bbef84
--- /dev/null
+++ b/ansible/roles/docker/files/docker.centos.service
@@ -0,0 +1,17 @@
+[Unit]
+Description=Docker Application Container Engine
+Documentation=https://docs.docker.com
+After=network.target docker.socket
+Requires=docker.socket
+
+[Service]
+EnvironmentFile=-/etc/sysconfig/docker
+Type=notify
+ExecStart=/usr/bin/docker daemon --insecure-registry 10.100.198.200:5000 -H fd://
+MountFlags=slave
+LimitNOFILE=1048576
+LimitNPROC=1048576
+LimitCORE=infinity
+
+[Install]
+WantedBy=multi-user.target
diff --git a/ansible/roles/docker/tasks/centos.yml b/ansible/roles/docker/tasks/centos.yml
new file mode 100644
index 0000000..a8910d4
--- /dev/null
+++ b/ansible/roles/docker/tasks/centos.yml
@@ -0,0 +1,23 @@
+- name: CentOS files are copied
+  copy:
+    src: "{{ item.src }}"
+    dest: "{{ item.dest }}"
+  with_items: centos_files
+  tags: [docker]
+
+- name: CentOS package is installed
+  yum:
+    name: docker-engine
+    state: present
+  tags: [docker]
+
+- name: CentOS Daemon is reloaded
+  command: systemctl daemon-reload
+  tags: [docker]
+
+- name: CentOS service is running
+  service:
+    name: docker
+    state: running
+  tags: [docker]
+
diff --git a/ansible/roles/docker/tasks/debian.yml b/ansible/roles/docker/tasks/debian.yml
new file mode 100644
index 0000000..aa10934
--- /dev/null
+++ b/ansible/roles/docker/tasks/debian.yml
@@ -0,0 +1,61 @@
+- name: Debian add Docker repository and update apt cache
+  apt_repository:
+    repo: deb https://apt.dockerproject.org/repo ubuntu-{{ debian_version }} main
+    update_cache: yes
+    state: present
+  tags: [docker]
+
+- name: Debian Docker is present
+  apt:
+    name: docker-engine
+    state: latest
+    force: yes
+  tags: [docker]
+
+- name: Debian python-pip is present
+  apt: name=python-pip state=present
+  tags: [docker]
+
+- name: Debian docker-py is present
+  pip:
+    name: docker-py
+    version: 1.6.0
+    state: present
+  tags: [docker]
+
+- name: Debian files are present
+  template:
+    src: "{{ docker_cfg }}"
+    dest: "{{ docker_cfg_dest }}"
+  register: copy_result
+  tags: [docker]
+
+- name: Debian Daemon is reloaded
+  command: systemctl daemon-reload
+  when: copy_result|changed and is_systemd is defined
+  tags: [docker]
+
+- name: vagrant user is added to the docker group
+  user:
+    name: vagrant
+    group: docker
+  register: user_result
+  tags: [docker]
+
+- name: Debian Docker service is restarted
+  service:
+    name: docker
+    state: restarted
+  when: copy_result|changed or user_result|changed
+  tags: [docker]
+
+- name: DockerUI is running
+  docker:
+    image: abh1nav/dockerui
+    name: dockerui
+    ports: 9000:9000
+    privileged: yes
+    volumes:
+      - /var/run/docker.sock:/var/run/docker.sock
+  when: not skip_ui is defined
+  tags: [docker]
\ No newline at end of file
diff --git a/ansible/roles/docker/tasks/main.yml b/ansible/roles/docker/tasks/main.yml
new file mode 100644
index 0000000..1495847
--- /dev/null
+++ b/ansible/roles/docker/tasks/main.yml
@@ -0,0 +1,5 @@
+- include: debian.yml
+  when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'
+
+- include: centos.yml
+  when: ansible_distribution == 'CentOS' or ansible_distribution == 'Red Hat Enterprise Linux'
diff --git a/ansible/roles/docker/templates/docker-swarm-master.service b/ansible/roles/docker/templates/docker-swarm-master.service
new file mode 100644
index 0000000..1ec64aa
--- /dev/null
+++ b/ansible/roles/docker/templates/docker-swarm-master.service
@@ -0,0 +1,21 @@
+[Unit]
+Description=Docker Application Container Engine
+Documentation=https://docs.docker.com
+After=network.target docker.socket
+Requires=docker.socket
+
+[Service]
+Type=notify
+ExecStart=/usr/bin/docker daemon -H fd:// \
+          --insecure-registry 10.100.198.200:5000 \
+          --registry-mirror=http://10.100.198.200:5001 \
+          --cluster-store=consul://{{ ip }}:8500/swarm \
+          --cluster-advertise={{ ip }}:2375 {{ docker_extra }}
+MountFlags=master
+LimitNOFILE=1048576
+LimitNPROC=1048576
+LimitCORE=infinity
+
+[Install]
+WantedBy=multi-user.target
+
diff --git a/ansible/roles/docker/templates/docker-swarm-node.service b/ansible/roles/docker/templates/docker-swarm-node.service
new file mode 100644
index 0000000..09f5141
--- /dev/null
+++ b/ansible/roles/docker/templates/docker-swarm-node.service
@@ -0,0 +1,23 @@
+[Unit]
+Description=Docker Application Container Engine
+Documentation=https://docs.docker.com
+After=network.target docker.socket
+Requires=docker.socket
+
+[Service]
+Type=notify
+ExecStart=/usr/bin/docker daemon -H fd:// \
+          -H tcp://0.0.0.0:2375 \
+          -H unix:///var/run/docker.sock \
+          --insecure-registry 10.100.198.200:5000 \
+          --registry-mirror=http://10.100.198.200:5001 \
+          --cluster-store=consul://{{ ip }}:8500/swarm \
+          --cluster-advertise={{ ip }}:2375 {{ docker_extra }}
+MountFlags=slave
+LimitNOFILE=1048576
+LimitNPROC=1048576
+LimitCORE=infinity
+
+[Install]
+WantedBy=multi-user.target
+
diff --git a/ansible/roles/docker/templates/docker.cfg b/ansible/roles/docker/templates/docker.cfg
new file mode 100644
index 0000000..ac03f17
--- /dev/null
+++ b/ansible/roles/docker/templates/docker.cfg
@@ -0,0 +1 @@
+DOCKER_OPTS="$DOCKER_OPTS --insecure-registry 10.100.198.200:5000 -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --registry-mirror=http://10.100.198.200:5001"
\ No newline at end of file
diff --git a/ansible/roles/java8-oracle/tasks/main.yml b/ansible/roles/java8-oracle/tasks/main.yml
new file mode 100644
index 0000000..809fbee
--- /dev/null
+++ b/ansible/roles/java8-oracle/tasks/main.yml
@@ -0,0 +1,20 @@
+---
+- name: Install add-apt-repository
+  sudo: yes
+  apt: name=software-properties-common state=latest
+
+- name: Add Oracle Java repository
+  sudo: yes
+  apt_repository: repo='ppa:webupd8team/java'
+
+- name: Accept Java 8 license
+  sudo: yes
+  debconf: name='oracle-java8-installer' question='shared/accepted-oracle-license-v1-1' value='true' vtype='select'
+
+- name: Install Oracle Java 8
+  sudo: yes
+  apt: name={{item}} state=latest
+  with_items:
+  - oracle-java8-installer
+  - ca-certificates
+  - oracle-java8-set-default
diff --git a/ansible/roles/registry/files/mirror-config.yml b/ansible/roles/registry/files/mirror-config.yml
new file mode 100644
index 0000000..65ff62c
--- /dev/null
+++ b/ansible/roles/registry/files/mirror-config.yml
@@ -0,0 +1,23 @@
+version: 0.1
+log:
+  fields:
+    service: registry
+storage:
+  cache:
+    blobdescriptor: inmemory
+  filesystem:
+    rootdirectory: /var/lib/registry
+  delete:
+    enabled: true
+http:
+    addr: :5000
+    headers:
+        X-Content-Type-Options: [nosniff]
+health:
+  storagedriver:
+    enabled: true
+    interval: 10s
+    threshold: 3
+
+proxy:
+  remoteurl: https://registry-1.docker.io
diff --git a/ansible/roles/registry/tasks/main.yml b/ansible/roles/registry/tasks/main.yml
new file mode 100644
index 0000000..ceb8e46
--- /dev/null
+++ b/ansible/roles/registry/tasks/main.yml
@@ -0,0 +1,35 @@
+- name: Directories are present
+  file:
+    path: "{{ item }}"
+    state: directory
+    recurse: yes
+  with_items:
+    - /data/registry-mirror/conf
+  tags: [registry]
+
+- name: Configuration is copied
+  copy:
+    src: mirror-config.yml
+    dest: /data/registry-mirror/conf/config.yml
+  tags: [registry]
+
+- name: Registry container is running
+  docker:
+    name: registry
+    image: registry:2.4.0
+    ports: 5000:5000
+    volumes:
+      - /vagrant/registry:/var/lib/registry/docker/registry
+      - /data/registry/conf:/conf
+  tags: [registry]
+
+- name: Mirror container is running
+  docker:
+    name: registry-mirror
+    image: registry:2.4.0
+    ports: 5001:5000
+    volumes:
+      - /vagrant/registry-mirror:/var/lib/registry/docker/registry
+      - /data/registry-mirror/conf:/conf
+    command: /conf/config.yml
+  tags: [registry]
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..e479884
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+import org.opencord.build.rules.*
+import org.yaml.snakeyaml.Yaml
+
+allprojects {
+    apply plugin: 'base'
+    apply plugin: 'de.gesellix.docker'
+    //apply plugin: 'com.tmiyamon.config'
+
+    docker {
+        // dockerHost = System.env.DOCKER_HOST ?: 'unix:///var/run/docker.sock'
+        // dockerHost = System.env.DOCKER_HOST ?: 'https://192.168.99.100:2376'
+        // certPath = System.getProperty('docker.cert.path') ?: "${System.getProperty('user.home')}/.docker/machine/machines/default"
+        // authConfigPlain = [
+        //   "username"       : "joe",
+        //   "password"       : "some-pw-as-needed",
+        //   "email"          : "joe@acme.com",
+        //   "serveraddress"  : "https://index.docker.io/v1/"
+        //  ]
+    }
+}
+
+ext {
+
+    // Upstream registry to simplify filling out the comps table below
+    upstreamReg = 'docker.io'
+
+    // Target registry to be used to publish docker images needed for deployment
+    targetReg = 'localhost:5000'
+
+    // The tag used to tag the docker images push to the target registry
+    targetTag = 'candidate'
+
+    // Component table
+    comps = [
+        'nginx':      [ 'type':     'image',
+                        'upstream': upstreamReg,
+                        'name':     'nginx',
+                        'digest':   'sha256:b555f8c64ab4e85405e0d8b03f759b73ce88deb802892a3b155ef55e3e832806' ],
+        'swarm':      [ 'type':     'image',
+                        'upstream': upstreamReg,
+                        'name':     'swarm',
+                        'digest':   'sha256:6ca9b40980e2fcdcd229900ec8933f3e92c14ead22c9404cb09736cb4f3a9248' ],
+    ]
+
+    // 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 fetchUpstreamImages {
+  comps.each { name, spec -> if (spec.type == 'image') { dependsOn "fetch" + name } }
+}
+
+task fetch {
+  dependsOn fetchUpstreamImages
+}
+
+task publishImages {
+  comps.each { name, _ -> dependsOn "publish" + name }
+}
+
+task publish {
+  dependsOn publishImages
+}
+
+tasks.addRule(new DockerFetchRule(project))
+tasks.addRule(new DockerPublishRule(project))
+tasks.addRule(new DockerTagRule(project))
+
+task deploy {
+    // TODO this is a place-holder.
+    doFirst {
+        println "Using deployment config: $deployConfig"
+        File configFile = new File(deployConfig)
+        def yaml = new Yaml()
+        def config = yaml.load(configFile.newReader())
+        println "Config: $config"
+        println "Access some data in config:\n\tSeed server IP=${config.seedServer.ip}"
+    }
+}
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
new file mode 100644
index 0000000..cbb6652
--- /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/buildSrc/src/main/groovy/org/opencord/build/rules/DockerFetchRule.groovy b/buildSrc/src/main/groovy/org/opencord/build/rules/DockerFetchRule.groovy
new file mode 100644
index 0000000..01f9176
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/opencord/build/rules/DockerFetchRule.groovy
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+package org.opencord.build.rules
+
+import org.gradle.api.Rule
+import de.gesellix.gradle.docker.tasks.DockerPullTask
+
+
+/**
+ * Gradle Rule class to fetch a docker image
+ */
+class DockerFetchRule implements Rule {
+
+    def project
+
+    DockerFetchRule(project) {
+        this.project = project
+    }
+
+    String getDescription() {
+        'Rule Usage: fetch<image-name>'
+    }
+
+    void apply(String taskName) {
+        if (taskName.startsWith('fetch')) {
+            project.task(taskName, type: DockerPullTask) {
+                ext.compName = taskName - 'fetch'
+                def spec = project.comps[ext.compName]
+                imageName = spec.name + '@' + spec.digest
+            }
+        }
+    }
+}
diff --git a/buildSrc/src/main/groovy/org/opencord/build/rules/DockerPublishRule.groovy b/buildSrc/src/main/groovy/org/opencord/build/rules/DockerPublishRule.groovy
new file mode 100644
index 0000000..75a5990
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/opencord/build/rules/DockerPublishRule.groovy
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+package org.opencord.build.rules
+
+import org.gradle.api.Rule
+import de.gesellix.gradle.docker.tasks.DockerPushTask
+
+
+/**
+ * Gradle Rule class to publish (push) a docker image to a private repo
+ */
+class DockerPublishRule implements Rule {
+
+    def project
+
+    DockerPublishRule(project) {
+        this.project = project
+    }
+
+    String getDescription() {
+        'Rule Usage: publish<image-name>'
+    }
+
+    void apply(String taskName) {
+        if (taskName.startsWith('publish')) {
+            project.task(taskName, type: DockerPushTask) {
+                ext.compName = taskName - 'publish'
+                dependsOn "tag" + compName
+                repositoryName = compName + ':' + project.targetTag
+                registry = project.targetReg
+            }
+        }
+    }
+}
diff --git a/buildSrc/src/main/groovy/org/opencord/build/rules/DockerTagRule.groovy b/buildSrc/src/main/groovy/org/opencord/build/rules/DockerTagRule.groovy
new file mode 100644
index 0000000..114bdfc
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/opencord/build/rules/DockerTagRule.groovy
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+package org.opencord.build.rules
+
+import org.gradle.api.Rule
+import de.gesellix.gradle.docker.tasks.DockerTagTask
+
+
+/**
+ * Gradle Rule class to tag a docker image
+ */
+class DockerTagRule implements Rule {
+
+    def project
+
+    DockerTagRule(project) {
+        this.project = project
+    }
+
+    String getDescription() {
+        'Rule Usage: tag<image-name>'
+    }
+
+    void apply(String taskName) {
+        if (taskName.startsWith('tag')) {
+            project.task(taskName, type: DockerTagTask) {
+                ext.compName = taskName - 'tag'
+                dependsOn "fetch" + compName
+                def spec = project.comps[ext.compName]
+                imageId = spec.name + '@' + spec.digest
+                tag = compName + ':' + project.targetTag
+            }
+        }
+    }
+}
diff --git a/components/nginx/build.gradle b/components/nginx/build.gradle
new file mode 100644
index 0000000..8980e82
--- /dev/null
+++ b/components/nginx/build.gradle
@@ -0,0 +1,66 @@
+plugins {
+  id "com.github.ben-manes.versions" version "0.12.0"
+  id "de.gesellix.docker" version "2016-05-05T13-15-11"
+}
+
+import de.gesellix.gradle.docker.tasks.*
+
+import static groovy.json.JsonOutput.prettyPrint
+import static groovy.json.JsonOutput.toJson
+
+allprojects {
+  apply plugin: 'base'
+  apply plugin: 'de.gesellix.docker'
+  docker {
+    // dockerHost = System.env.DOCKER_HOST ?: 'unix:///var/run/docker.sock'
+    // dockerHost = System.env.DOCKER_HOST ?: 'https://192.168.99.100:2376'
+    // certPath = System.getProperty('docker.cert.path') ?: "${System.getProperty('user.home')}/.docker/machine/machines/default"
+    // authConfigPlain = [
+    //   "username"       : "joe",
+    //   "password"       : "some-pw-as-needed",
+    //   "email"          : "joe@acme.com",
+    //   "serveraddress"  : "https://index.docker.io/v1/"
+    //  ]
+  }
+}
+
+task ping(type: DockerPingTask) {
+  doLast { println prettyPrint(toJson(result.content)) }
+}
+
+task info(type: DockerInfoTask) {
+  doLast { println prettyPrint(toJson(info)) }
+}
+
+task version(type: DockerVersionTask) {
+  doLast { println prettyPrint(toJson(version)) }
+}
+
+//task publish(type: DockerPublishTask) {
+//  imageName = 'nginx'
+//  imageTag = 'cand'
+//  buildContextDirectory = file('./docker/')
+//  targetRegistries = [
+//    dev: "localhost:5000"
+//  ]
+//}
+
+task fetch(type: DockerPullTask) {
+  imageName = 'nginx@sha256:b555f8c64ab4e85405e0d8b03f759b73ce88deb802892a3b155ef55e3e832806'
+  // tag = 'sha256:b555f8c64ab4e85405e0d8b03f759b73ce88deb802892a3b155ef55e3e832806'
+  // tag = '1.10.0'
+  // authConfigPlain = getDockerClient().readDefaultAuthConfig()
+}
+
+task tag(type: DockerTagTask) {
+  dependsOn fetch
+  imageId = 'nginx@sha256:b555f8c64ab4e85405e0d8b03f759b73ce88deb802892a3b155ef55e3e832806'
+  tag = 'nginx:cand'
+}
+
+task publish(type: DockerPushTask) {
+  dependsOn tag
+
+  repositoryName = 'nginx:cand'
+  registry = 'localhost:5000'
+}
diff --git a/config/default.yml b/config/default.yml
new file mode 100644
index 0000000..70945c3
--- /dev/null
+++ b/config/default.yml
@@ -0,0 +1,8 @@
+---
+
+size: 2
+
+seedServer:
+  ip: '10.100.198.202'
+
+otherServers: []
diff --git a/docs/objectives.md b/docs/objectives.md
new file mode 100644
index 0000000..389e76c
--- /dev/null
+++ b/docs/objectives.md
@@ -0,0 +1,151 @@
+# CORD Repo Requirements and Design
+
+## Two Main Objectives
+
+**Trying CORD Must be a Pleasant Experience**
+
+1. Very pleasant first impression for shrink-wrapped "copy-paste" trial
+   * 5-10 simple commands
+   * 1-2 verified prerequisites
+   * <60 minutes)
+1. One/two relevant baked-in use-case(s)
+1. A few supported target environments to chose from (see below)
+
+**Extending, customizing CORD should be well supported**
+
+1. Straightforward to customize and extend
+1. Customizations, extensions can be implemented in their own repo(s) to allow their own SCM by user, independent of CORD CI/CD repos
+1. Tutorials on-line (as well as embedded in the top-level repo) provides step-by-step guidance
+
+## Definitions
+
+[illustration to be added to further explain these:]
+
+* Dev host
+* Dev env (may be a VM on the dev host)
+* Target (deployment) environments
+* Upstream artifacts
+* Upstream artifact repo(s)
+* Result/staged artifact repo
+* Replicated local repo
+* Build phase/process
+* Deployment phase/process
+  * Seed stage
+  * Push stage
+  * Local (pull) stage
+* Use-case phase
+* Clean-up processes
+
+
+## Detailed Short-Term Requirements
+
+These requirements are to support the intended experience outlined above:
+
+* Supported environments for dev host:
+  * Mac OS X
+  * Linux
+  * [Possibly Windows - lower prio, but it may be feasible due to the vagrant/external deployment models]
+* Supported target (deployment) configurations [lets narrow this down for 1st release]:
+  * all-in-one on local VM (Vagrant)
+  * all-in-one IP-accessible bare-metal server (with Ubuntu 14.04LTS pre-installed)
+  * all-in-one AWS node, pre-instantiated with Ubuntu 14.04LTS
+  * all-in-one AWS node, automated pre-instantiation (needs AWS credentials, default region, but can be overridden, pem file, etc.)
+  * few-server, server-only, distributed deployment, local physical servers with given IP
+  * few-server, AWS, remote-deployed with auto-created nodes
+  * real-pod - config 1  
+  * real-pod - config 2
+  * real-pod - config 3  
+* Trial mode should have minimalistic prerequisites on the development host:
+  * git - to clone the top-level repo
+  * vagrant - to bring up the development environment, and also as deployment target
+* Trial mode should allow host to be cleaned up (no trace left if user decides to wipe)
+* Example steps to achieve above goal
+  * Step 1: git clone <opencord repo>
+  * Step 2: cd <repo>
+  * Step 3: vagrant up cord-devenv  # may take a few minutes for the 1st time
+  * Step 4: vagrant ssh cord-devenv
+  * Step 5: cd \<repo>
+  * Step 6: \<config target>
+  * Step 7: \<deploy to target> # may take a few times ten minutes for the 1st time
+* In addition to vagrant-based Linux dev env, MAC OS X shall be supported as native dev env too (albeit with more setup effort, which shall be well documented too)
+* Consistent, clean, informative console feedback as the deployment progresses
+* All assumption are verified (prerequisites, version numbers, etc.)
+* Informative, helpful, consistent error messages that help to diagnose the problem and to make progress
+* Allow continuation of deployment process in case of error disrupted previous run (should not need to wipe everything)
+  * Idempotent steps as much as possible
+* Easy full re-deployment after changes made in local devenv shall be supported (and be fast)
+* Embedded documentation, but also available on-line
+* All upstream artifacts shall be version-controlled, traceable and verifiable (md5, sha1 or sha256)
+  * Upstream includes:
+    * Vagrant box
+    * Docker images
+    * git source repos
+    * [git binary artifacts]
+    * Maven repos
+    * Python/pip repos
+    * Debian repos
+* Upstream references shall be configurable
+* We shall support the creation and the use of controlled local artifact repositories which can contain all upstream dependencies
+  * To support isolated lab environments
+  * To allow cascading, connected (recursive) CI/CD pipelines
+  * Best would be to consolidate all these formats into one packaging and deployment format: docker image/container
+* When/if upstream points to an intranet repo, deployment process must not require Internet access (only access to the local artifact repo)
+* Rely on DevOps 2.0 latest/best practices:
+  * Not to reinvent the wheel
+  * Allow people to be self-sufficient (using their modern skills)
+  * Will make our job easier: no need to explain; we can point to contemporary docs
+* Number of git repos involved in CORD deployment should be "healthy"
+  * One top-level CI/CD repo to allow above experience
+  * It may check out a few additional sub-repos automatically
+  * Sub-repos should be used for truly self-contained projects:
+    * Where loose coupling with other projects is really desirable
+    * When there repo lines up naturally with team ownership
+    * When project is useful without the rest of the CORD ensemble
+* Three domains of configuration:
+  * Source of upstream prerequisites
+  * Target deployment environment
+  * Deployed use-case
+* Multi-server (N server) deployment should not require to copy all artifacts remotely N time, but rather a one-time push/pull of such artifacts to a local repo, and additional servers shall pull from the local repo.
+* Well-supported and well-documented manual steps for the following work-flows:
+  * Dev host: Verify pre-requisites on dev host
+  * Dev host or dev env: Pull down or update local top-level repo
+  * Dev host: Build development env
+  * Dev host: start/stop dev env (once it is built)
+  * Dev env: Pull down all prerequisites
+  * Dev env: Update prerequisites after updating top-level repo (or modifying upstream configs)
+  * Dev env: Build all target artifacts (whatever needs building)
+  * Dev env: Run pre-deployment tests (if any)
+  * Dev env: Select server and start it if needed (docker image with docker registry)
+  * Dev env: Push all target artifacts to target artifact repo (with optional tag)
+  * Dev env: Select / configure target (manual config of target descriptor files)
+  * Dev env: Verify target readiness
+  * Dev env: Deploy to select target (from optional tag)
+  * Target: Execute select post-deploy test suite(s) on select target
+  * Dev env or target: Destroy/wipe target (as applicable)
+
+ 
+## Detailed Longer-term Requirements
+
+* Supported evaluation use-cases shall include:
+  * Testing HA scenarios
+  * Testing scale-out and scale-in scenarios
+  * Testing upgrade process scenarios
+  * Numerical tests (performance tests)
+  * [Posting tests to test report server]
+* The CI/CD environment shall be embedded into the CORD repo
+* The CI/CD environment shall support easy setup of:
+  * Multiple deployment stations (for various types of tests, such as post-commit regression tests, daily smoke- and performance tests)
+  * Local or remote git repo for SCM
+  * Self-contained jenkins profile(s) for automating CI/CD pipeline (useful/meaningful as is, but customizable by user)
+
+ 
+# Design
+
+[to be flashed out once we ratify the requirements]
+
+
+## Open Issues
+
+* On AWS we need a container-only use-case (absolutely no VMs) - is that feasible?
+* Same is needed in a Vagrant-based local simulated env - is that feasible?
+* Role of local Orchestrator in deployment and management of the basic infrastructure - we believe that this shall be minimized to avoid self-management loop. Specifically, local Orchestrator shall not manage what it depends on for its own functionality
diff --git a/docs/quick.md b/docs/quick.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/docs/quick.md
diff --git a/docs/quickstart.md b/docs/quickstart.md
new file mode 100644
index 0000000..494bf23
--- /dev/null
+++ b/docs/quickstart.md
@@ -0,0 +1,117 @@
+# OpenCORD Quick Start Guide
+
+[*This description is for a stand-alone bare-metal target server.
+If we succeed to bring up CORD on a VM, we will relax the text and
+go for the simpler experience.*]
+
+This tutorial walks you through the steps to bring up an OpenCORD "POD" on a single server.
+This deployment uses a simulated fabric, but it is good to get a quick feel
+for what is involved and how CORD works.
+
+Specifically, the tutorial covers the following:
+
+1. Bring up a build environment
+2. Fetch and build all binary artifacts
+3. Deploy the software to the target platform (server)
+4. Run some tests on the platform
+5. Clean-up
+
+### What you need (Prerequisites)
+
+You will need a build machine (can be your developer laptop) and a target server.
+
+Build host:
+
+* Mac OS X, Linux, or Windows with a 64-bit OS
+* Git (2.5.4 or later) - [TODO add pointers and/or instructions]
+* Vagrant (1.8.1 or later) - [TODO add pointers and/or instructions]
+* Access to the Internet (at least through the fetch phase)
+* SSH access to the target server
+
+Target server:
+
+* 64-bit server, with
+  * 16GB+ RAM
+  * 30GB+ disk
+* Ubuntu 14.04 LTS freshly installed (see [TBF]() for instruction on how to install Ubuntu 14.04).
+
+
+### Bring up an Use the OpenCORD Build Environment
+
+On the build host, clone the OpenCORD integration repository and switch into its top directory:
+
+   ```
+   git clone https://gerrit.opencord.org/opencord
+   cd opencord
+   ```
+   
+Bring up the standardized OpenCORD build and development environment (VM). This will take a few minutes, depending on your connection speed:
+
+   ```
+   vagrant up corddev
+   ```
+   
+Login to the build environment:
+
+   ```
+   vagrant ssh corddev
+   ```
+   
+Switch to the OpenCORD integration directory, which is shared from your host:
+
+   ```
+   cd /opencord
+   ```
+   
+Pre-fetch all pre-requisites needed to build all components for OpenCORD. This is the step that takes the longest time as a large number of images and files need to be downloaded.
+
+   ```
+   ./gradlew fetch
+   ```
+   
+Time to build artifacts needed for deployment:
+
+   ```
+   ./gradlew build
+   ```
+   
+Lets publish all artifacts to the staging registry (Docker registry).
+
+   ```
+   ./gradlew publish
+   ```
+   
+   
+### Deploy to the Target Server
+
+Deploy the software to the target platform:
+
+   ```
+   ./gradlew deploy
+   ```
+   
+Execute a set of basic health tests on the platform:
+
+   ```
+   ./gradlew post-deploy-tests
+   ```
+   
+
+### Optional cleanup
+
+Exit from the build environment and destroy it:
+
+   ```
+   exit
+   vagrant destroy -f
+   ```
+
+   
+### Congratulations
+
+If you got this far, you successfully built, deployed, and tested your first OpenCORD POD.
+
+
+### Further Steps
+
+[TODO]
\ No newline at end of file
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/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..2c6137b
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..cf051c0
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Thu May 05 16:09:18 PDT 2016
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-all.zip
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..9d82f78
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..72d362d
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off

+@rem ##########################################################################

+@rem

+@rem  Gradle startup script for Windows

+@rem

+@rem ##########################################################################

+

+@rem Set local scope for the variables with windows NT shell

+if "%OS%"=="Windows_NT" setlocal

+

+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.

+set DEFAULT_JVM_OPTS=

+

+set DIRNAME=%~dp0

+if "%DIRNAME%" == "" set DIRNAME=.

+set APP_BASE_NAME=%~n0

+set APP_HOME=%DIRNAME%

+

+@rem Find java.exe

+if defined JAVA_HOME goto findJavaFromJavaHome

+

+set JAVA_EXE=java.exe

+%JAVA_EXE% -version >NUL 2>&1

+if "%ERRORLEVEL%" == "0" goto init

+

+echo.

+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

+echo.

+echo Please set the JAVA_HOME variable in your environment to match the

+echo location of your Java installation.

+

+goto fail

+

+:findJavaFromJavaHome

+set JAVA_HOME=%JAVA_HOME:"=%

+set JAVA_EXE=%JAVA_HOME%/bin/java.exe

+

+if exist "%JAVA_EXE%" goto init

+

+echo.

+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%

+echo.

+echo Please set the JAVA_HOME variable in your environment to match the

+echo location of your Java installation.

+

+goto fail

+

+:init

+@rem Get command-line arguments, handling Windows variants

+

+if not "%OS%" == "Windows_NT" goto win9xME_args

+if "%@eval[2+2]" == "4" goto 4NT_args

+

+:win9xME_args

+@rem Slurp the command line arguments.

+set CMD_LINE_ARGS=

+set _SKIP=2

+

+:win9xME_args_slurp

+if "x%~1" == "x" goto execute

+

+set CMD_LINE_ARGS=%*

+goto execute

+

+:4NT_args

+@rem Get arguments from the 4NT Shell from JP Software

+set CMD_LINE_ARGS=%$

+

+:execute

+@rem Setup the command line

+

+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

+

+@rem Execute Gradle

+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

+

+:end

+@rem End local scope for the variables with windows NT shell

+if "%ERRORLEVEL%"=="0" goto mainEnd

+

+:fail

+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of

+rem the _cmd.exe /c_ return code!

+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1

+exit /b 1

+

+:mainEnd

+if "%OS%"=="Windows_NT" endlocal

+

+:omega

diff --git a/scripts/bootstrap_ansible.sh b/scripts/bootstrap_ansible.sh
new file mode 100755
index 0000000..d8550fc
--- /dev/null
+++ b/scripts/bootstrap_ansible.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# 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.
+#
+
+set -e
+
+echo "Installing Ansible..."
+apt-get install -y software-properties-common
+apt-add-repository ppa:ansible/ansible
+apt-get update
+apt-get install -y ansible
+cp /opencord/ansible/ansible.cfg /etc/ansible/ansible.cfg
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..8a5ffa7
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,2 @@
+//include 'components/nginx'
+