From ac5d5217fc7b40bdd2371f7f0f2caa4d734568bb Mon Sep 17 00:00:00 2001
From: Duong Ha-Quang <duonghq@vn.fujitsu.com>
Date: Wed, 7 Dec 2016 15:22:35 +0700
Subject: [PATCH] Apply Neutron rolling upgrade logic

This patchset implements Neutron rolling upgrade logic as described
in [1].

Due to only neutron, vpnass and fwaas have supported for rolling upgrade
database migration, so I used the list "neutron_rolling_upgrade_services"
in neutron/default/main.yml for contain there services.

[1] https://docs.openstack.org/neutron/latest/contributor/internals/upgrade.html

Co-author: Ha Manh Dong <donghm@vn.fujitsu.com>
Change-Id: I2ed2f941d30d4df0d0f42c0d10e7ca03ec1c166a
Implements: blueprint apply-service-upgrade-procedure
---
 ansible/roles/neutron/defaults/main.yml       |  6 ++
 .../roles/neutron/tasks/bootstrap_service.yml |  2 +
 .../roles/neutron/tasks/legacy_upgrade.yml    | 12 +++
 .../roles/neutron/tasks/rolling_upgrade.yml   | 91 +++++++++++++++++++
 ansible/roles/neutron/tasks/upgrade.yml       | 15 +--
 etc/kolla/globals.yml                         |  9 +-
 ...tron-rolling-upgrade-a7b3124eab7adfa2.yaml |  6 ++
 7 files changed, 129 insertions(+), 12 deletions(-)
 create mode 100644 ansible/roles/neutron/tasks/legacy_upgrade.yml
 create mode 100644 ansible/roles/neutron/tasks/rolling_upgrade.yml
 create mode 100644 releasenotes/notes/implement-neutron-rolling-upgrade-a7b3124eab7adfa2.yaml

diff --git a/ansible/roles/neutron/defaults/main.yml b/ansible/roles/neutron/defaults/main.yml
index eba7335bba..c8a9118a39 100644
--- a/ansible/roles/neutron/defaults/main.yml
+++ b/ansible/roles/neutron/defaults/main.yml
@@ -312,6 +312,12 @@ extension_drivers:
 
 neutron_extension_drivers: "{{ extension_drivers|selectattr('enabled', 'equalto', true)|list }}"
 
+####################
+# Neutron upgrade
+####################
+neutron_enable_rolling_upgrade: "yes"
+neutron_rolling_upgrade_services: ["neutron", "neutron-fwaas", "neutron-vpnaas"]
+
 ####################
 # Service Plugins
 ####################
diff --git a/ansible/roles/neutron/tasks/bootstrap_service.yml b/ansible/roles/neutron/tasks/bootstrap_service.yml
index df738e70ab..70ad81e4c2 100644
--- a/ansible/roles/neutron/tasks/bootstrap_service.yml
+++ b/ansible/roles/neutron/tasks/bootstrap_service.yml
@@ -18,6 +18,8 @@
     volumes: "{{ neutron_server.volumes }}"
   run_once: True
   delegate_to: "{{ groups[neutron_server.group][0] }}"
+  when: (kolla_action == "deploy")
+        or (not neutron_enable_rolling_upgrade | bool)
 
 - name: Running Neutron lbaas bootstrap container
   vars:
diff --git a/ansible/roles/neutron/tasks/legacy_upgrade.yml b/ansible/roles/neutron/tasks/legacy_upgrade.yml
new file mode 100644
index 0000000000..403a613dca
--- /dev/null
+++ b/ansible/roles/neutron/tasks/legacy_upgrade.yml
@@ -0,0 +1,12 @@
+---
+- include_tasks: config.yml
+
+- include_tasks: config-neutron-fake.yml
+  when:
+    - inventory_hostname in groups['compute']
+    - enable_nova_fake | bool
+
+- include_tasks: bootstrap_service.yml
+
+- name: Flush Handlers
+  meta: flush_handlers
diff --git a/ansible/roles/neutron/tasks/rolling_upgrade.yml b/ansible/roles/neutron/tasks/rolling_upgrade.yml
new file mode 100644
index 0000000000..f826c6a9bb
--- /dev/null
+++ b/ansible/roles/neutron/tasks/rolling_upgrade.yml
@@ -0,0 +1,91 @@
+---
+- include_tasks: pull.yml
+
+- include_tasks: config.yml
+
+- include_tasks: config-neutron-fake.yml
+  when:
+    - inventory_hostname in groups['compute']
+    - enable_nova_fake | bool
+
+- name: Running Neutron database expand container
+  vars:
+    neutron_server: "{{ neutron_services['neutron-server'] }}"
+  kolla_docker:
+    action: "start_container"
+    common_options: "{{ docker_common_options }}"
+    detach: False
+    environment:
+      KOLLA_UPGRADE:
+      NEUTRON_DB_EXPAND:
+      KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
+      NEUTRON_ROLLING_UPGRADE_SERVICES: "{{ neutron_rolling_upgrade_services }}"
+    image: "{{ neutron_server.image }}"
+    labels:
+      UPGRADE:
+    name: "bootstrap_neutron"
+    restart_policy: "never"
+    volumes: "{{ neutron_server.volumes }}"
+  run_once: True
+  delegate_to: "{{ groups['neutron-server'][0] }}"
+
+- include_tasks: bootstrap_service.yml
+  vars:
+    neutron_lbaas_agent: "{{ neutron_services['neutron-lbaas-agent'] }}"
+    neutron_server: "{{ neutron_services['neutron-server'] }}"
+  when: (neutron_lbaas_agent.enabled | bool)
+        or (enable_neutron_sfc | bool and neutron_server.enabled | bool)
+
+- name: Flush Handlers
+  meta: flush_handlers
+
+- name: Checking neutron pending contract scripts
+  become: true
+  command: "docker exec -t neutron_server neutron-db-manage --subproject {{ item }} has_offline_migrations"
+  register: neutron_check_contract_db_stdout
+  ignore_errors: yes
+  with_items: "{{ neutron_rolling_upgrade_services }}"
+  when: inventory_hostname == groups['neutron-server'][0]
+
+- name: Stopping all neutron-server for contract db
+  vars:
+    neutron_server: "{{ neutron_services['neutron-server'] }}"
+    first_neutron_server_host: "{{ groups[neutron_server.group][0] }}"
+    results_of_check_pending_contract_scripts: "{{ hostvars[first_neutron_server_host]['neutron_check_contract_db_stdout'] }}"
+    filter_rc: "results[?rc!=`0`]"
+    is_stop_neutron_server: "{{ results_of_check_pending_contract_scripts | json_query(filter_rc) }}"
+  become: true
+  kolla_docker:
+    action: "stop_container"
+    common_options: "{{ docker_common_options }}"
+    name: "{{ neutron_server.container_name }}"
+  when:
+    - is_stop_neutron_server|length > 0
+    - neutron_server.host_in_groups | bool
+  notify:
+    - "Restart neutron-server container"
+
+- name: Running Neutron database contract container
+  vars:
+    neutron_server: "{{ neutron_services['neutron-server'] }}"
+  kolla_docker:
+    action: "start_container"
+    common_options: "{{ docker_common_options }}"
+    detach: False
+    environment:
+      KOLLA_UPGRADE:
+      NEUTRON_DB_CONTRACT:
+      KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
+      NEUTRON_ROLLING_UPGRADE_SERVICES: "{{ neutron_rolling_upgrade_services }}"
+    image: "{{ neutron_server.image }}"
+    labels:
+      UPGRADE:
+    name: "bootstrap_neutron"
+    restart_policy: "never"
+    volumes: "{{ neutron_server.volumes }}"
+  run_once: True
+  delegate_to: "{{ groups['neutron-server'][0] }}"
+
+# Flush handlers here to ensure neutron-server containers are started
+- name: Flush Handlers
+  meta: flush_handlers
diff --git a/ansible/roles/neutron/tasks/upgrade.yml b/ansible/roles/neutron/tasks/upgrade.yml
index 5585421b66..9e9355b7da 100644
--- a/ansible/roles/neutron/tasks/upgrade.yml
+++ b/ansible/roles/neutron/tasks/upgrade.yml
@@ -1,13 +1,6 @@
 ---
-- include_tasks: config.yml
+- include_tasks: rolling_upgrade.yml
+  when: neutron_enable_rolling_upgrade | bool
 
-- include_tasks: config-neutron-fake.yml
-  when:
-    - inventory_hostname in groups['compute']
-    - enable_nova_fake | bool
-
-- include_tasks: bootstrap_service.yml
-  when: inventory_hostname in groups['neutron-server']
-
-- name: Flush Handlers
-  meta: flush_handlers
+- include_tasks: legacy_upgrade.yml
+  when: not neutron_enable_rolling_upgrade | bool
diff --git a/etc/kolla/globals.yml b/etc/kolla/globals.yml
index 382235e5b9..8244143758 100644
--- a/etc/kolla/globals.yml
+++ b/etc/kolla/globals.yml
@@ -107,6 +107,13 @@ kolla_internal_vip_address: "10.10.10.254"
 # Valid options are [ internal, infoblox ]
 #neutron_ipam_driver: "internal"
 
+# Configure Neutron upgrade option, currently Kolla support
+# two upgrade ways for Neutron: legacy_upgrade and rolling_upgrade
+# The variable "neutron_enable_rolling_upgrade: yes" is meaning rolling_upgrade
+# were enabled and opposite
+# Neutron rolling upgrade were enable by default
+#neutron_enable_rolling_upgrade: "yes"
+
 
 ####################
 # keepalived options
@@ -444,7 +451,7 @@ ironic_dnsmasq_dhcp_range:
 
 # Configure ironic upgrade option, due to currently kolla support
 # two upgrade ways for ironic: legacy_upgrade and rolling_upgrade
-# The variable "ironic_enable_rolling_upgrade: yes" is meaning legacy_upgrade
+# The variable "ironic_enable_rolling_upgrade: yes" is meaning rolling_upgrade
 # were enabled and opposite
 # Rolling upgrade were enable by default
 #ironic_enable_rolling_upgrade: "yes"
diff --git a/releasenotes/notes/implement-neutron-rolling-upgrade-a7b3124eab7adfa2.yaml b/releasenotes/notes/implement-neutron-rolling-upgrade-a7b3124eab7adfa2.yaml
new file mode 100644
index 0000000000..6f911c0c4e
--- /dev/null
+++ b/releasenotes/notes/implement-neutron-rolling-upgrade-a7b3124eab7adfa2.yaml
@@ -0,0 +1,6 @@
+---
+features:
+  - |
+    Implement Neutron rolling upgrade logic, apply for: neutron,
+    vpnaas and fwaas because only these projects have supported for
+    rolling upgrade database migration.