Add infrared plugin for OVN migration

This patch adds an ansible playbook and few roles to carry out
the OVN migration (from ml2ovs) as an infrared plugin. Although
the playbook can be used independently.

The goal is to make use of this in CI environments with
infrared/tripleo deployments to test the OVN migration.

Change-Id: I44c36933437abf451e8efa0f9795a58aa62d8dd1
changes/55/576955/8
Numan Siddique 5 years ago
parent c4cbdcd197
commit b49afd3ba5
  1. 33
      migration/infrared/tripleo-ovn-migration/README.rst
  2. 232
      migration/infrared/tripleo-ovn-migration/main.yml
  3. 9
      migration/infrared/tripleo-ovn-migration/roles/create-resources/defaults/main.yml
  4. 31
      migration/infrared/tripleo-ovn-migration/roles/create-resources/tasks/main.yml
  5. 153
      migration/infrared/tripleo-ovn-migration/roles/create-resources/templates/create-resources.sh.j2
  6. 58
      migration/infrared/tripleo-ovn-migration/roles/create-resources/templates/start-pinger.sh.j2
  7. 7
      migration/infrared/tripleo-ovn-migration/roles/prepare-migration/defaults/main.yml
  8. 163
      migration/infrared/tripleo-ovn-migration/roles/prepare-migration/tasks/main.yml
  9. 7
      migration/infrared/tripleo-ovn-migration/templates/start-ovn-migration.sh.j2
  10. 77
      plugin.spec

@ -0,0 +1,33 @@
Infrared plugin to carry out migration from ML2OVS to OVN
=========================================================
This is an infrared plugin which can be used to carry out the migration
from ML2OVS to OVN if the tripleo was deployed using infrared.
See http://infrared.readthedocs.io/en/stable/index.html for more information.
Before using this plugin, first deploy an ML2OVS overcloud and then:
1. On your undercloud, install python-networking-ovn-migration-tool package (https://trunk.rdoproject.org/centos7-master/current/)
You also need to install python-networking-ovn and python2-openvswitch packages.
2. Run ::
$infrared plugin add "https://github.com/openstack/networking-ovn.git"
3. Start migration by running::
$infrared tripleo-ovn-migration --version 13|14 \
--registry-namespace <REGISTRY_NAMESPACE> \
--registry-tag <TAG> \
--registry-prefix <PREFIX>
Using this as a standalone playbook for tripleo deployments
===========================================================
It is also possible to use the playbook main.yml with tripleo deployments.
In order to use this:
1. Create hosts inventory file like below
[undercloud]
undercloud_ip ansible_ssh_user=stack
2. Run the playbook as:
ansible-playbook main.yml -i hosts -e install_from_package=True -e registry_prefix=centos-binary -e registry_namespace=docker.io/tripleomaster -e registry_localnamespace=192.168.24.1:8787/tripleomaster -e registry_tag=current-tripleo-rdo

@ -0,0 +1,232 @@
# Playbook which preps migration and then invokes the migration script.
- name: Install migration tool
hosts: undercloud
become: true
tasks:
- name: Install python virtualenv
yum:
name: python-virtualenv
state: present
- name: Enable delorean deps repository
yum_repository:
name: dlrn-master-deps
description: dlrn-master-deps
baseurl: https://trunk.rdoproject.org/centos7-master/deps/latest/
gpgcheck: no
includepkgs: python2-openvswitch
- name: Enable delorean current repository
yum_repository:
name: dlrn-master
description: dlrn-master
baseurl: https://trunk.rdoproject.org/centos7-master/current/
gpgcheck: no
includepkgs: python-networking-ovn,python-networking-ovn-migration-tool
- name: Install python2 openvswitch
yum:
name: python2-openvswitch
state: present
- name: Install python-networking-ovn
yum:
name: python-networking-ovn
state: present
- name: Install python networking ovn migration tool
yum:
name: python-networking-ovn-migration-tool
state: present
- name: Disable delorean deps repository
yum_repository:
name: dlrn-master-deps
state: absent
- name: Disable delorean repository
yum_repository:
name: dlrn-master
state: absent
- name: Set host_key_checking to False in ansible.cfg
ini_file:
path=/etc/ansible/ansible.cfg
section=defaults
option=host_key_checking
value=False
ignore_errors: yes
- name: Prepare for migration
hosts: undercloud
tasks:
- name: Set ovn migration working dir
set_fact:
ovn_migration_working_dir: /home/stack/ovn_migration
- name: Delete temp file directory if present
file:
state: absent
path: "{{ ovn_migration_working_dir }}"
- name : Create temp file directory if not present
file:
state: directory
path: "{{ ovn_migration_working_dir }}"
- name: Set the docker registry information
block:
- name: Get the docker registry info (infrared deployment)
block:
- name: Set is_infrard deployment
set_fact:
is_infrared: True
- name: Save the docker reg
set_fact:
container_image_prepare:
namespace: "{{ install.get('registry', {}).namespace|default(False)|ternary(install.get('registry', {}).namespace, install.get('registry', {}).mirror + '/' + 'rhosp' + install.version) }}"
prefix: "{{ install.registry.prefix|default('openstack') }}"
tag: "{{ install.registry.tag|default('') }}"
local_namespace: "{{ install.registry.local|default('') }}"
is_dvr: "{{ install.dvr }}"
when:
- install is defined
- name: Get the docker registry info (tripleo deployment)
block:
- name: Set is_infrard deployment
set_fact:
is_infrared: False
- name: Save the docker reg
set_fact:
container_image_prepare:
namespace: "{{ registry_namespace }}"
local_namespace: "{{ registry_localnamespace }}"
prefix: "{{ registry_prefix }}"
tag: "{{ registry_tag }}"
is_dvr: "{{ dvr }}"
when:
- install is not defined
- name: Prepare for migration
include_role:
name: prepare-migration
vars:
infrared_deployment: "{{ is_infrared }}"
registry_namespace: "{{ container_image_prepare['namespace'] }}"
image_prefix: "{{ container_image_prepare['prefix'] }}"
image_tag: "{{ container_image_prepare['tag'] }}"
local_namespace: "{{ container_image_prepare['local_namespace'] }}"
is_dvr: "{{ container_image_prepare['is_dvr'] }}"
- name: Boot few VMs to measure downtime
hosts: undercloud
tasks:
- name: Check if need to create resources
block:
- name: Set create_vms (infrared)
set_fact:
create_vms: "{{ install.create_resources }}"
when:
- install is defined
- name: Set create_vms (tripleo deployment)
set_fact:
create_vms: "{{ create_resources }}"
when:
- install is not defined
- name: Create few resources
block:
- name: Set the public network name (infrared deployment)
set_fact:
public_net: "{{ install.external_network }}"
when: install is defined
- name: Set the public network name (Tripleo deployment)
set_fact:
public_net: "{{ external_network }}"
when: install is not defined
- name: Set the image name (infrared deployment)
set_fact:
image_to_boot: "{{ install.image_name }}"
when: install is defined
- name: Set the image name(Tripleo deployment)
set_fact:
image_to_boot: "{{ image_name }}"
when: install is not defined
- name: Create resources
include_role:
name: create-resources
vars:
public_network_name: "{{ public_net }}"
image_name: "{{ image_to_boot }}"
ovn_migration_temp_dir: /home/stack/ovn_migration
overcloudrc: /home/stack/overcloudrc
when:
- create_vms|bool
- name: Kick start the migration
hosts: undercloud
tasks:
#TODO: Get the working dir from the param
- name: Starting migration block
block:
- name: Set ovn migration working dir
set_fact:
ovn_migration_working_dir: /home/stack/ovn_migration
- name: Copy the playbook files into ovn_migration working dir
shell: cp -rf /usr/share/ansible/networking-ovn-migration/playbooks {{ ovn_migration_working_dir }}
- name: Set the public network name (infrared deployment)
set_fact:
public_network: "{{ install.external_network }}"
when: install is defined
- name: Set the public network name (Tripleo deployment)
set_fact:
public_network: "{{ external_network }}"
when: install is not defined
- name: Create ovn migration script
template:
src: templates/start-ovn-migration.sh.j2
dest: "{{ ovn_migration_working_dir }}/start-ovn-migration.sh"
mode: 0744
- name: Generate inventory file for ovn migration
shell:
set -o pipefail &&
{{ ovn_migration_working_dir }}/start-ovn-migration.sh generate-inventory 2>&1 > {{ ovn_migration_working_dir}}/generate-inventory.log
- name: Set MTU T1
shell:
set -o pipefail &&
{{ ovn_migration_working_dir }}/start-ovn-migration.sh setup-mtu-t1 2>&1 > {{ ovn_migration_working_dir}}/setup-mtu-t1.log
- name: Reduce mtu of the pre migration networks
shell:
set -o pipefail &&
{{ ovn_migration_working_dir }}/start-ovn-migration.sh reduce-mtu 2>&1 > {{ ovn_migration_working_dir}}/reduce-mtu.log
- name: Start the migration process
shell:
set -o pipefail &&
{{ ovn_migration_working_dir }}/start-ovn-migration.sh start-migration 2>&1
> {{ ovn_migration_working_dir}}/start-ovn-migration.sh.log
- name: Stop pinger if started
shell:
echo "exit" > {{ ovn_migration_working_dir}}/_pinger_cmd.txt
always:
- name: Fetch ovn_migration log directory
fetch:
src: "{{ ovn_migration_working_dir }}"
dest: "{{ inventory_dir }}/ovn_migration/"
when: install is defined

@ -0,0 +1,9 @@
---
public_network_name: "{{ public_network_name }}"
create_resource_script: create-resources.sh.j2
ovn_migration_temp_dir: "{{ ovn_migration_temp_dir }}"
image_name: "{{ image_name }}"
server_user_name: "{{ server_user_name }}"
overcloudrc: "{{ overcloudrc }}"
resource_suffix: pinger

@ -0,0 +1,31 @@
- name: Delete temp file directory if present
file:
state: absent
path: "{{ ovn_migration_temp_dir }}"
- name : Create temp file directory if not present
file:
state: directory
path: "{{ ovn_migration_temp_dir }}"
- name: Generate resource creation script
template:
src: create-resources.sh.j2
dest: "{{ ovn_migration_temp_dir }}/create-resources.sh"
mode: 0744
- name: Creating pre pre migration resources
shell: >
set -o pipefail &&
{{ ovn_migration_temp_dir }}/create-resources.sh 2>&1 >
{{ ovn_migration_temp_dir }}/create-resources.sh.log
- name: Generate pinger script
template:
src: start-pinger.sh.j2
dest: "{{ ovn_migration_temp_dir }}/start-pinger.sh"
mode: 0744
- name: Start pinger in background
shell: >
nohup {{ ovn_migration_temp_dir }}/start-pinger.sh </dev/null >/dev/null 2>&1 &

@ -0,0 +1,153 @@
#!/bin/bash
set -x
source {{ overcloudrc }}
image_name={{ image_name }}
openstack image show $image_name
if [ "$?" != "0" ]
then
if [ ! -f cirros-0.4.0-x86_64-disk.img ]
then
curl -o cirros-0.4.0-x86_64-disk.img http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-x86_64-disk.img
fi
openstack image create "cirros-ovn-migration-{{ resource_suffix }}" --file cirros-0.4.0-x86_64-disk.img \
--disk-format qcow2 --container-format bare --public
image_name="cirros-ovn-migration-{{ resource_suffix }}"
fi
openstack flavor create ovn-migration-{{ resource_suffix }} --ram 1024 --disk 1 --vcpus 1
openstack keypair create ovn-migration-{{ resource_suffix }} --private-key {{ ovn_migration_temp_dir }}/ovn_migration_ssh_key
openstack security group create ovn-migration-sg-{{ resource_suffix }}
openstack security group rule create --ingress --protocol icmp ovn-migration-sg-{{ resource_suffix }}
openstack security group rule create --ingress --protocol tcp --dst-port 22 ovn-migration-sg-{{ resource_suffix }}
openstack network create ovn-migration-net-{{ resource_suffix }}
neutron net-update ovn-migration-net-{{ resource_suffix }} --mtu 1442
openstack subnet create --network ovn-migration-net-{{ resource_suffix }} --subnet-range 172.168.168.0/24 ovn-migration-subnet-{{ resource_suffix }}
num_hypervisors=`openstack hypervisor stats show | grep count | awk '{print $4}'`
openstack server create --flavor ovn-migration-{{ resource_suffix }} --image $image_name \
--key-name ovn-migration-{{ resource_suffix }} \
--nic net-id=ovn-migration-net-{{ resource_suffix }} \
--security-group ovn-migration-sg-{{ resource_suffix }} \
--min $num_hypervisors --max $num_hypervisors \
ovn-migration-server-{{ resource_suffix }}
openstack router create ovn-migration-router-{{ resource_suffix }}
openstack router set --external-gateway {{ public_network_name }} ovn-migration-router-{{ resource_suffix }}
openstack router add subnet ovn-migration-router-{{ resource_suffix }} ovn-migration-subnet-{{ resource_suffix }}
for i in $(seq 1 $num_hypervisors)
do
num_attempts=0
while true
do
openstack server show ovn-migration-server-{{ resource_suffix }}-$i -c status | grep ACTIVE
if [ "$?" == "0" ]; then
break
fi
sleep 5
num_attempts=$((num_attempts+1))
if [ $num_attempts -gt 24 ]
then
echo "VM is not up even after 2 minutes. Something is wrong"
exit 1
fi
done
vm_ip=`openstack server show ovn-migration-server-{{ resource_suffix }}-$i -c addresses | grep addresses | awk '{ split($4, ip, "="); print ip[2]}'`
port_id=`openstack port list | grep $vm_ip | awk '{print $2}'`
# Wait till the port is ACTIVE
echo "Wait till the port is ACTIVE"
port_status=`openstack port show $port_id -c status | grep status | awk '{print $4}'`
num_attempts=0
while [ "$port_status" != "ACTIVE" ]
do
num_attempts=$((num_attempts+1))
sleep 5
port_status=`openstack port show $port_id -c status | grep status | awk '{print $4}'`
echo "Port status = $port_status"
if [ $num_attempts -gt 24 ]
then
echo "Port is not up even after 2 minutes. Something is wrong"
exit 1
fi
done
echo "VM is up and the port is ACTIVE"
server_ip=`openstack floating ip create --port $port_id \
{{ public_network_name }} -c floating_ip_address | grep floating_ip_address \
| awk '{print $4'}`
echo $server_ip >> {{ ovn_migration_temp_dir }}/server_fips
# Wait till the VM allows ssh connections
vm_status="down"
num_attempts=0
while [ "$vm_status" != "up" ]
do
num_attempts=$((num_attempts+1))
sleep 5
openstack console log show ovn-migration-server-{{ resource_suffix }}-$i | grep "login:"
if [ "$?" == "0" ]
then
vm_status="up"
else
if [ $num_attempts -gt 60 ]
then
echo "VM is not up with login prompt even after 5 minutes. Something is wrong."
# Even though something seems wrong, lets try and ping.
break
fi
fi
done
done
chmod 0600 {{ ovn_migration_temp_dir }}/ovn_migration_ssh_key
for server_ip in `cat {{ ovn_migration_temp_dir }}/server_fips`
do
num_attempts=0
vm_reachable="false"
while [ "$vm_reachable" != "true" ]
do
num_attempts=$((num_attempts+1))
sleep 1
ping -c 3 $server_ip
if [ "$?" == "0" ]
then
vm_reachable="true"
else
if [ $num_attempts -gt 60 ]
then
echo "VM is not pingable. Something is wrong."
exit 1
fi
fi
done
ssh -i {{ ovn_migration_temp_dir }}/ovn_migration_ssh_key -o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null cirros@$server_ip date
done
echo "Done with the resource creation : exiting"
exit 0

@ -0,0 +1,58 @@
#!/bin/bash
set -x
echo "creating virtualven in {{ ovn_migration_temp_dir }}/pinger_venv"
virtualenv {{ ovn_migration_temp_dir }}/pinger_venv
source {{ ovn_migration_temp_dir }}/pinger_venv/bin/activate
pip install --upgrade pip
pip install sh
cat > {{ ovn_migration_temp_dir }}/pinger.py <<-EOF
import sh
import sys
import time
def main(ips):
run_cmds = []
for ip in ips:
ip_out_file = "{{ ovn_migration_temp_dir }}/" + ip.replace('.', '_') + '_ping.out'
run_cmds.append(sh.ping('-i', '1', ip, _out=ip_out_file, _bg=True))
if not run_cmds:
return
while True:
try:
cmd_file = open("{{ ovn_migration_temp_dir }}/_pinger_cmd.txt", "r")
cmd = cmd_file.readline()
if cmd.startswith("exit"):
break
cmd_file.close()
except IOError:
time.sleep(3)
continue
for p in run_cmds:
p.signal(2)
p.wait()
if __name__ == '__main__':
main(sys.argv[1:])
EOF
pinger_ips=""
for ip in `cat {{ ovn_migration_temp_dir }}/server_fips`
do
pinger_ips="$pinger_ips $ip"
done
echo "pinger ips = $pinger_ips"
echo "calling pinger.py"
python {{ ovn_migration_temp_dir }}/pinger.py $pinger_ips
echo "Exiting..."

@ -0,0 +1,7 @@
---
infrared_deployment: False
registry_namespace: docker.io/tripleomaster
local_namespace: 192.168.24.1:8787/tripleomaster
image_tag: current-tripleo-rdo
image_prefix: centos-binary-

@ -0,0 +1,163 @@
- name: Copy overcloud deploy script to overcloud-deploy-ovn.sh
block:
- name: Check if overcloud_deploy.sh is present or not
stat:
path: ~/overcloud_deploy.sh
register: deploy_file
- name: Set the ml2ovs overcloud deploy script file name
set_fact:
overcloud_deploy_script: '~/overcloud_deploy.sh'
when: deploy_file.stat.exists|bool
- name: Check if overcloud-deploy.sh is present
stat:
path: ~/overcloud-deploy.sh
register: deploy_file_2
when: not deploy_file.stat.exists|bool
- name: Set the ml2ovs overcloud deploy script file name
set_fact:
overcloud_deploy_script: '~/overcloud-deploy.sh'
when:
- not deploy_file.stat.exists|bool
- deploy_file_2.stat.exists|bool
- name: Copy overcloud deploy script to overcloud-deploy-ovn.sh
shell:
cp -f {{ overcloud_deploy_script }} ~/overcloud-deploy-ovn.sh
when: infrared_deployment|bool
- name: set overcloud deploy ovn script
set_fact:
overcloud_deploy_ovn_script: '~/overcloud-deploy-ovn.sh'
- name: Set docker images environment file
set_fact:
output_env_file: /home/stack/docker-images-ovn.yaml
- name: Get the proper neutron-ovn-ha.yaml path
stat:
path: /usr/share/openstack-tripleo-heat-templates/environments/services/neutron-ovn-ha.yaml
register: ovn_env_path
- name: Set the neutron-ovn-dvr-ha.yaml file path if dvr
set_fact:
neutron_ovn_env_path: /usr/share/openstack-tripleo-heat-templates/environments/services/neutron-ovn-dvr-ha.yaml
when: is_dvr|bool
- name: Set the neutron-ovn-ha.yaml file path if not dvr
set_fact:
neutron_ovn_env_path: /usr/share/openstack-tripleo-heat-templates/environments/services/neutron-ovn-ha.yaml
when: not is_dvr|bool
- name: Construct overcloud-deploy-ovn.sh script for infrared deployments
lineinfile:
dest: "{{ overcloud_deploy_ovn_script }}"
line: "{{ item }} \\"
insertbefore: "^--log-file.*"
with_items:
- "-e {{ neutron_ovn_env_path }}"
- "-e /home/stack/ovn-extras.yaml"
- "-e {{ output_env_file }}"
when:
- infrared_deployment|bool
- name: Construct overcloud-deploy-ovn.sh script for tripleo deployments
template:
src: templates/overcloud-deploy-ovn.sh.j2
dest: ~/overcloud-deploy-ovn.sh
mode: 0744
when:
- not infrared_deployment|bool
- name: Set image tag (infrared deployment)
block:
- name: Get puddle version
shell: cat ~/core_puddle_version
ignore_error: True
register: core_puddle_version
- name: Set image tag from puddle version
set_fact:
docker_image_tag: "{{ (core_puddle_version.stdout != '') | ternary(core_puddle_version.stdout, image_tag) }}"
- debug:
msg: "{{ core_puddle_version.stdout }}"
- debug:
msg: "{{ docker_image_tag }}"
when: infrared_deployment|bool
- name: Set image tag (tripleo deployment)
set_fact:
docker_image_tag: "{{ image_tag }}"
when:
- not infrared_deployment|bool
- name: Generate ovn container images
shell: |
echo "container_images:" > ~/ovn_container_images.yaml
- name: Add ovn container images to ovn_container_images.yaml
lineinfile:
dest: ~/ovn_container_images.yaml
line: "- imagename: {{ registry_namespace }}/{{ image_prefix }}-{{ item }}:{{ docker_image_tag }}"
with_items:
- "ovn-northd"
- "ovn-controller"
- "neutron-server-ovn"
- "neutron-metadata-agent-ovn"
- name: Set the local namespace
block:
- name: Extract the local namespace
shell: |
set -exo pipefail
source ~/stackrc
openstack overcloud plan export overcloud
mkdir -p /tmp/oc_plan
mv overcloud.tar.gz /tmp/oc_plan/
cd /tmp/oc_plan
tar xvf overcloud.tar.gz
reg=`cat /tmp/oc_plan/plan-environment.yaml | grep DockerNeutronApiImage | awk '{ split($2, image , "/"); print image[1] }'`
namespace=`cat /tmp/oc_plan/plan-environment.yaml | grep DockerNeutronApiImage | awk '{ split($2, image , "/"); print image[2] }'`
img=`cat plan-environment.yaml | grep DockerNeutronApiImage | awk '{ split($2, image, "/"); print image[3] }'`
echo $reg/$namespace > /tmp/_reg_namespace
rm -rf /tmp/oc_plan
- name: Get the local namespace
shell: cat /tmp/_reg_namespace
register: local_ns
- name: Set the local registry
set_fact:
local_registry: "{{ local_ns.stdout }}"
when:
- local_namespace == ''
- name: Set the local namespace
set_fact:
local_registry: "{{ local_namespace }}"
when:
- local_namespace != ''
- name: Generate docker images environment file
shell: |
set -exo pipefail
openstack overcloud container image prepare \
--namespace={{ local_registry }} \
--tag={{ docker_image_tag }} \
--prefix={{ image_prefix }} \
--output-env-file={{ output_env_file }} \
-e /usr/share/openstack-tripleo-heat-templates/environments/docker.yaml \
-e /usr/share/openstack-tripleo-heat-templates/environments/docker-ha.yaml \
-e {{ neutron_ovn_env_path }}
- name: Upload the ovn docker images to the local registry
shell: |
source ~/stackrc
openstack overcloud container image upload --verbose --config-file ~/ovn_container_images.yaml

@ -0,0 +1,7 @@
#!/bin/bash
export PUBLIC_NETWORK_NAME={{ public_network }}
# TODO: Get this from the var
export OPT_WORKDIR=/home/stack/ovn_migration
/usr/bin/ovn_migration.sh $1

@ -0,0 +1,77 @@
---
config:
entry_point: ./migration/infrared/tripleo-ovn-migration/main.yml
plugin_type: install
subparsers:
tripleo-ovn-migration:
description: Migrate an existing TripleO overcloud from Neutron ML2OVS plugin to OVN
include_groups: ["Ansible options", "Inventory", "Common options", "Answers file"]
groups:
- title: Containers
options:
registry-namespace:
type: Value
help: The alternative docker registry namespace to use for deployment.
registry-prefix:
type: Value
help: The images prefix
registry-tag:
type: Value
help: The images tag
registry-mirror:
type: Value
help: The alternative docker registry to use for deployment.
- title: Deployment Description
options:
version:
type: Value
help: |
The product version
Numbers are for OSP releases
Names are for RDO releases
If not given, same version of the undercloud will be used
choices:
- "7"
- "8"
- "9"
- "10"
- "11"
- "12"
- "13"
- "14"
- kilo
- liberty
- mitaka
- newton
- ocata
- pike
- queens
- rocky
install_from_package:
type: Bool
help: Install python-networking-ovn-migration-tool rpm
default: True
dvr:
type: Bool
help: If the deployment is to be dvr or not
default: False
create_resources:
type: Bool
help: Create resources to measure downtime
default: True
external_network:
type: Value
help: External network name to use
default: public
image_name:
type: Value
help: Image name to use
default: cirros-0.3.5-x86_64-disk.img
Loading…
Cancel
Save