123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- # -*- coding: utf-8 -*-
- # 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.
- """
- Installs and configures Puppet
- """
- import sys
- import logging
- import os
- import time
- from packstack.installer import utils
- from packstack.installer import basedefs
- from packstack.installer.exceptions import PuppetError
- from packstack.installer.exceptions import ScriptRuntimeError
- from packstack.installer.utils import split_hosts
- from packstack.modules.common import filtered_hosts
- from packstack.modules.ospluginutils import appendManifestFile
- from packstack.modules.ospluginutils import generateHieraDataFile
- from packstack.modules.ospluginutils import getManifestTemplate
- from packstack.modules.ospluginutils import manifestfiles
- from packstack.modules.puppet import validate_logfile
- from packstack.modules.puppet import scan_logfile
- # ------------- Puppet Packstack Plugin Initialization --------------
- PLUGIN_NAME = "Puppet"
- PLUGIN_NAME_COLORED = utils.color_text(PLUGIN_NAME, 'blue')
- PUPPET_DIR = os.environ.get('PACKSTACK_PUPPETDIR',
- '/usr/share/openstack-puppet/')
- MODULE_DIR = os.path.join(PUPPET_DIR, 'modules')
- def initConfig(controller):
- group = {"GROUP_NAME": "PUPPET",
- "DESCRIPTION": "Puppet Config parameters",
- "PRE_CONDITION": lambda x: 'yes',
- "PRE_CONDITION_MATCH": "yes",
- "POST_CONDITION": False,
- "POST_CONDITION_MATCH": True}
- controller.addGroup(group, [])
- def initSequences(controller):
- puppetpresteps = [
- {'title': 'Clean Up', 'functions': [run_cleanup]},
- ]
- controller.insertSequence("Clean Up", [], [], puppetpresteps, index=0)
- puppetsteps = [
- {'title': 'Preparing Puppet manifests',
- 'functions': [prepare_puppet_modules]},
- {'title': 'Copying Puppet modules and manifests',
- 'functions': [copy_puppet_modules]},
- {'title': 'Applying Puppet manifests',
- 'functions': [apply_puppet_manifest]},
- {'title': 'Finalizing',
- 'functions': [finalize]}
- ]
- controller.addSequence("Puppet", [], [], puppetsteps)
- # ------------------------- helper functions -------------------------
- def wait_for_puppet(currently_running, messages):
- log_len = 0
- twirl = ["-", "\\", "|", "/"]
- while currently_running:
- for hostname, finished_logfile in currently_running:
- log_file = os.path.splitext(os.path.basename(finished_logfile))[0]
- if len(log_file) > log_len:
- log_len = len(log_file)
- if hasattr(sys.stdout, "isatty") and sys.stdout.isatty():
- twirl = twirl[-1:] + twirl[:-1]
- sys.stdout.write(("\rTesting if puppet apply is finished: %s"
- % log_file).ljust(40 + log_len))
- sys.stdout.write("[ %s ]" % twirl[0])
- sys.stdout.flush()
- try:
- # Once a remote puppet run has finished, we retrieve the log
- # file and check it for errors
- local_server = utils.ScriptRunner()
- log = os.path.join(basedefs.PUPPET_MANIFEST_DIR,
- os.path.basename(finished_logfile))
- log = log.replace(".finished", ".log")
- local_server.append('scp -o StrictHostKeyChecking=no '
- '-o UserKnownHostsFile=/dev/null '
- 'root@[%s]:%s %s'
- % (hostname, finished_logfile, log))
- # To not pollute logs we turn of logging of command execution
- local_server.execute(log=False)
- # If we got to this point the puppet apply has finished
- currently_running.remove((hostname, finished_logfile))
- # clean off the last "testing apply" msg
- if hasattr(sys.stdout, "isatty") and sys.stdout.isatty():
- sys.stdout.write(("\r").ljust(45 + log_len))
- except ScriptRuntimeError:
- # the test raises an exception if the file doesn't exist yet
- # TO-DO: We need to start testing 'e' for unexpected exceptions
- time.sleep(3)
- continue
- # check log file for relevant notices
- messages.extend(scan_logfile(log))
- # check the log file for errors
- sys.stdout.write('\r')
- try:
- validate_logfile(log)
- state = utils.state_message('%s:' % log_file, 'DONE', 'green')
- sys.stdout.write('%s\n' % state)
- sys.stdout.flush()
- except PuppetError:
- state = utils.state_message('%s:' % log_file, 'ERROR', 'red')
- sys.stdout.write('%s\n' % state)
- sys.stdout.flush()
- raise
- # -------------------------- step functions --------------------------
- def run_cleanup(config, messages):
- localserver = utils.ScriptRunner()
- localserver.append("rm -rf %s/*pp" % basedefs.PUPPET_MANIFEST_DIR)
- localserver.execute()
- def copy_puppet_modules(config, messages):
- os_modules = ' '.join(('aodh', 'apache', 'ceilometer', 'certmonger',
- 'cinder', 'concat', 'firewall', 'glance',
- 'gnocchi', 'heat', 'horizon', 'inifile', 'ironic',
- 'keystone', 'magnum', 'manila', 'memcached', 'mongodb',
- 'mysql', 'neutron', 'nova', 'nssdb', 'openstack',
- 'openstacklib', 'oslo', 'packstack', 'panko', 'rabbitmq',
- 'redis', 'remote', 'rsync', 'sahara', 'ssh',
- 'stdlib', 'swift', 'sysctl', 'tempest', 'trove',
- 'vcsrepo', 'vswitch', 'xinetd', ))
- # write puppet manifest to disk
- manifestfiles.writeManifests()
- # write hieradata file to disk
- generateHieraDataFile()
- server = utils.ScriptRunner()
- for hostname in filtered_hosts(config):
- host_dir = config['HOST_DETAILS'][hostname]['tmpdir']
- # copy hiera defaults.yaml file
- server.append("cd %s" % basedefs.HIERADATA_DIR)
- server.append("tar --dereference -cpzf - ../hieradata | "
- "ssh -o StrictHostKeyChecking=no "
- "-o UserKnownHostsFile=/dev/null "
- "root@%s tar -C %s -xpzf -" % (hostname, host_dir))
- # copy Packstack manifests
- server.append("cd %s/puppet" % basedefs.DIR_PROJECT_DIR)
- server.append("cd %s" % basedefs.PUPPET_MANIFEST_DIR)
- server.append("tar --dereference -cpzf - ../manifests | "
- "ssh -o StrictHostKeyChecking=no "
- "-o UserKnownHostsFile=/dev/null "
- "root@%s tar -C %s -xpzf -" % (hostname, host_dir))
- # copy resources
- resources = config.get('RESOURCES', {})
- for path, localname in resources.get(hostname, []):
- server.append("scp -o StrictHostKeyChecking=no "
- "-o UserKnownHostsFile=/dev/null "
- "%s root@[%s]:%s/resources/%s" %
- (path, hostname, host_dir, localname))
- # copy Puppet modules required by Packstack
- server.append("cd %s" % MODULE_DIR)
- server.append("tar --dereference -cpzf - %s | "
- "ssh -o StrictHostKeyChecking=no "
- "-o UserKnownHostsFile=/dev/null "
- "root@%s tar -C %s -xpzf -" %
- (os_modules, hostname,
- os.path.join(host_dir, 'modules')))
- server.execute()
- def apply_puppet_manifest(config, messages):
- if config.get("DRY_RUN"):
- return
- currently_running = []
- lastmarker = None
- loglevel = ''
- logcmd = False
- if logging.root.level <= logging.DEBUG:
- loglevel = '--debug'
- logcmd = True
- for manifest, marker in manifestfiles.getFiles():
- # if the marker has changed then we don't want to proceed until
- # all of the previous puppet runs have finished
- if lastmarker is not None and lastmarker != marker:
- wait_for_puppet(currently_running, messages)
- lastmarker = marker
- for hostname in filtered_hosts(config):
- if "%s_" % hostname not in manifest:
- continue
- host_dir = config['HOST_DETAILS'][hostname]['tmpdir']
- print("Applying %s" % manifest)
- server = utils.ScriptRunner(hostname)
- man_path = os.path.join(config['HOST_DETAILS'][hostname]['tmpdir'],
- basedefs.PUPPET_MANIFEST_RELATIVE,
- manifest)
- running_logfile = "%s.running" % man_path
- finished_logfile = "%s.finished" % man_path
- currently_running.append((hostname, finished_logfile))
- server.append("touch %s" % running_logfile)
- server.append("chmod 600 %s" % running_logfile)
- server.append("export PACKSTACK_VAR_DIR=%s" % host_dir)
- cmd = ("( flock %s/ps.lock "
- "puppet apply %s --modulepath %s/modules %s > %s "
- "2>&1 < /dev/null ; "
- "mv %s %s ) > /dev/null 2>&1 < /dev/null &"
- % (host_dir, loglevel, host_dir, man_path, running_logfile,
- running_logfile, finished_logfile))
- server.append(cmd)
- server.execute(log=logcmd)
- # wait for outstanding puppet runs before exiting
- wait_for_puppet(currently_running, messages)
- def prepare_puppet_modules(config, messages):
- network_hosts = split_hosts(config['CONFIG_NETWORK_HOSTS'])
- compute_hosts = split_hosts(config['CONFIG_COMPUTE_HOSTS'])
- manifestdata = getManifestTemplate("controller")
- manifestfile = "%s_controller.pp" % config['CONFIG_CONTROLLER_HOST']
- appendManifestFile(manifestfile, manifestdata, marker='controller')
- for host in network_hosts:
- manifestdata = getManifestTemplate("network")
- manifestfile = "%s_network.pp" % host
- appendManifestFile(manifestfile, manifestdata, marker='network')
- for host in compute_hosts:
- manifestdata = getManifestTemplate("compute")
- manifestfile = "%s_compute.pp" % host
- appendManifestFile(manifestfile, manifestdata, marker='compute')
- def finalize(config, messages):
- for hostname in filtered_hosts(config):
- server = utils.ScriptRunner(hostname)
- server.append("installed=$(rpm -q kernel --last | head -n1 | "
- "sed 's/kernel-\([a-z0-9\.\_\-]*\).*/\\1/g')")
- server.append("loaded=$(uname -r | head -n1)")
- server.append('[ "$loaded" == "$installed" ]')
- try:
- rc, out = server.execute()
- except ScriptRuntimeError:
- messages.append('Because of the kernel update the host %s '
- 'requires reboot.' % hostname)
|