From 3e8f9986d1229896af3e52e5a138bcbb7244a449 Mon Sep 17 00:00:00 2001
From: Sean Mooney <sean.k.mooney@intel.com>
Date: Thu, 4 Aug 2016 02:50:31 +0000
Subject: [PATCH] add baremetal role to install kolla deps.

Change-Id: Ie70db1b18a73528b1194e4fbcf53d09fed20f4a0
Implements: blueprint kolla-host
---
 ansible/inventory/multinode                   |   5 +
 ansible/kolla-host.yml                        |   7 +
 ansible/roles/baremetal/defaults/main.yml     |  41 +++++
 .../baremetal/tasks/append_to_etc_hosts.yml   |  17 ++
 .../baremetal/tasks/bootstrap-servers.yml     |   4 +
 ansible/roles/baremetal/tasks/install.yml     |  59 +++++++
 ansible/roles/baremetal/tasks/main.yml        |   2 +
 .../roles/baremetal/tasks/post-install.yml    |  79 +++++++++
 ansible/roles/baremetal/tasks/pre-install.yml | 154 ++++++++++++++++++
 .../baremetal/templates/docker_apt_repo.j2    |   2 +
 .../baremetal/templates/docker_defaults.j2    |  26 +++
 .../templates/docker_systemd_service.j2       |  11 ++
 .../baremetal/templates/docker_yum_repo.j2    |   6 +
 .../roles/prechecks/tasks/service_checks.yml  |   2 +-
 etc/kolla/passwords.yml                       |   4 +
 kolla/cmd/genpwd.py                           |   2 +-
 .../notes/kolla-host-584270e3aee6dfd6.yaml    |  29 ++++
 tools/kolla-ansible                           |   6 +
 18 files changed, 454 insertions(+), 2 deletions(-)
 create mode 100644 ansible/kolla-host.yml
 create mode 100644 ansible/roles/baremetal/defaults/main.yml
 create mode 100644 ansible/roles/baremetal/tasks/append_to_etc_hosts.yml
 create mode 100644 ansible/roles/baremetal/tasks/bootstrap-servers.yml
 create mode 100644 ansible/roles/baremetal/tasks/install.yml
 create mode 100644 ansible/roles/baremetal/tasks/main.yml
 create mode 100644 ansible/roles/baremetal/tasks/post-install.yml
 create mode 100644 ansible/roles/baremetal/tasks/pre-install.yml
 create mode 100644 ansible/roles/baremetal/templates/docker_apt_repo.j2
 create mode 100644 ansible/roles/baremetal/templates/docker_defaults.j2
 create mode 100644 ansible/roles/baremetal/templates/docker_systemd_service.j2
 create mode 100644 ansible/roles/baremetal/templates/docker_yum_repo.j2
 create mode 100644 releasenotes/notes/kolla-host-584270e3aee6dfd6.yaml

diff --git a/ansible/inventory/multinode b/ansible/inventory/multinode
index afc4235698..2d2104566d 100644
--- a/ansible/inventory/multinode
+++ b/ansible/inventory/multinode
@@ -24,6 +24,11 @@ compute01
 [storage]
 storage01
 
+[baremetal:children]
+control
+network
+compute
+storage
 
 # You can explicitly specify which hosts run each project by updating the
 # groups in the sections below. Common services are grouped together.
diff --git a/ansible/kolla-host.yml b/ansible/kolla-host.yml
new file mode 100644
index 0000000000..db50419ece
--- /dev/null
+++ b/ansible/kolla-host.yml
@@ -0,0 +1,7 @@
+---
+- hosts: baremetal
+  gather_facts: no
+  roles:
+    - { role: baremetal,
+        tags: baremetal }
+
diff --git a/ansible/roles/baremetal/defaults/main.yml b/ansible/roles/baremetal/defaults/main.yml
new file mode 100644
index 0000000000..c2f8bccbae
--- /dev/null
+++ b/ansible/roles/baremetal/defaults/main.yml
@@ -0,0 +1,41 @@
+---
+baremetal_nic: "{{ api_interface | default('em1') }}"
+
+docker_apt_url: "https://apt.dockerproject.org"
+docker_apt_key_id: F76221572C52609D
+
+docker_yum_url: "https://yum.dockerproject.org"
+docker_gpg_fingerprint: "58118E89F3A912897C070ADBF76221572C52609D"
+
+customize_etc_hosts: True
+
+create_kolla_user: True
+
+docker_storage_driver: ""
+
+debian_pkg_install:
+ - docker-engine=1.11.*
+ - git
+ - python-dev
+ - libssl-dev
+ - libffi-dev
+ - python-setuptools
+ - ntp
+
+redhat_pkg_install:
+ - epel-release
+ - docker-engine-1.11.0
+ - git
+ - python-devel
+ - openssl-devel
+ - libffi-devel
+ - python-setuptools
+ - ntp
+
+ubuntu_pkg_removals:
+ - lxd
+ - lxc
+ - libvirt
+
+redhat_pkg_removals:
+ - libvirt
diff --git a/ansible/roles/baremetal/tasks/append_to_etc_hosts.yml b/ansible/roles/baremetal/tasks/append_to_etc_hosts.yml
new file mode 100644
index 0000000000..8b26d01016
--- /dev/null
+++ b/ansible/roles/baremetal/tasks/append_to_etc_hosts.yml
@@ -0,0 +1,17 @@
+---
+- name: get real node hostname
+  shell: echo $(hostname)
+  register: real_node_hostname
+  delegate_to: "{{ baremetal_node }}"
+
+- name: get real node ip
+  shell: ip -4 addr show "{{ hostvars[baremetal_node]['baremetal_nic'] }}" | grep -oP "(?<=inet )[\d\.]+(?=/)"
+  register: real_node_ip
+  delegate_to: "{{ baremetal_node }}"
+
+- name: Insert hosts entries for all kolla-ansible hosts
+  lineinfile:
+    dest=/etc/hosts
+    line="{{ real_node_ip.stdout }} {{ real_node_hostname.stdout.split('.')[0] }} {{ real_node_hostname.stdout }} {{ '#' }}a_kolla_ansible_host"
+    insertafter=".*kolla-ansible\ hosts"
+    state=present
diff --git a/ansible/roles/baremetal/tasks/bootstrap-servers.yml b/ansible/roles/baremetal/tasks/bootstrap-servers.yml
new file mode 100644
index 0000000000..3888ed5cb9
--- /dev/null
+++ b/ansible/roles/baremetal/tasks/bootstrap-servers.yml
@@ -0,0 +1,4 @@
+---
+- include: pre-install.yml
+- include: install.yml
+- include: post-install.yml
diff --git a/ansible/roles/baremetal/tasks/install.yml b/ansible/roles/baremetal/tasks/install.yml
new file mode 100644
index 0000000000..c1593f85fd
--- /dev/null
+++ b/ansible/roles/baremetal/tasks/install.yml
@@ -0,0 +1,59 @@
+---
+-   name: update apt cache
+    command: apt-get update
+    become: True
+    when: ansible_os_family == 'Debian'
+
+-   name: install apt packages
+    package: name={{item}} state=present
+    become: True
+    with_items: "{{ debian_pkg_install }}"
+    when: ansible_os_family == 'Debian'
+
+-   name: install wily kernel
+    package: name=linux-generic-lts-wily state=latest
+    register: kernel_updated
+    become: True
+    when:
+     - ansible_distribution|lower == "ubuntu" | bool
+     - ansible_distribution_release|lower == "trusty" | bool
+
+-   name: set reboot required
+    set_fact:
+      reboot_required: True
+    when:
+     - kernel_updated is defined
+     - kernel_updated.changed
+
+-   name: install deltarpm packages
+    package: name={{item}} state=installed
+    become: True
+    with_items:
+    - deltarpm
+    when: ansible_os_family == 'RedHat'
+
+-   name: install yum packages
+    package: name={{item}} state=present
+    become: True
+    with_items: "{{ redhat_pkg_install }}"
+    when: ansible_os_family == 'RedHat'
+
+-   name: install pip
+    easy_install: name=pip
+    become: True
+
+-   name: Install docker-py
+    pip: name=docker-py state=latest
+    become: True
+
+-   name: remove packages
+    package: name={{item}} state=absent
+    with_items: "{{ ubuntu_pkg_removals }}"
+    become: True
+    when: ansible_distribution|lower == "ubuntu" | bool
+
+-   name: remove packages
+    package: name={{item}} state=absent
+    with_items: "{{ redhat_pkg_removals }}"
+    become: True
+    when: ansible_os_family == 'RedHat'
diff --git a/ansible/roles/baremetal/tasks/main.yml b/ansible/roles/baremetal/tasks/main.yml
new file mode 100644
index 0000000000..b017e8b4ad
--- /dev/null
+++ b/ansible/roles/baremetal/tasks/main.yml
@@ -0,0 +1,2 @@
+---
+- include: "{{ action }}.yml"
diff --git a/ansible/roles/baremetal/tasks/post-install.yml b/ansible/roles/baremetal/tasks/post-install.yml
new file mode 100644
index 0000000000..1fa91be1f7
--- /dev/null
+++ b/ansible/roles/baremetal/tasks/post-install.yml
@@ -0,0 +1,79 @@
+---
+
+- name: Ensure docker service directory exists
+  file:
+      path=/etc/systemd/system/docker.service.d
+      state=directory
+      recurse=yes
+  become: True
+  when: (ansible_distribution == "Ubuntu" and ansible_distribution_major_version > "14") or
+        (ansible_os_family == "RedHat") or (ansible_distribution == "Debian")
+
+- name: configure docker service
+  become: True
+  template:
+     src=docker_systemd_service.j2
+     dest=/etc/systemd/system/docker.service.d/kolla.conf
+  when: (ansible_distribution == "Ubuntu" and ansible_distribution_major_version > "14") or
+        (ansible_os_family == "RedHat") or (ansible_distribution == "Debian")
+
+- name: reload docker service file
+  become: True
+  command: systemctl daemon-reload
+  when: (ansible_distribution == "Ubuntu" and ansible_distribution_major_version > "14") or
+        (ansible_os_family == "RedHat") or (ansible_distribution == "Debian")
+
+- name: configure docker service
+  become: True
+  template:
+     src=docker_defaults.j2
+     dest=/etc/default/docker
+  when: (ansible_distribution == "Ubuntu" and ansible_distribution_major_version < "15")
+
+- name: docker mount shared
+  command: mount --make-shared /run
+  become: True
+  when: (ansible_distribution == "Ubuntu" and ansible_distribution_major_version < "15")
+
+- name: remove apparmor profile for libvirt
+  command: apparmor_parser -R /etc/apparmor.d/usr.sbin.libvirtd
+  become: True
+  when: ansible_distribution == "Ubuntu"
+
+- name: create docker group
+  group:
+     name: docker
+  become: True
+
+- name: add kolla user to docker group
+  user:
+     name: kolla
+     append: yes
+     groups: docker
+  become: True
+  when: create_kolla_user | bool == True
+
+- name: start docker
+  service:
+     name: docker
+     state: started
+  become: yes
+
+- name: restart docker
+  service:
+     name: docker
+     state: restarted
+  become: yes
+
+- name: enable docker
+  service:
+     name: docker
+     enabled: yes
+  become: yes
+
+- name: reboot
+  command: reboot -f
+  become: yes
+  when:
+   - reboot_required is defined
+   - reboot_required | bool == true
diff --git a/ansible/roles/baremetal/tasks/pre-install.yml b/ansible/roles/baremetal/tasks/pre-install.yml
new file mode 100644
index 0000000000..9aa13c2564
--- /dev/null
+++ b/ansible/roles/baremetal/tasks/pre-install.yml
@@ -0,0 +1,154 @@
+---
+
+- name: "install python2 and python-simplejson"
+  become: true
+  raw: "yum install -y python python-simplejson || apt-get install -y python2.7 python-simplejson"
+
+- name: gather facts
+  setup:
+
+- name: get node hostname
+  shell: echo $(hostname)
+  register: node_hostname
+
+- name: update /etc/hosts with hostname
+  lineinfile:
+    dest: /etc/hosts
+    regexp: "127.0.0.1	{{ node_hostname.stdout }} localhost"
+    line: "127.0.0.1	{{ node_hostname.stdout }} localhost"
+    state: present
+  become: True
+  when: customize_etc_hosts | bool == True
+
+- name: Remove all previous kolla-ansible hosts entries to prevent cruft
+  lineinfile:
+    dest=/etc/hosts
+    regexp="{{ '#' }}a_kolla-ansible_host"
+    state=absent
+  become: True
+  when: customize_etc_hosts | bool == True
+
+- name: Insert a comment after EOF to put our entries under, IF it is not already present
+  lineinfile:
+    dest=/etc/hosts
+    regexp="{{ '#' }}kolla-ansible hosts"
+    line="{{ '#' }}kolla-ansible hosts"
+    insertafter=EOF
+    state=present
+  become: True
+  when: customize_etc_hosts | bool == True
+
+- include: append_to_etc_hosts.yml
+  with_inventory_hostnames: baremetal
+  loop_control:
+    loop_var: baremetal_node
+  become: True
+  when: customize_etc_hosts | bool == True
+
+- name: ensure sudo group is present
+  group: name=sudo state=present
+  become: True
+
+- name: ensure kolla group is present
+  group: name=kolla state=present
+  become: True
+  when: create_kolla_user | bool == True
+
+- name: create kolla user
+  user:
+    name: kolla
+    state: present
+    group: kolla
+    groups: "sudo"
+  become: True
+  when: create_kolla_user | bool == True
+
+- name: grant kolla user passwordless sudo
+  lineinfile:
+    dest: /etc/sudoers
+    state: present
+    regexp: '^kolla'
+    line: 'kolla ALL=(ALL) NOPASSWD: ALL'
+  become: True
+  when: create_kolla_user | bool == True
+
+- name: add public key to kolla user authorized keys
+  authorized_key:
+    user: kolla
+    key: "{{ kolla_ssh_key.public_key }}"
+  become: True
+  when: create_kolla_user | bool == True
+
+- name: install apt packages
+  command: apt-get update
+  become: True
+  when: ansible_os_family == 'Debian'
+
+- name: install ubuntu ca certs
+  package: name={{item}} state=latest
+  become: True
+  with_items:
+  - ca-certificates
+  - apt-transport-https
+  when:
+   - ansible_os_family == 'Debian'
+
+- name: Ensure apt sources list directory exists
+  file: path=/etc/apt/sources.list.d state=directory recurse=yes
+  become: True
+  when: ansible_os_family == 'Debian'
+
+- name: enable docker repo apt
+  template:
+    src: docker_apt_repo.j2
+    dest: /etc/apt/sources.list.d/docker.list
+  become: True
+  when: ansible_os_family == 'Debian'
+
+- name: install docker apt gpg key
+  apt_key:
+    url: "{{ docker_apt_url }}/gpg"
+    id: "{{ docker_apt_key_id }}"
+    state: present
+  become: True
+  when:
+   - ansible_os_family == 'Debian'
+   - ansible_distribution == 'Ubuntu'
+
+- name: Ensure yum repos directory exists
+  file: path=/etc/yum.repos.d/ state=directory recurse=yes
+  become: True
+  when: ansible_os_family == 'RedHat'
+
+- name: enable docker repo yum
+  become: True
+  template:
+    src: docker_yum_repo.j2
+    dest: /etc/yum.repos.d/docker.repo
+  when: ansible_os_family == 'RedHat'
+
+- name: install docker rpm gpg key
+  rpm_key:
+    state: present
+    key: "{{ docker_yum_url }}/gpg"
+  become: True
+  when: ansible_os_family == 'RedHat'
+
+- name: Ensure /etc/kolla directory exists
+  file:
+    path: /etc/kolla
+    state: directory
+    recurse: yes
+    owner: kolla
+    mode: 755
+  become: True
+  when: create_kolla_user | bool == True
+
+- name: Ensure /etc/kolla directory exists
+  file:
+    path: /etc/kolla
+    state: directory
+    recurse: yes
+    mode: 666
+  become: True
+  when: create_kolla_user | bool == False
diff --git a/ansible/roles/baremetal/templates/docker_apt_repo.j2 b/ansible/roles/baremetal/templates/docker_apt_repo.j2
new file mode 100644
index 0000000000..a317c5b56f
--- /dev/null
+++ b/ansible/roles/baremetal/templates/docker_apt_repo.j2
@@ -0,0 +1,2 @@
+# main docker repo
+deb {{docker_apt_url}}/repo {{ansible_distribution|lower}}-{{ansible_distribution_release|lower}} main
diff --git a/ansible/roles/baremetal/templates/docker_defaults.j2 b/ansible/roles/baremetal/templates/docker_defaults.j2
new file mode 100644
index 0000000000..0b6b375bb5
--- /dev/null
+++ b/ansible/roles/baremetal/templates/docker_defaults.j2
@@ -0,0 +1,26 @@
+# Docker Upstart and SysVinit configuration file
+
+#
+# THIS FILE DOES NOT APPLY TO SYSTEMD
+#
+#   Please see the documentation for "systemd drop-ins":
+#   https://docs.docker.com/engine/articles/systemd/
+#
+
+# Customize location of Docker binary (especially for development testing).
+#DOCKERD="/usr/local/bin/dockerd"
+
+# Use DOCKER_OPTS to modify the daemon startup options.
+DOCKER_OPTS=""
+{% if docker_storage_driver %}
+DOCKER_OPTS="$DOCKER_OPTS --storage-driver={{ docker_storage_driver }}"
+{% endif %}
+{% if docker_registry %}
+DOCKER_OPTS="$DOCKER_OPTS --insecure-registry  {{ docker_registry }}"
+{% endif %}
+
+# If you need Docker to use an HTTP proxy, it can also be specified here.
+#export http_proxy="http://127.0.0.1:3128/"
+
+# This is also a handy place to tweak where Docker's temporary files go.
+#export TMPDIR="/mnt/bigdrive/docker-tmp"
diff --git a/ansible/roles/baremetal/templates/docker_systemd_service.j2 b/ansible/roles/baremetal/templates/docker_systemd_service.j2
new file mode 100644
index 0000000000..fb021a677f
--- /dev/null
+++ b/ansible/roles/baremetal/templates/docker_systemd_service.j2
@@ -0,0 +1,11 @@
+[Service]
+MountFlags=shared
+ExecStart=
+ExecStart=/usr/bin/docker daemon \
+{% if docker_registry %}
+--insecure-registry  {{ docker_registry }} \
+{% endif %}
+{% if docker_storage_driver %}
+--storage-driver={{ docker_storage_driver }}
+{% endif %}
+ -H fd://
diff --git a/ansible/roles/baremetal/templates/docker_yum_repo.j2 b/ansible/roles/baremetal/templates/docker_yum_repo.j2
new file mode 100644
index 0000000000..a165efab20
--- /dev/null
+++ b/ansible/roles/baremetal/templates/docker_yum_repo.j2
@@ -0,0 +1,6 @@
+[docker-repo]
+name=Docker main Repository
+baseurl={{docker_yum_url}}/repo/main/{{ansible_distribution|lower}}/{{ansible_distribution_major_version|lower}}
+enabled=1
+gpgcheck=1
+gpgkey={{docker_yum_url}}/gpg
diff --git a/ansible/roles/prechecks/tasks/service_checks.yml b/ansible/roles/prechecks/tasks/service_checks.yml
index 29e9f90173..42335ab394 100644
--- a/ansible/roles/prechecks/tasks/service_checks.yml
+++ b/ansible/roles/prechecks/tasks/service_checks.yml
@@ -41,4 +41,4 @@
   local_action: command grep '^[^#].*:\s*$' "{{ CONFIG_DIR }}/passwords.yml"
   register: result
   changed_when: false
-  failed_when: result.stdout | regex_replace('(.*nova_ssh_key.*)', '') | search(":")
+  failed_when: result.stdout | regex_replace('(.*ssh_key.*)', '') | search(":")
diff --git a/etc/kolla/passwords.yml b/etc/kolla/passwords.yml
index b026cb89a7..18e0b9dc1e 100644
--- a/etc/kolla/passwords.yml
+++ b/etc/kolla/passwords.yml
@@ -77,6 +77,10 @@ nova_ssh_key:
   private_key:
   public_key:
 
+kolla_ssh_key:
+  private_key:
+  public_key:
+
 ####################
 # RabbitMQ options
 ####################
diff --git a/kolla/cmd/genpwd.py b/kolla/cmd/genpwd.py
index ad77a77c0f..b45fa56adc 100755
--- a/kolla/cmd/genpwd.py
+++ b/kolla/cmd/genpwd.py
@@ -43,7 +43,7 @@ def main():
     uuid_keys = ['ceph_cluster_fsid', 'rbd_secret_uuid']
 
     # SSH key pair
-    ssh_keys = ['nova_ssh_key']
+    ssh_keys = ['kolla_ssh_key', 'nova_ssh_key']
 
     # If these keys are None, leave them as None
     blank_keys = ['docker_registry_password']
diff --git a/releasenotes/notes/kolla-host-584270e3aee6dfd6.yaml b/releasenotes/notes/kolla-host-584270e3aee6dfd6.yaml
new file mode 100644
index 0000000000..b3ad9794e2
--- /dev/null
+++ b/releasenotes/notes/kolla-host-584270e3aee6dfd6.yaml
@@ -0,0 +1,29 @@
+---
+prelude: >
+  - In the Newton cycle a new kolla-host playbook was
+    introduced. The kolla-host playbook is intended to
+    prepare servers for use as kolla deployment hosts.
+    The kolla-host playbook requires the nodes to have
+    an os installed and be reachable via ssh. Currently
+    the kolla-host playbook supports ubuntu 14.04,
+    ubuntu 16.04 and centos 7.2 as target servers.
+    See features section for more details.
+features:
+  - The kolla-host playbook supports bootrapping
+    clean os installations to enable them to be
+    used as kolla hosts. When the playbook completes
+    the bootstraped systems should pass the kolla
+    prechecks.
+  - The kolla-host playbook will install docker 1.11
+    and docker-py on all baremetal nodes.
+  - The kolla-host playbook will configure /etc/host
+    with the hostname and ip address of all nodes
+    in the kolla inventroy if customize_etc_host
+    set to its default value of True.
+security:
+  - The kolla-host playbook will create a kolla user
+    on all nodes using the ssh-key specified in the
+    passwords.yml. The kolla user will be granted
+    passwordless sudo privalages on the host.
+    this behavior can be disabled by setting
+    create_kolla_user=False
diff --git a/tools/kolla-ansible b/tools/kolla-ansible
index 030f0323e6..a37cbbf7b2 100755
--- a/tools/kolla-ansible
+++ b/tools/kolla-ansible
@@ -41,6 +41,7 @@ Options:
 Commands:
     prechecks           Do pre-deployment checks for hosts
     mariadb_recovery    Recover a completely stopped mariadb cluster
+    bootstrap-servers   bootstrap servers with kolla deploy dependencies
     deploy              Deploy and start all kolla containers
     destroy             Destroy Kolla containers, volumes and host configuration
                         ('-e destroy_include_images=yes' to also destroy Kolla images)
@@ -144,6 +145,11 @@ case "$1" in
         ACTION="Destroy Kolla containers, volumes and host configuration"
         PLAYBOOK="${BASEDIR}/ansible/destroy.yml"
         ;;
+(bootstrap-servers)
+        ACTION="Deploying Playbooks"
+        PLAYBOOK="${BASEDIR}/ansible/kolla-host.yml"
+        EXTRA_OPTS="$EXTRA_OPTS -e action=bootstrap-servers"
+        ;;
 (deploy)
         ACTION="Deploying Playbooks"
         EXTRA_OPTS="$EXTRA_OPTS -e action=deploy"