From f4ce57c319f95ce4306d9d65b9545361f7f2dfc6 Mon Sep 17 00:00:00 2001 From: Antonio Marsico Date: Thu, 23 Apr 2020 12:06:19 +0200 Subject: [PATCH] Feature 8623 This feature offers a OSM installer to OpenStack by using Ansible Change-Id: I0d609dc227f8968614b4e9a358cb80961b69fb3e Signed-off-by: Antonio Marsico --- installers/full_install_osm.sh | 60 +++++++- installers/install_osm.sh | 2 +- installers/openstack/README.md | 38 +++++ installers/openstack/ansible.cfg | 17 +++ installers/openstack/group_vars/all.yml | 47 ++++++ .../roles/create_instances/tasks/main.yml | 61 ++++++++ .../roles/osm_installation/tasks/main.yml | 63 ++++++++ .../roles/setup_openstack/tasks/main.yml | 139 ++++++++++++++++++ installers/openstack/site.yml | 29 ++++ 9 files changed, 454 insertions(+), 2 deletions(-) create mode 100644 installers/openstack/README.md create mode 100644 installers/openstack/ansible.cfg create mode 100644 installers/openstack/group_vars/all.yml create mode 100644 installers/openstack/roles/create_instances/tasks/main.yml create mode 100644 installers/openstack/roles/osm_installation/tasks/main.yml create mode 100644 installers/openstack/roles/setup_openstack/tasks/main.yml create mode 100644 installers/openstack/site.yml diff --git a/installers/full_install_osm.sh b/installers/full_install_osm.sh index 99999269..aef58835 100755 --- a/installers/full_install_osm.sh +++ b/installers/full_install_osm.sh @@ -38,6 +38,8 @@ function usage(){ echo -e " --pla: install the PLA module for placement support" echo -e " -m : install OSM but only rebuild the specified docker images (LW-UI, NBI, LCM, RO, MON, POL, KAFKA, MONGO, PROMETHEUS, PROMETHEUS-CADVISOR, KEYSTONE-DB, PLA, NONE)" echo -e " -o : ONLY (un)installs one of the addons (vimemu, elk_stack, k8s_monitor)" + echo -e " -O : Install OSM to an OpenStack infrastructure. is required. If a is used, the clouds.yaml file should be under ~/.config/openstack/ or /etc/openstack/" + echo -e " -N : Public network name required to setup OSM to OpenStack" echo -e " -D use local devops installation path" echo -e " -w Location to store runtime installation" echo -e " -t specify osm docker tag (default is latest)" @@ -55,6 +57,7 @@ function usage(){ echo -e " --develop: (deprecated, use '-b master') install OSM from source code using the master branch" echo -e " --pullimages: pull/run osm images from docker.io/opensourcemano" echo -e " --k8s_monitor: install the OSM kubernetes monitoring with prometheus and grafana" + echo -e " --volume: create a VM volume when installing to OpenStack" # echo -e " --reconfigure: reconfigure the modules (DO NOT change NAT rules)" # echo -e " --update: update to the latest stable release or to the latest commit if using a specific branch" echo -e " --showopts: print chosen options and exit (only for debugging)" @@ -1146,6 +1149,36 @@ EOF return 0 } +function install_to_openstack() { + + if [ -z "$2" ]; then + FATAL "OpenStack installer requires a valid external network name" + fi + + # Install Pip for Python3 + $WORKDIR_SUDO apt install -y python3-pip + $WORKDIR_SUDO -H LC_ALL=C python3 -m pip install -U pip + + # Install Ansible, OpenStack client and SDK + $WORKDIR_SUDO -H LC_ALL=C python3 -m pip install -U python-openstackclient "openstacksdk<1" "ansible>=2.9,<3" + + export ANSIBLE_CONFIG="$OSM_DEVOPS/installers/openstack/ansible.cfg" + + OSM_INSTALLER_ARGS="${REPO_ARGS[@]}" + + # Execute the Ansible playbook based on openrc or clouds.yaml + if [ -e "$1" ]; then + . $1 + ansible-playbook -e external_network_name=$2 -e installer_args="\"$OSM_INSTALLER_ARGS\"" \ + -e setup_volume=$3 $OSM_DEVOPS/installers/openstack/site.yml + else + ansible-playbook -e external_network_name=$2 -e installer_args="\"$OSM_INSTALLER_ARGS\"" \ + -e setup_volume=$3 -e cloud_name=$1 $OSM_DEVOPS/installers/openstack/site.yml + fi + + return 0 +} + function install_vimemu() { echo "\nInstalling vim-emu" EMUTEMPDIR="$(mktemp -d -q --tmpdir "installosmvimemu.XXXXXX")" @@ -1204,6 +1237,10 @@ function dump_vars(){ echo "INSTALL_ONLY=$INSTALL_ONLY" echo "INSTALL_ELK=$INSTALL_ELK" #echo "INSTALL_PERFMON=$INSTALL_PERFMON" + echo "INSTALL_TO_OPENSTACK=$INSTALL_TO_OPENSTACK" + echo "OPENSTACK_PUBLIC_NET_NAME=$OPENSTACK_PUBLIC_NET_NAME" + echo "OPENSTACK_OPENRC_FILE_OR_CLOUD=$OPENSTACK_OPENRC_FILE_OR_CLOUD" + echo "OPENSTACK_ATTACH_VOLUME=$OPENSTACK_ATTACH_VOLUME" echo "INSTALL_K8S_MONITOR=$INSTALL_K8S_MONITOR" echo "TO_REBUILD=$TO_REBUILD" echo "INSTALL_NOLXD=$INSTALL_NOLXD" @@ -1261,6 +1298,10 @@ INSTALL_PLA="" LXD_REPOSITORY_BASE="https://osm-download.etsi.org/repository/osm/lxd" LXD_REPOSITORY_PATH="" INSTALL_LIGHTWEIGHT="y" +INSTALL_TO_OPENSTACK="" +OPENSTACK_OPENRC_FILE_OR_CLOUD="" +OPENSTACK_PUBLIC_NET_NAME="" +OPENSTACK_ATTACH_VOLUME="false" INSTALL_ONLY="" INSTALL_ELK="" TO_REBUILD="" @@ -1303,7 +1344,7 @@ POD_NETWORK_CIDR=10.244.0.0/16 K8S_MANIFEST_DIR="/etc/kubernetes/manifests" RE_CHECK='^[a-z0-9]([-a-z0-9]*[a-z0-9])?$' -while getopts ":b:r:c:k:u:R:D:o:m:H:S:s:w:t:U:P:A:l:L:K:-: hy" o; do +while getopts ":b:r:c:k:u:R:D:o:O:m:N:H:S:s:w:t:U:P:A:l:L:K:-: hy" o; do case "${o}" in b) COMMIT_ID=${OPTARG} @@ -1340,6 +1381,18 @@ while getopts ":b:r:c:k:u:R:D:o:m:H:S:s:w:t:U:P:A:l:L:K:-: hy" o; do [ "${OPTARG}" == "elk_stack" ] && INSTALL_ELK="y" && continue [ "${OPTARG}" == "k8s_monitor" ] && INSTALL_K8S_MONITOR="y" && continue ;; + O) + INSTALL_TO_OPENSTACK="y" + if [ -n "${OPTARG}" ]; then + OPENSTACK_OPENRC_FILE_OR_CLOUD="${OPTARG}" + else + echo -e "Invalid argument for -O : ' $OPTARG'\n" >&2 + usage && exit 1 + fi + ;; + N) + OPENSTACK_PUBLIC_NET_NAME="${OPTARG}" + ;; m) [ "${OPTARG}" == "LW-UI" ] && TO_REBUILD="$TO_REBUILD LW-UI" && continue [ "${OPTARG}" == "NBI" ] && TO_REBUILD="$TO_REBUILD NBI" && continue @@ -1372,6 +1425,7 @@ while getopts ":b:r:c:k:u:R:D:o:m:H:S:s:w:t:U:P:A:l:L:K:-: hy" o; do ;; t) OSM_DOCKER_TAG="${OPTARG}" + REPO_ARGS+=(-t "$OSM_DOCKER_TAG") ;; U) DOCKER_USER="${OPTARG}" @@ -1421,6 +1475,7 @@ while getopts ":b:r:c:k:u:R:D:o:m:H:S:s:w:t:U:P:A:l:L:K:-: hy" o; do [ "${OPTARG}" == "ha" ] && continue [ "${OPTARG}" == "tag" ] && continue [ "${OPTARG}" == "pla" ] && INSTALL_PLA="y" && continue + [ "${OPTARG}" == "volume" ] && OPENSTACK_ATTACH_VOLUME="true" && continue echo -e "Invalid option: '--$OPTARG'\n" >&2 usage && exit 1 ;; @@ -1482,6 +1537,9 @@ fi [ -z "$COMMIT_ID" ] && [ -n "$DEVELOP" ] && COMMIT_ID="master" need_packages="git wget curl tar" + +[ -n "$INSTALL_TO_OPENSTACK" ] && install_to_openstack $OPENSTACK_OPENRC_FILE_OR_CLOUD $OPENSTACK_PUBLIC_NET_NAME $OPENSTACK_ATTACH_VOLUME && echo -e "\nDONE" && exit 0 + echo -e "Checking required packages: $need_packages" dpkg -l $need_packages &>/dev/null \ || ! echo -e "One or several required packages are not installed. Updating apt cache requires root privileges." \ diff --git a/installers/install_osm.sh b/installers/install_osm.sh index 36593541..c8f20a64 100755 --- a/installers/install_osm.sh +++ b/installers/install_osm.sh @@ -113,7 +113,7 @@ if [ $? -eq 0 ]; then fi } -while getopts ":b:r:c:k:u:R:l:L:K:p:D:o:m:H:S:s:w:t:U:P:A:-: hy" o; do +while getopts ":b:r:c:k:u:R:l:L:K:p:D:o:O:m:N:H:S:s:w:t:U:P:A:-: hy" o; do case "${o}" in r) REPOSITORY="${OPTARG}" diff --git a/installers/openstack/README.md b/installers/openstack/README.md new file mode 100644 index 00000000..a8e43560 --- /dev/null +++ b/installers/openstack/README.md @@ -0,0 +1,38 @@ + + + +# User guide + +This short guide explains how to use directly the Ansible playbook to install OSM to an OpenStack infrastructure. + +## Prerequisites +The ansible playbook requires `ansible` and `openstacksdk` to be executed. `python-openstackclient` is not mandatory but highly recommended. They are part of Python pip and can be installed as follows: + +`$ sudo -H pip install python-openstackclient "openstacksdk<1" "ansible>=2.9,<3"` + +## Execute the playbook + +In order to execute the playbook, it is required an OpenStack openrc file. It can be downloaded from the OpenStack web interface Horizon. + +After that, it can be loaded with the following command: + +`$ . openrc` + +Then, all the credentials are loaded in the bash environment. Now it is possible to execute the playbook to configure OpenStack and install OSM: + +`$ ansible-playbook -e external_network_name= site.yml` \ No newline at end of file diff --git a/installers/openstack/ansible.cfg b/installers/openstack/ansible.cfg new file mode 100644 index 00000000..b85fcb96 --- /dev/null +++ b/installers/openstack/ansible.cfg @@ -0,0 +1,17 @@ +# Copyright 2020 British Telecommunications plc +# +# 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. +# Author: Antonio Marsico (antonio.marsico@bt.com) + +[defaults] +host_key_checking = False diff --git a/installers/openstack/group_vars/all.yml b/installers/openstack/group_vars/all.yml new file mode 100644 index 00000000..ce0f9c12 --- /dev/null +++ b/installers/openstack/group_vars/all.yml @@ -0,0 +1,47 @@ +--- + +# Copyright 2020 British Telecommunications plc +# +# 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. +# Author: Antonio Marsico (antonio.marsico@bt.com) + +osm_installer_path: /usr/share/osm-devops/installers/install_osm.sh + +prefix: server + +cloud_name: + +setup_volume: false + +external_network_name: + +installer_args: + +os_key_name: ansible-key + +os_flavor: + name: medium-4-cpu-8-gb-40-disk + cpu: 4 + ram: 8192 + disk: 40 + +servers: + - name: osm + user: ubuntu + image: ubuntu1804 + image_url: https://cloud-images.ubuntu.com/bionic/current/bionic-server-cloudimg-amd64.img + flavor: "{{os_flavor.name}}" + key: "{{os_key_name}}" + nics: "net-name={{external_network_name}}" + meta: + group: appservers \ No newline at end of file diff --git a/installers/openstack/roles/create_instances/tasks/main.yml b/installers/openstack/roles/create_instances/tasks/main.yml new file mode 100644 index 00000000..03c0b4c1 --- /dev/null +++ b/installers/openstack/roles/create_instances/tasks/main.yml @@ -0,0 +1,61 @@ +--- +# Copyright 2020 British Telecommunications plc +# +# 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. +# Author: Antonio Marsico (antonio.marsico@bt.com) + +- name: Launch OSM instances + os_server: + cloud: "{{ cloud_name }}" + name: "{{ prefix }}-{{ item.name }}" + state: present + key_name: "{{ item.key }}" + nics: "{{ item.nics }}" + image: "{{ item.image }}" + flavor: "{{ item.flavor }}" + security_groups: + - default + - "{{external_network_name}}_access" + with_items: "{{ servers }}" + register: "os_hosts" + when: setup_volume|bool == False + +- name: Launch OSM instances with a volume + os_server: + cloud: "{{ cloud_name }}" + name: "{{ prefix }}-{{ item.name }}" + state: present + key_name: "{{ item.key }}" + nics: "{{ item.nics }}" + image: "{{ item.image }}" + flavor: "{{ item.flavor }}" + boot_from_volume: yes + terminate_volume: yes + security_groups: + - default + - "{{external_network_name}}_access" + with_items: "{{ servers }}" + register: "os_hosts_with_volume" + when: setup_volume|bool == True + +- set_fact: + os_hosts: "{{ os_hosts_with_volume }}" + when: setup_volume|bool == True + +- name: Add OSM host to the local Ansible inventory + add_host: + name: "{{ item.openstack.accessIPv4 }}" + groups: "{{ item['item']['meta']['group'] }}" + ansible_private_key_file: "~/.ssh/{{ os_key_name }}" + ansible_user: "{{ item['item']['user'] }}" + with_items: "{{ os_hosts.results }}" diff --git a/installers/openstack/roles/osm_installation/tasks/main.yml b/installers/openstack/roles/osm_installation/tasks/main.yml new file mode 100644 index 00000000..c2545741 --- /dev/null +++ b/installers/openstack/roles/osm_installation/tasks/main.yml @@ -0,0 +1,63 @@ +--- +# Copyright 2020 British Telecommunications plc +# +# 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. +# Author: Antonio Marsico (antonio.marsico@bt.com) + +- name: Waiting target connection to become reachable/usable + wait_for_connection: + +- name: Gathering facts + setup: + +- name: Copy OSM installer + copy: + src: "{{ osm_installer_path }}" + dest: install_osm.sh + mode: '744' + +- name: Check OSM reachability + uri: + url: http://localhost + ignore_errors: yes + register: curl_result + +- name: Pre-configure iptables persistent + debconf: name=iptables-persistent question={{ item }} vtype=boolean value=true + become: yes + with_items: + - iptables-persistent/autosave_v4 + - iptables-persistent/autosave_v6 + +- debug: + var: installer_args + verbosity: 2 + +- name: Install and configure OSM (It may require 10 min or more!) + shell: + cmd: ./install_osm.sh -y {{installer_args}} 2>&1 | tee osm_install_log.txt + args: + executable: /bin/bash + register: osm_installation_results + environment: + PATH: "/snap/bin:{{ ansible_env.PATH }}" + when: curl_result is failed + +- debug: + var: osm_installation_results + verbosity: 2 + +- name: Check OSM reachability + uri: + url: http://localhost + register: curl_result diff --git a/installers/openstack/roles/setup_openstack/tasks/main.yml b/installers/openstack/roles/setup_openstack/tasks/main.yml new file mode 100644 index 00000000..8c729dfa --- /dev/null +++ b/installers/openstack/roles/setup_openstack/tasks/main.yml @@ -0,0 +1,139 @@ +--- +# Copyright 2020 British Telecommunications plc +# +# 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. +# Author: Antonio Marsico (antonio.marsico@bt.com) + +- name: Looking for the OpenStack external network + os_networks_info: + cloud: "{{ cloud_name }}" + filters: + name: "{{ external_network_name }}" + register: openstack_external_networks + +- name: Show OpenStack networks + debug: + msg: "{{ openstack_external_networks.openstack_networks }}" + verbosity: 2 + +- name: Gather information about previously created subnets + os_subnets_info: + cloud: "{{ cloud_name }}" + name: "{{ openstack_external_networks.openstack_networks[0].subnets[0] }}" + register: subnet_info + +- name: Show openstack subnets + debug: + msg: "{{ subnet_info.openstack_subnets[0] }}" + verbosity: 2 + +- set_fact: + cidr: "{{ subnet_info.openstack_subnets[0].cidr }}" + +- name: Creating a new openstack flavor + os_nova_flavor: + cloud: "{{ cloud_name }}" + state: present + name: "{{os_flavor.name}}" + ram: "{{os_flavor.ram}}" + vcpus: "{{os_flavor.cpu}}" + disk: "{{os_flavor.disk}}" + +- name: Gather information about OpenStack images + os_image_info: + cloud: "{{ cloud_name }}" + image: "{{ item.image }}" + with_items: "{{ servers }}" + register: image_query + +- name: Show OpenStack image information + debug: + msg: "{{ item.openstack_image }}" + verbosity: 2 + with_items: "{{ image_query.results }}" + when: item.openstack_image != none + +# Missing SHA256 check if we want to update an image + +- name: Downloading images + get_url: + url: "{{item.0.image_url}}" + dest: "/tmp/{{ item.0.image }}.img" + mode: '644' + loop: "{{ servers |product(image_query.results)|list }}" + when: item.1.openstack_image == none and item.0.image == item.1.item.image + +- name: Creating images + os_image: + cloud: "{{ cloud_name }}" + name: "{{ item.0.image }}" + container_format: bare + disk_format: qcow2 + state: present + filename: "/tmp/{{ item.0.image }}.img" + loop: "{{ servers |product(image_query.results)|list }}" + when: item.1.openstack_image == none and item.0.image == item.1.item.image + +- name: Removing tmp image files + file: + path: "/tmp/{{ item.image }}.img" + state: absent + with_items: "{{ servers }}" + +- name: Creating a security group + os_security_group: + cloud: "{{ cloud_name }}" + state: present + name: "{{external_network_name}}_access" + description: Security group for LAN external access + +- name: Creating ICMP rule + os_security_group_rule: + cloud: "{{ cloud_name }}" + security_group: "{{external_network_name}}_access" + protocol: icmp + remote_ip_prefix: 0.0.0.0/0 + +- name: Creating TCP access rule + os_security_group_rule: + cloud: "{{ cloud_name }}" + security_group: "{{external_network_name}}_access" + protocol: tcp + remote_ip_prefix: "{{ cidr }}" + +- name: SSH key check + os_keypair: + cloud: "{{ cloud_name }}" + state: present + name: "{{ os_key_name }}" + register: keypair + +- debug: + var: keypair + verbosity: 2 + +- name: Creating the new ansible key + local_action: + module: copy + content: "{{ keypair.key.public_key }}" + dest: "~/.ssh/{{ keypair.key.name }}.pub" + mode: '600' + when: keypair.key.public_key is not none + +- name: Creating the new ansible private key + local_action: + module: copy + content: "{{ keypair.key.private_key }}" + dest: "~/.ssh/{{ keypair.key.name }}" + mode: '600' + when: keypair.key.private_key is not none \ No newline at end of file diff --git a/installers/openstack/site.yml b/installers/openstack/site.yml new file mode 100644 index 00000000..c1cba50b --- /dev/null +++ b/installers/openstack/site.yml @@ -0,0 +1,29 @@ +--- +# Copyright 2020 British Telecommunications plc +# +# 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. +# Author: Antonio Marsico (antonio.marsico@bt.com) + +- name: Setting up OpenStack and creating a VM for hosting OSM + hosts: localhost + + roles: + - setup_openstack + - create_instances + +- name: Install OSM + hosts: appservers + gather_facts: no + + roles: + - osm_installation -- 2.25.1