heat-agents/heat-config/bin/heat-config-notify

180 lines
5.6 KiB
Python
Executable File

#!/usr/bin/env 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 json
import logging
import os
import sys
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
try:
from heatclient import client as heatclient
except ImportError:
heatclient = None
try:
from keystoneclient.v3 import client as ksclient
except ImportError:
ksclient = None
try:
from zaqarclient.queues.v1 import client as zaqarclient
except ImportError:
zaqarclient = None
MAX_RESPONSE_SIZE = 950000
def init_logging():
log = logging.getLogger('heat-config-notify')
handler = logging.StreamHandler(sys.stderr)
handler.setFormatter(
logging.Formatter(
'[%(asctime)s] (%(name)s) [%(levelname)s] %(message)s'))
log.addHandler(handler)
log.setLevel('DEBUG')
return log
def trim_response(response, trimmed_values=None):
"""Trim selected values from response.
Makes given response smaller or the same size as MAX_RESPONSE_SIZE by
trimming given trimmed_values from response dict from the left side
(beginning). Returns trimmed and serialized JSON response itself.
"""
trimmed_values = trimmed_values or ('deploy_stdout', 'deploy_stderr')
str_response = json.dumps(response, ensure_ascii=True)
len_total = len(str_response)
offset = MAX_RESPONSE_SIZE - len_total
if offset >= 0:
return str_response
offset = abs(offset)
for key in trimmed_values:
len_value = len(response[key])
cut = int(round(float(len_value) / len_total * offset))
response[key] = response[key][cut:]
str_response = json.dumps(response, ensure_ascii=True, encoding='utf-8')
return str_response
def main(argv=sys.argv, stdin=sys.stdin):
log = init_logging()
usage = ('Usage:\n heat-config-notify /path/to/config.json '
'< /path/to/signal_data.json')
if len(argv) < 2:
log.error(usage)
return 1
try:
signal_data = json.load(stdin)
except ValueError:
log.warn('No valid json found on stdin')
signal_data = {}
conf_file = argv[1]
if not os.path.exists(conf_file):
log.error('No config file %s' % conf_file)
log.error(usage)
return 1
c = json.load(open(conf_file))
iv = dict((i['name'], i['value']) for i in c['inputs'])
if 'deploy_signal_id' in iv:
sigurl = iv.get('deploy_signal_id')
sigverb = iv.get('deploy_signal_verb', 'POST')
log.debug('Signaling to %s via %s' % (sigurl, sigverb))
# we need to trim log content because Heat response size is limited
# by max_json_body_size = 1048576
str_signal_data = trim_response(signal_data)
session = requests.Session()
# Retry if connection issues occur or the service is returning a 5xx
retry = Retry(
total=10,
read=10,
connect=10,
backoff_factor=0.5,
status_forcelist=(500, 502, 503, 504)
)
adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)
if sigverb == 'PUT':
r = session.put(sigurl, data=str_signal_data,
headers={'content-type': 'application/json'})
else:
r = session.post(sigurl, data=str_signal_data,
headers={'content-type': 'application/json'})
log.debug('Response %s ' % r)
if 'deploy_queue_id' in iv:
queue_id = iv.get('deploy_queue_id')
log.debug('Signaling to queue %s' % (queue_id,))
ks = ksclient.Client(
auth_url=iv['deploy_auth_url'],
user_id=iv['deploy_user_id'],
password=iv['deploy_password'],
project_id=iv['deploy_project_id'])
endpoint = ks.service_catalog.url_for(
service_type='messaging', endpoint_type='publicURL')
conf = {
'auth_opts': {
'backend': 'keystone',
'options': {
'os_auth_token': ks.auth_token,
'os_project_id': iv['deploy_project_id'],
}
}
}
cli = zaqarclient.Client(endpoint, conf=conf, version=1.1)
queue = cli.queue(queue_id)
r = queue.post({'body': signal_data, 'ttl': 600})
log.debug('Response %s ' % r)
elif 'deploy_auth_url' in iv:
ks = ksclient.Client(
auth_url=iv['deploy_auth_url'],
user_id=iv['deploy_user_id'],
password=iv['deploy_password'],
project_id=iv['deploy_project_id'])
endpoint = ks.service_catalog.url_for(
service_type='orchestration', endpoint_type='publicURL')
log.debug('Signalling to %s' % endpoint)
heat = heatclient.Client(
'1', endpoint, token=ks.auth_token)
r = heat.resources.signal(
iv.get('deploy_stack_id'),
iv.get('deploy_resource_name'),
data=signal_data)
log.debug('Response %s ' % r)
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv, sys.stdin))