[CORD-2608]
Install helm/kubespray and create chart for XOS

Change-Id: I1bb90fd2575fb399d367985659719378f17680fe
diff --git a/cord-config-playbook.yml b/cord-config-playbook.yml
index 760e61f..ea52e04 100644
--- a/cord-config-playbook.yml
+++ b/cord-config-playbook.yml
@@ -1,5 +1,4 @@
 ---
-
 # Copyright 2017-present Open Networking Foundation
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -26,13 +25,10 @@
     - pki-cert
     - ssh-pki
 
-- name: Create CORD profile
+- name: Create CORD profile, Helm charts, and dynamic services config
   hosts: config
   roles:
     - cord-profile
-
-- name: Generate config for dynamic services
-  hosts: config
-  roles:
+    - { role: cord-helm-charts, when: use_k8s | default(False) }
     - xos-services-config
 
diff --git a/install-kubernetes-tools-playbook.yml b/install-kubernetes-tools-playbook.yml
new file mode 100644
index 0000000..b947889
--- /dev/null
+++ b/install-kubernetes-tools-playbook.yml
@@ -0,0 +1,24 @@
+---
+# Copyright 2017-present Open Networking Foundation
+#
+# 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.
+
+# install-kubernetes-tools-playbook.yml
+# Installs kubernetes on the config node
+
+- name: Install kubernetes tools
+  hosts: config
+  roles:
+    - kubectl
+    - helm
+
diff --git a/roles/cord-helm-charts/defaults/main.yml b/roles/cord-helm-charts/defaults/main.yml
new file mode 100644
index 0000000..69147f5
--- /dev/null
+++ b/roles/cord-helm-charts/defaults/main.yml
@@ -0,0 +1,33 @@
+---
+# Copyright 2017-present Open Networking Foundation
+#
+# 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.
+
+# cord-helm-charts/defaults/main.yml
+
+config_cord_profile_dir: "/opt/cord_profile"
+config_cord_helm_dir: "{{ config_cord_profile_dir }}/helm"
+
+head_cord_profile_dir: "/opt/cord_profile"
+head_cord_helm_dir: "{{ head_cord_profile_dir }}/helm"
+
+# site name
+site_name: placeholder-sitename
+site_suffix: "{{ site_name }}.test"
+
+# Docker related settings
+docker_registry_ext_port: "5000"
+docker_registry: "registry.{{ site_suffix }}:{{ docker_registry_ext_port }}"
+
+docker_tag: "candidate"
+
diff --git a/roles/cord-helm-charts/files/core_templates/_helpers.tpl b/roles/cord-helm-charts/files/core_templates/_helpers.tpl
new file mode 100644
index 0000000..399c79a
--- /dev/null
+++ b/roles/cord-helm-charts/files/core_templates/_helpers.tpl
@@ -0,0 +1,8 @@
+{{- define "xos-core.release_labels" }}
+app: {{ printf "%s-%s" .Release.Name .Chart.Name | trunc 63 }}
+version: {{ .Chart.Version }}
+release: {{ .Release.Name }}
+{{- end }}
+{{- define "xos-core.full_name" -}}
+{{- printf "%s-%s" .Release.Name .Chart.Name | trunc 63 -}}
+{{- end -}}
diff --git a/roles/cord-helm-charts/files/core_templates/core-configmap.yaml b/roles/cord-helm-charts/files/core_templates/core-configmap.yaml
new file mode 100644
index 0000000..1e79d79
--- /dev/null
+++ b/roles/cord-helm-charts/files/core_templates/core-configmap.yaml
@@ -0,0 +1,31 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: xos-core
+  labels:
+    {{- include "xos-core.release_labels" . | indent 4 }}
+data:
+  config: |-
+    ---
+    name: xos-core
+    database:
+      name: xos
+      username: postgres
+      password: password
+    logging:
+      version: 1
+      handlers:
+        console:
+          class: logging.StreamHandler
+        file:
+          class: logging.handlers.RotatingFileHandler
+          filename: /var/log/xos.log
+          maxBytes: 10485760
+          backupCount: 5
+      loggers:
+        '':
+          handlers:
+              - console
+              - file
+          level: DEBUG
+    xos_dir: /opt/xos
diff --git a/roles/cord-helm-charts/files/core_templates/core-deployment.yaml b/roles/cord-helm-charts/files/core_templates/core-deployment.yaml
new file mode 100644
index 0000000..8090347
--- /dev/null
+++ b/roles/cord-helm-charts/files/core_templates/core-deployment.yaml
@@ -0,0 +1,34 @@
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: xos-core
+  labels:
+    app: xos-core
+spec:
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: xos-core
+    spec:
+      containers:
+        - name: xos-core
+          image: {{ .Values.images.xos_core.repository }}:{{ .Values.images.xos_core.tag }}
+          # command: ["/bin/bash", "-c", "cd coreapi; ./start_coreapi.sh"]
+          command: ["/bin/bash", "-c", "sleep 86400"]
+          ports:
+            - containerPort: 50051
+              protocol: TCP
+            - containerPort: 50055
+              protocol: TCP
+          volumeMounts:
+            - name: xos-core-config
+              mountPath: /opt/xos/xos_config.yaml
+              subPath: config/xos_config.yaml
+      volumes:
+        - name: xos-core-config
+          configMap:
+            name: xos-core
+            items:
+             - key: config
+               path: config/xos_config.yaml
diff --git a/roles/cord-helm-charts/files/core_templates/core-service.yaml b/roles/cord-helm-charts/files/core_templates/core-service.yaml
new file mode 100644
index 0000000..ab63b07
--- /dev/null
+++ b/roles/cord-helm-charts/files/core_templates/core-service.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: "xos-core"
+  labels:
+    {{- include "xos-core.release_labels" . | indent 4 }}
+spec:
+  type: NodePort
+  ports:
+  - port: 50051
+    name: secure
+    targetPort: 50051
+    protocol: TCP
+  - port: 50055
+    name: insecure
+    targetPort: 50055
+    protocol: TCP
+  selector:
+    app: "xos-core"
diff --git a/roles/cord-helm-charts/files/core_templates/db-configmap.yaml b/roles/cord-helm-charts/files/core_templates/db-configmap.yaml
new file mode 100644
index 0000000..45183b2
--- /dev/null
+++ b/roles/cord-helm-charts/files/core_templates/db-configmap.yaml
@@ -0,0 +1,8 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: xos-db
+  labels:
+    {{- include "xos-core.release_labels" . | indent 4 }}
+data:
+  service_5432_name: 'xos-db'
diff --git a/roles/cord-helm-charts/files/core_templates/db-deployment.yaml b/roles/cord-helm-charts/files/core_templates/db-deployment.yaml
new file mode 100644
index 0000000..326c475
--- /dev/null
+++ b/roles/cord-helm-charts/files/core_templates/db-deployment.yaml
@@ -0,0 +1,27 @@
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: xos-db
+  labels:
+    app: xos-db
+spec:
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: xos-db
+      annotations:
+        checksum/config-map: {{ include (print $.Chart.Name "/templates/db-configmap.yaml") . | sha256sum }}
+    spec:
+      containers:
+        - name: xos-db
+          image: {{ .Values.images.xos_db.repository }}:{{ .Values.images.xos_db.tag }}
+          ports:
+            - containerPort: 5432
+              protocol: TCP
+          env:
+            - name: SERVICE_5432_NAME
+              valueFrom:
+                configMapKeyRef:
+                  name: xos-db
+                  key: service_5432_name
diff --git a/roles/cord-helm-charts/files/core_templates/db-service.yaml b/roles/cord-helm-charts/files/core_templates/db-service.yaml
new file mode 100644
index 0000000..96433b2
--- /dev/null
+++ b/roles/cord-helm-charts/files/core_templates/db-service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: "xos-db"
+  labels:
+    {{- include "xos-core.release_labels" . | indent 4 }}
+spec:
+  type: NodePort
+  ports:
+  - port: 5432
+    targetPort: 5432
+    protocol: TCP
+  selector:
+    app: "xos-db"
diff --git a/roles/cord-helm-charts/tasks/main.yml b/roles/cord-helm-charts/tasks/main.yml
new file mode 100644
index 0000000..f626a30
--- /dev/null
+++ b/roles/cord-helm-charts/tasks/main.yml
@@ -0,0 +1,58 @@
+---
+# Copyright 2017-present Open Networking Foundation
+#
+# 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.
+
+# cord-helm-charts/tasks/main.yml
+# Creates Helm charts for CORD services
+
+- name: Create cord_profile/helm directory and chart subdirectories
+  file:
+    dest: "{{ config_cord_helm_dir }}"
+    state: directory
+    mode: 0755
+    owner: "{{ ansible_user_id }}"
+    group: "{{ ansible_user_gid }}"
+
+- name: Create chart subdirectories
+  file:
+    dest: "{{ config_cord_helm_dir }}/{{ item }}"
+    state: directory
+    mode: 0755
+    owner: "{{ ansible_user_id }}"
+    group: "{{ ansible_user_gid }}"
+  with_items:
+    - "xos-core"
+    - "xos-core/templates"
+    - "xos-services"
+    - "xos-services/templates"
+
+- name: Copy XOS Core templates
+  copy:
+    src: "core_templates/"
+    dest: "{{ config_cord_helm_dir }}/xos-core/templates/"
+    mode: 0755
+    owner: "{{ ansible_user_id }}"
+    group: "{{ ansible_user_gid }}"
+
+- name: Create chart configuration from templates
+  template:
+    src: "{{ item }}.j2"
+    dest: "{{ config_cord_helm_dir }}/xos-core/{{ item }}"
+    mode: 0755
+    owner: "{{ ansible_user_id }}"
+    group: "{{ ansible_user_gid }}"
+  with_items:
+    - Chart.yaml
+    - values.yaml
+
diff --git a/roles/cord-helm-charts/templates/Chart.yaml.j2 b/roles/cord-helm-charts/templates/Chart.yaml.j2
new file mode 100644
index 0000000..40a1708
--- /dev/null
+++ b/roles/cord-helm-charts/templates/Chart.yaml.j2
@@ -0,0 +1,2 @@
+name: xos-core
+version: 1.0.0
diff --git a/roles/cord-helm-charts/templates/values.yaml.j2 b/roles/cord-helm-charts/templates/values.yaml.j2
new file mode 100644
index 0000000..36127e2
--- /dev/null
+++ b/roles/cord-helm-charts/templates/values.yaml.j2
@@ -0,0 +1,12 @@
+images:
+  xos_core:
+    repository: "{{ docker_registry }}/xosproject/xos-ui"
+    tag: "{{ docker_tag }}"
+  xos_db:
+    repository: "{{ docker_registry }}/xosproject/xos-postgres"
+    tag: "{{ docker_tag }}"
+
+services:
+  - name: vsg
+    repository: "{{ docker_registry }}/xosproject/vsg-synchronizer"
+    tag: "{{ docker_tag }}"
diff --git a/roles/helm/defaults/main.yml b/roles/helm/defaults/main.yml
new file mode 100644
index 0000000..91c7ca5
--- /dev/null
+++ b/roles/helm/defaults/main.yml
@@ -0,0 +1,26 @@
+---
+# Copyright 2017-present Open Networking Foundation
+#
+# 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.
+
+# helm/defaults/main.yml
+
+# These vars need to be determined on a per-OS/arch basis
+cpu_arch: "amd64"
+helm_version: "v2.8.0"
+helm_dl_checksum: "sha256:6e1f5957f9c7cec8463f38cf658bea0cf225fc324236617b23fe9044e9dd4ba7"
+
+helm_dl_url: "https://storage.googleapis.com/kubernetes-helm/helm-{{ helm_version }}-{{ ansible_system | lower }}-{{ cpu_arch }}.tar.gz"
+
+helm_bin_path: "/usr/local/bin/helm"
+
diff --git a/roles/helm/tasks/main.yml b/roles/helm/tasks/main.yml
new file mode 100644
index 0000000..1a0b828
--- /dev/null
+++ b/roles/helm/tasks/main.yml
@@ -0,0 +1,85 @@
+---
+# Copyright 2017-present Open Networking Foundation
+#
+# 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.
+
+# helm/tasks/main.yml
+# Installs Helm for kubernetes
+
+# should probably check that downloaded matched installed version, but would
+# need checksum of binary inside the tarball, which isn't published
+- name: Check to see if Helm is installed
+  stat:
+    path: "{{ helm_bin_path }}"
+  register: helm_bin
+
+- name: Create a tempdir for Helm download
+  when: not helm_bin.stat.exists or not helm_bin.stat.executable
+  tempfile:
+    state: directory
+    suffix: helm
+  register: helm_tempdir
+
+- name: Download and verify Helm archive
+  when: not helm_bin.stat.exists or not helm_bin.stat.executable
+  get_url:
+    url: "{{ helm_dl_url }}"
+    checksum: "{{ helm_dl_checksum }}"
+    dest: "{{ helm_tempdir.path }}/helm.tgz"
+
+- name: Unarchive Helm
+  when: not helm_bin.stat.exists or not helm_bin.stat.executable
+  unarchive:
+    remote_src: true
+    src: "{{ helm_tempdir.path }}/helm.tgz"
+    dest: "{{ helm_tempdir.path }}/"
+
+- name: Move helm binary into place
+  when: not helm_bin.stat.exists or not helm_bin.stat.executable
+  become: yes
+  copy:
+    src: "{{ helm_tempdir.path }}/{{ ansible_system | lower }}-{{ cpu_arch }}/helm"
+    dest: "{{ helm_bin_path }}"
+    owner: root
+    group: root
+    mode: 0755
+
+# The helm binary is now installed.  Start up tiller on k8s.
+# `helm init --wait` should handle these waits below, but is broken
+# as of 2018-02-06, see: https://github.com/kubernetes/helm/issues/3379
+
+- name: Initialize Helm and wait for it to be ready
+  command: "helm init"
+  tags:
+    - skip_ansible_lint # while helm may be installed, k8s might have been wiped so tiller needs to be reinstalled
+
+- name: "Wait for 'helm init' to set up Tiller"
+  pause:
+    seconds: 60
+
+# needed to give permissions and avoid the cryptic
+#   "Error: no available release name found" message
+# per: https://github.com/kubernetes/helm/issues/3055
+- name: Give RBAC permissions to tiller
+  command: "kubectl {{ item }}"
+  with_items:
+    - 'create serviceaccount --namespace kube-system tiller'
+    - 'create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller'
+    - 'patch deploy --namespace kube-system tiller-deploy -p ''{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'''
+  tags:
+    - skip_ansible_lint # have to run these to set up tiller, as k8s might not be up
+
+- name: "Wait for Helm/Tiller to be ready"
+  pause:
+    seconds: 30
+
diff --git a/roles/imagebuilder-publish/defaults/main.yml b/roles/imagebuilder-publish/defaults/main.yml
new file mode 100644
index 0000000..551740c
--- /dev/null
+++ b/roles/imagebuilder-publish/defaults/main.yml
@@ -0,0 +1,20 @@
+---
+# Copyright 2017-present Open Networking Foundation
+#
+# 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.
+
+# imagebuilder-publish/defaults/main.yml
+
+deploy_docker_registry: ""
+deploy_docker_tag: "candidate"
+
diff --git a/roles/kubectl/defaults/main.yml b/roles/kubectl/defaults/main.yml
new file mode 100644
index 0000000..6f8efc3
--- /dev/null
+++ b/roles/kubectl/defaults/main.yml
@@ -0,0 +1,27 @@
+---
+# Copyright 2017-present Open Networking Foundation
+#
+# 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.
+
+# kubeadm/defaults/main.yml
+
+kubernetes_version: "1.9.2"
+
+# These vars need to be determined on a per-OS/arch/dl basis
+cpu_arch: "amd64"
+kubectl_dl_checksum: "sha256:455999c8232c57748f4cee4b5446ee39fe8af093434d732ddcd628a02f3d9118"
+
+kubectl_dl_url: "https://storage.googleapis.com/kubernetes-release/release/v{{ kubernetes_version }}/bin/{{ ansible_system | lower }}/{{ cpu_arch }}/kubectl"
+
+kubectl_bin_path: "/usr/local/bin/kubectl"
+
diff --git a/roles/kubectl/tasks/main.yml b/roles/kubectl/tasks/main.yml
new file mode 100644
index 0000000..5dfb550
--- /dev/null
+++ b/roles/kubectl/tasks/main.yml
@@ -0,0 +1,28 @@
+---
+# Copyright 2017-present Open Networking Foundation
+#
+# 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.
+
+# kubectl/tasks/main.yml
+# Installs Kubectl for kubernetes
+
+- name: Download and install kubectl
+  become: yes
+  get_url:
+    url: "{{ kubectl_dl_url }}"
+    checksum: "{{ kubectl_dl_checksum }}"
+    dest: "{{ kubectl_bin_path }}"
+    owner: root
+    group: root
+    mode: 0755
+
diff --git a/roles/start-xos-helm/defaults/main.yml b/roles/start-xos-helm/defaults/main.yml
new file mode 100644
index 0000000..ef5f379
--- /dev/null
+++ b/roles/start-xos-helm/defaults/main.yml
@@ -0,0 +1,22 @@
+---
+# Copyright 2017-present Open Networking Foundation
+#
+# 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.
+
+# start-xos-helm/defaults/main.yml
+
+build_cord_dir: "{{ playbook_dir ~ '/../..' }}"
+
+config_cord_profile_dir: "/opt/cord_profile"
+config_cord_helm_dir: "{{ config_cord_profile_dir }}/helm"
+
diff --git a/roles/start-xos-helm/tasks/main.yml b/roles/start-xos-helm/tasks/main.yml
new file mode 100644
index 0000000..3128973
--- /dev/null
+++ b/roles/start-xos-helm/tasks/main.yml
@@ -0,0 +1,24 @@
+---
+# Copyright 2017-present Open Networking Foundation
+#
+# 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.
+
+# start-xos-helm/tasks/main.yml
+
+- name: Start XOS via Helm
+  command: "helm install --wait xos-core"
+  args:
+    chdir: "{{ config_cord_helm_dir }}"
+  tags:
+    - skip_ansible_lint # running a command, ansible helm module isn't mature
+
diff --git a/start-xos-helm-playbook.yml b/start-xos-helm-playbook.yml
new file mode 100644
index 0000000..814351a
--- /dev/null
+++ b/start-xos-helm-playbook.yml
@@ -0,0 +1,23 @@
+---
+# Copyright 2017-present Open Networking Foundation
+#
+# 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.
+
+# start-xos-helm-playbook.yml
+# Start and XOS containers with helm
+
+- name: Start XOS containers with helm
+  hosts: config
+  roles:
+    - start-xos-helm
+