solar/solar/utils.py

192 lines
4.4 KiB
Python

# Copyright 2015 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 glob
import io
import json
import logging
import os
import re
import subprocess
import urlparse
import uuid
from bunch import Bunch
from jinja2 import Environment
import yaml
logger = logging.getLogger(__name__)
def to_json(data):
return json.dumps(data)
def to_pretty_json(data):
return json.dumps(data, indent=4)
def communicate(command, data):
popen = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE,
stderr=subprocess.PIPE)
return popen.communicate(input=data)[0]
def execute(command, shell=False):
popen = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=shell)
out, err = popen.communicate()
return popen.returncode, out, err
# Configure jinja2 filters
jinja_env_with_filters = Environment()
jinja_env_with_filters.filters['to_json'] = to_json
jinja_env_with_filters.filters['to_pretty_json'] = to_pretty_json
def create_dir(dir_path):
logger.debug(u'Creating directory %s', dir_path)
if not os.path.isdir(dir_path):
os.makedirs(dir_path)
def yaml_load(file_path):
with io.open(file_path) as f:
result = yaml.load(f)
return result
def yaml_dump(yaml_data):
return yaml.safe_dump(yaml_data, default_flow_style=False)
def write_to_file(data, file_path):
with open(file_path, 'w') as f:
f.write(data)
def yaml_dump_to(data, file_path):
write_to_file(yaml_dump(data), file_path)
def find_by_mask(mask):
for file_path in glob.glob(mask):
yield os.path.abspath(file_path)
def load_by_mask(mask):
result = []
for file_path in find_by_mask(mask):
result.append(yaml_load(file_path))
return result
def generate_uuid():
return str(uuid.uuid4())
def render_template(template_path, **params):
with io.open(template_path) as f:
temp = jinja_env_with_filters.from_string(f.read())
return temp.render(**params)
def ext_encoder(fpath):
ext = os.path.splitext(os.path.basename(fpath))[1].strip('.')
if ext in ['json']:
return json
elif ext in ['yaml', 'yaml']:
return yaml
raise Exception('Unknown extension {}'.format(ext))
def load_file(fpath):
encoder = ext_encoder(fpath)
try:
with open(fpath) as f:
return encoder.load(f)
except IOError:
return {}
def read_config():
CONFIG_FILE = os.environ.get('CONFIG_FILE') or '/vagrant/config.yaml'
return load_file(CONFIG_FILE)
def read_config_file(key):
fpath = read_config()[key]
return load_file(fpath)
def save_to_config_file(key, data):
fpath = read_config()[key]
with open(fpath, 'w') as f:
encoder = ext_encoder(fpath)
encoder.dump(data, f)
def solar_map(funct, args, **kwargs):
return map(funct, args)
def get_local():
import threading
return threading.local
def parse_database_conn(name):
regex = re.compile(r'''
(?P<mode>[\w\+]+)://
(?:
(?P<username>[^:/]*)
(?::(?P<password>[^/]*))?
@)?
(?:
(?P<host>[^/:]*)
(?::(?P<port>[^/]*))?
)?
(?:/(?P<database>.*))?
''', re.X)
if not name:
raise Exception("Database connection string is empty, "
"please ensure that you set config path correctly")
if '?' in name:
name, opts = name.split('?', 1)
opts = dict(urlparse.parse_qsl(opts))
else:
opts = {}
m = regex.match(name)
if m is not None:
groups = m.groupdict()
return Bunch(groups), Bunch(opts)
else:
raise Exception("Invalid database connection string: %r "
"It should be in RFC 1738 format. " % name)