summaryrefslogtreecommitdiffstats
path: root/apex/overcloud/deploy.py
diff options
context:
space:
mode:
authorTim Rozet <trozet@redhat.com>2017-12-04 11:20:23 -0500
committerTim Rozet <trozet@redhat.com>2018-03-16 14:51:33 -0400
commitf6dbb3929d904b4d5a9ee01f8270051e29ac1ec3 (patch)
treef2490665c2febe0ebc463714f5375483bfca9710 /apex/overcloud/deploy.py
parenta008f8394e07f1b82d5bf7288f46c63252f6084f (diff)
Enables containerized overcloud deployments
Changes Include: - For upstream deployments, Docker local registry will be updated with latest current RDO containers, regular deployments will use latest stable - Upstream container images will then be patched/modified and then re-uploaded into local docker registry with 'apex' tag - Deployment command modified to deploy with containers - Adds a --no-fetch deployment argument to disable pulling latest from upstream, and instead using what already exists in cache - Moves Undercloud NAT setup to just after undercloud is installed. This provides internet during overcloud install which is now required for upstream container deployments. - Creates loop device for Ceph deployment when no device is provided in deploy settings (for container deployment only) - Updates NIC J2 template to use the new format in OOO since the os-apply-config method is now deprecated in > Queens JIRA: APEX-566 JIRA: APEX-549 Change-Id: I0652c194c059b915a942ac7401936e8f5c69d1fa Signed-off-by: Tim Rozet <trozet@redhat.com>
Diffstat (limited to 'apex/overcloud/deploy.py')
-rw-r--r--apex/overcloud/deploy.py172
1 files changed, 156 insertions, 16 deletions
diff --git a/apex/overcloud/deploy.py b/apex/overcloud/deploy.py
index 33641ed5..0701c188 100644
--- a/apex/overcloud/deploy.py
+++ b/apex/overcloud/deploy.py
@@ -16,10 +16,13 @@ import shutil
import uuid
import struct
import time
+import apex.builders.overcloud_builder as oc_builder
+import apex.builders.common_builder as c_builder
from apex.common import constants as con
from apex.common.exceptions import ApexDeployException
from apex.common import parsers
+from apex.common import utils
from apex.virtual import utils as virt_utils
from cryptography.hazmat.primitives import serialization as \
crypto_serialization
@@ -72,6 +75,21 @@ 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"
+LOSETUP_SERVICE = """[Unit]
+Description=Setup loop devices
+Before=network.target
+
+[Service]
+Type=oneshot
+ExecStart=/sbin/losetup /dev/loop3 /srv/data.img
+ExecStop=/sbin/losetup -d /dev/loop3
+TimeoutSec=60
+RemainAfterExit=yes
+
+[Install]
+WantedBy=multi-user.target
+"""
+
def build_sdn_env_list(ds, sdn_map, env_list=None):
"""
@@ -118,6 +136,25 @@ def build_sdn_env_list(ds, sdn_map, env_list=None):
return env_list
+def get_docker_sdn_file(ds_opts):
+ """
+ Returns docker env file for detected SDN
+ :param ds_opts: deploy options
+ :return: docker THT env file for an SDN
+ """
+ # FIXME(trozet): We assume right now there is only one docker SDN file
+ docker_services = con.VALID_DOCKER_SERVICES
+ sdn_env_list = build_sdn_env_list(ds_opts, SDN_FILE_MAP)
+ for sdn_file in 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(con.THT_DOCKER_ENV_DIR,
+ docker_services[sdn_base])
+ else:
+ return os.path.join(con.THT_DOCKER_ENV_DIR, sdn_base)
+
+
def create_deploy_cmd(ds, ns, inv, tmp_dir,
virtual, env_file='opnfv-environment.yaml',
net_data=False):
@@ -125,26 +162,47 @@ def create_deploy_cmd(ds, ns, inv, tmp_dir,
logging.info("Creating deployment command")
deploy_options = ['network-environment.yaml']
+ ds_opts = ds['deploy_options']
+
+ if ds_opts['containers']:
+ deploy_options.append(os.path.join(con.THT_ENV_DIR,
+ 'docker.yaml'))
+
+ if ds['global_params']['ha_enabled']:
+ if ds_opts['containers']:
+ deploy_options.append(os.path.join(con.THT_ENV_DIR,
+ 'docker-ha.yaml'))
+ else:
+ deploy_options.append(os.path.join(con.THT_ENV_DIR,
+ 'puppet-pacemaker.yaml'))
+
if env_file:
deploy_options.append(env_file)
- ds_opts = ds['deploy_options']
- deploy_options += build_sdn_env_list(ds_opts, SDN_FILE_MAP)
+
+ if ds_opts['containers']:
+ deploy_options.append('docker-images.yaml')
+ sdn_docker_file = get_docker_sdn_file(ds_opts)
+ if sdn_docker_file:
+ deploy_options.append(sdn_docker_file)
+ deploy_options.append('sdn-images.yaml')
+ else:
+ deploy_options += build_sdn_env_list(ds_opts, SDN_FILE_MAP)
for k, v in OTHER_FILE_MAP.items():
if k in ds_opts and ds_opts[k]:
- deploy_options.append(os.path.join(con.THT_ENV_DIR, v))
+ if ds_opts['containers']:
+ deploy_options.append(os.path.join(con.THT_DOCKER_ENV_DIR,
+ "{}.yaml".format(k)))
+ else:
+ deploy_options.append(os.path.join(con.THT_ENV_DIR, v))
if ds_opts['ceph']:
- prep_storage_env(ds, tmp_dir)
+ prep_storage_env(ds, ns, virtual, tmp_dir)
deploy_options.append(os.path.join(con.THT_ENV_DIR,
'storage-environment.yaml'))
if ds_opts['sriov']:
prep_sriov_env(ds, tmp_dir)
- if ds['global_params']['ha_enabled']:
- deploy_options.append(os.path.join(con.THT_ENV_DIR,
- 'puppet-pacemaker.yaml'))
-
if virtual:
deploy_options.append('virtual-environment.yaml')
else:
@@ -190,7 +248,8 @@ def create_deploy_cmd(ds, ns, inv, tmp_dir,
return cmd
-def prep_image(ds, ns, img, tmp_dir, root_pw=None):
+def prep_image(ds, ns, img, tmp_dir, root_pw=None, docker_tag=None,
+ patches=None, upstream=False):
"""
Locates sdn image and preps for deployment.
:param ds: deploy settings
@@ -198,6 +257,9 @@ def prep_image(ds, ns, img, tmp_dir, root_pw=None):
:param img: sdn image
:param tmp_dir: dir to store modified sdn image
: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
@@ -210,6 +272,7 @@ def prep_image(ds, ns, img, tmp_dir, root_pw=None):
ds_opts = ds['deploy_options']
virt_cmds = list()
sdn = ds_opts['sdn_controller']
+ patched_containers = set()
# we need this due to rhbz #1436021
# fixed in systemd-219-37.el7
if sdn is not False:
@@ -298,7 +361,13 @@ def prep_image(ds, ns, img, tmp_dir, root_pw=None):
"/root/nosdn_vpp_rpms/*.rpm"}
])
- if sdn == 'opendaylight':
+ 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"},
@@ -325,6 +394,19 @@ def prep_image(ds, ns, img, tmp_dir, root_pw=None):
{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']
+ oc_builder.inject_opendaylight(
+ odl_version=ds_opts['odl_version'],
+ image=tmp_oc_image,
+ tmp_dir=tmp_dir,
+ uc_ip=undercloud_admin_ip,
+ os_version=ds_opts['os_version'],
+ docker_tag=docker_tag,
+ )
+ if docker_tag:
+ patched_containers = patched_containers.union({'opendaylight'})
if sdn == 'ovn':
virt_cmds.extend([
@@ -334,12 +416,35 @@ def prep_image(ds, ns, img, tmp_dir, root_pw=None):
"*openvswitch*"}
])
- 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 patches:
+ if ds_opts['os_version'] == 'master':
+ branch = ds_opts['os_version']
+ else:
+ branch = "stable/{}".format(ds_opts['os_version'])
+ logging.info('Adding patches to overcloud')
+ patched_containers = patched_containers.union(
+ c_builder.add_upstream_patches(patches,
+ tmp_oc_image, tmp_dir,
+ branch,
+ uc_ip=undercloud_admin_ip,
+ docker_tag=docker_tag))
+ # if containers with ceph, and no ceph device we need to use a
+ # persistent loop device for Ceph OSDs
+ if docker_tag and not ds_opts.get('ceph_device', None):
+ tmp_losetup = os.path.join(tmp_dir, 'losetup.service')
+ with open(tmp_losetup, 'w') as fh:
+ fh.write(LOSETUP_SERVICE)
+ 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: 'mkfs.ext4 -F /srv/data.img'},
+ {con.VIRT_RUN_CMD: 'systemctl daemon-reload'},
+ {con.VIRT_RUN_CMD: 'systemctl enable losetup.service'},
+ ])
virt_utils.virt_customize(virt_cmds, tmp_oc_image)
logging.info("Overcloud image customization complete")
+ return patched_containers
def make_ssh_key():
@@ -541,11 +646,13 @@ def generate_ceph_key():
return base64.b64encode(header + key)
-def prep_storage_env(ds, tmp_dir):
+def prep_storage_env(ds, ns, virtual, tmp_dir):
"""
Creates storage environment file for deployment. Source file is copied by
undercloud playbook to host.
:param ds:
+ :param ns:
+ :param virtual:
:param tmp_dir:
:return:
"""
@@ -572,7 +679,40 @@ def prep_storage_env(ds, tmp_dir):
'utf-8')))
else:
print(line)
- if 'ceph_device' in ds_opts and ds_opts['ceph_device']:
+
+ 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,
+ }
+ if not ds['global_params']['ha_enabled']:
+ ceph_params['CephPoolDefaultSize'] = 1
+
+ if virtual:
+ ceph_params['CephAnsibleExtraConfig'] = {
+ 'centos_package_dependencies': [],
+ 'ceph_osd_docker_memory_limit': '1g',
+ 'ceph_mds_docker_memory_limit': '1g',
+ }
+ ceph_params['CephPoolDefaultPgNum'] = 32
+ if 'ceph_device' in ds_opts and ds_opts['ceph_device']:
+ ceph_device = ds_opts['ceph_device']
+ else:
+ # TODO(trozet): make this DS default after Fraser
+ ceph_device = '/dev/loop3'
+
+ ceph_params['CephAnsibleDisksConfig'] = {
+ 'devices': [ceph_device],
+ 'journal_size': 512,
+ 'osd_scenario': 'collocated'
+ }
+ utils.edit_tht_env(storage_file, 'parameter_defaults', ceph_params)
+ elif 'ceph_device' in ds_opts and ds_opts['ceph_device']:
with open(storage_file, 'a') as fh:
fh.write(' ExtraConfig:\n')
fh.write(" ceph::profile::params::osds:{{{}:{{}}}}\n".format(