From 066173bec0c66de82c1337a3ecd272d4932ad127 Mon Sep 17 00:00:00 2001
From: Jeffrey Zhang <jeffrey.zhang@99cloud.net>
Date: Thu, 21 Jul 2016 01:22:56 +0800
Subject: [PATCH] Implement mongodb replication set cluster

Closes-Bug: #1605457
Change-Id: I1a8e746f79f4dfcc5a43e736c3461b316db3f593
---
 ansible/roles/ceilometer/defaults/main.yml    |  4 +--
 ansible/roles/mongodb/defaults/main.yml       |  3 +++
 .../roles/mongodb/tasks/bootstrap_cluster.yml | 19 ++++++++++++++
 ansible/roles/mongodb/tasks/start.yml         | 13 ++++++++++
 .../mongodb/templates/bootstrap_cluster.js.j2 | 14 ++++++++++
 .../roles/mongodb/templates/mongodb.conf.j2   | 26 ++++++++++---------
 ...eplicate-set-cluster-0d3f140f7116c3ba.yaml |  3 +++
 7 files changed, 67 insertions(+), 15 deletions(-)
 create mode 100644 ansible/roles/mongodb/tasks/bootstrap_cluster.yml
 create mode 100644 ansible/roles/mongodb/templates/bootstrap_cluster.js.j2
 create mode 100644 releasenotes/notes/implement-mongo-replicate-set-cluster-0d3f140f7116c3ba.yaml

diff --git a/ansible/roles/ceilometer/defaults/main.yml b/ansible/roles/ceilometer/defaults/main.yml
index dd481fe800..6546dc1d03 100644
--- a/ansible/roles/ceilometer/defaults/main.yml
+++ b/ansible/roles/ceilometer/defaults/main.yml
@@ -7,9 +7,7 @@ project_name: "ceilometer"
 ####################
 ceilometer_database_name: "ceilometer"
 ceilometer_database_user: "ceilometer"
-# TODO(HuiKang): Update this so that connection to mongodb could be through
-#                haproxy; haproxy conf needs configurations for mongodb.
-ceilometer_database_address: "{{ hostvars[groups['mongodb'][0]]['ansible_' + hostvars[groups['mongodb'][0]]['api_interface']]['ipv4']['address'] }}"
+ceilometer_database_address: "{% for host in groups['mongodb'] %}{{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ mongodb_port }}{% if not loop.last %},{% endif %}{% endfor %}"
 
 
 ####################
diff --git a/ansible/roles/mongodb/defaults/main.yml b/ansible/roles/mongodb/defaults/main.yml
index 4dfddf874e..d57ce5f20b 100644
--- a/ansible/roles/mongodb/defaults/main.yml
+++ b/ansible/roles/mongodb/defaults/main.yml
@@ -9,6 +9,9 @@ mongodb_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_
 mongodb_tag: "{{ openstack_release }}"
 mongodb_image_full: "{{ mongodb_image }}:{{ mongodb_tag }}"
 
+
 ####################
 # Mongodb
 ####################
+
+mongodb_replication_set_name: "rs0"
diff --git a/ansible/roles/mongodb/tasks/bootstrap_cluster.yml b/ansible/roles/mongodb/tasks/bootstrap_cluster.yml
new file mode 100644
index 0000000000..8d445f36f9
--- /dev/null
+++ b/ansible/roles/mongodb/tasks/bootstrap_cluster.yml
@@ -0,0 +1,19 @@
+---
+- name: Copying the mongodb replication set bootstrap script
+  template: src=bootstrap_cluster.js.j2 dest=/tmp/mongodb_bootstrap_replication_set.js
+  delegate_to: "{{ groups['mongodb'][0] }}"
+  run_once: True
+
+- name: Bootstraping the mongodb replication set
+  command: "docker exec -t mongodb mongo {{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }} --quiet --eval '{{ lookup('file','/tmp/mongodb_bootstrap_replication_set.js') }}'"
+  register: bootstrap_mongodb_cluster
+  failed_when: "{{ (bootstrap_mongodb_cluster.stdout|from_json).ok != 1 }}"
+  delegate_to: "{{ groups['mongodb'][0] }}"
+  run_once: True
+
+- name: Deleting the mongodb replication set bootstrap script
+  file: path=/tmp/mongodb_bootstrap_replication_set.js state=absent
+  changed_when: false
+  failed_when: false
+  delegate_to: "{{ groups['mongodb'][0] }}"
+  run_once: True
diff --git a/ansible/roles/mongodb/tasks/start.yml b/ansible/roles/mongodb/tasks/start.yml
index 40edba8e4e..3926a73168 100644
--- a/ansible/roles/mongodb/tasks/start.yml
+++ b/ansible/roles/mongodb/tasks/start.yml
@@ -11,3 +11,16 @@
       - "/etc/localtime:/etc/localtime:ro"
       - "kolla_logs:/var/log/kolla/"
       - "mongodb:/var/lib/mongodb"
+
+- name: Waiting for the mongodb startup
+  wait_for: host={{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }} port={{ mongodb_port }}
+
+- name: Checking current replication status
+  command: "docker exec -t mongodb mongo {{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }} --quiet --eval rs.status().ok"
+  register: mongodb_replication_status
+  changed_when: false
+  delegate_to: "{{ groups['mongodb'][0] }}"
+  run_once: True
+
+- include: "bootstrap_cluster.yml"
+  when: mongodb_replication_status.stdout != "1"
diff --git a/ansible/roles/mongodb/templates/bootstrap_cluster.js.j2 b/ansible/roles/mongodb/templates/bootstrap_cluster.js.j2
new file mode 100644
index 0000000000..05ea1c655a
--- /dev/null
+++ b/ansible/roles/mongodb/templates/bootstrap_cluster.js.j2
@@ -0,0 +1,14 @@
+printjson(rs.initiate(
+  {
+    "_id" : "{{ mongodb_replication_set_name }}",
+    "version" : 1,
+    "members" : [
+      {% for host in groups["mongodb"] %}
+      {
+        "_id" : {{ loop.index }},
+        "host" : "{{ hostvars[host]['ansible_' + storage_interface]['ipv4']['address'] }}:{{ mongodb_port }}"
+      }{% if not loop.last %},{% endif %}
+      {% endfor %}
+    ]
+  }
+))
diff --git a/ansible/roles/mongodb/templates/mongodb.conf.j2 b/ansible/roles/mongodb/templates/mongodb.conf.j2
index d3863e935e..c5cc8344db 100644
--- a/ansible/roles/mongodb/templates/mongodb.conf.j2
+++ b/ansible/roles/mongodb/templates/mongodb.conf.j2
@@ -1,15 +1,17 @@
-# mongodb.conf
+systemLog:
+  destination: file
+  logAppend: true
+  path: /var/log/kolla/mongodb/mongodb.log
 
-# Where to store the data.
-dbpath = /var/lib/mongodb
+storage:
+  dbPath: /var/lib/mongodb
+  # Enable journaling, http://www.mongodb.org/display/DOCS/Journaling
+  journal:
+    enabled: true
 
-# where to log
-logpath = /var/log/kolla/mongodb/mongodb.log
+net:
+  bindIp: {{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}
+  port: {{ mongodb_port }}
 
-logappend = true
-
-bind_ip = {{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}
-port = {{ mongodb_port }}
-
-# Enable journaling, http://www.mongodb.org/display/DOCS/Journaling
-journal = true
+replication:
+  replSetName: {{ mongodb_replication_set_name }}
diff --git a/releasenotes/notes/implement-mongo-replicate-set-cluster-0d3f140f7116c3ba.yaml b/releasenotes/notes/implement-mongo-replicate-set-cluster-0d3f140f7116c3ba.yaml
new file mode 100644
index 0000000000..14aaa421df
--- /dev/null
+++ b/releasenotes/notes/implement-mongo-replicate-set-cluster-0d3f140f7116c3ba.yaml
@@ -0,0 +1,3 @@
+---
+features:
+  - Implement MongoDB replicate set cluster