initial commit

add sources
This commit is contained in:
Julio Montes
2015-12-14 11:29:34 -06:00
parent 16892cf6a4
commit 9aa500cb9d
83 changed files with 5107 additions and 26 deletions
+22
View File
@@ -0,0 +1,22 @@
.coverage
cover/
.testrepository
subunit.log
.venv
*.pyc
.idea
*.sw?
*.egg?
*~
.tox
ChangeLog
build
dist
clearstack.egg-info
clearstack/versioninfo
# Development environment files
.project
.pydevproject
.DS_Store
covhtml/
tags
+4
View File
@@ -0,0 +1,4 @@
Alberto Murillo <alberto.murillo.silva@intel.com>
Julio Montes <julio.montes@intel.com>
Obed Muñoz <obed.n.munoz@intel.com>
Victor Morales <victor.morales@intel.com>
+55
View File
@@ -0,0 +1,55 @@
Clearstack Style Commandments
==============================
- Step 1: Read the OpenStack Style Commandments
http://docs.openstack.org/developer/hacking/
- Step 2: Read on
Docstrings
----------
Docstrings should ONLY use triple-double-quotes (``"""``)
Single-line docstrings should NEVER have extraneous whitespace
between enclosing triple-double-quotes.
Deviation! Sentence fragments do not have punctuation. Specifically in the
command classes the one line docstring is also the help string for that
command and those do not have periods.
"""A one line docstring looks like this"""
Calling Methods
---------------
Deviation! When breaking up method calls due to the 79 char line length limit,
use the alternate 4 space indent. With the first argument on the succeeding
line all arguments will then be vertically aligned. Use the same convention
used with other data structure literals and terminate the method call with
the last argument line ending with a comma and the closing paren on its own
line indented to the starting line level.
unnecessarily_long_function_name(
'string one',
'string two',
kwarg1=constants.ACTIVE,
kwarg2=['a', 'b', 'c'],
)
Python 3.x Compatibility
------------------------
Clearstack is only Python 3.4 compatible. Common guidelines:
* print statements are functions: print statements should be converted
to an appropriate log or other output mechanism.
* Use six where applicable: x.iteritems is converted to six.iteritems(x)
for example
Running Tests
-------------
The testing system is based on a combination of tox and testr. If you just
want to run the whole suite, run `tox` and all will be fine. However, if
you'd like to dig in a bit more, you might want to learn some things about
testr itself. A basic walkthrough for OpenStack can be found at
http://wiki.openstack.org/testr
+1 -26
View File
@@ -1,3 +1,4 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
@@ -174,29 +175,3 @@
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
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.
+17
View File
@@ -0,0 +1,17 @@
Metadata-Version: 1.1
Name: clearstack
Version: 1.1.4
Summary: Tool for set up an Openstack environment
Home-page:
Author: Alberto Murillo, Julio Montes, Obed Muñoz, Victor Morales
License: Apache-2.0
Description: Tool for set up an Openstack environment
Keywords: Openstack
Platform: Unix
Classifier: Environment :: OpenStack
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.3
+32
View File
@@ -0,0 +1,32 @@
A tool to deploy components of Openstack on multiple servers with Clear Linux* Project for Intel Architecture installed
====
Contents:
1) Description of this project
2) Compiling, prerequisites
3) Bugs and feedback?
====
====
2. Compiling
$ pip3 install -r requirements-py3.txt
$ python3 setup.py install
====
3. Bugs, feedback, contact
clearstack is hosted on github. You can find releases, an issue
tracker and git sources on github.com/clearlinux/clearstack. For
mailing lists, subscribe to dev@lists.clearlinux.org (via
lists.clearlinux.org).
This project has many contributors. Not all may be mentioned in the
AUTHORS file.
+1
View File
@@ -0,0 +1 @@
[python: **.py]
+22
View File
@@ -0,0 +1,22 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Julio Montes <julio.montes@intel.com>
#
# 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 pbr.version
__version__ = pbr.version.VersionInfo('clearstack').version_string()
+65
View File
@@ -0,0 +1,65 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Julio Montes <julio.montes@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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 os
import configparser
from clearstack.controller import Controller
from clearstack.common.util import LOG
from clearstack.common.singleton import Singleton
@Singleton
class AnswerFile:
def generate(self, file, variables_cmd):
with open(file, "w") as f:
f.write("[general]\n\n")
for group in Controller.get().get_all_groups():
for argument in group.get_all_arguments():
f.write("# {0}\n".format(argument.description))
value = variables_cmd.get(argument.conf_name,
argument.default_value)
f.write("{0}={1}\n\n".format(argument.conf_name, value))
def read(self, file, variables_cmd):
conf = Controller.get().CONF
config = configparser.RawConfigParser()
config.optionxform = str
if not os.path.isfile(file):
raise IOError("file {0} not found".format(file))
""" Validate option in answer file"""
config.read(file)
if not config.has_section('general'):
raise KeyError("answer file {0} doesn't have general"
" section".format(file))
conf_file = dict(config['general'])
conf_file.update(variables_cmd) # override variables
conf.update(conf_file)
try:
Controller.get().validate_groups(conf_file)
except Exception as e:
raise e
all_args = Controller.get().get_all_arguments()
for non_supported in (set(conf_file) - set(all_args)):
LOG.warn("clearstack: variable {0} is not"
" supported yet".format(non_supported))
+37
View File
@@ -0,0 +1,37 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Julio Montes <julio.montes@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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.
#
class Argument(object):
def __init__(self, cmd_option, description,
conf_name, default_value, validators=[],
options=None):
self.cmd_option = cmd_option
self.description = description
self.conf_name = conf_name
self.default_value = default_value
self.validators = validators
self.option_list = options
def validate(self, option):
for validator in self.validators:
try:
validator(option)
except ValueError as e:
raise ValueError("{0}: {1}".format(self.conf_name, str(e)))
View File
+35
View File
@@ -0,0 +1,35 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Julio Montes <julio.montes@intel.com>
#
# 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.
#
class Singleton:
def __init__(self, decorated):
self._decorated = decorated
def get(self):
try:
return self._instance
except AttributeError:
self._instance = self._decorated()
return self._instance
def __call__(self):
raise TypeError('Singletons must be accessed through `Get()`.')
def __instancecheck__(self, inst):
return isinstance(inst, self._decorated)
+43
View File
@@ -0,0 +1,43 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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 os
from common import util
from common.util import LOG
class Client():
def install(bundle):
if not os.path.isfile("/usr/share/clear/bundles/" + str(bundle)) and \
not os.path.isfile("/usr/share/clear/bundles/"
"openstack-all-in-one"):
LOG.info("Installing {0} bundle".format(bundle))
cmd = "clr_bundle_add -V {0}".format(bundle)
if(os.path.isfile("/bin/swupd")):
cmd = "swupd bundle-add -V {0}".format(bundle)
try:
stdout, stderr = util.run_command(cmd)
if stderr:
LOG.error("swupd bundle-add: {0}\n{1}"
.format(stdout, stderr))
except Exception:
LOG.error("clearstack: cannot install"
" {0} bundle".format(bundle))
+210
View File
@@ -0,0 +1,210 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
#
# 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 os
import socket
import subprocess
import configparser
import netifaces
import ipaddress
import logging
from errno import EACCES, EPERM, ENOENT
HOST_LOG_DIR = '/var/log/clearstack'
HOST_LOG_FILE = "{0}/clearstack.log".format(HOST_LOG_DIR)
LOG_DIR = '/var/log/clearstack'
if os.geteuid() != 0:
LOG_DIR = '/tmp/log/clearstack'
LOG_FILE = "{0}/clearstack.log".format(LOG_DIR)
LOG = logging.getLogger("Clearstack")
def _print_error_message(self, e, file_name):
# PermissionError
if e.errno == EPERM or e.errno == EACCES:
print("PermissionError error({0}): {1} for:\n{2}".format(e.errno,
e.strerror, file_name))
# FileNotFoundError
elif e.errno == ENOENT:
print("FileNotFoundError error({0}): {1} as:\n{2}".format(e.errno,
e.strerror, file_name))
elif IOError:
print("I/O error({0}): {1} as:\n{2}".format(e.errno, e.strerror,
file_name))
elif OSError:
print("OS error({0}): {1} as:\n{2}".format(e.errno, e.strerror,
file_name))
def setup_debugging(debug, is_remote_host=True):
if not os.path.isdir(LOG_DIR):
os.makedirs(LOG_DIR)
try:
logging.basicConfig(filename=LOG_FILE,
format='%(message)s',
level=logging.INFO)
except (IOError, OSError) as e:
_print_error_message(e, LOG_FILE)
''' paramiko detects all output as error (stderr)'''
''' if it is a remote host redirect output to log file '''
if not is_remote_host:
sh = logging.StreamHandler()
sh.setLevel(logging.INFO)
LOG.addHandler(sh)
if debug:
LOG.setLevel(logging.DEBUG)
def run_command(command, stdin=None, environ=None, debug=True):
"""Returns (stdout, stderr), raises error on non-zero return code"""
if environ is None:
env = None
else:
env = os.environ.copy()
env.update(environ)
if debug: # to avoid show passwords
LOG.debug("command: %s", command)
proc = subprocess.Popen(['bash', '-c', command],
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE, env=env)
stdout, stderr = proc.communicate()
if proc.returncode and stderr:
raise Exception("Error running: {0}\n{1}"
.format(command, stderr.decode("utf-8")))
return stdout, stderr
def str2bool(value):
return value.lower() in ("yes", "true", "t", "1", "y")
def write_config(file, data):
directory = os.path.dirname(file)
if not os.path.isdir(directory):
os.makedirs(directory)
config = configparser.RawConfigParser(allow_no_value=True)
if os.path.isfile(file):
config.read(file)
config.read_string(data)
with open(file, 'w') as f:
config.write(f)
def write_properties(file, data):
directory = os.path.dirname(file)
if not os.path.isdir(directory):
os.makedirs(directory)
if os.path.isfile(file):
with open(file, 'r') as f:
for l in f.readlines():
key, value = [x.strip() for x in l.split('=')]
data[key] = value
output = ""
for key, value in data.items():
output += "%s = %s\n" % (key, value)
with open(file, 'w') as f:
f.write(output)
def get_option(file, section, option):
config = configparser.RawConfigParser(allow_no_value=True)
config.read(file)
return config[section][option]
def delete_option(file, section, option=None):
config = configparser.RawConfigParser(allow_no_value=True)
config.read(file)
if option:
config.remove_option(section, option)
else:
config.remove_section(section)
with open(file, 'w') as f:
config.write(f)
# write in file if not exist the line
def write_in_file_ine(file, data):
with open(file, 'a+') as f:
f.seek(0)
if not any(data == x.rstrip('\r\n') for x in f):
f.write(data + '\n')
return True
return False
def get_dns():
with open('/etc/resolv.conf', 'r') as f:
return [l.split(' ')[1].strip() for l in f.readlines()
if l.startswith('nameserver')]
def get_netmask():
interface = get_net_interface()
mask = netifaces.ifaddresses(interface)[netifaces.AF_INET][0]['netmask']
return ipaddress.IPv4Network('0.0.0.0/%s' % mask).prefixlen
def get_gateway():
return netifaces.gateways()['default'][netifaces.AF_INET][0]
def get_net_interface():
return (netifaces.gateways())['default'][netifaces.AF_INET][1]
def get_ip():
interface = get_net_interface()
return netifaces.ifaddresses(interface)[netifaces.AF_INET][0]['addr']
def is_localhost(host):
return host == "localhost" or host == "127.0.0.1" or \
host == socket.gethostname() or host == get_ip()
def has_localhost(hosts):
for host in hosts:
if is_localhost(host):
return True
return False
def remove_localhost(hosts):
for host in hosts.copy():
if is_localhost(host):
hosts.remove(host)
def ensure_directory(dir):
if not os.path.exists(dir):
os.makedirs(dir)
def link_file(source, target):
dir = os.path.dirname(target)
ensure_directory(dir)
if os.path.exists(target):
os.remove(target)
os.symlink(source, target)
+89
View File
@@ -0,0 +1,89 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Julio Montes <julio.montes@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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.
#
from clearstack.group import Group
from clearstack.sequence import Sequence
from clearstack.common.singleton import Singleton
DEBUG = False
@Singleton
class Controller:
CONF = {}
_plugins = []
_groups = []
_sequences = []
def add_sequence(self, desc, function, args=None):
self._sequences.append(Sequence(desc, function, args))
def run_all_sequences(self):
for seq in self._sequences:
try:
seq.run()
except Exception as e:
raise e
def add_plugin(self, plugin):
self._plugins.append(plugin)
def get_all_plugins(self):
return self._plugins
def add_group(self, name, args):
self._groups.append(Group(name, args))
def get_all_groups(self):
return self._groups
def get_all_arguments(self):
"""Get a list of the configuration argument loaded"""
arguments = []
for group in self._groups:
arguments.extend([argument.conf_name
for argument in group.get_all_arguments()])
return arguments
def remove_argument(self, group_name, conf_name):
for group in self._groups:
if group.group_name == group_name:
for arg in group.arguments:
if arg.conf_name == conf_name:
group.arguments.remove(arg)
return True
return False
def remove_validators(self, conf_names):
for group in self._groups:
for arg in group.arguments:
if arg.conf_name in conf_names:
arg.validators.clear()
def validate_groups(self, conf_values):
""" Load validation functions, in order to check
the values in the answer file """
arguments = {}
for group in self._groups:
for arg in group.get_all_arguments():
try:
arg.validate(conf_values[arg.conf_name])
except Exception as e:
raise Exception("{0}: {1}".format(arg.conf_name, str(e)))
return arguments
+29
View File
@@ -0,0 +1,29 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Julio Montes <julio.montes@intel.com>
#
# 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.
#
class Group(object):
def __init__(self, group_name, arguments):
self.group_name = group_name
self.arguments = arguments
def get_group_name(self):
return self.group_name
def get_all_arguments(self):
return self.arguments
View File
View File
+58
View File
@@ -0,0 +1,58 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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 socket
from modules.keystone import Keystone
from modules.openstack import OpenStackService
from modules.conf import CONF
from common import util
from common.singleton import Singleton
@Singleton
class Ceilometer(OpenStackService):
_name = "ceilometer"
_bundle = "openstack-telemetry"
_services = ["ceilometer-agent-central", "ceilometer-agent-notification",
"ceilometer-api", "ceilometer-collector",
"ceilometer-alarm-evaluator", "ceilometer-alarm-notifier"]
_type = "metering"
_description = "OpenStack Telemetry Service"
_public_url = "http://{0}:8777".format(CONF['CONFIG_CONTROLLER_HOST'])
def config_database(self, configfile):
dbpass = CONF['CONFIG_%s_DB_PW' % self._name.upper()]
dbhost = socket.gethostbyaddr(CONF['CONFIG_MONGODB_HOST'])[0]
config = ("[database]\n"
"connection=mongodb://{0}:{1}@{2}:27017/{0}"
.format(self._name, dbpass, dbhost))
util.write_config(configfile, config)
def config_service_credentials(self, configfile):
keystone = Keystone.get()
config = \
"[service_credentials]\n" + \
"os_auth_url = %s\n" % keystone._admin_url + \
"os_username = %s\n" % self._name + \
"os_tenant_name = service\n" + \
"os_password = %s\n" % self._password + \
"os_endpoint_type = internalURL\n" + \
"os_region_name = %s\n" % self._region
util.write_config(configfile, config)
+26
View File
@@ -0,0 +1,26 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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.
#
from common import util
def support_hw_acceleration():
stdout, stderr = util.run_command("egrep -c '(vmx|svm)' /proc/cpuinfo")
return bool(int(stdout.decode('utf-8')))
+40
View File
@@ -0,0 +1,40 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
#
# 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 os
import configparser
_conf_file = "{0}/../defaults.conf".format(os.path.dirname(__file__))
_config = configparser.RawConfigParser()
_config.optionxform = str
_config.read(_conf_file)
CONF = dict(_config['general'])
ENV = {"OS_PROJECT_DOMAIN_ID": "default",
"OS_USER_DOMAIN_ID": "default",
"OS_PROJECT_NAME": "admin",
"OS_USERNAME": "admin",
"OS_PASSWORD": "{0}".format(CONF['CONFIG_KEYSTONE_ADMIN_PW']),
"OS_TENANT_NAME": "admin",
"OS_AUTH_URL": "http://{0}:35357/v3"
.format(CONF['CONFIG_CONTROLLER_HOST']),
"OS_IDENTITY_API_VERSION": "3",
"OS_IMAGE_API_VERSION": "2"}
+64
View File
@@ -0,0 +1,64 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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 os
from modules.openstack import OpenStackService
from modules.conf import CONF
from common import util
from common.util import LOG
from common.singleton import Singleton
@Singleton
class Glance(OpenStackService):
_name = "glance"
_bundle = "openstack-image"
_services = ["glance-api", "glance-registry"]
_type = "image"
_description = "OpenStack Image"
_public_url = "http://{0}:9292".format(CONF['CONFIG_CONTROLLER_HOST'])
def sync_database(self):
LOG.debug("syncing database")
util.run_command("su -s /bin/sh -c"
" \"glance-manage db_sync\" glance")
def create_image(self, name, format, url, public=False):
LOG.debug("Creating image %s" % name)
try:
util.run_command("openstack image show %s" % name,
environ=self._env)
except:
command = ("openstack image create --disk-format %s %s"
% (format, name))
if os.path.isfile(url):
command += " --file %s" % url
else:
command += " --location %s" % url
if public:
command += " --public"
util.run_command(command, environ=self._env)
def ceilometer_enable(self, configfile):
self.config_rabbitmq(configfile)
config = ("[DEFAULT]\n"
"notification_driver = messagingv2\n")
util.write_config(configfile, config)
+73
View File
@@ -0,0 +1,73 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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 configparser
from modules.openstack import OpenStackService
from modules.conf import CONF
from common import util
from common.util import LOG
from common.singleton import Singleton
@Singleton
class Heat(OpenStackService):
_name = "heat"
_bundle = "openstack-orchestration"
_services = ["heat-api", "heat-api-cfn", "heat-engine"]
_type = "orchestration"
_description = "OpenStack Orchestration"
_public_url = ("http://{0}:8004/v1/%\(tenant_id\)s"
.format(CONF['CONFIG_CONTROLLER_HOST']))
domain_admin = CONF['CONFIG_HEAT_DOMAIN_ADMIN']
domain_admin_pw = CONF['CONFIG_HEAT_DOMAIN_PASSWORD']
domain_name = CONF['CONFIG_HEAT_DOMAIN']
def sync_database(self):
LOG.debug("syncing database")
util.run_command("su -s /bin/sh -c"
" \"heat-manage db_sync\" heat")
def config_auth(self, configfile):
OpenStackService.config_auth(self, configfile)
config = configparser.RawConfigParser(allow_no_value=True)
config.read(configfile)
auth_uri = config['keystone_authtoken']['auth_uri']
config['trustee'] = config['keystone_authtoken']
if not config.has_section('clients_keystone'):
config.add_section('clients_keystone')
config['clients_keystone']['auth_uri'] = auth_uri
if not config.has_section('ec2authtoken'):
config.add_section('ec2authtoken')
config['ec2authtoken']['auth_uri'] = auth_uri
with open(configfile, 'w') as f:
config.write(f)
def config_domain(self, configfile):
config = ("[DEFAULT]\n"
"heat_metadata_server_url = http://{0}:8000\n"
"heat_waitcondition_server_url = "
"http://{0}:8000/v1/waitcondition\n"
"stack_domain_admin = {1}\n"
"stack_domain_admin_password = {2}\n"
"stack_user_domain_name = {3}\n"
.format(self._controller, self.domain_admin,
self.domain_admin_pw, self.domain_name))
util.write_config(configfile, config)
+39
View File
@@ -0,0 +1,39 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
# Author: Obed Muñoz <obed.n.munoz@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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.
#
from modules.openstack import OpenStackService
from modules.conf import CONF
from common.singleton import Singleton
@Singleton
class Horizon(OpenStackService):
_name = "horizon"
_bundle = "openstack-dashboard"
if CONF['CONFIG_HTTP_SERVICE'] == 'nginx':
_services = ["nginx", "uwsgi@horizon.socket"]
elif CONF['CONFIG_HTTP_SERVICE'] == 'apache2':
_services = ["httpd"]
# These are needed by OpenStackService but not used by horizon
_type = ""
_public_url = ""
_description = ""
_password = True
+72
View File
@@ -0,0 +1,72 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
# Author: Obed Muñoz <obed.n.munoz@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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.
#
from modules.openstack import OpenStackService
from modules.conf import CONF
from common import util
from common.util import LOG
from common.singleton import Singleton
@Singleton
class Keystone(OpenStackService):
_name = "keystone"
_bundle = "openstack-identity"
if CONF['CONFIG_HTTP_SERVICE'] == 'nginx':
_services = ["memcached", "nginx", "uwsgi@keystone-admin.socket",
"uwsgi@keystone-public.socket"]
elif CONF['CONFIG_HTTP_SERVICE'] == 'apache2':
_services = ["memcached", "httpd"]
else:
_services = ["keystone"]
_type = "identity"
_description = "OpenStack Identity"
_user = "admin"
_password = CONF['CONFIG_KEYSTONE_ADMIN_PW']
_public_url = "http://%s:5000/v3" % CONF['CONFIG_CONTROLLER_HOST']
_internal_url = _public_url
_admin_url = "http://%s:35357/v3" % CONF['CONFIG_CONTROLLER_HOST']
_env = {"OS_TOKEN": CONF['CONFIG_KEYSTONE_ADMIN_TOKEN'],
"OS_URL": "http://{0}:35357/v3"
.format(CONF['CONFIG_CONTROLLER_HOST']),
"OS_IDENTITY_API_VERSION": "3"}
def sync_database(self):
LOG.debug("syncing database")
util.run_command("su -s /bin/sh -c"
" \"keystone-manage db_sync\" keystone")
def create_project(self, project, description):
LOG.debug("setting up %s project" % project)
try:
""" test if project already exists """
util.run_command("openstack project show %s" % project,
environ=self._env)
except:
util.run_command("openstack project create --domain default"
" --description \"%s\" %s"
% (description, project), environ=self._env)
def config_admin_token(self, configfile):
config = \
"[DEFAULT]\n" + \
"admin_token=%s\n" % CONF['CONFIG_KEYSTONE_ADMIN_TOKEN']
util.write_config(configfile, config)
+111
View File
@@ -0,0 +1,111 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
# Author: Obed Muñoz <obed.n.munoz@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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 sys
import socket
from common import util
from common.singleton import Singleton
from common.swupd import Client as swupd_client
from common.util import LOG
from modules.conf import CONF
@Singleton
class MariaDB:
def install(self):
swupd_client.install("database-mariadb")
def start_server(self):
LOG.debug("starting services")
util.run_command("systemctl enable mariadb")
util.run_command("systemctl restart mariadb")
def configure(self):
config_file = "/etc/mariadb/openstack.cnf"
config = """
[mysqld]
default-storage-engine = innodb
innodb_file_per_table
collation-server = utf8_general_ci
init-connect = 'SET NAMES utf8'
character-set-server = utf8
bind-address = 0.0.0.0
"""
util.write_config(config_file, config)
def secure_installation(self, user, password):
LOG.debug("secure installation mariadb")
try:
""" test if mysql has a password """
util.run_command("mysql -u{0} -e \"\"".format(user), debug=False)
""" Secure the database service """
util.run_command('mysqladmin -u root password "{0}"'
.format(password, debug=False))
util.run_command('mysql -u root -p"{0}" -e "UPDATE mysql.user '
'SET Password=PASSWORD(\'{0}\') '
'WHERE User=\'root\'"'
.format(password, debug=False))
util.run_command('mysql -u root -p"{0}" -e "DELETE FROM '
'mysql.user WHERE User=\'root\' AND Host '
' NOT IN (\'localhost\', \'127.0.0.1\', '
'\'::1\')"'
.format(password, debug=False))
util.run_command('mysql -u root -p"{0}" -e "DELETE FROM '
'mysql.user WHERE User=\'\'"'
.format(password, debug=False))
util.run_command('mysql -u root -p"{0}" -e "DELETE FROM mysql.db '
'WHERE Db=\'test\' OR Db=\'test\_%\'"'
.format(password, debug=False))
util.run_command('mysql -u root -p"{0}" -e '
'"FLUSH PRIVILEGES"'
.format(password, debug=False))
except:
pass
try:
""" verify the password """
util.run_command("mysql -u{0} -p{1} -e \"\""
.format(user, password), debug=False)
except:
LOG.error("clearstack: cannot connect to mysql database,"
" the password is incorrect")
return sys.exit(1)
def setup_database(self, database, user, password, host):
LOG.debug("setting up database")
mariadb_host = socket.gethostbyaddr(CONF["CONFIG_MARIADB_HOST"])[0]
mariadb_user = CONF["CONFIG_MARIADB_USER"]
mariadb_pw = CONF["CONFIG_MARIADB_PW"]
util.run_command("mysql -u{0} -p{1} -h{2} -e"
" \"CREATE DATABASE if not exists {3};\""
.format(mariadb_user, mariadb_pw, mariadb_host,
database), debug=False)
util.run_command("mysql -u{0} -p{1} -h{2} -e"
" \"GRANT ALL PRIVILEGES ON {3}.* TO"
" '{4}'@'localhost' IDENTIFIED BY '{5}';\""
.format(mariadb_user, mariadb_pw, mariadb_host,
database, user, password), debug=False)
util.run_command("mysql -u{0} -p{1} -h{2} -e"
" \"GRANT ALL PRIVILEGES ON {3}.* TO '{4}'@'{5}'"
" IDENTIFIED BY '{6}';\""
.format(mariadb_user, mariadb_pw, mariadb_host,
database, user, host, password), debug=False)
+56
View File
@@ -0,0 +1,56 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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.
#
from common import util
from common.singleton import Singleton
from common.swupd import Client as swupd_client
from common.util import LOG
@Singleton
class MongoDB:
def install(self):
swupd_client.install("database-mongodb")
def start_server(self):
LOG.debug("starting services")
util.run_command("systemctl enable mongodb")
util.run_command("systemctl restart mongodb")
count = 0
while count < 10:
try:
util.run_command("mongo --host 127.0.0.1")
return
except:
util.run_command("sleep 1")
count += 1
raise Exception("Failed to start mongodb service")
def configure(self):
config_file = "/etc/mongodb/mongod.conf"
config = {'bind_ip': '0.0.0.0'}
util.write_properties(config_file, config)
def setup_database(self, database, user, password):
cmd = ("mongo --host 127.0.0.1 --eval '"
"db = db.getSiblingDB(\"%s\");"
"db.createUser({user: \"%s\",pwd: \"%s\","
"roles: [ \"readWrite\", \"dbAdmin\" ]})'"
% (database, user, password))
util.run_command(cmd)
+254
View File
@@ -0,0 +1,254 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Obed Muñoz <obed.n.munoz@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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.
#
from ipaddress import IPv4Network
from modules.keystone import Keystone
from modules.nova import Nova
from modules.openstack import OpenStackService
from modules.conf import CONF
from common import util
from common.util import LOG
from common.singleton import Singleton
metadata_password = CONF['CONFIG_NEUTRON_METADATA_PW']
tenant_network_types = CONF['CONFIG_NEUTRON_ML2_TENANT_NETWORK_TYPES']
mechanism_drivers = CONF['CONFIG_NEUTRON_ML2_MECHANISM_DRIVERS']
vni_ranges = CONF['CONFIG_NEUTRON_ML2_TUNNEL_ID_RANGES']
type_drivers = CONF['CONFIG_NEUTRON_ML2_TYPE_DRIVERS']
bridge_mappings = CONF['CONFIG_NEUTRON_LINUXBRIDGE_IFACES']
flat_networks = CONF['CONFIG_NEUTRON_ML2_FLAT_NETWORKS']
@Singleton
class Neutron(OpenStackService):
_name = "neutron"
_bundle = "openstack-network"
_services = ["neutron-server", "neutron-linuxbridge-agent",
"neutron-dhcp-agent", "neutron-metadata-agent",
"neutron-l3-agent"]
_type = "network"
_description = "OpenStack Networking"
_public_url = ("http://{0}:9696"
.format(CONF['CONFIG_CONTROLLER_HOST']))
def sync_database(self):
LOG.debug("syncing database")
util.run_command('su -s /bin/sh -c "neutron-db-manage '
'--config-file /etc/neutron/neutron.conf '
'--config-file /etc/neutron/plugins/ml2/ml2_conf.ini '
'upgrade head" neutron')
if util.str2bool(CONF['CONFIG_LBAAS_INSTALL']):
util.run_command('su -s /bin/sh -c "neutron-db-manage '
'--service lbaas upgrade head"')
def config_ml2_plugin(self):
config = \
"[DEFAULT]\n" + \
"core_plugin = ml2\n" \
"service_plugins = router\n" + \
"allow_overlapping_ips = True\n"
util.write_config("/etc/neutron/neutron.conf", config)
config = \
"[ml2]\n" + \
"type_drivers = %s\n" % type_drivers + \
"tenant_network_types = %s\n" % tenant_network_types + \
"mechanism_drivers = %s\n" % mechanism_drivers + \
"extension_drivers = port_security\n" + \
"[ml2_type_flat]\n" + \
"flat_networks = public\n" + \
"[ml2_type_vxlan]\n" + \
"vni_ranges = %s\n" % vni_ranges + \
"[securitygroup]\n" + \
"enable_ipset = True\n"
util.write_config("/etc/neutron/plugins/ml2/ml2_conf.ini", config)
util.link_file('/etc/neutron/plugins/ml2/ml2_conf.ini',
'/etc/neutron/plugin.ini')
def config_linux_bridge_agent(self):
config = \
"[linux_bridge]\n" + \
"physical_interface_mappings = %s\n" % bridge_mappings + \
"[vxlan]\n" + \
"enable_vxlan = True\n" + \
"local_ip = %s\n" % util.get_ip() + \
"l2_population = True\n" + \
"[agent]\n" + \
"prevent_arp_spoofing = True\n" + \
"[securitygroup]\n" + \
"enable_security_group = True\n" + \
"firewall_driver = neutron.agent.linux.iptables_firewall." + \
"IptablesFirewallDriver\n"
util.write_config("/etc/neutron/plugins/ml2/linuxbridge_agent.ini",
config)
def config_l3_agent(self, configfile):
config = ("[DEFAULT]\n"
"interface_driver = "
"neutron.agent.linux.interface.BridgeInterfaceDriver\n"
"external_network_bridge = \n")
util.write_config(configfile, config)
def config_dhcp_agent(self, configfile):
config = ("[DEFAULT]\n"
"interface_driver = "
"neutron.agent.linux.interface.BridgeInterfaceDriver\n"
"dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq\n"
"enable_isolated_metadata = True\n")
util.write_config(configfile, config)
def config_metadata_agent(self, configfile):
config = \
"[DEFAULT]\n" + \
"auth_uri = http://%s:5000\n" % self._controller + \
"auth_url = http://%s:35357\n" % self._controller + \
"auth_region = %s\n" % self._region + \
"auth_plugin = password\n" + \
"project_domain_id = default\n" + \
"user_domain_id = default\n" + \
"project_name = service\n" + \
"username = %s\n" % self._name + \
"password = %s\n" % self._password + \
"nova_metadata_ip = %s\n" % self._controller + \
"metadata_proxy_shared_secret = %s\n" % metadata_password
util.write_config(configfile, config)
def config_nova(self, configfile):
nova = Nova.get()
config = ("[DEFAULT]\n"
"notify_nova_on_port_status_changes = True\n"
"notify_nova_on_port_data_changes = True\n"
"nova_url = http://{0}:8774/v2\n"
"[nova]\n"
"auth_url = http://{0}:35357\n"
"auth_plugin = password\n"
"project_domain_id = default\n"
"user_domain_id = default\n"
"region_name = {1}\n"
"project_name = service\n"
"username = nova\n"
"password = {2}\n"
.format(self._controller, self._region, nova._password))
util.write_config(configfile, config)
def config_neutron_on_nova(self, configfile):
keystone = Keystone.get()
config = \
"[DEFAULT]\n" + \
"network_api_class = nova.network.neutronv2.api.API\n" + \
"security_group_api = neutron\n" + \
"linuxnet_interface_driver = " + \
"nova.network.linux_net.NeutronLinuxBridgeInterfaceDriver\n" + \
"firewall_driver = nova.virt.firewall.NoopFirewallDriver\n" + \
"[neutron]\n" + \
"url = %s\n" % self._public_url + \
"auth_url = %s\n" % keystone._admin_url + \
"auth_plugin = password\n" + \
"project_domain_id = default\n" + \
"user_domain_id = default\n" + \
"region_name = %s\n" % self._region + \
"project_name = service\n" + \
"username = neutron\n" + \
"password = %s\n" % self._password + \
"service_metadata_proxy = True\n" + \
"metadata_proxy_shared_secret = %s\n" % metadata_password
util.write_config(configfile, config)
if CONF['CONFIG_HTTP_SERVICE'] == 'nginx':
nova_api_services = ['uwsgi@nova-api.socket',
'uwsgi@nova-metadata.socket']
elif CONF['CONFIG_HTTP_SERVICE'] == 'apache2':
nova_api_services = ['httpd']
else:
nova_api_services = ['nova-api']
self.start_server(nova_api_services)
def add_service_plugin(self, plugin):
plugins = util.get_option('/etc/neutron/neutron.conf',
'DEFAULT', 'service_plugins').split(',')
if plugin not in plugins:
plugins.append(plugin)
config = ('[DEFAULT]\n'
"service_plugins = %s\n" % ','.join(plugins))
util.write_config("/etc/neutron/neutron.conf", config)
def config_lbaas(self):
self.add_service_plugin('lbaas')
config = ("[DEFAULT]\n"
"interface_driver = "
"neutron.agent.linux.interface.BridgeInterfaceDriver\n")
util.write_config("/etc/neutron/lbaas_agent.ini", config)
self._services += ['neutron-lbaas-agent']
def config_vpnaas(self):
self.add_service_plugin('vpnaas')
driver = ("neutron_vpnaas.services.vpn.device_drivers.libreswan_ipsec"
".LibreSwanDriver")
config = "[vpnagent]\n" + \
"vpn_device_driver = %s\n" % driver
util.write_config("/etc/neutron/vpnaas_agent.ini", config)
self._services += ['ipsec', 'neutron-vpn-agent']
def create_network(self, name, public=None):
if public:
cidr = IPv4Network(CONF['CONFIG_NOVA_NETWORK_FLOATRANGE'])
else:
cidr = IPv4Network(CONF['CONFIG_NOVA_NETWORK_FIXEDRANGE'])
cidr_e = cidr.exploded
cidr_gw = (cidr.network_address + 1).exploded
cidr_start = (cidr.network_address + 2).exploded
cidr_end = (cidr.broadcast_address - 1).exploded
try:
util.run_command("neutron net-show %s" % name,
environ=self._env)
except:
cmd = "neutron net-create %s" % name
if public:
cmd += (" --provider:physical_network public"
" --shared --provider:network_type flat")
util.run_command(cmd, environ=self._env)
cmd = ("neutron subnet-create %s %s --name %s"
" --gateway %s" % (name, cidr_e, name, cidr_gw))
if public:
cmd += (" --allocation-pool start=%s,end=%s"
% (cidr_start, cidr_end))
util.run_command(cmd, environ=self._env)
if public:
util.run_command("neutron net-update %s --router:external"
% name, environ=self._env)
def create_router(self, router, gw, interfaces):
try:
util.run_command("neutron router-show %s" % router,
environ=self._env)
except:
util.run_command("neutron router-create %s" % router,
environ=self._env)
util.run_command("neutron router-gateway-set %s %s"
% (router, gw), environ=self._env)
for i in interfaces:
util.run_command("neutron router-interface-add %s %s"
% (router, i), environ=self._env)
def ceilometer_enable(self, configfile):
self.config_rabbitmq(configfile)
config = ("[DEFAULT]\n"
"notification_driver = messagingv2\n")
util.write_config(configfile, config)
+95
View File
@@ -0,0 +1,95 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
# Author: Obed Muñoz <obed.n.munoz@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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.
#
from modules.openstack import OpenStackService
from modules.ceilometer import Ceilometer
from modules.conf import CONF
from common import util
from common.util import LOG
from common.singleton import Singleton
@Singleton
class Nova(OpenStackService):
_name = "nova"
_bundle = "openstack-compute-controller"
_services = ["nova-cert", "nova-consoleauth", "nova-scheduler",
"nova-conductor", "nova-novncproxy"]
if CONF['CONFIG_HTTP_SERVICE'] == 'nginx':
_services.extend(["nginx", "uwsgi@nova-api.socket",
"uwsgi@nova-metadata.socket"])
elif CONF['CONFIG_HTTP_SERVICE'] == 'apache2':
_services.append("httpd")
else:
_services.append("nova-api")
_type = "compute"
_description = "OpenStack Compute"
_password = CONF['CONFIG_NOVA_KS_PW']
_public_url = ("http://{0}:8774/v2/%\(tenant_id\)s"
.format(CONF['CONFIG_CONTROLLER_HOST']))
def install_compute(self):
self.install("openstack-compute")
def sync_database(self):
LOG.debug("syncing database")
util.run_command("su -s /bin/sh -c \"nova-manage db sync\" nova")
def create_network(self):
LOG.debug("Creating network")
command = ("nova-manage network create --bridge=br100"
"--label=demo-net --fixed_range_v4=%s"
% CONF['CONFIG_NOVA_NETWORK_FIXEDRANGE'])
try:
util.run_command("nova network-show demo-net", environ=self._env)
except:
command = ("nova-manage network create --bridge=br100 "
"--label=demo-net --fixed_range_v4=%s"
% CONF['CONFIG_NOVA_NETWORK_FIXEDRANGE'])
if util.str2bool(CONF['CONFIG_NOVA_NETWORK_MULTIHOST']):
command += " --multi_host=T"
util.run_command(command, environ=self._env)
def create_floating_ips(self):
LOG.debug("Creating floating ips")
try:
util.run_command("nova floating-ip-pool-list | grep nova")
except:
cmd = ("nova-manage floating create --pool nova "
"--ip_range=%s" % CONF['CONFIG_NOVA_NETWORK_FLOATRANGE'])
util.run_command(cmd, environ=self._env)
def ceilometer_enable(self, configfile):
ceilometer = Ceilometer.get()
ceilometer_cfg = "/etc/ceilometer/ceilometer.conf"
ceilometer.install()
ceilometer.config_rabbitmq(ceilometer_cfg)
ceilometer.config_auth(ceilometer_cfg)
ceilometer.config_service_credentials(ceilometer_cfg)
config = ("[DEFAULT]\n"
"instance_usage_audit = True\n"
"instance_usage_audit_period = hour\n"
"notify_on_state_change = vm_and_task_state\n"
"notification_driver = messagingv2\n")
util.write_config(configfile, config)
self.start_server(['ceilometer-agent-compute.service'])
+195
View File
@@ -0,0 +1,195 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Obed Muñoz <obed.n.munoz@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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 socket
from common import util
from common.swupd import Client as swupd_client
from common.util import LOG
from modules.conf import CONF
from modules.conf import ENV
class OpenStackService:
_env = ""
_internal_url = ""
_admin_url = ""
_region = ""
_user = ""
_controller = socket.gethostbyaddr(CONF["CONFIG_CONTROLLER_HOST"])[0]
_password = ""
def __init__(self):
if not self._env:
self._env = ENV
if not self._user:
self._user = self._name
if not self._password:
self._password = CONF['CONFIG_%s_KS_PW' % self._name.upper()]
if not self._internal_url:
self._internal_url = self._public_url
if not self._admin_url:
self._admin_url = self._public_url
if not self._region:
self._region = CONF['CONFIG_KEYSTONE_REGION']
def install(self, bundle=None):
bundle = bundle or self._bundle
swupd_client.install(bundle)
def start_server(self, services=None):
services = services or self._services
LOG.debug("Starting services")
util.run_command("systemctl enable %s" % " ".join(services))
for service in services:
if service.endswith(".socket"):
util.run_command("systemctl stop %s" %
service.replace(".socket", ".service"))
util.run_command("systemctl restart %s" % service)
def create_service(self, name=None, description=None, type=None):
name = name or self._name
description = description or self._description
type = type or self._type
LOG.debug("setting up %s service" % name)
try:
""" test if service already exists """
util.run_command("openstack service show %s" % name,
environ=self._env)
except:
util.run_command("openstack service create %s"
" --name %s --description \"%s\""
% (type, name, description),
environ=self._env)
def create_endpoint(self, publicurl=None,
internalurl=None,
adminurl=None,
region=None,
type=None):
publicurl = publicurl or self._public_url
internalurl = internalurl or self._internal_url
adminurl = adminurl or self._admin_url
region = region or self._region
type = type or self._type
LOG.debug("creating endpoint")
""" test if endpoint already exists """
out, err = util.run_command("openstack endpoint list | grep %s"
% self._name, environ=self._env)
if not out:
cmd = ("openstack endpoint create --region {0} {1}"
.format(region, type))
util.run_command(cmd + " public {0}".format(publicurl),
environ=self._env)
util.run_command(cmd + " internal {0}".format(internalurl),
environ=self._env)
util.run_command(cmd + " admin {0}".format(adminurl),
environ=self._env)
def create_role(self, role):
LOG.debug("setting up %s role" % role)
try:
util.run_command("openstack role show %s" % role,
environ=self._env)
except:
util.run_command("openstack role create %s" % role,
environ=self._env)
def add_role(self, user, role, project="service", domain="default"):
# openstack role add: error: argument --project: not allowed with
# argument --domain
cmd = "openstack role add --user {0} {1}".format(user, role)
if domain != "default":
cmd += " --domain %s" % domain
else:
cmd += " --project %s" % project
util.run_command(cmd, environ=self._env)
def create_user(self, user=None, password=None, domain="default",
project="service", role="admin"):
user = user or self._user
password = password or self._password
LOG.debug("setting up %s user" % user)
try:
""" test if user already exists """
util.run_command("openstack user show %s" % user,
environ=self._env)
except:
util.run_command("openstack user create --domain {0}"
" --password={1}"
" --email {2}@example.com {2}"
.format(domain, password, user),
environ=self._env, debug=False)
self.add_role(user, role, project, domain)
def create_domain(self, domain, description):
LOG.debug("setting up %s domain" % domain)
try:
""" test if domain already exists """
util.run_command("openstack domain show %s" % domain,
environ=self._env)
except:
util.run_command("openstack domain create --description \"%s\" %s"
% (description, domain),
environ=self._env, debug=False)
def config_debug(self, configfile):
if util.str2bool(CONF['CONFIG_DEBUG_MODE']):
config = "[DEFAULT]\n" + \
"debug=True\n" + \
"verbose=True\n"
util.write_config(configfile, config)
def config_database(self, configfile):
dbpass = CONF['CONFIG_%s_DB_PW' % self._name.upper()]
dbhost = socket.gethostbyaddr(CONF['CONFIG_MARIADB_HOST'])[0]
config = ("[database]\n"
"connection=mysql://{0}:{1}@{2}/{0}"
.format(self._name, dbpass, dbhost))
util.write_config(configfile, config)
def config_rabbitmq(self, configfile):
rabbit_host = socket.gethostbyaddr(CONF['CONFIG_AMQP_HOST'])[0]
rabbit_password = CONF['CONFIG_AMQP_AUTH_PASSWORD']
rabbit_user = CONF['CONFIG_AMQP_AUTH_USER']
config = \
"[DEFAULT]\n" + \
"rpc_backend=rabbit\n" + \
"[oslo_messaging_rabbit]\n" + \
"rabbit_host=%s\n" % rabbit_host + \
"rabbit_userid=%s\n" % rabbit_user + \
"rabbit_password=%s\n" % rabbit_password + \
"send_single_reply=True"
util.write_config(configfile, config)
def config_auth(self, configfile, section='keystone_authtoken'):
config = ("[{0}]\n"
"auth_uri=http://{1}:5000\n"
"auth_url=http://{1}:35357\n"
"auth_plugin=password\n"
"project_domain_id=default\n"
"user_domain_id=default\n"
"project_name=service\n"
"username={2}\n"
"password={3}"
.format(section, self._controller, self._name,
self._password))
util.write_config(configfile, config)
+71
View File
@@ -0,0 +1,71 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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.
#
from common import util
from common.singleton import Singleton
from common.swupd import Client as swupd_client
from common.util import LOG
@Singleton
class Rabbitmq:
def __init__(self):
hostname, stderr = util.run_command("hostname")
util.write_in_file_ine("/etc/hosts", "127.0.0.1 {0}"
.format(str(hostname.decode("utf-8")[:-1])))
def user_exists(self, user):
stdout = None
stderr = None
try:
stdout, stderr = util.run_command("rabbitmqctl list_users"
" | grep {0}".format(user))
except:
pass
if not stdout:
return False
return True
def install(self):
swupd_client.install("message-broker-rabbitmq")
def start_server(self):
LOG.debug("starting services")
util.run_command("systemctl enable rabbitmq-server")
util.run_command("systemctl restart rabbitmq-server")
def add_user(self, auth_user, auth_pw):
""" todo: what we do with guest """
LOG.debug("adding user")
if not self.user_exists(auth_user):
util.run_command("rabbitmqctl add_user {0} {1}"
.format(auth_user, auth_pw), debug=False)
def delete_user(self, user):
LOG.debug("deleting user")
util.run_command("rabbitmqctl delete_user {1}"
.format(user))
def set_permissions(self, auth_user, permissions):
LOG.debug("setting permissions")
util.run_command("rabbitmqctl set_permissions {0} {1}"
.format(auth_user, permissions))
+202
View File
@@ -0,0 +1,202 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
#
# 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 os
import shutil
from common import util
from modules.openstack import OpenStackService
from modules.conf import CONF
from common.singleton import Singleton
@Singleton
class Swift(OpenStackService):
_name = "swift"
_bundle = "openstack-object-storage"
_services = ["swift-proxy", "memcached"]
_type = "object-store"
_description = "OpenStack Object Storage"
_public_url = ("http://{0}:8080/v1/AUTH_%\(tenant_id\)s"
.format(CONF['CONFIG_CONTROLLER_HOST']))
_admin_url = "http://{0}:8080/v1".format(CONF['CONFIG_CONTROLLER_HOST'])
_devices = []
def ceilometer_enable(self, configfile):
pass
def config_auth(self, configfile):
confdir = os.path.dirname(configfile)
if not os.path.isdir(confdir):
os.makedirs(confdir)
shutil.copy('/usr/share/defaults/swift/proxy-server.conf', confdir)
OpenStackService.config_auth(self, configfile,
section='filter:authtoken')
config = ("[pipeline:main]\n"
"pipeline = catch_errors gatekeeper healthcheck "
"proxy-logging cache container_sync bulk ratelimit "
"authtoken keystoneauth container-quotas account-quotas "
"slo dlo versioned_writes proxy-logging proxy-server\n"
"[filter:authtoken]\n"
"paste.filter_factory = "
"keystonemiddleware.auth_token:filter_factory\n"
"delay_auth_decision = True\n"
"[app:proxy-server]\n"
"use = egg:swift#proxy\n"
"account_autocreate = True\n"
"[filter:keystoneauth]\n"
"use = egg:swift#keystoneauth\n"
"operator_roles = admin,user\n")
util.write_config(configfile, config)
def config_memcache(self, configfile):
config = ("[filter:cache]\n"
"use = egg:swift#memcache\n"
"memcache_servers = 127.0.0.1:11211")
util.write_config(configfile, config)
def config_hash(self, configfile):
suffix = CONF['CONFIG_SWIFT_HASH']
config = ("[swift-hash]\n"
"swift_hash_path_suffix = {0}").format(suffix)
util.write_config(configfile, config)
def parse_devices(self):
def create_loopback(name, size):
# Remove the file if exists
if os.path.isfile(name):
os.remove(name)
# Create an empty file
with open(name, 'wb') as f:
f.seek(1024 * 1024 * 1024 * size - 1)
f.write(b"\0")
util.run_command("mkfs.xfs %s" % name)
devs = CONF['CONFIG_SWIFT_STORAGES']
if devs:
devs = devs.split(',')
devs = [x.strip() for x in devs]
device_number = 0
num_zones = int(CONF["CONFIG_SWIFT_STORAGE_ZONES"])
for dev in devs:
device_number += 1
zone = (device_number % num_zones) + 1
self._devices.append({'device': dev, 'zone': zone,
'name': 'device%s' % device_number})
else:
# Setup loopdevice
filename = '/srv/loopback-device'
filesize = int(CONF['CONFIG_SWIFT_STORAGE_SIZE'])
create_loopback(filename, filesize)
self._devices.append({'device': filename, 'zone': 1,
'name': 'loopback'})
def prepare_devices(self):
# Avoid adding duplicate entries in fstab
mounted_devices = []
if os.path.isfile('/etc/fstab'):
with open('/etc/fstab', 'r') as f:
for l in f:
mounted_devices.append(l.split()[0].strip())
# Add each device to fstab if not already added
fstab = ""
for device in self._devices:
# Format the device with xfs filesystem
util.ensure_directory('/srv/node/%s' % device['name'])
# Ensure the device is mounted
if device['device'] not in mounted_devices:
fstab += ("{0} /srv/node/{1} xfs noatime,nodiratime,nobarrier,"
"logbufs=8 0 2\n").format(device['device'],
device['name'])
with open('/etc/fstab', 'a') as f:
f.write(fstab)
util.run_command('mount -a')
# Change ownership of /srv to swift
util.run_command("chown -R swift:swift /srv")
def create_rings(self):
replicas = CONF['CONFIG_SWIFT_STORAGE_REPLICAS']
ip = util.get_ip()
for ringtype, port in [('object', '6000'),
('container', '6001'),
('account', 6002)]:
cmd = ("swift-ring-builder {0}.builder create 10 {1} 1"
.format(ringtype, replicas))
util.run_command(cmd)
for device in self._devices:
cmd = ("swift-ring-builder %s.builder add --region 1 "
"--zone %s --ip %s --port %s --device %s --weight 100"
% (ringtype, device['zone'], ip, port, device['name']))
util.run_command(cmd)
cmd = "swift-ring-builder {0}.builder rebalance".format(ringtype)
util.run_command(cmd)
if os.path.isfile("/etc/swift/%s.ring.gz" % ringtype):
os.remove("/etc/swift/%s.ring.gz" % ringtype)
shutil.move("%s.ring.gz" % ringtype, "/etc/swift")
def config_storage_services(self):
confdir = '/etc/swift/'
shutil.copy('/usr/share/defaults/swift/account-server.conf', confdir)
shutil.copy('/usr/share/defaults/swift/container-server.conf', confdir)
shutil.copy('/usr/share/defaults/swift/object-server.conf', confdir)
shutil.copy('/usr/share/defaults/swift/container-reconciler.conf',
confdir)
shutil.copy('/usr/share/defaults/swift/object-expirer.conf', confdir)
for type in ['account', 'container', 'object']:
conf = ("[DEFAULT]\n"
"bind_ip = 0.0.0.0\n"
"devices = /srv/node\n"
"[pipeline:main]\n"
"pipeline = healthcheck recon {0}-server\n"
"[filter:recon]\n"
"recon_cache_path = /var/cache/swift\n").format(type)
util.write_config('/etc/swift/%s-server.conf' % type, conf)
def config_rsync(self):
config = """
uid = swift
gid = swift
log file = /var/log/rsyncd.log
pid file = /var/run/rsyncd.pid
address = {0}
[account]
max connections = 2
path = /srv/node/
read only = false
lock file = /var/lock/account.lock
[container]
max connections = 2
path = /srv/node/
read only = false
lock file = /var/lock/container.lock
[object]
max connections = 2
path = /srv/node/
read only = false
lock file = /var/lock/object.lock
""".format(util.get_ip())
with open('/etc/rsyncd.conf', 'w') as f:
f.write(config)
View File
+59
View File
@@ -0,0 +1,59 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Julio Montes <julio.montes@intel.com>
#
# 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.
#
from clearstack import utils
from clearstack import validators
from clearstack.argument import Argument
from clearstack.controller import Controller
from clearstack.common import util
def init_config():
conf = {
"AMQP": [
Argument("amqp-auth-user",
"User for amqp authentication",
"CONFIG_AMQP_AUTH_USER",
"amqp_user",
validators=[validators.not_empty]),
Argument("amqp-auth-pw",
"Password for amqp user authentication",
"CONFIG_AMQP_AUTH_PASSWORD",
utils.generate_random_pw(),
validators=[validators.not_empty]),
Argument("amqp-host",
"The IP address or hostname of the server on which"
" to install the AMQP service",
"CONFIG_AMQP_HOST",
util.get_ip(),
validators=[validators.ip_or_hostname])
]
}
for group in conf:
Controller.get().add_group(group, conf[group])
def init_sequences():
Controller.get().add_sequence("Setting up rabbit", setup_rabbit)
def setup_rabbit():
conf = Controller.get().CONF
recipe = utils.get_template("rabbitmq")
return utils.run_recipe("rabbitmq.py", recipe, [conf["CONFIG_AMQP_HOST"]])
+58
View File
@@ -0,0 +1,58 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
#
# 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.
#
from clearstack import utils
from clearstack import validators
from clearstack.controller import Controller
from clearstack.argument import Argument
from clearstack.common import util
def init_config():
conf = {
"CEILOMETER": [
Argument("ceilometer-db-pw",
"Password for ceilometer to access DB",
"CONFIG_CEILOMETER_DB_PW",
utils.generate_random_pw(),
validators=[validators.not_empty]),
Argument("ceilometer-ks-pw",
"Password to use for Ceilometer to"
" authenticate with Keystone",
"CONFIG_CEILOMETER_KS_PW",
utils.generate_random_pw(),
validators=[validators.not_empty])
]
}
for group in conf:
Controller.get().add_group(group, conf[group])
def init_sequences():
controller = Controller.get()
conf = controller.CONF
if util.str2bool(conf['CONFIG_CEILOMETER_INSTALL']):
controller.add_sequence("Setting up ceilometer", setup_ceilometer)
def setup_ceilometer():
conf = Controller.get().CONF
recipe = utils.get_template("ceilometer")
return utils.run_recipe("ceilometer.py", recipe,
[conf["CONFIG_CONTROLLER_HOST"]])
+59
View File
@@ -0,0 +1,59 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
#
# 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.
#
from clearstack import utils
from clearstack import validators
from clearstack.controller import Controller
from clearstack.argument import Argument
from clearstack.common import util
def init_config():
conf = {
"GLANCE": [
Argument("glance-db-pw",
"Password for glance to access DB",
"CONFIG_GLANCE_DB_PW",
utils.generate_random_pw(),
validators=[validators.not_empty]),
Argument("glance-ks-pw",
"Password to use for Glance to"
" authenticate with Keystone",
"CONFIG_GLANCE_KS_PW",
utils.generate_random_pw(),
validators=[validators.not_empty])
]
}
for group in conf:
Controller.get().add_group(group, conf[group])
def init_sequences():
controller = Controller.get()
conf = controller.CONF
if util.str2bool(conf['CONFIG_GLANCE_INSTALL']):
controller.add_sequence("Setting up glance", setup_glance)
def setup_glance():
conf = Controller.get().CONF
recipe = utils.get_template("glance")
return utils.run_recipe("glance.py", recipe,
[conf["CONFIG_CONTROLLER_HOST"]])
+75
View File
@@ -0,0 +1,75 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
#
# 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.
#
from clearstack import utils
from clearstack import validators
from clearstack.controller import Controller
from clearstack.argument import Argument
from clearstack.common import util
def init_config():
conf = {
"HEAT": [
Argument("heat-db-pw",
"Password for heat to access DB",
"CONFIG_HEAT_DB_PW",
utils.generate_random_pw(),
validators=[validators.not_empty]),
Argument("heat-ks-pw",
"Password to use for Heat to"
" authenticate with Keystone",
"CONFIG_HEAT_KS_PW",
utils.generate_random_pw(),
validators=[validators.not_empty]),
Argument("heat-domain",
"Name of the Identity domain for Orchestration.",
"CONFIG_HEAT_DOMAIN",
"heat",
validators=[validators.not_empty]),
Argument("heat-domain-admin",
"Name of the Identity domain administrative user for "
"Orchestration.",
"CONFIG_HEAT_DOMAIN_ADMIN",
"heat_domain_admin",
validators=[validators.not_empty]),
Argument("heat-domain-password",
"Password for the Identity domain administrative user "
"for Orchestration",
"CONFIG_HEAT_DOMAIN_PASSWORD",
utils.generate_random_pw(),
validators=[validators.not_empty])
]
}
for group in conf:
Controller.get().add_group(group, conf[group])
def init_sequences():
controller = Controller.get()
conf = controller.CONF
if util.str2bool(conf['CONFIG_HEAT_INSTALL']):
controller.add_sequence("Setting up heat", setup_heat)
def setup_heat():
conf = Controller.get().CONF
recipe = utils.get_template("heat")
return utils.run_recipe("heat.py", recipe,
[conf["CONFIG_CONTROLLER_HOST"]])
+43
View File
@@ -0,0 +1,43 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
#
# 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.
#
from clearstack import utils
from clearstack.controller import Controller
from clearstack.common import util
def init_config():
conf = {}
for group in conf:
Controller.get().add_group(group, conf[group])
def init_sequences():
controller = Controller.get()
conf = controller.CONF
if util.str2bool(conf['CONFIG_HORIZON_INSTALL']):
controller.add_sequence("Setting up horizon", setup_horizon)
def setup_horizon():
template = "horizon"
conf = Controller.get().CONF
recipe = utils.get_template(template)
return utils.run_recipe("{0}.py".format(template), recipe,
[conf["CONFIG_CONTROLLER_HOST"]])
+71
View File
@@ -0,0 +1,71 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
#
# 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 uuid
from clearstack.controller import Controller
from clearstack.argument import Argument
from clearstack import utils
from clearstack import validators
def init_config():
conf = {
"KEYSTONE": [
Argument("keystone-db-pw",
"Password for keystone to access DB",
"CONFIG_KEYSTONE_DB_PW",
utils.generate_random_pw(),
validators=[validators.not_empty]),
Argument("keystone-admin-token",
"The token to use for the Keystone service api",
"CONFIG_KEYSTONE_ADMIN_TOKEN",
uuid.uuid4().hex,
validators=[validators.not_empty]),
Argument("keystone-admin-pw",
"The password to use for the Keystone admin user",
"CONFIG_KEYSTONE_ADMIN_PW",
utils.generate_random_pw(),
validators=[validators.not_empty]),
Argument("keystone-demo-pw",
"The password to use for the Keystone demo user",
"CONFIG_KEYSTONE_DEMO_PW",
utils.generate_random_pw(),
validators=[validators.not_empty]),
Argument("keystone-region",
"Region name",
"CONFIG_KEYSTONE_REGION",
"RegionOne",
validators=[validators.not_empty])
]
}
for group in conf:
Controller.get().add_group(group, conf[group])
def init_sequences():
Controller.get().add_sequence("Setting up keystone", setup_keystone)
def setup_keystone():
conf = Controller.get().CONF
recipe = utils.get_template('keystone')
return utils.run_recipe("keystone.py", recipe,
[conf["CONFIG_CONTROLLER_HOST"]])
+62
View File
@@ -0,0 +1,62 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
#
# 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.
#
from clearstack.controller import Controller
from clearstack.argument import Argument
from clearstack import utils
from clearstack import validators
from clearstack.common import util
def init_config():
conf = {
"MARIADB": [
Argument("mariadb-host",
"The IP address or hostname of the MariaDB server",
"CONFIG_MARIADB_HOST",
util.get_ip(),
validators=[validators.ip_or_hostname]),
Argument("mariadb-user",
"User for mariadb authentication",
"CONFIG_MARIADB_USER",
"root",
validators=[validators.not_empty]),
Argument("mariadb-pw",
"Password for mariadb user",
"CONFIG_MARIADB_PW",
utils.generate_random_pw(),
validators=[validators.not_empty])
]
}
for group in conf:
Controller.get().add_group(group, conf[group])
def init_sequences():
controller = Controller.get()
controller.add_sequence("Setting up mariadb",
setup_mariadb, args=['mariadb'])
def setup_mariadb(template):
conf = Controller.get().CONF
recipe = utils.get_template(template)
return utils.run_recipe("{0}.py".format(template), recipe,
[conf["CONFIG_MARIADB_HOST"]])
+52
View File
@@ -0,0 +1,52 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
#
# 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.
#
from clearstack.controller import Controller
from clearstack.argument import Argument
from clearstack import utils
from clearstack import validators
from clearstack.common import util
def init_config():
conf = {
"MONGODB": [
Argument("mongodb-host",
"The IP address or hostname of the MongoDB server",
"CONFIG_MONGODB_HOST",
util.get_ip(),
validators=[validators.ip_or_hostname])
]
}
for group in conf:
Controller.get().add_group(group, conf[group])
def init_sequences():
controller = Controller.get()
conf = controller.CONF
if util.str2bool(conf['CONFIG_CEILOMETER_INSTALL']):
controller.add_sequence("Setting up MongoDB", setup_mongodb)
def setup_mongodb():
conf = Controller.get().CONF
recipe = utils.get_template('mongodb')
return utils.run_recipe("mongodb.py", recipe,
[conf["CONFIG_MONGODB_HOST"]])
+159
View File
@@ -0,0 +1,159 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
#
# 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.
#
from clearstack import utils
from clearstack import validators
from clearstack.controller import Controller
from clearstack.argument import Argument
from clearstack.common import util
def init_config():
conf = {
"NEUTRON": [
Argument("neutron-ks-pw",
"Password to use for OpenStack Networking (neutron) to"
" authenticate with the Identity service.",
"CONFIG_NEUTRON_KS_PW",
utils.generate_random_pw(),
validators=[validators.not_empty]),
Argument("neutron-db-pw",
"The password to use for OpenStack Networking to access "
"the database.",
"CONFIG_NEUTRON_DB_PW",
utils.generate_random_pw(),
validators=[validators.not_empty]),
# Argument('neutron-l3-ext-bridge',
# 'The name of the Open vSwitch bridge (or empty for '
# 'linuxbridge) for the OpenStack Networking L3 agent to '
# 'use for external traffic',
# 'CONFIG_NEUTRON_L3_EXT_BRIDGE',
# 'br-ex',
# validators=[validators.not_empty]),
Argument('neutron-metadata-pw',
'Password for the OpenStack Networking metadata agent',
'CONFIG_NEUTRON_METADATA_PW',
utils.generate_random_pw(),
validators=[validators.not_empty]),
Argument('neutron-lbaas-install',
"Specify 'y' to install OpenStack Networking's "
"Load-Balancing-as-a-Service (LBaaS)",
"CONFIG_LBAAS_INSTALL",
'n',
options=['y', 'n'],
validators=[validators.y_or_n]),
Argument('neutron-vpnass-install',
"Specify 'y' to install OpenStack Networking's "
"VPN-as-a-Service (VPNaaS)",
"CONFIG_VPNAAS_INSTALL",
'n',
options=['y', 'n'],
validators=[validators.y_or_n])
],
# "NEUTRON_OVS_AGENT": [
# Argument("neutron-ovs-bridge-mappings",
# "Comma-separated list of bridge mappings for the "
# "OpenStack Networking Open vSwitch plugin. Each tuple "
# "in the list must be in he format "
# " <physical_network>:<ovs_bridge>",
# "CONFIG_NEUTRON_OVS_BRIDGE_MAPPINGS",
# "external:br-ex"),
# Argument("neutron-ovs-bridge-interfaces",
# "Comma-separated list of colon-separated Open vSwitch"
# " <bridge>:<interface> pairs.",
# "CONFIG_NEUTRON_OVS_BRIDGE_IFACES",
# "br-ex:%s" % util.get_net_interface())
# ],
"NEUTRON_LINUXBRIDGE_AGENT": [
Argument("neutron-linuxbridge-physical-interface-mappings",
"Colon separated linuxbridge <bridge>:<interface> pairs",
"CONFIG_NEUTRON_LINUXBRIDGE_IFACES",
"public:%s" % util.get_net_interface())
],
"NEUTRON_ML2_PLUGIN": [
Argument("neutron-ml2-type-drivers",
"Comma-separated list of network-type driver entry "
"points to be loaded from the neutron.ml2.type_drivers "
"namespace",
"CONFIG_NEUTRON_ML2_TYPE_DRIVERS",
"flat,vlan,vxlan",
options=['local', 'flat', 'vlan', 'gre', 'vxlan'],
validators=[validators.not_empty]),
Argument("neutron-ml2-tenant-network-types",
"Comma-separated, ordered list of network types to "
"allocate as tenant networks",
"CONFIG_NEUTRON_ML2_TENANT_NETWORK_TYPES",
"vxlan",
options=['local', 'vlan', 'gre', 'vxlan'],
validators=[validators.not_empty]),
Argument("neutron-ml2-mechanism-drivers",
"Comma-separated, ordered list of network types to "
"allocate as tenant networks",
"CONFIG_NEUTRON_ML2_MECHANISM_DRIVERS",
"linuxbridge,l2population",
options=['openvswitch', 'linuxbridge'],
validators=[validators.not_empty]),
Argument("neutron-ml2-flat-networks",
"Comma-separated list of physical_network names with "
"wich flat networks can be created.",
"CONFIG_NEUTRON_ML2_FLAT_NETWORKS",
"public",
validators=[validators.not_empty]),
Argument("neutron-ml2-tunnel-id-ranges",
"Comma-separated list of <tun_min>:<tun_max> tuples "
"enumerating ranges of GRE tunnel IDs that are available "
"for tenant-network allocation.",
"CONFIG_NEUTRON_ML2_TUNNEL_ID_RANGES",
"1:1000",
validators=[validators.not_empty]),
Argument("neutron-l2-agent",
"Name of the L2 agent to be used with OpenStack "
"Networking",
"CONFIG_NEUTRON_L2_AGENT",
"linuxbridge",
options=['openvswitch', 'linuxbridge'],
validators=[validators.not_empty])
]
}
for group in conf:
Controller.get().add_group(group, conf[group])
def init_sequences():
controller = Controller.get()
conf = controller.CONF
if util.str2bool(conf['CONFIG_NEUTRON_INSTALL']):
controller.add_sequence("Setting up neutron controller",
setup_controller)
controller.add_sequence("Setting up neutron on computes nodes",
setup_compute_nodes)
def setup_controller():
conf = Controller.get().CONF
recipe = utils.get_template('neutron')
return utils.run_recipe("neutron.py", recipe,
[conf["CONFIG_CONTROLLER_HOST"]])
def setup_compute_nodes():
conf = Controller.get().CONF
recipe = utils.get_template('neutron_compute')
return utils.run_recipe("neutron_compute.py", recipe,
conf["CONFIG_COMPUTE_HOSTS"].split(','))
+114
View File
@@ -0,0 +1,114 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
#
# 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.
#
from clearstack import utils
from clearstack import validators
from clearstack.controller import Controller
from clearstack.argument import Argument
from clearstack.common import util
def init_config():
conf = {
"NOVA": [
Argument("nova-db-pw",
"Password for nova to access DB",
"CONFIG_NOVA_DB_PW",
utils.generate_random_pw(),
validators=[validators.not_empty]),
Argument("nova-ks-pw",
"Password to use for the Nova to"
" authenticate with Keystone",
"CONFIG_NOVA_KS_PW",
utils.generate_random_pw(),
validators=[validators.not_empty])
],
"NOVA_NETWORK": [
Argument("nova-compute-privif",
"Private interface for Flat DHCP on"
" the Nova compute servers",
"CONFIG_NOVA_COMPUTE_PRIVIF",
util.get_net_interface(),
validators=[validators.not_empty]),
Argument("nova-network-manager",
"Nova network manager",
"CONFIG_NOVA_NETWORK_MANAGER",
"nova.network.manager.FlatDHCPManager",
validators=[validators.not_empty]),
Argument("nova-network-pubif",
"Public interface on the Nova network server",
"CONFIG_NOVA_NETWORK_PUBIF",
util.get_net_interface(),
validators=[validators.not_empty]),
Argument("nova-network-fixed-range",
"IP Range for flat DHCP.",
"CONFIG_NOVA_NETWORK_FIXEDRANGE",
"192.168.32.0/22",
validators=[validators.cidr]),
Argument("nova-network-floating-range",
"IP Range for floating IP addresses.",
"CONFIG_NOVA_NETWORK_FLOATRANGE",
"10.3.4.0/22",
validators=[validators.cidr]),
Argument("nova-network-auto-assign-floating-ip",
"Specify 'y' to automatically assign a floating IP to "
"new instances ['y', 'n']",
"CONFIG_NOVA_NETWORK_AUTOASSIGNFLOATINGIP",
"n",
options=['y', 'n'],
validators=[validators.y_or_n]),
Argument("nova-network-size",
"Number of addresses in each private subnet",
"CONFIG_NOVA_NETWORK_SIZE",
"255",
validators=[validators.digit]),
Argument("nova-network-multihost",
"Nova network multihost",
"CONFIG_NOVA_NETWORK_MULTIHOST",
"True",
validators=[validators.true_or_false])
]
}
for group in conf:
Controller.get().add_group(group, conf[group])
def init_sequences():
controller = Controller.get()
conf = controller.CONF
if util.str2bool(conf['CONFIG_NOVA_INSTALL']):
controller.add_sequence("Setting up nova controller",
setup_controller)
controller.add_sequence("Setting up nova computes",
setup_computes)
def setup_controller():
conf = Controller.get().CONF
recipe = utils.get_template('nova')
return utils.run_recipe("nova.py", recipe,
[conf["CONFIG_CONTROLLER_HOST"]])
def setup_computes():
conf = Controller.get().CONF
recipe = utils.get_template('nova_compute')
return utils.run_recipe("nova_compute.py", recipe,
conf["CONFIG_COMPUTE_HOSTS"].split(','))
+191
View File
@@ -0,0 +1,191 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
# Author: Obed Muñoz <obed.n.munoz@intel.com>
#
# 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 os
from clearstack.argument import Argument
from clearstack.controller import Controller
from clearstack import validators
from clearstack import utils
from clearstack.common import util
def validate_ssh_key(ssh_key):
hosts = utils.get_all_hosts()
util.remove_localhost(hosts)
if len(hosts) != 0:
validators.file(ssh_key)
def init_config():
home = os.getenv('HOME')
if home is None:
home = "/root"
conf = {
"GENERAL": [
Argument("debug-mode",
"Set to 'y' if you want to run"
" OpenStack services in debug mode",
"CONFIG_DEBUG_MODE",
"n",
options=['y', 'n'],
validators=[validators.y_or_n]),
Argument("ssh-private-key",
"Path to the private SSH key file",
"CONFIG_PRIVATE_SSH_KEY",
"",
validators=[validate_ssh_key]),
Argument("controller-host",
"IP address or hostname of the server on which "
" to install OpenStack services specific to"
" controller role such as API servers",
"CONFIG_CONTROLLER_HOST",
util.get_ip(),
validators=[validators.ip_or_hostname]),
Argument("clean-controller-host",
"Set 'y' if you would like Clearstack to "
"clean up controller host",
"CONFIG_CLEAN_CONTROLLER_HOST",
"y",
validators=[validators.y_or_n]),
Argument("compute-hosts",
"List of IP addresses or hostnames of the server on which"
" to install the Nova compute service",
"CONFIG_COMPUTE_HOSTS",
util.get_ip(),
validators=[validators.ip_or_hostname]),
Argument("clean-compute-hosts",
"Set 'y' if you would like Clearstack to "
"clean up compute hosts",
"CONFIG_CLEAN_COMPUTE_HOSTS",
"y",
validators=[validators.y_or_n]),
Argument("mariadb-install",
"Set 'y' if you would like Clearstack to install MariaDB",
"CONFIG_MARIADB_INSTALL",
"y",
options=['y', 'n'],
validators=[validators.y_or_n]),
Argument("mongodb-install",
"Set 'y' if you would like Clearstack to install MongoDB",
"CONFIG_MONGODB_INSTALL",
"y",
options=['y', 'n'],
validators=[validators.y_or_n]),
Argument("http-service",
"Set 'apache2' or 'nginx' as HTTP Service for Horizon, "
"Keystone and Nova API web services",
"CONFIG_HTTP_SERVICE",
"nginx",
options=['nginx', 'apache2'],
validators=[validators.not_empty]),
Argument("glance-install ",
"Set 'y' if you would like Clearstack to install"
" Openstack image (glance)",
"CONFIG_GLANCE_INSTALL",
"y",
options=['y', 'n'],
validators=[validators.y_or_n]),
Argument("nova-install ",
"Set 'y' if you would like Clearstack to install"
" Openstack compute (nova)",
"CONFIG_NOVA_INSTALL",
"y",
options=['y', 'n'],
validators=[validators.y_or_n]),
Argument("horizon-install",
"Set 'y' if you would like Clearstack to install"
" OpenStack dashboard (horizon)",
"CONFIG_HORIZON_INSTALL",
"y",
options=['y', 'n'],
validators=[validators.y_or_n]),
Argument("neutron-install",
"Set 'y' if you would like Clearstack to install"
" OpenStack Networking (neutron)",
"CONFIG_NEUTRON_INSTALL",
"y",
options=['y', 'n'],
validators=[validators.y_or_n]),
Argument("ceilometer-install",
"Set 'y' if you would like Clearstack to install"
" OpenStack Telemetry (ceilometer)",
"CONFIG_CEILOMETER_INSTALL",
"y",
options=['y', 'n'],
validators=[validators.y_or_n]),
Argument("heat-install",
"Set 'y' if you would like Clearstack to install"
" OpenStack Orchestration (heat)",
"CONFIG_HEAT_INSTALL",
"n",
options=['y', 'n'],
validators=[validators.y_or_n]),
Argument("swift-install",
"Set 'y' if you would like Clearstack to install"
" OpenStack Object Storage (swift)",
"CONFIG_SWIFT_INSTALL",
"n",
options=['y', 'n'],
validators=[validators.y_or_n])
]
}
for group in conf:
Controller.get().add_group(group, conf[group])
def init_sequences():
Controller.get().add_sequence("Setting up controller host",
setup_controller)
Controller.get().add_sequence("Setting up compute hosts",
setup_computes)
def setup_controller():
conf = Controller.get().CONF
if util.str2bool(conf['CONFIG_CLEAN_CONTROLLER_HOST']):
try:
utils.run_recipe("{0}".format("controller_cleanup.sh"),
utils.get_template("controller_cleanup.sh"),
[conf["CONFIG_CONTROLLER_HOST"]])
except:
pass
template = "pre_controller.sh"
recipe = utils.get_template(template)
return utils.run_recipe("{0}".format(template), recipe,
[conf["CONFIG_CONTROLLER_HOST"]])
def setup_computes():
conf = Controller.get().CONF
if util.str2bool(conf['CONFIG_CLEAN_COMPUTE_HOSTS']):
try:
utils.run_recipe("{0}".format("compute_cleanup.sh"),
utils.get_template("compute_cleanup.sh"),
conf["CONFIG_COMPUTE_HOSTS"].split(','))
except:
pass
template = "pre_compute.sh"
recipe = utils.get_template(template)
return utils.run_recipe("{0}".format(template), recipe,
conf["CONFIG_COMPUTE_HOSTS"].split(','))
+86
View File
@@ -0,0 +1,86 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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.
#
from clearstack import utils
from clearstack import validators
from clearstack.controller import Controller
from clearstack.argument import Argument
from clearstack.common import util
def init_config():
conf = {
"PROVISION_INIT": [
Argument("provision-demo",
"Specify 'y' to provision for demo usage and testing."
" ['y', 'n']",
"CONFIG_PROVISION_DEMO",
"n",
options=['y', 'n'],
validators=[validators.y_or_n])
],
"PROVISION_DEMO": [
Argument("provision-demo-floatrange",
"CIDR network address for the floating IP subnet.",
"CONFIG_PROVISION_DEMO_FLOATRANGE",
"172.24.4.224/28",
validators=[validators.cidr]),
Argument("privision-image-format",
'Format for the demo image (default "qcow2").',
"CONFIG_PROVISION_IMAGE_FORMAT",
"qcow2",
validators=[validators.not_empty]),
Argument("provision-image-name",
'The name to be assigned to the demo image in Glance '
'(default "cirros")',
"CONFIG_PROVISION_IMAGE_NAME",
"cirros",
validators=[validators.not_empty]),
Argument("provision-image-url",
'A URL or local file location for an image to download'
'and provision in Glance (defaults to a URL for a '
'recent "cirros" image).',
"CONFIG_PROVISION_IMAGE_URL",
'http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-'
'x86_64-disk.img',
validators=[validators.not_empty])
]
}
for group in conf:
Controller.get().add_group(group, conf[group])
def init_sequences():
controller = Controller.get()
conf = controller.CONF
if util.str2bool(conf['CONFIG_PROVISION_DEMO']):
controller.add_sequence("Running provisioning",
setup_controller)
def setup_controller():
conf = Controller.get().CONF
templates = ['provision']
recipe = ""
for template in templates:
recipe += utils.get_template(template)
return utils.run_recipe("provision.py", recipe,
[conf["CONFIG_CONTROLLER_HOST"]])
+101
View File
@@ -0,0 +1,101 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
#
# 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 os
import stat
from clearstack import utils
from clearstack import validators
from clearstack.controller import Controller
from clearstack.argument import Argument
from clearstack.common import util
def init_config():
conf = {
"SWIFT": [
Argument("swift-ks-pw",
"Password to use for the Object Storage service to "
" authenticate with with the Identity service",
"CONFIG_SWIFT_KS_PW",
utils.generate_random_pw(),
validators=[validators.not_empty]),
Argument("swift-storages",
"Comma-separated list of devices to use as storage device"
" for Object Storage. e.g. /path/to/dev1,/path/to/dev2."
" Clearstack DOES NOT creare the file system, you must "
"format it with xfs. Leave blank to use a loop device",
"CONFIG_SWIFT_STORAGES",
'',
validators=[validate_storage]),
Argument("swift-storage-zones",
"Number of Object Storage storage zones; this number "
"MUST be no larger than the number of configured "
"storage devices.",
"CONFIG_SWIFT_STORAGE_ZONES",
'1',
validators=[validators.digit]),
Argument("swift-storage-replicas",
"Number of Object Storage storage replicas; this number "
"MUST be no larger than the number of configured "
"storage zones.",
"CONFIG_SWIFT_STORAGE_REPLICAS",
'1',
validators=[validators.digit]),
Argument("swift-hash",
"Custom seed number to use for swift_hash_path_suffix in"
" /etc/swift/swift.conf. If you do not provide a value, "
"a seed number is automatically generated.",
"CONFIG_SWIFT_HASH",
utils.generate_random_pw(),
validators=[validators.not_empty]),
Argument("swift-storage-size",
"Size of the Object Storage loopback file storage "
"device in GB",
"CONFIG_SWIFT_STORAGE_SIZE",
"2",
validators=[validators.digit]),
]
}
for group in conf:
Controller.get().add_group(group, conf[group])
def init_sequences():
controller = Controller.get()
conf = controller.CONF
if util.str2bool(conf['CONFIG_SWIFT_INSTALL']):
controller.add_sequence("Setting up swift", setup_swift)
def setup_swift():
conf = Controller.get().CONF
recipe = utils.get_template("swift")
return utils.run_recipe("swift.py", recipe,
[conf["CONFIG_CONTROLLER_HOST"]])
def validate_storage(value):
if not value:
return
devices = value.split(',')
for device in devices:
mode = os.stat(device).st_mode
if not stat.S_ISBLK(mode):
raise ValueError("%s is not a block device" % device)
+110
View File
@@ -0,0 +1,110 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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 re
import os
from importlib import import_module
from clearstack import utils
from clearstack.controller import Controller
from clearstack.common.util import LOG
def load_plugins():
""" return if plugins already are loaded """
if Controller.get().get_all_plugins():
return
path = "plugins"
base_module = "clearstack.{0}".format(path)
directory = "{0}/{1}".format(os.path.dirname(
os.path.realpath(__file__)), path)
rx_val = r'^[a-zA-Z]+_[0-9]{3}\.py$'
files = [fd for fd in os.listdir(directory) if re.match(rx_val, fd)]
for fd in sorted(files, key=_get_weight):
plugin = import_module("{0}.{1}".format(base_module, fd.split(".")[0]))
Controller.get().add_plugin(plugin)
try:
getattr(plugin, "init_config")()
except AttributeError:
LOG.debug("missing attribute: init_config in %s",
plugin.__file__)
def add_arguments(parser):
load_plugins()
for group in Controller.get().get_all_groups():
for argument in group.get_all_arguments():
parser.add_argument("--{0}".format(argument.cmd_option),
action="store",
dest=argument.conf_name,
help=argument.description,
choices=argument.option_list)
def load_sequences():
load_plugins()
for plugin in Controller.get().get_all_plugins():
try:
getattr(plugin, "init_sequences")()
except AttributeError:
LOG.debug("missing attribute: init_sequences in %s",
plugin.__file__)
def run_all_sequences():
load_sequences()
try:
utils.copy_resources()
except Exception as e:
raise e
try:
Controller.get().run_all_sequences()
except Exception as e:
raise e
finally:
utils.get_logs()
def generate_admin_openrc():
conf = Controller.get().CONF
home = os.getenv('HOME')
with open("{0}/admin-openrc.sh".format(home), "w") as f:
f.write('export OS_PROJECT_DOMAIN_ID=default\n')
f.write('export OS_USER_DOMAIN_ID=default\n')
f.write('export OS_PROJECT_NAME=admin\n')
f.write('export OS_USERNAME="admin"\n')
f.write('export OS_TENANT_NAME="admin"\n')
f.write('export OS_AUTH_URL=http://{0}:35357/v3\n'
.format(conf['CONFIG_CONTROLLER_HOST']))
f.write('export OS_REGION_NAME="{0}"\n'
.format(conf['CONFIG_KEYSTONE_REGION']))
f.write('export OS_PASSWORD={0}\n'
.format(conf['CONFIG_KEYSTONE_ADMIN_PW']))
f.write('export OS_IDENTITY_API_VERSION=3\n')
def _get_weight(item):
tmp = item.split('_')[-1]
tmp = tmp.split('.')[0]
return tmp
+39
View File
@@ -0,0 +1,39 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Julio Montes <julio.montes@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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.
#
from clearstack.common.util import LOG
class Sequence:
def __init__(self, desc, function, args=None):
self.description = desc
self.function = function
self.function_args = args
def run(self):
LOG.info(self.description)
if self.function_args:
if not self.function(*self.function_args):
raise Exception("error running {0}({1})"
.format(self.function.__name__,
self.function_args))
else:
if not self.function():
raise Exception("error running {0}"
.format(self.function.__name__))
+143
View File
@@ -0,0 +1,143 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Julio Montes <julio.montes@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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.
#
"""Command-line interface to configure Clearstack."""
from __future__ import print_function
import argparse
import sys
import clearstack
from clearstack.answer_file import AnswerFile
from clearstack import run_setup
from clearstack import utils
from clearstack.common.util import LOG
class ClearstackConfiguratorShell(object):
def __init__(self, parser_class=argparse.ArgumentParser):
self.parser_class = parser_class
def get_base_parser(self):
parser = self.parser_class(
prog='clearstack',
description=__doc__.strip(),
epilog='See "clearstack help COMMAND" '
'for help on a specific command.',
add_help=False,
formatter_class=argparse.HelpFormatter,
)
# Global arguments
parser.add_argument('-h',
'--help',
action='store_true',
help=argparse.SUPPRESS)
parser.add_argument('--version',
action='version',
version=clearstack.__version__,
help="Shows the client version and exits.")
parser.add_argument('-d',
'--debug',
action='store_true',
help="Enable debug mode in clearstack")
parser.add_argument('--gen-answer-file',
action='store',
dest='gen_answer_file',
help='Generate an answer file')
parser.add_argument('--answer-file',
action='store',
dest='answer_file',
help='Read answer file')
parser.add_argument('--gen-keys',
action='store',
dest='gen_keys',
help='Generate ssh keys')
return parser
def main(self, argv):
self.parser = self.get_base_parser()
run_setup.add_arguments(self.parser)
(options, args) = self.parser.parse_known_args(argv)
utils.setup_debugging(options.debug)
LOG.debug('Starting clearstack')
if not argv or options.help:
self.do_help(options)
return 0
if options.gen_keys:
LOG.debug('generating ssh keys')
utils.generate_ssh_keys(options.gen_keys)
# todo: fix
# if options.allinone:
# LOG.debug('testing root access')
# if os.geteuid() != 0:
# LOG.error("clearstack: error: you need to have root access")
# sys.exit(1)
""" Save user's variables, used to read/write answerfile """
variables_cmd = {k: v for (k, v) in options.__dict__.items()
if v is not None and k.startswith("CONFIG_")}
ansfile = AnswerFile.get()
if options.gen_answer_file:
LOG.debug('generating answer file')
ansfile.generate(options.gen_answer_file, variables_cmd)
if options.answer_file:
try:
LOG.debug('Reading answer file')
ansfile.read(options.answer_file, variables_cmd)
LOG.debug('Running all sequences')
run_setup.run_all_sequences()
except Exception as e:
LOG.error("clearstack: {0}".format(str(e)))
sys.exit(1)
LOG.debug('Generating admin-openrc')
run_setup.generate_admin_openrc()
@utils.arg('command', metavar='<subcommand>', nargs='?',
help='Display help for <subcommand>.')
def do_help(self, args):
self.parser.print_help()
def main():
try:
ClearstackConfiguratorShell().main(sys.argv[1:])
except KeyboardInterrupt:
print("... terminating clearstack", file=sys.stderr)
sys.exit(130)
except Exception as e:
print(str(e), file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
sys.exit(main())
+166
View File
@@ -0,0 +1,166 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Julio Montes <julio.montes@intel.com>
# Author: Obed Muñoz <obed.n.munoz@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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 os
import paramiko
from clearstack.controller import Controller
from clearstack.common import util
from clearstack.common.util import LOG
from clearstack.common.singleton import Singleton
@Singleton
class SshHandler(object):
def __init__(self):
conf = Controller.get().CONF
path = os.path.expanduser(
conf['CONFIG_PRIVATE_SSH_KEY'])
path = os.path.realpath(path)
self.ssh_private_key = path
self.ssh_user = "root"
def connect(self, user, key_file, host):
''' Creates a connection to the host using SSH key '''
private_key = paramiko.RSAKey.from_private_key_file(key_file)
connection = paramiko.SSHClient()
connection.set_missing_host_key_policy(paramiko.AutoAddPolicy())
connection.connect(hostname=host, username=user, pkey=private_key,
timeout=1000)
return connection
def run_command(self, connection, command):
try:
stdin, stdout, stderr = connection.exec_command(command)
while not stdout.channel.exit_status_ready():
pass
except Exception as e:
raise e
''' if stderr is not empty then something fail '''
error = stderr.read()
if error:
raise Exception(error.decode('utf-8'))
return stdin, stdout, stderr
def transfer_file(self, file, dest_path, ip):
try:
connection = self.connect(self.ssh_user, self.ssh_private_key, ip)
sftp = connection.open_sftp()
except paramiko.ssh_exception.SSHException:
raise Exception("cannot send {0} to {1}, please check"
" your ssh connection".format(file, ip))
if os.path.isdir(file):
parent_dir = "/".join(file.split('/')[:-1])
try:
sftp.mkdir(dest_path)
except IOError:
pass
for dirpath, dirnames, filenames in os.walk(file):
remote_path = dest_path + dirpath.split(parent_dir)[1]
try:
sftp.mkdir(remote_path)
except:
LOG.info("clearstack: Directory {0} is already created"
"in remote host".format(remote_path))
for filename in filenames:
local_path = os.path.join(dirpath, filename)
remote_filepath = os.path.join(remote_path, filename)
sftp.put(local_path, remote_filepath)
else:
filename = file.split('/')[-1]
sftp.put(file, "{0}/{1}".format(dest_path, filename))
connection.close()
def test_python_in_host(self, host, connection):
try:
stdin, stdout, stderr = self.run_command(connection,
'python3 --version')
except:
raise Exception("cannot run python3 in {0},"
" please install python3".format(host))
def test_hosts(self, _hosts):
hosts = set(_hosts)
connection = None
conf = Controller.get().CONF
util.remove_localhost(hosts)
if not conf['CONFIG_PRIVATE_SSH_KEY'] and hosts:
raise Exception("CONFIG_PRIVATE_SSH_KEY: missing private key")
for host in hosts:
try:
connection = self.connect(self.ssh_user, self.ssh_private_key,
host)
self.test_python_in_host(host, connection)
except Exception as e:
raise Exception("host {0}: {1}".format(host, str(e)))
finally:
if connection:
connection.close()
def run_recipe(self, recipe_file, host):
connection = None
interpreter = "python3"
if recipe_file.endswith('.sh'):
interpreter = "bash -f"
try:
connection = self.connect(self.ssh_user, self.ssh_private_key,
host)
cmd = "source /root/.bashrc 2> /dev/null;" \
"source /usr/share/defaults/etc/profile 2> /dev/null;" \
"{0} {1}".format(interpreter, recipe_file)
stdin, stdout, stderr = self.run_command(connection, cmd)
except Exception as e:
LOG.error("clearstack: an error has occurred in {0},"
" please check logs for more information"
.format(host))
raise e
finally:
if connection:
connection.close()
def get_logs(self, _hosts):
hosts = set(_hosts)
basename = os.path.splitext(util.LOG_FILE)[0]
connection = None
util.remove_localhost(hosts)
for host in hosts:
new_name = "{0}-{1}.log".format(basename, host)
try:
connection = self.connect(self.ssh_user, self.ssh_private_key,
host)
sftp = connection.open_sftp()
sftp.get(util.HOST_LOG_FILE, new_name)
except:
LOG.warning("clearstack: cannot get log file from {0}".format(
host))
finally:
if connection:
connection.close()
View File
+38
View File
@@ -0,0 +1,38 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
#
# 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.
#
from modules.ceilometer import Ceilometer
from common import util
ceilometer = Ceilometer.get()
config_file = "/etc/ceilometer/ceilometer.conf"
ceilometer.install()
ceilometer.create_user()
ceilometer.create_service()
ceilometer.create_endpoint()
ceilometer.config_debug(config_file)
ceilometer.config_database(config_file)
ceilometer.config_rabbitmq(config_file)
ceilometer.config_auth(config_file)
ceilometer.config_service_credentials(config_file)
util.run_command("systemctl restart update-triggers.target")
ceilometer.start_server()
+48
View File
@@ -0,0 +1,48 @@
#!/bin/bash
# reset neutron services
neutron_services="neutron-server neutron-linuxbridge-agent \
neutron-dhcp-agent neutron-metadata-agent neutron-l3-agent"
systemctl stop $neutron_services
systemctl disable $neutron_services
# Reset compute services
systemctl disable libvirtd.socket libvirtd.service nova-compute.service \
nova-network.service nova-metadata.{socket,service}
systemctl stop libvirtd.socket libvirtd.service nova-compute.service \
nova-network.service nova-metadata.{socket,service}
# Delete nova config file
rm -rf /etc/nova
# Update /etc/nova permissions
systemctl restart update-triggers.target
# Clean Bridges
ip link set br100 down
brctl delbr br100
# Restart network service
systemctl restart systemd-networkd
# Clean Nova data
rm -rf /var/lib/nova/CA/*
rm -rf /var/lib/nova/instances/*
rm -rf /var/lib/nova/keys/*
rm -rf /var/lib/nova/networks/*
# Clean Libvirt data
rm -rf /var/lib/libvirt/qemu/*.monitor
rm -rf /etc/libvirt/nwfilter/*
rm -rf /etc/libvirt/qemu/*
# Kill reamining qemu VMs
ps aux | grep qemu | grep -v grep | awk '{print $2}' | xargs kill -9
# Kill all about dnsmasq
ps aux | grep dnsmasq | grep -v grep | awk '{print $2}' | xargs kill -9
# Clean Logs
rm -rf /var/log/nova/*
rm -rf /var/log/libvirt/qemu/*
rm -rf /var/log/swupd/*
@@ -0,0 +1,55 @@
#!/bin/bash
# reset neutron services
neutron_services="neutron-server neutron-linuxbridge-agent \
neutron-dhcp-agent neutron-metadata-agent neutron-l3-agent"
systemctl stop $neutron_services
systemctl disable $neutron_services
# reset nova services
systemctl stop memcached uwsgi@nova-{api,metadata}.{service,socket} nova-cert \
nova-consoleauth nova-scheduler \
nova-conductor nova-novncproxy
systemctl disable memcached uwsgi@nova-{api,metadata}.{service,socket} nova-cert \
nova-consoleauth nova-scheduler \
nova-conductor nova-novncproxy
rm -rf /etc/nova
# reset glance services
systemctl stop glance-api glance-registry
systemctl disable glance-api glance-registry
rm -rf /etc/glance
rm -rf /var/lib/glance/images/*
# reset keystone services
systemctl stop httpd nginx uwsgi@keystone{admin,public}.{socket,service}
systemctl disable httpd nginx
rm -rf /etc/keystone
rm /etc/httpd/conf.d/wsgi-keystone.conf
# reset horizon
systemctl stop httpd nginx uwsgi@horizon.{socket,service}
# reset owners and permissions
systemctl restart update-triggers.target
# reset rabbitmq
systemctl stop rabbitmq-server
systemctl disable rabbitmq-server
rm -rf /etc/rabbitmq/rabbitmq.config
rm -rf /var/lib/rabbitmq/*
rm -rf /etc/hosts
# reset mariadb
systemctl stop mariadb
systemctl disable mariadb
rm -rf /etc/mariadb
rm -rf /var/lib/mysql
# Clean Logs
rm -rf /var/log/nova/*
rm -rf /var/log/keystone/*
rm -rf /var/log/glance/*
rm -rf /var/log/rabbitmq/*
rm -rf /var/log/httpd/*
rm -rf /var/log/swupd/*
+43
View File
@@ -0,0 +1,43 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
#
# 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.
#
from common import util
from modules.conf import CONF
from modules.glance import Glance
glance = Glance.get()
config_files = ["/etc/glance/glance-api.conf"]
config_files.append("/etc/glance/glance-registry.conf")
glance.install()
glance.create_user()
glance.create_service()
glance.create_endpoint()
for config_file in config_files:
glance.config_debug(config_file)
glance.config_database(config_file)
glance.config_auth(config_file)
if util.str2bool(CONF['CONFIG_CEILOMETER_INSTALL']):
glance.ceilometer_enable(config_file)
util.run_command("systemctl restart update-triggers.target")
glance.sync_database()
glance.start_server()
+49
View File
@@ -0,0 +1,49 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
#
# 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.
#
from common import util
from modules.heat import Heat
heat = Heat.get()
config_file = "/etc/heat/heat.conf"
heat.install()
heat.create_user()
heat.create_service(name='heat', description='OpenStack Orchestration',
type='orchestration')
heat.create_service(name='heat-cfn', description='OpenStack Orchestration',
type='cloudformation')
heat.create_endpoint()
publicurl = "http://%s:8000/v1" % heat._controller
heat.create_endpoint(publicurl=publicurl, internalurl=publicurl,
adminurl=publicurl, type='cloudformation')
heat.create_domain(heat.domain_name, 'Stack projects and users')
heat.create_user(user=heat.domain_admin, password=heat.domain_admin_pw,
domain=heat.domain_name)
heat.create_role('heat_stack_owner')
heat.create_role('heat_stack_user')
heat.config_database(config_file)
heat.config_rabbitmq(config_file)
heat.config_auth(config_file)
heat.config_domain(config_file)
util.run_command("systemctl restart update-triggers.target")
heat.sync_database()
heat.start_server()
+24
View File
@@ -0,0 +1,24 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
#
# 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.
#
from modules.horizon import Horizon
horizon = Horizon.get()
horizon.install()
horizon.start_server()
+47
View File
@@ -0,0 +1,47 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
#
# 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.
#
from modules.conf import CONF
from modules.keystone import Keystone
from common import util
keystone = Keystone.get()
config_file = "/etc/keystone/keystone.conf"
keystone.install()
keystone.config_debug(config_file)
keystone.config_database(config_file)
keystone.config_admin_token(config_file)
util.run_command("systemctl restart update-triggers.target")
keystone.sync_database()
keystone.start_server()
keystone.create_service()
keystone.create_endpoint()
keystone.create_project("admin", "Admin Project")
keystone.create_role("admin")
keystone.create_user(user="admin", project="admin", role="admin")
keystone.create_project("service", "Service Project")
keystone.create_project("demo", "Demo Project")
keystone.create_role("user")
keystone.create_user(user="demo", project="demo", role="user",
password=CONF['CONFIG_KEYSTONE_DEMO_PW'])
util.delete_option(config_file, "DEFAULT", "admin_token")
keystone.start_server()
+46
View File
@@ -0,0 +1,46 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
#
# 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 socket
from common.util import LOG
from common import util
from modules.conf import CONF
from modules.mariadb import MariaDB
conf = CONF
mariadb = MariaDB.get()
mariadb_user = CONF["CONFIG_MARIADB_USER"]
mariadb_pw = CONF["CONFIG_MARIADB_PW"]
controller = socket.gethostbyaddr(CONF["CONFIG_CONTROLLER_HOST"])[0]
if util.str2bool(conf['CONFIG_MARIADB_INSTALL']):
mariadb.install()
mariadb.configure()
mariadb.start_server()
mariadb.secure_installation(mariadb_user, mariadb_pw)
databases = ['keystone', 'glance', 'nova', 'neutron', 'heat']
for database in databases:
if database == 'keystone' or util.str2bool(conf['CONFIG_%s_INSTALL'
% database.upper()]):
LOG.info("Setting up mariadb for %s" % database)
password = CONF['CONFIG_%s_DB_PW' % database.upper()]
mariadb.setup_database(database, database, password, controller)
+31
View File
@@ -0,0 +1,31 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
#
# 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.
#
from common import util
from modules.conf import CONF
from modules.mongodb import MongoDB
mongo = MongoDB.get()
if util.str2bool(CONF['CONFIG_MONGODB_INSTALL']):
mongo.install()
mongo.configure()
mongo.start_server()
mongo.setup_database('ceilometer', 'ceilometer',
CONF['CONFIG_CEILOMETER_DB_PW'])
+60
View File
@@ -0,0 +1,60 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
#
# 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.
#
from modules.conf import CONF
from modules.neutron import Neutron
from common import util
neutron = Neutron.get()
config_file = "/etc/neutron/neutron.conf"
# Install neutron controller
neutron.install()
neutron.create_user()
neutron.create_service()
neutron.create_endpoint()
# Configure neutron controller
neutron.config_debug(config_file)
neutron.config_database(config_file)
neutron.config_rabbitmq(config_file)
neutron.config_auth(config_file)
neutron.config_nova(config_file)
neutron.config_ml2_plugin()
neutron.config_linux_bridge_agent()
neutron.config_l3_agent("/etc/neutron/l3_agent.ini")
neutron.config_dhcp_agent("/etc/neutron/dhcp_agent.ini")
neutron.config_metadata_agent("/etc/neutron/metadata_agent.ini")
neutron.config_neutron_on_nova("/etc/nova/nova.conf")
if util.str2bool(CONF['CONFIG_CEILOMETER_INSTALL']):
neutron.ceilometer_enable(config_file)
if util.str2bool(CONF['CONFIG_LBAAS_INSTALL']):
neutron.install('openstack-lbaas')
neutron.config_lbaas()
if util.str2bool(CONF['CONFIG_VPNAAS_INSTALL']):
neutron.install('openstack-vpnaas')
neutron.config_vpnaas()
util.run_command("systemctl restart update-triggers.target")
neutron.sync_database()
neutron.start_server()
+40
View File
@@ -0,0 +1,40 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
#
# 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.
#
from modules.conf import CONF
from modules.neutron import Neutron
from common import util
neutron = Neutron.get()
config_file = "/etc/neutron/neutron.conf"
services = ['nova-compute', 'neutron-linuxbridge-agent']
neutron.install()
neutron.config_debug(config_file)
neutron.config_rabbitmq(config_file)
neutron.config_auth(config_file)
neutron.config_linux_bridge_agent()
neutron.config_neutron_on_nova('/etc/nova/nova.conf')
if util.str2bool(CONF['CONFIG_CEILOMETER_INSTALL']):
neutron.ceilometer_enable(config_file)
util.run_command("systemctl restart update-triggers.target")
neutron.start_server(services)
+72
View File
@@ -0,0 +1,72 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
#
# 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.
#
from modules.nova import Nova
from modules.conf import CONF
from common import util
nova = Nova.get()
config_file = "/etc/nova/nova.conf"
my_ip = util.get_ip()
# Install nova controller
nova.install()
nova.create_user()
nova.create_service()
nova.create_endpoint()
# Configure nova controller
nova.config_debug(config_file)
nova.config_database(config_file)
nova.config_rabbitmq(config_file)
nova.config_auth(config_file)
# Setup vncproxy
config = \
"[DEFAULT]\n" + \
"my_ip=%s\n" % my_ip + \
"[vnc]\n" + \
"vncserver_listen=0.0.0.0\n" + \
"vncserver_proxyclient_address=%s\n" % my_ip
util.write_config(config_file, config)
# Setup glance host
config = \
"[glance]\n" + \
"host=%s\n" % CONF['CONFIG_CONTROLLER_HOST']
util.write_config(config_file, config)
# Setup nova-network if neutron is not installed
if not util.str2bool(CONF['CONFIG_NEUTRON_INSTALL']):
config = \
"[DEFAULT]\n" + \
"network_api_class = nova.network.api.API\n" + \
"security_group_api = nova\n"
util.write_config(config_file, config)
if CONF['CONFIG_HTTP_SERVICE'] == 'nginx':
util.link_file('/usr/share/nginx/conf.d/nova-api.template',
'/etc/nginx/nova-api.conf')
else:
util.link_file('/usr/share/defaults/httpd/conf.d/nova-api.template',
'/etc/httpd/conf.d/nova-api.conf')
util.run_command("systemctl restart update-triggers.target")
nova.sync_database()
nova.start_server()
+97
View File
@@ -0,0 +1,97 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
# Author: Obed Muñoz <obed.n.munoz@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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.
#
from modules import clearlinux
from modules.nova import Nova
from modules.conf import CONF
from common import util
nova = Nova.get()
config_file = "/etc/nova/nova.conf"
services = ['libvirtd.socket', 'nova-compute']
my_ip = util.get_ip()
if CONF['CONFIG_HTTP_SERVICE'] == 'nginx':
services.extend(['nginx', 'uwsgi@nova-metadata.socket'])
elif CONF['CONFIG_HTTP_SERVICE'] == 'apache2':
services.append('httpd')
else:
services.append('nova-api-metadata')
nova.install_compute()
nova.config_debug(config_file)
nova.config_rabbitmq(config_file)
nova.config_auth(config_file)
# Setup vncproxy server
config = ("[DEFAULT]\n"
"my_ip={0}\n"
"[vnc]\n"
"vnc_enabled=True\n"
"vncserver_listen=0.0.0.0\n"
"vncserver_proxyclient_address={0}\n"
"novncproxy_base_url=http://{1}:6080/vnc_auto.html\n"
.format(my_ip, CONF['CONFIG_CONTROLLER_HOST']))
# Setup glance host
config += ("[glance]\n"
"host=%s\n") % CONF['CONFIG_CONTROLLER_HOST']
# Disable HW acceleration on unsupported HW
if not clearlinux.support_hw_acceleration():
config += ("[libvirt]\n"
"virt_type=qemu\n")
util.write_config(config_file, config)
# Setup compute Networking
if not util.str2bool(CONF['CONFIG_NEUTRON_INSTALL']):
services.append("nova-network")
network_manager = CONF['CONFIG_NOVA_NETWORK_MANAGER']
network_size = CONF['CONFIG_NOVA_NETWORK_SIZE']
multihost = CONF['CONFIG_NOVA_NETWORK_MULTIHOST']
network_pubif = CONF['CONFIG_NOVA_NETWORK_PUBIF']
network_privif = CONF['CONFIG_NOVA_COMPUTE_PRIVIF']
config = \
"[DEFAULT]\n" + \
"network_api_class=nova.network.api.API\n" + \
"security_group_api=nova\n" + \
"firewall_driver=" + \
"nova.virt.libvirt.firewall.IptablesFirewallDriver\n" + \
"network_size=%s\n" % network_size + \
"allow_same_net_traffic=False\n" + \
"multi_host=%s\n" % multihost + \
"send_arp_for_ha=True\n" + \
"share_dhcp_address=True\n" + \
"force_dhcp_release=True\n" + \
"flat_network_bridge=br100\n" + \
"public_interface=%s\n" % network_pubif + \
"flat_interface=%s\n" % network_privif
if util.str2bool(CONF['CONFIG_NOVA_NETWORK_AUTOASSIGNFLOATINGIP']):
config += "auto_assign_floating_ip = True\n"
util.write_config(config_file, config)
if util.str2bool(CONF['CONFIG_CEILOMETER_INSTALL']):
nova.ceilometer_enable(config_file)
util.run_command("systemctl restart update-triggers.target")
nova.start_server(services)
+26
View File
@@ -0,0 +1,26 @@
#!/bin/bash
#
# Copyright (c) 2015 Intel Corporation
#
# 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.
#
if [ -f /bin/swupd ];then
if [ ! -f /usr/share/clear/bundles/openstack-configure ];then
swupd bundle-add openstack-configure
fi
elif [ -f /bin/clr_bundle_add];then
if [ ! -f /usr/share/clear/bundles/openstack-configure ];then
clr_bundle_add openstack-configure
fi
fi
+34
View File
@@ -0,0 +1,34 @@
#!/bin/bash
#
# Copyright (c) 2015 Intel Corporation
#
# 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.
#
if [ -f /bin/swupd ];then
if [ ! -f /usr/share/clear/bundles/openstack-configure ];then
swupd bundle-add openstack-configure
fi
if [ ! -f /usr/share/clear/bundles/openstack-python-clients -a ! -f /usr/share/clear/bundles/openstack-all-in-one ];then
swupd bundle-add openstack-python-clients
fi
elif [ -f /bin/clr_bundle_add];then
if [ ! -f /usr/share/clear/bundles/openstack-configure ];then
clr_bundle_add openstack-configure
fi
if [ ! -f /usr/share/clear/bundles/openstack-python-clients -a ! -f /usr/share/clear/bundles/openstack-all-in-one ];then
clr_bundle_add openstack-python-clients
fi
fi
+44
View File
@@ -0,0 +1,44 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
#
# 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.
#
from modules.glance import Glance
from modules.neutron import Neutron
from modules.nova import Nova
from modules.conf import CONF
from common import util
glance = Glance.get()
nova = Nova.get()
neutron = Neutron.get()
if util.str2bool(CONF['CONFIG_PROVISION_DEMO']):
name = CONF['CONFIG_PROVISION_IMAGE_NAME']
format = CONF['CONFIG_PROVISION_IMAGE_FORMAT']
url = CONF['CONFIG_PROVISION_IMAGE_URL']
glance.create_image(name, format, url, public=True)
fr = CONF['CONFIG_PROVISION_DEMO_FLOATRANGE']
CONF['CONFIG_NOVA_NETWORK_FLOATRANGE'] = fr
if not util.str2bool(CONF['CONFIG_NEUTRON_INSTALL']):
nova.create_network()
nova.create_floating_ips()
else:
neutron.create_network('private', public=False)
neutron.create_network('public', public=True)
neutron.create_router('router', gw='public', interfaces=['private'])
+29
View File
@@ -0,0 +1,29 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Julio Montes <julio.montes@intel.com>
#
# 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.
#
from modules.rabbitmq import Rabbitmq
from modules.conf import CONF
rabbitmq_auth_user = CONF["CONFIG_AMQP_AUTH_USER"]
rabbitmq_auth_pw = CONF["CONFIG_AMQP_AUTH_PASSWORD"]
rabbit = Rabbitmq.get()
rabbit.install()
rabbit.start_server()
rabbit.add_user(rabbitmq_auth_user, rabbitmq_auth_pw)
rabbit.set_permissions(rabbitmq_auth_user, '".*" ".*" ".*"')
+58
View File
@@ -0,0 +1,58 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
#
# 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.
#
from common import util
from modules.conf import CONF
from modules.swift import Swift
swift = Swift.get()
config_file = "/etc/swift/proxy-server.conf"
swift.install()
swift.create_user()
swift.create_service()
swift.create_endpoint()
swift.config_auth(config_file)
swift.config_memcache(config_file)
swift.config_hash('/etc/swift/swift.conf')
# Storage configuration
swift.parse_devices()
swift.prepare_devices()
swift.create_rings()
swift.config_rsync()
swift.config_storage_services()
if util.str2bool(CONF['CONFIG_CEILOMETER_INSTALL']):
swift.ceilometer_enable(config_file)
util.run_command("systemctl restart update-triggers.target")
# Start controller services
swift.start_server()
# Start storage node services
services = ['rsyncd', 'swift-account', 'swift-account-auditor',
'swift-account-reaper', 'swift-account-replicator',
'swift-container', 'swift-container-auditor',
'swift-container-replicator', 'swift-container-updater',
'swift-object', 'swift-object-auditor',
'swift-object-replicator', 'swift-object-updater']
swift.start_server(services)
View File
+51
View File
@@ -0,0 +1,51 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Julio Montes <julio.montes@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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 mock
import testtools
from clearstack.answer_file import AnswerFile
from clearstack.argument import Argument
from clearstack.controller import Controller
conf = {'COMPONENT': [Argument('argument',
'description',
'CONFIG_ARGUMET',
'secure')]}
for group in conf:
Controller.get().add_group(group, conf[group])
class AnswerFileTest(testtools.TestCase):
def setUp(self):
super(AnswerFileTest, self).setUp()
def test_generate_file(self):
m = mock.mock_open()
filename = '/tmp/clearstack.answerfile'
with mock.patch('clearstack.answer_file.open', m, create=True):
AnswerFile.get().generate(filename, {})
m.assert_called_once_with(filename, 'w')
@mock.patch('os.path.isfile')
def test_read_non_existing_file(self, mock_isfile):
mock_isfile.side_effect = [False]
filename = '/tmp/clearstack.answerfile'
self.assertRaises(IOError, AnswerFile.get().read, filename, {})
+37
View File
@@ -0,0 +1,37 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Julio Montes <julio.montes@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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 testtools
class ArgumentTest(testtools.TestCase):
def setUp(self):
super(ArgumentTest, self).setUp()
# def test_argument_validate(self):
# argument = Argument('cmd_option', 'description', 'conf_name',
# 'default_value')
# self.assertTrue(argument.validate('test'))
# def validator(value):
# return 'ERROR'
# argument = Argument('cmd_option', 'description', 'conf_name',
# 'default_value', [validator])
# self.assertFalse(argument.validate('test'))
+51
View File
@@ -0,0 +1,51 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Julio Montes <julio.montes@intel.com>
#
# 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 testtools
from clearstack.common import util
class ModulesUtilTest(testtools.TestCase):
def setUp(self):
super(ModulesUtilTest, self).setUp()
# # Test if run_command is hidden debug logs
# def test_0000_run_command(self):
# util.setup_debugging(True, False)
# util.run_command("echo", debug=False)
# logging.StreamHandler().close()
# self.assertEqual("echo" in open(self.log_file).read(), False)
# # Test if run_command is showing debug logs
# def test_0001_run_command(self):
# util.setup_debugging(True, False)
# util.run_command("echo")
# logging.StreamHandler().close()
# self.assertEqual("echo" in open(self.log_file).read(), True)
# Test command not found
def test_0002_run_command(self):
self.assertRaises(Exception, util.run_command, "inexistente")
# Test simple command
def test_0003_run_command(self):
try:
util.run_command("echo")
except Exception:
self.fail()
+39
View File
@@ -0,0 +1,39 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Julio Montes <julio.montes@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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 mock
import testtools
from clearstack.sequence import Sequence
class SequenceTest(testtools.TestCase):
def setUp(self):
super(SequenceTest, self).setUp()
def test_run(self):
mock_function = mock.Mock(return_value=False)
mock_function.__name__ = 'Bar'
seq = Sequence('test', mock_function)
self.assertRaises(Exception, seq.run)
seq = Sequence('test', mock_function, ["subsequence"])
self.assertRaises(Exception, seq.run)
+35
View File
@@ -0,0 +1,35 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Julio Montes <julio.montes@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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 testtools
from testtools import matchers
from clearstack.tests import utils
class ShellTest(testtools.TestCase):
def setUp(self):
super(ShellTest, self).setUp()
def test_help(self):
required = 'usage:'
help_text = utils.shell('--help')
self.assertThat(help_text,
matchers.MatchesRegex(required))
+42
View File
@@ -0,0 +1,42 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Julio Montes <julio.montes@intel.com>
#
# 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 os
import sys
import io
from clearstack import shell as clearstack_shell
def shell(argstr):
orig = sys.stdout
clean_env = {}
_old_env, os.environ = os.environ, clean_env.copy()
try:
sys.stdout = io.StringIO()
_shell = clearstack_shell.ClearstackConfiguratorShell()
_shell.main(argstr.split())
except SystemExit:
exc_type, exc_value, exc_traceback = sys.exc_info()
assert exc_value, 0
finally:
out = sys.stdout.getvalue()
sys.stdout.close()
sys.stdout = orig
os.environ = _old_env
return out
+200
View File
@@ -0,0 +1,200 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
# Author: Victor Morales <victor.morales@intel.com>
#
# 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 calendar
import configparser
import datetime
import os
import binascii
import time
import shutil
from clearstack import controller
from clearstack.ssh import SshHandler
from clearstack.controller import Controller
from clearstack.common import util
__now = datetime.datetime.now()
__recipes_directory = "/tmp/clearstack-{0}-{1}-{2}-{3}/".format(
__now.year, __now.month, __now.day, calendar.timegm(time.gmtime()))
def arg(*args, **kwargs):
def _decorator(func):
func.__dict__.setdefault('arguments', []).insert(0, (args, kwargs))
return func
return _decorator
def run_recipe(recipe_file, recipe_src, hosts):
recipes_dir = __recipes_directory
if not os.path.isdir(recipes_dir):
os.makedirs(recipes_dir)
if controller.DEBUG and recipe_file.endswith('.py'):
recipe_src = "from common import util\n" + \
"util.setup_debugging(True)\n\n" + \
recipe_src
recipe_file = os.path.join(recipes_dir, recipe_file)
with open(recipe_file, "w") as f:
f.write(recipe_src)
_run_recipe_in_hosts(recipe_file, recipes_dir, hosts)
return True
def _run_recipe_local(recipe_file):
if recipe_file.endswith('.py'):
util.run_command("python3 {0}".format(recipe_file))
else:
util.run_command("bash -f {0}".format(recipe_file))
def _run_recipe_in_hosts(recipe_file, recipes_dir, _hosts):
hosts = set(_hosts)
ssh = SshHandler.get()
if util.has_localhost(hosts):
_run_recipe_local(recipe_file)
util.remove_localhost(hosts)
for host in hosts:
try:
ssh.transfer_file(recipe_file, recipes_dir, host)
ssh.run_recipe(recipe_file, host)
except Exception as e:
raise e
def get_all_hosts():
conf = Controller.get().CONF
hosts = set()
hosts.update(set(conf["CONFIG_COMPUTE_HOSTS"].split(",")))
hosts.add(conf["CONFIG_CONTROLLER_HOST"])
hosts.add(conf["CONFIG_AMQP_HOST"])
hosts.add(conf["CONFIG_MARIADB_HOST"])
hosts.add(conf["CONFIG_MONGODB_HOST"])
return hosts
def generate_conf_file(conf_file):
""" create defaults.conf file """
conf = Controller.get().CONF
config_file = configparser.RawConfigParser()
config_file.optionxform = str
dir_name = os.path.dirname(conf_file)
if not os.path.isdir(dir_name):
os.makedirs(dir_name)
config_file.add_section("general")
for key in conf.keys():
config_file.set("general", key, '{0}'.format(conf[key]))
with open(conf_file, 'w') as f:
config_file.write(f)
def copy_resources():
_copy_resources_to_hosts(get_all_hosts())
return True
def _copy_resources_local():
resources_dir = os.path.dirname(os.path.realpath(__file__))
modules_src = "{0}/modules".format(resources_dir)
common_src = "{0}/common".format(resources_dir)
modules_dst = "{0}/modules".format(__recipes_directory)
common_dst = "{0}/common".format(__recipes_directory)
conf_file = "{0}/defaults.conf".format(__recipes_directory)
generate_conf_file(conf_file)
shutil.copytree(modules_src, modules_dst)
shutil.copytree(common_src, common_dst)
def _copy_resources_to_hosts(_hosts):
try:
SshHandler.get().test_hosts(_hosts)
except Exception as e:
raise e
hosts = set(_hosts)
ssh = SshHandler.get()
resources_dir = os.path.dirname(os.path.realpath(__file__))
modules_dir = "{0}/modules".format(resources_dir)
common_dir = "{0}/common".format(resources_dir)
conf_file = "{0}/defaults.conf".format(__recipes_directory)
if util.has_localhost(hosts):
_copy_resources_local()
util.remove_localhost(hosts)
if not os.path.isfile(conf_file):
generate_conf_file(conf_file)
""" Copy modules and conf to hosts """
for host in hosts:
try:
ssh.transfer_file(modules_dir, __recipes_directory, host)
ssh.transfer_file(common_dir, __recipes_directory, host)
ssh.transfer_file(conf_file, __recipes_directory, host)
except Exception as e:
raise e
return True
def get_logs():
SshHandler.get().get_logs(get_all_hosts())
def get_template(template):
directory = "{0}/{1}".format(os.path.dirname(
os.path.realpath(__file__)), "templates")
if not template.endswith(".sh"):
template = template + ".py"
template = os.path.join(directory, template)
source = "\n{0} {1} {0}\n".format("#" * 5, template)
with open(template, 'r') as f:
source += f.read()
source += "\n{0}\n".format("#" * 60)
return source
raise Exception("cannot load {0} template".format(template))
def generate_random_pw():
return binascii.b2a_hex(os.urandom(10)).decode("utf-8")
def generate_ssh_keys(output):
util.run_command("ssh-keygen -b 4096 -f {0} -a 500 -N ''"
.format(output))
def setup_debugging(debug):
controller.DEBUG = debug
util.setup_debugging(debug, is_remote_host=False)
+62
View File
@@ -0,0 +1,62 @@
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Alberto Murillo <alberto.murillo.silva@intel.com>
# Author: Julio Montes <julio.montes@intel.com>
#
# 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 ipaddress
import os
import socket
def y_or_n(value):
if not value.lower() in ("n", "y"):
raise ValueError("please set 'y' or 'n'")
def true_or_false(value):
if not value.lower() in ("true", "false"):
raise ValueError("please set 'True' or 'False'")
def ip_or_hostname(value):
for v in value.split(","):
try:
ipaddress.ip_address(v)
except ValueError:
socket.gethostbyname(v)
def cidr(value):
ip = ipaddress.ip_network(value)
if not ip:
raise ValueError("Invalid cidr")
def file(value):
value = os.path.expanduser(value)
if not os.path.exists(value):
raise ValueError("file {0} not found".format(value))
def not_empty(value):
if not value.strip():
raise ValueError("empty value")
def digit(value):
if not value.isdigit():
raise ValueError("{0} is not a digit".format(value))
+5
View File
@@ -0,0 +1,5 @@
pbr # Apache-2.0
ipaddress # Python-2.0
netifaces # MIT
paramiko # LGPL-2.1
sphinx # BSD-2-Clause
+55
View File
@@ -0,0 +1,55 @@
[metadata]
name = clearstack
summary = Tool for set up an OpenStack environment
description-file =
README.rst
author = Alberto Murillo, Julio Montes, Obed Muñoz, Victor Morales
home-page =
classifier =
Environment :: OpenStack
Intended Audience :: Information Technology
Intended Audience :: System Administrators
License :: OSI Approved :: Apache Software License
Operating System :: POSIX :: Linux
Programming Language :: Python :: 3
Programming Language :: Python :: 3.3
[files]
packages =
clearstack
[global]
setup-hooks =
pbr.hooks.setup_hook
[entry_points]
console_scripts =
clearstack = clearstack.shell:main
[build_sphinx]
source-dir = doc/source
build-dir = doc/build
all_files = 1
[pbr]
warnerrors = True
[upload_sphinx]
upload-dir = doc/build/html
[compile_catalog]
directory = clearstack/locale
domain = clearstack
[update_catalog]
domain = clearstack
output_dir = clearstack/locale
input_file = clearstack/locale/clearstack.pot
[extract_messages]
keywords = _ gettext ngettext l_ lazy_gettext
mapping_file = babel.cfg
output_file = clearstack/locale/clearstack.pot
[wheel]
universal = 1
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env python
#
# Copyright (c) 2015 Intel Corporation
#
# Author: Julio Montes <julio.montes@intel.com>
#
# 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.
#
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
import setuptools
# In python < 2.7.4, a lazy loading of package `pbr` will break
# setuptools if some other modules registered functions in `atexit`.
# solution from: http://bugs.python.org/issue15881#msg170215
try:
import multiprocessing # noqa
except ImportError:
pass
setuptools.setup(
setup_requires=['pbr'],
pbr=True,
packages=['clearstack'],
package_dir={'clearstack': 'clearstack'},
scripts=['clearstack/templates/pre_compute.sh',
'clearstack/templates/pre_controller.sh']
)
+4
View File
@@ -0,0 +1,4 @@
coverage>=3.6
flake8>=2.2.4
testrepository>=0.0.18
mock
+41
View File
@@ -0,0 +1,41 @@
[tox]
minversion = 1.6
skipsdist = True
envlist = py34,pep8
[testenv]
usedevelop = True
install_command = pip install -U {opts} {packages}
setenv = VIRTUAL_ENV={envdir}
OS_STDOUT_NOCAPTURE=False
OS_STDERR_NOCAPTURE=False
deps = -r{toxinidir}/requirements-py3.txt
-r{toxinidir}/test-requirements-py3.txt
commands = python setup.py testr --testr-args='{posargs}'
[testenv:pep8]
commands =
flake8
[testenv:venv]
commands = {posargs}
[testenv:cover]
commands = python setup.py testr --coverage --testr-args='{posargs}'
[tox:jenkins]
downloadcache = ~/cache/pip
[testenv:debug]
commands = oslo_debug_helper -t keystoneclient/tests {posargs}
[flake8]
# H405: multi line docstring summary not separated with an empty line
ignore = H405
show-source = True
exclude = .venv,.tox,dist,doc,*egg,build
[testenv:docs]
commands=
python setup.py build_sphinx