fuel-web/nailgun/nailgun/orchestrator/tasks_templates.py

234 lines
7.6 KiB
Python

# -*- coding: utf-8 -*-
# Copyright 2014 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
from oslo.serialization import jsonutils
import requests
import six
from nailgun.logger import logger
from nailgun.settings import settings
from nailgun.utils import debian
def make_upload_task(uids, data, path):
return {
'type': 'upload_file',
'uids': uids,
'parameters': {
'path': path,
'data': data}}
def make_ubuntu_sources_task(uids, repo):
sources_content = 'deb {uri} {suite} {section}'.format(**repo)
sources_path = '/etc/apt/sources.list.d/{name}.list'.format(
name=repo['name'])
return make_upload_task(uids, sources_content, sources_path)
def make_ubuntu_preferences_task(uids, repo):
# NOTE(ikalnitsky): In order to implement the proper pinning,
# we have to download and parse the repo's "Release" file.
# Generally, that's not a good idea to make some HTTP request
# from Nailgun, but taking into account that this task
# will be executed in uWSGI's mule worker we can skip this
# rule, because proper pinning is more valuable thing right now.
template = '\n'.join([
'Package: *',
'Pin: release {conditions}',
'Pin-Priority: {priority}'])
preferences_content = []
try:
release = debian.get_release_file(repo, retries=3)
release = debian.parse_release_file(release)
pin = debian.get_apt_preferences_line(release)
except requests.exceptions.HTTPError as exc:
logger.error("Failed to fetch 'Release' file due to '%s'. "
"The apt preferences won't be applied for repo '%s'.",
six.text_type(exc), repo['name'])
return None
except Exception:
logger.exception("Failed to parse 'Release' file.")
return None
# if sections are detected (non-flat repo) create pinning per
# sections; otherwise - create just one pin for the entire repo
if repo['section']:
for section in repo['section'].split():
preferences_content.append(template.format(
conditions='{0},c={1}'.format(pin, section),
priority=repo['priority']))
else:
preferences_content.append(template.format(
conditions=pin,
priority=repo['priority']))
preferences_content = '\n\n'.join(preferences_content)
preferences_path = '/etc/apt/preferences.d/{0}.pref'.format(repo['name'])
return make_upload_task(uids, preferences_content, preferences_path)
def make_ubuntu_apt_disable_ipv6(uids):
config_content = 'Acquire::ForceIPv4 "true";\n'
config_path = '/etc/apt/apt.conf.d/05disable-ipv6'
return make_upload_task(uids, config_content, config_path)
def make_ubuntu_unauth_repos_task(uids):
# NOTE(kozhukalov): This task is to allow installing packages
# from unauthenticated repositories. Apt has special
# mechanism for this.
config_content = 'APT::Get::AllowUnauthenticated 1;\n'
config_path = '/etc/apt/apt.conf.d/02mirantis-allow-unsigned'
return make_upload_task(uids, config_content, config_path)
def make_centos_repo_task(uids, repo):
repo_content = [
'[{name}]',
'name=Plugin {name} repository',
'baseurl={uri}',
'gpgcheck=0',
]
if repo.get('priority'):
repo_content.append('priority={priority}')
repo_content = '\n'.join(repo_content).format(**repo)
repo_path = '/etc/yum.repos.d/{name}.repo'.format(name=repo['name'])
return make_upload_task(uids, repo_content, repo_path)
def make_sync_scripts_task(uids, src, dst):
return {
'type': 'sync',
'uids': uids,
'parameters': {
'src': src,
'dst': dst}}
def make_shell_task(uids, task):
return {
'type': 'shell',
'uids': uids,
'parameters': {
'cmd': task['parameters']['cmd'],
'timeout': task['parameters']['timeout'],
'retries': task['parameters'].get(
'retries', settings.SHELL_TASK_RETRIES),
'interval': task['parameters'].get(
'interval', settings.SHELL_TASK_INTERVAL),
'cwd': task['parameters'].get('cwd', '/')}}
def make_yum_clean(uids):
task = {
'parameters': {
'cmd': 'yum clean all',
'timeout': 180}}
return make_shell_task(uids, task)
def make_apt_update_task(uids):
task = {
'parameters': {
'cmd': 'apt-get update',
'timeout': 180}}
return make_shell_task(uids, task)
def make_puppet_task(uids, task):
return {
'type': 'puppet',
'uids': uids,
'parameters': {
'puppet_manifest': task['parameters']['puppet_manifest'],
'puppet_modules': task['parameters']['puppet_modules'],
'timeout': task['parameters']['timeout'],
'cwd': task['parameters'].get('cwd', '/')}}
def make_generic_task(uids, task):
return {
'type': task['type'],
'uids': uids,
'fail_on_error': task.get('fail_on_error', True),
'parameters': task['parameters']
}
def make_reboot_task(uids, task):
return {
'type': 'reboot',
'uids': uids,
'parameters': {
'timeout': task['parameters']['timeout']}}
def make_provisioning_images_task(uids, repos, provision_data, cid):
conf = {
'repos': repos,
'image_data': provision_data['image_data'],
'codename': provision_data['codename'],
'output': settings.PROVISIONING_IMAGES_PATH,
}
# TODO(ikalnitsky):
# Upload settings before using and pass them as command line argument.
conf = jsonutils.dumps(conf)
return make_shell_task(uids, {
'parameters': {
'cmd': ("fa_build_image "
"--log-file /var/log/fuel-agent-env-{0}.log "
"--data_driver nailgun_build_image "
"--input_data '{1}'").format(cid, conf),
'timeout': settings.PROVISIONING_IMAGES_BUILD_TIMEOUT,
'retries': 1}})
def make_download_debian_installer_task(
uids, repos, installer_kernel, installer_initrd):
# NOTE(kozhukalov): This task is going to go away by 7.0
# because we going to get rid of classic way of provision.
# NOTE(ikalnitsky): We can't use urljoin here because it works
# pretty bad in cases when 'uri' doesn't have a trailing slash.
remote_kernel = os.path.join(
repos[0]['uri'], installer_kernel['remote_relative'])
remote_initrd = os.path.join(
repos[0]['uri'], installer_initrd['remote_relative'])
return make_shell_task(uids, {
'parameters': {
'cmd': ('LOCAL_KERNEL_FILE={local_kernel} '
'LOCAL_INITRD_FILE={local_initrd} '
'download-debian-installer '
'{remote_kernel} {remote_initrd}').format(
local_kernel=installer_kernel['local'],
local_initrd=installer_initrd['local'],
remote_kernel=remote_kernel,
remote_initrd=remote_initrd),
'timeout': 10 * 60,
'retries': 1}})