summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--INFO.yaml59
-rw-r--r--apex/build_utils.py15
-rw-r--r--apex/builders/common_builder.py117
-rw-r--r--apex/builders/overcloud_builder.py68
-rw-r--r--apex/builders/undercloud_builder.py73
-rw-r--r--apex/clean.py8
-rw-r--r--apex/common/constants.py37
-rw-r--r--apex/common/exceptions.py12
-rw-r--r--apex/common/utils.py63
-rw-r--r--apex/deploy.py436
-rw-r--r--apex/deployment/__init__.py0
-rw-r--r--apex/deployment/snapshot.py241
-rw-r--r--apex/deployment/tripleo.py60
-rw-r--r--apex/inventory/inventory.py7
-rw-r--r--apex/network/jumphost.py8
-rw-r--r--apex/network/network_data.py2
-rw-r--r--apex/network/network_environment.py9
-rw-r--r--apex/overcloud/deploy.py273
-rw-r--r--apex/overcloud/node.py147
-rw-r--r--apex/settings/deploy_settings.py8
-rw-r--r--apex/tests/config/98faaca.diff2
-rw-r--r--apex/tests/config/admin.xml7
-rw-r--r--apex/tests/config/baremetal0.xml73
-rw-r--r--apex/tests/config/common-patches.yaml6
-rw-r--r--apex/tests/config/dummy-deploy-settings.yaml19
-rw-r--r--apex/tests/config/inventory-virt-1-compute-node.yaml14
-rw-r--r--apex/tests/config/node.yaml12
-rw-r--r--apex/tests/config/snapshot.properties2
-rw-r--r--apex/tests/test_apex_build_utils.py6
-rw-r--r--apex/tests/test_apex_common_builder.py69
-rw-r--r--apex/tests/test_apex_common_utils.py16
-rw-r--r--apex/tests/test_apex_deploy.py117
-rw-r--r--apex/tests/test_apex_deployment_snapshot.py374
-rw-r--r--apex/tests/test_apex_deployment_tripleo.py49
-rw-r--r--apex/tests/test_apex_inventory.py7
-rw-r--r--apex/tests/test_apex_network_environment.py7
-rw-r--r--apex/tests/test_apex_overcloud_builder.py2
-rw-r--r--apex/tests/test_apex_overcloud_deploy.py417
-rw-r--r--apex/tests/test_apex_overcloud_node.py191
-rw-r--r--apex/tests/test_apex_undercloud.py25
-rw-r--r--apex/undercloud/undercloud.py49
-rwxr-xr-xapex/virtual/configure_vm.py9
-rw-r--r--build/ansible.cfg11
-rw-r--r--build/build_ovs_nsh.sh20
-rw-r--r--build/containers-prepare-parameter.yaml26
-rw-r--r--build/csit-environment.yaml29
-rw-r--r--build/csit-queens-environment.yaml29
-rw-r--r--build/csit-rocky-environment.yaml116
-rw-r--r--build/kubernetes-environment.yaml26
-rw-r--r--build/network-environment.yaml22
-rw-r--r--build/nics-template.yaml.jinja2130
-rw-r--r--build/patches/neutron-patch-NSDriver.patch2
-rw-r--r--build/rpm_specs/opnfv-apex.spec31
-rw-r--r--build/upstream-environment.yaml8
-rwxr-xr-xci/util.sh2
-rw-r--r--config/deploy/common-patches.yaml45
-rw-r--r--config/deploy/deploy_settings.yaml5
-rw-r--r--config/deploy/k8s-nosdn-nofeature-noha.yaml16
-rw-r--r--config/deploy/os-nosdn-calipso-noha.yaml1
-rw-r--r--config/deploy/os-nosdn-calipso_rocky-noha.yaml (renamed from config/deploy/os-ovn-nofeature-noha.yaml)7
-rw-r--r--config/deploy/os-nosdn-nofeature-ha.yaml5
-rw-r--r--config/deploy/os-nosdn-nofeature-noha.yaml5
-rw-r--r--config/deploy/os-nosdn-rocky-ha.yaml (renamed from config/deploy/os-nosdn-queens-ha.yaml)2
-rw-r--r--config/deploy/os-nosdn-rocky-noha.yaml (renamed from config/deploy/os-nosdn-queens-noha.yaml)2
-rw-r--r--config/deploy/os-odl-bgpvpn-ha.yaml6
-rw-r--r--config/deploy/os-odl-bgpvpn-noha.yaml6
-rw-r--r--config/deploy/os-odl-bgpvpn_rocky-ha.yaml13
-rw-r--r--config/deploy/os-odl-bgpvpn_rocky-noha.yaml13
-rw-r--r--config/deploy/os-odl-nofeature-ha.yaml5
-rw-r--r--config/deploy/os-odl-nofeature-noha.yaml4
-rw-r--r--config/deploy/os-odl-queens-ha.yaml1
-rw-r--r--config/deploy/os-odl-queens-noha.yaml5
-rw-r--r--config/deploy/os-odl-rocky-ha.yaml13
-rw-r--r--config/deploy/os-odl-rocky-noha.yaml13
-rw-r--r--config/deploy/os-odl-sfc-ha.yaml8
-rw-r--r--config/deploy/os-odl-sfc-noha.yaml8
-rw-r--r--config/deploy/os-odl-sfc_rocky-ha.yaml13
-rw-r--r--config/deploy/os-odl-sfc_rocky-noha.yaml13
-rw-r--r--config/deploy/os-ovn-nofeature-ha.yaml15
-rw-r--r--config/deploy/os-ovn-rocky-ha.yaml17
-rw-r--r--config/network/network_settings.yaml8
-rw-r--r--config/network/network_settings_csit.yaml6
-rw-r--r--config/network/network_settings_tenant_vlan.yaml333
-rw-r--r--config/network/network_settings_v6.yaml10
-rw-r--r--contrib/aarch64/overcloud-full-rootfs.yaml54
-rw-r--r--contrib/aarch64/undercloud-full.yaml87
-rw-r--r--docs/conf.py1
-rw-r--r--docs/conf.yaml3
-rw-r--r--docs/contributor/APEX-on-aarch64.rst146
-rw-r--r--docs/index.rst23
-rw-r--r--docs/release/installation/abstract.rst6
-rw-r--r--docs/release/installation/architecture.rst17
-rw-r--r--docs/release/installation/baremetal.rst48
-rw-r--r--docs/release/installation/index.rst2
-rw-r--r--docs/release/installation/introduction.rst27
-rw-r--r--docs/release/installation/references.rst2
-rw-r--r--docs/release/installation/requirements.rst4
-rw-r--r--docs/release/installation/upstream.rst40
-rw-r--r--docs/release/installation/virtual.rst91
-rw-r--r--docs/release/release-notes/release-notes.rst51
-rw-r--r--docs/release/scenarios/k8s-nosdn-nofeature-noha/index.rst (renamed from docs/release/scenarios/os-nosdn-performance-ha/index.rst)10
-rw-r--r--docs/release/scenarios/k8s-nosdn-nofeature-noha/k8s-nosdn-nofeature-noha.rst46
-rw-r--r--docs/release/scenarios/os-nosdn-nofeature-ha/os-nosdn-nofeature-ha.rst8
-rw-r--r--docs/release/scenarios/os-nosdn-nofeature-noha/os-nosdn-nofeature-noha.rst8
-rw-r--r--docs/release/scenarios/os-nosdn-performance-ha/os-nosdn-performance-ha.rst54
-rw-r--r--docs/release/scenarios/os-odl-nofeature-ha/os-odl-nofeature-ha.rst14
-rw-r--r--docs/release/scenarios/os-odl-nofeature-noha/os-odl-nofeature-noha.rst14
-rw-r--r--docs/release/scenarios/os-ovn-nofeature-ha/index.rst (renamed from docs/release/scenarios/os-ovn-nofeature-noha/index.rst)4
-rw-r--r--docs/release/scenarios/os-ovn-nofeature-ha/os-ovn-nofeature-ha.rst (renamed from docs/release/scenarios/os-ovn-nofeature-noha/os-ovn-nofeature-noha.rst)11
-rw-r--r--docs/requirements.txt2
-rw-r--r--lib/ansible/playbooks/configure_undercloud.yml100
-rw-r--r--lib/ansible/playbooks/deploy_dependencies.yml33
-rw-r--r--lib/ansible/playbooks/deploy_overcloud.yml55
-rw-r--r--lib/ansible/playbooks/k8s_remove_pkgs.yml5
-rw-r--r--lib/ansible/playbooks/patch_containers.yml13
-rw-r--r--lib/ansible/playbooks/post_deploy_overcloud.yml50
-rw-r--r--lib/ansible/playbooks/post_deploy_undercloud.yml38
-rw-r--r--lib/ansible/playbooks/prepare_overcloud_containers.yml77
-rw-r--r--lib/ansible/playbooks/undercloud_aarch64.yml38
-rw-r--r--requirements.txt2
-rw-r--r--setup.cfg5
-rw-r--r--tox.ini14
123 files changed, 4520 insertions, 853 deletions
diff --git a/.gitignore b/.gitignore
index 2789a249..6bc2461f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,13 @@
*~
*.pyc
-/docs_build/
/docs_output/
/releng/
+venv/
apex.egg-info/
coverage.xml
nosetests.xml
.*
*.log
*.retry
+.tox
+docs/_build/*
diff --git a/INFO.yaml b/INFO.yaml
new file mode 100644
index 00000000..eaa700cf
--- /dev/null
+++ b/INFO.yaml
@@ -0,0 +1,59 @@
+---
+project: 'Apex'
+project_creation_date: 'July 14, 2015'
+project_category: 'Integration & Testing'
+lifecycle_state: 'Incubation'
+project_lead: &opnfv_apex_ptl
+ name: 'Tim Rozet'
+ email: 'trozet@redhat.com'
+ id: 'trozet'
+ company: 'redhat.com'
+ timezone: 'USA/East Coast'
+primary_contact: *opnfv_apex_ptl
+issue_tracking:
+ type: 'jira'
+ url: 'https://jira.opnfv.org/projects/APEX'
+ key: 'APEX'
+mailing_list:
+ type: 'mailman2'
+ url: 'opnfv-tech-discuss@lists.opnfv.org'
+ tag: '[apex]'
+realtime_discussion:
+ type: irc
+ server: 'freenode.net'
+ channel: '#opnfv-apex'
+meetings:
+ - type: 'gotomeeting+irc'
+ agenda: 'https://wiki.opnfv.org/display/apex'
+ url: 'http://bluejeans.com/trozet'
+ server: 'freenode.net'
+ channel: '#opnfv-apex'
+ repeats: 'weekly'
+ time: '15:00 UTC'
+repositories:
+ - 'apex'
+ - 'apex-os-net-config'
+ - 'apex-puppet-tripleo'
+ - 'apex-tripleo-heat-templates'
+committers:
+ - <<: *opnfv_apex_ptl
+ - name: 'Dan Radez'
+ email: 'dradez@redhat.com'
+ company: 'redhat.com'
+ id: 'radez'
+ - name: 'Michael Chapman'
+ email: 'michapma@redhat.com'
+ company: 'redhat.com'
+ id: 'michapma'
+ - name: 'Feng Pan'
+ email: 'fpan@redhat.com'
+ company: 'redhat.com'
+ id: 'fpan'
+ - name: 'Ricardo Noriega'
+ email: 'rnoriega@redhat.com'
+ company: 'redhat.com'
+ id: 'rnoriega'
+tsc:
+ # yamllint disable rule:line-length
+ approval: 'http//ircbot.wl.linuxfoundation.org/meetings/opnfv-meeting/2015/opnfv-meeting.2015-07-14-14.00.html'
+ # yamllint enable rule:line-length
diff --git a/apex/build_utils.py b/apex/build_utils.py
index 213ae115..7457e561 100644
--- a/apex/build_utils.py
+++ b/apex/build_utils.py
@@ -86,7 +86,7 @@ def clone_fork(args):
logging.info('Checked out commit:\n{}'.format(ws.head.commit.message))
-def strip_patch_sections(patch, sections=['releasenotes']):
+def strip_patch_sections(patch, sections=['releasenotes', 'tests']):
"""
Removes patch sections from a diff which contain a file path
:param patch: patch to strip
@@ -111,6 +111,19 @@ def strip_patch_sections(patch, sections=['releasenotes']):
return '\n'.join(tmp_patch)
+def is_path_in_patch(patch, path):
+ """
+ Checks if a particular path is modified in a patch diff
+ :param patch: patch diff
+ :param path: path to check for in diff
+ :return: Boolean
+ """
+ for line in patch.split("\n"):
+ if re.match('^diff.*{}'.format(path), line):
+ return True
+ return False
+
+
def get_patch(change_id, repo, branch, url=con.OPENSTACK_GERRIT):
logging.info("Fetching patch for change id {}".format(change_id))
change = get_change(url, repo, branch, change_id)
diff --git a/apex/builders/common_builder.py b/apex/builders/common_builder.py
index 10fab9b6..59af94cd 100644
--- a/apex/builders/common_builder.py
+++ b/apex/builders/common_builder.py
@@ -14,8 +14,11 @@ import git
import json
import logging
import os
+import platform
+import pprint
import re
import urllib.parse
+import yaml
import apex.builders.overcloud_builder as oc_builder
from apex import build_utils
@@ -25,10 +28,11 @@ from apex.common import utils
from apex.virtual import utils as virt_utils
-def project_to_path(project):
+def project_to_path(project, patch=None):
"""
Translates project to absolute file path to use in patching
:param project: name of project
+ :param patch: the patch to applied to the project
:return: File path
"""
if project.startswith('openstack/'):
@@ -37,6 +41,15 @@ def project_to_path(project):
return "/etc/puppet/modules/{}".format(project.replace('puppet-', ''))
elif 'tripleo-heat-templates' in project:
return "/usr/share/openstack-tripleo-heat-templates"
+ elif ('tripleo-common' in project and
+ build_utils.is_path_in_patch(patch, 'container-images/')):
+ # tripleo-common has python and another component to it
+ # here we detect if there is a change to the yaml component and if so
+ # treat it like it is not python. This has the caveat of if there
+ # is a patch to both python and yaml this will not work
+ # FIXME(trozet): add ability to split tripleo-common patches that
+ # modify both python and yaml
+ return "/usr/share/openstack-tripleo-common-containers/"
else:
# assume python. python patches will apply to a project name subdir.
# For example, python-tripleoclient patch will apply to the
@@ -46,17 +59,19 @@ def project_to_path(project):
return "/usr/lib/python2.7/site-packages/"
-def project_to_docker_image(project):
+def project_to_docker_image(project, docker_url):
"""
Translates OpenStack project to OOO services that are containerized
- :param project: name of OpenStack project
+ :param project: short name of OpenStack project
:return: List of OOO docker service names
"""
# Fetch all docker containers in docker hub with tripleo and filter
# based on project
-
+ logging.info("Checking for docker images matching project: {}".format(
+ project))
hub_output = utils.open_webpage(
- urllib.parse.urljoin(con.DOCKERHUB_OOO, '?page_size=1024'), timeout=10)
+ urllib.parse.urljoin(docker_url,
+ '?page_size=1024'), timeout=10)
try:
results = json.loads(hub_output.decode())['results']
except Exception as e:
@@ -71,12 +86,14 @@ def project_to_docker_image(project):
for result in results:
if result['name'].startswith("centos-binary-{}".format(project)):
# add as docker image shortname (just service name)
+ logging.debug("Adding docker image {} for project {} for "
+ "patching".format(result['name'], project))
docker_images.append(result['name'].replace('centos-binary-', ''))
return docker_images
-def is_patch_promoted(change, branch, docker_image=None):
+def is_patch_promoted(change, branch, docker_url, docker_image=None):
"""
Checks to see if a patch that is in merged exists in either the docker
container or the promoted tripleo images
@@ -109,8 +126,8 @@ def is_patch_promoted(change, branch, docker_image=None):
return True
else:
# must be a docker patch, check docker tag modified time
- docker_url = con.DOCKERHUB_OOO.replace('tripleomaster',
- "tripleo{}".format(branch))
+ docker_url = docker_url.replace('tripleomaster',
+ "tripleo{}".format(branch))
url_path = "{}/tags/{}".format(docker_image, con.DOCKER_TAG)
docker_url = urllib.parse.urljoin(docker_url, url_path)
logging.debug("docker url is: {}".format(docker_url))
@@ -157,16 +174,29 @@ def add_upstream_patches(patches, image, tmp_dir,
branch = default_branch
patch_diff = build_utils.get_patch(patch['change-id'],
patch['project'], branch)
- project_path = project_to_path(patch['project'])
+ project_path = project_to_path(patch['project'], patch_diff)
# If docker tag and python we know this patch belongs on docker
# container for a docker service. Therefore we build the dockerfile
# and move the patch into the containers directory. We also assume
# this builder call is for overcloud, because we do not support
# undercloud containers
+ if platform.machine() == 'aarch64':
+ docker_url = con.DOCKERHUB_AARCH64
+ else:
+ docker_url = con.DOCKERHUB_OOO
if docker_tag and 'python' in project_path:
# Projects map to multiple THT services, need to check which
# are supported
- ooo_docker_services = project_to_docker_image(patch['project'])
+ project_short_name = os.path.basename(patch['project'])
+ ooo_docker_services = project_to_docker_image(project_short_name,
+ docker_url)
+ if not ooo_docker_services:
+ logging.error("Did not find any matching docker containers "
+ "for project: {}".format(project_short_name))
+ raise exc.ApexCommonBuilderException(
+ 'Unable to find docker services for python project in '
+ 'patch')
+ # Just use the first image to see if patch was promoted into it
docker_img = ooo_docker_services[0]
else:
ooo_docker_services = []
@@ -175,29 +205,44 @@ def add_upstream_patches(patches, image, tmp_dir,
patch['project'], branch,
patch['change-id'])
patch_promoted = is_patch_promoted(change,
- branch.replace('/stable', ''),
+ branch.replace('stable/', ''),
+ docker_url,
docker_img)
if patch_diff and not patch_promoted:
patch_file = "{}.patch".format(patch['change-id'])
+ patch_file_paths = []
# If we found services, then we treat the patch like it applies to
# docker only
if ooo_docker_services:
os_version = default_branch.replace('stable/', '')
for service in ooo_docker_services:
docker_services = docker_services.union({service})
+ # We need to go root to be able to install patch and then
+ # switch back to previous user. Some containers that
+ # have the same name as the project do not necessarily
+ # contain the project code. For example
+ # novajoin-notifier does not contain nova package code.
+ # Therefore we must try to patch and unfortunately
+ # ignore failures until we have a better way of checking
+ # this
docker_cmds = [
"WORKDIR {}".format(project_path),
+ "USER root",
+ "ARG REAL_USER",
+ "RUN yum -y install patch",
"ADD {} {}".format(patch_file, project_path),
- "RUN patch -p1 < {}".format(patch_file)
+ "RUN patch -p1 < {} || echo "
+ "'Patching failed'".format(patch_file),
+ "USER $REAL_USER"
]
src_img_uri = "{}:8787/tripleo{}/centos-binary-{}:" \
"{}".format(uc_ip, os_version, service,
docker_tag)
oc_builder.build_dockerfile(service, tmp_dir, docker_cmds,
src_img_uri)
- patch_file_path = os.path.join(tmp_dir, 'containers',
- patch_file)
+ patch_file_paths.append(os.path.join(
+ tmp_dir, "containers/{}".format(service), patch_file))
else:
patch_file_path = os.path.join(tmp_dir, patch_file)
virt_ops.extend([
@@ -207,8 +252,10 @@ def add_upstream_patches(patches, image, tmp_dir,
project_path, patch_file)}])
logging.info("Adding patch {} to {}".format(patch_file,
image))
- with open(patch_file_path, 'w') as fh:
- fh.write(patch_diff)
+ patch_file_paths.append(patch_file_path)
+ for patch_fp in patch_file_paths:
+ with open(patch_fp, 'w') as fh:
+ fh.write(patch_diff)
else:
logging.info("Ignoring patch:\n{}".format(patch))
if len(virt_ops) > 1:
@@ -248,3 +295,41 @@ def create_git_archive(repo_url, repo_name, tmp_dir,
repo.archive(fh, prefix=prefix)
logging.debug("Wrote archive file: {}".format(archive_path))
return archive_path
+
+
+def get_neutron_driver(ds_opts):
+ sdn = ds_opts.get('sdn_controller', None)
+
+ if sdn == 'opendaylight':
+ return 'odl'
+ elif sdn == 'ovn':
+ return sdn
+ elif ds_opts.get('vpp', False):
+ return 'vpp'
+ else:
+ return None
+
+
+def prepare_container_images(prep_file, branch='master', neutron_driver=None):
+ if not os.path.isfile(prep_file):
+ raise exc.ApexCommonBuilderException("Prep file does not exist: "
+ "{}".format(prep_file))
+ with open(prep_file) as fh:
+ data = yaml.safe_load(fh)
+ try:
+ p_set = data['parameter_defaults']['ContainerImagePrepare'][0]['set']
+ if neutron_driver:
+ p_set['neutron_driver'] = neutron_driver
+ p_set['namespace'] = "docker.io/tripleo{}".format(branch)
+ if platform.machine() == 'aarch64':
+ p_set['namespace'] = "docker.io/armbandapex"
+ p_set['ceph_tag'] = 'v3.1.0-stable-3.1-luminous-centos-7-aarch64'
+
+ except KeyError:
+ logging.error("Invalid prep file format: {}".format(prep_file))
+ raise exc.ApexCommonBuilderException("Invalid format for prep file")
+
+ logging.debug("Writing new container prep file:\n{}".format(
+ pprint.pformat(data)))
+ with open(prep_file, 'w') as fh:
+ yaml.safe_dump(data, fh, default_flow_style=False)
diff --git a/apex/builders/overcloud_builder.py b/apex/builders/overcloud_builder.py
index d2a31001..eab8fb66 100644
--- a/apex/builders/overcloud_builder.py
+++ b/apex/builders/overcloud_builder.py
@@ -15,6 +15,7 @@ import tarfile
import apex.builders.common_builder
from apex.common import constants as con
+from apex.common import utils as utils
from apex.common.exceptions import ApexBuildException
from apex.virtual import utils as virt_utils
@@ -24,7 +25,12 @@ def inject_opendaylight(odl_version, image, tmp_dir, uc_ip,
assert odl_version in con.VALID_ODL_VERSIONS
# add repo
if odl_version == 'master':
+ # last version in the constants is "master" so select 2nd to last
+ # odl package version has no "master" version
odl_pkg_version = con.VALID_ODL_VERSIONS[-2]
+ # branch will be used to pull puppet-opendaylight. Since puppet-odl
+ # does not pull branch until later, we need to use master version of
+ # that if master ODL version is specified
branch = odl_version
else:
odl_pkg_version = odl_version
@@ -42,7 +48,8 @@ def inject_opendaylight(odl_version, image, tmp_dir, uc_ip,
{con.VIRT_UPLOAD: "{}:/etc/puppet/modules/".format(archive)},
{con.VIRT_RUN_CMD: 'rm -rf /etc/puppet/modules/opendaylight'},
{con.VIRT_RUN_CMD: "cd /etc/puppet/modules/ && tar xvf "
- "puppet-opendaylight.tar"}
+ "puppet-opendaylight.tar"},
+ {con.VIRT_INSTALL: "java-1.8.0-openjdk"}
]
if docker_tag:
docker_cmds = [
@@ -63,6 +70,65 @@ def inject_opendaylight(odl_version, image, tmp_dir, uc_ip,
logging.info("OpenDaylight injected into {}".format(image))
+def inject_quagga(image, tmp_dir):
+ """
+ Downloads quagga tarball from artifacts.opnfv.org
+ and install it on the overcloud image on the fly.
+ :param image:
+ :param tmp_dir:
+ :return:
+ """
+ utils.fetch_upstream_and_unpack(tmp_dir,
+ os.path.split(con.QUAGGA_URL)[0] + "/",
+ [os.path.basename(con.QUAGGA_URL)])
+
+ virt_ops = [
+ {con.VIRT_UPLOAD: "{}/quagga-4.tar.gz:/root/".format(tmp_dir)},
+ {con.VIRT_RUN_CMD: "cd /root/ && tar xzf quagga-4.tar.gz"},
+ {con.VIRT_RUN_CMD: "cd /root/quagga;packages=$(ls |grep -vE 'debug"
+ "info|devel|contrib');yum -y install $packages"}
+ ]
+ virt_utils.virt_customize(virt_ops, image)
+ logging.info("Quagga injected into {}".format(image))
+
+
+def inject_ovs_nsh(image, tmp_dir):
+ """
+ Downloads OpenVswitch, compiles it and installs it on the
+ overcloud image on the fly.
+ :param image:
+ :param tmp_dir:
+ :return:
+ """
+ ovs_filename = os.path.basename(con.OVS_URL)
+ ovs_folder = ovs_filename.replace(".tar.gz", "")
+ utils.fetch_upstream_and_unpack(tmp_dir,
+ os.path.split(con.OVS_URL)[0] + "/",
+ [ovs_filename])
+ (ovs_dist_name, ovs_version) = ovs_folder.split("-")
+
+ virt_ops = [
+ {con.VIRT_UPLOAD: "{}:/root/".format(tmp_dir + "/" + ovs_filename)},
+ {con.VIRT_INSTALL: "rpm-build,autoconf,automake,libtool,openssl,"
+ "openssl-devel,python,python-twisted-core,python-six,groff,graphviz,"
+ "python-zope-interface,desktop-file-utils,procps-ng,PyQt4,"
+ "libcap-ng,libcap-ng-devel,selinux-policy-devel,kernel-devel,"
+ "kernel-headers,kernel-tools,rpmdevtools,systemd-units,python-devel,"
+ "python-sphinx"},
+ {con.VIRT_RUN_CMD: "cd /root/ && tar xzf {}".format(ovs_filename)},
+ {con.VIRT_UPLOAD:
+ "{}/build_ovs_nsh.sh:/root/{}".format(tmp_dir, ovs_folder)},
+ {con.VIRT_RUN_CMD:
+ "cd /root/{0} && chmod -R 777 * && chown -R root:root * && "
+ "./build_ovs_nsh.sh && rpm -Uhv --force rpm/rpmbuild/RPMS/x86_64/{0}"
+ "-1.el7.x86_64.rpm && rpm -Uhv --force rpm/rpmbuild/RPMS/x86_64"
+ "/openvswitch-kmod-{1}-1.el7.x86_64.rpm".format(ovs_folder,
+ ovs_version)}
+ ]
+ virt_utils.virt_customize(virt_ops, image)
+ logging.info("OVS injected into {}".format(image))
+
+
def build_dockerfile(service, tmp_dir, docker_cmds, src_image_uri):
"""
Builds docker file per service and stores it in a
diff --git a/apex/builders/undercloud_builder.py b/apex/builders/undercloud_builder.py
index f82e79d1..47d2568d 100644
--- a/apex/builders/undercloud_builder.py
+++ b/apex/builders/undercloud_builder.py
@@ -8,8 +8,13 @@
##############################################################################
# Used to modify undercloud qcow2 image
+import logging
+import json
+import os
+import subprocess
from apex.common import constants as con
+from apex.common import utils
from apex.virtual import utils as virt_utils
@@ -21,20 +26,82 @@ def add_upstream_packages(image):
"""
virt_ops = list()
pkgs = [
+ 'epel-release',
'openstack-utils',
- 'ceph-common',
'python2-networking-sfc',
'openstack-ironic-inspector',
'subunit-filters',
'docker-distribution',
'openstack-tripleo-validations',
'libguestfs-tools',
- 'ceph-ansible',
- 'python-tripleoclient'
+ 'python-tripleoclient',
+ 'openstack-tripleo-heat-templates'
]
+ # Remove incompatible python-docker version
+ virt_ops.append({con.VIRT_RUN_CMD: "yum remove -y python-docker-py"})
for pkg in pkgs:
virt_ops.append({con.VIRT_INSTALL: pkg})
virt_utils.virt_customize(virt_ops, image)
+
+def inject_calipso_installer(tmp_dir, image):
+ """
+ Downloads calipso installer script from artifacts.opnfv.org
+ and puts it under /root/ for further installation process.
+ :return:
+ """
+ calipso_file = os.path.basename(con.CALIPSO_INSTALLER_URL)
+ calipso_url = con.CALIPSO_INSTALLER_URL.replace(calipso_file, '')
+ utils.fetch_upstream_and_unpack(tmp_dir, calipso_url, [calipso_file])
+
+ virt_ops = [
+ {con.VIRT_UPLOAD: "{}/{}:/root/".format(tmp_dir, calipso_file)}]
+ virt_utils.virt_customize(virt_ops, image)
+ logging.info("Calipso injected into {}".format(image))
+
+# TODO(trozet): add unit testing for calipso injector
# TODO(trozet): add rest of build for undercloud here as well
+
+
+def update_repos(image, branch):
+ virt_ops = [
+ {con.VIRT_RUN_CMD: "rm -f /etc/yum.repos.d/delorean*"},
+ {con.VIRT_RUN_CMD: "yum-config-manager --add-repo "
+ "https://trunk.rdoproject.org/centos7/{}"
+ "/delorean.repo".format(con.RDO_TAG)},
+ {con.VIRT_RUN_CMD: "yum clean all"},
+ {con.VIRT_INSTALL: "python2-tripleo-repos"},
+ {con.VIRT_RUN_CMD: "tripleo-repos -b {} {} ceph".format(branch,
+ con.RDO_TAG)}
+ ]
+ virt_utils.virt_customize(virt_ops, image)
+
+
+def expand_disk(image, desired_size=50):
+ """
+ Expands a disk image to desired_size in GigaBytes
+ :param image: image to resize
+ :param desired_size: desired size in GB
+ :return: None
+ """
+ # there is a lib called vminspect which has some dependencies and is
+ # not yet available in pip. Consider switching to this lib later.
+ try:
+ img_out = json.loads(subprocess.check_output(
+ ['qemu-img', 'info', '--output=json', image],
+ stderr=subprocess.STDOUT).decode())
+ disk_gb_size = int(img_out['virtual-size'] / 1000000000)
+ if disk_gb_size < desired_size:
+ logging.info("Expanding disk image: {}. Current size: {} is less"
+ "than require size: {}".format(image, disk_gb_size,
+ desired_size))
+ diff_size = desired_size - disk_gb_size
+ subprocess.check_call(['qemu-img', 'resize', image,
+ "+{}G".format(diff_size)],
+ stderr=subprocess.STDOUT)
+
+ except (subprocess.CalledProcessError, json.JSONDecodeError, KeyError) \
+ as e:
+ logging.warning("Unable to resize disk, disk may not be large "
+ "enough: {}".format(e))
diff --git a/apex/clean.py b/apex/clean.py
index f56287e1..3e33c8e4 100644
--- a/apex/clean.py
+++ b/apex/clean.py
@@ -114,7 +114,13 @@ def clean_networks():
logging.debug("Destroying virsh network: {}".format(network))
if virsh_net.isActive():
virsh_net.destroy()
- virsh_net.undefine()
+ try:
+ virsh_net.undefine()
+ except libvirt.libvirtError as e:
+ if 'Network not found' in e.get_error_message():
+ logging.debug('Network already undefined')
+ else:
+ raise
def main():
diff --git a/apex/common/constants.py b/apex/common/constants.py
index 89c3e6e1..59988f74 100644
--- a/apex/common/constants.py
+++ b/apex/common/constants.py
@@ -39,34 +39,43 @@ VIRT_PW = '--root-password'
THT_DIR = '/usr/share/openstack-tripleo-heat-templates'
THT_ENV_DIR = os.path.join(THT_DIR, 'environments')
-THT_DOCKER_ENV_DIR = {
- 'master': os.path.join(THT_ENV_DIR, 'services'),
- 'queens': os.path.join(THT_ENV_DIR, 'services-docker')
-}
+THT_DOCKER_ENV_DIR = os.path.join(THT_ENV_DIR, 'services')
DEFAULT_OS_VERSION = 'master'
DEFAULT_ODL_VERSION = 'oxygen'
-VALID_ODL_VERSIONS = ['carbon', 'nitrogen', 'oxygen', 'master']
-CEPH_VERSION_MAP = {'pike': 'jewel',
- 'queens': 'luminous',
- 'master': 'luminous'}
+VALID_ODL_VERSIONS = ['carbon', 'nitrogen', 'oxygen', 'fluorine',
+ 'neon', 'master']
PUPPET_ODL_URL = 'https://git.opendaylight.org/gerrit/integration/packaging' \
'/puppet-opendaylight'
DEBUG_OVERCLOUD_PW = 'opnfvapex'
NET_ENV_FILE = 'network-environment.yaml'
-DEPLOY_TIMEOUT = 90
-UPSTREAM_RDO = 'https://images.rdoproject.org/master/delorean/current' \
- '-tripleo-rdo/'
-OPENSTACK_GERRIT = 'https://review.openstack.org'
+DEPLOY_TIMEOUT = 120
+RDO_TAG = 'current-tripleo'
+UPSTREAM_RDO = "https://images.rdoproject.org/master/rdo_trunk/{}/".format(
+ RDO_TAG)
+OPENSTACK_GERRIT = 'https://review.opendev.org'
-DOCKER_TAG = 'current-tripleo-rdo'
+DOCKER_TAG = RDO_TAG
# Maps regular service files to docker versions
# None value means mapping is same as key
VALID_DOCKER_SERVICES = {
'neutron-opendaylight.yaml': None,
'neutron-opendaylight-dpdk.yaml': None,
'neutron-opendaylight-sriov.yaml': None,
- 'neutron-ml2-ovn.yaml': 'neutron-ovn.yaml'
+ 'neutron-bgpvpn-opendaylight.yaml': None,
+ 'neutron-sfc-opendaylight.yaml': None,
+ 'neutron-ml2-ovn.yaml': 'neutron-ovn-ha.yaml'
}
DOCKERHUB_OOO = 'https://registry.hub.docker.com/v2/repositories' \
'/tripleomaster/'
+DOCKERHUB_AARCH64 = 'https://registry.hub.docker.com/v2/repositories' \
+ '/armbandapex/'
+KUBESPRAY_URL = 'https://github.com/kubernetes-incubator/kubespray.git'
+OPNFV_ARTIFACTS = 'http://storage.googleapis.com/artifacts.opnfv.org'
+CUSTOM_OVS = '{}/apex/random/openvswitch-2.9.0-9.el7fdn.x86_64.' \
+ 'rpm'.format(OPNFV_ARTIFACTS)
+
+OVS_URL = "http://openvswitch.org/releases/openvswitch-2.9.2.tar.gz"
+QUAGGA_URL = "{}/sdnvpn/quagga/quagga-4.tar.gz".format(OPNFV_ARTIFACTS)
+CALIPSO_INSTALLER_URL = "https://raw.githubusercontent.com/opnfv/calipso" \
+ "/master/app/install/calipso-installer.py"
diff --git a/apex/common/exceptions.py b/apex/common/exceptions.py
index a4d390a4..6d8383b8 100644
--- a/apex/common/exceptions.py
+++ b/apex/common/exceptions.py
@@ -22,3 +22,15 @@ class ApexCleanException(Exception):
class ApexBuildException(Exception):
pass
+
+
+class SnapshotDeployException(Exception):
+ pass
+
+
+class OvercloudNodeException(Exception):
+ pass
+
+
+class FetchException(Exception):
+ pass
diff --git a/apex/common/utils.py b/apex/common/utils.py
index 2ac900a3..72a66d10 100644
--- a/apex/common/utils.py
+++ b/apex/common/utils.py
@@ -75,12 +75,17 @@ def run_ansible(ansible_vars, playbook, host='localhost', user='root',
Executes ansible playbook and checks for errors
:param ansible_vars: dictionary of variables to inject into ansible run
:param playbook: playbook to execute
+ :param host: inventory file or string of target hosts
+ :param user: remote user to run ansible tasks
:param tmp_dir: temp directory to store ansible command
:param dry_run: Do not actually apply changes
:return: None
"""
logging.info("Executing ansible playbook: {}".format(playbook))
- inv_host = "{},".format(host)
+ if not os.path.isfile(host):
+ inv_host = "{},".format(host)
+ else:
+ inv_host = host
if host == 'localhost':
conn_type = 'local'
else:
@@ -213,7 +218,7 @@ def fetch_upstream_and_unpack(dest, url, targets, fetch=True):
if download_target:
urllib.request.urlretrieve(target_url, filename=target_dest)
logging.info("Target downloaded: {}".format(target))
- if target.endswith('.tar'):
+ if target.endswith(('.tar', 'tar.gz', 'tgz')):
logging.info('Unpacking tar file')
tar = tarfile.open(target_dest)
tar.extractall(path=dest)
@@ -250,9 +255,9 @@ def open_webpage(url, timeout=5):
try:
response = urllib.request.urlopen(url, timeout=timeout)
return response.read()
- except (urllib.request.URLError, socket.timeout):
+ except (urllib.request.URLError, socket.timeout) as e:
logging.error("Unable to open URL: {}".format(url))
- raise
+ raise exc.FetchException('Unable to open URL') from e
def edit_tht_env(env_file, section, settings):
@@ -267,3 +272,53 @@ def edit_tht_env(env_file, section, settings):
with open(env_file, 'w') as fh:
yaml.safe_dump(data, fh, default_flow_style=False)
logging.debug("Data written to env file {}:\n{}".format(env_file, data))
+
+
+def unique(tmp_list):
+ assert isinstance(tmp_list, list)
+ uniq_list = []
+ for x in tmp_list:
+ if x not in uniq_list:
+ uniq_list.append(x)
+ return uniq_list
+
+
+def bash_settings_to_dict(data):
+ """
+ Parses bash settings x=y and returns dict of key, values
+ :param data: bash settings data in x=y format
+ :return: dict of keys and values
+ """
+ return dict(item.split('=') for item in data.splitlines())
+
+
+def fetch_properties(url):
+ """
+ Downloads OPNFV properties and returns a dictionary of the key, values
+ :param url: URL of properties file
+ :return: dict of k,v for each properties
+ """
+ if bool(urllib.parse.urlparse(url).scheme):
+ logging.debug('Fetching properties from internet: {}'.format(url))
+ return bash_settings_to_dict(open_webpage(url).decode('utf-8'))
+ elif os.path.isfile(url):
+ logging.debug('Fetching properties from file: {}'.format(url))
+ with open(url, 'r') as fh:
+ data = fh.read()
+ return bash_settings_to_dict(data)
+ else:
+ logging.warning('Unable to fetch properties for: {}'.format(url))
+ raise exc.FetchException('Unable determine properties location: '
+ '{}'.format(url))
+
+
+def find_container_client(os_version):
+ """
+ Determines whether to use docker or podman client
+ :param os_version: openstack version
+ :return: client name as string
+ """
+ if os_version == 'rocky' or os_version == 'queens':
+ return 'docker'
+ else:
+ return 'podman'
diff --git a/apex/deploy.py b/apex/deploy.py
index cbecee8b..d0c2b208 100644
--- a/apex/deploy.py
+++ b/apex/deploy.py
@@ -10,6 +10,7 @@
##############################################################################
import argparse
+import git
import json
import logging
import os
@@ -18,6 +19,7 @@ import pprint
import shutil
import sys
import tempfile
+import yaml
import apex.virtual.configure_vm as vm_lib
import apex.virtual.utils as virt_utils
@@ -28,10 +30,12 @@ from apex import DeploySettings
from apex import Inventory
from apex import NetworkEnvironment
from apex import NetworkSettings
+from apex.deployment.snapshot import SnapshotDeployment
from apex.common import utils
from apex.common import constants
from apex.common import parsers
from apex.common.exceptions import ApexDeployException
+from apex.deployment.tripleo import ApexDeployment
from apex.network import jumphost
from apex.network import network_data
from apex.undercloud import undercloud as uc_lib
@@ -40,11 +44,12 @@ from apex.overcloud import deploy as oc_deploy
APEX_TEMP_DIR = tempfile.mkdtemp(prefix='apex_tmp')
SDN_IMAGE = 'overcloud-full-opendaylight.qcow2'
-
-
-def deploy_quickstart(args, deploy_settings_file, network_settings_file,
- inventory_file=None):
- pass
+UC_DISK_FILES = [
+ 'overcloud-full.vmlinuz',
+ 'overcloud-full.initrd',
+ 'ironic-python-agent.initramfs',
+ 'ironic-python-agent.kernel'
+]
def validate_cross_settings(deploy_settings, net_settings, inventory):
@@ -112,7 +117,7 @@ def create_deploy_parser():
help='File which contains Apex deploy settings')
deploy_parser.add_argument('-n', '--network-settings',
dest='network_settings_file',
- required=True,
+ required=False,
help='File which contains Apex network '
'settings')
deploy_parser.add_argument('-i', '--inventory-file',
@@ -173,17 +178,29 @@ def create_deploy_parser():
default='/usr/share/opnfv-apex',
help='Directory path for apex ansible '
'and third party libs')
- deploy_parser.add_argument('--quickstart', action='store_true',
+ deploy_parser.add_argument('-s', '--snapshot', action='store_true',
default=False,
- help='Use tripleo-quickstart to deploy')
+ help='Use snapshots for deployment')
+ deploy_parser.add_argument('--snap-cache', dest='snap_cache',
+ default="{}/snap_cache".format(
+ os.path.expanduser('~')),
+ help='Local directory to cache snapshot '
+ 'artifacts. Defaults to $HOME/snap_cache')
deploy_parser.add_argument('--upstream', action='store_true',
- default=False,
+ default=True,
help='Force deployment to use upstream '
- 'artifacts')
+ 'artifacts. This option is now '
+ 'deprecated and only upstream '
+ 'deployments are supported.')
deploy_parser.add_argument('--no-fetch', action='store_true',
default=False,
help='Ignore fetching latest upstream and '
'use what is in cache')
+ deploy_parser.add_argument('-p', '--patches',
+ default='/etc/opnfv-apex/common-patches.yaml',
+ dest='patches_file',
+ help='File to include for common patches '
+ 'which apply to all deployment scenarios')
return deploy_parser
@@ -195,20 +212,25 @@ def validate_deploy_args(args):
"""
logging.debug('Validating arguments for deployment')
- if args.virtual and args.inventory_file is not None:
+ if args.snapshot:
+ logging.debug('Skipping inventory validation as it is not applicable'
+ 'to snapshot deployments')
+ elif args.virtual and args.inventory_file is not None:
logging.error("Virtual enabled but inventory file also given")
raise ApexDeployException('You should not specify an inventory file '
'with virtual deployments')
elif args.virtual:
args.inventory_file = os.path.join(APEX_TEMP_DIR,
'inventory-virt.yaml')
- elif os.path.isfile(args.inventory_file) is False:
+ elif not os.path.isfile(args.inventory_file):
logging.error("Specified inventory file does not exist: {}".format(
args.inventory_file))
raise ApexDeployException('Specified inventory file does not exist')
for settings_file in (args.deploy_settings_file,
args.network_settings_file):
+ if settings_file == args.network_settings_file and args.snapshot:
+ continue
if os.path.isfile(settings_file) is False:
logging.error("Specified settings file does not "
"exist: {}".format(settings_file))
@@ -242,74 +264,94 @@ def main():
# Parse all settings
deploy_settings = DeploySettings(args.deploy_settings_file)
logging.info("Deploy settings are:\n {}".format(pprint.pformat(
- deploy_settings)))
- net_settings = NetworkSettings(args.network_settings_file)
- logging.info("Network settings are:\n {}".format(pprint.pformat(
- net_settings)))
- os_version = deploy_settings['deploy_options']['os_version']
- net_env_file = os.path.join(args.deploy_dir, constants.NET_ENV_FILE)
- net_env = NetworkEnvironment(net_settings, net_env_file,
- os_version=os_version)
- net_env_target = os.path.join(APEX_TEMP_DIR, constants.NET_ENV_FILE)
- utils.dump_yaml(dict(net_env), net_env_target)
-
- # get global deploy params
- ha_enabled = deploy_settings['global_params']['ha_enabled']
- introspect = deploy_settings['global_params'].get('introspect', True)
-
- if args.virtual:
- if args.virt_compute_ram is None:
- compute_ram = args.virt_default_ram
- else:
- compute_ram = args.virt_compute_ram
- if deploy_settings['deploy_options']['sdn_controller'] == \
- 'opendaylight' and args.virt_default_ram < 12:
- control_ram = 12
- logging.warning('RAM per controller is too low. OpenDaylight '
- 'requires at least 12GB per controller.')
- logging.info('Increasing RAM per controller to 12GB')
- elif args.virt_default_ram < 10:
- control_ram = 10
- logging.warning('RAM per controller is too low. nosdn '
- 'requires at least 10GB per controller.')
- logging.info('Increasing RAM per controller to 10GB')
- else:
- control_ram = args.virt_default_ram
- if ha_enabled and args.virt_compute_nodes < 2:
- logging.debug('HA enabled, bumping number of compute nodes to 2')
- args.virt_compute_nodes = 2
- virt_utils.generate_inventory(args.inventory_file, ha_enabled,
- num_computes=args.virt_compute_nodes,
- controller_ram=control_ram * 1024,
- compute_ram=compute_ram * 1024,
- vcpus=args.virt_cpus
- )
- inventory = Inventory(args.inventory_file, ha_enabled, args.virtual)
-
- validate_cross_settings(deploy_settings, net_settings, inventory)
+ deploy_settings)))
+
+ if not args.snapshot:
+ net_settings = NetworkSettings(args.network_settings_file)
+ logging.info("Network settings are:\n {}".format(pprint.pformat(
+ net_settings)))
+ os_version = deploy_settings['deploy_options']['os_version']
+ net_env_file = os.path.join(args.deploy_dir, constants.NET_ENV_FILE)
+ net_env = NetworkEnvironment(net_settings, net_env_file,
+ os_version=os_version)
+ net_env_target = os.path.join(APEX_TEMP_DIR, constants.NET_ENV_FILE)
+ utils.dump_yaml(dict(net_env), net_env_target)
+
+ # get global deploy params
+ ha_enabled = deploy_settings['global_params']['ha_enabled']
+ introspect = deploy_settings['global_params'].get('introspect', True)
+ net_list = net_settings.enabled_network_list
+ if args.virtual:
+ if args.virt_compute_ram is None:
+ compute_ram = args.virt_default_ram
+ else:
+ compute_ram = args.virt_compute_ram
+ if (deploy_settings['deploy_options']['sdn_controller'] ==
+ 'opendaylight' and args.virt_default_ram < 12):
+ control_ram = 12
+ logging.warning('RAM per controller is too low. OpenDaylight '
+ 'requires at least 12GB per controller.')
+ logging.info('Increasing RAM per controller to 12GB')
+ elif args.virt_default_ram < 10:
+ if platform.machine() == 'aarch64':
+ control_ram = 16
+ logging.warning('RAM per controller is too low for '
+ 'aarch64 ')
+ logging.info('Increasing RAM per controller to 16GB')
+ else:
+ control_ram = 10
+ logging.warning('RAM per controller is too low. nosdn '
+ 'requires at least 10GB per controller.')
+ logging.info('Increasing RAM per controller to 10GB')
+ else:
+ control_ram = args.virt_default_ram
+ if platform.machine() == 'aarch64' and args.virt_cpus < 16:
+ vcpus = 16
+ logging.warning('aarch64 requires at least 16 vCPUS per '
+ 'target VM. Increasing to 16.')
+ else:
+ vcpus = args.virt_cpus
+ if ha_enabled and args.virt_compute_nodes < 2:
+ logging.debug(
+ 'HA enabled, bumping number of compute nodes to 2')
+ args.virt_compute_nodes = 2
+ virt_utils.generate_inventory(args.inventory_file, ha_enabled,
+ num_computes=args.virt_compute_nodes,
+ controller_ram=control_ram * 1024,
+ compute_ram=compute_ram * 1024,
+ vcpus=vcpus
+ )
+ inventory = Inventory(args.inventory_file, ha_enabled, args.virtual)
+ logging.info("Inventory is:\n {}".format(pprint.pformat(
+ inventory)))
+
+ validate_cross_settings(deploy_settings, net_settings, inventory)
+ else:
+ # only one network with snapshots
+ net_list = [constants.ADMIN_NETWORK]
+
ds_opts = deploy_settings['deploy_options']
- if args.quickstart:
- deploy_settings_file = os.path.join(APEX_TEMP_DIR,
- 'apex_deploy_settings.yaml')
- utils.dump_yaml(utils.dict_objects_to_str(deploy_settings),
- deploy_settings_file)
- logging.info("File created: {}".format(deploy_settings_file))
- network_settings_file = os.path.join(APEX_TEMP_DIR,
- 'apex_network_settings.yaml')
- utils.dump_yaml(utils.dict_objects_to_str(net_settings),
- network_settings_file)
- logging.info("File created: {}".format(network_settings_file))
- deploy_quickstart(args, deploy_settings_file, network_settings_file,
- args.inventory_file)
+ ansible_args = {
+ 'virsh_enabled_networks': net_list,
+ 'snapshot': args.snapshot
+ }
+ utils.run_ansible(ansible_args,
+ os.path.join(args.lib_dir, constants.ANSIBLE_PATH,
+ 'deploy_dependencies.yml'))
+ all_in_one = not bool(args.virt_compute_nodes)
+ if args.snapshot:
+ # Start snapshot Deployment
+ logging.info('Executing Snapshot Deployment...')
+ SnapshotDeployment(deploy_settings=deploy_settings,
+ snap_cache_dir=args.snap_cache,
+ fetch=not args.no_fetch,
+ all_in_one=all_in_one)
else:
+ # Start Standard TripleO Deployment
+ deployment = ApexDeployment(deploy_settings, args.patches_file,
+ args.deploy_settings_file)
# TODO (trozet): add logic back from:
# Iedb75994d35b5dc1dd5d5ce1a57277c8f3729dfd (FDIO DVR)
- ansible_args = {
- 'virsh_enabled_networks': net_settings.enabled_network_list
- }
- utils.run_ansible(ansible_args,
- os.path.join(args.lib_dir, constants.ANSIBLE_PATH,
- 'deploy_dependencies.yml'))
uc_external = False
if 'external' in net_settings.enabled_network_list:
uc_external = True
@@ -341,39 +383,53 @@ def main():
else:
root_pw = None
- upstream = (os_version != constants.DEFAULT_OS_VERSION or
- args.upstream)
+ if not args.upstream:
+ logging.warning("Using upstream is now required for Apex. "
+ "Forcing upstream to true")
if os_version == 'master':
branch = 'master'
else:
branch = "stable/{}".format(os_version)
- if upstream:
- logging.info("Deploying with upstream artifacts for OpenStack "
- "{}".format(os_version))
- args.image_dir = os.path.join(args.image_dir, os_version)
- upstream_url = constants.UPSTREAM_RDO.replace(
- constants.DEFAULT_OS_VERSION, os_version)
- upstream_targets = ['overcloud-full.tar', 'undercloud.qcow2']
- utils.fetch_upstream_and_unpack(args.image_dir, upstream_url,
- upstream_targets,
- fetch=not args.no_fetch)
- sdn_image = os.path.join(args.image_dir, 'overcloud-full.qcow2')
- # copy undercloud so we don't taint upstream fetch
- uc_image = os.path.join(args.image_dir, 'undercloud_mod.qcow2')
- uc_fetch_img = os.path.join(args.image_dir, 'undercloud.qcow2')
- shutil.copyfile(uc_fetch_img, uc_image)
- # prep undercloud with required packages
- uc_builder.add_upstream_packages(uc_image)
- # add patches from upstream to undercloud and overcloud
- logging.info('Adding patches to undercloud')
- patches = deploy_settings['global_params']['patches']
- c_builder.add_upstream_patches(patches['undercloud'], uc_image,
- APEX_TEMP_DIR, branch)
+
+ logging.info("Deploying with upstream artifacts for OpenStack "
+ "{}".format(os_version))
+ args.image_dir = os.path.join(args.image_dir, os_version)
+ upstream_url = constants.UPSTREAM_RDO.replace(
+ constants.DEFAULT_OS_VERSION, os_version)
+
+ upstream_targets = ['overcloud-full.tar', 'ironic-python-agent.tar']
+ if platform.machine() == 'aarch64':
+ upstream_targets.append('undercloud.qcow2')
+ utils.fetch_upstream_and_unpack(args.image_dir, upstream_url,
+ upstream_targets,
+ fetch=not args.no_fetch)
+ # Copy ironic files and overcloud ramdisk and kernel into temp dir
+ # to be copied by ansible into undercloud /home/stack
+ # Note the overcloud disk does not need to be copied here as it will
+ # be modified and copied later
+ for tmp_file in UC_DISK_FILES:
+ shutil.copyfile(os.path.join(args.image_dir, tmp_file),
+ os.path.join(APEX_TEMP_DIR, tmp_file))
+ if platform.machine() == 'aarch64':
+ sdn_image = os.path.join(args.image_dir, 'undercloud.qcow2')
else:
- sdn_image = os.path.join(args.image_dir, SDN_IMAGE)
- uc_image = 'undercloud.qcow2'
- # patches are ignored in non-upstream deployments
- patches = {'overcloud': [], 'undercloud': []}
+ sdn_image = os.path.join(args.image_dir, 'overcloud-full.qcow2')
+ # copy undercloud so we don't taint upstream fetch
+ uc_image = os.path.join(args.image_dir, 'undercloud_mod.qcow2')
+ uc_fetch_img = sdn_image
+ shutil.copyfile(uc_fetch_img, uc_image)
+ # prep undercloud with required packages
+ if platform.machine() != 'aarch64':
+ uc_builder.update_repos(image=uc_image,
+ branch=branch.replace('stable/', ''))
+ uc_builder.add_upstream_packages(uc_image)
+ uc_builder.inject_calipso_installer(APEX_TEMP_DIR, uc_image)
+ # add patches from upstream to undercloud and overcloud
+ logging.info('Adding patches to undercloud')
+ patches = deployment.determine_patches()
+ c_builder.add_upstream_patches(patches['undercloud'], uc_image,
+ APEX_TEMP_DIR, branch)
+
# Create/Start Undercloud VM
undercloud = uc_lib.Undercloud(args.image_dir,
args.deploy_dir,
@@ -385,7 +441,7 @@ def main():
undercloud_admin_ip = net_settings['networks'][
constants.ADMIN_NETWORK]['installer_vm']['ip']
- if upstream and ds_opts['containers']:
+ if ds_opts['containers']:
tag = constants.DOCKER_TAG
else:
tag = None
@@ -394,6 +450,21 @@ def main():
for role in 'compute', 'controller':
oc_cfg.create_nic_template(net_settings, deploy_settings, role,
args.deploy_dir, APEX_TEMP_DIR)
+ # Prepare/Upload docker images
+ docker_env = 'containers-prepare-parameter.yaml'
+ shutil.copyfile(os.path.join(args.deploy_dir, docker_env),
+ os.path.join(APEX_TEMP_DIR, docker_env))
+ # Upload extra ansible.cfg
+ if platform.machine() == 'aarch64':
+ ansible_env = 'ansible.cfg'
+ shutil.copyfile(os.path.join(args.deploy_dir, ansible_env),
+ os.path.join(APEX_TEMP_DIR, ansible_env))
+
+ c_builder.prepare_container_images(
+ os.path.join(APEX_TEMP_DIR, docker_env),
+ branch=branch.replace('stable/', ''),
+ neutron_driver=c_builder.get_neutron_driver(ds_opts)
+ )
# Install Undercloud
undercloud.configure(net_settings, deploy_settings,
os.path.join(args.lib_dir, constants.ANSIBLE_PATH,
@@ -408,24 +479,27 @@ def main():
net_data_file)
else:
net_data = False
- if upstream and args.env_file == 'opnfv-environment.yaml':
+
+ shutil.copyfile(os.path.join(args.deploy_dir, 'build_ovs_nsh.sh'),
+ os.path.join(APEX_TEMP_DIR, 'build_ovs_nsh.sh'))
+
+ # TODO(trozet): Either fix opnfv env or default to use upstream env
+ if args.env_file == 'opnfv-environment.yaml':
# Override the env_file if it is defaulted to opnfv
# opnfv env file will not work with upstream
args.env_file = 'upstream-environment.yaml'
opnfv_env = os.path.join(args.deploy_dir, args.env_file)
- if not upstream:
- # TODO(trozet): Invoke with containers after Fraser migration
- oc_deploy.prep_env(deploy_settings, net_settings, inventory,
- opnfv_env, net_env_target, APEX_TEMP_DIR)
+ oc_deploy.prep_env(deploy_settings, net_settings, inventory,
+ opnfv_env, net_env_target, APEX_TEMP_DIR)
+ if not args.virtual:
+ oc_deploy.LOOP_DEVICE_SIZE = "50G"
+ if platform.machine() == 'aarch64':
+ oc_image = os.path.join(args.image_dir, 'overcloud-full.qcow2')
else:
- shutil.copyfile(
- opnfv_env,
- os.path.join(APEX_TEMP_DIR, os.path.basename(opnfv_env))
- )
+ oc_image = sdn_image
patched_containers = oc_deploy.prep_image(
- deploy_settings, net_settings, sdn_image, APEX_TEMP_DIR,
- root_pw=root_pw, docker_tag=tag, patches=patches['overcloud'],
- upstream=upstream)
+ deploy_settings, net_settings, oc_image, APEX_TEMP_DIR,
+ root_pw=root_pw, docker_tag=tag, patches=patches['overcloud'])
oc_deploy.create_deploy_cmd(deploy_settings, net_settings, inventory,
APEX_TEMP_DIR, args.virtual,
@@ -435,10 +509,11 @@ def main():
docker_playbook = os.path.join(args.lib_dir, constants.ANSIBLE_PATH,
'prepare_overcloud_containers.yml')
if ds_opts['containers']:
- ceph_version = constants.CEPH_VERSION_MAP[ds_opts['os_version']]
- ceph_docker_image = "ceph/daemon:tag-build-master-" \
- "{}-centos-7".format(ceph_version)
logging.info("Preparing Undercloud with Docker containers")
+ sdn_env = oc_deploy.get_docker_sdn_files(ds_opts)
+ sdn_env_files = str()
+ for sdn_file in sdn_env:
+ sdn_env_files += " -e {}".format(sdn_file)
if patched_containers:
oc_builder.archive_docker_patches(APEX_TEMP_DIR)
container_vars = dict()
@@ -447,13 +522,13 @@ def main():
patched_containers)
container_vars['container_tag'] = constants.DOCKER_TAG
container_vars['stackrc'] = 'source /home/stack/stackrc'
- container_vars['upstream'] = upstream
container_vars['sdn'] = ds_opts['sdn_controller']
container_vars['undercloud_ip'] = undercloud_admin_ip
container_vars['os_version'] = os_version
- container_vars['ceph_docker_image'] = ceph_docker_image
- container_vars['sdn_env_file'] = \
- oc_deploy.get_docker_sdn_file(ds_opts)
+ container_vars['aarch64'] = platform.machine() == 'aarch64'
+ container_vars['sdn_env_file'] = sdn_env_files
+ container_vars['container_client'] = utils.find_container_client(
+ os_version)
try:
utils.run_ansible(container_vars, docker_playbook,
host=undercloud.ip, user='stack',
@@ -462,6 +537,8 @@ def main():
except Exception:
logging.error("Unable to complete container prep on "
"Undercloud")
+ for tmp_file in UC_DISK_FILES:
+ os.remove(os.path.join(APEX_TEMP_DIR, tmp_file))
os.remove(os.path.join(APEX_TEMP_DIR, 'overcloud-full.qcow2'))
raise
@@ -469,7 +546,8 @@ def main():
'deploy_overcloud.yml')
virt_env = 'virtual-environment.yaml'
bm_env = 'baremetal-environment.yaml'
- for p_env in virt_env, bm_env:
+ k8s_env = 'kubernetes-environment.yaml'
+ for p_env in virt_env, bm_env, k8s_env:
shutil.copyfile(os.path.join(args.deploy_dir, p_env),
os.path.join(APEX_TEMP_DIR, p_env))
@@ -487,12 +565,14 @@ def main():
deploy_vars['apex_env_file'] = os.path.basename(opnfv_env)
deploy_vars['stackrc'] = 'source /home/stack/stackrc'
deploy_vars['overcloudrc'] = 'source /home/stack/overcloudrc'
- deploy_vars['upstream'] = upstream
deploy_vars['undercloud_ip'] = undercloud_admin_ip
deploy_vars['ha_enabled'] = ha_enabled
deploy_vars['os_version'] = os_version
deploy_vars['http_proxy'] = net_settings.get('http_proxy', '')
deploy_vars['https_proxy'] = net_settings.get('https_proxy', '')
+ deploy_vars['vim'] = ds_opts['vim']
+ deploy_vars['container_client'] = utils.find_container_client(
+ os_version)
for dns_server in net_settings['dns_servers']:
deploy_vars['dns_server_args'] += " --dns-nameserver {}".format(
dns_server)
@@ -508,6 +588,8 @@ def main():
raise
finally:
os.remove(os.path.join(APEX_TEMP_DIR, 'overcloud-full.qcow2'))
+ for tmp_file in UC_DISK_FILES:
+ os.remove(os.path.join(APEX_TEMP_DIR, tmp_file))
# Post install
logging.info("Executing post deploy configuration")
@@ -546,17 +628,107 @@ def main():
else:
deploy_vars['overcloudrc_files'] = ['overcloudrc']
- post_undercloud = os.path.join(args.lib_dir, constants.ANSIBLE_PATH,
+ post_undercloud = os.path.join(args.lib_dir,
+ constants.ANSIBLE_PATH,
'post_deploy_undercloud.yml')
- logging.info("Executing post deploy configuration undercloud playbook")
+ logging.info("Executing post deploy configuration undercloud "
+ "playbook")
try:
- utils.run_ansible(deploy_vars, post_undercloud, host=undercloud.ip,
- user='stack', tmp_dir=APEX_TEMP_DIR)
+ utils.run_ansible(deploy_vars, post_undercloud,
+ host=undercloud.ip, user='stack',
+ tmp_dir=APEX_TEMP_DIR)
logging.info("Post Deploy Undercloud Configuration Complete")
except Exception:
logging.error("Post Deploy Undercloud Configuration failed. "
"Please check log")
raise
+
+ # Deploy kubernetes if enabled
+ # (TODO)zshi move handling of kubernetes deployment
+ # to its own deployment class
+ if deploy_vars['vim'] == 'k8s':
+ # clone kubespray repo
+ git.Repo.clone_from(constants.KUBESPRAY_URL,
+ os.path.join(APEX_TEMP_DIR, 'kubespray'))
+ shutil.copytree(
+ os.path.join(APEX_TEMP_DIR, 'kubespray', 'inventory',
+ 'sample'),
+ os.path.join(APEX_TEMP_DIR, 'kubespray', 'inventory',
+ 'apex'))
+ k8s_node_inventory = {
+ 'all':
+ {'hosts': {},
+ 'children': {
+ 'k8s-cluster': {
+ 'children': {
+ 'kube-master': {
+ 'hosts': {}
+ },
+ 'kube-node': {
+ 'hosts': {}
+ }
+ }
+ },
+ 'etcd': {
+ 'hosts': {}
+ }
+ }
+ }
+ }
+ for node, ip in deploy_vars['overcloud_nodes'].items():
+ k8s_node_inventory['all']['hosts'][node] = {
+ 'ansible_become': True,
+ 'ansible_ssh_host': ip,
+ 'ansible_become_user': 'root',
+ 'ip': ip
+ }
+ if 'controller' in node:
+ k8s_node_inventory['all']['children']['k8s-cluster'][
+ 'children']['kube-master']['hosts'][node] = None
+ k8s_node_inventory['all']['children']['etcd'][
+ 'hosts'][node] = None
+ elif 'compute' in node:
+ k8s_node_inventory['all']['children']['k8s-cluster'][
+ 'children']['kube-node']['hosts'][node] = None
+
+ kubespray_dir = os.path.join(APEX_TEMP_DIR, 'kubespray')
+ with open(os.path.join(kubespray_dir, 'inventory', 'apex',
+ 'apex.yaml'), 'w') as invfile:
+ yaml.dump(k8s_node_inventory, invfile,
+ default_flow_style=False)
+ k8s_deploy_vars = {}
+ # Add kubespray ansible control variables in k8s_deploy_vars,
+ # example: 'kube_network_plugin': 'flannel'
+ k8s_deploy = os.path.join(kubespray_dir, 'cluster.yml')
+ k8s_deploy_inv_file = os.path.join(kubespray_dir, 'inventory',
+ 'apex', 'apex.yaml')
+
+ k8s_remove_pkgs = os.path.join(args.lib_dir,
+ constants.ANSIBLE_PATH,
+ 'k8s_remove_pkgs.yml')
+ try:
+ logging.debug("Removing any existing overcloud docker "
+ "packages")
+ utils.run_ansible(k8s_deploy_vars, k8s_remove_pkgs,
+ host=k8s_deploy_inv_file,
+ user='heat-admin', tmp_dir=APEX_TEMP_DIR)
+ logging.info("k8s Deploy Remove Existing Docker Related "
+ "Packages Complete")
+ except Exception:
+ logging.error("k8s Deploy Remove Existing Docker Related "
+ "Packages failed. Please check log")
+ raise
+
+ try:
+ utils.run_ansible(k8s_deploy_vars, k8s_deploy,
+ host=k8s_deploy_inv_file,
+ user='heat-admin', tmp_dir=APEX_TEMP_DIR)
+ logging.info("k8s Deploy Overcloud Configuration Complete")
+ except Exception:
+ logging.error("k8s Deploy Overcloud Configuration failed."
+ "Please check log")
+ raise
+
# Post deploy overcloud node configuration
# TODO(trozet): just parse all ds_opts as deploy vars one time
deploy_vars['sfc'] = ds_opts['sfc']
@@ -564,6 +736,10 @@ def main():
deploy_vars['l2gw'] = ds_opts.get('l2gw')
deploy_vars['sriov'] = ds_opts.get('sriov')
deploy_vars['tacker'] = ds_opts.get('tacker')
+ deploy_vars['all_in_one'] = all_in_one
+ # TODO(trozet): need to set container client to docker until OOO
+ # migrates OC to podman. Remove this later.
+ deploy_vars['container_client'] = 'docker'
# TODO(trozet): pull all logs and store in tmp dir in overcloud
# playbook
post_overcloud = os.path.join(args.lib_dir, constants.ANSIBLE_PATH,
diff --git a/apex/deployment/__init__.py b/apex/deployment/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/apex/deployment/__init__.py
diff --git a/apex/deployment/snapshot.py b/apex/deployment/snapshot.py
new file mode 100644
index 00000000..b33907fb
--- /dev/null
+++ b/apex/deployment/snapshot.py
@@ -0,0 +1,241 @@
+##############################################################################
+# Copyright (c) 2018 Tim Rozet (trozet@redhat.com) and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+import fnmatch
+import logging
+import os
+import pprint
+import socket
+import time
+
+import libvirt
+
+import apex.common.constants as con
+from apex.common import exceptions as exc
+from apex.common import utils
+from apex.overcloud.node import OvercloudNode
+import apex.settings.deploy_settings as ds
+
+
+SNAP_FILE = 'snapshot.properties'
+CHECKSUM = 'OPNFV_SNAP_SHA512SUM'
+OVERCLOUD_RC = 'overcloudrc'
+SSH_KEY = 'id_rsa'
+OPENSTACK = 'openstack'
+OPENDAYLIGHT = 'opendaylight'
+SERVICES = (OPENSTACK, OPENDAYLIGHT)
+
+
+class SnapshotDeployment:
+ def __init__(self, deploy_settings, snap_cache_dir, fetch=True,
+ all_in_one=False):
+ self.id_rsa = None
+ self.fetch = fetch
+ ds_opts = deploy_settings['deploy_options']
+ self.os_version = ds_opts['os_version']
+ self.ha_enabled = deploy_settings['global_params']['ha_enabled']
+ if self.ha_enabled:
+ self.ha_ext = 'ha'
+ elif all_in_one:
+ self.ha_ext = 'noha-allinone'
+ else:
+ self.ha_ext = 'noha'
+ self.snap_cache_dir = os.path.join(snap_cache_dir,
+ "{}/{}".format(self.os_version,
+ self.ha_ext))
+ self.networks = []
+ self.oc_nodes = []
+ self.properties_url = "{}/apex/{}/{}".format(con.OPNFV_ARTIFACTS,
+ self.os_version,
+ self.ha_ext)
+ self.conn = libvirt.open('qemu:///system')
+ if not self.conn:
+ raise exc.SnapshotDeployException(
+ 'Unable to open libvirt connection')
+ if self.fetch:
+ self.pull_snapshot(self.properties_url, self.snap_cache_dir)
+ else:
+ logging.info('No fetch enabled. Will not attempt to pull latest '
+ 'snapshot')
+ self.deploy_snapshot()
+
+ @staticmethod
+ def pull_snapshot(url_path, snap_cache_dir):
+ """
+ Compare opnfv properties file and download and unpack snapshot if
+ necessary
+ :param url_path: path of latest snap info
+ :param snap_cache_dir: local directory for snap cache
+ :return: None
+ """
+ full_url = os.path.join(url_path, SNAP_FILE)
+ upstream_props = utils.fetch_properties(full_url)
+ logging.debug("Upstream properties are: {}".format(upstream_props))
+ try:
+ upstream_sha = upstream_props[CHECKSUM]
+ except KeyError:
+ logging.error('Unable to find {} for upstream properties: '
+ '{}'.format(CHECKSUM, upstream_props))
+ raise exc.SnapshotDeployException('Unable to find upstream '
+ 'properties checksum value')
+ local_prop_file = os.path.join(snap_cache_dir, SNAP_FILE)
+ try:
+ local_props = utils.fetch_properties(local_prop_file)
+ local_sha = local_props[CHECKSUM]
+ pull_snap = local_sha != upstream_sha
+ except (exc.FetchException, KeyError):
+ logging.info("No locally cached properties found, will pull "
+ "latest")
+ local_sha = None
+ pull_snap = True
+ logging.debug('Local sha: {}, Upstream sha: {}'.format(local_sha,
+ upstream_sha))
+ if pull_snap:
+ logging.info('SHA mismatch, will download latest snapshot')
+ full_snap_url = upstream_props['OPNFV_SNAP_URL']
+ snap_file = os.path.basename(full_snap_url)
+ snap_url = full_snap_url.replace(snap_file, '')
+ if not snap_url.startswith('http://'):
+ snap_url = 'http://' + snap_url
+ utils.fetch_upstream_and_unpack(dest=snap_cache_dir,
+ url=snap_url,
+ targets=[SNAP_FILE, snap_file]
+ )
+ else:
+ logging.info('SHA match, artifacts in cache are already latest. '
+ 'Will not download.')
+
+ def create_networks(self):
+ logging.info("Detecting snapshot networks")
+ try:
+ xmls = fnmatch.filter(os.listdir(self.snap_cache_dir), '*.xml')
+ except FileNotFoundError:
+ raise exc.SnapshotDeployException(
+ 'No XML files found in snap cache directory: {}'.format(
+ self.snap_cache_dir))
+ net_xmls = list()
+ for xml in xmls:
+ if xml.startswith('baremetal'):
+ continue
+ net_xmls.append(os.path.join(self.snap_cache_dir, xml))
+ if not net_xmls:
+ raise exc.SnapshotDeployException(
+ 'No network XML files detected in snap cache, '
+ 'please check local snap cache contents')
+ logging.info('Snapshot networks found: {}'.format(net_xmls))
+ for xml in net_xmls:
+ logging.debug('Creating network from {}'.format(xml))
+ with open(xml, 'r') as fh:
+ net_xml = fh.read()
+ net = self.conn.networkCreateXML(net_xml)
+ self.networks.append(net)
+ logging.info('Network started: {}'.format(net.name()))
+
+ def parse_and_create_nodes(self):
+ """
+ Parse snapshot node.yaml config file and create overcloud nodes
+ :return: None
+ """
+ node_file = os.path.join(self.snap_cache_dir, 'node.yaml')
+ if not os.path.isfile(node_file):
+ raise exc.SnapshotDeployException('Missing node definitions from '
+ ''.format(node_file))
+ node_data = utils.parse_yaml(node_file)
+ if 'servers' not in node_data:
+ raise exc.SnapshotDeployException('Invalid node.yaml format')
+ for node, data in node_data['servers'].items():
+ logging.info('Creating node: {}'.format(node))
+ logging.debug('Node data is:\n{}'.format(pprint.pformat(data)))
+ node_xml = os.path.join(self.snap_cache_dir,
+ '{}.xml'.format(data['vNode-name']))
+ node_qcow = os.path.join(self.snap_cache_dir,
+ '{}.qcow2'.format(data['vNode-name']))
+ self.oc_nodes.append(
+ OvercloudNode(ip=data['address'],
+ ovs_ctrlrs=data['ovs-controller'],
+ ovs_mgrs=data['ovs-managers'],
+ role=data['type'],
+ name=node,
+ node_xml=node_xml,
+ disk_img=node_qcow)
+ )
+ logging.info('Node Created')
+ logging.info('Starting nodes')
+ for node in self.oc_nodes:
+ node.start()
+
+ def get_controllers(self):
+ controllers = []
+ for node in self.oc_nodes:
+ if node.role == 'controller':
+ controllers.append(node)
+ return controllers
+
+ def is_service_up(self, service):
+ assert service in SERVICES
+ if service == OPENSTACK:
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.settimeout(5)
+ controllers = self.get_controllers()
+ if not controllers:
+ raise exc.SnapshotDeployException('No OpenStack controllers found')
+
+ for node in controllers:
+ logging.info('Waiting until {} is up on controller: '
+ '{}'.format(service, node.name))
+ for x in range(10):
+ logging.debug('Checking {} is up attempt {}'.format(service,
+ str(x + 1)))
+ if service == OPENSTACK:
+ # Check if Neutron is up
+ if sock.connect_ex((node.ip, 9696)) == 0:
+ logging.info('{} is up on controller {}'.format(
+ service, node.name))
+ break
+ elif service == OPENDAYLIGHT:
+ url = 'http://{}:8081/diagstatus'.format(node.ip)
+ try:
+ utils.open_webpage(url)
+ logging.info('{} is up on controller {}'.format(
+ service, node.name))
+ break
+ except Exception as e:
+ logging.debug('Cannot contact ODL. Reason: '
+ '{}'.format(e))
+ time.sleep(60)
+ else:
+ logging.error('{} is not running after 10 attempts'.format(
+ service))
+ return False
+ return True
+
+ def deploy_snapshot(self):
+ # bring up networks
+ self.create_networks()
+ # check overcloudrc exists, id_rsa
+ for snap_file in (OVERCLOUD_RC, SSH_KEY):
+ if not os.path.isfile(os.path.join(self.snap_cache_dir,
+ snap_file)):
+ logging.warning('File is missing form snap cache: '
+ '{}'.format(snap_file))
+ # create nodes
+ self.parse_and_create_nodes()
+ # validate deployment
+ if self.is_service_up(OPENSTACK):
+ logging.info('OpenStack is up')
+ else:
+ raise exc.SnapshotDeployException('OpenStack is not alive')
+ if self.is_service_up(OPENDAYLIGHT):
+ logging.info('OpenDaylight is up')
+ else:
+ raise exc.SnapshotDeployException(
+ 'OpenDaylight {} is not reporting diag status')
+ # TODO(trozet): recreate external network/subnet if missing
+ logging.info('Snapshot deployment complete. Please use the {} file '
+ 'in {} to interact with '
+ 'OpenStack'.format(OVERCLOUD_RC, self.snap_cache_dir))
diff --git a/apex/deployment/tripleo.py b/apex/deployment/tripleo.py
new file mode 100644
index 00000000..c131e161
--- /dev/null
+++ b/apex/deployment/tripleo.py
@@ -0,0 +1,60 @@
+##############################################################################
+# Copyright (c) 2018 Tim Rozet (trozet@redhat.com) and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+# TODO(trozet): this will serve as the deployment class as we migrate logic out
+# of deploy.py
+import logging
+import os
+import pprint
+
+from apex.common.exceptions import ApexDeployException
+from apex.common import utils
+
+
+class ApexDeployment:
+ def __init__(self, deploy_settings, patch_file, ds_file):
+ self.ds = deploy_settings
+ # TODO(trozet): remove ds_file from args and have this class inherit
+ # super deployment class init which does all the settings
+ self.ds_file = ds_file
+ self.ds_globals = self.ds['global_params']
+ self.p_file = patch_file
+
+ def determine_patches(self):
+ patches = self.ds_globals['patches']
+ if not os.path.isfile(self.p_file):
+ new_file = os.path.join(os.path.dirname(self.ds_file),
+ 'common-patches.yaml')
+ if os.path.isfile(new_file):
+ logging.warning('Patch file {} not found, falling back to '
+ '{}'.format(self.p_file, new_file))
+ self.p_file = new_file
+ else:
+ logging.error('Unable to find common patch file: '
+ '{}'.format(self.p_file))
+ raise ApexDeployException(
+ 'Specified common patch file not found: {}'.format(
+ self.p_file))
+ logging.info('Loading patches from common patch file {}'.format(
+ self.p_file))
+ common_patches = utils.parse_yaml(self.p_file)
+ logging.debug('Content from common patch file is: {}'.format(
+ pprint.pformat(common_patches)))
+ os_version = self.ds['deploy_options']['os_version']
+ try:
+ common_patches = common_patches['patches'][os_version]
+ except KeyError:
+ logging.error('Error parsing common patches file, wrong format.')
+ raise ApexDeployException('Invalid format of common patch file')
+
+ for ptype in ('undercloud', 'overcloud'):
+ if ptype in common_patches:
+ patches[ptype] = utils.unique(patches[ptype] +
+ common_patches[ptype])
+ return patches
diff --git a/apex/inventory/inventory.py b/apex/inventory/inventory.py
index b5ffd2f8..0546fe9f 100644
--- a/apex/inventory/inventory.py
+++ b/apex/inventory/inventory.py
@@ -67,9 +67,12 @@ class Inventory(dict):
if ha and len(self['nodes']) < 5:
raise ApexInventoryException('You must provide at least 5 '
'nodes for HA deployment')
- elif len(self['nodes']) < 2:
- raise ApexInventoryException('You must provide at least 2 nodes '
+ elif len(self['nodes']) < 1:
+ raise ApexInventoryException('You must provide at least 1 node '
'for non-HA deployment')
+ elif list(self.get_node_counts())[0] < 1:
+ raise ApexInventoryException('You must provide at least 1 '
+ 'control node for deployment')
if virtual:
self['host-ip'] = '192.168.122.1'
diff --git a/apex/network/jumphost.py b/apex/network/jumphost.py
index c28c105e..86556659 100644
--- a/apex/network/jumphost.py
+++ b/apex/network/jumphost.py
@@ -53,12 +53,8 @@ def configure_bridges(ns):
if cidr.version == 6:
ipv6_br_path = "/proc/sys/net/ipv6/conf/{}/disable_" \
"ipv6".format(NET_MAP[network])
- try:
- subprocess.check_call('echo', 0, '>', ipv6_br_path)
- except subprocess.CalledProcessError:
- logging.error("Unable to enable ipv6 on "
- "bridge {}".format(NET_MAP[network]))
- raise
+ with open(ipv6_br_path, 'w') as f:
+ print(0, file=f)
try:
ip_prefix = "{}/{}".format(ovs_ip, cidr.prefixlen)
subprocess.check_call(['ip', 'addr', 'add', ip_prefix, 'dev',
diff --git a/apex/network/network_data.py b/apex/network/network_data.py
index 1177af09..6f330c50 100644
--- a/apex/network/network_data.py
+++ b/apex/network/network_data.py
@@ -83,7 +83,7 @@ def create_network_data(ns, target=None):
"{}".format(net))
raise NetworkDataException("cidr is null for network {}".format(
net))
-
+ tmp_net['mtu'] = network.get('mtu', 1500)
network_data.append(copy.deepcopy(tmp_net))
# have to do this due to the aforementioned bug
diff --git a/apex/network/network_environment.py b/apex/network/network_environment.py
index 0a4d1036..52b4452a 100644
--- a/apex/network/network_environment.py
+++ b/apex/network/network_environment.py
@@ -186,6 +186,8 @@ class NetworkEnvironment(dict):
for flag in IPV6_FLAGS:
self[param_def][flag] = True
+ self._update_service_netmap(net_settings.enabled_network_list)
+
def _get_vlan(self, network):
if isinstance(network['nic_mapping'][CONTROLLER]['vlan'], int):
return network['nic_mapping'][CONTROLLER]['vlan']
@@ -218,6 +220,13 @@ class NetworkEnvironment(dict):
prefix = ''
self[reg][key] = self.tht_dir + prefix + postfix
+ def _update_service_netmap(self, network_list):
+ if 'ServiceNetMap' not in self[param_def]:
+ return
+ for service, network in self[param_def]['ServiceNetMap'].items():
+ if network not in network_list:
+ self[param_def]['ServiceNetMap'][service] = 'ctlplane'
+
class NetworkEnvException(Exception):
def __init__(self, value):
diff --git a/apex/overcloud/deploy.py b/apex/overcloud/deploy.py
index a45b3a9b..538f50a4 100644
--- a/apex/overcloud/deploy.py
+++ b/apex/overcloud/deploy.py
@@ -12,10 +12,12 @@ import fileinput
import logging
import os
import platform
+import pprint
import shutil
import uuid
import struct
import time
+import yaml
import apex.builders.overcloud_builder as oc_builder
import apex.builders.common_builder as c_builder
@@ -70,11 +72,11 @@ OVS_PERF_MAP = {
'NeutronDpdkMemoryChannels': 'memory_channels'
}
-OVS_NSH_KMOD_RPM = "openvswitch-kmod-2.6.1-1.el7.centos.x86_64.rpm"
-OVS_NSH_RPM = "openvswitch-2.6.1-1.el7.centos.x86_64.rpm"
ODL_NETVIRT_VPP_RPM = "/root/opendaylight-7.0.0-0.1.20170531snap665.el7" \
".noarch.rpm"
+LOOP_DEVICE_SIZE = "10G"
+
LOSETUP_SERVICE = """[Unit]
Description=Setup loop devices
Before=network.target
@@ -90,6 +92,19 @@ RemainAfterExit=yes
WantedBy=multi-user.target
"""
+DUPLICATE_COMPUTE_SERVICES = [
+ 'OS::TripleO::Services::ComputeNeutronCorePlugin',
+ 'OS::TripleO::Services::ComputeNeutronMetadataAgent',
+ 'OS::TripleO::Services::ComputeNeutronOvsAgent',
+ 'OS::TripleO::Services::ComputeNeutronL3Agent'
+]
+
+NFS_VARS = [
+ 'NovaNfsEnabled',
+ 'GlanceNfsEnabled',
+ 'CinderNfsEnabledBackend'
+]
+
def build_sdn_env_list(ds, sdn_map, env_list=None):
"""
@@ -136,24 +151,24 @@ def build_sdn_env_list(ds, sdn_map, env_list=None):
return env_list
-def get_docker_sdn_file(ds_opts):
+def get_docker_sdn_files(ds_opts):
"""
Returns docker env file for detected SDN
:param ds_opts: deploy options
- :return: docker THT env file for an SDN
+ :return: list of docker THT env files for an SDN
"""
- # FIXME(trozet): We assume right now there is only one docker SDN file
docker_services = con.VALID_DOCKER_SERVICES
- tht_dir = con.THT_DOCKER_ENV_DIR[ds_opts['os_version']]
+ tht_dir = con.THT_DOCKER_ENV_DIR
sdn_env_list = build_sdn_env_list(ds_opts, SDN_FILE_MAP)
- for sdn_file in sdn_env_list:
+ for i, sdn_file in enumerate(sdn_env_list):
sdn_base = os.path.basename(sdn_file)
if sdn_base in docker_services:
if docker_services[sdn_base] is not None:
- return os.path.join(tht_dir,
- docker_services[sdn_base])
+ sdn_env_list[i] = \
+ os.path.join(tht_dir, docker_services[sdn_base])
else:
- return os.path.join(tht_dir, sdn_base)
+ sdn_env_list[i] = os.path.join(tht_dir, sdn_base)
+ return sdn_env_list
def create_deploy_cmd(ds, ns, inv, tmp_dir,
@@ -182,10 +197,9 @@ def create_deploy_cmd(ds, ns, inv, tmp_dir,
if ds_opts['containers']:
deploy_options.append('docker-images.yaml')
- sdn_docker_file = get_docker_sdn_file(ds_opts)
- if sdn_docker_file:
+ sdn_docker_files = get_docker_sdn_files(ds_opts)
+ for sdn_docker_file in sdn_docker_files:
deploy_options.append(sdn_docker_file)
- deploy_options.append('sdn-images.yaml')
else:
deploy_options += build_sdn_env_list(ds_opts, SDN_FILE_MAP)
@@ -197,6 +211,8 @@ def create_deploy_cmd(ds, ns, inv, tmp_dir,
else:
deploy_options.append(os.path.join(con.THT_ENV_DIR, v))
+ # TODO(trozet) Fix this check to look for if ceph is in controller services
+ # and not use name of the file
if ds_opts['ceph'] and 'csit' not in env_file:
prep_storage_env(ds, ns, virtual, tmp_dir)
deploy_options.append(os.path.join(con.THT_ENV_DIR,
@@ -204,17 +220,18 @@ def create_deploy_cmd(ds, ns, inv, tmp_dir,
if ds_opts['sriov']:
prep_sriov_env(ds, tmp_dir)
+ # Check for 'k8s' here intentionally, as we may support other values
+ # such as openstack/openshift for 'vim' option.
+ if ds_opts['vim'] == 'k8s':
+ deploy_options.append('kubernetes-environment.yaml')
+
if virtual:
deploy_options.append('virtual-environment.yaml')
else:
deploy_options.append('baremetal-environment.yaml')
num_control, num_compute = inv.get_node_counts()
- if num_control == 0 or num_compute == 0:
- logging.error("Detected 0 control or compute nodes. Control nodes: "
- "{}, compute nodes{}".format(num_control, num_compute))
- raise ApexDeployException("Invalid number of control or computes")
- elif num_control > 1 and not ds['global_params']['ha_enabled']:
+ if num_control > 1 and not ds['global_params']['ha_enabled']:
num_control = 1
if platform.machine() == 'aarch64':
# aarch64 deploys were not completing in the default 90 mins.
@@ -236,12 +253,16 @@ def create_deploy_cmd(ds, ns, inv, tmp_dir,
if net_data:
cmd += ' --networks-file network_data.yaml'
libvirt_type = 'kvm'
- if virtual:
+ if virtual and (platform.machine() != 'aarch64'):
with open('/sys/module/kvm_intel/parameters/nested') as f:
nested_kvm = f.read().strip()
if nested_kvm != 'Y':
libvirt_type = 'qemu'
+ elif virtual and (platform.machine() == 'aarch64'):
+ libvirt_type = 'qemu'
cmd += ' --libvirt-type {}'.format(libvirt_type)
+ if platform.machine() == 'aarch64':
+ cmd += ' --override-ansible-cfg /home/stack/ansible.cfg '
logging.info("Deploy command set: {}".format(cmd))
with open(os.path.join(tmp_dir, 'deploy_command'), 'w') as fh:
@@ -250,7 +271,7 @@ def create_deploy_cmd(ds, ns, inv, tmp_dir,
def prep_image(ds, ns, img, tmp_dir, root_pw=None, docker_tag=None,
- patches=None, upstream=False):
+ patches=None):
"""
Locates sdn image and preps for deployment.
:param ds: deploy settings
@@ -260,7 +281,6 @@ def prep_image(ds, ns, img, tmp_dir, root_pw=None, docker_tag=None,
:param root_pw: password to configure for overcloud image
:param docker_tag: Docker image tag for RDO version (default None)
:param patches: List of patches to apply to overcloud image
- :param upstream: (boolean) Indicates if upstream deployment or not
:return: None
"""
# TODO(trozet): Come up with a better way to organize this logic in this
@@ -300,7 +320,13 @@ def prep_image(ds, ns, img, tmp_dir, root_pw=None, docker_tag=None,
"echo 'https_proxy={}' >> /etc/environment".format(
ns['https_proxy'])})
+ tmp_oc_image = os.path.join(tmp_dir, 'overcloud-full.qcow2')
+ shutil.copyfile(img, tmp_oc_image)
+ logging.debug("Temporary overcloud image stored as: {}".format(
+ tmp_oc_image))
+
if ds_opts['vpn']:
+ oc_builder.inject_quagga(tmp_oc_image, tmp_dir)
virt_cmds.append({con.VIRT_RUN_CMD: "chmod +x /etc/rc.d/rc.local"})
virt_cmds.append({
con.VIRT_RUN_CMD:
@@ -340,15 +366,14 @@ def prep_image(ds, ns, img, tmp_dir, root_pw=None, docker_tag=None,
if root_pw:
pw_op = "password:{}".format(root_pw)
virt_cmds.append({con.VIRT_PW: pw_op})
- if ds_opts['sfc'] and dataplane == 'ovs':
- virt_cmds.extend([
- {con.VIRT_RUN_CMD: "yum -y install "
- "/root/ovs/rpm/rpmbuild/RPMS/x86_64/"
- "{}".format(OVS_NSH_KMOD_RPM)},
- {con.VIRT_RUN_CMD: "yum downgrade -y "
- "/root/ovs/rpm/rpmbuild/RPMS/x86_64/"
- "{}".format(OVS_NSH_RPM)}
- ])
+
+ # FIXME(trozet) ovs build is failing in CentOS 7.6
+ # if dataplane == 'ovs':
+ # FIXME(trozet) remove this after RDO is updated with fix for
+ # https://bugzilla.redhat.com/show_bug.cgi?id=1544892
+ # https://review.rdoproject.org/r/#/c/13839/
+ # oc_builder.inject_ovs_nsh(tmp_oc_image, tmp_dir)
+
if dataplane == 'fdio':
# Patch neutron with using OVS external interface for router
# and add generic linux NS interface driver
@@ -362,42 +387,9 @@ def prep_image(ds, ns, img, tmp_dir, root_pw=None, docker_tag=None,
"/root/nosdn_vpp_rpms/*.rpm"}
])
- tmp_oc_image = os.path.join(tmp_dir, 'overcloud-full.qcow2')
- shutil.copyfile(img, tmp_oc_image)
- logging.debug("Temporary overcloud image stored as: {}".format(
- tmp_oc_image))
-
- # TODO (trozet): remove this if block after Fraser
- if sdn == 'opendaylight' and not upstream:
- if ds_opts['odl_version'] != con.DEFAULT_ODL_VERSION:
- virt_cmds.extend([
- {con.VIRT_RUN_CMD: "yum -y remove opendaylight"},
- {con.VIRT_RUN_CMD: "rm -rf /etc/puppet/modules/opendaylight"},
- {con.VIRT_RUN_CMD: "cd /etc/puppet/modules && tar xzf "
- "/root/puppet-opendaylight-"
- "{}.tar.gz".format(ds_opts['odl_version'])}
- ])
- if ds_opts['odl_version'] == 'master':
- virt_cmds.extend([
- {con.VIRT_RUN_CMD: "rpm -ivh --nodeps /root/{}/*".format(
- ds_opts['odl_version'])}
- ])
- else:
- virt_cmds.extend([
- {con.VIRT_RUN_CMD: "yum -y install /root/{}/*".format(
- ds_opts['odl_version'])}
- ])
-
- elif sdn == 'opendaylight' and 'odl_vpp_netvirt' in ds_opts \
- and ds_opts['odl_vpp_netvirt']:
- virt_cmds.extend([
- {con.VIRT_RUN_CMD: "yum -y remove opendaylight"},
- {con.VIRT_RUN_CMD: "yum -y install /root/{}/*".format(
- ODL_NETVIRT_VPP_RPM)}
- ])
- elif sdn == 'opendaylight':
- undercloud_admin_ip = ns['networks'][con.ADMIN_NETWORK][
- 'installer_vm']['ip']
+ undercloud_admin_ip = ns['networks'][con.ADMIN_NETWORK][
+ 'installer_vm']['ip']
+ if sdn == 'opendaylight':
oc_builder.inject_opendaylight(
odl_version=ds_opts['odl_version'],
image=tmp_oc_image,
@@ -430,10 +422,39 @@ def prep_image(ds, ns, img, tmp_dir, root_pw=None, docker_tag=None,
virt_cmds.extend([
{con.VIRT_UPLOAD: "{}:/usr/lib/systemd/system/".format(tmp_losetup)
},
- {con.VIRT_RUN_CMD: 'truncate /srv/data.img --size 10G'},
+ {con.VIRT_RUN_CMD: 'truncate /srv/data.img --size {}'
+ .format(LOOP_DEVICE_SIZE)},
{con.VIRT_RUN_CMD: 'systemctl daemon-reload'},
{con.VIRT_RUN_CMD: 'systemctl enable losetup.service'},
])
+ # TODO(trozet) remove this after LP#173474 is fixed
+ dhcp_unit = '/usr/lib/systemd/system/dhcp-interface@.service'
+ virt_cmds.append(
+ {con.VIRT_RUN_CMD: "crudini --del {} Unit "
+ "ConditionPathExists".format(dhcp_unit)})
+ # Prep for NFS
+ virt_cmds.extend([
+ {con.VIRT_INSTALL: "nfs-utils"},
+ {con.VIRT_RUN_CMD: "ln -s /usr/lib/systemd/system/nfs-server.service "
+ "/etc/systemd/system/multi-user.target.wants/"
+ "nfs-server.service"},
+ {con.VIRT_RUN_CMD: "mkdir -p /glance"},
+ {con.VIRT_RUN_CMD: "mkdir -p /cinder"},
+ {con.VIRT_RUN_CMD: "mkdir -p /nova"},
+ {con.VIRT_RUN_CMD: "chmod 777 /glance"},
+ {con.VIRT_RUN_CMD: "chmod 777 /cinder"},
+ {con.VIRT_RUN_CMD: "chmod 777 /nova"},
+ {con.VIRT_RUN_CMD: "chown nfsnobody:nfsnobody /glance"},
+ {con.VIRT_RUN_CMD: "chown nfsnobody:nfsnobody /cinder"},
+ {con.VIRT_RUN_CMD: "chown nfsnobody:nfsnobody /nova"},
+ {con.VIRT_RUN_CMD: "echo '/glance *(rw,sync,"
+ "no_root_squash,no_acl)' > /etc/exports"},
+ {con.VIRT_RUN_CMD: "echo '/cinder *(rw,sync,"
+ "no_root_squash,no_acl)' >> /etc/exports"},
+ {con.VIRT_RUN_CMD: "echo '/nova *(rw,sync,"
+ "no_root_squash,no_acl)' >> /etc/exports"},
+ {con.VIRT_RUN_CMD: "exportfs -avr"},
+ ])
virt_utils.virt_customize(virt_cmds, tmp_oc_image)
logging.info("Overcloud image customization complete")
return patched_containers
@@ -488,6 +509,10 @@ def prep_env(ds, ns, inv, opnfv_env, net_env, tmp_dir):
# SSH keys
private_key, public_key = make_ssh_key()
+ num_control, num_compute = inv.get_node_counts()
+ if num_control > 1 and not ds['global_params']['ha_enabled']:
+ num_control = 1
+
# Make easier/faster variables to index in the file editor
if 'performance' in ds_opts:
perf = True
@@ -515,6 +540,10 @@ def prep_env(ds, ns, inv, opnfv_env, net_env, tmp_dir):
else:
perf = False
+ tenant_settings = ns['networks']['tenant']
+ tenant_vlan_enabled = 'tenant' in ns.enabled_network_list and \
+ ns['networks']['tenant'].get('segmentation_type') == 'vlan'
+
# Modify OPNFV environment
# TODO: Change to build a dict and outputting yaml rather than parsing
for line in fileinput.input(tmp_opnfv_env, inplace=True):
@@ -538,6 +567,46 @@ def prep_env(ds, ns, inv, opnfv_env, net_env, tmp_dir):
ds_opts['dataplane'] == 'ovs_dpdk':
output_line = ' OS::TripleO::ComputeExtraConfigPre: ' \
'./ovs-dpdk-preconfig.yaml'
+ elif 'NeutronNetworkVLANRanges' in line:
+ vlan_setting = ''
+ if tenant_vlan_enabled:
+ if ns['networks']['tenant']['overlay_id_range']:
+ vlan_setting = ns['networks']['tenant']['overlay_id_range']
+ if 'datacentre' not in vlan_setting:
+ vlan_setting += ',datacentre:1:1000'
+ # SRIOV networks are VLAN based provider networks. In order to
+ # simplify the deployment, nfv_sriov will be the default physnet.
+ # VLANs are not needed in advance, and the user will have to create
+ # the network specifying the segmentation-id.
+ if ds_opts['sriov']:
+ if vlan_setting:
+ vlan_setting += ",nfv_sriov"
+ else:
+ vlan_setting = "datacentre:1:1000,nfv_sriov"
+ if vlan_setting:
+ output_line = " NeutronNetworkVLANRanges: " + vlan_setting
+ elif 'NeutronBridgeMappings' in line and tenant_vlan_enabled:
+ if tenant_settings['overlay_id_range']:
+ physnets = tenant_settings['overlay_id_range'].split(',')
+ output_line = " NeutronBridgeMappings: "
+ for physnet in physnets:
+ physnet_name = physnet.split(':')[0]
+ if physnet_name != 'datacentre':
+ output_line += "{}:br-vlan,".format(physnet_name)
+ output_line += "datacentre:br-ex"
+ elif 'OpenDaylightProviderMappings' in line and tenant_vlan_enabled \
+ and ds_opts['sdn_controller'] == 'opendaylight':
+ if tenant_settings['overlay_id_range']:
+ physnets = tenant_settings['overlay_id_range'].split(',')
+ output_line = " OpenDaylightProviderMappings: "
+ for physnet in physnets:
+ physnet_name = physnet.split(':')[0]
+ if physnet_name != 'datacentre':
+ output_line += "{}:br-vlan,".format(physnet_name)
+ output_line += "datacentre:br-ex"
+ elif 'NeutronNetworkType' in line and tenant_vlan_enabled:
+ output_line = " NeutronNetworkType: vlan\n" \
+ " NeutronTunnelTypes: ''"
if ds_opts['sdn_controller'] == 'opendaylight' and \
'odl_vpp_routing_node' in ds_opts:
@@ -557,19 +626,15 @@ def prep_env(ds, ns, inv, opnfv_env, net_env, tmp_dir):
if 'OS::TripleO::Services::NeutronDhcpAgent' in line:
output_line = ''
elif 'NeutronDhcpAgentsPerNetwork' in line:
- num_control, num_compute = inv.get_node_counts()
+ if num_compute == 0:
+ num_dhcp_agents = num_control
+ else:
+ num_dhcp_agents = num_compute
output_line = (" NeutronDhcpAgentsPerNetwork: {}"
- .format(num_compute))
+ .format(num_dhcp_agents))
elif 'ComputeServices' in line:
output_line = (" ComputeServices:\n"
" - OS::TripleO::Services::NeutronDhcpAgent")
- # SRIOV networks are VLAN based provider networks. In order to simplify
- # the deployment, nfv_sriov will be the default physnet. VLANs are not
- # needed in advance, and the user will have to create the network
- # specifying the segmentation-id.
- if ds_opts['sriov']:
- if 'NeutronNetworkVLANRanges' in line:
- output_line = ("{},nfv_sriov'".format(line[:-1]))
if perf:
for role in 'NovaCompute', 'Controller':
@@ -632,7 +697,50 @@ def prep_env(ds, ns, inv, opnfv_env, net_env, tmp_dir):
print(output_line)
+ # Merge compute services into control services if only a single
+ # node deployment
+ if num_compute == 0:
+ with open(tmp_opnfv_env, 'r') as fh:
+ data = yaml.safe_load(fh)
+ param_data = data['parameter_defaults']
+ logging.info("All in one deployment detected")
+ logging.info("Disabling NFS in env file")
+ # Check to see if any parameters are set for Compute
+ for param in param_data.keys():
+ if param != 'ComputeServices' and param.startswith('Compute'):
+ logging.warning("Compute parameter set, but will not be used "
+ "in deployment: {}. Please use Controller "
+ "based parameters when using All-in-one "
+ "deployments".format(param))
+ if param in NFS_VARS:
+ param_data[param] = False
+ logging.info("Checking if service merging required into "
+ "control services")
+ if ('ControllerServices' in param_data and 'ComputeServices' in
+ param_data):
+ logging.info("Services detected in environment file. Merging...")
+ ctrl_services = param_data['ControllerServices']
+ cmp_services = param_data['ComputeServices']
+ param_data['ControllerServices'] = list(set().union(
+ ctrl_services, cmp_services))
+ for dup_service in DUPLICATE_COMPUTE_SERVICES:
+ if dup_service in param_data['ControllerServices']:
+ param_data['ControllerServices'].remove(dup_service)
+ param_data.pop('ComputeServices')
+ logging.debug("Merged controller services: {}".format(
+ pprint.pformat(param_data['ControllerServices'])
+ ))
+ else:
+ logging.info("No services detected in env file, not merging "
+ "services")
+ with open(tmp_opnfv_env, 'w') as fh:
+ yaml.safe_dump(data, fh, default_flow_style=False)
+
logging.info("opnfv-environment file written to {}".format(tmp_opnfv_env))
+ with open(tmp_opnfv_env, 'r') as fh:
+ logging.debug("opnfv-environment content is : {}".format(
+ pprint.pformat(yaml.safe_load(fh.read()))
+ ))
def generate_ceph_key():
@@ -676,15 +784,7 @@ def prep_storage_env(ds, ns, virtual, tmp_dir):
print(line)
if ds_opts['containers']:
- undercloud_admin_ip = ns['networks'][con.ADMIN_NETWORK][
- 'installer_vm']['ip']
- ceph_version = con.CEPH_VERSION_MAP[ds_opts['os_version']]
- docker_image = "{}:8787/ceph/daemon:tag-build-master-" \
- "{}-centos-7".format(undercloud_admin_ip,
- ceph_version)
- ceph_params = {
- 'DockerCephDaemonImage': docker_image,
- }
+ ceph_params = {}
# max pgs allowed are calculated as num_mons * 200. Therefore we
# set number of pgs and pools so that the total will be less:
@@ -794,8 +894,7 @@ def external_network_cmds(ns, ds):
"--allocation-pool start={},end={} --subnet-range " \
"{}".format(gateway, pool_start, pool_end, str(cidr))
if external and cidr.version == 6:
- subnet_cmd += ' --ip-version 6 --ipv6-ra-mode slaac ' \
- '--ipv6-address-mode slaac'
+ subnet_cmd += ' --ip-version 6'
cmds.append(subnet_cmd)
logging.debug("Neutron external network commands determined "
"as: {}".format(cmds))
diff --git a/apex/overcloud/node.py b/apex/overcloud/node.py
new file mode 100644
index 00000000..622d1fd1
--- /dev/null
+++ b/apex/overcloud/node.py
@@ -0,0 +1,147 @@
+##############################################################################
+# Copyright (c) 2018 Tim Rozet (trozet@redhat.com) and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+import logging
+import os
+import shutil
+import xml.etree.ElementTree as ET
+
+import distro
+import libvirt
+
+from apex.common.exceptions import OvercloudNodeException
+
+
+class OvercloudNode:
+ """
+ Overcloud server
+ """
+ def __init__(self, role, ip, ovs_ctrlrs, ovs_mgrs, name, node_xml,
+ disk_img):
+ self.role = role
+ self.ip = ip
+ self.ovs_ctrlrs = ovs_ctrlrs
+ self.ovs_mgrs = ovs_mgrs
+ self.name = name
+ self.node_xml_file = node_xml
+ self.node_xml = None
+ self.vm = None
+ self.disk_img = None
+ if not os.path.isfile(self.node_xml_file):
+ raise OvercloudNodeException('XML definition file not found: '
+ '{}'.format(self.node_xml_file))
+ if not os.path.isfile(disk_img):
+ raise OvercloudNodeException('Disk image file not found: '
+ '{}'.format(disk_img))
+ self.conn = libvirt.open('qemu:///system')
+ if not self.conn:
+ raise OvercloudNodeException('Unable to open libvirt connection')
+
+ self.create(src_disk=disk_img)
+
+ def _configure_disk(self, disk):
+ # find default storage pool path
+ pool = self.conn.storagePoolLookupByName('default')
+ if pool is None:
+ raise OvercloudNodeException('Cannot find default storage pool')
+ pool_xml = pool.XMLDesc()
+ logging.debug('Default storage pool xml: {}'.format(pool_xml))
+ etree = ET.fromstring(pool_xml)
+ try:
+ path = etree.find('target').find('path').text
+ logging.info('System libvirt default pool path: {}'.format(path))
+ except AttributeError as e:
+ logging.error('Failure to find libvirt storage path: {}'.format(
+ e))
+ raise OvercloudNodeException('Cannot find default storage path')
+ # copy disk to system path
+ self.disk_img = os.path.join(path, os.path.basename(disk))
+ logging.info('Copying disk image to: {}. This may take some '
+ 'time...'.format(self.disk_img))
+ shutil.copyfile(disk, self.disk_img)
+
+ @staticmethod
+ def _update_xml(xml, disk_path=None):
+ """
+ Updates a libvirt XML file for the current architecture and OS of this
+ machine
+ :param xml: XML string of Libvirt domain definition
+ :param disk_path: Optional file path to update for the backing disk
+ image
+ :return: Updated XML
+ """
+ logging.debug('Parsing xml')
+ try:
+ etree = ET.fromstring(xml)
+ except ET.ParseError:
+ logging.error('Unable to parse node XML: {}'.format(xml))
+ raise OvercloudNodeException('Unable to parse node XML')
+
+ try:
+ type_element = etree.find('os').find('type')
+ if 'machine' in type_element.keys():
+ type_element.set('machine', 'pc')
+ logging.debug('XML updated with machine "pc"')
+ except AttributeError:
+ logging.warning('Failure to set XML machine type')
+
+ # qemu-kvm path may differ per system, need to detect it and update xml
+ linux_ver = distro.linux_distribution()[0]
+ if linux_ver == 'Fedora':
+ qemu_path = '/usr/bin/qemu-kvm'
+ else:
+ qemu_path = '/usr/libexec/qemu-kvm'
+
+ try:
+ etree.find('devices').find('emulator').text = qemu_path
+ logging.debug('XML updated with emulator location: '
+ '{}'.format(qemu_path))
+ xml = ET.tostring(etree).decode('utf-8')
+ except AttributeError:
+ logging.warning('Failure to update XML qemu path')
+
+ if disk_path:
+ try:
+ disk_element = etree.find('devices').find('disk').find(
+ 'source')
+ disk_element.set('file', disk_path)
+ logging.debug('XML updated with file path: {}'.format(
+ disk_path))
+ except AttributeError:
+ logging.error('Failure to parse XML and set disk type')
+ raise OvercloudNodeException(
+ 'Unable to set new disk path in xml {}'.format(xml))
+
+ return ET.tostring(etree).decode('utf-8')
+
+ def create(self, src_disk):
+ # copy disk to pool and get new disk location
+ logging.debug('Preparing disk image')
+ self._configure_disk(src_disk)
+ logging.debug('Parsing node XML from {}'.format(self.node_xml_file))
+ with open(self.node_xml_file, 'r') as fh:
+ self.node_xml = fh.read()
+ # if machine is not pc we need to set, also need to update qemu-kvm and
+ # storage location
+ self.node_xml = self._update_xml(self.node_xml, self.disk_img)
+ logging.info('Creating node {} in libvirt'.format(self.name))
+ self.vm = self.conn.defineXML(self.node_xml)
+
+ def start(self):
+ """
+ Boot node in libvirt
+ :return:
+ """
+ try:
+ self.vm.create()
+ logging.info('Node {} started'.format(self.name))
+ except libvirt.libvirtError as e:
+ logging.error('Failed to start domain: {}'.format(self.name))
+ raise OvercloudNodeException('Failed to start VM. Reason: '
+ '{}'.format(e))
diff --git a/apex/settings/deploy_settings.py b/apex/settings/deploy_settings.py
index 29fe64fb..9f8a6f18 100644
--- a/apex/settings/deploy_settings.py
+++ b/apex/settings/deploy_settings.py
@@ -27,7 +27,8 @@ REQ_DEPLOY_SETTINGS = ['sdn_controller',
'l2gw',
'sriov',
'containers',
- 'ceph_device']
+ 'ceph_device',
+ 'vim']
OPT_DEPLOY_SETTINGS = ['performance',
'vsperf',
@@ -113,6 +114,8 @@ class DeploySettings(dict):
elif req_set == 'os_version':
self['deploy_options'][req_set] = \
constants.DEFAULT_OS_VERSION
+ elif req_set == 'vim':
+ self['deploy_options'][req_set] = 'openstack'
else:
self['deploy_options'][req_set] = False
elif req_set == 'odl_version' and self['deploy_options'][
@@ -126,9 +129,6 @@ class DeploySettings(dict):
"Invalid SRIOV interface name: {}".format(
self['deploy_options']['sriov']))
- if self['deploy_options']['odl_version'] == 'oxygen':
- self['deploy_options']['odl_version'] = 'master'
-
if 'performance' in deploy_options:
if not isinstance(deploy_options['performance'], dict):
raise DeploySettingsException("Performance deploy_option"
diff --git a/apex/tests/config/98faaca.diff b/apex/tests/config/98faaca.diff
index 68a66fbc..96462d5f 100644
--- a/apex/tests/config/98faaca.diff
+++ b/apex/tests/config/98faaca.diff
@@ -17,7 +17,7 @@ specified in environments/services-docker/update-odl.yaml.
Upgrading ODL to the next major release (1.1->2) requires
only the L2 steps. These are implemented as upgrade_tasks and
-post_upgrade_tasks in https://review.openstack.org/489201.
+post_upgrade_tasks in https://review.opendev.org/489201.
Steps involved in level 2 update are
1. Block OVS instances to connect to ODL
diff --git a/apex/tests/config/admin.xml b/apex/tests/config/admin.xml
new file mode 100644
index 00000000..69b15b1f
--- /dev/null
+++ b/apex/tests/config/admin.xml
@@ -0,0 +1,7 @@
+<network connections='1' ipv6='yes'>
+ <name>admin</name>
+ <uuid>761c34f8-2a72-4205-8e69-5ed6626c6efa</uuid>
+ <forward mode='bridge'/>
+ <bridge name='br-admin'/>
+ <virtualport type='openvswitch'/>
+</network>
diff --git a/apex/tests/config/baremetal0.xml b/apex/tests/config/baremetal0.xml
new file mode 100644
index 00000000..4ff8f65a
--- /dev/null
+++ b/apex/tests/config/baremetal0.xml
@@ -0,0 +1,73 @@
+<domain type='kvm'>
+ <name>baremetal0</name>
+ <uuid>25bf15b6-130c-4bca-87af-e5cbc14bb454</uuid>
+ <memory unit='KiB'>12582912</memory>
+ <currentMemory unit='KiB'>12582912</currentMemory>
+ <vcpu placement='static'>4</vcpu>
+ <resource>
+ <partition>/machine</partition>
+ </resource>
+ <os>
+ <type arch='x86_64' machine='pc-i440fx-rhel7.0.0'>hvm</type>
+ <boot dev='hd'/>
+ <bootmenu enable='no'/>
+ </os>
+ <features>
+ <acpi/>
+ <apic/>
+ <pae/>
+ </features>
+ <cpu mode='host-passthrough'/>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <devices>
+ <emulator>/usr/libexec/qemu-kvm</emulator>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2' cache='unsafe'/>
+ <source file='/home/images/baremetal0.qcow2'/>
+ <target dev='sda' bus='sata'/>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <controller type='scsi' index='0' model='virtio-scsi'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
+ </controller>
+ <controller type='usb' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <controller type='sata' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
+ </controller>
+ <interface type='bridge'>
+ <mac address='00:5b:06:25:0c:dc'/>
+ <source bridge='br-admin'/>
+ <virtualport type='openvswitch'>
+ <parameters interfaceid='04b63cb9-21a9-4385-bbd6-df677a5eeecf'/>
+ </virtualport>
+ <model type='virtio'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+ </interface>
+ <serial type='pty'>
+ <target port='0'/>
+ </serial>
+ <console type='pty'>
+ <target type='serial' port='0'/>
+ </console>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'>
+ <listen type='address' address='127.0.0.1'/>
+ </graphics>
+ <video>
+ <model type='cirrus' vram='16384' heads='1' primary='yes'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
+ </video>
+ <memballoon model='virtio'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
+ </memballoon>
+ </devices>
+ <seclabel type='dynamic' model='selinux' relabel='yes'/>
+ <seclabel type='dynamic' model='dac' relabel='yes'/>
+</domain>
diff --git a/apex/tests/config/common-patches.yaml b/apex/tests/config/common-patches.yaml
new file mode 100644
index 00000000..fef8fcd0
--- /dev/null
+++ b/apex/tests/config/common-patches.yaml
@@ -0,0 +1,6 @@
+---
+patches:
+ queens:
+ undercloud:
+ - change-id: I2e0a40d7902f592e4b7bd727f57048111e0bea36
+ project: openstack/tripleo-common
diff --git a/apex/tests/config/dummy-deploy-settings.yaml b/apex/tests/config/dummy-deploy-settings.yaml
new file mode 100644
index 00000000..54890f38
--- /dev/null
+++ b/apex/tests/config/dummy-deploy-settings.yaml
@@ -0,0 +1,19 @@
+---
+global_params:
+ ha_enabled: false
+ patches:
+ undercloud:
+ - change-id: I2e0a40d7902f592e4b7bd727f57048111e0bea36
+ project: openstack/tripleo-common
+ overcloud:
+ - change-id: Ie988ba6a2d444a614e97c0edf5fce24b23970310
+ project: openstack/puppet-tripleo
+deploy_options:
+ containers: true
+ os_version: queens
+ sdn_controller: opendaylight
+ odl_version: oxygen
+ tacker: false
+ congress: false
+ sfc: false
+ vpn: false
diff --git a/apex/tests/config/inventory-virt-1-compute-node.yaml b/apex/tests/config/inventory-virt-1-compute-node.yaml
new file mode 100644
index 00000000..4c2dc5d4
--- /dev/null
+++ b/apex/tests/config/inventory-virt-1-compute-node.yaml
@@ -0,0 +1,14 @@
+---
+nodes:
+ node0:
+ arch: x86_64
+ capabilities: profile:compute
+ cpu: 4
+ disk: 41
+ ipmi_ip: 192.168.122.1
+ ipmi_pass: password
+ ipmi_user: admin
+ mac_address: 00:a8:58:29:f9:99
+ memory: 10240
+ pm_port: 6230
+ pm_type: pxe_ipmitool
diff --git a/apex/tests/config/node.yaml b/apex/tests/config/node.yaml
new file mode 100644
index 00000000..e05644c9
--- /dev/null
+++ b/apex/tests/config/node.yaml
@@ -0,0 +1,12 @@
+---
+servers:
+ overcloud-controller-0.opnfvlf.org:
+ address: 192.0.2.28
+ orig-ctl-mac: 00:5b:06:25:0c:dc
+ ovs-controller: tcp:192.0.2.28:6653
+ ovs-managers:
+ - ptcp:6639:127.0.0.1
+ - tcp:192.0.2.28:6640
+ type: controller
+ user: heat-admin
+ vNode-name: baremetal0
diff --git a/apex/tests/config/snapshot.properties b/apex/tests/config/snapshot.properties
new file mode 100644
index 00000000..64c149e2
--- /dev/null
+++ b/apex/tests/config/snapshot.properties
@@ -0,0 +1,2 @@
+OPNFV_SNAP_URL=artifacts.opnfv.org/apex/master/noha/apex-csit-snap-2018-08-05.tar.gz
+OPNFV_SNAP_SHA512SUM=bb0c6fa0e675dcb39cfad11d81bb99f309d5cfc236e36a74d05ee813584f3e5bb92aa23dec775846317b75d574f8c86186c666f78a299c24fb68849897bdd4bc
diff --git a/apex/tests/test_apex_build_utils.py b/apex/tests/test_apex_build_utils.py
index f18103c8..36caaf1f 100644
--- a/apex/tests/test_apex_build_utils.py
+++ b/apex/tests/test_apex_build_utils.py
@@ -178,6 +178,12 @@ class TestBuildUtils(unittest.TestCase):
self.assertNotRegex(tmp_patch, 'Steps of upgrade are as follows')
self.assertNotRegex(tmp_patch, 'Steps invlolved in level 2 update')
+ def test_is_path_in_patch(self):
+ with open(os.path.join(con.TEST_DUMMY_CONFIG, '98faaca.diff')) as fh:
+ dummy_patch = fh.read()
+ self.assertTrue(build_utils.is_path_in_patch(dummy_patch,
+ 'releasenotes/'))
+
def test_strip_no_patch_sections(self):
with open(os.path.join(con.TEST_DUMMY_CONFIG, '98faaca.diff')) as fh:
dummy_patch = fh.read()
diff --git a/apex/tests/test_apex_common_builder.py b/apex/tests/test_apex_common_builder.py
index 09bd2545..3ff95bb5 100644
--- a/apex/tests/test_apex_common_builder.py
+++ b/apex/tests/test_apex_common_builder.py
@@ -24,6 +24,8 @@ DOCKER_YAML = {
}
}
+a_mock_open = mock_open(read_data=None)
+
class TestCommonBuilder(unittest.TestCase):
@classmethod
@@ -55,7 +57,8 @@ class TestCommonBuilder(unittest.TestCase):
dummy_change = {'submitted': '2017-06-05 20:23:09.000000000',
'status': 'MERGED'}
self.assertTrue(c_builder.is_patch_promoted(dummy_change,
- 'master'))
+ 'master',
+ con.DOCKERHUB_OOO))
def test_is_patch_promoted_docker(self):
dummy_change = {'submitted': '2017-06-05 20:23:09.000000000',
@@ -63,13 +66,15 @@ class TestCommonBuilder(unittest.TestCase):
dummy_image = 'centos-binary-opendaylight'
self.assertTrue(c_builder.is_patch_promoted(dummy_change,
'master',
+ con.DOCKERHUB_OOO,
docker_image=dummy_image))
def test_patch_not_promoted(self):
dummy_change = {'submitted': '2900-06-05 20:23:09.000000000',
'status': 'MERGED'}
self.assertFalse(c_builder.is_patch_promoted(dummy_change,
- 'master'))
+ 'master',
+ con.DOCKERHUB_OOO))
def test_patch_not_promoted_docker(self):
dummy_change = {'submitted': '2900-06-05 20:23:09.000000000',
@@ -77,13 +82,15 @@ class TestCommonBuilder(unittest.TestCase):
dummy_image = 'centos-binary-opendaylight'
self.assertFalse(c_builder.is_patch_promoted(dummy_change,
'master',
+ con.DOCKERHUB_OOO,
docker_image=dummy_image))
def test_patch_not_promoted_and_not_merged(self):
dummy_change = {'submitted': '2900-06-05 20:23:09.000000000',
'status': 'BLAH'}
self.assertFalse(c_builder.is_patch_promoted(dummy_change,
- 'master'))
+ 'master',
+ con.DOCKERHUB_OOO))
@patch('builtins.open', mock_open())
@patch('apex.builders.common_builder.is_patch_promoted')
@@ -239,7 +246,8 @@ class TestCommonBuilder(unittest.TestCase):
'/dummytmp/dummyrepo.tar')
def test_project_to_docker_image(self):
- found_services = c_builder.project_to_docker_image(project='nova')
+ found_services = c_builder.project_to_docker_image('nova',
+ con.DOCKERHUB_OOO)
assert 'nova-api' in found_services
@patch('apex.common.utils.open_webpage')
@@ -248,4 +256,55 @@ class TestCommonBuilder(unittest.TestCase):
mock_open_web.return_value = b'{"blah": "blah"}'
self.assertRaises(exceptions.ApexCommonBuilderException,
c_builder.project_to_docker_image,
- 'nova')
+ 'nova',
+ con.DOCKERHUB_OOO)
+
+ def test_get_neutron_driver(self):
+ ds_opts = {'dataplane': 'fdio',
+ 'sdn_controller': 'opendaylight',
+ 'odl_version': 'master',
+ 'vpn': False,
+ 'sriov': False}
+ self.assertEquals(c_builder.get_neutron_driver(ds_opts),
+ 'odl')
+ ds_opts['sdn_controller'] = None
+ ds_opts['vpp'] = True
+ self.assertEquals(c_builder.get_neutron_driver(ds_opts),
+ 'vpp')
+ ds_opts['sdn_controller'] = 'ovn'
+ self.assertEquals(c_builder.get_neutron_driver(ds_opts),
+ 'ovn')
+
+ @patch('apex.builders.common_builder.yaml')
+ @patch('apex.overcloud.deploy.os.path.isfile')
+ @patch('builtins.open', a_mock_open, create=True)
+ def test_prepare_container_images(self, mock_is_file, mock_yaml):
+ mock_yaml.safe_load.return_value = {
+ 'parameter_defaults': {
+ 'ContainerImagePrepare': [
+ {'set':
+ {'namespace': 'blah',
+ 'neutron_driver': 'null',
+ }
+ }
+ ]
+ }
+ }
+ expected_output = {
+ 'parameter_defaults': {
+ 'ContainerImagePrepare': [
+ {'set':
+ {'namespace': 'docker.io/tripleoqueens',
+ 'neutron_driver': 'odl',
+ }
+ }
+ ]
+ }
+ }
+
+ c_builder.prepare_container_images('dummy.yaml', 'queens',
+ 'odl')
+ mock_yaml.safe_dump.assert_called_with(
+ expected_output,
+ a_mock_open.return_value,
+ default_flow_style=False)
diff --git a/apex/tests/test_apex_common_utils.py b/apex/tests/test_apex_common_utils.py
index 0e4041ca..1ecb7df6 100644
--- a/apex/tests/test_apex_common_utils.py
+++ b/apex/tests/test_apex_common_utils.py
@@ -64,8 +64,11 @@ class TestCommonUtils:
def test_run_ansible(self):
playbook = 'apex/tests/playbooks/test_playbook.yaml'
+ extra_vars = [{'testvar1': 'value1', 'testvar2': 'value2'}]
assert_equal(utils.run_ansible(None, os.path.join(playbook),
dry_run=True), None)
+ assert_equal(utils.run_ansible(extra_vars, os.path.join(playbook),
+ dry_run=True, host='1.1.1.1'), None)
def test_failed_run_ansible(self):
playbook = 'apex/tests/playbooks/test_failed_playbook.yaml'
@@ -81,7 +84,7 @@ class TestCommonUtils:
def test_fetch_upstream_previous_file(self):
test_file = 'overcloud-full.tar.md5'
- url = 'https://images.rdoproject.org/master/delorean/' \
+ url = 'https://images.rdoproject.org/master/rdo_trunk/' \
'current-tripleo/stable/'
os.makedirs('/tmp/fetch_test', exist_ok=True)
open("/tmp/fetch_test/{}".format(test_file), 'w').close()
@@ -132,7 +135,7 @@ class TestCommonUtils:
assert output is not None
def test_open_invalid_webpage(self):
- assert_raises(urllib.request.URLError, utils.open_webpage,
+ assert_raises(exceptions.FetchException, utils.open_webpage,
'http://inv4lIdweb-page.com')
@patch('builtins.open', a_mock_open)
@@ -148,3 +151,12 @@ class TestCommonUtils:
new_data = {'parameter_defaults': settings}
mock_yaml_dump.assert_called_once_with(new_data, a_mock_open(),
default_flow_style=False)
+
+ def test_unique(self):
+ dummy_list = [1, 2, 1, 3, 4, 5, 5]
+ assert_equal(utils.unique(dummy_list), [1, 2, 3, 4, 5])
+
+ def test_find_container_client(self):
+ for version in 'rocky', 'queens':
+ assert_equal(utils.find_container_client(version), 'docker')
+ assert_equal(utils.find_container_client('master'), 'podman')
diff --git a/apex/tests/test_apex_deploy.py b/apex/tests/test_apex_deploy.py
index 6c2a185d..004c21c1 100644
--- a/apex/tests/test_apex_deploy.py
+++ b/apex/tests/test_apex_deploy.py
@@ -8,6 +8,7 @@
##############################################################################
import argparse
+import os
import unittest
from mock import patch
@@ -17,12 +18,12 @@ from mock import mock_open
from apex.common.exceptions import ApexDeployException
from apex.common.constants import DEFAULT_OS_VERSION
-from apex.deploy import deploy_quickstart
from apex.deploy import validate_cross_settings
from apex.deploy import build_vms
from apex.deploy import create_deploy_parser
from apex.deploy import validate_deploy_args
from apex.deploy import main
+from apex.tests.constants import TEST_DUMMY_CONFIG
from nose.tools import (
assert_is_instance,
@@ -48,9 +49,6 @@ class TestDeploy(unittest.TestCase):
def teardown(self):
"""This method is run once after _each_ test method is executed"""
- def test_deloy_quickstart(self):
- deploy_quickstart(None, None, None)
-
def test_validate_cross_settings(self):
deploy_settings = {'deploy_options': {'dataplane': 'ovs'}}
net_settings = Mock()
@@ -85,12 +83,23 @@ class TestDeploy(unittest.TestCase):
args = Mock()
args.inventory_file = None
args.virtual = True
+ args.snapshot = False
+ validate_deploy_args(args)
+
+ def test_validate_snapshot_deploy_args(self):
+ args = Mock()
+ args.deploy_settings_file = os.path.join(TEST_DUMMY_CONFIG,
+ 'dummy-deploy-settings.yaml')
+ args.inventory_file = None
+ args.virtual = True
+ args.snapshot = True
validate_deploy_args(args)
def test_validate_deploy_args_no_virt_no_inv(self):
args = Mock()
args.inventory_file = 'file_name'
args.virtual = False
+ args.snapshot = False
assert_raises(ApexDeployException, validate_deploy_args, args)
@patch('apex.deploy.os.path')
@@ -99,14 +108,19 @@ class TestDeploy(unittest.TestCase):
args = Mock()
args.inventory_file = None
args.virtual = True
+ args.snapshot = False
assert_raises(ApexDeployException, validate_deploy_args, args)
def test_validate_deploy_args_virt_and_inv_file(self):
args = Mock()
args.inventory_file = 'file_name'
args.virtual = True
+ args.snapshot = False
assert_raises(ApexDeployException, validate_deploy_args, args)
+ @patch('apex.deploy.c_builder')
+ @patch('apex.deploy.ApexDeployment')
+ @patch('apex.deploy.uc_builder')
@patch('apex.deploy.network_data.create_network_data')
@patch('apex.deploy.shutil')
@patch('apex.deploy.oc_deploy')
@@ -132,7 +146,8 @@ class TestDeploy(unittest.TestCase):
mock_deploy_sets, mock_net_sets, mock_net_env,
mock_utils, mock_parsers, mock_oc_cfg,
mock_virt_utils, mock_inv, mock_build_vms, mock_uc_lib,
- mock_oc_deploy, mock_shutil, mock_network_data):
+ mock_oc_deploy, mock_shutil, mock_network_data,
+ mock_uc_builder, mock_deployment, mock_c_builder):
net_sets_dict = {'networks': MagicMock(),
'dns_servers': 'test'}
ds_opts_dict = {'global_params': MagicMock(),
@@ -142,6 +157,7 @@ class TestDeploy(unittest.TestCase):
'dataplane': 'ovs',
'sfc': False,
'vpn': False,
+ 'vim': 'openstack',
'yardstick': 'test',
'os_version': DEFAULT_OS_VERSION,
'containers': False}}
@@ -149,7 +165,8 @@ class TestDeploy(unittest.TestCase):
args.virtual = False
args.quickstart = False
args.debug = False
- args.upstream = False
+ args.snapshot = False
+ args.upstream = True
net_sets = mock_net_sets.return_value
net_sets.enabled_network_list = ['external']
net_sets.__getitem__.side_effect = net_sets_dict.__getitem__
@@ -160,6 +177,7 @@ class TestDeploy(unittest.TestCase):
mock_parsers.parse_nova_output.return_value = {'testnode1': 'test'}
main()
+ @patch('apex.deploy.SnapshotDeployment')
@patch('apex.deploy.validate_cross_settings')
@patch('apex.deploy.virt_utils')
@patch('apex.deploy.utils')
@@ -170,15 +188,19 @@ class TestDeploy(unittest.TestCase):
@patch('apex.deploy.os')
@patch('apex.deploy.create_deploy_parser')
@patch('builtins.open', a_mock_open, create=True)
- def test_main_qs(self, mock_parser, mock_os, mock_deploy,
- mock_net_sets, mock_net_env, mock_inv, mock_utils,
- mock_virt_utils, mock_cross):
+ def test_main_snapshot(self, mock_parser, mock_os, mock_deploy,
+ mock_net_sets, mock_net_env, mock_inv, mock_utils,
+ mock_virt_utils, mock_cross, mock_snap_deployment):
args = mock_parser.return_value.parse_args.return_value
args.virtual = False
- args.quickstart = True
+ args.snapshot = True
args.debug = True
main()
+ mock_snap_deployment.assert_called()
+ @patch('apex.deploy.c_builder')
+ @patch('apex.deploy.ApexDeployment')
+ @patch('apex.deploy.uc_builder')
@patch('apex.deploy.network_data.create_network_data')
@patch('apex.deploy.shutil')
@patch('apex.deploy.oc_deploy')
@@ -204,7 +226,8 @@ class TestDeploy(unittest.TestCase):
mock_deploy_sets, mock_net_sets, mock_net_env,
mock_utils, mock_parsers, mock_oc_cfg,
mock_virt_utils, mock_inv, mock_build_vms, mock_uc_lib,
- mock_oc_deploy, mock_shutil, mock_network_data):
+ mock_oc_deploy, mock_shutil, mock_network_data,
+ mock_uc_builder, mock_deployment, mock_c_builder):
# didn't work yet line 412
# net_sets_dict = {'networks': {'admin': {'cidr': MagicMock()}},
# 'dns_servers': 'test'}
@@ -216,6 +239,7 @@ class TestDeploy(unittest.TestCase):
'dataplane': 'ovs',
'sfc': False,
'vpn': False,
+ 'vim': 'openstack',
'yardstick': 'test',
'os_version': DEFAULT_OS_VERSION,
'containers': False}}
@@ -228,7 +252,8 @@ class TestDeploy(unittest.TestCase):
args.virt_compute_nodes = 1
args.virt_compute_ram = None
args.virt_default_ram = 12
- args.upstream = False
+ args.upstream = True
+ args.snapshot = False
net_sets = mock_net_sets.return_value
net_sets.enabled_network_list = ['admin']
deploy_sets = mock_deploy_sets.return_value
@@ -239,6 +264,7 @@ class TestDeploy(unittest.TestCase):
args.virt_default_ram = 10
main()
+ @patch('apex.deploy.ApexDeployment')
@patch('apex.deploy.c_builder')
@patch('apex.deploy.uc_builder')
@patch('apex.deploy.oc_builder')
@@ -268,7 +294,7 @@ class TestDeploy(unittest.TestCase):
mock_utils, mock_parsers, mock_oc_cfg, mock_virt_utils,
mock_inv, mock_build_vms, mock_uc_lib, mock_oc_deploy,
mock_shutil, mock_network_data, mock_oc_builder,
- mock_uc_builder, mock_c_builder):
+ mock_uc_builder, mock_c_builder, mock_deployment):
ds_opts_dict = {'global_params': MagicMock(),
'deploy_options': {'gluon': False,
@@ -277,6 +303,7 @@ class TestDeploy(unittest.TestCase):
'dataplane': 'ovs',
'sfc': False,
'vpn': False,
+ 'vim': 'openstack',
'yardstick': 'test',
'os_version': DEFAULT_OS_VERSION,
'containers': True}}
@@ -290,6 +317,7 @@ class TestDeploy(unittest.TestCase):
args.virt_compute_ram = None
args.virt_default_ram = 12
args.upstream = True
+ args.snapshot = False
net_sets = mock_net_sets.return_value
net_sets.enabled_network_list = ['admin']
deploy_sets = mock_deploy_sets.return_value
@@ -299,6 +327,67 @@ class TestDeploy(unittest.TestCase):
args.virt_compute_ram = 16
args.virt_default_ram = 10
main()
- mock_oc_deploy.prep_image.assert_called
+ mock_oc_deploy.prep_image.assert_called()
# TODO(trozet) add assertions here with arguments for functions in
# deploy main
+
+ @patch('apex.deploy.c_builder')
+ @patch('apex.deploy.ApexDeployment')
+ @patch('apex.deploy.uc_builder')
+ @patch('apex.deploy.network_data.create_network_data')
+ @patch('apex.deploy.shutil')
+ @patch('apex.deploy.git')
+ @patch('apex.deploy.oc_deploy')
+ @patch('apex.deploy.uc_lib')
+ @patch('apex.deploy.build_vms')
+ @patch('apex.deploy.Inventory')
+ @patch('apex.deploy.virt_utils')
+ @patch('apex.deploy.oc_cfg')
+ @patch('apex.deploy.parsers')
+ @patch('apex.deploy.utils')
+ @patch('apex.deploy.NetworkEnvironment')
+ @patch('apex.deploy.NetworkSettings')
+ @patch('apex.deploy.DeploySettings')
+ @patch('apex.deploy.os')
+ @patch('apex.deploy.json')
+ @patch('apex.deploy.jumphost')
+ @patch('apex.deploy.validate_cross_settings')
+ @patch('apex.deploy.validate_deploy_args')
+ @patch('apex.deploy.create_deploy_parser')
+ @patch('builtins.open', a_mock_open, create=True)
+ def test_main_k8s(self, mock_parser, mock_val_args, mock_cross_sets,
+ mock_jumphost, mock_json, mock_os,
+ mock_deploy_sets, mock_net_sets, mock_net_env,
+ mock_utils, mock_parsers, mock_oc_cfg,
+ mock_virt_utils, mock_inv, mock_build_vms, mock_uc_lib,
+ mock_oc_deploy, mock_git, mock_shutil,
+ mock_network_data, mock_uc_builder, mock_deployment,
+ mock_c_builder):
+ net_sets_dict = {'networks': MagicMock(),
+ 'dns_servers': 'test'}
+ ds_opts_dict = {'global_params': MagicMock(),
+ 'deploy_options': {'gluon': False,
+ 'congress': True,
+ 'sdn_controller': False,
+ 'dataplane': 'ovs',
+ 'sfc': False,
+ 'vpn': False,
+ 'vim': 'k8s',
+ 'yardstick': 'test',
+ 'os_version': DEFAULT_OS_VERSION,
+ 'containers': False}}
+ args = mock_parser.return_value.parse_args.return_value
+ args.virtual = False
+ args.quickstart = False
+ args.debug = False
+ args.upstream = False
+ args.snapshot = False
+ net_sets = mock_net_sets.return_value
+ net_sets.enabled_network_list = ['external']
+ net_sets.__getitem__.side_effect = net_sets_dict.__getitem__
+ net_sets.__contains__.side_effect = net_sets_dict.__contains__
+ deploy_sets = mock_deploy_sets.return_value
+ deploy_sets.__getitem__.side_effect = ds_opts_dict.__getitem__
+ deploy_sets.__contains__.side_effect = ds_opts_dict.__contains__
+ mock_parsers.parse_nova_output.return_value = {'testnode1': 'test'}
+ main()
diff --git a/apex/tests/test_apex_deployment_snapshot.py b/apex/tests/test_apex_deployment_snapshot.py
new file mode 100644
index 00000000..d7542585
--- /dev/null
+++ b/apex/tests/test_apex_deployment_snapshot.py
@@ -0,0 +1,374 @@
+##############################################################################
+# Copyright (c) 2018 Tim Rozet (trozet@redhat.com) (Red Hat)
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+from mock import patch
+import os
+import unittest
+import urllib.request
+
+from apex.common import exceptions as exc
+from apex.deployment.snapshot import SnapshotDeployment
+from apex.settings.deploy_settings import DeploySettings
+from apex.tests.constants import TEST_DUMMY_CONFIG
+
+DUMMY_SNAP_DIR = '/tmp/dummy_cache'
+
+
+class TestSnapshotDeployment(unittest.TestCase):
+ @classmethod
+ def setup_class(cls):
+ """This method is run once for each class before any tests are run"""
+
+ @classmethod
+ def teardown_class(cls):
+ """This method is run once for each class _after_ all tests are run"""
+
+ def setup(self):
+ """This method is run once before _each_ test method is executed"""
+
+ def teardown(self):
+ """This method is run once after _each_ test method is executed"""
+
+ @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot')
+ @patch('apex.deployment.snapshot.libvirt.open')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot')
+ def test_init(self, mock_deploy_snap, mock_libvirt_open, mock_pull_snap):
+
+ ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml')
+ ds = DeploySettings(ds_file)
+ d = SnapshotDeployment(deploy_settings=ds,
+ snap_cache_dir=DUMMY_SNAP_DIR,
+ fetch=True, all_in_one=False)
+ snap_dir = os.path.join(DUMMY_SNAP_DIR, 'queens', 'noha')
+ self.assertEqual(d.snap_cache_dir, snap_dir)
+ mock_pull_snap.assert_called()
+ mock_deploy_snap.assert_called()
+ self.assertEqual(d.ha_ext, 'noha')
+
+ @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot')
+ @patch('apex.deployment.snapshot.libvirt.open')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot')
+ def test_init_allinone_no_fetch(self, mock_deploy_snap, mock_libvirt_open,
+ mock_pull_snap):
+
+ ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml')
+ ds = DeploySettings(ds_file)
+ d = SnapshotDeployment(deploy_settings=ds,
+ snap_cache_dir=DUMMY_SNAP_DIR,
+ fetch=False, all_in_one=True)
+ snap_dir = os.path.join(DUMMY_SNAP_DIR, 'queens', 'noha-allinone')
+ self.assertEqual(d.snap_cache_dir, snap_dir)
+ mock_pull_snap.assert_not_called()
+ mock_deploy_snap.assert_called()
+ self.assertEqual(d.ha_ext, 'noha-allinone')
+
+ @patch('apex.deployment.snapshot.utils.fetch_upstream_and_unpack')
+ @patch('apex.deployment.snapshot.utils.fetch_properties')
+ def test_pull_snapshot_is_latest(self, mock_fetch_props,
+ mock_fetch_artifact):
+ mock_fetch_props.return_value = {
+ 'OPNFV_SNAP_URL': 'artifacts.opnfv.org/apex/master/noha/'
+ 'apex-csit-snap-2018-08-05.tar.gz',
+ 'OPNFV_SNAP_SHA512SUM': 'bb0c6fa0e675dcb39cfad11d81bb99f309d5cfc23'
+ '6e36a74d05ee813584f3e5bb92aa23dec77584631'
+ '7b75d574f8c86186c666f78a299c24fb68849897b'
+ 'dd4bc'
+ }
+ SnapshotDeployment.pull_snapshot('http://dummy_url',
+ TEST_DUMMY_CONFIG)
+ mock_fetch_artifact.assert_not_called()
+
+ @patch('apex.deployment.snapshot.utils.fetch_upstream_and_unpack')
+ @patch('apex.deployment.snapshot.utils.fetch_properties')
+ def test_pull_snapshot_fetch_props_failure(self, mock_fetch_props,
+ mock_fetch_artifact):
+ mock_fetch_props.side_effect = exc.FetchException
+ self.assertRaises(exc.FetchException,
+ SnapshotDeployment.pull_snapshot,
+ 'http://dummy_url', TEST_DUMMY_CONFIG)
+
+ @patch('apex.deployment.snapshot.utils.fetch_upstream_and_unpack')
+ @patch('apex.deployment.snapshot.utils.fetch_properties')
+ def test_pull_snapshot_is_not_latest(self, mock_fetch_props,
+ mock_fetch_artifact):
+ mock_fetch_props.side_effect = [{
+ 'OPNFV_SNAP_URL': 'artifacts.opnfv.org/apex/master/noha/'
+ 'apex-csit-snap-2018-08-05.tar.gz',
+ 'OPNFV_SNAP_SHA512SUM': '123c6fa0e675dcb39cfad11d81bb99f309d5cfc23'
+ '6e36a74d05ee813584f3e5bb92aa23dec77584631'
+ '7b75d574f8c86186c666f78a299c24fb68849897b'
+ 'dd4bc'},
+ {
+ 'OPNFV_SNAP_URL': 'artifacts.opnfv.org/apex/master/noha/'
+ 'apex-csit-snap-2018-08-05.tar.gz',
+ 'OPNFV_SNAP_SHA512SUM': 'bb0c6fa0e675dcb39cfad11d81bb99f309d5cfc23'
+ '6e36a74d05ee813584f3e5bb92aa23dec77584631'
+ '7b75d574f8c86186c666f78a299c24fb68849897b'
+ 'dd4bc'}]
+ SnapshotDeployment.pull_snapshot('http://dummy_url',
+ TEST_DUMMY_CONFIG)
+ mock_fetch_artifact.assert_called()
+
+ @patch('apex.deployment.snapshot.OvercloudNode')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot')
+ @patch('apex.deployment.snapshot.libvirt.open')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot')
+ def test_create_networks(self, mock_deploy_snap, mock_libvirt_open,
+ mock_pull_snap, mock_oc_node):
+ ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml')
+ ds = DeploySettings(ds_file)
+ d = SnapshotDeployment(deploy_settings=ds,
+ snap_cache_dir=DUMMY_SNAP_DIR,
+ fetch=False, all_in_one=False)
+ d.snap_cache_dir = TEST_DUMMY_CONFIG
+ conn = mock_libvirt_open('qemu:///system')
+ d.create_networks()
+ conn.networkCreateXML.assert_called()
+
+ @patch('apex.deployment.snapshot.OvercloudNode')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot')
+ @patch('apex.deployment.snapshot.libvirt.open')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot')
+ def test_create_networks_invalid_cache(self, mock_deploy_snap,
+ mock_libvirt_open, mock_pull_snap,
+ mock_oc_node):
+ ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml')
+ ds = DeploySettings(ds_file)
+ d = SnapshotDeployment(deploy_settings=ds,
+ snap_cache_dir=DUMMY_SNAP_DIR,
+ fetch=False, all_in_one=False)
+ d.snap_cache_dir = '/doesnotexist/'
+ self.assertRaises(exc.SnapshotDeployException, d.create_networks)
+
+ @patch('apex.deployment.snapshot.fnmatch')
+ @patch('apex.deployment.snapshot.OvercloudNode')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot')
+ @patch('apex.deployment.snapshot.libvirt.open')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot')
+ def test_create_networks_no_net_xmls(self, mock_deploy_snap,
+ mock_libvirt_open, mock_pull_snap,
+ mock_oc_node, mock_fnmatch):
+ ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml')
+ ds = DeploySettings(ds_file)
+ d = SnapshotDeployment(deploy_settings=ds,
+ snap_cache_dir=DUMMY_SNAP_DIR,
+ fetch=False, all_in_one=False)
+ d.snap_cache_dir = '/doesnotexist/'
+ mock_fnmatch.filter.return_value = []
+ self.assertRaises(exc.SnapshotDeployException, d.create_networks)
+
+ @patch('apex.deployment.snapshot.OvercloudNode')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot')
+ @patch('apex.deployment.snapshot.libvirt.open')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot')
+ def test_parse_and_create_nodes(self, mock_deploy_snap, mock_libvirt_open,
+ mock_pull_snap, mock_oc_node):
+ ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml')
+ ds = DeploySettings(ds_file)
+ d = SnapshotDeployment(deploy_settings=ds,
+ snap_cache_dir=DUMMY_SNAP_DIR,
+ fetch=False, all_in_one=False)
+ d.snap_cache_dir = TEST_DUMMY_CONFIG
+ node = mock_oc_node()
+ d.parse_and_create_nodes()
+ node.start.assert_called()
+ self.assertListEqual([node], d.oc_nodes)
+
+ @patch('apex.deployment.snapshot.utils.parse_yaml')
+ @patch('apex.deployment.snapshot.OvercloudNode')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot')
+ @patch('apex.deployment.snapshot.libvirt.open')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot')
+ def test_parse_and_create_nodes_invalid_node_yaml(
+ self, mock_deploy_snap, mock_libvirt_open, mock_pull_snap,
+ mock_oc_node, mock_parse_yaml):
+ ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml')
+ ds = DeploySettings(ds_file)
+ d = SnapshotDeployment(deploy_settings=ds,
+ snap_cache_dir=DUMMY_SNAP_DIR,
+ fetch=False, all_in_one=False)
+ d.snap_cache_dir = TEST_DUMMY_CONFIG
+ node = mock_oc_node()
+ mock_parse_yaml.return_value = {'blah': 'dummy'}
+ self.assertRaises(exc.SnapshotDeployException,
+ d.parse_and_create_nodes)
+ node.start.assert_not_called()
+
+ @patch('apex.deployment.snapshot.OvercloudNode')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot')
+ @patch('apex.deployment.snapshot.libvirt.open')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot')
+ def test_get_controllers(self, mock_deploy_snap, mock_libvirt_open,
+ mock_pull_snap, mock_oc_node):
+ ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml')
+ ds = DeploySettings(ds_file)
+ d = SnapshotDeployment(deploy_settings=ds,
+ snap_cache_dir=DUMMY_SNAP_DIR,
+ fetch=False, all_in_one=False)
+ d.snap_cache_dir = TEST_DUMMY_CONFIG
+ node = mock_oc_node()
+ node.role = 'controller'
+ d.oc_nodes = [node]
+ self.assertListEqual(d.get_controllers(), [node])
+
+ @patch('apex.deployment.snapshot.OvercloudNode')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot')
+ @patch('apex.deployment.snapshot.libvirt.open')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot')
+ def test_get_controllers_none(self, mock_deploy_snap, mock_libvirt_open,
+ mock_pull_snap, mock_oc_node):
+ ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml')
+ ds = DeploySettings(ds_file)
+ d = SnapshotDeployment(deploy_settings=ds,
+ snap_cache_dir=DUMMY_SNAP_DIR,
+ fetch=False, all_in_one=False)
+ d.snap_cache_dir = TEST_DUMMY_CONFIG
+ node = mock_oc_node()
+ node.role = 'compute'
+ d.oc_nodes = [node]
+ self.assertListEqual(d.get_controllers(), [])
+
+ @patch('apex.deployment.snapshot.SnapshotDeployment.get_controllers')
+ @patch('apex.deployment.snapshot.time')
+ @patch('apex.deployment.snapshot.socket')
+ @patch('apex.deployment.snapshot.OvercloudNode')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot')
+ @patch('apex.deployment.snapshot.libvirt.open')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot')
+ def test_is_openstack_up(self, mock_deploy_snap, mock_libvirt_open,
+ mock_pull_snap, mock_oc_node, mock_socket,
+ mock_time, mock_get_ctrls):
+ ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml')
+ ds = DeploySettings(ds_file)
+ d = SnapshotDeployment(deploy_settings=ds,
+ snap_cache_dir=DUMMY_SNAP_DIR,
+ fetch=False, all_in_one=False)
+ d.snap_cache_dir = TEST_DUMMY_CONFIG
+ node = mock_oc_node()
+ node.ip = '123.123.123.123'
+ node.name = 'dummy-controller-0'
+ mock_get_ctrls.return_value = [node]
+ sock = mock_socket.socket(mock_socket.AF_INET, mock_socket.SOCK_STREAM)
+ sock.connect_ex.return_value = 0
+ self.assertTrue(d.is_service_up('openstack'))
+
+ @patch('apex.deployment.snapshot.SnapshotDeployment.get_controllers')
+ @patch('apex.deployment.snapshot.time')
+ @patch('apex.deployment.snapshot.socket')
+ @patch('apex.deployment.snapshot.OvercloudNode')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot')
+ @patch('apex.deployment.snapshot.libvirt.open')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot')
+ def test_is_openstack_up_false(self, mock_deploy_snap, mock_libvirt_open,
+ mock_pull_snap, mock_oc_node, mock_socket,
+ mock_time, mock_get_ctrls):
+ ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml')
+ ds = DeploySettings(ds_file)
+ d = SnapshotDeployment(deploy_settings=ds,
+ snap_cache_dir=DUMMY_SNAP_DIR,
+ fetch=False, all_in_one=False)
+ d.snap_cache_dir = TEST_DUMMY_CONFIG
+ node = mock_oc_node()
+ node.ip = '123.123.123.123'
+ node.name = 'dummy-controller-0'
+ mock_get_ctrls.return_value = [node]
+ sock = mock_socket.socket(mock_socket.AF_INET, mock_socket.SOCK_STREAM)
+ sock.connect_ex.return_value = 1
+ self.assertFalse(d.is_service_up('openstack'))
+
+ @patch('apex.deployment.snapshot.SnapshotDeployment.get_controllers')
+ @patch('apex.deployment.snapshot.time')
+ @patch('apex.deployment.snapshot.utils')
+ @patch('apex.deployment.snapshot.OvercloudNode')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot')
+ @patch('apex.deployment.snapshot.libvirt.open')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot')
+ def test_is_opendaylight_up(self, mock_deploy_snap, mock_libvirt_open,
+ mock_pull_snap, mock_oc_node, mock_utils,
+ mock_time, mock_get_ctrls):
+ ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml')
+ ds = DeploySettings(ds_file)
+ d = SnapshotDeployment(deploy_settings=ds,
+ snap_cache_dir=DUMMY_SNAP_DIR,
+ fetch=False, all_in_one=False)
+ d.snap_cache_dir = TEST_DUMMY_CONFIG
+ node = mock_oc_node()
+ node.ip = '123.123.123.123'
+ node.name = 'dummy-controller-0'
+ mock_get_ctrls.return_value = [node]
+ mock_utils.open_webpage.return_value = 0
+ self.assertTrue(d.is_service_up('opendaylight'))
+
+ @patch('apex.deployment.snapshot.SnapshotDeployment.get_controllers')
+ @patch('apex.deployment.snapshot.time')
+ @patch('apex.deployment.snapshot.utils')
+ @patch('apex.deployment.snapshot.OvercloudNode')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot')
+ @patch('apex.deployment.snapshot.libvirt.open')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot')
+ def test_is_opendaylight_up_false(self, mock_deploy_snap,
+ mock_libvirt_open, mock_pull_snap,
+ mock_oc_node, mock_utils,
+ mock_time, mock_get_ctrls):
+ ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml')
+ ds = DeploySettings(ds_file)
+ d = SnapshotDeployment(deploy_settings=ds,
+ snap_cache_dir=DUMMY_SNAP_DIR,
+ fetch=False, all_in_one=False)
+ d.snap_cache_dir = TEST_DUMMY_CONFIG
+ node = mock_oc_node()
+ node.ip = '123.123.123.123'
+ node.name = 'dummy-controller-0'
+ mock_get_ctrls.return_value = [node]
+ mock_utils.open_webpage.side_effect = urllib.request.URLError(
+ reason='blah')
+ self.assertFalse(d.is_service_up('opendaylight'))
+
+ @patch('apex.deployment.snapshot.os.path.isfile')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.is_service_up')
+ @patch('apex.deployment.snapshot.SnapshotDeployment'
+ '.parse_and_create_nodes')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot')
+ @patch('apex.deployment.snapshot.libvirt.open')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.create_networks')
+ def test_deploy_snapshot(self, mock_create_networks, mock_libvirt_open,
+ mock_pull_snap, mock_parse_create,
+ mock_service_up, mock_is_file):
+ mock_is_file.return_value = True
+ ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml')
+ ds = DeploySettings(ds_file)
+ SnapshotDeployment(deploy_settings=ds, snap_cache_dir=DUMMY_SNAP_DIR,
+ fetch=False, all_in_one=False)
+ mock_parse_create.assert_called()
+ mock_create_networks.assert_called()
+ mock_service_up.assert_called()
+
+ @patch('apex.deployment.snapshot.os.path.isfile')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.is_service_up')
+ @patch('apex.deployment.snapshot.SnapshotDeployment'
+ '.parse_and_create_nodes')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot')
+ @patch('apex.deployment.snapshot.libvirt.open')
+ @patch('apex.deployment.snapshot.SnapshotDeployment.create_networks')
+ def test_deploy_snapshot_services_down(self, mock_create_networks,
+ mock_libvirt_open,
+ mock_pull_snap, mock_parse_create,
+ mock_service_up, mock_is_file):
+ mock_is_file.return_value = True
+ ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml')
+ ds = DeploySettings(ds_file)
+ mock_service_up.return_value = False
+ self.assertRaises(exc.SnapshotDeployException,
+ SnapshotDeployment,
+ ds, DUMMY_SNAP_DIR, False, False)
+
+ mock_service_up.side_effect = [True, False]
+ self.assertRaises(exc.SnapshotDeployException,
+ SnapshotDeployment,
+ ds, DUMMY_SNAP_DIR, False, False)
diff --git a/apex/tests/test_apex_deployment_tripleo.py b/apex/tests/test_apex_deployment_tripleo.py
new file mode 100644
index 00000000..912fe104
--- /dev/null
+++ b/apex/tests/test_apex_deployment_tripleo.py
@@ -0,0 +1,49 @@
+##############################################################################
+# Copyright (c) 2018 Tim Rozet (trozet@redhat.com) (Red Hat)
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+import os
+import unittest
+
+from apex.deployment.tripleo import ApexDeployment
+from apex.settings.deploy_settings import DeploySettings
+from apex.tests.constants import TEST_DUMMY_CONFIG
+
+
+class TestApexDeployment(unittest.TestCase):
+ @classmethod
+ def setup_class(cls):
+ """This method is run once for each class before any tests are run"""
+
+ @classmethod
+ def teardown_class(cls):
+ """This method is run once for each class _after_ all tests are run"""
+
+ def setup(self):
+ """This method is run once before _each_ test method is executed"""
+
+ def teardown(self):
+ """This method is run once after _each_ test method is executed"""
+
+ def test_determine_patches(self):
+ self.maxDiff = None
+ ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml')
+ ds = DeploySettings(ds_file)
+ patches_file = os.path.join(TEST_DUMMY_CONFIG, 'common-patches.yaml')
+ d = ApexDeployment(deploy_settings=ds, patch_file=patches_file,
+ ds_file=ds_file)
+ patches = d.determine_patches()
+ test_patches = {
+ 'undercloud':
+ [{'change-id': 'I2e0a40d7902f592e4b7bd727f57048111e0bea36',
+ 'project': 'openstack/tripleo-common'}],
+ 'overcloud':
+ [{'change-id': 'Ie988ba6a2d444a614e97c0edf5fce24b23970310',
+ 'project': 'openstack/puppet-tripleo'}]
+ }
+ self.assertDictEqual(patches, test_patches)
diff --git a/apex/tests/test_apex_inventory.py b/apex/tests/test_apex_inventory.py
index 71979465..38a4271a 100644
--- a/apex/tests/test_apex_inventory.py
+++ b/apex/tests/test_apex_inventory.py
@@ -56,10 +56,15 @@ class TestInventory:
os.path.join(TEST_DUMMY_CONFIG, 'inventory-virt.yaml'),
virtual=True, ha=True)
+ def test_inventory_valid_allinone_count(self):
+ i = Inventory(os.path.join(TEST_DUMMY_CONFIG,
+ 'inventory-virt-1-node.yaml'), ha=False)
+ assert_equal(list(i.get_node_counts()), [1, 0])
+
def test_inventory_invalid_noha_count(self):
assert_raises(ApexInventoryException, Inventory,
os.path.join(TEST_DUMMY_CONFIG,
- 'inventory-virt-1-node.yaml'),
+ 'inventory-virt-1-compute-node.yaml'),
virtual=True, ha=False)
def test_inventory_virtual(self):
diff --git a/apex/tests/test_apex_network_environment.py b/apex/tests/test_apex_network_environment.py
index 79a72a55..7aa6ef15 100644
--- a/apex/tests/test_apex_network_environment.py
+++ b/apex/tests/test_apex_network_environment.py
@@ -165,3 +165,10 @@ class TestNetworkEnvironment:
e = NetworkEnvException("test")
print(e)
assert_is_instance(e, NetworkEnvException)
+
+ def test_service_netmap(self):
+ ns = copy(self.ns)
+ ns.enabled_network_list = ['admin']
+ ne = NetworkEnvironment(ns, os.path.join(TEST_BUILD_DIR, NET_ENV_FILE))
+ for network in ne['parameter_defaults']['ServiceNetMap'].values():
+ assert_equal(network, 'ctlplane')
diff --git a/apex/tests/test_apex_overcloud_builder.py b/apex/tests/test_apex_overcloud_builder.py
index 46b5f871..8bed3d70 100644
--- a/apex/tests/test_apex_overcloud_builder.py
+++ b/apex/tests/test_apex_overcloud_builder.py
@@ -43,6 +43,7 @@ class TestOvercloudBuilder(unittest.TestCase):
{con.VIRT_RUN_CMD: 'rm -rf /etc/puppet/modules/opendaylight'},
{con.VIRT_RUN_CMD: "cd /etc/puppet/modules/ && tar xvf "
"puppet-opendaylight.tar"},
+ {con.VIRT_INSTALL: "java-1.8.0-openjdk"},
{con.VIRT_INSTALL: 'opendaylight'}
]
oc_builder.inject_opendaylight(con.DEFAULT_ODL_VERSION, 'dummy.qcow2',
@@ -65,6 +66,7 @@ class TestOvercloudBuilder(unittest.TestCase):
{con.VIRT_RUN_CMD: 'rm -rf /etc/puppet/modules/opendaylight'},
{con.VIRT_RUN_CMD: "cd /etc/puppet/modules/ && tar xvf "
"puppet-opendaylight.tar"},
+ {con.VIRT_INSTALL: "java-1.8.0-openjdk"},
]
oc_builder.inject_opendaylight('oxygen', 'dummy.qcow2',
'/dummytmp/', uc_ip='192.0.2.2',
diff --git a/apex/tests/test_apex_overcloud_deploy.py b/apex/tests/test_apex_overcloud_deploy.py
index f1db91ad..79dbf54b 100644
--- a/apex/tests/test_apex_overcloud_deploy.py
+++ b/apex/tests/test_apex_overcloud_deploy.py
@@ -7,6 +7,7 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
+import mock
import os
import sys
import unittest
@@ -29,7 +30,7 @@ from apex.overcloud.deploy import prep_sriov_env
from apex.overcloud.deploy import external_network_cmds
from apex.overcloud.deploy import create_congress_cmds
from apex.overcloud.deploy import SDN_FILE_MAP
-from apex.overcloud.deploy import get_docker_sdn_file
+from apex.overcloud.deploy import get_docker_sdn_files
from nose.tools import (
assert_regexp_matches,
@@ -104,7 +105,8 @@ class TestOvercloudDeploy(unittest.TestCase):
'containers': False,
'barometer': True,
'ceph': False,
- 'sriov': False
+ 'sriov': False,
+ 'vim': 'openstack'
},
'global_params': MagicMock()}
@@ -132,10 +134,12 @@ class TestOvercloudDeploy(unittest.TestCase):
'tacker': False,
'containers': True,
'barometer': False,
+ 'vpn': False,
'ceph': True,
'sdn_controller': 'opendaylight',
'sriov': False,
- 'os_version': 'queens'
+ 'os_version': 'queens',
+ 'vim': 'openstack'
},
'global_params': MagicMock()}
@@ -152,13 +156,12 @@ class TestOvercloudDeploy(unittest.TestCase):
assert_in('--control-scale 3', result_cmd)
assert_in('--compute-scale 2', result_cmd)
assert_in('docker-images.yaml', result_cmd)
- assert_in('sdn-images.yaml', result_cmd)
assert_in('/usr/share/openstack-tripleo-heat-templates/environments'
'/docker.yaml', result_cmd)
assert_in('/usr/share/openstack-tripleo-heat-templates/environments/'
'storage-environment.yaml', result_cmd)
assert_in('/usr/share/openstack-tripleo-heat-templates/environments'
- '/services-docker/neutron-opendaylight.yaml', result_cmd)
+ '/services/neutron-opendaylight.yaml', result_cmd)
ds['deploy_options']['os_version'] = 'master'
result_cmd = create_deploy_cmd(ds, ns, inv, '/tmp', virt)
assert_in('/usr/share/openstack-tripleo-heat-templates/environments'
@@ -190,31 +193,18 @@ class TestOvercloudDeploy(unittest.TestCase):
assert_not_in('enable_congress.yaml', result_cmd)
assert_not_in('enable_barometer.yaml', result_cmd)
- @patch('apex.overcloud.deploy.prep_sriov_env')
- @patch('apex.overcloud.deploy.prep_storage_env')
- @patch('apex.overcloud.deploy.build_sdn_env_list')
- def test_create_deploy_cmd_raises(self, mock_sdn_list, mock_prep_storage,
- mock_prep_sriov):
- mock_sdn_list.return_value = []
- ds = {'deploy_options': MagicMock(),
- 'global_params': MagicMock()}
- ds['deploy_options'].__getitem__.side_effect = \
- lambda i: 'master' if i == 'os_version' else MagicMock()
- ns = {}
- inv = MagicMock()
- inv.get_node_counts.return_value = (0, 0)
- virt = False
- assert_raises(ApexDeployException, create_deploy_cmd,
- ds, ns, inv, '/tmp', virt)
-
+ @patch('apex.builders.overcloud_builder.inject_opendaylight')
@patch('apex.overcloud.deploy.virt_utils')
@patch('apex.overcloud.deploy.shutil')
- @patch('apex.overcloud.deploy.os.path')
+ @patch('apex.overcloud.deploy.os.path.isfile')
@patch('builtins.open', mock_open())
- def test_prep_image(self, mock_os_path, mock_shutil, mock_virt_utils):
+ def test_prep_image(self, mock_is_file, mock_shutil, mock_virt_utils,
+ mock_inject_odl):
+ mock_is_file.return_value = True
ds_opts = {'dataplane': 'fdio',
'sdn_controller': 'opendaylight',
'odl_version': 'master',
+ 'vpn': False,
'sriov': False}
ds = {'deploy_options': MagicMock(),
'global_params': MagicMock()}
@@ -223,14 +213,17 @@ class TestOvercloudDeploy(unittest.TestCase):
ns = MagicMock()
prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
mock_virt_utils.virt_customize.assert_called()
+ mock_inject_odl.assert_called()
@patch('apex.overcloud.deploy.virt_utils')
@patch('apex.overcloud.deploy.shutil')
- @patch('apex.overcloud.deploy.os.path')
+ @patch('apex.overcloud.deploy.os.path.isfile')
@patch('builtins.open', mock_open())
- def test_prep_image_sdn_false(self, mock_os_path, mock_shutil,
+ def test_prep_image_sdn_false(self, mock_is_file, mock_shutil,
mock_virt_utils):
+ mock_is_file.return_value = True
ds_opts = {'dataplane': 'fdio',
+ 'vpn': False,
'sdn_controller': False}
ds = {'deploy_options': MagicMock(),
'global_params': MagicMock()}
@@ -240,14 +233,21 @@ class TestOvercloudDeploy(unittest.TestCase):
prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
mock_virt_utils.virt_customize.assert_called()
+ @patch('apex.builders.overcloud_builder.inject_ovs_nsh')
+ @patch('apex.overcloud.deploy.utils.fetch_upstream_and_unpack')
+ @patch('apex.builders.overcloud_builder.inject_opendaylight')
@patch('apex.overcloud.deploy.virt_utils')
@patch('apex.overcloud.deploy.shutil')
- @patch('apex.overcloud.deploy.os.path')
+ @patch('apex.overcloud.deploy.os.path.isfile')
@patch('builtins.open', mock_open())
- def test_prep_image_sdn_odl(self, mock_os_path, mock_shutil,
- mock_virt_utils):
+ def test_prep_image_sdn_odl(self, mock_is_file, mock_shutil,
+ mock_virt_utils, mock_inject_odl,
+ mock_fetch, mock_ovs_nsh):
+ mock_is_file.return_value = True
ds_opts = {'dataplane': 'ovs',
'sdn_controller': 'opendaylight',
+ 'vpn': False,
+ 'sfc': False,
'odl_version': con.DEFAULT_ODL_VERSION,
'odl_vpp_netvirt': True}
ds = {'deploy_options': MagicMock(),
@@ -259,16 +259,19 @@ class TestOvercloudDeploy(unittest.TestCase):
ns = MagicMock()
prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
mock_virt_utils.virt_customize.assert_called()
+ mock_inject_odl.assert_called()
+ # mock_ovs_nsh.assert_called()
@patch('apex.overcloud.deploy.c_builder')
@patch('apex.overcloud.deploy.oc_builder')
@patch('apex.overcloud.deploy.virt_utils')
@patch('apex.overcloud.deploy.shutil')
- @patch('apex.overcloud.deploy.os.path')
+ @patch('apex.overcloud.deploy.os.path.isfile')
@patch('builtins.open', mock_open())
def test_prep_image_sdn_odl_upstream_containers_patches(
- self, mock_os_path, mock_shutil, mock_virt_utils,
+ self, mock_is_file, mock_shutil, mock_virt_utils,
mock_oc_builder, mock_c_builder):
+ mock_is_file.return_value = True
ds_opts = {'dataplane': 'ovs',
'sdn_controller': 'opendaylight',
'odl_version': con.DEFAULT_ODL_VERSION,
@@ -283,18 +286,50 @@ class TestOvercloudDeploy(unittest.TestCase):
mock_c_builder.add_upstream_patches.return_value = ['nova-api']
patches = ['dummy_nova_patch']
rv = prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test',
- docker_tag='latest', patches=patches, upstream=True)
- mock_oc_builder.inject_opendaylight.assert_called
+ docker_tag='latest', patches=patches)
+ mock_oc_builder.inject_opendaylight.assert_called()
mock_virt_utils.virt_customize.assert_called()
- mock_c_builder.add_upstream_patches.assert_called
+ mock_c_builder.add_upstream_patches.assert_called()
self.assertListEqual(sorted(rv), ['nova-api', 'opendaylight'])
+ @patch('apex.overcloud.deploy.c_builder')
+ @patch('apex.overcloud.deploy.oc_builder')
+ @patch('apex.overcloud.deploy.virt_utils')
+ @patch('apex.overcloud.deploy.shutil')
+ @patch('apex.overcloud.deploy.os.path.isfile')
+ @patch('builtins.open', mock_open())
+ def test_prep_image_nosdn_upstream_containers_patches(
+ self, mock_is_file, mock_shutil, mock_virt_utils,
+ mock_oc_builder, mock_c_builder):
+ mock_is_file.return_value = True
+ ds_opts = {'dataplane': 'ovs',
+ 'sdn_controller': False,
+ 'odl_version': con.DEFAULT_ODL_VERSION,
+ 'odl_vpp_netvirt': False}
+ ds = {'deploy_options': MagicMock(),
+ 'global_params': MagicMock()}
+ ds['deploy_options'].__getitem__.side_effect = \
+ lambda i: ds_opts.get(i, MagicMock())
+ ds['deploy_options'].__contains__.side_effect = \
+ lambda i: True if i in ds_opts else MagicMock()
+ ns = MagicMock()
+ mock_c_builder.add_upstream_patches.return_value = ['nova-api']
+ patches = ['dummy_nova_patch']
+ rv = prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test',
+ docker_tag='latest', patches=patches)
+ mock_virt_utils.virt_customize.assert_called()
+ mock_c_builder.add_upstream_patches.assert_called()
+ self.assertListEqual(sorted(rv), ['nova-api'])
+
+ @patch('apex.overcloud.deploy.oc_builder')
@patch('apex.overcloud.deploy.virt_utils')
@patch('apex.overcloud.deploy.shutil')
- @patch('apex.overcloud.deploy.os.path')
+ @patch('apex.overcloud.deploy.os.path.isfile')
@patch('builtins.open', mock_open())
- def test_prep_image_sdn_odl_not_def(self, mock_os_path,
- mock_shutil, mock_virt_utils):
+ def test_prep_image_sdn_odl_not_def(self, mock_is_file,
+ mock_shutil, mock_virt_utils,
+ mock_oc_builder):
+ mock_is_file.return_value = True
ds_opts = {'dataplane': 'ovs',
'sdn_controller': 'opendaylight',
'odl_version': 'uncommon'}
@@ -305,14 +340,19 @@ class TestOvercloudDeploy(unittest.TestCase):
ns = MagicMock()
prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
mock_virt_utils.virt_customize.assert_called()
+ mock_oc_builder.inject_opendaylight.assert_called()
+ @patch('apex.builders.overcloud_builder.inject_ovs_nsh')
@patch('apex.overcloud.deploy.virt_utils')
@patch('apex.overcloud.deploy.shutil')
- @patch('apex.overcloud.deploy.os.path')
+ @patch('apex.overcloud.deploy.os.path.isfile')
@patch('builtins.open', mock_open())
- def test_prep_image_sdn_ovn(self, mock_os_path, mock_shutil,
- mock_virt_utils):
+ def test_prep_image_sdn_ovn(self, mock_is_file, mock_shutil,
+ mock_virt_utils, mock_ovs_nsh):
+ mock_is_file.return_value = True
ds_opts = {'dataplane': 'ovs',
+ 'vpn': False,
+ 'sfc': False,
'sdn_controller': 'ovn'}
ds = {'deploy_options': MagicMock(),
'global_params': MagicMock()}
@@ -321,6 +361,67 @@ class TestOvercloudDeploy(unittest.TestCase):
ns = MagicMock()
prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
mock_virt_utils.virt_customize.assert_called()
+ # mock_ovs_nsh.assert_called()
+
+ @patch('apex.builders.overcloud_builder.inject_ovs_nsh')
+ @patch('apex.overcloud.deploy.utils.fetch_upstream_and_unpack')
+ @patch('apex.builders.overcloud_builder.inject_quagga')
+ @patch('apex.builders.overcloud_builder.inject_opendaylight')
+ @patch('apex.overcloud.deploy.virt_utils')
+ @patch('apex.overcloud.deploy.shutil')
+ @patch('apex.overcloud.deploy.os.path.isfile')
+ @patch('builtins.open', mock_open())
+ def test_prep_image_sdn_odl_vpn(self, mock_is_file, mock_shutil,
+ mock_virt_utils, mock_inject_odl,
+ mock_inject_quagga, mock_fetch,
+ mock_ovs_nsh):
+ mock_is_file.return_value = True
+ ds_opts = {'dataplane': 'ovs',
+ 'sdn_controller': 'opendaylight',
+ 'vpn': True,
+ 'sfc': False,
+ 'odl_version': con.DEFAULT_ODL_VERSION,
+ 'odl_vpp_netvirt': True}
+ ds = {'deploy_options': MagicMock(),
+ 'global_params': MagicMock()}
+ ds['deploy_options'].__getitem__.side_effect = \
+ lambda i: ds_opts.get(i, MagicMock())
+ ds['deploy_options'].__contains__.side_effect = \
+ lambda i: True if i in ds_opts else MagicMock()
+ ns = MagicMock()
+ prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
+ mock_virt_utils.virt_customize.assert_called()
+ mock_inject_odl.assert_called()
+ mock_inject_quagga.assert_called()
+ # mock_ovs_nsh.assert_called()
+
+ @patch('apex.builders.overcloud_builder.inject_ovs_nsh')
+ @patch('apex.builders.overcloud_builder.inject_opendaylight')
+ @patch('apex.overcloud.deploy.virt_utils')
+ @patch('apex.overcloud.deploy.shutil')
+ @patch('apex.overcloud.deploy.os.path.isfile')
+ @patch('builtins.open', mock_open())
+ def test_prep_image_sdn_odl_sfc(self, mock_is_file, mock_shutil,
+ mock_virt_utils, mock_inject_odl,
+ mock_inject_ovs_nsh):
+ mock_is_file.return_value = True
+ ds_opts = {'dataplane': 'ovs',
+ 'sdn_controller': 'opendaylight',
+ 'vpn': False,
+ 'sfc': True,
+ 'odl_version': con.DEFAULT_ODL_VERSION,
+ 'odl_vpp_netvirt': True}
+ ds = {'deploy_options': MagicMock(),
+ 'global_params': MagicMock()}
+ ds['deploy_options'].__getitem__.side_effect = \
+ lambda i: ds_opts.get(i, MagicMock())
+ ds['deploy_options'].__contains__.side_effect = \
+ lambda i: True if i in ds_opts else MagicMock()
+ ns = MagicMock()
+ prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
+ mock_virt_utils.virt_customize.assert_called()
+ mock_inject_odl.assert_called()
+ # mock_inject_ovs_nsh.assert_called()
@patch('apex.overcloud.deploy.os.path.isfile')
def test_prep_image_no_image(self, mock_isfile):
@@ -333,16 +434,24 @@ class TestOvercloudDeploy(unittest.TestCase):
assert_in('-----BEGIN PRIVATE KEY-----', priv)
assert_in('ssh-rsa', pub)
+ @patch('apex.overcloud.deploy.yaml')
@patch('apex.overcloud.deploy.fileinput')
@patch('apex.overcloud.deploy.shutil')
- def test_prep_env(self, mock_shutil, mock_fileinput):
+ @patch('builtins.open', mock_open())
+ def test_prep_env(self, mock_shutil, mock_fileinput, mock_yaml):
mock_fileinput.input.return_value = \
['CloudDomain', 'replace_private_key', 'replace_public_key',
'opendaylight::vpp_routing_node', 'ControllerExtraConfig',
'NovaComputeExtraConfig', 'ComputeKernelArgs', 'HostCpusList',
'ComputeExtraConfigPre', 'resource_registry',
'NovaSchedulerDefaultFilters']
- ds = {'deploy_options':
+ mock_yaml.safe_load.return_value = {
+ 'parameter_defaults': {
+ 'ControllerServices': [1, 2, 3],
+ 'ComputeServices': [3, 4, 5]
+ }}
+ ds = {'global_params': {'ha_enabled': False},
+ 'deploy_options':
{'sdn_controller': 'opendaylight',
'odl_vpp_routing_node': 'test',
'dataplane': 'ovs_dpdk',
@@ -352,24 +461,28 @@ class TestOvercloudDeploy(unittest.TestCase):
'ovs': {'dpdk_cores': 'test'},
'kernel': {'test': 'test'}},
'Controller': {'vpp': 'test'}}}}
- ns = {'domain_name': 'test.domain',
- 'networks':
- {'tenant':
- {'nic_mapping': {'controller':
- {'members': ['tenant_nic']},
- 'compute':
- {'members': ['tenant_nic']}}},
- 'external':
- [{'nic_mapping': {'controller':
- {'members': ['ext_nic']},
- 'compute':
- {'members': ['ext_nic']}}}]}}
- inv = None
+ ns_dict = {'domain_name': 'test.domain',
+ 'networks':
+ {'tenant':
+ {'nic_mapping': {'controller':
+ {'members': ['tenant_nic']},
+ 'compute':
+ {'members': ['tenant_nic']}}},
+ 'external':
+ [{'nic_mapping': {'controller':
+ {'members': ['ext_nic']},
+ 'compute':
+ {'members': ['ext_nic']}}}]}}
+ inv = MagicMock()
+ inv.get_node_counts.return_value = (1, 0)
try:
# Swap stdout
saved_stdout = sys.stdout
out = StringIO()
sys.stdout = out
+ ns = MagicMock()
+ ns.enabled_network_list = ['external', 'tenant']
+ ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
# run test
prep_env(ds, ns, inv, 'opnfv-env.yml', '/net-env.yml', '/tmp')
output = out.getvalue().strip()
@@ -377,39 +490,51 @@ class TestOvercloudDeploy(unittest.TestCase):
assert_in('ssh-rsa', output)
assert_in('ComputeKernelArgs: \'test=test \'', output)
assert_in('fdio::vpp_cpu_main_core: \'test\'', output)
+ mock_yaml.safe_dump.assert_called_with(
+ {'parameter_defaults': {
+ 'ControllerServices': [1, 2, 3, 4, 5],
+ }},
+ mock.ANY, default_flow_style=False
+ )
finally:
# put stdout back
sys.stdout = saved_stdout
@patch('apex.overcloud.deploy.fileinput')
@patch('apex.overcloud.deploy.shutil')
+ @patch('builtins.open', mock_open())
def test_prep_env_round_two(self, mock_shutil, mock_fileinput):
mock_fileinput.input.return_value = \
['NeutronVPPAgentPhysnets']
- ds = {'deploy_options':
+ ds = {'global_params': {'ha_enabled': False},
+ 'deploy_options':
{'sdn_controller': False,
'dataplane': 'fdio',
'sriov': 'xxx',
'performance': {'Compute': {},
'Controller': {}}}}
- ns = {'domain_name': 'test.domain',
- 'networks':
- {'tenant':
- {'nic_mapping': {'controller':
- {'members': ['tenant_nic']},
- 'compute':
- {'members': ['tenant_nic']}}},
- 'external':
- [{'nic_mapping': {'controller':
- {'members': ['ext_nic']},
- 'compute':
- {'members': ['ext_nic']}}}]}}
- inv = None
+ ns_dict = {'domain_name': 'test.domain',
+ 'networks':
+ {'tenant':
+ {'nic_mapping': {'controller':
+ {'members': ['tenant_nic']},
+ 'compute':
+ {'members': ['tenant_nic']}}},
+ 'external':
+ [{'nic_mapping': {'controller':
+ {'members': ['ext_nic']},
+ 'compute':
+ {'members': ['ext_nic']}}}]}}
+ inv = MagicMock()
+ inv.get_node_counts.return_value = (3, 2)
try:
# Swap stdout
saved_stdout = sys.stdout
out = StringIO()
sys.stdout = out
+ ns = MagicMock()
+ ns.enabled_network_list = ['external', 'tenant']
+ ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
# run test
prep_env(ds, ns, inv, 'opnfv-env.yml', '/net-env.yml', '/tmp')
output = out.getvalue().strip()
@@ -423,27 +548,29 @@ class TestOvercloudDeploy(unittest.TestCase):
@patch('apex.overcloud.deploy.fileinput')
@patch('apex.overcloud.deploy.shutil')
+ @patch('builtins.open', mock_open())
def test_prep_env_round_three(self, mock_shutil, mock_fileinput):
mock_fileinput.input.return_value = \
['OS::TripleO::Services::NeutronDhcpAgent',
'NeutronDhcpAgentsPerNetwork', 'ComputeServices']
- ds = {'deploy_options':
+ ds = {'global_params': {'ha_enabled': False},
+ 'deploy_options':
{'sdn_controller': 'opendaylight',
'dataplane': 'fdio',
'sriov': 'xxx',
'dvr': True}}
- ns = {'domain_name': 'test.domain',
- 'networks':
- {'tenant':
- {'nic_mapping': {'controller':
- {'members': ['tenant_nic']},
- 'compute':
- {'members': ['tenant_nic']}}},
- 'external':
- [{'nic_mapping': {'controller':
- {'members': ['ext_nic']},
- 'compute':
- {'members': ['ext_nic']}}}]}}
+ ns_dict = {'domain_name': 'test.domain',
+ 'networks':
+ {'tenant':
+ {'nic_mapping': {'controller':
+ {'members': ['tenant_nic']},
+ 'compute':
+ {'members': ['tenant_nic']}}},
+ 'external':
+ [{'nic_mapping': {'controller':
+ {'members': ['ext_nic']},
+ 'compute':
+ {'members': ['ext_nic']}}}]}}
inv = MagicMock()
inv.get_node_counts.return_value = (3, 2)
try:
@@ -451,6 +578,9 @@ class TestOvercloudDeploy(unittest.TestCase):
saved_stdout = sys.stdout
out = StringIO()
sys.stdout = out
+ ns = MagicMock()
+ ns.enabled_network_list = ['external', 'tenant']
+ ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
# run test
prep_env(ds, ns, inv, 'opnfv-env.yml', '/net-env.yml', '/tmp')
output = out.getvalue().strip()
@@ -459,6 +589,111 @@ class TestOvercloudDeploy(unittest.TestCase):
# put stdout back
sys.stdout = saved_stdout
+ @patch('apex.overcloud.deploy.fileinput')
+ @patch('apex.overcloud.deploy.shutil')
+ @patch('builtins.open', mock_open())
+ def test_prep_env_tenant_vlan(self, mock_shutil, mock_fileinput):
+ mock_fileinput.input.return_value = \
+ ['NeutronNetworkVLANRanges',
+ 'NeutronNetworkType', 'NeutronBridgeMappings']
+ ds = {'global_params': {'ha_enabled': False},
+ 'deploy_options':
+ {'sdn_controller': False,
+ 'dataplane': 'ovs',
+ 'sriov': 'xxx',
+ 'dvr': True}}
+ ns_dict = {'domain_name': 'test.domain',
+ 'networks':
+ {'tenant':
+ {'nic_mapping': {'controller':
+ {'members': ['tenant_nic']},
+ 'compute':
+ {'members': ['tenant_nic']}},
+ 'segmentation_type': 'vlan',
+ 'overlay_id_range': 'vlan:500:600'
+ },
+ 'external':
+ [{'nic_mapping': {'controller':
+ {'members': ['ext_nic']},
+ 'compute':
+ {'members': ['ext_nic']}}}]}}
+ inv = MagicMock()
+ inv.get_node_counts.return_value = (3, 2)
+ try:
+ # Swap stdout
+ saved_stdout = sys.stdout
+ out = StringIO()
+ sys.stdout = out
+ ns = MagicMock()
+ ns.enabled_network_list = ['external', 'tenant']
+ ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
+ # run test
+ prep_env(ds, ns, inv, 'opnfv-env.yml', '/net-env.yml', '/tmp')
+ output = out.getvalue().strip()
+ assert_in('NeutronNetworkVLANRanges: '
+ 'vlan:500:600,datacentre:1:1000', output)
+ assert_in('NeutronNetworkType: vlan', output)
+ assert_in('NeutronBridgeMappings: '
+ 'vlan:br-vlan,datacentre:br-ex', output)
+ assert_not_in('OpenDaylightProviderMappings', output)
+ finally:
+ # put stdout back
+ sys.stdout = saved_stdout
+
+ @patch('apex.overcloud.deploy.fileinput')
+ @patch('apex.overcloud.deploy.shutil')
+ @patch('builtins.open', mock_open())
+ def test_prep_env_tenant_vlan_odl(self, mock_shutil, mock_fileinput):
+ mock_fileinput.input.return_value = \
+ ['NeutronNetworkVLANRanges',
+ 'NeutronNetworkType',
+ 'NeutronBridgeMappings',
+ 'OpenDaylightProviderMappings']
+ ds = {'global_params': {'ha_enabled': False},
+ 'deploy_options':
+ {'sdn_controller': 'opendaylight',
+ 'dataplane': 'ovs',
+ 'sriov': 'xxx',
+ 'dvr': True}}
+ ns_dict = {'domain_name': 'test.domain',
+ 'networks':
+ {'tenant':
+ {'nic_mapping': {'controller':
+ {'members': ['tenant_nic']},
+ 'compute':
+ {'members': ['tenant_nic']}},
+ 'segmentation_type': 'vlan',
+ 'overlay_id_range': 'vlan:500:600'
+ },
+ 'external':
+ [{'nic_mapping': {'controller':
+ {'members': ['ext_nic']},
+ 'compute':
+ {'members': ['ext_nic']}}}]}}
+ inv = MagicMock()
+ inv.get_node_counts.return_value = (3, 2)
+ try:
+ # Swap stdout
+ saved_stdout = sys.stdout
+ out = StringIO()
+ sys.stdout = out
+ ns = MagicMock()
+ ns.enabled_network_list = ['external', 'tenant']
+ ns.__getitem__.side_effect = lambda i: ns_dict.get(i, MagicMock())
+ # run test
+ prep_env(ds, ns, inv, 'opnfv-env.yml', '/net-env.yml', '/tmp')
+ output = out.getvalue().strip()
+ assert_in('NeutronNetworkVLANRanges: '
+ 'vlan:500:600,datacentre:1:1000', output)
+ assert_in('NeutronNetworkType: vlan', output)
+ assert_in('NeutronBridgeMappings: '
+ 'vlan:br-vlan,datacentre:br-ex', output)
+ assert_in('OpenDaylightProviderMappings: '
+ 'vlan:br-vlan,datacentre:br-ex', output)
+ finally:
+ # put stdout back
+ sys.stdout = saved_stdout
+
def test_generate_ceph_key(self):
assert_equal(len(generate_ceph_key()), 40)
@@ -496,9 +731,6 @@ class TestOvercloudDeploy(unittest.TestCase):
}
prep_storage_env(ds, ns, virtual=True, tmp_dir='/tmp')
ceph_params = {
- 'DockerCephDaemonImage':
- '192.0.2.1:8787/ceph/daemon:tag-build-master-luminous-centos'
- '-7',
'CephPoolDefaultSize': 2,
'CephAnsibleExtraConfig': {
'centos_package_dependencies': [],
@@ -650,19 +882,20 @@ class TestOvercloudDeploy(unittest.TestCase):
mock_parsers.return_value.__getitem__.side_effect = KeyError()
assert_raises(KeyError, create_congress_cmds, 'overcloud_file')
- def test_get_docker_sdn_file(self):
+ def test_get_docker_sdn_files(self):
ds_opts = {'ha_enabled': True,
'congress': True,
'tacker': True,
'containers': False,
'barometer': True,
'ceph': False,
+ 'vpn': True,
'sdn_controller': 'opendaylight',
'os_version': 'queens'
}
- output = get_docker_sdn_file(ds_opts)
- self.assertEqual(output,
- ('/usr/share/openstack-tripleo-heat-templates'
- '/environments/services-docker/neutron-opendaylight'
- '.yaml')
- )
+ output = get_docker_sdn_files(ds_opts)
+ compare = ['/usr/share/openstack-tripleo-heat-templates/'
+ 'environments/services/neutron-opendaylight.yaml',
+ '/usr/share/openstack-tripleo-heat-templates/environments'
+ '/services/neutron-bgpvpn-opendaylight.yaml']
+ self.assertEqual(output, compare)
diff --git a/apex/tests/test_apex_overcloud_node.py b/apex/tests/test_apex_overcloud_node.py
new file mode 100644
index 00000000..4c67b1d8
--- /dev/null
+++ b/apex/tests/test_apex_overcloud_node.py
@@ -0,0 +1,191 @@
+##############################################################################
+# Copyright (c) 2018 Tim Rozet (trozet@redhat.com) (Red Hat)
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+from libvirt import libvirtError
+from mock import patch
+from mock import MagicMock
+import os
+import unittest
+import urllib.request
+
+from apex.common import exceptions as exc
+from apex.overcloud.node import OvercloudNode
+from apex.settings.deploy_settings import DeploySettings
+from apex.tests.constants import TEST_DUMMY_CONFIG
+
+DUMMY_SNAP_DIR = '/tmp/dummy_cache'
+
+
+class TestSnapshotDeployment(unittest.TestCase):
+ @classmethod
+ def setup_class(cls):
+ """This method is run once for each class before any tests are run"""
+
+ @classmethod
+ def teardown_class(cls):
+ """This method is run once for each class _after_ all tests are run"""
+
+ def setup(self):
+ """This method is run once before _each_ test method is executed"""
+
+ def teardown(self):
+ """This method is run once after _each_ test method is executed"""
+
+ @patch('apex.overcloud.node.OvercloudNode.create')
+ @patch('apex.overcloud.node.os.path.isfile')
+ @patch('apex.overcloud.node.libvirt.open')
+ def test_init(self, mock_libvirt_open, mock_is_file, mock_node_create):
+ mock_is_file.return_value = True
+ OvercloudNode(role='controller', ip='123.123.123.123',
+ ovs_ctrlrs=None, ovs_mgrs=None,
+ name='dummy-controller-0', node_xml='dummynode.xml',
+ disk_img='dummy.qcow2')
+ mock_node_create.assert_called()
+
+ @patch('apex.overcloud.node.OvercloudNode.create')
+ @patch('apex.overcloud.node.libvirt.open')
+ def test_init_invalid_files(self, mock_libvirt_open, mock_node_create):
+ self.assertRaises(exc.OvercloudNodeException,
+ OvercloudNode, 'controller', '123.123.123',
+ None, None, 'dummy-controller-0', 'dummynode.xml',
+ 'dummy.qcow2')
+
+ @patch('apex.overcloud.node.shutil.copyfile')
+ @patch('apex.overcloud.node.OvercloudNode.create')
+ @patch('apex.overcloud.node.os.path.isfile')
+ @patch('apex.overcloud.node.libvirt.open')
+ def test_configure_disk(self, mock_libvirt_open, mock_is_file,
+ mock_node_create, mock_copy):
+ mock_is_file.return_value = True
+ node = OvercloudNode(role='controller', ip='123.123.123.123',
+ ovs_ctrlrs=None, ovs_mgrs=None,
+ name='dummy-controller-0',
+ node_xml='dummynode.xml',
+ disk_img='dummy.qcow2')
+ conn = mock_libvirt_open.return_value
+ conn.storagePoolLookupByName.return_value.XMLDesc.return_value = """
+ <pool type='dir'>
+ <target>
+ <path>/var/lib/libvirt/images</path>
+ </target>
+ </pool>
+ """
+ node._configure_disk('dummy.qcow2')
+ mock_copy.assert_called()
+ self.assertEqual(node.disk_img, '/var/lib/libvirt/images/dummy.qcow2')
+
+ @patch('apex.overcloud.node.shutil.copyfile')
+ @patch('apex.overcloud.node.OvercloudNode.create')
+ @patch('apex.overcloud.node.os.path.isfile')
+ @patch('apex.overcloud.node.libvirt.open')
+ def test_configure_disk_bad_path(self, mock_libvirt_open, mock_is_file,
+ mock_node_create, mock_copy):
+ mock_is_file.return_value = True
+ node = OvercloudNode(role='controller', ip='123.123.123.123',
+ ovs_ctrlrs=None, ovs_mgrs=None,
+ name='dummy-controller-0',
+ node_xml='dummynode.xml',
+ disk_img='dummy.qcow2')
+ conn = mock_libvirt_open.return_value
+ conn.storagePoolLookupByName.return_value.XMLDesc.return_value = """
+ <pool type='dir'>
+ <target>
+ </target>
+ </pool>
+ """
+ self.assertRaises(exc.OvercloudNodeException,
+ node._configure_disk, 'dummy.qcow2')
+
+ @patch('apex.overcloud.node.shutil.copyfile')
+ @patch('apex.overcloud.node.OvercloudNode.create')
+ @patch('apex.overcloud.node.os.path.isfile')
+ @patch('apex.overcloud.node.libvirt.open')
+ def test_configure_disk_no_pool(self, mock_libvirt_open, mock_is_file,
+ mock_node_create, mock_copy):
+ mock_is_file.return_value = True
+ node = OvercloudNode(role='controller', ip='123.123.123.123',
+ ovs_ctrlrs=None, ovs_mgrs=None,
+ name='dummy-controller-0',
+ node_xml='dummynode.xml',
+ disk_img='dummy.qcow2')
+ conn = mock_libvirt_open.return_value
+ conn.storagePoolLookupByName.return_value = None
+ self.assertRaises(exc.OvercloudNodeException,
+ node._configure_disk, 'dummy.qcow2')
+
+ @patch('apex.overcloud.node.distro.linux_distribution')
+ def test_update_xml(self, mock_linux_distro):
+ mock_linux_distro.return_value = ['Fedora']
+ xml_file = os.path.join(TEST_DUMMY_CONFIG, 'baremetal0.xml')
+ with open(xml_file, 'r') as fh:
+ xml = fh.read()
+ new_xml = OvercloudNode._update_xml(
+ xml=xml, disk_path='/dummy/disk/path/blah.qcow2')
+ self.assertIn('/dummy/disk/path/blah.qcow2', new_xml)
+ self.assertIn('/usr/bin/qemu-kvm', new_xml)
+
+ @patch('apex.overcloud.node.distro.linux_distribution')
+ def test_update_xml_no_disk(self, mock_linux_distro):
+ mock_linux_distro.return_value = ['Fedora']
+ xml_file = os.path.join(TEST_DUMMY_CONFIG, 'baremetal0.xml')
+ with open(xml_file, 'r') as fh:
+ xml = fh.read()
+ new_xml = OvercloudNode._update_xml(xml=xml)
+ self.assertIn('/home/images/baremetal0.qcow2', new_xml)
+ self.assertIn('/usr/bin/qemu-kvm', new_xml)
+
+ @patch('apex.overcloud.node.OvercloudNode._update_xml')
+ @patch('apex.overcloud.node.OvercloudNode._configure_disk')
+ @patch('apex.overcloud.node.libvirt.open')
+ @patch('apex.overcloud.node.os.path.isfile')
+ def test_create(self, mock_isfile, mock_libvirt_conn, mock_configure_disk,
+ mock_update_xml):
+ mock_isfile.return_value = True
+ domain = mock_libvirt_conn.return_value.defineXML.return_value
+ node = OvercloudNode(role='controller', ip='123.123.123.123',
+ ovs_ctrlrs=None, ovs_mgrs=None,
+ name='dummy-controller-0',
+ node_xml=os.path.join(TEST_DUMMY_CONFIG,
+ 'baremetal0.xml'),
+ disk_img='dummy.qcow2')
+ self.assertIs(node.vm, domain)
+
+ @patch('apex.overcloud.node.OvercloudNode._update_xml')
+ @patch('apex.overcloud.node.OvercloudNode._configure_disk')
+ @patch('apex.overcloud.node.libvirt.open')
+ @patch('apex.overcloud.node.os.path.isfile')
+ def test_start(self, mock_isfile, mock_libvirt_conn, mock_configure_disk,
+ mock_update_xml):
+ mock_isfile.return_value = True
+ domain = mock_libvirt_conn.return_value.defineXML.return_value
+ node = OvercloudNode(role='controller', ip='123.123.123.123',
+ ovs_ctrlrs=None, ovs_mgrs=None,
+ name='dummy-controller-0',
+ node_xml=os.path.join(TEST_DUMMY_CONFIG,
+ 'baremetal0.xml'),
+ disk_img='dummy.qcow2')
+ node.start()
+ domain.create.assert_called()
+
+ @patch('apex.overcloud.node.OvercloudNode._update_xml')
+ @patch('apex.overcloud.node.OvercloudNode._configure_disk')
+ @patch('apex.overcloud.node.libvirt.open')
+ @patch('apex.overcloud.node.os.path.isfile')
+ def test_start_fail(self, mock_isfile, mock_libvirt_conn,
+ mock_configure_disk, mock_update_xml):
+ mock_isfile.return_value = True
+ domain = mock_libvirt_conn.return_value.defineXML.return_value
+ domain.create.side_effect = libvirtError('blah')
+ node = OvercloudNode(role='controller', ip='123.123.123.123',
+ ovs_ctrlrs=None, ovs_mgrs=None,
+ name='dummy-controller-0',
+ node_xml=os.path.join(TEST_DUMMY_CONFIG,
+ 'baremetal0.xml'),
+ disk_img='dummy.qcow2')
+ self.assertRaises(exc.OvercloudNodeException, node.start)
diff --git a/apex/tests/test_apex_undercloud.py b/apex/tests/test_apex_undercloud.py
index 9bc91e51..14586528 100644
--- a/apex/tests/test_apex_undercloud.py
+++ b/apex/tests/test_apex_undercloud.py
@@ -10,6 +10,7 @@
import ipaddress
import libvirt
import os
+import platform
import subprocess
import unittest
@@ -239,13 +240,16 @@ class TestUndercloud(unittest.TestCase):
assert_raises(ApexUndercloudException,
uc.configure, ns, ds, 'playbook', '/tmp/dir')
+ @patch('apex.undercloud.undercloud.virt_utils')
+ @patch('apex.undercloud.undercloud.uc_builder')
@patch('apex.undercloud.undercloud.os.remove')
@patch('apex.undercloud.undercloud.os.path')
@patch('apex.undercloud.undercloud.shutil')
@patch.object(Undercloud, '_get_vm', return_value=None)
@patch.object(Undercloud, 'create')
def test_setup_vols(self, mock_get_vm, mock_create,
- mock_shutil, mock_os_path, mock_os_remove):
+ mock_shutil, mock_os_path, mock_os_remove,
+ mock_uc_builder, mock_virt_utils):
uc = Undercloud('img_path', 'tplt_path', external_network=True)
mock_os_path.isfile.return_value = True
mock_os_path.exists.return_value = True
@@ -255,6 +259,9 @@ class TestUndercloud(unittest.TestCase):
src_img = os.path.join(uc.image_path, img_file)
dest_img = os.path.join(constants.LIBVIRT_VOLUME_PATH, img_file)
mock_shutil.copyfile.assert_called_with(src_img, dest_img)
+ if platform.machine() != 'aarch64':
+ mock_uc_builder.expand_disk.assert_called()
+ mock_virt_utils.virt_customize.assert_called()
@patch('apex.undercloud.undercloud.os.path')
@patch.object(Undercloud, '_get_vm', return_value=None)
@@ -276,13 +283,21 @@ class TestUndercloud(unittest.TestCase):
{'--upload':
'/root/.ssh/id_rsa.pub:/root/.ssh/authorized_keys'},
{'--run-command': 'chmod 600 /root/.ssh/authorized_keys'},
- {'--run-command': 'restorecon /root/.ssh/authorized_keys'},
+ {'--run-command': 'restorecon '
+ '-R -v /root/.ssh'},
+ {'--run-command': 'id -u stack || useradd -m stack'},
+ {'--run-command': 'mkdir -p /home/stack/.ssh'},
+ {'--run-command': 'chown stack:stack /home/stack/.ssh'},
{'--run-command':
'cp /root/.ssh/authorized_keys /home/stack/.ssh/'},
{'--run-command':
'chown stack:stack /home/stack/.ssh/authorized_keys'},
{'--run-command':
- 'chmod 600 /home/stack/.ssh/authorized_keys'}]
+ 'chmod 600 /home/stack/.ssh/authorized_keys'},
+ {'--run-command':
+ 'echo "stack ALL = (ALL) NOPASSWD: ALL" >> '
+ '/etc/sudoers'},
+ {'--run-command': 'touch /etc/cloud/cloud-init.disabled'}]
mock_vutils.virt_customize.assert_called_with(test_ops, uc.volume)
@patch.object(Undercloud, '_get_vm', return_value=None)
@@ -293,6 +308,7 @@ class TestUndercloud(unittest.TestCase):
ns_dict = {
'apex': MagicMock(),
'dns-domain': 'dns',
+ 'ntp': 'pool.ntp.org',
'networks': {'admin':
{'cidr': ipaddress.ip_network('192.0.2.0/24'),
'installer_vm': {'ip': '192.0.2.1',
@@ -309,7 +325,8 @@ class TestUndercloud(unittest.TestCase):
}
ns.__getitem__.side_effect = ns_dict.__getitem__
ns.__contains__.side_effect = ns_dict.__contains__
- ds = {'global_params': {}}
+ ds = {'global_params': {},
+ 'deploy_options': {}}
Undercloud('img_path', 'tplt_path').generate_config(ns, ds)
diff --git a/apex/undercloud/undercloud.py b/apex/undercloud/undercloud.py
index d2de2de1..5ee487c2 100644
--- a/apex/undercloud/undercloud.py
+++ b/apex/undercloud/undercloud.py
@@ -15,6 +15,7 @@ import shutil
import subprocess
import time
+from apex.builders import undercloud_builder as uc_builder
from apex.virtual import utils as virt_utils
from apex.virtual import configure_vm as vm_lib
from apex.common import constants
@@ -63,7 +64,7 @@ class Undercloud:
if self.external_net:
networks.append('external')
console = 'ttyAMA0' if platform.machine() == 'aarch64' else 'ttyS0'
- root = 'vda' if platform.machine() == 'aarch64' else 'sda'
+ root = 'vda2' if platform.machine() == 'aarch64' else 'sda'
self.vm = vm_lib.create_vm(name='undercloud',
image=self.volume,
@@ -72,7 +73,8 @@ class Undercloud:
kernel_args=['console={}'.format(console),
'root=/dev/{}'.format(root)],
default_network=True,
- template_dir=self.template_path)
+ template_dir=self.template_path,
+ memory=10240)
self.setup_volumes()
self.inject_auth()
@@ -110,7 +112,7 @@ class Undercloud:
# give 10 seconds to come up
time.sleep(10)
# set IP
- for x in range(5):
+ for x in range(10):
if self._set_ip():
logging.info("Undercloud started. IP Address: {}".format(
self.ip))
@@ -153,6 +155,8 @@ class Undercloud:
ansible_vars['apex_temp_dir'] = apex_temp_dir
ansible_vars['nat'] = self.detect_nat(net_settings)
+ ansible_vars['container_client'] = utils.find_container_client(
+ self.os_version)
try:
utils.run_ansible(ansible_vars, playbook, host=self.ip,
user='stack')
@@ -180,11 +184,19 @@ class Undercloud:
if os.path.exists(dest_img):
os.remove(dest_img)
shutil.copyfile(src_img, dest_img)
+ if img_file == self.image_name and platform.machine() != 'aarch64':
+ uc_builder.expand_disk(dest_img)
+ self.expand_root_fs()
+
shutil.chown(dest_img, user='qemu', group='qemu')
os.chmod(dest_img, 0o0744)
- # TODO(trozet):check if resize needed right now size is 50gb
+
+ def expand_root_fs(self):
# there is a lib called vminspect which has some dependencies and is
# not yet available in pip. Consider switching to this lib later.
+ logging.debug("Expanding root filesystem on /dev/sda partition")
+ virt_ops = [{constants.VIRT_RUN_CMD: 'xfs_growfs /dev/sda'}]
+ virt_utils.virt_customize(virt_ops, self.volume)
def inject_auth(self):
virt_ops = list()
@@ -199,10 +211,15 @@ class Undercloud:
'/root/.ssh/id_rsa.pub:/root/.ssh/authorized_keys'})
run_cmds = [
'chmod 600 /root/.ssh/authorized_keys',
- 'restorecon /root/.ssh/authorized_keys',
+ 'restorecon -R -v /root/.ssh',
+ 'id -u stack || useradd -m stack',
+ 'mkdir -p /home/stack/.ssh',
+ 'chown stack:stack /home/stack/.ssh',
'cp /root/.ssh/authorized_keys /home/stack/.ssh/',
'chown stack:stack /home/stack/.ssh/authorized_keys',
- 'chmod 600 /home/stack/.ssh/authorized_keys'
+ 'chmod 600 /home/stack/.ssh/authorized_keys',
+ 'echo "stack ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers',
+ 'touch /etc/cloud/cloud-init.disabled'
]
for cmd in run_cmds:
virt_ops.append({constants.VIRT_RUN_CMD: cmd})
@@ -234,12 +251,19 @@ class Undercloud:
"undercloud_hostname undercloud.{}".format(ns['dns-domain']),
"local_ip {}/{}".format(str(ns_admin['installer_vm']['ip']),
str(ns_admin['cidr']).split('/')[1]),
- "network_gateway {}".format(str(ns_admin['installer_vm']['ip'])),
- "network_cidr {}".format(str(ns_admin['cidr'])),
+ "generate_service_certificate false",
+ "undercloud_ntp_servers {}".format(str(ns['ntp'][0])),
+ "container_images_file "
+ "/home/stack/containers-prepare-parameter.yaml",
+ "undercloud_enable_selinux false"
+ ]
+
+ config['undercloud_network_config'] = [
+ "gateway {}".format(str(ns_admin['installer_vm']['ip'])),
+ "cidr {}".format(str(ns_admin['cidr'])),
"dhcp_start {}".format(str(ns_admin['dhcp_range'][0])),
"dhcp_end {}".format(str(ns_admin['dhcp_range'][1])),
"inspection_iprange {}".format(','.join(intro_range)),
- "generate_service_certificate false"
]
config['ironic_config'] = [
@@ -263,8 +287,11 @@ class Undercloud:
"prefix": str(ns_external['cidr']).split('/')[1],
"enabled": ns_external['enabled']
}
- # TODO(trozet): clean this logic up and merge with above
- if 'external' in ns.enabled_network_list:
+ # We will NAT external network if it is enabled. If external network
+ # is IPv6, we will NAT admin network in case we need IPv4 connectivity
+ # for things like DNS server.
+ if 'external' in ns.enabled_network_list and \
+ ns_external['cidr'].version == 4:
nat_cidr = ns_external['cidr']
else:
nat_cidr = ns['networks']['admin']['cidr']
diff --git a/apex/virtual/configure_vm.py b/apex/virtual/configure_vm.py
index ba0398bb..9d47bf03 100755
--- a/apex/virtual/configure_vm.py
+++ b/apex/virtual/configure_vm.py
@@ -102,6 +102,10 @@ def create_vm(name, image, diskbus='sata', baremetal_interfaces=['admin'],
with open(os.path.join(template_dir, 'domain.xml'), 'r') as f:
source_template = f.read()
imagefile = os.path.realpath(image)
+
+ if arch == 'aarch64' and diskbus == 'sata':
+ diskbus = 'virtio'
+
memory = int(memory) * 1024
params = {
'name': name,
@@ -118,9 +122,6 @@ def create_vm(name, image, diskbus='sata', baremetal_interfaces=['admin'],
'user_interface': '',
}
- # assign virtio as default for aarch64
- if arch == 'aarch64' and diskbus == 'sata':
- diskbus = 'virtio'
# Configure the bus type for the target disk device
params['diskbus'] = diskbus
nicparams = {
@@ -171,7 +172,7 @@ def create_vm(name, image, diskbus='sata', baremetal_interfaces=['admin'],
"""
params['user_interface'] = """
<controller type='virtio-serial' index='0'>
- <address type='virtio-mmio'/>
+ <address type='pci'/>
</controller>
<serial type='pty'>
<target port='0'/>
diff --git a/build/ansible.cfg b/build/ansible.cfg
new file mode 100644
index 00000000..a9db58a0
--- /dev/null
+++ b/build/ansible.cfg
@@ -0,0 +1,11 @@
+[defaults]
+retry_files_enabled = False
+forks = 25
+timeout = 60
+gather_timeout = 30
+
+[ssh_connection]
+ssh_args = -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o ControlMaster=auto -o ControlPersist=30m -o ServerAliveInterval=5 -o ServerAliveCountMax=5
+retries = 8
+pipelining = True
+
diff --git a/build/build_ovs_nsh.sh b/build/build_ovs_nsh.sh
new file mode 100644
index 00000000..4e15c363
--- /dev/null
+++ b/build/build_ovs_nsh.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+##############################################################################
+# Copyright (c) 2016 Tim Rozet (Red Hat) and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+set -e
+
+./boot.sh
+libtoolize --force
+aclocal
+autoheader
+automake --force-missing --add-missing
+autoconf
+./configure
+make rpm-fedora RPMBUILD_OPT="\"-D kversion `rpm -q kernel | rpmdev-sort | tail -n -1 | sed 's/^kernel-//'`\" --without check"
+make rpm-fedora-kmod RPMBUILD_OPT="\"-D kversion `rpm -q kernel | rpmdev-sort | tail -n -1 | sed 's/^kernel-//'`\"" \ No newline at end of file
diff --git a/build/containers-prepare-parameter.yaml b/build/containers-prepare-parameter.yaml
new file mode 100644
index 00000000..5089c335
--- /dev/null
+++ b/build/containers-prepare-parameter.yaml
@@ -0,0 +1,26 @@
+---
+parameter_defaults:
+ ContainerImagePrepare:
+ - push_destination: true
+ set:
+ ceph_image: daemon
+ ceph_namespace: docker.io/ceph
+ ceph_tag: v3.1.0-stable-3.1-luminous-centos-7-x86_64
+ name_prefix: centos-binary-
+ name_suffix: ''
+ namespace: docker.io/tripleomaster
+ neutron_driver: null
+ tag: current-tripleo
+ excludes:
+ - sensu
+ - manila
+ - octavia
+ - skydive
+ - drouter
+ - sahara
+ - rsys
+ - fluent
+ - designate
+ - barbican
+ - etcd
+ - ec2
diff --git a/build/csit-environment.yaml b/build/csit-environment.yaml
index 2fc63696..39486d32 100644
--- a/build/csit-environment.yaml
+++ b/build/csit-environment.yaml
@@ -14,6 +14,29 @@ parameter_defaults:
ExtraConfig:
tripleo::ringbuilder::build_ring: false
nova::api::default_floating_pool: 'external'
+ ControllerExtraConfig:
+ tripleo::firewall::firewall_rules:
+ '139 allow NFS TCP':
+ dport:
+ - 2049
+ - 111
+ - 32765
+ proto: tcp
+ action: accept
+ '140 allow NFS UDP':
+ dport:
+ - 2049
+ - 111
+ - 32765
+ proto: udp
+ action: accept
+ GlanceNfsEnabled: true
+ GlanceNfsShare: overcloud-controller-0.opnfvlf.org:/glance
+ GlanceNfsOptions:
+ 'rw,sync,context=system_u:object_r:glance_var_lib_t:s0'
+ NovaNfsEnabled: true
+ NovaNfsShare: overcloud-controller-0.opnfvlf.org:/nova
+ NovaNfsOptions: 'rw,sync,context=system_u:object_r:nfs_t:s0'
DockerPuppetProcessCount: 10
NeutronNetworkVLANRanges: 'datacentre:500:525'
SshServerOptions:
@@ -39,12 +62,14 @@ parameter_defaults:
UseDNS: 'no'
ControllerServices:
- OS::TripleO::Services::CACerts
+ - OS::TripleO::Services::Clustercheck
- OS::TripleO::Services::Kernel
- OS::TripleO::Services::Docker
- OS::TripleO::Services::Keystone
- OS::TripleO::Services::GlanceApi
- OS::TripleO::Services::GlanceRegistry
- OS::TripleO::Services::MySQL
+ - OS::TripleO::Services::MySQLClient
- OS::TripleO::Services::NeutronDhcpAgent
- OS::TripleO::Services::NeutronMetadataAgent
- OS::TripleO::Services::NeutronApi
@@ -59,10 +84,12 @@ parameter_defaults:
- OS::TripleO::Services::NovaMetadata
- OS::TripleO::Services::NovaScheduler
- OS::TripleO::Services::NovaConsoleauth
+ - OS::TripleO::Services::NovaPlacement
- OS::TripleO::Services::NovaVncProxy
- OS::TripleO::Services::Ntp
- OS::TripleO::Services::OsloMessagingRpc
- OS::TripleO::Services::OsloMessagingNotify
+ - OS::TripleO::Services::Pacemaker
- OS::TripleO::Services::Snmp
- OS::TripleO::Services::Sshd
- OS::TripleO::Services::Timezone
@@ -76,13 +103,13 @@ parameter_defaults:
- OS::TripleO::Services::Ntp
- OS::TripleO::Services::Snmp
- OS::TripleO::Services::Sshd
+ - OS::TripleO::Services::MySQLClient
- OS::TripleO::Services::NovaCompute
- OS::TripleO::Services::NovaLibvirt
- OS::TripleO::Services::Kernel
- OS::TripleO::Services::Docker
- OS::TripleO::Services::ComputeNeutronCorePlugin
- OS::TripleO::Services::ComputeNeutronMetadataAgent
- - OS::TripleO::Services::NovaPlacement
- OS::TripleO::Services::TripleoPackages
- OS::TripleO::Services::TripleoFirewall
- OS::TripleO::Services::NeutronSriovAgent
diff --git a/build/csit-queens-environment.yaml b/build/csit-queens-environment.yaml
index f2b7b015..12c994d1 100644
--- a/build/csit-queens-environment.yaml
+++ b/build/csit-queens-environment.yaml
@@ -14,6 +14,29 @@ parameter_defaults:
ExtraConfig:
tripleo::ringbuilder::build_ring: false
nova::api::default_floating_pool: 'external'
+ ControllerExtraConfig:
+ tripleo::firewall::firewall_rules:
+ '139 allow NFS TCP':
+ dport:
+ - 2049
+ - 111
+ - 32765
+ proto: tcp
+ action: accept
+ '140 allow NFS UDP':
+ dport:
+ - 2049
+ - 111
+ - 32765
+ proto: udp
+ action: accept
+ GlanceNfsEnabled: true
+ GlanceNfsShare: overcloud-controller-0.opnfvlf.org:/glance
+ GlanceNfsOptions:
+ 'rw,sync,context=system_u:object_r:glance_var_lib_t:s0'
+ NovaNfsEnabled: true
+ NovaNfsShare: overcloud-controller-0.opnfvlf.org:/nova
+ NovaNfsOptions: 'rw,sync,context=system_u:object_r:nfs_t:s0'
DockerPuppetProcessCount: 10
NeutronNetworkVLANRanges: 'datacentre:500:525'
SshServerOptions:
@@ -39,12 +62,14 @@ parameter_defaults:
UseDNS: 'no'
ControllerServices:
- OS::TripleO::Services::CACerts
+ - OS::TripleO::Services::Clustercheck
- OS::TripleO::Services::Kernel
- OS::TripleO::Services::Docker
- OS::TripleO::Services::Keystone
- OS::TripleO::Services::GlanceApi
- OS::TripleO::Services::GlanceRegistry
- OS::TripleO::Services::MySQL
+ - OS::TripleO::Services::MySQLClient
- OS::TripleO::Services::NeutronDhcpAgent
- OS::TripleO::Services::NeutronMetadataAgent
- OS::TripleO::Services::NeutronApi
@@ -58,10 +83,12 @@ parameter_defaults:
- OS::TripleO::Services::MongoDb
- OS::TripleO::Services::NovaApi
- OS::TripleO::Services::NovaMetadata
+ - OS::TripleO::Services::NovaPlacement
- OS::TripleO::Services::NovaScheduler
- OS::TripleO::Services::NovaConsoleauth
- OS::TripleO::Services::NovaVncProxy
- OS::TripleO::Services::Ntp
+ - OS::TripleO::Services::Pacemaker
- OS::TripleO::Services::Snmp
- OS::TripleO::Services::Sshd
- OS::TripleO::Services::Timezone
@@ -75,13 +102,13 @@ parameter_defaults:
- OS::TripleO::Services::Ntp
- OS::TripleO::Services::Snmp
- OS::TripleO::Services::Sshd
+ - OS::TripleO::Services::MySQLClient
- OS::TripleO::Services::NovaCompute
- OS::TripleO::Services::NovaLibvirt
- OS::TripleO::Services::Kernel
- OS::TripleO::Services::Docker
- OS::TripleO::Services::ComputeNeutronCorePlugin
- OS::TripleO::Services::ComputeNeutronMetadataAgent
- - OS::TripleO::Services::NovaPlacement
- OS::TripleO::Services::TripleoPackages
- OS::TripleO::Services::TripleoFirewall
- OS::TripleO::Services::NeutronSriovAgent
diff --git a/build/csit-rocky-environment.yaml b/build/csit-rocky-environment.yaml
new file mode 100644
index 00000000..39486d32
--- /dev/null
+++ b/build/csit-rocky-environment.yaml
@@ -0,0 +1,116 @@
+---
+# Environment file used to list common parameters required for all deployment
+# types
+
+parameters:
+ CloudDomain: opnfvlf.org
+
+parameter_defaults:
+ GlanceBackend: file
+ CeilometerStoreEvents: true
+ NeutronEnableForceMetadata: true
+ NeutronEnableDHCPMetadata: true
+ NeutronEnableIsolatedMetadata: true
+ ExtraConfig:
+ tripleo::ringbuilder::build_ring: false
+ nova::api::default_floating_pool: 'external'
+ ControllerExtraConfig:
+ tripleo::firewall::firewall_rules:
+ '139 allow NFS TCP':
+ dport:
+ - 2049
+ - 111
+ - 32765
+ proto: tcp
+ action: accept
+ '140 allow NFS UDP':
+ dport:
+ - 2049
+ - 111
+ - 32765
+ proto: udp
+ action: accept
+ GlanceNfsEnabled: true
+ GlanceNfsShare: overcloud-controller-0.opnfvlf.org:/glance
+ GlanceNfsOptions:
+ 'rw,sync,context=system_u:object_r:glance_var_lib_t:s0'
+ NovaNfsEnabled: true
+ NovaNfsShare: overcloud-controller-0.opnfvlf.org:/nova
+ NovaNfsOptions: 'rw,sync,context=system_u:object_r:nfs_t:s0'
+ DockerPuppetProcessCount: 10
+ NeutronNetworkVLANRanges: 'datacentre:500:525'
+ SshServerOptions:
+ HostKey:
+ - '/etc/ssh/ssh_host_rsa_key'
+ - '/etc/ssh/ssh_host_ecdsa_key'
+ - '/etc/ssh/ssh_host_ed25519_key'
+ SyslogFacility: 'AUTHPRIV'
+ AuthorizedKeysFile: '.ssh/authorized_keys'
+ PasswordAuthentication: 'no'
+ ChallengeResponseAuthentication: 'no'
+ GSSAPIAuthentication: 'no'
+ GSSAPICleanupCredentials: 'no'
+ UsePAM: 'yes'
+ X11Forwarding: 'yes'
+ UsePrivilegeSeparation: 'sandbox'
+ AcceptEnv:
+ - 'LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES'
+ - 'LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT'
+ - 'LC_IDENTIFICATION LC_ALL LANGUAGE'
+ - 'XMODIFIERS'
+ Subsystem: 'sftp /usr/libexec/openssh/sftp-server'
+ UseDNS: 'no'
+ ControllerServices:
+ - OS::TripleO::Services::CACerts
+ - OS::TripleO::Services::Clustercheck
+ - OS::TripleO::Services::Kernel
+ - OS::TripleO::Services::Docker
+ - OS::TripleO::Services::Keystone
+ - OS::TripleO::Services::GlanceApi
+ - OS::TripleO::Services::GlanceRegistry
+ - OS::TripleO::Services::MySQL
+ - OS::TripleO::Services::MySQLClient
+ - OS::TripleO::Services::NeutronDhcpAgent
+ - OS::TripleO::Services::NeutronMetadataAgent
+ - OS::TripleO::Services::NeutronApi
+ - OS::TripleO::Services::NeutronCorePlugin
+ - OS::TripleO::Services::HAproxy
+ - OS::TripleO::Services::Keepalived
+ - OS::TripleO::Services::Memcached
+ - OS::TripleO::Services::Redis
+ - OS::TripleO::Services::NovaConductor
+ - OS::TripleO::Services::MongoDb
+ - OS::TripleO::Services::NovaApi
+ - OS::TripleO::Services::NovaMetadata
+ - OS::TripleO::Services::NovaScheduler
+ - OS::TripleO::Services::NovaConsoleauth
+ - OS::TripleO::Services::NovaPlacement
+ - OS::TripleO::Services::NovaVncProxy
+ - OS::TripleO::Services::Ntp
+ - OS::TripleO::Services::OsloMessagingRpc
+ - OS::TripleO::Services::OsloMessagingNotify
+ - OS::TripleO::Services::Pacemaker
+ - OS::TripleO::Services::Snmp
+ - OS::TripleO::Services::Sshd
+ - OS::TripleO::Services::Timezone
+ - OS::TripleO::Services::TripleoPackages
+ - OS::TripleO::Services::TripleoFirewall
+ - OS::TripleO::Services::OpenDaylightApi
+ - OS::TripleO::Services::OpenDaylightOvs
+ ComputeServices:
+ - OS::TripleO::Services::CACerts
+ - OS::TripleO::Services::Timezone
+ - OS::TripleO::Services::Ntp
+ - OS::TripleO::Services::Snmp
+ - OS::TripleO::Services::Sshd
+ - OS::TripleO::Services::MySQLClient
+ - OS::TripleO::Services::NovaCompute
+ - OS::TripleO::Services::NovaLibvirt
+ - OS::TripleO::Services::Kernel
+ - OS::TripleO::Services::Docker
+ - OS::TripleO::Services::ComputeNeutronCorePlugin
+ - OS::TripleO::Services::ComputeNeutronMetadataAgent
+ - OS::TripleO::Services::TripleoPackages
+ - OS::TripleO::Services::TripleoFirewall
+ - OS::TripleO::Services::NeutronSriovAgent
+ - OS::TripleO::Services::OpenDaylightOvs
diff --git a/build/kubernetes-environment.yaml b/build/kubernetes-environment.yaml
new file mode 100644
index 00000000..bfc1f9ad
--- /dev/null
+++ b/build/kubernetes-environment.yaml
@@ -0,0 +1,26 @@
+---
+resource_registry:
+ OS::TripleO::Services::Docker: OS::Heat::None
+
+
+parameter_defaults:
+ ControllerServices:
+ - OS::TripleO::Services::Kernel
+ - OS::TripleO::Services::Ntp
+ - OS::TripleO::Services::Snmp
+ - OS::TripleO::Services::Timezone
+ - OS::TripleO::Services::TripleoPackages
+ # - OS::TripleO::Services::TripleoFirewall
+ - OS::TripleO::Services::Sshd
+ # - OS::TripleO::Services::OpenShift::Master
+ # - OS::TripleO::Services::OpenShift::Worker
+ ComputeServices:
+ - OS::TripleO::Services::Kernel
+ - OS::TripleO::Services::Ntp
+ - OS::TripleO::Services::Snmp
+ - OS::TripleO::Services::Timezone
+ - OS::TripleO::Services::TripleoPackages
+ # - OS::TripleO::Services::TripleoFirewall
+ - OS::TripleO::Services::Sshd
+ # - OS::TripleO::Services::OpenShift::Worker
+ Debug: true
diff --git a/build/network-environment.yaml b/build/network-environment.yaml
index 3fd22e3d..1397a0c8 100644
--- a/build/network-environment.yaml
+++ b/build/network-environment.yaml
@@ -63,33 +63,53 @@ parameter_defaults:
NeutronExternalNetworkBridge: 'br-ex'
ServiceNetMap:
+ ApacheNetwork: internal_api
NeutronTenantNetwork: tenant
CeilometerApiNetwork: internal_api
AodhApiNetwork: internal_api
+ PankoApiNetwork: internal_api
+ BarbicanApiNetwork: internal_api
+ GnocchiApiNetwork: internal_api
OpendaylightApiNetwork: internal_api
MongoDbNetwork: internal_api
CinderApiNetwork: internal_api
CinderIscsiNetwork: storage
GlanceApiNetwork: internal_api
GlanceRegistryNetwork: internal_api
+ IronicApiNetwork: ctlplane
+ IronicNetwork: ctlplane
+ IronicInspectorNetwork: ctlplane
KeystoneAdminApiNetwork: ctlplane
KeystonePublicApiNetwork: internal_api
NeutronApiNetwork: internal_api
HeatApiNetwork: internal_api
+ HeatApiCfnNetwork: internal_api
+ HeatApiCloudwatchNetwork: internal_api
+ ManilaApiNetwork: internal_api
+ MetricsQdrNetwork: internal_api
NovaApiNetwork: internal_api
NovaMetadataNetwork: internal_api
+ NovaPlacementNetwork: internal_api
NovaVncProxyNetwork: internal_api
+ NovaLibvirtNetwork: internal_api
+ NovajoinNetwork: internal_api
+ OctaviaApiNetwork: internal_api
SwiftMgmtNetwork: storage
SwiftProxyNetwork: storage
TackerApiNetwork: internal_api
CongressApiNetwork: internal_api
HorizonNetwork: internal_api
+ OsloMessagingRpcNetwork: internal_api
+ OsloMessagingNotifyNetwork: internal_api
MemcachedNetwork: internal_api
RabbitMqNetwork: internal_api
RedisNetwork: internal_api
MysqlNetwork: internal_api
CephClusterNetwork: storage
- CephPublicNetwork: storage
+ CephMonNetwork: storage
+ PublicNetwork: external
+ OvnDbsNetwork: internal_api
+ DockerRegistryNetwork: ctlplane
# Define which network will be used for hostname resolution
ControllerHostnameResolveNetwork: internal_api
ComputeHostnameResolveNetwork: internal_api
diff --git a/build/nics-template.yaml.jinja2 b/build/nics-template.yaml.jinja2
index 959a3926..6d1fb9c0 100644
--- a/build/nics-template.yaml.jinja2
+++ b/build/nics-template.yaml.jinja2
@@ -9,30 +9,14 @@ parameters:
default: ''
description: IP address/subnet on the ctlplane network
type: string
- ExternalIpSubnet:
- default: ''
- description: IP address/subnet on the external network
- type: string
- InternalApiIpSubnet:
- default: ''
- description: IP address/subnet on the internal API network
- type: string
- StorageIpSubnet:
- default: ''
- description: IP address/subnet on the storage network
- type: string
- StorageMgmtIpSubnet:
- default: ''
- description: IP address/subnet on the storage mgmt network
- type: string
- TenantIpSubnet:
- default: ''
- description: IP address/subnet on the tenant network
- type: string
- ManagementIpSubnet: # Only populated when including environments/network-management.yaml
- default: ''
- description: IP address/subnet on the management network
- type: string
+ ControlPlaneStaticRoutes:
+ default: []
+ description: >
+ Routes for the ctlplane network traffic.
+ JSON route e.g. [{'destination':'10.0.0.0/16', 'nexthop':'10.0.0.1'}]
+ Unless the default is changed, the parameter is automatically resolved
+ from the subnet host_routes attribute.
+ type: json
ExternalNetworkVlanID:
default: 10
description: Vlan ID for the external network traffic.
@@ -75,6 +59,90 @@ parameters:
EC2MetadataIp: # Override this via parameter_defaults
description: The IP address of the EC2 metadata server.
type: string
+ ExternalIpSubnet:
+ default: ''
+ description: IP address/subnet on the external network
+ type: string
+ ExternalInterfaceRoutes:
+ default: []
+ description: >
+ Routes for the external network traffic.
+ JSON route e.g. [{'destination':'10.0.0.0/16', 'nexthop':'10.0.0.1'}]
+ Unless the default is changed, the parameter is automatically resolved
+ from the subnet host_routes attribute.
+ type: json
+ InternalApiIpSubnet:
+ default: ''
+ description: IP address/subnet on the internal_api network
+ type: string
+ InternalApiInterfaceRoutes:
+ default: []
+ description: >
+ Routes for the internal_api network traffic.
+ JSON route e.g. [{'destination':'10.0.0.0/16', 'nexthop':'10.0.0.1'}]
+ Unless the default is changed, the parameter is automatically resolved
+ from the subnet host_routes attribute.
+ type: json
+ StorageIpSubnet:
+ default: ''
+ description: IP address/subnet on the storage network
+ type: string
+ StorageInterfaceRoutes:
+ default: []
+ description: >
+ Routes for the storage network traffic.
+ JSON route e.g. [{'destination':'10.0.0.0/16', 'nexthop':'10.0.0.1'}]
+ Unless the default is changed, the parameter is automatically resolved
+ from the subnet host_routes attribute.
+ type: json
+ StorageMgmtIpSubnet:
+ default: ''
+ description: IP address/subnet on the storage_mgmt network
+ type: string
+ StorageMgmtInterfaceRoutes:
+ default: []
+ description: >
+ Routes for the storage_mgmt network traffic.
+ JSON route e.g. [{'destination':'10.0.0.0/16', 'nexthop':'10.0.0.1'}]
+ Unless the default is changed, the parameter is automatically resolved
+ from the subnet host_routes attribute.
+ type: json
+ StorageNFSIpSubnet:
+ default: ''
+ description: IP address/subnet on the storage_nfs network
+ type: string
+ StorageNFSRoutes:
+ default: []
+ description: >
+ Routes for the storage_nfs network traffic.
+ JSON route e.g. [{'destination':'10.0.0.0/16', 'nexthop':'10.0.0.1'}]
+ Unless the default is changed, the parameter is automatically resolved
+ from the subnet host_routes attribute.
+ type: json
+ TenantIpSubnet:
+ default: ''
+ description: IP address/subnet on the tenant network
+ type: string
+ TenantInterfaceRoutes:
+ default: []
+ description: >
+ Routes for the tenant network traffic.
+ JSON route e.g. [{'destination':'10.0.0.0/16', 'nexthop':'10.0.0.1'}]
+ Unless the default is changed, the parameter is automatically resolved
+ from the subnet host_routes attribute.
+ type: json
+ ManagementIpSubnet:
+ default: ''
+ description: IP address/subnet on the management network
+ type: string
+ ManagementInterfaceRoutes:
+ default: []
+ description: >
+ Routes for the management network traffic.
+ JSON route e.g. [{'destination':'10.0.0.0/16', 'nexthop':'10.0.0.1'}]
+ Unless the default is changed, the parameter is automatically resolved
+ from the subnet host_routes attribute.
+ type: json
resources:
OsNetConfigImpl:
@@ -190,6 +258,18 @@ resources:
name: {{ nets['tenant']['nic_mapping'][role]['members'][0] }}
# force the MAC address of the bridge to this interface
primary: true
+ {%- elif nets['tenant']['segmentation_type'] == 'vlan' %}
+ type: ovs_bridge
+ name: br-vlan
+ use_dhcp: false
+ addresses:
+ -
+ ip_netmask: {get_param: TenantIpSubnet}
+ members:
+ -
+ type: interface
+ name: {{ nets['tenant']['nic_mapping'][role]['members'][0] }}
+ primary: true
{%- else %}
-
type: {{ nets['tenant']['nic_mapping'][role]['phys_type'] }}
@@ -242,7 +322,6 @@ resources:
name: {{ nets['external'][0]['nic_mapping'][role]['members'][0] }}
# force the MAC address of the bridge to this interface
primary: true
- {%- if role == 'controller' %}
dns_servers: {get_param: DnsServers}
addresses:
-
@@ -252,7 +331,6 @@ resources:
default: true
ip_netmask: 0.0.0.0/0
next_hop: {get_param: ExternalInterfaceDefaultRoute}
- {%- endif %}
{%- endif %}
{%- if nets['storage']['enabled'] and nets['storage']['nic_mapping'][role]['vlan'] == 'native' %}
-
diff --git a/build/patches/neutron-patch-NSDriver.patch b/build/patches/neutron-patch-NSDriver.patch
index 84b4fb02..95ad58f9 100644
--- a/build/patches/neutron-patch-NSDriver.patch
+++ b/build/patches/neutron-patch-NSDriver.patch
@@ -139,7 +139,7 @@ index 88d6e67f31..c0fab604d1 100644
+
+ def _configure_mtu(self, ns_dev, mtu=None):
+ # Need to set MTU, after added to namespace. See review
-+ # https://review.openstack.org/327651
++ # https://review.opendev.org/327651
+ try:
+ # Note: network_device_mtu will be deprecated in future
+ mtu_override = self.conf.network_device_mtu
diff --git a/build/rpm_specs/opnfv-apex.spec b/build/rpm_specs/opnfv-apex.spec
index 7f4eb702..d05397ed 100644
--- a/build/rpm_specs/opnfv-apex.spec
+++ b/build/rpm_specs/opnfv-apex.spec
@@ -1,7 +1,7 @@
%global srcname opnfv-apex
Name: python34-%{srcname}
-Version: 7.0
+Version: 8.0
Release: %{_release}
Summary: Scripts for OPNFV deployment using Apex
@@ -67,19 +67,23 @@ install config/inventory/pod_example_settings.yaml %{buildroot}%{_docdir}/opnfv/
%attr(755,root,root) %{_bindir}/opnfv-pyutil
%{_datadir}/opnfv-apex/
%{_sysconfdir}/bash_completion.d/apex
+%{_sysconfdir}/opnfv-apex/common-patches.yaml
%{_sysconfdir}/opnfv-apex/os-nosdn-nofeature-noha.yaml
%{_sysconfdir}/opnfv-apex/os-nosdn-bar-noha.yaml
%{_sysconfdir}/opnfv-apex/os-nosdn-bar-ha.yaml
%{_sysconfdir}/opnfv-apex/os-nosdn-calipso-noha.yaml
+%{_sysconfdir}/opnfv-apex/os-nosdn-calipso_rocky-noha.yaml
%{_sysconfdir}/opnfv-apex/os-nosdn-fdio-noha.yaml
%{_sysconfdir}/opnfv-apex/os-nosdn-fdio-ha.yaml
%{_sysconfdir}/opnfv-apex/os-nosdn-ovs_dpdk-noha.yaml
%{_sysconfdir}/opnfv-apex/os-nosdn-nofeature-ha.yaml
%{_sysconfdir}/opnfv-apex/os-nosdn-performance-ha.yaml
-%{_sysconfdir}/opnfv-apex/os-nosdn-queens-noha.yaml
-%{_sysconfdir}/opnfv-apex/os-nosdn-queens-ha.yaml
+%{_sysconfdir}/opnfv-apex/os-nosdn-rocky-noha.yaml
+%{_sysconfdir}/opnfv-apex/os-nosdn-rocky-ha.yaml
%{_sysconfdir}/opnfv-apex/os-odl-queens-noha.yaml
%{_sysconfdir}/opnfv-apex/os-odl-queens-ha.yaml
+%{_sysconfdir}/opnfv-apex/os-odl-rocky-noha.yaml
+%{_sysconfdir}/opnfv-apex/os-odl-rocky-ha.yaml
%{_sysconfdir}/opnfv-apex/os-nosdn-ovs_dpdk-ha.yaml
%{_sysconfdir}/opnfv-apex/os-nosdn-kvm-ha.yaml
%{_sysconfdir}/opnfv-apex/os-nosdn-kvm-noha.yaml
@@ -87,8 +91,12 @@ install config/inventory/pod_example_settings.yaml %{buildroot}%{_docdir}/opnfv/
%{_sysconfdir}/opnfv-apex/os-nosdn-kvm_ovs_dpdk-noha.yaml
%{_sysconfdir}/opnfv-apex/os-odl-bgpvpn-ha.yaml
%{_sysconfdir}/opnfv-apex/os-odl-bgpvpn-noha.yaml
+%{_sysconfdir}/opnfv-apex/os-odl-bgpvpn_rocky-ha.yaml
+%{_sysconfdir}/opnfv-apex/os-odl-bgpvpn_rocky-noha.yaml
%{_sysconfdir}/opnfv-apex/os-odl-sfc-ha.yaml
%{_sysconfdir}/opnfv-apex/os-odl-sfc-noha.yaml
+%{_sysconfdir}/opnfv-apex/os-odl-sfc_rocky-ha.yaml
+%{_sysconfdir}/opnfv-apex/os-odl-sfc_rocky-noha.yaml
%{_sysconfdir}/opnfv-apex/os-odl-fdio-noha.yaml
%{_sysconfdir}/opnfv-apex/os-odl_netvirt-fdio-noha.yaml
%{_sysconfdir}/opnfv-apex/os-odl-fdio-ha.yaml
@@ -103,7 +111,8 @@ install config/inventory/pod_example_settings.yaml %{buildroot}%{_docdir}/opnfv/
%{_sysconfdir}/opnfv-apex/os-odl-sriov-ha.yaml
%{_sysconfdir}/opnfv-apex/os-odl-sriov-noha.yaml
%{_sysconfdir}/opnfv-apex/os-odl-gluon-noha.yaml
-%{_sysconfdir}/opnfv-apex/os-ovn-nofeature-noha.yaml
+%{_sysconfdir}/opnfv-apex/os-ovn-nofeature-ha.yaml
+%{_sysconfdir}/opnfv-apex/os-ovn-rocky-ha.yaml
%{_sysconfdir}/opnfv-apex/os-onos-nofeature-ha.yaml
%{_sysconfdir}/opnfv-apex/os-onos-sfc-ha.yaml
%{_sysconfdir}/opnfv-apex/os-ocl-nofeature-ha.yaml
@@ -111,6 +120,8 @@ install config/inventory/pod_example_settings.yaml %{buildroot}%{_docdir}/opnfv/
%{_sysconfdir}/opnfv-apex/network_settings_csit.yaml
%{_sysconfdir}/opnfv-apex/network_settings_vlans.yaml
%{_sysconfdir}/opnfv-apex/network_settings_v6.yaml
+%{_sysconfdir}/opnfv-apex/k8s-nosdn-nofeature-noha.yaml
+%{_sysconfdir}/opnfv-apex/network_settings_tenant_vlan.yaml
%doc %{_docdir}/opnfv/LICENSE.rst
%doc %{_docdir}/opnfv/installation-instructions.html
%doc %{_docdir}/opnfv/release-notes.rst
@@ -121,6 +132,18 @@ install config/inventory/pod_example_settings.yaml %{buildroot}%{_docdir}/opnfv/
%doc %{_docdir}/opnfv/inventory.yaml.example
%changelog
+* Thu Sep 27 2018 Tim Rozet <trozet@redhat.com> - 8.0-0
+ Updates from Queens to Rocky
+* Fri Aug 24 2018 Tim Rozet <trozet@redhat.com> - 7.0-7
+ Add Calipso for Queens
+* Tue Aug 21 2018 Ricardo Noriega <rnoriega@redhat.com> - 7.0-6
+ Enable SFC scenarios for Gambia
+* Tue Aug 14 2018 Tim Rozet <trozet@redhat.com> - 7.0-5
+ Adds common patches file
+* Wed Jun 27 2018 Feng Pan <fpan@redhat.com> - 7.0-4
+ Adds network_settings_tenant_vlan.yaml
+* Wed Jun 20 2018 Zenghui Shi <zshi@redhat.com> - 7.0-3
+ Adds Kubernetes deployment scenario
* Fri Jun 15 2018 Tim Rozet <trozet@redhat.com> - 7.0-2
Adds missing HA deploy settings for Queens
* Fri May 25 2018 Tim Rozet <trozet@redhat.com> - 7.0-1
diff --git a/build/upstream-environment.yaml b/build/upstream-environment.yaml
index debe6f3a..ab110177 100644
--- a/build/upstream-environment.yaml
+++ b/build/upstream-environment.yaml
@@ -7,7 +7,13 @@ parameters:
parameter_defaults:
DockerPuppetProcessCount: 10
- NeutronNetworkVLANRanges: 'datacentre:500:525'
+ #NeutronNetworkVLANRanges: 'datacentre:500:525'
+ #NeutronBridgeMappings: "datacentre:br-ex"
+ #OpenDaylightProviderMappings: "datacentre:br-ex"
+ NeutronNetworkType: vxlan
+ MigrationSshKey:
+ public_key: replace_public_key
+ private_key: replace_private_key
SshServerOptions:
HostKey:
- '/etc/ssh/ssh_host_rsa_key'
diff --git a/ci/util.sh b/ci/util.sh
index a9df0213..5172ae1b 100755
--- a/ci/util.sh
+++ b/ci/util.sh
@@ -48,7 +48,7 @@ controller<number> or compute<number>"
node_output=$(undercloud_connect "stack" "source stackrc; nova list")
node=$(echo "$1" | sed -E 's/([a-zA-Z]+)([0-9]+)/\1-\2/')
- node_ip=$(echo "$node_output" | grep "$node" | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
+ node_ip=$(echo "$node_output" | grep "$node " | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
if [ "$node_ip" == "" ]; then
echo -e "Unable to find IP for ${node} in \n${node_output}"
diff --git a/config/deploy/common-patches.yaml b/config/deploy/common-patches.yaml
new file mode 100644
index 00000000..bac6812c
--- /dev/null
+++ b/config/deploy/common-patches.yaml
@@ -0,0 +1,45 @@
+---
+patches:
+ master:
+ undercloud:
+ - change-id: I2e0a40d7902f592e4b7bd727f57048111e0bea36
+ project: openstack/tripleo-common
+ - change-id: Iaa2276aadae351fbc138de258c51d786f69e4395
+ project: openstack/tripleo-common
+ - change-id: I8d1db69d520da069099f919f286e6a553dd645a5
+ project: openstack/tripleo-heat-templates
+ - change-id: Ia51a825d11bd9b94d0110f13cdf2a6bbcedf6194
+ project: openstack/tripleo-common
+ overcloud:
+ - change-id: Ie988ba6a2d444a614e97c0edf5fce24b23970310
+ project: openstack/puppet-tripleo
+ - change-id: I93e3d355625508fdc42f44bdd358f3ba86fbd8d7
+ project: openstack/puppet-tripleo
+ rocky:
+ undercloud:
+ - change-id: I2e0a40d7902f592e4b7bd727f57048111e0bea36
+ project: openstack/tripleo-common
+ branch: master
+ - change-id: Iaa2276aadae351fbc138de258c51d786f69e4395
+ project: openstack/tripleo-common
+ branch: master
+ - change-id: I8d1db69d520da069099f919f286e6a553dd645a5
+ project: openstack/tripleo-heat-templates
+ - change-id: Ia51a825d11bd9b94d0110f13cdf2a6bbcedf6194
+ project: openstack/tripleo-common
+ overcloud:
+ - change-id: Ie988ba6a2d444a614e97c0edf5fce24b23970310
+ project: openstack/puppet-tripleo
+ branch: master
+ - change-id: I93e3d355625508fdc42f44bdd358f3ba86fbd8d7
+ project: openstack/puppet-tripleo
+ branch: master
+ queens:
+ undercloud:
+ - change-id: I966bf7f6f8d1cbc656abfad59e8bb927e1aa53c2
+ project: openstack/tripleo-common
+ overcloud:
+ - change-id: Ie988ba6a2d444a614e97c0edf5fce24b23970310
+ project: openstack/puppet-tripleo
+ - change-id: I93e3d355625508fdc42f44bdd358f3ba86fbd8d7
+ project: openstack/puppet-tripleo
diff --git a/config/deploy/deploy_settings.yaml b/config/deploy/deploy_settings.yaml
index b8f01006..caef2628 100644
--- a/config/deploy/deploy_settings.yaml
+++ b/config/deploy/deploy_settings.yaml
@@ -108,3 +108,8 @@ deploy_options:
# Set dovetail option to install dovetail
# dovetail: false
+
+ # Whether the nodes are deployed as openstack, kubernetes or openshift nodes
+ # Defaults to openstack.
+ # Possible values are openstack, k8s, openshift
+ vim: 'openstack'
diff --git a/config/deploy/k8s-nosdn-nofeature-noha.yaml b/config/deploy/k8s-nosdn-nofeature-noha.yaml
new file mode 100644
index 00000000..33a9b41a
--- /dev/null
+++ b/config/deploy/k8s-nosdn-nofeature-noha.yaml
@@ -0,0 +1,16 @@
+---
+global_params:
+ ha_enabled: false
+ patches:
+ undercloud:
+ - change-id: Ib8ff69a4bc869de21ad838b3bc6c38a8676036c6
+ project: openstack/tripleo-heat-templates
+
+deploy_options:
+ sdn_controller: false
+ tacker: false
+ congress: false
+ sfc: false
+ vpn: false
+ ceph: false
+ vim: 'k8s'
diff --git a/config/deploy/os-nosdn-calipso-noha.yaml b/config/deploy/os-nosdn-calipso-noha.yaml
index ce5c8a5e..6502bcb0 100644
--- a/config/deploy/os-nosdn-calipso-noha.yaml
+++ b/config/deploy/os-nosdn-calipso-noha.yaml
@@ -3,6 +3,7 @@ global_params:
ha_enabled: false
deploy_options:
+ containers: true
sdn_controller: false
sfc: false
vpn: false
diff --git a/config/deploy/os-ovn-nofeature-noha.yaml b/config/deploy/os-nosdn-calipso_rocky-noha.yaml
index 8c8c5f97..b14ceed5 100644
--- a/config/deploy/os-ovn-nofeature-noha.yaml
+++ b/config/deploy/os-nosdn-calipso_rocky-noha.yaml
@@ -3,8 +3,9 @@ global_params:
ha_enabled: false
deploy_options:
- sdn_controller: ovn
- tacker: false
- congress: true
+ containers: true
+ os_version: rocky
+ sdn_controller: false
sfc: false
vpn: false
+ calipso: true
diff --git a/config/deploy/os-nosdn-nofeature-ha.yaml b/config/deploy/os-nosdn-nofeature-ha.yaml
index 13bf6d89..d896a672 100644
--- a/config/deploy/os-nosdn-nofeature-ha.yaml
+++ b/config/deploy/os-nosdn-nofeature-ha.yaml
@@ -1,10 +1,7 @@
---
global_params:
ha_enabled: true
- patches:
- undercloud:
- - change-id: Ib8ff69a4bc869de21ad838b3bc6c38a8676036c6
- project: openstack/tripleo-heat-templates
+
deploy_options:
containers: true
os_version: master
diff --git a/config/deploy/os-nosdn-nofeature-noha.yaml b/config/deploy/os-nosdn-nofeature-noha.yaml
index 0b1aaa04..0725031f 100644
--- a/config/deploy/os-nosdn-nofeature-noha.yaml
+++ b/config/deploy/os-nosdn-nofeature-noha.yaml
@@ -1,10 +1,7 @@
---
global_params:
ha_enabled: false
- patches:
- undercloud:
- - change-id: Ib8ff69a4bc869de21ad838b3bc6c38a8676036c6
- project: openstack/tripleo-heat-templates
+
deploy_options:
containers: true
os_version: master
diff --git a/config/deploy/os-nosdn-queens-ha.yaml b/config/deploy/os-nosdn-rocky-ha.yaml
index 88a40042..152a8840 100644
--- a/config/deploy/os-nosdn-queens-ha.yaml
+++ b/config/deploy/os-nosdn-rocky-ha.yaml
@@ -3,7 +3,7 @@ global_params:
ha_enabled: true
deploy_options:
containers: true
- os_version: queens
+ os_version: rocky
sdn_controller: false
tacker: false
congress: false
diff --git a/config/deploy/os-nosdn-queens-noha.yaml b/config/deploy/os-nosdn-rocky-noha.yaml
index efadc31e..5fecfb6d 100644
--- a/config/deploy/os-nosdn-queens-noha.yaml
+++ b/config/deploy/os-nosdn-rocky-noha.yaml
@@ -3,7 +3,7 @@ global_params:
ha_enabled: false
deploy_options:
containers: true
- os_version: queens
+ os_version: rocky
sdn_controller: false
tacker: false
congress: false
diff --git a/config/deploy/os-odl-bgpvpn-ha.yaml b/config/deploy/os-odl-bgpvpn-ha.yaml
index 68b62734..f61e1a60 100644
--- a/config/deploy/os-odl-bgpvpn-ha.yaml
+++ b/config/deploy/os-odl-bgpvpn-ha.yaml
@@ -3,9 +3,11 @@ global_params:
ha_enabled: true
deploy_options:
+ containers: true
+ os_version: master
sdn_controller: opendaylight
- odl_version: nitrogen
+ odl_version: master
tacker: false
- congress: true
+ congress: false
sfc: false
vpn: true
diff --git a/config/deploy/os-odl-bgpvpn-noha.yaml b/config/deploy/os-odl-bgpvpn-noha.yaml
index 0435e6b5..4bf90aa7 100644
--- a/config/deploy/os-odl-bgpvpn-noha.yaml
+++ b/config/deploy/os-odl-bgpvpn-noha.yaml
@@ -3,9 +3,11 @@ global_params:
ha_enabled: false
deploy_options:
+ containers: true
+ os_version: master
sdn_controller: opendaylight
- odl_version: nitrogen
+ odl_version: master
tacker: false
- congress: true
+ congress: false
sfc: false
vpn: true
diff --git a/config/deploy/os-odl-bgpvpn_rocky-ha.yaml b/config/deploy/os-odl-bgpvpn_rocky-ha.yaml
new file mode 100644
index 00000000..a0833fd4
--- /dev/null
+++ b/config/deploy/os-odl-bgpvpn_rocky-ha.yaml
@@ -0,0 +1,13 @@
+---
+global_params:
+ ha_enabled: true
+
+deploy_options:
+ containers: true
+ os_version: rocky
+ sdn_controller: opendaylight
+ odl_version: master
+ tacker: false
+ congress: false
+ sfc: false
+ vpn: true
diff --git a/config/deploy/os-odl-bgpvpn_rocky-noha.yaml b/config/deploy/os-odl-bgpvpn_rocky-noha.yaml
new file mode 100644
index 00000000..6bc5adf3
--- /dev/null
+++ b/config/deploy/os-odl-bgpvpn_rocky-noha.yaml
@@ -0,0 +1,13 @@
+---
+global_params:
+ ha_enabled: false
+
+deploy_options:
+ containers: true
+ os_version: rocky
+ sdn_controller: opendaylight
+ odl_version: master
+ tacker: false
+ congress: false
+ sfc: false
+ vpn: true
diff --git a/config/deploy/os-odl-nofeature-ha.yaml b/config/deploy/os-odl-nofeature-ha.yaml
index 313cb1f4..748da3c7 100644
--- a/config/deploy/os-odl-nofeature-ha.yaml
+++ b/config/deploy/os-odl-nofeature-ha.yaml
@@ -1,10 +1,7 @@
---
global_params:
ha_enabled: true
- patches:
- undercloud:
- - change-id: Ib8ff69a4bc869de21ad838b3bc6c38a8676036c6
- project: openstack/tripleo-heat-templates
+
deploy_options:
containers: true
os_version: master
diff --git a/config/deploy/os-odl-nofeature-noha.yaml b/config/deploy/os-odl-nofeature-noha.yaml
index e2b34642..0767822b 100644
--- a/config/deploy/os-odl-nofeature-noha.yaml
+++ b/config/deploy/os-odl-nofeature-noha.yaml
@@ -1,10 +1,6 @@
---
global_params:
ha_enabled: false
- patches:
- undercloud:
- - change-id: Ib8ff69a4bc869de21ad838b3bc6c38a8676036c6
- project: openstack/tripleo-heat-templates
deploy_options:
containers: true
diff --git a/config/deploy/os-odl-queens-ha.yaml b/config/deploy/os-odl-queens-ha.yaml
index 62a12d2b..9738be38 100644
--- a/config/deploy/os-odl-queens-ha.yaml
+++ b/config/deploy/os-odl-queens-ha.yaml
@@ -1,6 +1,7 @@
---
global_params:
ha_enabled: true
+
deploy_options:
containers: true
os_version: queens
diff --git a/config/deploy/os-odl-queens-noha.yaml b/config/deploy/os-odl-queens-noha.yaml
index 75a7346c..0500eec1 100644
--- a/config/deploy/os-odl-queens-noha.yaml
+++ b/config/deploy/os-odl-queens-noha.yaml
@@ -1,10 +1,7 @@
---
global_params:
ha_enabled: false
- patches:
- undercloud:
- - change-id: Ie380cc41ca50a294a2647d673f339d02111bf6b3
- project: openstack/tripleo-heat-templates
+
deploy_options:
containers: true
os_version: queens
diff --git a/config/deploy/os-odl-rocky-ha.yaml b/config/deploy/os-odl-rocky-ha.yaml
new file mode 100644
index 00000000..8728bd8d
--- /dev/null
+++ b/config/deploy/os-odl-rocky-ha.yaml
@@ -0,0 +1,13 @@
+---
+global_params:
+ ha_enabled: true
+
+deploy_options:
+ containers: true
+ os_version: rocky
+ sdn_controller: opendaylight
+ odl_version: oxygen
+ tacker: false
+ congress: false
+ sfc: false
+ vpn: false
diff --git a/config/deploy/os-odl-rocky-noha.yaml b/config/deploy/os-odl-rocky-noha.yaml
new file mode 100644
index 00000000..f6ceb81b
--- /dev/null
+++ b/config/deploy/os-odl-rocky-noha.yaml
@@ -0,0 +1,13 @@
+---
+global_params:
+ ha_enabled: false
+
+deploy_options:
+ containers: true
+ os_version: rocky
+ sdn_controller: opendaylight
+ odl_version: oxygen
+ tacker: false
+ congress: false
+ sfc: false
+ vpn: false
diff --git a/config/deploy/os-odl-sfc-ha.yaml b/config/deploy/os-odl-sfc-ha.yaml
index 3a87bfe3..e8df1170 100644
--- a/config/deploy/os-odl-sfc-ha.yaml
+++ b/config/deploy/os-odl-sfc-ha.yaml
@@ -3,9 +3,11 @@ global_params:
ha_enabled: true
deploy_options:
+ containers: true
+ os_version: master
sdn_controller: opendaylight
- odl_version: nitrogen
- tacker: true
- congress: true
+ odl_version: master
+ tacker: false
+ congress: false
sfc: true
vpn: false
diff --git a/config/deploy/os-odl-sfc-noha.yaml b/config/deploy/os-odl-sfc-noha.yaml
index 2b08af6c..3dac36fa 100644
--- a/config/deploy/os-odl-sfc-noha.yaml
+++ b/config/deploy/os-odl-sfc-noha.yaml
@@ -3,9 +3,11 @@ global_params:
ha_enabled: false
deploy_options:
+ containers: true
+ os_version: master
sdn_controller: opendaylight
- odl_version: nitrogen
- tacker: true
- congress: true
+ odl_version: master
+ tacker: false
+ congress: false
sfc: true
vpn: false
diff --git a/config/deploy/os-odl-sfc_rocky-ha.yaml b/config/deploy/os-odl-sfc_rocky-ha.yaml
new file mode 100644
index 00000000..3a1b6c93
--- /dev/null
+++ b/config/deploy/os-odl-sfc_rocky-ha.yaml
@@ -0,0 +1,13 @@
+---
+global_params:
+ ha_enabled: true
+
+deploy_options:
+ containers: true
+ os_version: rocky
+ sdn_controller: opendaylight
+ odl_version: master
+ tacker: false
+ congress: false
+ sfc: true
+ vpn: false
diff --git a/config/deploy/os-odl-sfc_rocky-noha.yaml b/config/deploy/os-odl-sfc_rocky-noha.yaml
new file mode 100644
index 00000000..8af873a5
--- /dev/null
+++ b/config/deploy/os-odl-sfc_rocky-noha.yaml
@@ -0,0 +1,13 @@
+---
+global_params:
+ ha_enabled: false
+
+deploy_options:
+ containers: true
+ os_version: rocky
+ sdn_controller: opendaylight
+ odl_version: master
+ tacker: false
+ congress: false
+ sfc: true
+ vpn: false
diff --git a/config/deploy/os-ovn-nofeature-ha.yaml b/config/deploy/os-ovn-nofeature-ha.yaml
new file mode 100644
index 00000000..6c42cad9
--- /dev/null
+++ b/config/deploy/os-ovn-nofeature-ha.yaml
@@ -0,0 +1,15 @@
+---
+global_params:
+ ha_enabled: true
+ patches:
+ undercloud:
+ - change-id: Ic08ff58b10d4fa7116163be1f7fce57879cee8c5
+ project: openstack/tripleo-common
+
+deploy_options:
+ containers: true
+ sdn_controller: ovn
+ tacker: false
+ congress: false
+ sfc: false
+ vpn: false
diff --git a/config/deploy/os-ovn-rocky-ha.yaml b/config/deploy/os-ovn-rocky-ha.yaml
new file mode 100644
index 00000000..a2c5a865
--- /dev/null
+++ b/config/deploy/os-ovn-rocky-ha.yaml
@@ -0,0 +1,17 @@
+---
+global_params:
+ ha_enabled: true
+ patches:
+ undercloud:
+ - change-id: Ic08ff58b10d4fa7116163be1f7fce57879cee8c5
+ project: openstack/tripleo-common
+ branch: master
+
+deploy_options:
+ containers: true
+ os_version: rocky
+ sdn_controller: ovn
+ tacker: false
+ congress: false
+ sfc: false
+ vpn: false
diff --git a/config/network/network_settings.yaml b/config/network/network_settings.yaml
index a8ddca1a..fee6b500 100644
--- a/config/network/network_settings.yaml
+++ b/config/network/network_settings.yaml
@@ -116,6 +116,12 @@ networks:
mtu: 1500
# Tenant network Overlay segmentation ID range:
# VNI, VLAN-ID, etc.
+ # VLAN config should follow the pattern of neutron ml2 network_vlan_ranges
+ # allowed patterns are <physical_network> or
+ # <physical_network>:<vlan_min>:<vlan_max>
+ # Note that for VLAN config, physnet 'datacentre:1:1000' is used for
+ # external networks by default and will be automatically added to
+ # Neutron config if the range specified here does not include datacentre.
overlay_id_range: 2,65535
# Tenant network segmentation type:
@@ -180,7 +186,7 @@ networks:
nic_mapping:
# Mapping for compute profile (nodes assigned as Compute nodes)
compute:
- # Physical interface type (interface or bond)
+ # Physical interface type (ovs_bridge, interface or bond)
# Note that this phys_type for external network will be changed
# to vpp_interface for odl_fdio scenarios and linux_bridge for
# nosdn_fdio scenarios.
diff --git a/config/network/network_settings_csit.yaml b/config/network/network_settings_csit.yaml
index 8eec0f65..75271140 100644
--- a/config/network/network_settings_csit.yaml
+++ b/config/network/network_settings_csit.yaml
@@ -116,6 +116,12 @@ networks:
mtu: 1500
# Tenant network Overlay segmentation ID range:
# VNI, VLAN-ID, etc.
+ # VLAN config should follow the pattern of neutron ml2 network_vlan_ranges
+ # allowed patterns are <physical_network> or
+ # <physical_network>:<vlan_min>:<vlan_max>
+ # Note that for VLAN config, physnet 'datacentre:1:1000' is used for
+ # external networks by default and will be automatically added to
+ # Neutron config if the range specified here does not include datacentre.
overlay_id_range: 2,65535
# Tenant network segmentation type:
diff --git a/config/network/network_settings_tenant_vlan.yaml b/config/network/network_settings_tenant_vlan.yaml
new file mode 100644
index 00000000..e1f009fa
--- /dev/null
+++ b/config/network/network_settings_tenant_vlan.yaml
@@ -0,0 +1,333 @@
+---
+# This configuration file defines Network Environment for a
+# Baremetal Deployment of OPNFV. It contains default values
+# for 5 following networks:
+#
+# - admin
+# - tenant*
+# - external*
+# - storage*
+# - api*
+# *) optional networks
+#
+# Optional networks will be consolidated with the admin network
+# if not explicitly configured.
+#
+# See short description of the networks in the comments below.
+#
+# "admin" is the short name for Control Plane Network.
+# This network should be IPv4 even it is an IPv6 deployment
+# IPv6 does not have PXE boot support.
+# During OPNFV deployment it is used for node provisioning which will require
+# PXE booting as well as running a DHCP server on this network. Be sure to
+# disable any other DHCP/TFTP server on this network.
+#
+# "tenant" is the network used for tenant traffic.
+#
+# "external" is the network which should have internet or external
+# connectivity. External OpenStack networks will be configured to egress this
+# network. There can be multiple external networks, but only one assigned as
+# "public" which OpenStack public API's will register.
+#
+# "storage" is the network for storage I/O.
+#
+# "api" is an optional network for splitting out OpenStack service API
+# communication. This should be used for IPv6 deployments.
+
+
+# Meta data for the network configuration
+network-config-metadata:
+ title: LF-POD-1 Network config
+ version: 0.1
+ created: Mon Dec 28 2015
+ comment: None
+
+# DNS Settings
+dns-domain: opnfvlf.org
+dns-search: opnfvlf.org
+dns_nameservers:
+ - 8.8.8.8
+ - 8.8.4.4
+# NTP servers
+ntp:
+ - 0.se.pool.ntp.org
+ - 1.se.pool.ntp.org
+# Syslog server
+syslog:
+ server: 10.128.1.24
+ transport: 'tcp'
+
+# http(s) proxy settings added to /etc/environment of uc and oc nodes
+# http_proxy: http://proxy.server:8080
+# https_proxy: https://proxy.server:8081
+
+# Common network settings
+networks:
+ # Admin configuration (pxe and jumpstart)
+ admin:
+ enabled: true
+ # Network settings for the Installer VM on admin network
+ installer_vm:
+ # Indicates if this VM will be bridged to an interface, or to a bond
+ nic_type: interface
+ # Interfaces to bridge for installer VM (use multiple values for bond)
+ members:
+ - em1
+ # VLAN tag to use for this network on Installer VM, native means none
+ vlan: native
+ # IP to assign to Installer VM on this network
+ ip: 192.0.2.1
+ # Usable ip range for the overcloud node IPs (including VIPs)
+ # Last IP is used for host bridge (i.e. br-admin).
+ # If empty entire range is usable.
+ # Cannot overlap with dhcp_range or introspection_range.
+ overcloud_ip_range:
+ - 192.0.2.51
+ - 192.0.2.99
+ # Gateway (only needed when public_network is disabled)
+ gateway: 192.0.2.1
+ # Subnet in CIDR format 192.168.1.0/24
+ cidr: 192.0.2.0/24
+ # DHCP range for the admin network, automatically provisioned if empty
+ dhcp_range:
+ - 192.0.2.2
+ - 192.0.2.50
+ # Mapping of network configuration for Overcloud Nodes
+ nic_mapping:
+ # Mapping for compute profile (nodes assigned as Compute nodes)
+ compute:
+ # Physical interface type (interface or bond)
+ phys_type: interface
+ # Physical NIC members (Single value allowed for phys_type: interface)
+ members:
+ - eth0
+ # Mapping for controller profile (nodes assigned as Controller nodes)
+ controller:
+ phys_type: interface
+ members:
+ - eth0
+
+ # Tenant network configuration
+ tenant:
+ enabled: true
+ # Subnet in CIDR format 192.168.1.0/24
+ cidr: 11.0.0.0/24
+ # Tenant network MTU
+ mtu: 1500
+ # Tenant network Overlay segmentation ID range:
+ # VNI, VLAN-ID, etc.
+ # VLAN config should follow the pattern of neutron ml2 network_vlan_ranges
+ # allowed patterns are <physical_network> or
+ # <physical_network>:<vlan_min>:<vlan_max>
+ # Note that for VLAN config, physnet 'datacentre:1:1000' is used for
+ # external networks by default and will be automatically added to
+ # Neutron config if the range specified here does not include datacentre.
+ overlay_id_range: vlan:500:525
+
+ # Tenant network segmentation type:
+ # vlan, vxlan, gre
+ segmentation_type: vlan
+ # Mapping of network configuration for Overcloud Nodes
+ nic_mapping:
+ # Mapping for compute profile (nodes assigned as Compute nodes)
+ compute:
+ # Physical interface type (interface/bond)
+ phys_type: interface
+ # UIO driver to use for DPDK scenarios.
+ # The value is ignored for non-DPDK scenarios.
+ uio_driver: uio_pci_generic
+ # VLAN tag to use with this NIC
+ vlan: native
+ # Physical NIC members of this mapping
+ # Single value allowed for phys_type: interface
+ members:
+ # Note logical name like nic1 not valid for fdio deployment yet.
+ - eth1
+ # Mapping for controller profile (nodes assigned as Controller nodes)
+ controller:
+ # Physical interface type (interface/bond)
+ phys_type: interface
+ vlan: native
+ # Note: logicial names like nic1 are not valid for fdio deployment yet.
+ members:
+ - eth1
+
+ # Can contain 1 or more external networks
+ external:
+ - public:
+ enabled: true
+ # Public network MTU
+ mtu: 1500
+ # Network settings for the Installer VM on external network
+ # (note only valid on 'public' external network)
+ installer_vm:
+ # Indicates if this VM will be bridged to an interface, or to a bond
+ nic_type: interface
+ vlan: native
+ # Interfaces to bridge for installer VM (use multiple values for bond)
+ members:
+ - em1
+ # IP to assign to Installer VM on this network
+ ip: 192.168.37.1
+ cidr: 192.168.37.0/24
+ gateway: 192.168.37.1
+ # Range to allocate to floating IPs for the public network with Neutron
+ floating_ip_range:
+ - 192.168.37.200
+ - 192.168.37.220
+ # Usable ip range for the overcloud node IPs (including VIPs)
+ # Last IP will be used for host bridge (i.e. br-public).
+ # If empty entire range is usable.
+ # Cannot overlap with dhcp_range or introspection_range.
+ overcloud_ip_range:
+ - 192.168.37.10
+ - 192.168.37.199
+ # Mapping of network configuration for Overcloud Nodes
+ nic_mapping:
+ # Mapping for compute profile (nodes assigned as Compute nodes)
+ compute:
+ # Physical interface type (interface or bond)
+ # Note that this phys_type for external network will be changed
+ # to vpp_interface for odl_fdio scenarios and linux_bridge for
+ # nosdn_fdio scenarios.
+ phys_type: ovs_bridge
+ # VLAN tag to use with this NIC
+ vlan: native
+ # Physical NIC members of this mapping
+ # Single value allowed for phys_type: interface
+ members:
+ - eth2
+ # Mapping for controller profile (nodes assigned as Controller nodes)
+ controller:
+ # Note that this phys_type for external network will be changed
+ # to vpp_interface for odl_fdio scenarios and linux_bridge for
+ # nosdn_fdio scenarios.
+ phys_type: ovs_bridge
+ vlan: native
+ members:
+ - eth2
+ # External network to be created in OpenStack by Services tenant
+ external_overlay:
+ name: Public_internet
+ type: flat
+ gateway: 192.168.37.1
+ # another external network
+ # This is an example and not yet supported
+ - private_cloud:
+ enabled: false
+ mtu: 1500
+ # Network settings for the Installer VM on external network
+ # note only valid on 'public' external network
+ installer_vm:
+ # Indicates if this VM will be bridged to an interface, or to a bond
+ nic_type: interface
+ vlan: 101
+ # Interfaces to bridge for installer VM (use multiple values for bond)
+ members:
+ - em1
+ # IP to assign to Installer VM on this network
+ ip: 192.168.38.1
+ cidr: 192.168.38.0/24
+ gateway: 192.168.38.1
+ # Range to allocate to floating IPs for the public network with Neutron
+ floating_ip_range:
+ - 192.168.38.200
+ - 192.168.38.220
+ # Usable IP range for overcloud nodes (including VIPs)i
+ # usually this is a shared subnet.
+ # Cannot overlap with dhcp_range or introspection_range.
+ overcloud_ip_range:
+ - 192.168.38.10
+ - 192.168.38.199
+ # Mapping of network configuration for Overcloud Nodes
+ nic_mapping:
+ # Mapping for compute profile (nodes assigned as Compute nodes)
+ compute:
+ # Physical interface type (interface or bond)
+ phys_type: interface
+ # VLAN tag to use with this NIC
+ vlan: 101
+ # Physical NIC members of this mappingi
+ # Single value allowed for phys_type: interface
+ # Note: logical names like nic1 are not valid for fdio deployment yet.
+ members:
+ - eth3
+ # Mapping for controller profile (nodes assigned as Controller nodes)
+ controller:
+ phys_type: interface
+ vlan: 101
+ members:
+ - eth3
+ # External network to be created in OpenStack by Services tenant
+ external_overlay:
+ name: private_cloud
+ type: vlan
+ segmentation_id: 101
+ gateway: 192.168.38.1
+
+ # Storage network configuration
+ storage:
+ enabled: true
+ # Subnet in CIDR format
+ cidr: 12.0.0.0/24
+ # Storage network MTU
+ mtu: 1500
+ # Mapping of network configuration for Overcloud Nodes
+ nic_mapping:
+ # Mapping for compute profile (nodes assigned as Compute nodes)
+ compute:
+ # Physical interface type (interface or bond)
+ phys_type: interface
+ # VLAN tag to use with this NIC
+ vlan: native
+ # Physical NIC members of this mapping
+ # Single value allowed for phys_type: interface
+ members:
+ # Note logical names like nic1 not valid for fdio deployment yet.
+ - eth3
+ # Mapping for controller profile (nodes assigned as Controller nodes)
+ controller:
+ phys_type: interface
+ vlan: native
+ members:
+ - eth3
+
+ api:
+ # API network configuration
+ enabled: false
+ # Subnet in CIDR format
+ cidr: fd00:fd00:fd00:4000::/64
+ # VLAN tag to use for Overcloud hosts on this network
+ vlan: 13
+ # Api network MTU
+ mtu: 1500
+ # Mapping of network configuration for Overcloud Nodes
+ nic_mapping:
+ # Mapping for compute profile (nodes assigned as Compute nodes)
+ compute:
+ # Physical interface type (interface or bond)
+ phys_type: interface
+ # VLAN tag to use with this NIC
+ vlan: native
+ # Physical NIC members of this mapping
+ # Single value allowed for phys_type: interface
+ # Note logical names like nic1 not valid for fdio deployment yet.
+ members:
+ - eth4
+ # Mapping for controller profile (nodes assigned as Controller nodes)
+ controller:
+ phys_type: interface
+ vlan: native
+ members:
+ - eth4
+
+# Apex specific settings
+apex:
+ networks:
+ admin:
+ # Range used for introspection phase (examining nodes).
+ # This cannot overlap with dhcp_range or overcloud_ip_range.
+ # for the overcloud default external network
+ introspection_range:
+ - 192.0.2.100
+ - 192.0.2.120
diff --git a/config/network/network_settings_v6.yaml b/config/network/network_settings_v6.yaml
index 176bc7ca..71b0b272 100644
--- a/config/network/network_settings_v6.yaml
+++ b/config/network/network_settings_v6.yaml
@@ -116,6 +116,12 @@ networks:
mtu: 1500
# Tenant network Overlay segmentation ID range:
# VNI, VLAN-ID, etc.
+ # VLAN config should follow the pattern of neutron ml2 network_vlan_ranges
+ # allowed patterns are <physical_network> or
+ # <physical_network>:<vlan_min>:<vlan_max>
+ # Note that for VLAN config, physnet 'datacentre:1:1000' is used for
+ # external networks by default and will be automatically added to
+ # Neutron config if the range specified here does not include datacentre.
overlay_id_range: 2,65535
# Tenant network segmentation type:
@@ -174,7 +180,7 @@ networks:
# Mapping for compute profile (nodes assigned as Compute nodes)
compute:
# Physical interface type (interface or bond)
- phys_type: interface
+ phys_type: ovs_bridge
# VLAN tag to use with this NIC
vlan: native
# Physical NIC members of this mapping
@@ -183,7 +189,7 @@ networks:
- nic3
# Mapping for controller profile (nodes assigned as Controller nodes)
controller:
- phys_type: interface
+ phys_type: ovs_bridge
vlan: native
members:
- nic3
diff --git a/contrib/aarch64/overcloud-full-rootfs.yaml b/contrib/aarch64/overcloud-full-rootfs.yaml
new file mode 100644
index 00000000..ad420427
--- /dev/null
+++ b/contrib/aarch64/overcloud-full-rootfs.yaml
@@ -0,0 +1,54 @@
+disk_images:
+ -
+ imagename: overcloud-full-rootfs
+ arch: aarch64
+ type: qcow2
+ distro: centos7
+ elements:
+ - baremetal
+ - dhcp-all-interfaces
+ - cloud-init
+ - openvswitch
+ - overcloud-agent
+ - overcloud-full
+ - overcloud-controller
+ - overcloud-compute
+ - overcloud-ceph-storage
+ - puppet-modules
+ - enable-serial-console
+ - stable-interface-names
+ - selinux-permissive
+ - grub2
+ - growroot
+ - devuser
+ - element-manifest
+ - dynamic-login
+ - iptables
+ - enable-packages-install
+ - pip-and-virtualenv-override
+ - dracut-regenerate
+ - remove-machine-id
+ - remove-resolvconf
+ packages:
+ - openstack-utils
+ - python-tripleoclient
+ - python-tripleoclient-heat-installer
+ - python-psutil
+ - python-debtcollector
+ - plotnetcfg
+ - sos
+ - yum-plugin-priorities
+ - ntp
+ - jq
+ - openstack-heat-agents
+ - device-mapper-multipath
+ - os-net-config
+ - grub2-efi-aa64
+ - grub2-efi-aa64-modules
+ options:
+ - " --no-tmpfs"
+ environment:
+ DIB_PYTHON_VERSION: '2'
+ DIB_DEV_USER_USERNAME: 'stack'
+ DIB_DEV_USER_PASSWORD: 'stack'
+ DIB_DEV_USER_PWDLESS_SUDO: 'Yes'
diff --git a/contrib/aarch64/undercloud-full.yaml b/contrib/aarch64/undercloud-full.yaml
new file mode 100644
index 00000000..42084c89
--- /dev/null
+++ b/contrib/aarch64/undercloud-full.yaml
@@ -0,0 +1,87 @@
+disk_images:
+ -
+ imagename: undercloud-full
+ arch: aarch64
+ type: qcow2
+ distro: centos7
+ elements:
+ - vm
+ - block-device-efi
+ - baremetal
+ - dhcp-all-interfaces
+ - disable-selinux
+ - cloud-init-nocloud
+ - openvswitch
+ - overcloud-agent
+ - overcloud-full
+ - overcloud-controller
+ - overcloud-compute
+ - overcloud-ceph-storage
+ - puppet-modules
+ - enable-serial-console
+ - stable-interface-names
+ - grub2
+ - bootloader
+ - devuser
+ - element-manifest
+ - dynamic-login
+ - iptables
+ - enable-packages-install
+ - pip-and-virtualenv-override
+ - dracut-regenerate
+ - remove-machine-id
+ - remove-resolvconf
+ packages:
+ - openstack-utils
+ - python-tripleoclient
+ - python-tripleoclient-heat-installer
+ - python-psutil
+ - python-debtcollector
+ - plotnetcfg
+ - sos
+ - yum-plugin-priorities
+ - ntp
+ - jq
+ - openstack-heat-agents
+ - device-mapper-multipath
+ - os-net-config
+ options:
+ - " --no-tmpfs"
+ environment:
+ DIB_PYTHON_VERSION: '2'
+ DIB_DEV_USER_USERNAME: 'stack'
+ DIB_DEV_USER_PASSWORD: 'stack'
+ DIB_DEV_USER_PWDLESS_SUDO: 'Yes'
+ -
+ imagename: ironic-python-agent
+ # This is bogus, but there's no initrd type in diskimage-builder
+ arch: aarch64
+ type: qcow2
+ distro: centos7
+
+ # So we just override the extension instead
+ imageext: initramfs
+ elements:
+ - ironic-agent
+ - ironic-agent-multipath
+ - dynamic-login
+ - devuser
+ - disable-selinux
+ - element-manifest
+ - network-gateway
+ - enable-packages-install
+ - pip-and-virtualenv-override
+ packages:
+ - util-linux
+ - grub2-efi-aa64
+ - grub2-efi-aa64-module
+ - python-hardware-detect
+ - yum-plugin-priorities
+ - iscsi-initiator-utils
+ options:
+ - " --no-tmpfs"
+ environment:
+ DIB_PYTHON_VERSION: '2'
+ DIB_DEV_USER_USERNAME: 'stack'
+ DIB_DEV_USER_PASSWORD: 'stack'
+ DIB_DEV_USER_PWDLESS_SUDO: 'Yes'
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 00000000..eb12e74b
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1 @@
+from docs_conf.conf import * # noqa: F401,F403
diff --git a/docs/conf.yaml b/docs/conf.yaml
new file mode 100644
index 00000000..6c76e3c0
--- /dev/null
+++ b/docs/conf.yaml
@@ -0,0 +1,3 @@
+---
+project_cfg: opnfv
+project: APEX
diff --git a/docs/contributor/APEX-on-aarch64.rst b/docs/contributor/APEX-on-aarch64.rst
new file mode 100644
index 00000000..a2e90dd6
--- /dev/null
+++ b/docs/contributor/APEX-on-aarch64.rst
@@ -0,0 +1,146 @@
+==================================================================================
+APEX on AARCH64
+==================================================================================
+
+This document describes the changes needed to deploy OPNFV-APEX on aarch64
+ * General considerations
+ * Creating undercloud and overcloud images using DIB
+ * Creating Kolla containers
+
+General considerations
+--------------------------
+
+OPNFV - APEX relies on artifacts created by the OOO project.
+
+Those artifacts are:
+
+1. Openstack packages, found in delorean_.
+
+ .. _delorean: http://www.python.org/
+
+2. UC and OC images created by RDO and found in images_.
+
+ .. _images: https://images.rdoproject.org/master/rdo_trunk/current-tripleo-rdo-internal/
+
+3. The containerized version of the openstack services found in docker.io_.
+
+ .. _docker.io: https://hub.docker.com/r/tripleomaster/
+
+All the above artifacts are x86_64 only and as a result cannot be used by APEX on aarch64
+As a result the user needs to create the Images locally before attempting to deploy.
+The only supported scenario is 'os-nosdn-rocky-ha'.
+
+Other than the aarch64 disk images and containers, there is no other special configuration
+required for aarch64. The only requirement is for the nodes to be identified as aarch64 nodes
+in the inventory files.
+
+For example :
+
+.. code-block:: yaml
+
+ node1:
+ mac_address: "68:05:CA:68:08:CA"
+ ipmi_ip: 10.10.10.10
+ ipmi_user: user
+ ipmi_pass: pass
+ pm_type: "pxe_ipmitool"
+ cpus: 1
+ memory: 128000
+ disk: 480
+ disk_device: sda
+ arch: "aarch64"
+ capabilities: "profile:control"
+
+
+Creating undercloud and overcloud images using DIB
+--------------------------------------------------
+In order to create that image DIB_ must be used. DIB can either be built from source or use yum to be installed.
+
+.. _DIB: https://github.com/openstack/diskimage-builder
+
+It is important to use a fairly late version of DIB to support UEFI systems. The version currently on epel does NOT have support for UEFI. The version on delorean (15.01) works just fine. DIB uses a YAML file from the user which describes how the
+image should look like. The original yaml from RDO is here_:
+
+
+.. _here: https://github.com/openstack/tripleo-common/blob/master/image-yaml/overcloud-images.yaml
+
+The equivelant yaml files for aarch64 are included in the apex repo in the "apex/contrib/aarch64" folder.
+The UC and OC images are very similar in terms of packages. The major difference is the partition table in EFI so for the undercloud, that has to provided as an environmental variable.
+
+.. code-block:: python
+
+ export DIB_BLOCK_DEVICE_CONFIG="
+
+ - local_loop:
+ name: image0
+
+ - partitioning:
+ base: image0
+ label: gpt
+ partitions:
+ - name: ESP
+ type: 'EF00'
+ size: 64MiB
+ mkfs:
+ type: vfat
+ mount:
+ mount_point: /boot/efi
+ fstab:
+ options: "defaults"
+ fsck-passno: 1
+ - name: root
+ type: '8300'
+ size: 50GiB
+ mkfs:
+ type: ext4
+ mount:
+ mount_point: /
+ fstab:
+ options: "defaults"
+ fsck-passno: 1
+ "
+
+ export DIB_YUM_REPO_CONF+="/etc/yum.repos.d/delorean-deps-rocky.repo /etc/yum.repos.d/delorean-rocky.repo /etc/yum.repos.d
+ /epel.repo "
+ openstack --debug overcloud image build --config-file undercloud_full.yaml --output-directory ./
+
+
+The overcloud is built in a similar way.
+
+.. code-block:: python
+
+ export DIB_YUM_REPO_CONF+="/etc/yum.repos.d/delorean-deps-rocky.repo /etc/yum.repos.d/delorean-rocky.repo /etc/yum.repos.d
+ /epel.repo "
+ openstack --debug overcloud image build --config-file overcloud_full_rootfs.yaml --output-directory ./
+
+
+
+Apex container deployment
+-------------------------
+Similarly the containers provided by OOO are for x86 only. Containers for apex on aarch64 for the Rocky release can
+be found in armbandapex_.
+
+.. _armbandapex: https://registry.hub.docker.com/v2/repositories/armbandapex/
+
+A user who wishes to rebuild the containers can easily do so by sing Kolla. An example kolla.conf and the command to build the containers is given bellow.
+
+
+.. code-block:: python
+
+ [DEFAULT]
+
+ base=centos
+ type=binary
+ namespace="private docker.io repository"
+ tag=current-tripleo-rdo
+ rpm_setup_config=ceph.repo,epel.repo,delorean-deps.repo,delorean.repo
+ push=True
+
+
+
+.. code-block:: python
+
+ openstack overcloud container image build --config-file /usr/share/tripleo-common/container-images/overcloud_containers.yaml
+ --kolla-config-file /etc/kolla/kolla-build.conf
+
+
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 00000000..2fd1b4ab
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,23 @@
+.. _apex:
+
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. SPDX-License-Identifier CC-BY-4.0
+.. (c) Open Platform for NFV Project, Inc. and its contributors
+
+*********************************
+OPNFV Apex
+*********************************
+
+.. toctree::
+ :numbered:
+ :maxdepth: 3
+
+ release/scenarios/os-nosdn-nofeature-noha/index
+ release/scenarios/os-ovn-nofeature-ha/index
+ release/scenarios/os-nosdn-nofeature-ha/index
+ release/scenarios/os-odl-nofeature-noha/index
+ release/scenarios/os-odl-nofeature-ha/index
+ release/scenarios/k8s-nosdn-nofeature-noha/index
+ release/installation/index
+ release/release-notes/index
diff --git a/docs/release/installation/abstract.rst b/docs/release/installation/abstract.rst
index aeef1246..2d55c154 100644
--- a/docs/release/installation/abstract.rst
+++ b/docs/release/installation/abstract.rst
@@ -1,16 +1,16 @@
Abstract
========
-This document describes how to install the Fraser release of OPNFV when
+This document describes how to install the Gambia release of OPNFV when
using Apex as a deployment tool covering it's limitations, dependencies
and required system resources.
License
=======
-Fraser release of OPNFV when using Apex as a deployment tool Docs
+Gambia release of OPNFV when using Apex as a deployment tool Docs
(c) by Tim Rozet (Red Hat)
-Fraser release of OPNFV when using Apex as a deployment tool Docs
+Gambia release of OPNFV when using Apex as a deployment tool Docs
are licensed under a Creative Commons Attribution 4.0 International License.
You should have received a copy of the license along with this.
If not, see <http://creativecommons.org/licenses/by/4.0/>.
diff --git a/docs/release/installation/architecture.rst b/docs/release/installation/architecture.rst
index 1ab7c7fc..0bf2d3bc 100644
--- a/docs/release/installation/architecture.rst
+++ b/docs/release/installation/architecture.rst
@@ -16,8 +16,7 @@ deploy the overcloud.
The undercloud is the all-in-one installation of OpenStack that includes
baremetal provisioning capability. The undercloud will be deployed as a
-virtual machine on a Jump Host. This VM is pre-built and distributed as part
-of the Apex RPM.
+virtual machine on a Jump Host.
The overcloud is OPNFV. Configuration will be passed into undercloud and
the undercloud will use OpenStack's orchestration component, named Heat, to
@@ -127,11 +126,11 @@ issues per scenario. The following scenarios correspond to a supported
+-------------------------+-------------+---------------+
| os-nosdn-nofeature-noha | Apex | Yes |
+-------------------------+-------------+---------------+
-| os-nosdn-bar-ha | Barometer | Yes |
+| os-nosdn-bar-ha | Barometer | No |
+-------------------------+-------------+---------------+
-| os-nosdn-bar-noha | Barometer | Yes |
+| os-nosdn-bar-noha | Barometer | No |
+-------------------------+-------------+---------------+
-| os-nosdn-calipso-noha | Calipso | No |
+| os-nosdn-calipso-noha | Calipso | Yes |
+-------------------------+-------------+---------------+
| os-nosdn-ovs_dpdk-ha | Apex | No |
+-------------------------+-------------+---------------+
@@ -168,9 +167,9 @@ issues per scenario. The following scenarios correspond to a supported
+-------------------------+-------------+---------------+
| os-odl-l2gw-noha | Apex | No |
+-------------------------+-------------+---------------+
-| os-odl-sfc-ha | SFC | No |
+| os-odl-sfc-ha | SFC | Yes |
+-------------------------+-------------+---------------+
-| os-odl-sfc-noha | SFC | No |
+| os-odl-sfc-noha | SFC | Yes |
+-------------------------+-------------+---------------+
| os-odl-gluon-noha | Gluon | No |
+-------------------------+-------------+---------------+
@@ -188,5 +187,7 @@ issues per scenario. The following scenarios correspond to a supported
+-------------------------+-------------+---------------+
| os-onos-sfc-ha | ONOSFW | No |
+-------------------------+-------------+---------------+
-| os-ovn-nofeature-noha | Apex | Yes |
+| os-ovn-nofeature-noha | Apex | No |
++-------------------------+-------------+---------------+
+| os-ovn-nofeature-ha | Apex | Yes |
+-------------------------+-------------+---------------+
diff --git a/docs/release/installation/baremetal.rst b/docs/release/installation/baremetal.rst
index d8f90792..efea0f86 100644
--- a/docs/release/installation/baremetal.rst
+++ b/docs/release/installation/baremetal.rst
@@ -46,11 +46,17 @@ and report the properties of it back to the undercloud node.
After introspection the undercloud will execute a Heat Stack Deployment to
continue node provisioning and configuration. The nodes will reboot and PXE
from the undercloud PXE server again to provision each node using Glance disk
-images provided by the undercloud. These disk images include all the necessary
-packages and configuration for an OPNFV deployment to execute. Once the disk
+images provided by the undercloud. These disk images include all the necessary
+packages and configuration for an OPNFV deployment to execute. Once the disk
images have been written to node's disks the nodes will boot locally and
-execute cloud-init which will execute the final node configuration. This
-configuration is largely completed by executing a puppet apply on each node.
+execute cloud-init which will execute the final node configuration. At this
+point in the deployment, the Heat Stack will complete, and Mistral will
+takeover the configuration of the nodes. Mistral handles calling Ansible which
+will connect to each node, and begin configuration. This configuration includes
+launching the desired OPNFV services as containers, and generating their
+configuration files. These configuration is largely completed by executing a
+puppet apply on each container to generate the config files, which are then
+stored on the overcloud host and mounted into the service container at runtime.
Installation Guide - Bare Metal Deployment
==========================================
@@ -62,11 +68,7 @@ Install Bare Metal Jump Host
----------------------------
1a. If your Jump Host does not have CentOS 7 already on it, or you would like
- to do a fresh install, then download the Apex bootable ISO from the OPNFV
- artifacts site <http://artifacts.opnfv.org/apex.html>. There have been
- isolated reports of problems with the ISO having trouble completing
- installation successfully. In the unexpected event the ISO does not work
- please workaround this by downloading the CentOS 7 DVD and performing a
+ to do a fresh install, then download the CentOS 7 DVD and perform a
"Virtualization Host" install. If you perform a "Minimal Install" or
install type other than "Virtualization Host" simply run
``sudo yum -y groupinstall "Virtualization Host"``
@@ -84,11 +86,11 @@ Install Bare Metal Jump Host
Replace /dev/sdX with the device assigned to your usb drive. Then select
the USB device as the boot media on your Jump Host
-2a. When not using the OPNFV Apex ISO, install these repos:
+2a. Install these repos:
- ``sudo yum install https://repos.fedorapeople.org/repos/openstack/openstack-pike/rdo-release-pike-1.noarch.rpm``
+ ``sudo yum install https://repos.fedorapeople.org/repos/openstack/openstack-queens/rdo-release-queens-1.noarch.rpm``
``sudo yum install epel-release``
- ``sudo curl -o /etc/yum.repos.d/opnfv-apex.repo http://artifacts.opnfv.org/apex/fraser/opnfv-apex.repo``
+ ``sudo curl -o /etc/yum.repos.d/opnfv-apex.repo http://artifacts.opnfv.org/apex/gambia/opnfv-apex.repo``
The RDO Project release repository is needed to install OpenVSwitch, which
is a dependency of opnfv-apex. If you do not have external connectivity to
@@ -97,14 +99,12 @@ Install Bare Metal Jump Host
opnfv-apex repo hosts all of the Apex dependencies which will automatically
be installed when installing RPMs, but will be pre-installed with the ISO.
-2b. If you chose not to use the Apex ISO, then you must download and install
- the Apex RPMs to the Jump Host. Download the first 3 Apex RPMs from the
- OPNFV downloads page, under the TripleO RPMs
- ``https://www.opnfv.org/software/downloads``.
+2b. Download the first Apex RPMs from the OPNFV downloads page, under the
+ TripleO RPMs ``https://www.opnfv.org/software/downloads``. The dependent
+ RPMs will be automatically installed from the opnfv-apex repo in the
+ previous step.
The following RPMs are available for installation:
- - opnfv-apex - OpenDaylight, OVN, and nosdn support
- - opnfv-apex-undercloud - (reqed) Undercloud Image
- python34-opnfv-apex - (reqed) OPNFV Apex Python package
- python34-markupsafe - (reqed) Dependency of python34-opnfv-apex **
- python34-jinja2 - (reqed) Dependency of python34-opnfv-apex **
@@ -123,9 +123,9 @@ Install Bare Metal Jump Host
automatically installed by installing python34-opnfv-apex when the
opnfv-apex.repo has been previously downloaded to ``/etc/yum.repos.d/``.
- Install the three required RPMs (replace <rpm> with the actual downloaded
+ Install the required RPM (replace <rpm> with the actual downloaded
artifact):
- ``yum -y install <opnfv-apex.rpm> <opnfv-apex-undercloud> <python34-opnfv-apex>``
+ ``yum -y install <python34-opnfv-apex>``
3. After the operating system and the opnfv-apex RPMs are installed, login to
your Jump Host as root.
@@ -150,9 +150,13 @@ IPMI configuration information gathered in section
template to ``/etc/opnfv-apex/inventory.yaml``.
2. The nodes dictionary contains a definition block for each baremetal host
- that will be deployed. 1 or more compute nodes and 3 controller nodes are
- required. (The example file contains blocks for each of these already).
+ that will be deployed. 0 or more compute nodes and 1 or 3 controller nodes
+ are required (the example file contains blocks for each of these already).
It is optional at this point to add more compute nodes into the node list.
+ By specifying 0 compute nodes in the inventory file, the deployment will
+ automatically deploy "all-in-one" nodes which means the compute will run
+ along side the controller in a single overcloud node. Specifying 3 control
+ nodes will result in a highly-available service model.
3. Edit the following values for each node:
diff --git a/docs/release/installation/index.rst b/docs/release/installation/index.rst
index 82b9d25c..443aef6a 100644
--- a/docs/release/installation/index.rst
+++ b/docs/release/installation/index.rst
@@ -23,7 +23,7 @@ Contents:
:Authors: Tim Rozet (trozet@redhat.com)
:Authors: Dan Radez (dradez@redhat.com)
-:Version: 6.0
+:Version: 7.1
Indices and tables
==================
diff --git a/docs/release/installation/introduction.rst b/docs/release/installation/introduction.rst
index 8dbf8f2f..706e2265 100644
--- a/docs/release/installation/introduction.rst
+++ b/docs/release/installation/introduction.rst
@@ -1,7 +1,7 @@
Introduction
============
-This document describes the steps to install an OPNFV Fraser reference
+This document describes the steps to install an OPNFV Gambia reference
platform using the Apex installer.
The audience is assumed to have a good background in networking
@@ -12,31 +12,22 @@ Preface
Apex uses Triple-O from the RDO Project OpenStack distribution as a
provisioning tool. The Triple-O image based life cycle installation
-tool provisions an OPNFV Target System (3 controllers, 2 or more
+tool provisions an OPNFV Target System (1 or 3 controllers, 0 or more
compute nodes) with OPNFV specific configuration provided by the Apex
deployment tool chain.
The Apex deployment artifacts contain the necessary tools to deploy and
configure an OPNFV target system using the Apex deployment toolchain.
-These artifacts offer the choice of using the Apex bootable ISO
-(``opnfv-apex-fraser.iso``) to both install CentOS 7 and the
-necessary materials to deploy or the Apex RPMs (``opnfv-apex*.rpm``),
-and their associated dependencies, which expects installation to a
-CentOS 7 libvirt enabled host. The RPM contains a collection of
-configuration files, prebuilt disk images, and the automatic deployment
-script (``opnfv-deploy``).
+The Apex artifact is a python package capable of automating the installation of
+TripleO and other OPNFV components.
-An OPNFV install requires a "Jump Host" in order to operate. The bootable
-ISO will allow you to install a customized CentOS 7 release to the Jump Host,
+An OPNFV install requires a "Jump Host" in order to operate. It is required
+to install CentOS 7 release to the Jump Host for traditional deployment,
which includes the required packages needed to run ``opnfv-deploy``.
If you already have a Jump Host with CentOS 7 installed, you may choose to
-skip the ISO step and simply install the (``opnfv-apex*.rpm``) RPMs. The RPMs
-are the same RPMs included in the ISO and include all the necessary disk
-images and configuration files to execute an OPNFV deployment. Either method
-will prepare a host to the same ready state for OPNFV deployment.
+skip the ISO step and simply install the (``python34-opnfv-apex*.rpm``) RPM.
``opnfv-deploy`` instantiates a Triple-O Undercloud VM server using libvirt
as its provider. This VM is then configured and used to provision the
-OPNFV target deployment (3 controllers, n compute nodes). These nodes can
-be either virtual or bare metal. This guide contains instructions for
-installing either method.
+OPNFV target deployment. These nodes can be either virtual or bare metal.
+This guide contains instructions for installing either method.
diff --git a/docs/release/installation/references.rst b/docs/release/installation/references.rst
index 935be038..b8b177d6 100644
--- a/docs/release/installation/references.rst
+++ b/docs/release/installation/references.rst
@@ -21,7 +21,7 @@ OPNFV
OpenStack
---------
-`OpenStack Pike Release artifacts <http://www.openstack.org/software/pike>`_
+`OpenStack Queens Release artifacts <http://www.openstack.org/software/queens>`_
`OpenStack documentation <http://docs.openstack.org>`_
diff --git a/docs/release/installation/requirements.rst b/docs/release/installation/requirements.rst
index 9aefa21d..239db197 100644
--- a/docs/release/installation/requirements.rst
+++ b/docs/release/installation/requirements.rst
@@ -6,7 +6,7 @@ Jump Host Requirements
The Jump Host requirements are outlined below:
-1. CentOS 7 (from ISO or self-installed).
+1. CentOS 7 (self-installed) or Fedora (with Snapshot deployment).
2. Root access.
@@ -15,7 +15,7 @@ The Jump Host requirements are outlined below:
4. minimum 1 networks and maximum 5 networks, multiple NIC and/or VLAN
combinations are supported. This is virtualized for a VM deployment.
-5. The Fraser Apex RPMs and their dependencies.
+5. The Gambia Apex RPM and its dependencies.
6. 16 GB of RAM for a bare metal deployment, 64 GB of RAM for a Virtual
Deployment.
diff --git a/docs/release/installation/upstream.rst b/docs/release/installation/upstream.rst
index b98b0c19..f18c4b11 100644
--- a/docs/release/installation/upstream.rst
+++ b/docs/release/installation/upstream.rst
@@ -1,14 +1,11 @@
-Deploying Directly from Upstream - (Beta)
-=========================================
+Deploying Directly from Upstream
+================================
-In addition to deploying with OPNFV tested artifacts included in the
-opnfv-apex-undercloud and opnfv-apex RPMs, it is now possible to deploy
+When installing the Undercloud and Overcloud, the disk images are now downloaded
directly from upstream artifacts. Essentially this deployment pulls the latest
RDO overcloud and undercloud artifacts at deploy time. This option is useful
-for being able to deploy newer versions of OpenStack that are not included
-with this release, and offers some significant advantages for some users.
-Please note this feature is currently in beta for the Fraser release and will
-be fully supported in the next OPNFV release.
+for being able to pull the latest Queens and other OPNFV components which have
+been promoted via a TripleO pipeline and deemed to be stable.
Upstream Deployment Key Features
--------------------------------
@@ -39,19 +36,15 @@ in order to download and prepare the cached artifacts.
Scenarios and Deploy Settings for Upstream Deployments
------------------------------------------------------
-Some deploy settings files are already provided which have been tested by the
-Apex team. These include (under /etc/opnfv-apex/):
-
- - os-nosdn-queens_upstream-noha.yaml
- - os-nosdn-master_upstream-noha.yaml
- - os-odl-queens_upstream-noha.yaml
- - os-odl-master_upstream-noha.yaml
-
-Each of these scenarios has been tested by Apex over the Fraser release, but
-none are guaranteed to work as upstream is a moving target and this feature is
-relatively new. Still it is the goal of the Apex team to provide support
-and move to an upstream based deployments in the future, so please file a bug
-when encountering any issues.
+The deploy settings and scenarios included with the Gambia release of Apex will
+be supported as deemed by the `OPNFV Scenarios in Apex`_ section of this guide.
+Each of these scenarios has been tested by Apex over the Gambia release, and
+using those deploy settings will control which upstream artifacts are pulled
+at deploy time. By specifying different versions of OpenStack, ODL, or other
+components in the deploy settings, different upstream artifacts may be downloaded
+and are not considered to be supported. For deploying newer versions of components
+it is advised to use the master branch of OPNFV Apex as part of our continuous
+integration effort to support those components.
Including Upstream Patches with Deployment
------------------------------------------------------
@@ -83,8 +76,7 @@ Running ``opnfv-deploy``
Deploying is similar to the typical method used for baremetal and virtual
deployments with the addition of a few new arguments to the ``opnfv-deploy``
-command. In order to use an upstream deployment, please use the ``--upstream``
-argument. Also, the artifacts for each upstream deployment are only
+command. The artifacts for each upstream deployment are only
downloaded when a newer version is detected upstream. In order to explicitly
disable downloading new artifacts from upstream if previous artifacts are
already cached, please use the ``--no-fetch`` argument.
@@ -105,3 +97,5 @@ container with a bash shell. Note the containers do not use systemd, unlike
the traditional deployment model and are instead started as the first process
in the container. To restart a service, use the ``docker restart <container>``
command.
+
+.. _`OPNFV Scenarios in Apex`: architecture.html#opnfv-scenarios-in-apex
diff --git a/docs/release/installation/virtual.rst b/docs/release/installation/virtual.rst
index af8aece2..a844d43f 100644
--- a/docs/release/installation/virtual.rst
+++ b/docs/release/installation/virtual.rst
@@ -3,20 +3,36 @@ Installation High-Level Overview - Virtual Deployment
Deploying virtually is an alternative deployment method to bare metal, where
only a single bare metal Jump Host server is required to execute deployment.
-In this deployment type, the Jump Host server will host the undercloud VM along
-with any number of OPNFV overcloud control/compute nodes. This deployment type
-is useful when physical resources are constrained, or there is a desire to
-deploy a temporary sandbox environment.
+This deployment type is useful when physical resources are constrained, or
+there is a desire to deploy a temporary sandbox environment.
+
+With virtual deployments, two deployment options are offered. The first is a
+standard deployment where the Jump Host server will host the undercloud VM along
+with any number of OPNFV overcloud control/compute nodes. This follows the same
+deployment workflow as baremetal, and can take between 1 to 2 hours to complete.
+
+The second option is to use snapshot deployments. Snapshots are saved disk images
+of previously deployed OPNFV upstream. These snapshots are promoted daily and contain
+and already deployed OPNFV environment that has passed a series of tests. The
+advantage of the snapshot is that it deploys in less than 10 minutes. Another
+major advantage is that the snapshots work on both CentOS and Fedora OS. Note:
+Fedora support is only tested via PIP installation at this time and not via RPM.
+
+Standard Deployment Overview
+----------------------------
The virtual deployment operates almost the same way as the bare metal
deployment with a few differences mainly related to power management.
``opnfv-deploy`` still deploys an undercloud VM. In addition to the undercloud
VM a collection of VMs (3 control nodes + 2 compute for an HA deployment or 1
-control node and 1 or more compute nodes for a Non-HA Deployment) will be
+control node and 0 or more compute nodes for a Non-HA Deployment) will be
defined for the target OPNFV deployment. All overcloud VMs are registered
with a Virtual BMC emulator which will service power management (IPMI)
commands. The overcloud VMs are still provisioned with the same disk images
-and configuration that baremetal would use.
+and configuration that baremetal would use. Using 0 nodes for a virtual
+deployment will automatically deploy "all-in-one" nodes which means the compute
+will run along side the controller in a single overcloud node. Specifying 3
+control nodes will result in a highly-available service model.
To Triple-O these nodes look like they have just built and registered the same
way as bare metal nodes, the main difference is the use of a libvirt driver for
@@ -24,6 +40,23 @@ the power management. Finally, the default network settings file will deploy wi
modification. Customizations are welcome but not needed if a generic set of
network settings are acceptable.
+Snapshot Deployment Overview
+----------------------------
+
+Snapshot deployments use the same ``opnfv-deploy`` CLI as standard deployments.
+The snapshot deployment will use a cache in order to store snapshots that are
+downloaded from the internet at deploy time. This caching avoids re-downloading
+the same artifact between deployments. The snapshot deployment recreates the same
+network and libvirt setup as would have been provisioned by the Standard
+deployment, with the exception that there is no undercloud VM. The snapshot
+deployment will give the location of the RC file to use in order to interact
+with the Overcloud directly from the jump host.
+
+Snapshots come in different topology flavors. One is able to deploy either HA
+(3 Control, 2 Computes, no-HA (1 Control, 2 Computes), or all-in-one
+(1 Control/Compute. The snapshot deployment itself is always done with the
+os-odl-nofeature-* scenario.
+
Installation Guide - Virtual Deployment
=======================================
@@ -54,8 +87,8 @@ Install Jump Host
Follow the instructions in the `Install Bare Metal Jump Host`_ section.
-Running ``opnfv-deploy``
-------------------------
+Running ``opnfv-deploy`` for Standard Deployment
+------------------------------------------------
You are now ready to deploy OPNFV!
``opnfv-deploy`` has virtual deployment capability that includes all of
@@ -67,7 +100,7 @@ environment will deploy with the following architecture:
- 1 undercloud VM
- The option of 3 control and 2 or more compute VMs (HA Deploy / default)
- or 1 control and 1 or more compute VM (Non-HA deploy / pass -n)
+ or 1 control and 0 or more compute VMs (Non-HA deploy)
- 1-5 networks: provisioning, private tenant networking, external, storage
and internal API. The API, storage and tenant networking networks can be
@@ -83,7 +116,8 @@ Follow the steps below to execute:
password: 'opnfvapex'. It is also useful in some cases to surround the
deploy command with ``nohup``. For example:
``nohup <deploy command> &``, will allow a deployment to continue even if
- ssh access to the Jump Host is lost during deployment.
+ ssh access to the Jump Host is lost during deployment. By specifying
+ ``--virtual-computes 0``, the deployment will proceed as all-in-one.
2. It will take approximately 45 minutes to an hour to stand up undercloud,
define the target virtual machines, configure the deployment and execute
@@ -92,6 +126,43 @@ Follow the steps below to execute:
3. When the deployment is complete the IP for the undercloud and a url for the
OpenStack dashboard will be displayed
+Running ``opnfv-deploy`` for Snapshot Deployment
+------------------------------------------------
+
+Deploying snapshots requires enough disk space to cache snapshot archives, as well
+as store VM disk images per deployment. The snapshot cache directory can be
+configured at deploy time. Ensure a directory is used on a partition with enough
+space for about 20GB. Additionally, Apex will attempt to detect the default
+libvirt storage pool on the jump host. This is typically '/var/lib/libvirt/images'.
+On default CentOS installations, this path will resolve to the /root partition,
+which is only around 50GB. Therefore, ensure that the path for the default storage
+pool has enough space to hold the VM backing storage (approx 4GB per VM). Note,
+each Overcloud VM disk size is set to 40GB, however Libvirt grows these disks
+dynamically. Due to this only 4GB will show up at initial deployment, but the disk
+may grow from there up to 40GB.
+
+The new arguments to deploy snapshots include:
+
+ - `--snapshot`: Enables snapshot deployments
+ - `--snap-cache`: Indicates the directory to use for caching artifacts
+
+An example deployment command is:
+
+.. code-block::
+
+ opnfv-deploy -d ../config/deploy/os-odl-queens-noha.yaml --snapshot
+ --snap-cache /home/trozet/snap_cache --virtual-computes 0 --no-fetch
+
+In the above example, several of the Standard Deployment arguments are still
+used to deploy snapshots:
+
+ - `-d`: Deploy settings are used to determine OpenStack version of snapshots
+ to use as well as the topology
+ - `--virtual-computes` - When set to 0, it indicates to Apex to use an
+ all-in-one snapshot
+ - `--no-fetch` - Can be used to disable fetching latest snapshot artifact
+ from upstream and use the latest found in `--snap-cache`
+
Verifying the Setup - VMs
-------------------------
diff --git a/docs/release/release-notes/release-notes.rst b/docs/release/release-notes/release-notes.rst
index 8a8593a0..159165de 100644
--- a/docs/release/release-notes/release-notes.rst
+++ b/docs/release/release-notes/release-notes.rst
@@ -1,11 +1,11 @@
========================================================================
-OPNFV Release Notes for the Fraser release of OPNFV Apex deployment tool
+OPNFV Release Notes for the Gambia release of OPNFV Apex deployment tool
========================================================================
Abstract
========
-This document provides the release notes for Fraser release with the Apex
+This document provides the release notes for Gambia release with the Apex
deployment toolchain.
License
@@ -17,7 +17,7 @@ All Apex and "common" entities are protected by the Apache 2.0 License
Important Notes
===============
-This is the OPNFV Fraser release that implements the deploy stage of the
+This is the OPNFV Gambia release that implements the deploy stage of the
OPNFV CI pipeline via Apex.
Apex is based on RDO's Triple-O installation tool chain.
@@ -29,14 +29,14 @@ deploy OPNFV using Apex installer.
Summary
=======
-Fraser release with the Apex deployment toolchain will establish an OPNFV
+Gambia release with the Apex deployment toolchain will establish an OPNFV
target system on a Pharos compliant lab infrastructure. The current definition
of an OPNFV target system is OpenStack Pike combined with an SDN
controller, such as OpenDaylight. The system is deployed with OpenStack High
Availability (HA) for most OpenStack services. SDN controllers are deployed
on every controller unless deploying with one the HA FD.IO scenarios. Ceph
storage is used as Cinder backend, and is the only supported storage for
-Fraser. Ceph is setup as 3 OSDs and 3 Monitors, one OSD+Mon per Controller
+Gambia. Ceph is setup as 3 OSDs and 3 Monitors, one OSD+Mon per Controller
node in an HA setup. Apex also supports non-HA deployments, which deploys a
single controller and n number of compute nodes. Furthermore, Apex is
capable of deploying scenarios in a bare metal or virtual fashion. Virtual
@@ -46,7 +46,7 @@ simulate the a bare metal deployment.
- Documentation is built by Jenkins
- .iso image is built by Jenkins
- .rpm packages are built by Jenkins
-- Jenkins deploys a Fraser release with the Apex deployment toolchain
+- Jenkins deploys a Gambia release with the Apex deployment toolchain
bare metal, which includes 3 control+network nodes, and 2 compute nodes.
Release Data
@@ -56,16 +56,16 @@ Release Data
| **Project** | apex |
| | |
+--------------------------------------+--------------------------------------+
-| **Repo/tag** | opnfv-6.0.0 |
+| **Repo/tag** | opnfv-7.1.0 |
| | |
+--------------------------------------+--------------------------------------+
-| **Release designation** | 6.0.0 |
+| **Release designation** | 7.1.0 |
| | |
+--------------------------------------+--------------------------------------+
-| **Release date** | 2018-04-30 |
+| **Release date** | 2018-12-14 |
| | |
+--------------------------------------+--------------------------------------+
-| **Purpose of the delivery** | OPNFV Fraser release |
+| **Purpose of the delivery** | OPNFV Gambia release |
| | |
+--------------------------------------+--------------------------------------+
@@ -74,25 +74,25 @@ Version change
Module version changes
~~~~~~~~~~~~~~~~~~~~~~
-This is the first tracked version of the Fraser release with the Apex
-deployment toolchain. It is based on following upstream versions:
+This is the first tracked version of the Gambia release with the Apex
+deployment toolchain. It is based on following upstream versions:
-- OpenStack (Pike release)
+- OpenStack (Queens release)
-- OpenDaylight (Nitrogen/Oxygen releases)
+- OpenDaylight (Oxygen releases)
- CentOS 7
Document Version Changes
~~~~~~~~~~~~~~~~~~~~~~~~
-This is the first tracked version of Fraser release with the Apex
+This is the first tracked version of Gambia release with the Apex
deployment toolchain.
The following documentation is provided with this release:
-- OPNFV Installation instructions for the Fraser release with the Apex
+- OPNFV Installation instructions for the Gambia release with the Apex
deployment toolchain - ver. 1.0.0
-- OPNFV Release Notes for the Fraser release with the Apex deployment
+- OPNFV Release Notes for the Gambia release with the Apex deployment
toolchain - ver. 1.0.0 (this document)
Deliverables
@@ -108,10 +108,10 @@ Software Deliverables
Documentation Deliverables
~~~~~~~~~~~~~~~~~~~~~~~~~~
-- OPNFV Installation instructions for the Fraser release with the Apex
- deployment toolchain - ver. 6.0
-- OPNFV Release Notes for the Fraser release with the Apex deployment
- toolchain - ver. 6.0 (this document)
+- OPNFV Installation instructions for the Gambia release with the Apex
+ deployment toolchain - ver. 7.1
+- OPNFV Release Notes for the Gambia release with the Apex deployment
+ toolchain - ver. 7.1 (this document)
Known Limitations, Issues and Workarounds
=========================================
@@ -158,9 +158,6 @@ Known Issues
+--------------------------------------+--------------------------------------+
| JIRA: APEX-412 | Install failures with UEFI |
+--------------------------------------+--------------------------------------+
-| JIRA: APEX-425 | Need to tweak performance settings |
-| | virtual DPDK scenarios |
-+--------------------------------------+--------------------------------------+
Workarounds
@@ -178,10 +175,10 @@ Apex installer.
References
==========
-For more information on the OPNFV Fraser release, please see:
+For more information on the OPNFV Gambia release, please see:
-http://wiki.opnfv.org/releases/Fraser
+http://wiki.opnfv.org/releases/Gambia
:Authors: Tim Rozet (trozet@redhat.com)
:Authors: Dan Radez (dradez@redhat.com)
-:Version: 6.0
+:Version: 7.1
diff --git a/docs/release/scenarios/os-nosdn-performance-ha/index.rst b/docs/release/scenarios/k8s-nosdn-nofeature-noha/index.rst
index e0dbca7f..6efd74c2 100644
--- a/docs/release/scenarios/os-nosdn-performance-ha/index.rst
+++ b/docs/release/scenarios/k8s-nosdn-nofeature-noha/index.rst
@@ -1,15 +1,15 @@
-.. _os-nosdn-performance-ha:
+.. _k8s-nosdn-nofeature-noha:
.. This work is licensed under a Creative Commons Attribution 4.0 International Licence.
.. http://creativecommons.org/licenses/by/4.0
.. (c) <optionally add copywriters name>
-================================================
-os-nosdn-performance-ha overview and description
-================================================
+=================================================
+k8s-nosdn-nofeature-noha overview and description
+=================================================
.. toctree::
:numbered:
:maxdepth: 4
- os-nosdn-performance-ha.rst
+ k8s-nosdn-nofeature-noha.rst
diff --git a/docs/release/scenarios/k8s-nosdn-nofeature-noha/k8s-nosdn-nofeature-noha.rst b/docs/release/scenarios/k8s-nosdn-nofeature-noha/k8s-nosdn-nofeature-noha.rst
new file mode 100644
index 00000000..7ff21b73
--- /dev/null
+++ b/docs/release/scenarios/k8s-nosdn-nofeature-noha/k8s-nosdn-nofeature-noha.rst
@@ -0,0 +1,46 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. (c) <optionally add copywriters name>
+
+This document provides scenario level details for Gambia 1.1 of
+Kubernetes deployment with no SDN controller, no extra features
+and no High Availability enabled. Note this scenario is *not* supported
+for Gambia initial release and will be supported in a later service release
+of Gambia.
+
+============
+Introduction
+============
+
+This scenario is used primarily to validate and deploy a Kubernetes
+deployment without any NFV features or SDN controller enabled.
+
+Scenario components and composition
+===================================
+
+This scenario deploys a Kubernetes cluster on bare metal or virtual
+environment with a single master node. TripleO is used to bootstrap
+all the nodes and set up basic services like SSH. An undercloud VM
+used similarly to Openstack deployments, however no Openstack services
+(Nova, Neutron, Keystone, etc) will be deployed to the nodes. After
+TripleO successfully executes all the bootstrapping tasks, Kubespray
+is run (using ansible) to deploy Kubernetes cluster on the nodes.
+
+
+Scenario usage overview
+=======================
+
+Simply deploy this scenario by using the k8s-nosdn-nofeature-noha.yaml deploy
+settings file.
+
+Limitations, Issues and Workarounds
+===================================
+
+None
+
+References
+==========
+
+For more information on the OPNFV Gambia release, please visit
+http://www.opnfv.org/gambia
+
diff --git a/docs/release/scenarios/os-nosdn-nofeature-ha/os-nosdn-nofeature-ha.rst b/docs/release/scenarios/os-nosdn-nofeature-ha/os-nosdn-nofeature-ha.rst
index bc6d39b8..5f2839c1 100644
--- a/docs/release/scenarios/os-nosdn-nofeature-ha/os-nosdn-nofeature-ha.rst
+++ b/docs/release/scenarios/os-nosdn-nofeature-ha/os-nosdn-nofeature-ha.rst
@@ -2,14 +2,14 @@
.. http://creativecommons.org/licenses/by/4.0
.. (c) <optionally add copywriters name>
-This document provides scenario level details for Fraser 1.0 of
+This document provides scenario level details for Gambia 1.1 of
deployment with no SDN controller and no extra features enabled.
============
Introduction
============
-This scenario is used primarily to validate and deploy a Pike OpenStack
+This scenario is used primarily to validate and deploy a Queens OpenStack
deployment without any NFV features or SDN controller enabled.
Scenario components and composition
@@ -38,6 +38,6 @@ None
References
==========
-For more information on the OPNFV Fraser release, please visit
-http://www.opnfv.org/fraser
+For more information on the OPNFV Gambia release, please visit
+http://www.opnfv.org/gambia
diff --git a/docs/release/scenarios/os-nosdn-nofeature-noha/os-nosdn-nofeature-noha.rst b/docs/release/scenarios/os-nosdn-nofeature-noha/os-nosdn-nofeature-noha.rst
index 8edd29bd..e5d4c989 100644
--- a/docs/release/scenarios/os-nosdn-nofeature-noha/os-nosdn-nofeature-noha.rst
+++ b/docs/release/scenarios/os-nosdn-nofeature-noha/os-nosdn-nofeature-noha.rst
@@ -2,14 +2,14 @@
.. http://creativecommons.org/licenses/by/4.0
.. (c) <optionally add copywriters name>
-This document provides scenario level details for Fraser 1.0 of
+This document provides scenario level details for Gambia 1.1 of
deployment with no SDN controller and no extra features enabled.
============
Introduction
============
-This scenario is used primarily to validate and deploy a Pike OpenStack
+This scenario is used primarily to validate and deploy a Queens OpenStack
deployment without any NFV features or SDN controller enabled.
Scenario components and composition
@@ -35,6 +35,6 @@ None
References
==========
-For more information on the OPNFV Fraser release, please visit
-http://www.opnfv.org/fraser
+For more information on the OPNFV Gambia release, please visit
+http://www.opnfv.org/gambia
diff --git a/docs/release/scenarios/os-nosdn-performance-ha/os-nosdn-performance-ha.rst b/docs/release/scenarios/os-nosdn-performance-ha/os-nosdn-performance-ha.rst
deleted file mode 100644
index beed894e..00000000
--- a/docs/release/scenarios/os-nosdn-performance-ha/os-nosdn-performance-ha.rst
+++ /dev/null
@@ -1,54 +0,0 @@
-.. This work is licensed under a Creative Commons Attribution 4.0 International License.
-.. http://creativecommons.org/licenses/by/4.0
-.. (c) <optionally add copywriters name>
-
-This document provides scenario level details for Fraser 1.0 of
-deployment with no SDN controller and performance options enabled.
-
-============
-Introduction
-============
-
-This scenario is used primarily to demonstrate the performance settings and
-capabilities in Apex. This scenario will deploy a Pike OpenStack
-deployment without any NFV features or SDN controller enabled.
-
-Scenario components and composition
-===================================
-
-This scenario is composed of common OpenStack services enabled by default,
-including Nova, Neutron, Glance, Cinder, Keystone, Horizon. Optionally and
-by default, Tacker and Congress services are also enabled. Ceph is used as
-the backend storage to Cinder on all deployed nodes.
-
-All services are in HA, meaning that there are multiple cloned instances of
-each service, and they are balanced by HA Proxy using a Virtual IP Address
-per service.
-
-The main purpose of this scenario is to serve as an example to show how to
-set optional performance settings in an Apex deploy settings file.
-
-Scenario usage overview
-=======================
-
-The performance options listed in os-nosdn-performance-ha.yaml give an example
-of the different options a user can set in any deploy settings file. Some
-of these performance options are actually required for other scenarios which
-rely on DPDK. Options under the nova section like 'libvirtpin' allow a
-user to choose which core to pin nova instances to on the overcloud compute
-node. Options under 'kernel' allow a user to set kernel specific arguments
-at boot, which include options like hugepages, isolcpus, enabling iommu, etc.
-
-
-Limitations, Issues and Workarounds
-===================================
-
-* `APEX-389 <https://jira.opnfv.org/browse/APEX-389>`_:
- Compute kernel parameters are applied to all nodes
-
-References
-==========
-
-For more information on the OPNFV Fraser release, please visit
-http://www.opnfv.org/fraser
-
diff --git a/docs/release/scenarios/os-odl-nofeature-ha/os-odl-nofeature-ha.rst b/docs/release/scenarios/os-odl-nofeature-ha/os-odl-nofeature-ha.rst
index 52530cdd..111ba6f7 100644
--- a/docs/release/scenarios/os-odl-nofeature-ha/os-odl-nofeature-ha.rst
+++ b/docs/release/scenarios/os-odl-nofeature-ha/os-odl-nofeature-ha.rst
@@ -2,14 +2,14 @@
.. http://creativecommons.org/licenses/by/4.0
.. (c) <optionally add copywriters name>
-This document provides scenario level details for Fraser 1.0 of
+This document provides scenario level details for Gambia 1.1 of
deployment with the OpenDaylight SDN controller and no extra features enabled.
============
Introduction
============
-This scenario is used primarily to validate and deploy a Pike OpenStack
+This scenario is used primarily to validate and deploy a Queens OpenStack
deployment with OpenDaylight, and without any NFV features enabled.
Scenario components and composition
@@ -38,18 +38,12 @@ settings file.
Limitations, Issues and Workarounds
===================================
-* `APEX-112 <https://jira.opnfv.org/browse/APEX-112>`_:
- ODL routes local subnet traffic to GW
-* `APEX-149 <https://jira.opnfv.org/browse/APEX-149>`_:
- OpenFlow rules are populated very slowly
* `APEX-268 <https://jira.opnfv.org/browse/APEX-268>`_:
VMs with multiple floating IPs can only access via first NIC
-* `APEX-422 <https://jira.opnfv.org/browse/APEX-422>`_:
- First nova instance DHCP request fails
References
==========
-For more information on the OPNFV Fraser release, please visit
-http://www.opnfv.org/fraser
+For more information on the OPNFV Gambia release, please visit
+http://www.opnfv.org/gambia
diff --git a/docs/release/scenarios/os-odl-nofeature-noha/os-odl-nofeature-noha.rst b/docs/release/scenarios/os-odl-nofeature-noha/os-odl-nofeature-noha.rst
index 932ccc85..3e26d672 100644
--- a/docs/release/scenarios/os-odl-nofeature-noha/os-odl-nofeature-noha.rst
+++ b/docs/release/scenarios/os-odl-nofeature-noha/os-odl-nofeature-noha.rst
@@ -2,14 +2,14 @@
.. http://creativecommons.org/licenses/by/4.0
.. (c) <optionally add copywriters name>
-This document provides scenario level details for Fraser 1.0 of
+This document provides scenario level details for Gambia 1.1 of
deployment with the OpenDaylight SDN controller and no extra features enabled.
============
Introduction
============
-This scenario is used primarily to validate and deploy a Pike OpenStack
+This scenario is used primarily to validate and deploy a Queens OpenStack
deployment with OpenDaylight, and without any NFV features enabled.
Scenario components and composition
@@ -32,18 +32,12 @@ settings file.
Limitations, Issues and Workarounds
===================================
-* `APEX-112 <https://jira.opnfv.org/browse/APEX-112>`_:
- ODL routes local subnet traffic to GW
-* `APEX-149 <https://jira.opnfv.org/browse/APEX-149>`_:
- OpenFlow rules are populated very slowly
* `APEX-268 <https://jira.opnfv.org/browse/APEX-268>`_:
VMs with multiple floating IPs can only access via first NIC
-* `APEX-422 <https://jira.opnfv.org/browse/APEX-422>`_:
- First nova instance DHCP request fails
References
==========
-For more information on the OPNFV Fraser release, please visit
-http://www.opnfv.org/fraser
+For more information on the OPNFV Gambia release, please visit
+http://www.opnfv.org/gambia
diff --git a/docs/release/scenarios/os-ovn-nofeature-noha/index.rst b/docs/release/scenarios/os-ovn-nofeature-ha/index.rst
index 74545044..b7e62e6c 100644
--- a/docs/release/scenarios/os-ovn-nofeature-noha/index.rst
+++ b/docs/release/scenarios/os-ovn-nofeature-ha/index.rst
@@ -1,4 +1,4 @@
-.. _os-ovn-nofeature-noha:
+.. _os-ovn-nofeature-ha:
.. This work is licensed under a Creative Commons Attribution 4.0 International Licence.
.. http://creativecommons.org/licenses/by/4.0
@@ -12,4 +12,4 @@ os-ovn-nofeature-noha overview and description
:numbered:
:maxdepth: 4
- os-ovn-nofeature-noha.rst
+ os-ovn-nofeature-ha.rst
diff --git a/docs/release/scenarios/os-ovn-nofeature-noha/os-ovn-nofeature-noha.rst b/docs/release/scenarios/os-ovn-nofeature-ha/os-ovn-nofeature-ha.rst
index 1b2da194..165b5f71 100644
--- a/docs/release/scenarios/os-ovn-nofeature-noha/os-ovn-nofeature-noha.rst
+++ b/docs/release/scenarios/os-ovn-nofeature-ha/os-ovn-nofeature-ha.rst
@@ -2,7 +2,7 @@
.. http://creativecommons.org/licenses/by/4.0
.. (c) <optionally add copywriters name>
-This document provides scenario level details for Fraser 1.0 of
+This document provides scenario level details for Gambia 1.1 of
deployment with the OVN SDN controller and no extra features enabled.
============
@@ -23,18 +23,17 @@ the backend storage to Cinder on all deployed nodes.
Scenario usage overview
=======================
-Simply deploy this scenario by using the os-ovn-nofeature-noha.yaml deploy
+Simply deploy this scenario by using the os-ovn-nofeature-ha.yaml deploy
settings file.
Limitations, Issues and Workarounds
===================================
-* `APEX-430 <https://jira.opnfv.org/browse/APEX-430>`_:
- OVN HA functionality is not available.
+None
References
==========
-For more information on the OPNFV Fraser release, please visit
-http://www.opnfv.org/fraser
+For more information on the OPNFV Gambia release, please visit
+http://www.opnfv.org/gambia
diff --git a/docs/requirements.txt b/docs/requirements.txt
new file mode 100644
index 00000000..9fde2df2
--- /dev/null
+++ b/docs/requirements.txt
@@ -0,0 +1,2 @@
+lfdocs-conf
+sphinx_opnfv_theme
diff --git a/lib/ansible/playbooks/configure_undercloud.yml b/lib/ansible/playbooks/configure_undercloud.yml
index 040a559e..07b82c8e 100644
--- a/lib/ansible/playbooks/configure_undercloud.yml
+++ b/lib/ansible/playbooks/configure_undercloud.yml
@@ -27,6 +27,13 @@
with_items:
- controller
- compute
+ - name: Copy container prep env file to undercloud
+ copy:
+ src: "{{ apex_temp_dir }}/containers-prepare-parameter.yaml"
+ dest: "/home/stack/containers-prepare-parameter.yaml"
+ owner: stack
+ group: stack
+ mode: 0644
- lineinfile:
path: /etc/sudoers
regexp: 'Defaults\s*requiretty'
@@ -47,20 +54,9 @@
- name: openstack-configs undercloud
shell: openstack-config --set undercloud.conf DEFAULT {{ item }}
with_items: "{{ undercloud_config }}"
- - name: Add ironic packages
- yum:
- name: openstack-ironic-api,openstack-ironic-common,
- openstack-ironic-inspector
- become: yes
- - name: openstack-configs ironic
- shell: openstack-config --set /etc/ironic/ironic.conf {{ item }}
- become: yes
- with_items: "{{ ironic_config }}"
- - lineinfile:
- path: /usr/lib/python2.7/site-packages/ironic/common/pxe_utils.py
- regexp: '_link_ip_address_pxe_configs'
- line: ' _link_mac_pxe_configs(task)'
- when: aarch64
+ - name: openstack-configs undercloud network
+ shell: openstack-config --set undercloud.conf ctlplane-subnet {{ item }}
+ with_items: "{{ undercloud_network_config }}"
- block:
- name: undercloud install
shell: openstack undercloud install &> apex-undercloud-install.log
@@ -77,40 +73,42 @@
src: /home/stack/apex-undercloud-install.log
dest: "{{ apex_temp_dir }}/"
flat: yes
+ - name: Install ceph-ansible
+ yum:
+ name: ceph-ansible
+ become: yes
- name: openstack-configs nova
- shell: openstack-config --set /etc/nova/nova.conf DEFAULT {{ item }}
+ shell: openstack-config --set /var/lib/config-data/nova/etc/nova/nova.conf DEFAULT {{ item }}
become: yes
with_items: "{{ nova_config }}"
- name: restart nova services
- service:
- name: "{{ item }}"
- state: restarted
- enabled: yes
+ shell: "{{ container_client }} restart {{ item }}"
with_items:
- - openstack-nova-conductor
- - openstack-nova-compute
- - openstack-nova-api
- - openstack-nova-scheduler
+ - nova_conductor
+ - nova_compute
+ - nova_api
+ - nova_scheduler
+ become: yes
- name: openstack-configs neutron
- shell: openstack-config --set /etc/neutron/neutron.conf DEFAULT {{ item }}
+ shell: openstack-config --set /var/lib/config-data/neutron/etc/neutron/neutron.conf DEFAULT {{ item }}
become: yes
with_items: "{{ neutron_config }}"
- name: restart neutron services
- service:
- name: "{{ item }}"
- state: restarted
- enabled: yes
+ shell: "{{ container_client }} restart {{ item }}"
with_items:
- - neutron-server
- - neutron-dhcp-agent
- - name: Configure workaround for mariadb long blob (LP#1768913)
- shell: openstack-config --set /etc/my.cnf.d/galera.cnf mysqld innodb_log_file_size 256M
+ - neutron_api
+ - neutron_dhcp
become: yes
- - name: restart mariadb service
- service:
- name: mariadb
- state: restarted
- enabled: yes
+ - name: openstack-configs ironic
+ shell: openstack-config --set /var/lib/config-data/ironic/etc/ironic/ironic.conf {{ item }}
+ become: yes
+ with_items: "{{ ironic_config }}"
+ - name: restart ironic services
+ shell: "{{ container_client }} restart {{ item }}"
+ with_items:
+ - ironic_api
+ - ironic_conductor
+ - ironic_inspector
become: yes
- name: configure external network vlan ifcfg
template:
@@ -135,21 +133,12 @@
when:
- external_network.vlan == "native"
- external_network.enabled
- - not aarch64
- name: bring up eth2
shell: ip link set up dev eth2
when:
- external_network.vlan == "native"
- external_network.enabled
- - not aarch64
- become: yes
- - name: assign IP to native eth0 if aarch64
- shell: ip a a {{ external_network.ip }}/{{ external_network.prefix }} dev eth0
become: yes
- when:
- - external_network.vlan == "native"
- - external_network.enabled
- - aarch64
- name: bring up eth0 if aarch64
shell: ip link set up dev eth0
when:
@@ -183,12 +172,22 @@
jump: ACCEPT
source: "{{ nat_cidr }}"
ctstate: ESTABLISHED,RELATED
- - name: Undercloud NAT - Save iptables
- shell: service iptables save
become: yes
when:
- not nat_network_ipv6
- nat
+ - name: Allow SSH in iptables
+ iptables:
+ action: insert
+ chain: INPUT
+ rule_num: 1
+ protocol: tcp
+ destination_port: 22
+ jump: ACCEPT
+ become: yes
+ - name: Undercloud NAT - Save iptables
+ shell: service iptables save
+ become: yes
- name: fetch storage environment file
fetch:
src: /usr/share/openstack-tripleo-heat-templates/environments/storage-environment.yaml
@@ -196,9 +195,12 @@
flat: yes
- name: fetch sriov environment file
fetch:
- src: /usr/share/openstack-tripleo-heat-templates/environments/neutron-opendaylight-sriov.yaml
+ src: /usr/share/openstack-tripleo-heat-templates/environments/services/neutron-opendaylight-sriov.yaml
dest: "{{ apex_temp_dir }}/"
flat: yes
+ - name: Restorecon for root ssh
+ shell: restorecon -r -v /root/.ssh
+ become: yes
- include: undercloud_aarch64.yml
when: aarch64
diff --git a/lib/ansible/playbooks/deploy_dependencies.yml b/lib/ansible/playbooks/deploy_dependencies.yml
index fb1da46f..ab09ff6e 100644
--- a/lib/ansible/playbooks/deploy_dependencies.yml
+++ b/lib/ansible/playbooks/deploy_dependencies.yml
@@ -8,6 +8,25 @@
- python-lxml
- libvirt-python
- libguestfs-tools
+ - python-netaddr
+ - python2-pip
+ when: ansible_distribution == 'CentOS'
+ - dnf:
+ name: "{{ item }}"
+ state: present
+ with_items:
+ - libselinux-python
+ - python-lxml
+ - libvirt-python
+ - libguestfs-tools
+ - python-netaddr
+ - python2-pip
+ when: ansible_distribution == 'Fedora'
+ - pip:
+ name: ansible-modules-hashivault,hvac,Jinja2
+ state: latest
+ executable: pip2
+ when: not snapshot
- sysctl:
name: net.ipv4.ip_forward
state: present
@@ -32,20 +51,31 @@
xml: '{{ lookup("template", "virsh_network_default.xml.j2") }}'
state: active
autostart: yes
+ when: not snapshot
- openvswitch_bridge:
bridge: 'br-{{ item }}'
state: present
with_items: '{{ virsh_enabled_networks }}'
+ - name: 'Configure IP on bridge'
+ shell: 'ip addr add 192.0.2.99/24 dev br-{{ item }}'
+ with_items: '{{ virsh_enabled_networks }}'
+ when: snapshot
+ - name: 'Bring up bridge'
+ shell: 'ip link set up br-{{ item }}'
+ with_items: '{{ virsh_enabled_networks }}'
+ when: snapshot
- virt_net:
state: present
name: '{{ item }}'
xml: '{{ lookup("template", "virsh_network_ovs.xml.j2") }}'
with_items: '{{ virsh_enabled_networks }}'
+ when: not snapshot
- virt_net:
state: active
name: '{{ item }}'
autostart: yes
with_items: '{{ virsh_enabled_networks }}'
+ when: not snapshot
- virt_pool:
name: default
autostart: yes
@@ -81,16 +111,19 @@
state: present
- name: Generate SSH key for root if missing
shell: test -e ~/.ssh/id_rsa || ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
+ when: not snapshot
- name: Check that /u/l/python3.4/site-packages/virtualbmc/vbmc.py exists
stat:
path: /usr/lib/python3.4/site-packages/virtualbmc/vbmc.py
register: vbmc_py
+ when: not snapshot
- name: Manually patch vmbc to work with python3.x
lineinfile:
line: " conn.defineXML(ET.tostring(tree, encoding='unicode'))"
regexp: "tostring"
path: /usr/lib/python3.4/site-packages/virtualbmc/vbmc.py
when: vbmc_py.stat.exists == True
+ when: not snapshot
- name: Add ssh retry to Ansible config
ini_file:
path: /etc/ansible/ansible.cfg
diff --git a/lib/ansible/playbooks/deploy_overcloud.yml b/lib/ansible/playbooks/deploy_overcloud.yml
index a9c3b982..9a405814 100644
--- a/lib/ansible/playbooks/deploy_overcloud.yml
+++ b/lib/ansible/playbooks/deploy_overcloud.yml
@@ -12,10 +12,23 @@
- network-environment.yaml
- instackenv.json
- overcloud-full.qcow2
+ - overcloud-full.vmlinuz
+ - overcloud-full.initrd
+ - ironic-python-agent.initramfs
+ - ironic-python-agent.kernel
- deploy_command
- virtual-environment.yaml
- baremetal-environment.yaml
+ - kubernetes-environment.yaml
- "{{ apex_env_file }}"
+ - name: Copy ansible.cfg data to undercloud in aarch64
+ copy:
+ src: "{{ apex_temp_dir }}/ansible.cfg"
+ dest: "/home/stack/ansible.cfg"
+ owner: stack
+ group: stack
+ mode: 0644
+ when: aarch64
- name: Copy network data to undercloud
copy:
src: "{{ apex_temp_dir }}/network_data.yaml"
@@ -32,15 +45,10 @@
mode: 0664
- copy:
src: "{{ apex_temp_dir }}/neutron-opendaylight-sriov.yaml"
- dest: /usr/share/openstack-tripleo-heat-templates/environments/neutron-opendaylight-sriov.yaml
+ dest: /usr/share/openstack-tripleo-heat-templates/environments/services/neutron-opendaylight-sriov.yaml
owner: root
group: root
mode: 0664
- - systemd:
- name: openstack-swift-proxy
- state: restarted
- enabled: yes
- become: yes
- name: Remove Ceph OSD from ceph storage role
lineinfile:
path: /usr/share/openstack-tripleo-heat-templates/roles_data.yaml
@@ -65,6 +73,22 @@
owner: root
group: root
become: yes
+ - name: Insert External network into Compute role
+ shell: |
+ ruby -e '
+ require "yaml"
+ data = YAML.load(File.read("/usr/share/openstack-tripleo-heat-templates/roles_data.yaml"))
+ if data[1]["networks"].is_a?(Array)
+ data[1]["networks"].push("External")
+ elsif data[1]["networks"].is_a?(Hash)
+ data[1]["networks"].merge!("External"=> { "subnet" => "external_subnet" })
+ else
+ raise "Unable to determine data to modify in roles_data.yaml"
+ end
+ data[1]["default_route_networks"] = Array.new(["External"])
+ File.open("/usr/share/openstack-tripleo-heat-templates/roles_data.yaml", "w") { |f| f.write(data.to_yaml) }
+ '
+ become: yes
- name: Upload glance images
shell: "{{ stackrc }} && openstack overcloud image upload"
become: yes
@@ -84,8 +108,25 @@
- baremetal
- control
- compute
+ - name: Re-enable ceph config for aarch64
+ replace:
+ path: "/usr/share/ceph-ansible/roles/ceph-client/tasks/create_users_keys.yml"
+ regexp: "x86_64"
+ replace: "aarch64"
+ backup: yes
+ when: aarch64
- name: Configure DNS server for ctlplane network
shell: "{{ stackrc }} && openstack subnet set ctlplane-subnet {{ dns_server_args }}"
+ - name: Update NIC templates before deployment
+ shell: >
+ /usr/share/openstack-tripleo-heat-templates/tools/merge-new-params-nic-config-script.py
+ -n /home/stack/network_data.yaml -t /home/stack/nics/{{ item }}.yaml --discard-comments True
+ --role-name Controller
+ become: yes
+ become_user: stack
+ with_items:
+ - controller
+ - compute
- block:
- name: Execute Overcloud Deployment
shell: "{{ stackrc }} && bash deploy_command"
@@ -112,7 +153,7 @@
become: yes
- name: Show Keystone output
shell: "{{ overcloudrc }} && {{ item }}"
- when: debug
+ when: debug and vim == 'openstack'
with_items:
- openstack endpoint list
- openstack service list
diff --git a/lib/ansible/playbooks/k8s_remove_pkgs.yml b/lib/ansible/playbooks/k8s_remove_pkgs.yml
new file mode 100644
index 00000000..f9fa7787
--- /dev/null
+++ b/lib/ansible/playbooks/k8s_remove_pkgs.yml
@@ -0,0 +1,5 @@
+---
+- hosts: all
+ tasks:
+ - name: Removing existing docker related packages
+ shell: "rpm -e --nodeps docker docker-common docker-client container-selinux"
diff --git a/lib/ansible/playbooks/patch_containers.yml b/lib/ansible/playbooks/patch_containers.yml
new file mode 100644
index 00000000..1ef05810
--- /dev/null
+++ b/lib/ansible/playbooks/patch_containers.yml
@@ -0,0 +1,13 @@
+---
+ - name: "Pull docker image to ensure it exists locally: {{ item }}"
+ shell: "{{ container_client }} pull {{ undercloud_ip }}:8787/tripleo{{ os_version }}/centos-binary-{{ item }}:current-tripleo"
+ - name: "Find docker image user {{ item }}"
+ shell: >
+ {{ container_client }} inspect --format='{{ '{{' }}.ContainerConfig.User{{ '}}' }}'
+ {{ undercloud_ip }}:8787/tripleo{{ os_version }}/centos-binary-{{ item }}:current-tripleo
+ register: user_result
+ - name: "Patch docker image {{ item }}"
+ shell: >
+ cd /home/stack/containers/{{ item }} && {{ container_client }} build
+ --build-arg REAL_USER={{ user_result.stdout }}
+ -t {{ undercloud_ip }}:8787/tripleo{{ os_version }}/centos-binary-{{ item }}:apex .
diff --git a/lib/ansible/playbooks/post_deploy_overcloud.yml b/lib/ansible/playbooks/post_deploy_overcloud.yml
index af743b29..2b90ab1f 100644
--- a/lib/ansible/playbooks/post_deploy_overcloud.yml
+++ b/lib/ansible/playbooks/post_deploy_overcloud.yml
@@ -13,15 +13,6 @@
- dataplane == 'ovs_dpdk'
- "'compute' in ansible_hostname"
- sdn == false
- - name: SFC config workaround
- file:
- src: /etc/neutron/networking_sfc.conf
- dest: /etc/neutron/conf.d/neutron-server/networking_sfc.conf
- state: link
- become: yes
- when:
- - sfc
- - "'controller' in ansible_hostname"
- name: Ensure ZRPCD is running
shell: ps aux | grep zrpcd | grep -v grep
ignore_errors: yes
@@ -63,9 +54,42 @@
- openstack-nova-api
- openstack-nova-scheduler
- openstack-nova-conductor
- - name: Restart Compute Nova Compute (Pike Workaround)
- shell: "systemctl restart openstack-nova-compute"
+ - name: Restart Compute Nova Compute (workaround for NFS)
+ shell: "{{ container_client }} restart nova_compute"
+ become: yes
+ when: "'compute' in ansible_hostname or all_in_one"
+ - name: Update ODL container restart policy to always
+ shell: "{{ container_client }} update --restart=always opendaylight_api"
become: yes
when:
- - "'compute' in ansible_hostname"
- - os_version == 'pike'
+ - sdn == 'opendaylight'
+ - "'controller' in ansible_hostname"
+ - name: Open port 8101 (karaf shell) for ODL
+ iptables:
+ chain: INPUT
+ action: insert
+ protocol: tcp
+ destination_port: 8101
+ jump: ACCEPT
+ rule_num: 1
+ become: yes
+ when:
+ - sdn == 'opendaylight'
+ - "'controller' in ansible_hostname"
+ - name: save iptables
+ command: service iptables save
+ become: yes
+ - name: Modify nova metadata host to be IP
+ shell: >
+ crudini --set /var/lib/config-data/puppet-generated/neutron/etc/neutron/metadata_agent.ini
+ DEFAULT nova_metadata_host $(hiera -c /etc/puppet/hiera.yaml nova_metadata_vip)
+ become: yes
+ when:
+ - "'controller' in ansible_hostname"
+ - sdn != 'ovn'
+ - name: Restart metadata service
+ shell: "{{ container_client }} restart neutron_metadata_agent"
+ become: yes
+ when:
+ - "'controller' in ansible_hostname"
+ - sdn != 'ovn'
diff --git a/lib/ansible/playbooks/post_deploy_undercloud.yml b/lib/ansible/playbooks/post_deploy_undercloud.yml
index d0206f87..8cdfedfe 100644
--- a/lib/ansible/playbooks/post_deploy_undercloud.yml
+++ b/lib/ansible/playbooks/post_deploy_undercloud.yml
@@ -9,6 +9,7 @@
- name: Configure external network
shell: "{{ overcloudrc }} && {{ item }}"
with_items: "{{ external_network_cmds }}"
+ when: vim == 'openstack'
- name: Configure gluon networks
shell: "{{ overcloudrc }} && {{ item }}"
when: gluon
@@ -73,11 +74,35 @@
become: yes
become_user: stack
with_items: "{{ overcloudrc_files }}"
+ - name: Write SDN WEB and REST PORT to overcloudrc
+ lineinfile:
+ line: "export {{ item[0] }}=8081"
+ regexp: "{{ item[0] }}"
+ path: "/home/stack/{{ item[1] }}"
+ when: sdn != false
+ become: yes
+ become_user: stack
+ with_nested:
+ - [ 'SDN_CONTROLLER_WEBPORT', 'SDN_CONTROLLER_RESTCONFPORT' ]
+ - "{{ overcloudrc_files }}"
+ - name: Grab Heat Environment variables
+ shell: "{{ stackrc }} && openstack stack environment show overcloud -f json"
+ register: heat_env
+ become: yes
+ become_user: stack
+ - name: Write SDN controller password to overcloudrc for ODL
+ lineinfile:
+ line: "export SDN_CONTROLLER_PASSWORD={{(heat_env.stdout|from_json)['parameter_defaults']['OpenDaylightPassword']}}"
+ regexp: 'SDN_CONTROLLER_PASSWORD'
+ path: "/home/stack/{{ item }}"
+ when: sdn == 'opendaylight'
+ become: yes
+ become_user: stack
+ with_items: "{{ overcloudrc_files }}"
- name: Register OS Region
shell: "{{ overcloudrc }} && openstack endpoint list -c Region -f json"
register: region
- become: yes
- become_user: stack
+ when: vim == 'openstack'
- name: Write Region into overcloudrc
lineinfile:
line: "export OS_REGION_NAME={{(region.stdout|from_json)[1]['Region']}}"
@@ -86,6 +111,7 @@
become: yes
become_user: stack
with_items: "{{ overcloudrc_files }}"
+ when: vim == 'openstack'
- name: Create congress datasources
shell: "{{ overcloudrc }} && openstack congress datasource create {{ item }}"
become: yes
@@ -95,6 +121,10 @@
ignore_errors: yes
- name: Configure Calipso
block:
+ - name: Install pip3
+ yum:
+ name: python34-pip
+ state: present
- name: Install Calipso dependencies
pip:
name: "{{ item }}"
@@ -115,6 +145,8 @@
- docker-common
- docker-selinux
- docker-engine
+ - name: Add Docker CE repo
+ shell: yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
- name: Install Docker CE
package:
name: docker-ce
@@ -128,6 +160,6 @@
command: >
python3 /root/calipso-installer.py --command start-all
--copy q --hostname {{ calipso_ip }} --dbport 37017 --webport 81
- --apiport 8001 --rabbitmport 15673
+ --apiport 8001 --rabbitmport 15673 --home /root
become: yes
when: calipso
diff --git a/lib/ansible/playbooks/prepare_overcloud_containers.yml b/lib/ansible/playbooks/prepare_overcloud_containers.yml
index 79629c2b..ebf081dc 100644
--- a/lib/ansible/playbooks/prepare_overcloud_containers.yml
+++ b/lib/ansible/playbooks/prepare_overcloud_containers.yml
@@ -20,86 +20,31 @@
when: patched_docker_services|length > 0
- name: Prepare generic docker registry image file
shell: >
- {{ stackrc }} && openstack overcloud container image prepare
- --namespace docker.io/tripleo{{ os_version }}
- --tag {{ container_tag }}
- --push-destination {{ undercloud_ip }}:8787
- -e /usr/share/openstack-tripleo-heat-templates/environments/docker.yaml
- --output-images-file overcloud_containers.yml
- become: yes
- become_user: stack
- - name: Prepare SDN docker registry image file
- shell: >
- {{ stackrc }} && openstack overcloud container image prepare
- --namespace docker.io/tripleo{{ os_version }}
- --tag {{ container_tag }}
- --push-destination {{ undercloud_ip }}:8787
- -e {{ sdn_env_file }}
- --output-images-file sdn_containers.yml
- become: yes
- become_user: stack
- when: sdn != false
- - name: Upload docker images to local registry
- shell: >
- {{ stackrc }} && openstack overcloud container image upload
- --config-file /home/stack/overcloud_containers.yml
- - name: Upload SDN docker images to local registry
- shell: >
- {{ stackrc }} && openstack overcloud container image upload
- --config-file /home/stack/sdn_containers.yml
- when: sdn != false
+ sudo openstack tripleo container image prepare
+ -e /home/stack/containers-prepare-parameter.yaml
+ --output-env-file docker-images.yaml
- name: Collect docker images in registry
uri:
url: http://{{ undercloud_ip }}:8787/v2/_catalog
body_format: json
register: response
- - name: Patch Docker images
- shell: >
- cd /home/stack/containers/{{ item }} && docker build
- -t {{ undercloud_ip }}:8787/tripleo{{ os_version }}/centos-binary-{{ item }}:apex .
+ - include_tasks: patch_containers.yml
+ with_items: "{{ patched_docker_services }}"
+ loop_control:
+ loop_var: item
when:
- patched_docker_services|length > 0
- item in (response.json)['repositories']|join(" ")
- with_items: "{{ patched_docker_services }}"
- name: Push patched docker images to local registry
- shell: docker push {{ undercloud_ip }}:8787/tripleo{{ os_version }}/centos-binary-{{ item }}:apex
+ shell: "{{ container_client }} push {{ undercloud_ip }}:8787/tripleo{{ os_version }}/centos-binary-{{ item }}:apex"
when:
- patched_docker_services|length > 0
- item in (response.json)['repositories']|join(" ")
with_items: "{{ patched_docker_services }}"
- - name: Prepare deployment generic docker image file
- shell: >
- {{ stackrc }} && openstack overcloud container image prepare
- --namespace {{ undercloud_ip }}:8787/tripleo{{ os_version }}
- --tag {{ container_tag }}
- -e /usr/share/openstack-tripleo-heat-templates/environments/docker.yaml
- --output-env-file docker-images.yaml
- become: yes
- become_user: stack
- - name: Prepare deployment SDN docker image file
- shell: >
- {{ stackrc }} && openstack overcloud container image prepare
- --namespace {{ undercloud_ip }}:8787/tripleo{{ os_version }}
- --tag {{ container_tag }}
- -e {{ sdn_env_file }}
- --output-env-file sdn-images.yaml
- when: sdn != false
- become: yes
- become_user: stack
- name: Modify Images with Apex tag
replace:
- path: "{{ item[0] }}"
- regexp: "(\\s*Docker.*?:.*?centos-binary-{{ item[1] }}):.*"
+ path: "/home/stack/docker-images.yaml"
+ regexp: "(\\s*Docker.*?:.*?centos-binary-{{ item }}):.*"
replace: '\1:apex'
- with_nested:
- - [ '/home/stack/sdn-images.yaml', '/home/stack/docker-images.yaml']
- - "{{ patched_docker_services }}"
- - name: Pull Ceph docker image
- shell: docker pull {{ ceph_docker_image }}
- become: yes
- - name: Tag Ceph image for local registry
- shell: docker tag {{ ceph_docker_image }} {{ undercloud_ip }}:8787/{{ ceph_docker_image }}
- become: yes
- - name: Push Ceph docker image to local registry
- shell: docker push {{ undercloud_ip }}:8787/{{ ceph_docker_image }}
+ with_items: "{{ patched_docker_services }}"
become: yes
diff --git a/lib/ansible/playbooks/undercloud_aarch64.yml b/lib/ansible/playbooks/undercloud_aarch64.yml
index ddaf1b04..efcbdabd 100644
--- a/lib/ansible/playbooks/undercloud_aarch64.yml
+++ b/lib/ansible/playbooks/undercloud_aarch64.yml
@@ -3,13 +3,12 @@
tasks:
- name: aarch64 configuration
block:
- - shell: yum -y reinstall grub2-efi shim
- copy:
src: /boot/efi/EFI/centos/grubaa64.efi
- dest: /tftpboot/grubaa64.efi
+ dest: /var/lib/config-data/puppet-generated/ironic/var/lib/ironic/tftpboot/grubaa64.efi
remote_src: yes
- file:
- path: /tftpboot/EFI/centos
+ path: /var/lib/config-data/puppet-generated/ironic/var/lib/ironic/tftpboot/EFI/centos
state: directory
mode: 0755
- copy:
@@ -18,32 +17,25 @@
set timeout=5
set hidden_timeout_quiet=false
menuentry "local" {
- configfile (hd0,gpt3)/boot/grub2/grub.cfg
+ configfile /var/lib/ironic/tftpboot/$net_default_mac.conf
}
- dest: /tftpboot/EFI/centos/grub.cfg
+ dest: /var/lib/config-data/puppet-generated/ironic/var/lib/ironic/tftpboot/EFI/centos/grub.cfg
mode: 0644
- - shell: 'openstack-config --set /etc/ironic/ironic.conf pxe uefi_pxe_bootfile_name grubaa64.efi'
- - shell: 'openstack-config --set /etc/ironic/ironic.conf pxe uefi_pxe_config_template \$pybasedir/drivers/modules/pxe_grub_config.template'
-
- - systemd:
- name: openstack-ironic-conductor
- state: restarted
- enabled: yes
- - replace:
- path: /usr/lib/python2.7/site-packages/ironic/drivers/modules/pxe_grub_config.template
- regexp: 'linuxefi'
- replace: 'linux'
- - replace:
- path: /usr/lib/python2.7/site-packages/ironic/drivers/modules/pxe_grub_config.template
- regexp: 'initrdefi'
- replace: 'initrd'
+ - shell: 'sudo crudini --set /var/lib/config-data/puppet-generated/ironic/etc/ironic/ironic.conf pxe pxe_bootfile_name_by_arch aarch64:grubaa64.efi'
+ - shell: 'sudo crudini --set /var/lib/config-data/puppet-generated/ironic/etc/ironic/ironic.conf pxe pxe_config_template_by_arch aarch64:\$pybasedir/drivers/modules/pxe_grub_config.template'
+ - shell: 'docker exec -u root ironic_conductor sed -i "s/initrdefi/initrd/g" /usr/lib/python2.7/site-packages/ironic/drivers/modules/pxe_grub_config.template'
+ - shell: 'docker exec -u root ironic_conductor sed -i "s/linuxefi/linux/g" /usr/lib/python2.7/site-packages/ironic/drivers/modules/pxe_grub_config.template'
- lineinfile:
- path: /tftpboot/map-file
+ path: /var/lib/config-data/puppet-generated/ironic/var/lib/ironic/tftpboot/map-file
insertafter: EOF
state: present
line: ''
- - shell: "echo 'r ^/EFI/centos/grub.cfg-(.*) /tftpboot/pxelinux.cfg/\\1' | sudo tee --append /tftpboot/map-file"
- - shell: "echo 'r ^/EFI/centos/grub.cfg /tftpboot/EFI/centos/grub.cfg' | sudo tee --append /tftpboot/map-file"
+ - shell: "echo 'r ^/EFI/centos/grub.cfg-(.*) /var/lib/ironic/tftpboot/pxelinux.cfg/\\1' | sudo tee --append /var/lib/config-data/puppet-generated/ironic/var/lib/ironic/tftpboot/map-file"
+ - shell: "echo 'r ^/EFI/centos/grub.cfg /var/lib/ironic/tftpboot/EFI/centos/grub.cfg' | sudo tee --append /var/lib/config-data/puppet-generated/ironic/var/lib/ironic/tftpboot/map-file"
+ - shell: "docker restart {{ item }}"
+ with_items:
+ - ironic_conductor
+ - ironic_pxe_tftp
- systemd:
name: xinetd
state: restarted
diff --git a/requirements.txt b/requirements.txt
index 18bd020f..2d7c4199 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,7 +4,7 @@
pbr!=2.1.0,>=2.0.0 # Apache-2.0
libvirt-python
python-iptables
-virtualbmc
+virtualbmc==1.2.0
cryptography
python-ipmi
PyYAML
diff --git a/setup.cfg b/setup.cfg
index c9e42983..4bb9312e 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -32,14 +32,19 @@ packages =
apex
data_files =
share/opnfv-apex/ =
+ build/containers-prepare-parameter.yaml
build/network-environment.yaml
build/opnfv-environment.yaml
build/upstream-environment.yaml
+ build/kubernetes-environment.yaml
build/nics-template.yaml.jinja2
build/csit-environment.yaml
+ build/csit-queens-environment.yaml
+ build/csit-rocky-environment.yaml
build/virtual-environment.yaml
build/baremetal-environment.yaml
build/domain.xml
+ build/build_ovs_nsh.sh
share/opnfv-apex/ansible = lib/ansible/*
share/opnfv-apex/config = config/*
share/opnfv-apex/docs = docs/*
diff --git a/tox.ini b/tox.ini
index 6d53f30a..f69881ed 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist = docs,pep8,pylint,py35
+envlist = docs,docs-linkcheck,pep8,pylint,py35
[testenv]
usedevelop = True
@@ -14,7 +14,7 @@ commands =
--cover-package=apex \
--cover-xml \
--cover-min-percentage 95 \
- apex/tests
+ {posargs}
coverage report
[testenv:pep8]
@@ -24,3 +24,13 @@ commands = flake8 --exclude .build,build --ignore=F401
[testenv:py35]
basepython = python3
+[testenv:docs]
+deps = -rdocs/requirements.txt
+commands =
+ sphinx-build -b html -n -d {envtmpdir}/doctrees ./docs/ {toxinidir}/docs/_build/html
+ echo "Generated docs available in {toxinidir}/docs/_build/html"
+whitelist_externals = echo
+
+[testenv:docs-linkcheck]
+deps = -rdocs/requirements.txt
+commands = sphinx-build -b linkcheck -d {envtmpdir}/doctrees ./docs/ {toxinidir}/docs/_build/linkcheck