fuel-nailgun-extension-iac/fuel_external_git/extension.py

132 lines
4.9 KiB
Python

# 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 copy
import os
import yaml
from fuel_external_git import const
from fuel_external_git import handlers
from fuel_external_git.objects import GitRepo
from fuel_external_git.settings import GitExtensionSettings
from fuel_external_git import utils
from nailgun.extensions import BaseExtension
from nailgun.extensions import BasePipeline
from nailgun.logger import logger
class OpenStackConfigPipeline(BasePipeline):
# TODO(dukov) add cluster remove callback
@classmethod
def process_deployment_for_node(cls, node, node_data):
"""Updating deployment info
Genereate OpenStack configuration hash based on configuration files
stored in git repository associated with a particular environment
Example of configuration extension:
configuration:
nova_config:
DEFAULT/debug:
value: True
DEFAULT/amqp_durable_queues:
value: False
keystone_config:
DEFAULT/default_publisher_id:
ensure: absent
DEFAULT/crypt_strength:
value: 6000
"""
repo = GitRepo.get_by_cluster_id(node.cluster_id)
if not repo:
return node_data
GitRepo.checkout(repo)
repo_path = os.path.join(const.REPOS_DIR, repo.repo_name)
resource_mapping = ExternalGit.ext_settings['resource_mapping']
exts_list = utils.get_file_exts_list(resource_mapping)
global_config = utils.get_config_hash(repo_path,
resource_mapping,
exts=exts_list)
# Read config for overrides
# Overrides file should contain following mapping
# - role:config_file_dir
# - node_id:config_file_dir
# Config options from files for roles should override global
# configs (placed in repo root).
# Config options from files for nodes should override global
# and roles config oprions
overrides_file = os.path.join(repo_path, 'overrides.yaml')
if os.path.exists(overrides_file):
overrides = yaml.load(open(overrides_file))
else:
overrides = {'roles': {}, 'nodes': {}}
override_configs = {}
# ent = roles|nodes
for ent, override in overrides.items():
override_configs[ent] = {}
# key = role_name|node_id
for key, path in override.items():
file_dir = os.path.join(repo_path, path)
config_hash = utils.get_config_hash(file_dir,
resource_mapping,
exts=exts_list)
override_configs[ent][key] = config_hash
logger.debug("Override configs {}".format(override_configs))
common = copy.deepcopy(global_config)
roles = node_data['roles']
uid = node_data['uid']
logger.debug("Node {0} roles {1}".format(uid, roles))
for role in roles:
utils.deep_merge(common,
override_configs['roles'].get(role, {}))
logger.debug("Config Node {0} with roles {1}".format(uid, common))
utils.deep_merge(common,
override_configs['nodes'].get(uid, {}))
node_data['configuration'] = common
logger.info("Node {0} config from git {1}".format(uid, common))
return node_data
# TODO(dukov) Remove decorator extension management is available
@utils.register_extension(u'fuel_external_git')
class ExternalGit(BaseExtension):
name = 'fuel_external_git'
version = '1.0.0'
description = 'Nailgun extension which uses git repo for config files'
urls = [{'uri': r'/clusters/git-repos/?$',
'handler': handlers.GitRepoCollectionHandler},
{'uri':
r'/clusters/(?P<cluster_id>\d+)/git-repos/(?P<obj_id>\d+)?$',
'handler': handlers.GitRepoHandler},
{'uri':
r'/clusters/(?P<env_id>\d+)/git-repos/(?P<obj_id>\d+)/init?$',
'handler': handlers.GitRepoInit}]
data_pipelines = [
OpenStackConfigPipeline,
]
ext_settings = GitExtensionSettings().config
@classmethod
def alembic_migrations_path(cls):
return os.path.join(os.path.dirname(__file__), 'migrations')