# Copyright (c) 2013 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 base64 import config import random import string import time import datetime import xml_code_engine from openstack.common import log as logging log = logging.getLogger(__name__) def update_cf_stack(engine, context, body, template, result=None, error=None, **kwargs): command_dispatcher = context['/commandDispatcher'] def callback(result_value, error_result=None): if result is not None: context[result] = result_value if error_result is not None: if error is not None: context[error] = { 'message': getattr(error_result, 'message', None), 'strerror': getattr(error_result, 'strerror', None), 'timestamp': datetime.datetime.now().isoformat() } failure_handler = body.find('failure') if failure_handler is not None: log.warning("Handling exception in failure block", exc_info=True) engine.evaluate_content(failure_handler, context) return else: log.error("No failure block found for exception", exc_info=True) raise error_result success_handler = body.find('success') if success_handler is not None: engine.evaluate_content(success_handler, context) command_dispatcher.execute( name='cf', command='CreateOrUpdate', template=template, mappings=(kwargs.get('mappings') or {}), arguments=(kwargs.get('arguments') or {}), callback=callback) def delete_cf_stack(engine, context, body, **kwargs): command_dispatcher = context['/commandDispatcher'] def callback(result_value): success_handler = body.find('success') if success_handler is not None: engine.evaluate_content(success_handler, context) command_dispatcher.execute( name='cf', command='Delete', callback=callback) def prepare_user_data(context, hostname, service, unit, template='Default', initFile='init.ps1', **kwargs): settings = config.CONF.rabbitmq with open('data/{0}'.format(initFile)) as init_script_file: with open('data/templates/agent-config/{0}.template'.format( template)) as template_file: init_script = init_script_file.read() template_data = template_file.read() replacements = { '%RABBITMQ_HOST%': settings.host, '%RABBITMQ_PORT%': settings.port, '%RABBITMQ_INPUT_QUEUE%': '-'.join( ['e' + str(context['/dataSource']['id']), str(service), str(unit)]).lower(), '%RESULT_QUEUE%': '-execution-results-e{0}'.format( str(context['/dataSource']['id'])).lower(), '%RABBITMQ_USER%': settings.login, '%RABBITMQ_PASSWORD%': settings.password, '%RABBITMQ_VHOST%': settings.virtual_host, '%RABBITMQ_SSL%': 'true' if settings.ssl else 'false' } template_data = set_config_params(template_data, replacements) init_script = init_script.replace( '%AGENT_CONFIG_BASE64%', base64.b64encode(template_data)) init_script = init_script.replace('%INTERNAL_HOSTNAME%', hostname) init_script = init_script.replace( '%MURANO_SERVER_ADDRESS%', config.CONF.file_server or settings.host) init_script = init_script.replace( '%CA_ROOT_CERT_BASE64%', get_ca_certificate()) return init_script def set_config_params(template_data, replacements): for key in replacements: template_data = template_data.replace(key, str(replacements[key])) return template_data def get_ca_certificate(): ca_file = (config.CONF.rabbitmq.ca_certs or '').strip() if not ca_file: return '' with open(ca_file) as stream: return stream.read().encode('base64') counters = {} def int2base(x, base): digs = string.digits + string.lowercase if x < 0: sign = -1 elif x == 0: return '0' else: sign = 1 x *= sign digits = [] while x: digits.append(digs[x % base]) x /= base if sign < 0: digits.append('-') digits.reverse() return ''.join(digits) def generate_hostname(pattern, service_id, **kwargs): if not pattern: return _generate_random_hostname() elif '#' in pattern: counter = counters.get(service_id) or 1 counters[service_id] = counter + 1 return pattern.replace('#', str(counter), 1) else: return pattern def _generate_random_hostname(): counter = counters.get('') or 1 prefix = ''.join(random.choice(string.lowercase) for _ in range(5)) timestamp = int2base(int(time.time() * 1000), 36)[:8] suffix = int2base(counter, 36) counters[''] = (counter + 1) % 1296 return prefix + timestamp + suffix xml_code_engine.XmlCodeEngine.register_function( update_cf_stack, "update-cf-stack") xml_code_engine.XmlCodeEngine.register_function( delete_cf_stack, "delete-cf-stack") xml_code_engine.XmlCodeEngine.register_function( prepare_user_data, "prepare-user-data") xml_code_engine.XmlCodeEngine.register_function( generate_hostname, "generate-hostname")