deployment module
Change-Id: I1305b74595ab3259e9a813157eb4d8e653ca6f3f
This commit is contained in:
parent
8710a15261
commit
e744fe33c6
@ -13,16 +13,21 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
"""Module to deploy a given cluster
|
"""Module to deploy a given cluster
|
||||||
|
|
||||||
.. moduleauthor:: Xiaodong Wang <xiaodongwang@huawei.com>
|
|
||||||
"""
|
"""
|
||||||
import logging
|
|
||||||
|
|
||||||
from compass.actions import util
|
from compass.actions import util
|
||||||
from compass.db.api import database
|
from compass.db.api import adapter_holder as adapter_db
|
||||||
|
from compass.db.api import cluster as cluster_db
|
||||||
|
from compass.db.api import host as host_db
|
||||||
|
from compass.db.api import user as user_db
|
||||||
|
from compass.deployment.deploy_manager import DeployManager
|
||||||
|
from compass.deployment.utils import constants as const
|
||||||
|
|
||||||
|
|
||||||
def deploy(cluster_hosts):
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
def deploy(cluster_id, hosts_id_list, username=None):
|
||||||
"""Deploy clusters.
|
"""Deploy clusters.
|
||||||
|
|
||||||
:param cluster_hosts: clusters and hosts in each cluster to deploy.
|
:param cluster_hosts: clusters and hosts in each cluster to deploy.
|
||||||
@ -35,4 +40,207 @@ def deploy(cluster_hosts):
|
|||||||
if not lock:
|
if not lock:
|
||||||
raise Exception('failed to acquire lock to deploy')
|
raise Exception('failed to acquire lock to deploy')
|
||||||
|
|
||||||
logging.debug('deploy cluster_hosts: %s', cluster_hosts)
|
user = user_db.get_user_object(username)
|
||||||
|
|
||||||
|
cluster_info = ActionHelper.get_cluster_info(cluster_id, user)
|
||||||
|
adapter_id = cluster_info[const.ADAPTER_ID]
|
||||||
|
|
||||||
|
adapter_info = ActionHelper.get_adapter_info(adapter_id, cluster_id,
|
||||||
|
user)
|
||||||
|
hosts_info = ActionHelper.get_hosts_info(hosts_id_list, user)
|
||||||
|
|
||||||
|
logging.debug('[action][deploy]: adapter_info is %s', adapter_info)
|
||||||
|
logging.debug('[action][deploy]: cluster_info is %s', cluster_info)
|
||||||
|
logging.debug('[action][deploy]: hosts_info is %s', hosts_info)
|
||||||
|
|
||||||
|
deploy_manager = DeployManager(adapter_info, cluster_info, hosts_info)
|
||||||
|
#deploy_manager.prepare_for_deploy()
|
||||||
|
deployed_config = deploy_manager.deploy()
|
||||||
|
|
||||||
|
ActionHelper.save_deployed_config(deployed_config, user)
|
||||||
|
|
||||||
|
|
||||||
|
def redeploy(cluster_id, hosts_id_list, username=None):
|
||||||
|
"""Deploy clusters.
|
||||||
|
|
||||||
|
:param cluster_hosts: clusters and hosts in each cluster to deploy.
|
||||||
|
:type cluster_hosts: dict of int or str to list of int or str
|
||||||
|
"""
|
||||||
|
with util.lock('serialized_action') as lock:
|
||||||
|
if not lock:
|
||||||
|
raise Exception('failed to acquire lock to deploy')
|
||||||
|
|
||||||
|
user = user_db.get_user_object(username)
|
||||||
|
cluster_info = ActionHelper.get_cluster_info(cluster_id, user)
|
||||||
|
adapter_id = cluster_info[const.ADAPTER_ID]
|
||||||
|
|
||||||
|
adapter_info = ActionHelper.get_adapter_info(adapter_id,
|
||||||
|
cluster_id,
|
||||||
|
user)
|
||||||
|
hosts_info = ActionHelper.get_hosts_info(cluster_id,
|
||||||
|
hosts_id_list,
|
||||||
|
user)
|
||||||
|
|
||||||
|
deploy_manager = DeployManager(adapter_info, cluster_info, hosts_info)
|
||||||
|
#deploy_manager.prepare_for_deploy()
|
||||||
|
deploy_manager.redeploy()
|
||||||
|
|
||||||
|
|
||||||
|
def poweron(host_id):
|
||||||
|
"""Power on a list of hosts."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def poweroff(host_id):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def reset(host_id):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ActionHelper(object):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_adapter_info(adapter_id, cluster_id, user):
|
||||||
|
"""Get adapter information. Return a dictionary as below,
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "xxx",
|
||||||
|
"roles": ['xxx', 'yyy', ...],
|
||||||
|
"metadata": {
|
||||||
|
"os_config": {
|
||||||
|
...
|
||||||
|
},
|
||||||
|
"package_config": {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"os_installer": {
|
||||||
|
"name": "cobbler",
|
||||||
|
"settings": {....}
|
||||||
|
},
|
||||||
|
"pk_installer": {
|
||||||
|
"name": "chef",
|
||||||
|
"settings": {....}
|
||||||
|
},
|
||||||
|
...
|
||||||
|
}
|
||||||
|
To view a complete output, please refer to backend doc.
|
||||||
|
"""
|
||||||
|
adapter_info = adapter_db.get_adapter(user, adapter_id)
|
||||||
|
metadata = cluster_db.get_cluster_metadata(user, cluster_id)
|
||||||
|
adapter_info.update(metadata)
|
||||||
|
|
||||||
|
roles_info = adapter_info[const.ROLES]
|
||||||
|
roles_list = [role[const.NAME] for role in roles_info]
|
||||||
|
adapter_info[const.ROLES] = roles_list
|
||||||
|
|
||||||
|
return adapter_info
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_cluster_info(cluster_id, user):
|
||||||
|
"""Get cluster information.Return a dictionary as below,
|
||||||
|
{
|
||||||
|
"cluster": {
|
||||||
|
"id": 1,
|
||||||
|
"adapter_id": 1,
|
||||||
|
"os_version": "CentOS-6.5-x86_64",
|
||||||
|
"name": "cluster_01",
|
||||||
|
"os_config": {..},
|
||||||
|
"package_config": {...},
|
||||||
|
"deployed_os_config": {},
|
||||||
|
"deployed_package_config": {},
|
||||||
|
"owner": "xxx"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
cluster_info = cluster_db.get_cluster(user, cluster_id)
|
||||||
|
cluster_config = cluster_db.get_cluster_config(user, cluster_id)
|
||||||
|
cluster_info.update(cluster_config)
|
||||||
|
|
||||||
|
deploy_config = cluster_db.get_cluster_deployed_config(user,
|
||||||
|
cluster_id)
|
||||||
|
cluster_info.update(deploy_config)
|
||||||
|
|
||||||
|
return cluster_info
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_hosts_info(cluster_id, hosts_id_list, user):
|
||||||
|
"""Get hosts information. Return a dictionary as below,
|
||||||
|
{
|
||||||
|
"hosts": {
|
||||||
|
1($clusterhost_id/host_id): {
|
||||||
|
"reinstall_os": True,
|
||||||
|
"mac": "xxx",
|
||||||
|
"name": "xxx",
|
||||||
|
},
|
||||||
|
"networks": {
|
||||||
|
"eth0": {
|
||||||
|
"ip": "192.168.1.1",
|
||||||
|
"netmask": "255.255.255.0",
|
||||||
|
"is_mgmt": True,
|
||||||
|
"is_promiscuous": False,
|
||||||
|
"subnet": "192.168.1.0/24"
|
||||||
|
},
|
||||||
|
"eth1": {...}
|
||||||
|
},
|
||||||
|
"os_config": {},
|
||||||
|
"package_config": {},
|
||||||
|
"deployed_os_config": {},
|
||||||
|
"deployed_package_config": {}
|
||||||
|
},
|
||||||
|
2: {...},
|
||||||
|
....
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
hosts_info = {}
|
||||||
|
for clusterhost_id in hosts_id_list:
|
||||||
|
info = cluster_db.get_clusterhost(user, clusterhost_id)
|
||||||
|
host_id = info[const.HOST_ID]
|
||||||
|
temp = host_db.get_host(user, host_id)
|
||||||
|
config = cluster_db.get_cluster_host_config(user, cluster_id,
|
||||||
|
host_id)
|
||||||
|
# Delete 'id' from temp
|
||||||
|
del temp['id']
|
||||||
|
info.update(temp)
|
||||||
|
info.update(config)
|
||||||
|
|
||||||
|
networks = info[const.NETWORKS]
|
||||||
|
networks_dict = {}
|
||||||
|
# Convert networks from list to dictionary format
|
||||||
|
for entry in networks:
|
||||||
|
nic_info = {}
|
||||||
|
nic_info = {
|
||||||
|
entry[const.NIC]: {
|
||||||
|
const.IP_ADDR: entry[const.IP_ADDR],
|
||||||
|
const.NETMASK: entry[const.NETMASK],
|
||||||
|
const.MGMT_NIC_FLAG: entry[const.MGMT_NIC_FLAG],
|
||||||
|
const.PROMISCUOUS_FLAG: entry[const.PROMISCUOUS_FLAG],
|
||||||
|
const.SUBNET: entry[const.SUBNET]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
networks_dict.update(nic_info)
|
||||||
|
|
||||||
|
info[const.NETWORKS] = networks_dict
|
||||||
|
|
||||||
|
hosts_info[clusterhost_id] = info
|
||||||
|
|
||||||
|
return hosts_info
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def save_deployed_config(self, deployed_config, user):
|
||||||
|
cluster_config = deployed_config[const.CLUSTER]
|
||||||
|
cluster_id = cluster_config[const.ID]
|
||||||
|
del cluster_config[const.ID]
|
||||||
|
|
||||||
|
cluster_db.update_cluster_deployed_config(user, cluster_id,
|
||||||
|
**cluster_config)
|
||||||
|
|
||||||
|
hosts_id_list = deployed_config[const.HOSTS].keys()
|
||||||
|
for clusterhost_id in hosts_id_list:
|
||||||
|
config = deployed_config[const.HOSTS][clusterhost_id]
|
||||||
|
cluster_db.update_clusterhost_deployed_config(user,
|
||||||
|
clusterhost_id,
|
||||||
|
**config)
|
||||||
|
15
compass/deployment/__init__.py
Normal file
15
compass/deployment/__init__.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
__author__ = "Grace Yu (grace.yu@huawei.com)"
|
164
compass/deployment/deploy_manager.py
Normal file
164
compass/deployment/deploy_manager.py
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
__author__ = "Grace Yu (grace.yu@huawei.com)"
|
||||||
|
|
||||||
|
"""Module to get configs from provider and isntallers and update
|
||||||
|
them to provider and installers.
|
||||||
|
"""
|
||||||
|
from compass.deployment.installers.installer import OSInstaller
|
||||||
|
from compass.deployment.installers.installer import PKInstaller
|
||||||
|
from compass.deployment.utils import constants as const
|
||||||
|
from compass.utils import util
|
||||||
|
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
class DeployManager(object):
|
||||||
|
"""Deploy manager module."""
|
||||||
|
def __init__(self, adapter_info, cluster_info, hosts_info):
|
||||||
|
os_installer_name = adapter_info[const.OS_INSTALLER][const.NAME]
|
||||||
|
pk_installer_name = adapter_info[const.PK_INSTALLER][const.NAME]
|
||||||
|
|
||||||
|
os_hosts_info = self._get_hosts_for_os_installation(hosts_info)
|
||||||
|
|
||||||
|
self.os_installer = DeployManager._get_installer(OSInstaller,
|
||||||
|
os_installer_name,
|
||||||
|
adapter_info,
|
||||||
|
cluster_info,
|
||||||
|
os_hosts_info)
|
||||||
|
self.pk_installer = DeployManager._get_installer(PKInstaller,
|
||||||
|
pk_installer_name,
|
||||||
|
adapter_info,
|
||||||
|
cluster_info,
|
||||||
|
hosts_info)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_installer(installer_type, name, adapter_info, cluster_info,
|
||||||
|
hosts_info):
|
||||||
|
"""Get installer instance."""
|
||||||
|
callback = getattr(installer_type, 'get_installer')
|
||||||
|
installer = callback(name, adapter_info, cluster_info, hosts_info)
|
||||||
|
|
||||||
|
return installer
|
||||||
|
|
||||||
|
def clean_progress(self):
|
||||||
|
"""Clean previous installation log and progress."""
|
||||||
|
# Clean DB
|
||||||
|
# db_api.cluster.clean_progress(self.cluster_id)
|
||||||
|
# db_api.cluster.clean_progress(self.cluster_id, self.host_id_list)
|
||||||
|
|
||||||
|
# OS installer cleans previous installing progress.
|
||||||
|
if self.os_installer:
|
||||||
|
self.os_installer.clean_progress()
|
||||||
|
|
||||||
|
# Package installer cleans previous installing progress.
|
||||||
|
if self.pk_installer:
|
||||||
|
self.package_installer.clean_progress()
|
||||||
|
|
||||||
|
def prepare_for_deploy(self):
|
||||||
|
self.clean_progress()
|
||||||
|
|
||||||
|
def deploy(self):
|
||||||
|
"""Deploy the cluster."""
|
||||||
|
deploy_config = {}
|
||||||
|
pk_instl_confs = {}
|
||||||
|
if self.pk_installer:
|
||||||
|
# generate target system config which will be installed by OS
|
||||||
|
# installer right after OS installation is completed.
|
||||||
|
pk_instl_confs = self.package_installer.generate_installer_config()
|
||||||
|
logging.debug('[DeployManager][deploy] pk_instl_confs is %s',
|
||||||
|
pk_instl_confs)
|
||||||
|
|
||||||
|
if self.os_installer:
|
||||||
|
logging.info('[DeployManager][deploy]get OS installer %s',
|
||||||
|
self.os_installer)
|
||||||
|
# Send package installer config info to OS installer.
|
||||||
|
if pk_instl_confs:
|
||||||
|
self.os_installer.set_package_installer_config(pk_instl_confs)
|
||||||
|
|
||||||
|
# start to deploy OS
|
||||||
|
try:
|
||||||
|
os_deploy_config = self.os_installer.deploy()
|
||||||
|
deploy_config = os_deploy_config
|
||||||
|
except Exception as ex:
|
||||||
|
logging.error(ex.message)
|
||||||
|
|
||||||
|
if self.pk_installer:
|
||||||
|
logging.info('DeployManager][deploy]get package installer %s',
|
||||||
|
self.pk_installer)
|
||||||
|
|
||||||
|
pk_deploy_config = self.package_installer.deploy()
|
||||||
|
util.merge_dict(deploy_config, pk_deploy_config)
|
||||||
|
|
||||||
|
return deploy_config
|
||||||
|
|
||||||
|
def redeploy(self):
|
||||||
|
"""Redeploy the cluster without changing configurations."""
|
||||||
|
if self.os_installer:
|
||||||
|
self.os_installer.redeploy()
|
||||||
|
|
||||||
|
if self.package_installer:
|
||||||
|
self.package_installer.redeploy()
|
||||||
|
|
||||||
|
def remove_hosts(self):
|
||||||
|
"""Remove hosts from both OS and package installlers server side."""
|
||||||
|
if self.os_installer:
|
||||||
|
self.os_installer.delete_hosts()
|
||||||
|
|
||||||
|
if self.pk_installer:
|
||||||
|
self.pk_installer.delete_hosts()
|
||||||
|
|
||||||
|
def _get_hosts_for_os_installation(self, hosts_info):
|
||||||
|
"""Get info of hosts which need to install/reinstall OS."""
|
||||||
|
hosts_list = {}
|
||||||
|
for host_id in hosts_info:
|
||||||
|
reinstall_os_flag = hosts_info[host_id][const.REINSTALL_OS_FLAG]
|
||||||
|
if not reinstall_os_flag:
|
||||||
|
continue
|
||||||
|
|
||||||
|
hosts_list[host_id] = hosts_info[host_id]
|
||||||
|
|
||||||
|
return hosts_list
|
||||||
|
|
||||||
|
|
||||||
|
class PowerManager(object):
|
||||||
|
"""Manage host to power on, power off, and reset."""
|
||||||
|
|
||||||
|
def __init__(self, adapter_info, cluster_info, hosts_info):
|
||||||
|
os_installer_name = adapter_info[const.OS_INSTALLER][const.NAME]
|
||||||
|
self.os_installer = DeployManager._get_installer(OSInstaller,
|
||||||
|
os_installer_name,
|
||||||
|
adapter_info,
|
||||||
|
cluster_info,
|
||||||
|
hosts_info)
|
||||||
|
|
||||||
|
def poweron(self):
|
||||||
|
if not self.os_installer:
|
||||||
|
logging.info("No OS installer found, cannot power on machine!")
|
||||||
|
return
|
||||||
|
self.os_installer.poweron()
|
||||||
|
|
||||||
|
def poweroff(self):
|
||||||
|
if not self.os_installer:
|
||||||
|
logging.info("No OS installer found, cannot power on machine!")
|
||||||
|
return
|
||||||
|
self.os_installer.poweroff()
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
if not self.os_installer:
|
||||||
|
logging.info("No OS installer found, cannot power on machine!")
|
||||||
|
return
|
||||||
|
self.os_installer.reset()
|
21
compass/deployment/installers/__init__.py
Normal file
21
compass/deployment/installers/__init__.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
__author__ = "Grace Yu (grace.yu@huawei.com)"
|
||||||
|
|
||||||
|
|
||||||
|
"""modules to read/write cluster/host config from installers.
|
||||||
|
|
||||||
|
.. moduleauthor:: Grace Yu <grace.yu@huawei.com>
|
||||||
|
"""
|
460
compass/deployment/installers/config_manager.py
Normal file
460
compass/deployment/installers/config_manager.py
Normal file
@ -0,0 +1,460 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
__author__ = "Grace Yu (grace.yu@huawei.com)"
|
||||||
|
|
||||||
|
|
||||||
|
"""Module to manage and access cluster, hosts and adapter config.
|
||||||
|
"""
|
||||||
|
from copy import deepcopy
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
from compass.deployment.utils import constants as const
|
||||||
|
from compass.utils import util
|
||||||
|
|
||||||
|
|
||||||
|
class BaseConfigManager(object):
|
||||||
|
|
||||||
|
def __init__(self, adapter_info, cluster_info, hosts_info):
|
||||||
|
self.adapter_info = adapter_info
|
||||||
|
self.cluster_info = cluster_info
|
||||||
|
self.hosts_info = hosts_info
|
||||||
|
|
||||||
|
def get_cluster_id(self):
|
||||||
|
if not self.cluster_info:
|
||||||
|
logging.info("cluster config is None or {}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self.cluster_info[const.ID]
|
||||||
|
|
||||||
|
def get_clustername(self):
|
||||||
|
if not self.cluster_info:
|
||||||
|
logging.info("cluster config is None or {}")
|
||||||
|
return None
|
||||||
|
return self.cluster_info[const.NAME]
|
||||||
|
|
||||||
|
def get_os_version(self):
|
||||||
|
if not self.cluster_info:
|
||||||
|
logging.info("cluster config is None or {}")
|
||||||
|
return None
|
||||||
|
return self.cluster_info[const.OS_VERSION]
|
||||||
|
|
||||||
|
def get_cluster_baseinfo(self):
|
||||||
|
"""Get cluster base information, including cluster_id, os_version,
|
||||||
|
and cluster_name.
|
||||||
|
"""
|
||||||
|
if not self.cluster_info:
|
||||||
|
logging.info("cluster config is None or {}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
attr_names = [const.ID, const.NAME, const.OS_VERSION]
|
||||||
|
|
||||||
|
base_info = {}
|
||||||
|
for name in attr_names:
|
||||||
|
base_info[name] = self.cluster_info[name]
|
||||||
|
|
||||||
|
return base_info
|
||||||
|
|
||||||
|
def get_host_id_list(self):
|
||||||
|
if not self.hosts_info:
|
||||||
|
logging.info("hosts config is None or {}")
|
||||||
|
return []
|
||||||
|
|
||||||
|
return self.hosts_info.keys()
|
||||||
|
|
||||||
|
def get_cluster_os_config(self):
|
||||||
|
if not self.cluster_info:
|
||||||
|
logging.info("cluster config is None or {}")
|
||||||
|
return {}
|
||||||
|
|
||||||
|
return deepcopy(self.cluster_info[const.OS_CONFIG])
|
||||||
|
|
||||||
|
def get_cluster_package_config(self):
|
||||||
|
if not self.cluster_info:
|
||||||
|
logging.info("cluster config is None or {}")
|
||||||
|
return {}
|
||||||
|
|
||||||
|
return deepcopy(self.cluster_info[const.PK_CONFIG])
|
||||||
|
|
||||||
|
def get_cluster_network_mapping(self):
|
||||||
|
package_config = self.get_cluster_package_config()
|
||||||
|
if not package_config:
|
||||||
|
logging.info("cluster package_config is None or {}.")
|
||||||
|
return {}
|
||||||
|
|
||||||
|
mapping = package_config.setdefault(const.NETWORK_MAPPING, {})
|
||||||
|
logging.info("Network mapping in the config is '%s'!", mapping)
|
||||||
|
|
||||||
|
return deepcopy(mapping)
|
||||||
|
|
||||||
|
def get_cluster_deployed_os_config(self):
|
||||||
|
if not self.cluster_info:
|
||||||
|
logging.info("cluster config is None or {}")
|
||||||
|
return {}
|
||||||
|
|
||||||
|
config = self.cluster_info.setdefault(const.DEPLOYED_OS_CONFIG, {})
|
||||||
|
return config
|
||||||
|
|
||||||
|
def get_cluster_deployed_package_config(self):
|
||||||
|
if not self.cluster_info:
|
||||||
|
logging.info("cluster config is None or {}")
|
||||||
|
return {}
|
||||||
|
|
||||||
|
config = self.cluster_info.setdefault(const.DEPLOYED_PK_CONFIG, {})
|
||||||
|
return config
|
||||||
|
|
||||||
|
def get_cluster_os_vars_dict(self):
|
||||||
|
deployed_config = self.get_cluster_deployed_os_config()
|
||||||
|
return self.__get_deployed_config_item(deployed_config,
|
||||||
|
const.TMPL_VARS_DICT)
|
||||||
|
|
||||||
|
def get_cluster_package_vars_dict(self):
|
||||||
|
deployed_config = self.get_cluster_deployed_package_config()
|
||||||
|
return self.__get_deployed_config_item(deployed_config,
|
||||||
|
const.TMPL_VARS_DICT)
|
||||||
|
|
||||||
|
def __get_deployed_config_item(deployed_config, item):
|
||||||
|
if not deployed_config:
|
||||||
|
logging.info("Deploy config is {}")
|
||||||
|
return {}
|
||||||
|
|
||||||
|
value = deployed_config.setdefault(item, {})
|
||||||
|
return deepcopy(value)
|
||||||
|
|
||||||
|
def get_cluster_roles_mapping(self):
|
||||||
|
if not self.cluster_info:
|
||||||
|
logging.info("cluster config is None or {}")
|
||||||
|
return {}
|
||||||
|
|
||||||
|
deploy_config = self.get_cluster_deployed_package_config()
|
||||||
|
|
||||||
|
if const.ROLES_MAPPING not in deploy_config:
|
||||||
|
mapping = self._get_cluster_roles_mapping_helper()
|
||||||
|
deploy_config[const.ROLES_MAPPING] = mapping
|
||||||
|
else:
|
||||||
|
mapping = deploy_config[const.ROLES_MAPPING]
|
||||||
|
|
||||||
|
return mapping
|
||||||
|
|
||||||
|
def _get_host_info(self, host_id):
|
||||||
|
if not self.hosts_info:
|
||||||
|
logging.info("hosts config is None or {}")
|
||||||
|
return {}
|
||||||
|
|
||||||
|
if host_id not in self.hosts_info:
|
||||||
|
logging.info("Cannot find host, ID is '%s'", host_id)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
return self.hosts_info[host_id]
|
||||||
|
|
||||||
|
def get_host_baseinfo(self, host_id):
|
||||||
|
"""Get host base information."""
|
||||||
|
host_info = self._get_host_info(host_id)
|
||||||
|
if not host_info:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
attr_names = [const.REINSTALL_OS_FLAG, const.MAC_ADDR, const.NAME,
|
||||||
|
const.HOSTNAME, const.NETWORKS]
|
||||||
|
base_info = {}
|
||||||
|
for attr in attr_names:
|
||||||
|
temp = host_info[attr]
|
||||||
|
if isinstance(temp, dict) or isinstance(temp, list):
|
||||||
|
base_info[attr] = deepcopy(temp)
|
||||||
|
else:
|
||||||
|
base_info[attr] = temp
|
||||||
|
|
||||||
|
base_info[const.DNS] = self.get_host_dns(host_id)
|
||||||
|
|
||||||
|
return base_info
|
||||||
|
|
||||||
|
def get_host_name(self, host_id):
|
||||||
|
host_info = self._get_host_info(host_id)
|
||||||
|
if not host_info:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return host_info.setdefault(const.NAME, None)
|
||||||
|
|
||||||
|
def get_host_dns(self, host_id):
|
||||||
|
host_info = self._get_host_info(host_id)
|
||||||
|
if not host_info:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if const.DNS not in host_info:
|
||||||
|
name = host_info[const.NAME]
|
||||||
|
domain = self.get_host_domain(host_id)
|
||||||
|
host_info[const.DNS] = '.'.join((name, domain))
|
||||||
|
|
||||||
|
return host_info[const.DNS]
|
||||||
|
|
||||||
|
def get_host_mac_address(self, host_id):
|
||||||
|
host_info = self._get_host_info(host_id)
|
||||||
|
if not host_info:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return host_info.setdefault(const.MAC_ADDR, None)
|
||||||
|
|
||||||
|
def get_hostname(self, host_id):
|
||||||
|
host_info = self._get_host_info(host_id)
|
||||||
|
if not host_info:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return host_info.setdefault(const.HOSTNAME, None)
|
||||||
|
|
||||||
|
def get_host_networks(self, host_id):
|
||||||
|
host_info = self._get_host_info(host_id)
|
||||||
|
if not host_info:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
return deepcopy(host_info.setdefault(const.NETWORKS, {}))
|
||||||
|
|
||||||
|
def get_host_interfaces(self, host_id):
|
||||||
|
networks = self.get_host_networks(host_id)
|
||||||
|
if not networks:
|
||||||
|
return []
|
||||||
|
|
||||||
|
nic_names = networks.keys()
|
||||||
|
return nic_names
|
||||||
|
|
||||||
|
def get_host_interface_config(self, host_id, interface):
|
||||||
|
networks = self.get_host_networks(host_id)
|
||||||
|
if not networks:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
return deepcopy(networks.setdefault(interface, {}))
|
||||||
|
|
||||||
|
def get_host_interface_ip(self, host_id, interface):
|
||||||
|
interface_config = self._get_host_interface_config(host_id, interface)
|
||||||
|
if not interface_config:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return interface_config.setdefault(const.IP_ADDR, None)
|
||||||
|
|
||||||
|
def get_host_interface_netmask(self, host_id, interface):
|
||||||
|
interface_config = self.get_host_interface_config(host_id, interface)
|
||||||
|
if not interface_config:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return interface_config.setdefault(const.NETMASK, None)
|
||||||
|
|
||||||
|
def get_host_interface_subnet(self, host_id, interface):
|
||||||
|
nic_config = self.get_host_interface_config(host_id, interface)
|
||||||
|
if not nic_config:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return nic_config.setdefault(const.SUBNET, None)
|
||||||
|
|
||||||
|
def is_interface_promiscuous(self, host_id, interface):
|
||||||
|
nic_config = self.get_host_interface_config(host_id, interface)
|
||||||
|
if not nic_config:
|
||||||
|
raise Exception("Cannot find interface '%s'", interface)
|
||||||
|
|
||||||
|
return nic_config[const.PROMISCUOUS_FLAG]
|
||||||
|
|
||||||
|
def is_interface_mgmt(self, host_id, interface):
|
||||||
|
nic_config = self.get_host_interface_config(host_id, interface)
|
||||||
|
if not nic_config:
|
||||||
|
raise Exception("Cannot find interface '%s'", interface)
|
||||||
|
|
||||||
|
return nic_config[const.MGMT_NIC_FLAG]
|
||||||
|
|
||||||
|
def get_host_os_config(self, host_id):
|
||||||
|
host_info = self._get_host_info(host_id)
|
||||||
|
if not host_info:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
return deepcopy(host_info.setdefault(const.OS_CONFIG, {}))
|
||||||
|
|
||||||
|
def get_host_domain(self, host_id):
|
||||||
|
os_config = self.get_host_os_config(host_id)
|
||||||
|
os_general_config = os_config.setdefault(const.OS_CONFIG_GENERAL, {})
|
||||||
|
domain = os_general_config.setdefault(const.DOMAIN, None)
|
||||||
|
if domain is None:
|
||||||
|
global_config = self.get_cluster_os_config()
|
||||||
|
global_general = global_config.setdefault(const.OS_CONFIG_GENERAL,
|
||||||
|
{})
|
||||||
|
domain = global_general.setdefault(const.DOMAIN, None)
|
||||||
|
|
||||||
|
return domain
|
||||||
|
|
||||||
|
def get_host_network_mapping(self, host_id):
|
||||||
|
package_config = self.get_host_package_config(host_id)
|
||||||
|
if const.NETWORK_MAPPING not in package_config:
|
||||||
|
network_mapping = self.get_cluster_network_mapping()
|
||||||
|
else:
|
||||||
|
network_mapping = package_config[const.NETWORK_MAPPING]
|
||||||
|
|
||||||
|
return network_mapping
|
||||||
|
|
||||||
|
def get_host_package_config(self, host_id):
|
||||||
|
host_info = self._get_host_info(host_id)
|
||||||
|
if not host_info:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
return deepcopy(host_info.setdefault(const.PK_CONFIG, {}))
|
||||||
|
|
||||||
|
def get_host_deployed_os_config(self, host_id):
|
||||||
|
host_info = self._get_host_info(host_id)
|
||||||
|
if not host_info:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
return host_info.setdefault(const.DEPLOYED_OS_CONFIG, {})
|
||||||
|
|
||||||
|
def get_host_os_vars_dict(self, host_id):
|
||||||
|
deployed_config = self.get_host_deployed_os_config(host_id)
|
||||||
|
return self.__get_deployed_config_item(deployed_config,
|
||||||
|
const.TMPL_VARS_DICT)
|
||||||
|
|
||||||
|
def get_host_completed_os_config(self, host_id):
|
||||||
|
deployed_config = self.get_host_deployed_os_config(host_id)
|
||||||
|
config = self.__get_deployed_config_item(deployed_config,
|
||||||
|
const.COMPLETED_OS_CONFIG)
|
||||||
|
if not config:
|
||||||
|
config = self.get_cluster_os_config()
|
||||||
|
util.merge_dict(config, self.get_host_os_config(host_id))
|
||||||
|
deployed_config[const.COMPLETED_OS_CONFIG] = config
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
def get_host_deployed_package_config(self, host_id):
|
||||||
|
host_info = self._get_host_info(host_id)
|
||||||
|
if not host_info:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
return host_info.setdefault(const.DEPLOYED_PK_CONFIG, {})
|
||||||
|
|
||||||
|
def get_host_package_vars_dict(self, host_id):
|
||||||
|
deployed_config = self.get_host_deployed_package_config(host_id)
|
||||||
|
return self.__get_deployed_config_item(deployed_config,
|
||||||
|
const.TMPL_VARS_DICT)
|
||||||
|
|
||||||
|
def get_host_roles(self, host_id):
|
||||||
|
config = self.get_host_package_config(host_id)
|
||||||
|
if not config:
|
||||||
|
return []
|
||||||
|
|
||||||
|
return deepcopy(config.setdefault(const.ROLES, []))
|
||||||
|
|
||||||
|
def get_host_roles_mapping(self, host_id):
|
||||||
|
roles_mapping = {}
|
||||||
|
deployed_pk_config = self.get_host_deployed_package_config(host_id)
|
||||||
|
if const.ROLES_MAPPING not in deployed_pk_config:
|
||||||
|
roles_mapping = self._get_host_roles_mapping_helper(host_id)
|
||||||
|
else:
|
||||||
|
roles_mapping = deployed_pk_config[const.ROLES_MAPPING]
|
||||||
|
|
||||||
|
return roles_mapping
|
||||||
|
|
||||||
|
def get_adapter_name(self):
|
||||||
|
if not self.adapter_info:
|
||||||
|
logging.info("Adapter Info is None!")
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self.adapter_info.setdefault(const.NAME, None)
|
||||||
|
|
||||||
|
def get_dist_system_name(self):
|
||||||
|
if not self.adapter_info:
|
||||||
|
logging.info("Adapter Info is None!")
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self.adapter_info.setdefault(const.DIST_SYS_NAME, None)
|
||||||
|
|
||||||
|
def get_adapter_roles(self):
|
||||||
|
if not self.adapter_info:
|
||||||
|
logging.info("Adapter Info is None!")
|
||||||
|
return []
|
||||||
|
|
||||||
|
roles = self.adapter_info.setdefault(const.ROLES, [])
|
||||||
|
|
||||||
|
return deepcopy(roles)
|
||||||
|
|
||||||
|
def get_os_installer_settings(self):
|
||||||
|
if not self.adapter_info:
|
||||||
|
logging.info("Adapter Info is None!")
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self.adapter_info[const.OS_INSTALLER][const.INSTALLER_SETTINGS]
|
||||||
|
|
||||||
|
def get_pk_installer_settings(self):
|
||||||
|
if not self.adapter_info:
|
||||||
|
logging.info("Adapter Info is None!")
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self.adapter_info[const.PK_INSTALLER][const.INSTALLER_SETTINGS]
|
||||||
|
|
||||||
|
def get_os_config_metadata(self):
|
||||||
|
if not self.adapter_info:
|
||||||
|
logging.info("Adapter Info is None!")
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self.adapter_info[const.METADATA][const.OS_CONFIG]
|
||||||
|
|
||||||
|
def get_pk_config_meatadata(self):
|
||||||
|
if not self.adapter_info:
|
||||||
|
logging.info("Adapter Info is None!")
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self.adapter_info[const.METADATA][const.PK_CONFIG]
|
||||||
|
|
||||||
|
def _get_cluster_roles_mapping_helper(self):
|
||||||
|
"""The ouput format will be as below, for example:
|
||||||
|
{
|
||||||
|
"controller": {
|
||||||
|
"management": {
|
||||||
|
"interface": "eth0",
|
||||||
|
"ip": "192.168.1.10",
|
||||||
|
"netmask": "255.255.255.0",
|
||||||
|
"subnet": "192.168.1.0/24",
|
||||||
|
"is_mgmt": True,
|
||||||
|
"is_promiscuous": False
|
||||||
|
},
|
||||||
|
...
|
||||||
|
},
|
||||||
|
...
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
mapping = {}
|
||||||
|
hosts_id_list = self.get_host_id_list()
|
||||||
|
network_mapping = self.get_cluster_network_mapping()
|
||||||
|
if not network_mapping:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
for host_id in hosts_id_list:
|
||||||
|
roles_mapping = self.get_host_roles_mapping(host_id)
|
||||||
|
for role in roles_mapping:
|
||||||
|
if role not in mapping:
|
||||||
|
mapping[role] = roles_mapping[role]
|
||||||
|
|
||||||
|
return mapping
|
||||||
|
|
||||||
|
def _get_host_roles_mapping_helper(self, host_id):
|
||||||
|
"""The format will be the same as cluster roles mapping."""
|
||||||
|
mapping = {}
|
||||||
|
network_mapping = self.get_host_network_mapping(host_id)
|
||||||
|
if not network_mapping:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
roles = self.get_host_roles(host_id)
|
||||||
|
interfaces = self.get_host_interfaces(host_id)
|
||||||
|
temp = {}
|
||||||
|
for key in network_mapping:
|
||||||
|
nic = network_mapping[key][const.NIC]
|
||||||
|
if nic in interfaces:
|
||||||
|
temp[key] = self.get_host_interface_config(host_id, nic)
|
||||||
|
temp[key][const.NIC] = nic
|
||||||
|
|
||||||
|
for role in roles:
|
||||||
|
role = role.replace("-", "_")
|
||||||
|
mapping[role] = temp
|
||||||
|
return mapping
|
221
compass/deployment/installers/installer.py
Normal file
221
compass/deployment/installers/installer.py
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
__author__ = "Grace Yu (grace.yu@huawei.com)"
|
||||||
|
|
||||||
|
|
||||||
|
"""Module to provider installer interface.
|
||||||
|
"""
|
||||||
|
from Cheetah.Template import Template
|
||||||
|
from copy import deepcopy
|
||||||
|
import imp
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import simplejson as json
|
||||||
|
|
||||||
|
|
||||||
|
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
|
|
||||||
|
class BaseInstaller(object):
|
||||||
|
"""Interface for installer."""
|
||||||
|
NAME = 'installer'
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '%r[%r]' % (self.__class__.__name__, self.NAME)
|
||||||
|
|
||||||
|
def deploy(self, **kwargs):
|
||||||
|
"""virtual method to start installing process."""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def clean_progress(self, **kwargs):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def delete_hosts(self, **kwargs):
|
||||||
|
"""Delete hosts from installer server."""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def redeploy(self, **kwargs):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def get_tmpl_vars_from_metadata(self, metadata, config):
|
||||||
|
"""Get variables dictionary for rendering templates from metadata.
|
||||||
|
:param dict metadata: The metadata dictionary.
|
||||||
|
:param dict config: The
|
||||||
|
"""
|
||||||
|
template_vars = {}
|
||||||
|
self._get_tmpl_vars_helper(metadata, config, template_vars)
|
||||||
|
|
||||||
|
return template_vars
|
||||||
|
|
||||||
|
def _get_key_mapping(self, metadata, key, is_regular_key):
|
||||||
|
"""Get the keyword which the input key maps to. This keyword will be
|
||||||
|
added to dictionary used to render templates.
|
||||||
|
|
||||||
|
If the key in metadata has a mapping to another keyword which is
|
||||||
|
used for templates, then return this keyword. If the key is started
|
||||||
|
with '$', which is a variable in metadata, return the key itself as
|
||||||
|
the mapping keyword. If the key has no mapping, return None.
|
||||||
|
|
||||||
|
:param dict metadata: metadata/submetadata dictionary.
|
||||||
|
:param str key: The keyword defined in metadata.
|
||||||
|
:param bool is_regular_key: False when the key defined in metadata
|
||||||
|
is a variable(starting with '$').
|
||||||
|
"""
|
||||||
|
mapping_to = key
|
||||||
|
if is_regular_key:
|
||||||
|
try:
|
||||||
|
mapping_to = metadata['_self']['mapping_to']
|
||||||
|
except Exception:
|
||||||
|
mapping_to = None
|
||||||
|
return mapping_to
|
||||||
|
|
||||||
|
def _get_submeta_by_key(self, metadata, key):
|
||||||
|
"""Get submetadata dictionary based on current metadata key. And
|
||||||
|
determines the input key is a regular string keyword or a variable
|
||||||
|
keyword defined in metadata, which starts with '$'.
|
||||||
|
|
||||||
|
:param dict metadata: The metadata dictionary.
|
||||||
|
:param str key: The keyword defined in the metadata.
|
||||||
|
"""
|
||||||
|
if key in metadata:
|
||||||
|
return (True, metadata[key])
|
||||||
|
|
||||||
|
temp = deepcopy(metadata)
|
||||||
|
del temp['_self']
|
||||||
|
meta_key = temp.keys()[0]
|
||||||
|
if meta_key.startswith("$"):
|
||||||
|
return (False, metadata[meta_key])
|
||||||
|
|
||||||
|
raise KeyError("'%s' is an invalid metadata!" % key)
|
||||||
|
|
||||||
|
def _get_tmpl_vars_helper(self, metadata, config, output):
|
||||||
|
for key, config_value in config.iteritems():
|
||||||
|
is_regular_key, sub_meta = self._get_submeta_by_key(metadata, key)
|
||||||
|
mapping_to = self._get_key_mapping(sub_meta, key, is_regular_key)
|
||||||
|
|
||||||
|
if isinstance(config_value, dict):
|
||||||
|
if mapping_to:
|
||||||
|
new_output = output[mapping_to] = {}
|
||||||
|
else:
|
||||||
|
new_output = output
|
||||||
|
|
||||||
|
self._get_tmpl_vars_helper(sub_meta, config_value,
|
||||||
|
new_output)
|
||||||
|
elif mapping_to:
|
||||||
|
output[mapping_to] = config_value
|
||||||
|
|
||||||
|
def get_config_from_template(self, tmpl_dir, vars_dict):
|
||||||
|
if not os.path.exists(tmpl_dir) or not vars_dict:
|
||||||
|
logging.info("Template or variables dict is not specified!")
|
||||||
|
logging.debug("template dir is %s", tmpl_dir)
|
||||||
|
logging.debug("template vars dict is %s", vars_dict)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
tmpl = Template(file=tmpl_dir, searchList=[vars_dict])
|
||||||
|
config = json.loads(tmpl.respond(), encoding='utf-8')
|
||||||
|
config = json.loads(json.dumps(config), encoding='utf-8')
|
||||||
|
return config
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_installer(cls, name, path, adapter_info, cluster_info, hosts_info):
|
||||||
|
installer = None
|
||||||
|
try:
|
||||||
|
mod_file, path, descr = imp.find_module(name, [path])
|
||||||
|
if mod_file:
|
||||||
|
mod = imp.load_module(name, mod_file, path, descr)
|
||||||
|
return getattr(mod, mod.NAME)(adapter_info, cluster_info,
|
||||||
|
hosts_info)
|
||||||
|
|
||||||
|
except ImportError as exc:
|
||||||
|
logging.error('No such module found: %s', name)
|
||||||
|
logging.exception(exc)
|
||||||
|
|
||||||
|
return installer
|
||||||
|
|
||||||
|
|
||||||
|
class OSInstaller(BaseInstaller):
|
||||||
|
"""Interface for os installer."""
|
||||||
|
NAME = 'OSInstaller'
|
||||||
|
INSTALLER_BASE_DIR = os.path.join(CURRENT_DIR, 'os_installers')
|
||||||
|
|
||||||
|
def get_oses(self):
|
||||||
|
"""virtual method to get supported oses.
|
||||||
|
|
||||||
|
:returns: list of str, each is the supported os version.
|
||||||
|
"""
|
||||||
|
return []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_installer(cls, name, adapter_info, cluster_info, hosts_info):
|
||||||
|
path = os.path.join(cls.INSTALLER_BASE_DIR, name)
|
||||||
|
installer = super(OSInstaller, cls).get_installer(name, path,
|
||||||
|
adapter_info,
|
||||||
|
cluster_info,
|
||||||
|
hosts_info)
|
||||||
|
|
||||||
|
if not isinstance(installer, OSInstaller):
|
||||||
|
logging.info("Installer '%s' is not an OS installer!" % name)
|
||||||
|
return None
|
||||||
|
|
||||||
|
return installer
|
||||||
|
|
||||||
|
def poweron(self, host_id):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def poweroff(self, host_id):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def reset(self, host_id):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PKInstaller(BaseInstaller):
|
||||||
|
"""Interface for package installer."""
|
||||||
|
NAME = 'PKInstaller'
|
||||||
|
INSTALLER_BASE_DIR = os.path.join(CURRENT_DIR, 'pk_installers')
|
||||||
|
|
||||||
|
def get_target_systems(self):
|
||||||
|
"""virtual method to get available target_systems for each os.
|
||||||
|
|
||||||
|
:param oses: supported os versions.
|
||||||
|
:type oses: list of st
|
||||||
|
|
||||||
|
:returns: dict of os_version to target systems as list of str.
|
||||||
|
"""
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def get_roles(self, target_system):
|
||||||
|
"""virtual method to get all roles of given target system.
|
||||||
|
|
||||||
|
:param target_system: target distributed system such as openstack.
|
||||||
|
:type target_system: str
|
||||||
|
|
||||||
|
:returns: dict of role to role description as str.
|
||||||
|
"""
|
||||||
|
return {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_installer(cls, name, adapter_info, cluster_info, hosts_info):
|
||||||
|
path = os.path.join(cls.INSTALLER_BASE_DIR, name)
|
||||||
|
installer = super(PKInstaller, cls).get_installer(name, path,
|
||||||
|
adapter_info,
|
||||||
|
cluster_info,
|
||||||
|
hosts_info)
|
||||||
|
|
||||||
|
if not isinstance(installer, PKInstaller):
|
||||||
|
logging.info("Installer '%s' is not a package installer!" % name)
|
||||||
|
return None
|
||||||
|
|
||||||
|
return installer
|
13
compass/deployment/installers/os_installers/__init__.py
Normal file
13
compass/deployment/installers/os_installers/__init__.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
@ -0,0 +1,13 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
415
compass/deployment/installers/os_installers/cobbler/cobbler.py
Normal file
415
compass/deployment/installers/os_installers/cobbler/cobbler.py
Normal file
@ -0,0 +1,415 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
"""os installer cobbler plugin.
|
||||||
|
"""
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import xmlrpclib
|
||||||
|
|
||||||
|
from compass.deployment.installers.config_manager import BaseConfigManager
|
||||||
|
from compass.deployment.installers.installer import OSInstaller
|
||||||
|
from compass.deployment.utils import constants as const
|
||||||
|
from compass.utils import setting_wrapper as compass_setting
|
||||||
|
from compass.utils import util
|
||||||
|
|
||||||
|
|
||||||
|
NAME = 'CobblerInstaller'
|
||||||
|
|
||||||
|
|
||||||
|
class CobblerInstaller(OSInstaller):
|
||||||
|
"""cobbler installer"""
|
||||||
|
CREDENTIALS = "credentials"
|
||||||
|
USERNAME = 'username'
|
||||||
|
PASSWORD = 'password'
|
||||||
|
|
||||||
|
INSTALLER_URL = "cobbler_url"
|
||||||
|
TMPL_DIR = 'tmpl_dir'
|
||||||
|
SYS_TMPL = 'system.tmpl'
|
||||||
|
SYS_TMPL_NAME = 'system.tmpl'
|
||||||
|
PROFILE = 'profile'
|
||||||
|
POWER_TYPE = 'power_type'
|
||||||
|
POWER_ADDR = 'power_address'
|
||||||
|
POWER_USER = 'power_user'
|
||||||
|
POWER_PASS = 'power_pass'
|
||||||
|
|
||||||
|
def __init__(self, adapter_info, cluster_info, hosts_info):
|
||||||
|
super(CobblerInstaller, self).__init__()
|
||||||
|
|
||||||
|
self.config_manager = CobblerConfigManager(adapter_info,
|
||||||
|
cluster_info,
|
||||||
|
hosts_info)
|
||||||
|
installer_settings = self.config_manager.get_os_installer_settings()
|
||||||
|
try:
|
||||||
|
username = installer_settings[self.CREDENTIALS][self.USERNAME]
|
||||||
|
password = installer_settings[self.CREDENTIALS][self.PASSWORD]
|
||||||
|
cobbler_url = installer_settings[self.INSTALLER_URL]
|
||||||
|
self.tmpl_dir = CobblerInstaller.get_tmpl_path()
|
||||||
|
|
||||||
|
except KeyError as ex:
|
||||||
|
raise KeyError(ex.message)
|
||||||
|
|
||||||
|
# The connection is created when cobbler installer is initialized.
|
||||||
|
self.remote = self._get_cobbler_server(cobbler_url)
|
||||||
|
self.token = self._get_token(username, password)
|
||||||
|
self.pk_installer_config = None
|
||||||
|
|
||||||
|
logging.debug('%s instance created', 'CobblerInstaller')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_tmpl_path(cls):
|
||||||
|
return os.path.join(compass_setting.TMPL_DIR, 'cobbler')
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '%r[name=%r,remote=%r,token=%r' % (
|
||||||
|
self.__class__.__name__, self.remote, self.token)
|
||||||
|
|
||||||
|
def _get_cobbler_server(self, cobbler_url):
|
||||||
|
if not cobbler_url:
|
||||||
|
logging.error("Cobbler URL is None!")
|
||||||
|
raise Exception("Cobbler URL cannot be None!")
|
||||||
|
|
||||||
|
return xmlrpclib.Server(cobbler_url)
|
||||||
|
|
||||||
|
def _get_token(self, username, password):
|
||||||
|
if self.remote is None:
|
||||||
|
raise Exception("Cobbler remote instance is None!")
|
||||||
|
return self.remote.login(username, password)
|
||||||
|
|
||||||
|
def get_supported_oses(self):
|
||||||
|
"""get supported os versions.
|
||||||
|
.. note::
|
||||||
|
In cobbler, we treat profile name as the indicator
|
||||||
|
of os version. It is just a simple indicator
|
||||||
|
and not accurate.
|
||||||
|
"""
|
||||||
|
profiles = self.remote.get_profiles()
|
||||||
|
oses = []
|
||||||
|
for profile in profiles:
|
||||||
|
oses.append(profile['name'])
|
||||||
|
return oses
|
||||||
|
|
||||||
|
def deploy(self):
|
||||||
|
"""Sync cobbler to catch up the latest update config and start to
|
||||||
|
install OS. Return both cluster and hosts deploy configs. The return
|
||||||
|
format:
|
||||||
|
{
|
||||||
|
"cluster": {
|
||||||
|
"id": 1,
|
||||||
|
"deployed_os_config": {},
|
||||||
|
},
|
||||||
|
"hosts": {
|
||||||
|
1($clusterhost_id): {
|
||||||
|
"deployed_os_config": {...},
|
||||||
|
},
|
||||||
|
....
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
os_version = self.config_manager.get_os_version()
|
||||||
|
profile = self._get_profile_from_server(os_version)
|
||||||
|
|
||||||
|
global_vars_dict = self._get_cluster_tmpl_vars_dict()
|
||||||
|
|
||||||
|
clusterhost_ids = self.config_manager.get_host_id_list()
|
||||||
|
hosts_deploy_config = {}
|
||||||
|
|
||||||
|
for host_id in clusterhost_ids:
|
||||||
|
fullname = self.config_manager.get_host_name(host_id)
|
||||||
|
vars_dict = self._get_host_tmpl_vars_dict(host_id,
|
||||||
|
global_vars_dict,
|
||||||
|
fullname=fullname,
|
||||||
|
profile=profile)
|
||||||
|
|
||||||
|
self.update_host_config_to_cobbler(host_id, fullname, vars_dict)
|
||||||
|
|
||||||
|
# set host deploy config
|
||||||
|
temp = {}
|
||||||
|
temp = self.config_manager.get_host_deploy_os_config(host_id)
|
||||||
|
temp[const.TMPL_VARS_DICT] = vars_dict
|
||||||
|
host_config = {const.DEPLOYED_OS_CONFIG: temp}
|
||||||
|
hosts_deploy_config[host_id] = host_config
|
||||||
|
|
||||||
|
# set cluster deploy config
|
||||||
|
cluster_deconfig = self.config_manager.get_cluster_deployed_os_config()
|
||||||
|
cluster_deconfig[const.TMPL_VARS_DICT] = global_vars_dict
|
||||||
|
|
||||||
|
# sync to cobbler and trigger installtion.
|
||||||
|
self._sync()
|
||||||
|
|
||||||
|
return {
|
||||||
|
const.CLUSTER: {
|
||||||
|
const.ID: self.config_manager.get_cluster_id(),
|
||||||
|
const.DEPLOYED_OS_CONFIG: cluster_deconfig
|
||||||
|
},
|
||||||
|
const.HOSTS: hosts_deploy_config
|
||||||
|
}
|
||||||
|
|
||||||
|
def clean_progress(self):
|
||||||
|
"""clean log files and config for hosts which to deploy."""
|
||||||
|
clusterhost_list = self.config_manager.get_host_id_list()
|
||||||
|
log_dir_prefix = compass_setting.INSTALLATION_LOGDIR[self.NAME]
|
||||||
|
|
||||||
|
for host_id in clusterhost_list:
|
||||||
|
fullname = self.config_manager.get_host_name(host_id)
|
||||||
|
self._clean_log(log_dir_prefix, fullname)
|
||||||
|
|
||||||
|
def redeploy(self):
|
||||||
|
"""redeploy hosts."""
|
||||||
|
host_ids = self.config_manager.get_host_id_list()
|
||||||
|
for host_id in host_ids:
|
||||||
|
fullname = self.config_manager.get_host_name(host_id)
|
||||||
|
sys_id = self._get_system_id(fullname)
|
||||||
|
if sys_id:
|
||||||
|
self._netboot_enabled(sys_id)
|
||||||
|
|
||||||
|
self._sync()
|
||||||
|
|
||||||
|
def set_package_installer_config(self, package_configs):
|
||||||
|
"""Cobbler can install and configure package installer right after
|
||||||
|
OS installation compelets by setting package_config info provided
|
||||||
|
by package installer.
|
||||||
|
|
||||||
|
:param dict package_configs: The dict of config generated by package
|
||||||
|
installer for each clusterhost. The IDs
|
||||||
|
of clusterhosts are the keys of
|
||||||
|
package_configs.
|
||||||
|
"""
|
||||||
|
self.pk_installer_config = package_configs
|
||||||
|
|
||||||
|
def _sync(self):
|
||||||
|
"""Sync the updated config to cobbler and trigger installation."""
|
||||||
|
try:
|
||||||
|
self.remote.sync(self.token)
|
||||||
|
logging.debug('sync %s', self)
|
||||||
|
os.system('sudo service rsyslog restart')
|
||||||
|
except Exception as ex:
|
||||||
|
logging.debug("Failed to sync cobbler server! Error:", ex.message)
|
||||||
|
raise ex
|
||||||
|
|
||||||
|
def _get_system_config(self, host_id, vars_dict):
|
||||||
|
"""Generate updated system config from the template.
|
||||||
|
|
||||||
|
:param vars_dict: dict of variables for the system template to
|
||||||
|
generate system config dict.
|
||||||
|
"""
|
||||||
|
os_version = self.config_manager.get_os_version()
|
||||||
|
|
||||||
|
system_tmpl_path = os.path.join(os.path.join(self.tmpl_dir,
|
||||||
|
os_version),
|
||||||
|
self.SYS_TMPL_NAME)
|
||||||
|
system_config = self.get_config_from_template(system_tmpl_path,
|
||||||
|
vars_dict)
|
||||||
|
# update package config info to cobbler ksmeta
|
||||||
|
if self.pk_installer_config and host_id in self.pk_installer_config:
|
||||||
|
pk_config = self.pk_installer_config[host_id]
|
||||||
|
ksmeta = system_config.setdefault("ksmeta", {})
|
||||||
|
util.merge_dict(ksmeta, pk_config)
|
||||||
|
system_config["ksmeta"] = ksmeta
|
||||||
|
|
||||||
|
return system_config
|
||||||
|
|
||||||
|
def _get_profile_from_server(self, os_version):
|
||||||
|
"""Get profile from cobbler server."""
|
||||||
|
result = self.remote.find_profile({'name': os_version})
|
||||||
|
if not result:
|
||||||
|
raise Exception("Cannot find profile for '%s'", os_version)
|
||||||
|
|
||||||
|
profile = result[0]
|
||||||
|
return profile
|
||||||
|
|
||||||
|
def _get_system_id(self, fullname):
|
||||||
|
"""get system reference id for the host."""
|
||||||
|
sys_name = fullname
|
||||||
|
sys_id = None
|
||||||
|
system_info = self.remote.find_system({"name": fullname})
|
||||||
|
|
||||||
|
if not system_info:
|
||||||
|
# Create a new system
|
||||||
|
sys_id = self.remote.new_system(self.token)
|
||||||
|
self.remote.modify_system(sys_id, "name", fullname, self.token)
|
||||||
|
logging.debug('create new system %s for %s', sys_id, sys_name)
|
||||||
|
else:
|
||||||
|
sys_id = self.remote.get_system_handle(sys_name, self.token)
|
||||||
|
|
||||||
|
return sys_id
|
||||||
|
|
||||||
|
def _clean_system(self, fullname):
|
||||||
|
"""clean system."""
|
||||||
|
sys_name = fullname
|
||||||
|
try:
|
||||||
|
self.remote.remove_system(sys_name, self.token)
|
||||||
|
logging.debug('system %s is removed', sys_name)
|
||||||
|
except Exception:
|
||||||
|
logging.debug('no system %s found to remove', sys_name)
|
||||||
|
|
||||||
|
def _update_system_config(self, sys_id, system_config):
|
||||||
|
"""update modify system."""
|
||||||
|
for key, value in system_config.iteritems():
|
||||||
|
self.remote.modify_system(sys_id, str(key), value, self.token)
|
||||||
|
|
||||||
|
self.remote.save_system(sys_id, self.token)
|
||||||
|
|
||||||
|
def _netboot_enabled(self, sys_id):
|
||||||
|
"""enable netboot."""
|
||||||
|
self.remote.modify_system(sys_id, 'netboot_enabled', True, self.token)
|
||||||
|
self.remote.save_system(sys_id, self.token)
|
||||||
|
|
||||||
|
def _clean_log(self, log_dir_prefix, system_name):
|
||||||
|
"""clean log."""
|
||||||
|
log_dir = os.path.join(log_dir_prefix, system_name)
|
||||||
|
shutil.rmtree(log_dir, True)
|
||||||
|
|
||||||
|
def update_host_config_to_cobbler(self, host_id, fullname, vars_dict):
|
||||||
|
"""update host config and upload to cobbler server."""
|
||||||
|
sys_id = self._get_system_id(fullname)
|
||||||
|
|
||||||
|
system_config = self._get_system_config(host_id, vars_dict)
|
||||||
|
logging.debug('%s system config to update: %s', host_id, system_config)
|
||||||
|
|
||||||
|
self._update_system_config(sys_id, system_config)
|
||||||
|
self._netboot_enabled(sys_id)
|
||||||
|
|
||||||
|
def delete_hosts(self):
|
||||||
|
hosts_id_list = self.config_manager.get_host_id_list()
|
||||||
|
for host_id in hosts_id_list:
|
||||||
|
self.delete_single_host(host_id)
|
||||||
|
|
||||||
|
def delete_single_host(self, host_id):
|
||||||
|
"""Delete the host from cobbler server and clean up the installation
|
||||||
|
progress.
|
||||||
|
"""
|
||||||
|
fullname = self.config_manager.get_host_name(host_id)
|
||||||
|
try:
|
||||||
|
log_dir_prefix = compass_setting.INSTALLATION_LOGDIR[self.NAME]
|
||||||
|
self._clean_system(fullname)
|
||||||
|
self._clean_log(log_dir_prefix, fullname)
|
||||||
|
except Exception as ex:
|
||||||
|
logging.info("Deleting host got exception: %s", ex.message)
|
||||||
|
|
||||||
|
def _get_host_tmpl_vars_dict(self, host_id, global_vars_dict, **kwargs):
|
||||||
|
"""Generate template variables dictionary.
|
||||||
|
"""
|
||||||
|
vars_dict = {}
|
||||||
|
if global_vars_dict:
|
||||||
|
# Set cluster template vars_dict from cluster os_config.
|
||||||
|
util.merge_dict(vars_dict, global_vars_dict)
|
||||||
|
|
||||||
|
if self.PROFILE in kwargs:
|
||||||
|
profile = kwargs[self.PROFILE]
|
||||||
|
else:
|
||||||
|
os_version = self.config_manager.get_os_version()
|
||||||
|
profile = self._get_profile_from_server(os_version)
|
||||||
|
vars_dict[self.PROFILE] = profile
|
||||||
|
|
||||||
|
# Set fullname, MAC address and hostname, networks, dns and so on.
|
||||||
|
host_baseinfo = self.config_manager.get_host_baseinfo(host_id)
|
||||||
|
util.merge_dict(vars_dict, host_baseinfo)
|
||||||
|
|
||||||
|
os_config_metadata = self.config_manager.get_os_config_metadata()
|
||||||
|
host_os_config = self.config_manager.get_host_os_config(host_id)
|
||||||
|
|
||||||
|
# Get template variables values from host os_config
|
||||||
|
host_vars_dict = self.get_tmpl_vars_from_metadata(os_config_metadata,
|
||||||
|
host_os_config)
|
||||||
|
util.merge_dict(vars_dict, host_vars_dict)
|
||||||
|
|
||||||
|
return {const.HOST: vars_dict}
|
||||||
|
|
||||||
|
def _get_cluster_tmpl_vars_dict(self):
|
||||||
|
os_config_metadata = self.config_manager.get_os_config_metadata()
|
||||||
|
cluster_os_config = self.config_manager.get_cluster_os_config()
|
||||||
|
|
||||||
|
vars_dict = self.get_tmpl_vars_from_metadata(os_config_metadata,
|
||||||
|
cluster_os_config)
|
||||||
|
return vars_dict
|
||||||
|
|
||||||
|
def _check_and_set_system_impi(self, host_id, sys_id):
|
||||||
|
if not sys_id:
|
||||||
|
logging.info("System is None!")
|
||||||
|
return False
|
||||||
|
|
||||||
|
fullname = self.config_manager.get_host_name(host_id)
|
||||||
|
system = self.remote.get_system_as_rendered(fullname)
|
||||||
|
if system[self.POWER_TYPE] != 'ipmilan' or not system[self.POWER_USER]:
|
||||||
|
ipmi_info = self.config_manager.get_host_ipmi_info(host_id)
|
||||||
|
if not ipmi_info:
|
||||||
|
logging.info('No IPMI information found! Failed power on.')
|
||||||
|
return False
|
||||||
|
|
||||||
|
ipmi_ip, ipmi_user, ipmi_pass = ipmi_info
|
||||||
|
power_opts = {}
|
||||||
|
power_opts[self.POWER_TYPE] = 'ipmilan'
|
||||||
|
power_opts[self.POWER_ADDR] = ipmi_ip
|
||||||
|
power_opts[self.POWER_USER] = ipmi_user
|
||||||
|
power_opts[self.POWER_PASS] = ipmi_pass
|
||||||
|
|
||||||
|
self._update_system_config(sys_id, power_opts)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def poweron(self, host_id):
|
||||||
|
fullname = self.config_manager.get_host_name(host_id)
|
||||||
|
sys_id = self._get_system_id(fullname)
|
||||||
|
if not self._check_and_set_system_impi(sys_id):
|
||||||
|
return
|
||||||
|
|
||||||
|
self.remote.power_system(sys_id, self.token, power='on')
|
||||||
|
logging.info("Host with ID=%d starts to power on!" % host_id)
|
||||||
|
|
||||||
|
def poweroff(self, host_id):
|
||||||
|
fullname = self.config_manager.get_host_name(host_id)
|
||||||
|
sys_id = self._get_system_id(fullname)
|
||||||
|
if not self._check_and_set_system_impi(sys_id):
|
||||||
|
return
|
||||||
|
|
||||||
|
self.remote.power_system(sys_id, self.token, power='off')
|
||||||
|
logging.info("Host with ID=%d starts to power off!" % host_id)
|
||||||
|
|
||||||
|
def reset(self, host_id):
|
||||||
|
fullname = self.config_manager.get_host_name(host_id)
|
||||||
|
sys_id = self._get_system_id(fullname)
|
||||||
|
if not self._check_and_set_system_impi(sys_id):
|
||||||
|
return
|
||||||
|
|
||||||
|
self.remote.power_system(sys_id, self.token, power='reboot')
|
||||||
|
logging.info("Host with ID=%d starts to reboot!" % host_id)
|
||||||
|
|
||||||
|
|
||||||
|
class CobblerConfigManager(BaseConfigManager):
|
||||||
|
|
||||||
|
def __init__(self, adapter_info, cluster_info, hosts_info):
|
||||||
|
super(CobblerConfigManager, self).__init__(adapter_info,
|
||||||
|
cluster_info,
|
||||||
|
hosts_info)
|
||||||
|
|
||||||
|
def get_host_ipmi_info(self, host_id):
|
||||||
|
host_info = self._get_host_info(host_id)
|
||||||
|
if not host_info:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if self.IPMI not in host_info:
|
||||||
|
return None
|
||||||
|
|
||||||
|
ipmi_info = host_info[const.IPMI]
|
||||||
|
|
||||||
|
if not ipmi_info:
|
||||||
|
raise Exception('Cannot find IPMI information!')
|
||||||
|
|
||||||
|
ipmi_ip = ipmi_info[const.IP_ADDR]
|
||||||
|
ipmi_user = ipmi_info[const.IPMI_CREDS][const.USERNAME]
|
||||||
|
ipmi_pass = ipmi_info[const.IPMI_CREDS][const.PASSWORD]
|
||||||
|
|
||||||
|
return (ipmi_ip, ipmi_user, ipmi_pass)
|
13
compass/deployment/installers/pk_installers/__init__.py
Normal file
13
compass/deployment/installers/pk_installers/__init__.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
@ -0,0 +1,13 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
@ -0,0 +1,472 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
__author__ = "Grace Yu (grace.yu@huawei.com)"
|
||||||
|
|
||||||
|
"""package installer: chef plugin."""
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
from compass.deployment.installers.config_manager import BaseConfigManager
|
||||||
|
from compass.deployment.installers.installer import PKInstaller
|
||||||
|
from compass.deployment.utils import constants as const
|
||||||
|
from compass.utils import setting_wrapper as compass_setting
|
||||||
|
from compass.utils import util
|
||||||
|
|
||||||
|
|
||||||
|
NAME = 'ChefInstaller'
|
||||||
|
|
||||||
|
|
||||||
|
class ChefInstaller(PKInstaller):
|
||||||
|
"""chef package installer."""
|
||||||
|
ENV_TMPL_NAME = 'env.tmpl'
|
||||||
|
NODE_TMPL_DIR = 'node'
|
||||||
|
DATABAG_TMPL_DIR = 'databags'
|
||||||
|
COMMON_NODE_TMPL_NAME = 'node.tmpl'
|
||||||
|
|
||||||
|
def __init__(self, adapter_info, cluster_info, hosts_info):
|
||||||
|
super(ChefInstaller, self).__init__()
|
||||||
|
|
||||||
|
self.config_manager = ChefConfigManager(adapter_info, cluster_info,
|
||||||
|
hosts_info)
|
||||||
|
adapter_name = self.config_manager.get_dist_system_name()
|
||||||
|
self.tmpl_dir = ChefInstaller.get_tmpl_path(adapter_name)
|
||||||
|
|
||||||
|
self.installer_url = self.config_manager.get_chef_url()
|
||||||
|
key, client = self.config_manager.get_chef_credentials()
|
||||||
|
|
||||||
|
self.chef_api = self._get_chef_api(key, client)
|
||||||
|
logging.debug('%s instance created', self)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_tmpl_path(cls, adapter_name):
|
||||||
|
tmpl_path = os.path.join(os.path.join(compass_setting.TMPL_DIR,
|
||||||
|
'chef_installer'),
|
||||||
|
adapter_name)
|
||||||
|
return tmpl_path
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '%s[name=%s,installer_url=%s]' % (
|
||||||
|
self.__class__.__name__, self.NAME, self.installer_url)
|
||||||
|
|
||||||
|
def _get_chef_api(self, key=None, client=None):
|
||||||
|
"""Initializes chef API client."""
|
||||||
|
import chef
|
||||||
|
chef_api = None
|
||||||
|
try:
|
||||||
|
if key and client:
|
||||||
|
chef_api = chef.ChefAPI(self.installer_url, key, client)
|
||||||
|
else:
|
||||||
|
chef_api = chef.autoconfigure()
|
||||||
|
|
||||||
|
except Exception as ex:
|
||||||
|
err_msg = "Failed to instantiate chef API, error: %s" % ex.message
|
||||||
|
raise Exception(err_msg)
|
||||||
|
|
||||||
|
return chef_api
|
||||||
|
|
||||||
|
def get_env_name(self, dist_sys_name, cluster_id):
|
||||||
|
"""Generate environment name."""
|
||||||
|
return "-".join((dist_sys_name, cluster_id))
|
||||||
|
|
||||||
|
def get_databag_name(self):
|
||||||
|
"""Get databag name."""
|
||||||
|
return self.config_manager.get_dist_system_name()
|
||||||
|
|
||||||
|
def get_databag(self, databag_name):
|
||||||
|
"""Get databag object from chef server. Creating the databag if its
|
||||||
|
doesnot exist.
|
||||||
|
"""
|
||||||
|
import chef
|
||||||
|
bag = chef.DataBag(databag_name, api=self.chef_api)
|
||||||
|
bag.save()
|
||||||
|
return bag
|
||||||
|
|
||||||
|
def get_node(self, node_name, env_name=None):
|
||||||
|
"""Get chef node if existing, otherwise create one and set its
|
||||||
|
environment.
|
||||||
|
|
||||||
|
:param str node_name: The name for this node.
|
||||||
|
:param str env_name: The environment name for this node.
|
||||||
|
"""
|
||||||
|
import chef
|
||||||
|
if not self.chef_api:
|
||||||
|
logging.info("Cannot find ChefAPI object!")
|
||||||
|
raise Exception("Cannot find ChefAPI object!")
|
||||||
|
|
||||||
|
node = chef.Node(node_name, api=self.chef_api)
|
||||||
|
if node not in chef.Node.list(api=self.chef_api):
|
||||||
|
if env_name:
|
||||||
|
node.chef_environment = env_name
|
||||||
|
node.save()
|
||||||
|
|
||||||
|
return node
|
||||||
|
|
||||||
|
def delete_hosts(self):
|
||||||
|
hosts_id_list = self.config_manager.get_host_id_list()
|
||||||
|
for host_id in hosts_id_list:
|
||||||
|
self.delete_node(host_id)
|
||||||
|
|
||||||
|
def delete_node(self, host_id):
|
||||||
|
fullname = self.config_manager.get_host_name(host_id)
|
||||||
|
node = self.get_node(fullname)
|
||||||
|
self._delete_node(node)
|
||||||
|
|
||||||
|
def _delete_node(self, node):
|
||||||
|
"""clean node attributes about target system."""
|
||||||
|
import chef
|
||||||
|
if node is None:
|
||||||
|
raise Exception("Node is None, cannot delete a none node.")
|
||||||
|
node_name = node.name
|
||||||
|
client_name = node_name
|
||||||
|
|
||||||
|
# Clean log for this node first
|
||||||
|
log_dir_prefix = compass_setting.INSTALLATION_LOGDIR[self.NAME]
|
||||||
|
self._clean_log(log_dir_prefix, node_name)
|
||||||
|
|
||||||
|
# Delete node and its client on chef server
|
||||||
|
try:
|
||||||
|
node.delete()
|
||||||
|
client = chef.Client(client_name, api=self.chef_api)
|
||||||
|
client.delete()
|
||||||
|
logging.debug('delete node %s', node_name)
|
||||||
|
log_dir_prefix = compass_setting.INSTALLATION_LOGDIR[self.NAME]
|
||||||
|
self._clean_log(log_dir_prefix, node_name)
|
||||||
|
except Exception as error:
|
||||||
|
logging.debug(
|
||||||
|
'failed to delete node %s, error: %s', node_name, error)
|
||||||
|
|
||||||
|
def _add_roles(self, node, roles):
|
||||||
|
"""Add roles to the node.
|
||||||
|
:param object node: The node object.
|
||||||
|
:param list roles: The list of roles for this node.
|
||||||
|
"""
|
||||||
|
if node is None:
|
||||||
|
raise Exception("Node is None!")
|
||||||
|
|
||||||
|
if not roles:
|
||||||
|
logging.info("Role list is None. Run list will no change.")
|
||||||
|
return
|
||||||
|
|
||||||
|
run_list = node.run_list
|
||||||
|
for role in roles:
|
||||||
|
if role not in run_list:
|
||||||
|
node.run_list.append('role[%s]' % role)
|
||||||
|
|
||||||
|
node.save()
|
||||||
|
logging.debug('Runlist for node %s is %s', node.name, node.run_list)
|
||||||
|
|
||||||
|
def _get_node_attributes(self, roles, vars_dict):
|
||||||
|
"""Get node attributes from templates according to its roles. The
|
||||||
|
templates are named by roles without '-'. Return the dictionary
|
||||||
|
of attributes defined in the templates.
|
||||||
|
|
||||||
|
:param list roles: The roles for this node, used to load the
|
||||||
|
specific template.
|
||||||
|
:param dict vars_dict: The dictionary used in cheetah searchList to
|
||||||
|
render attributes from templates.
|
||||||
|
"""
|
||||||
|
if not roles:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
node_tmpl_dir = os.path.join(self.tmpl_dir, self.NODE_TMPL_DIR)
|
||||||
|
node_attri = {}
|
||||||
|
for role in roles:
|
||||||
|
role = role.replace('-', '_')
|
||||||
|
tmpl_name = '.'.join((role, 'tmpl'))
|
||||||
|
node_tmpl = os.path.join(node_tmpl_dir, tmpl_name)
|
||||||
|
node_attri = self.get_config_from_template(node_tmpl, vars_dict)
|
||||||
|
|
||||||
|
return node_attri
|
||||||
|
|
||||||
|
def update_node(self, node, roles, vars_dict):
|
||||||
|
"""Update node attributes to chef server."""
|
||||||
|
if node is None:
|
||||||
|
raise Exception("Node is None!")
|
||||||
|
|
||||||
|
if not roles:
|
||||||
|
logging.info("The list of roles is None.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Add roles to node Rolelist on chef server.
|
||||||
|
self._add_roles(node, roles)
|
||||||
|
|
||||||
|
# Update node attributes.
|
||||||
|
node_config = self._get_node_attributes(roles, vars_dict)
|
||||||
|
for attr in node_config:
|
||||||
|
setattr(node, attr, node_config[attr])
|
||||||
|
|
||||||
|
node.save()
|
||||||
|
|
||||||
|
def _get_env_attributes(self, vars_dict):
|
||||||
|
"""Get environment attributes from env templates."""
|
||||||
|
|
||||||
|
env_tmpl = os.path.join(self.tmpl_dir, self.ENV_TMPL_NAME)
|
||||||
|
env_attri = self.get_config_from_template(env_tmpl, vars_dict)
|
||||||
|
return env_attri
|
||||||
|
|
||||||
|
def update_environment(self, env_name, vars_dict):
|
||||||
|
"""Generate environment attributes based on the template file and
|
||||||
|
upload it to chef server.
|
||||||
|
|
||||||
|
:param str env_name: The environment name.
|
||||||
|
:param dict vars_dict: The dictionary used in cheetah searchList to
|
||||||
|
render attributes from templates.
|
||||||
|
"""
|
||||||
|
import chef
|
||||||
|
env_config = self._get_env_attributes(vars_dict)
|
||||||
|
env = chef.Environment(env_name, api=self.chef_api)
|
||||||
|
for attr in env_config:
|
||||||
|
if attr in env.attributes:
|
||||||
|
setattr(env, attr, env_config[attr])
|
||||||
|
env.save()
|
||||||
|
|
||||||
|
def _get_databagitem_attributes(self, tmpl_dir, vars_dict):
|
||||||
|
databagitem_attri = self.get_config_from_template(tmpl_dir,
|
||||||
|
vars_dict)
|
||||||
|
|
||||||
|
return databagitem_attri
|
||||||
|
|
||||||
|
def update_databags(self, vars_dict):
|
||||||
|
"""Update datbag item attributes.
|
||||||
|
|
||||||
|
:param dict vars_dict: The dictionary used to get attributes from
|
||||||
|
templates.
|
||||||
|
"""
|
||||||
|
databag_names = self.config_manager.get_chef_databag_names()
|
||||||
|
if not databag_names:
|
||||||
|
return
|
||||||
|
|
||||||
|
import chef
|
||||||
|
databags_dir = os.path.join(self.tmpl_dir, self.DATABAG_TMPL_DIR)
|
||||||
|
for databag_name in databag_names:
|
||||||
|
databag = self.get_databag(databag_name)
|
||||||
|
databag_tmpl = os.paht.join(databags_dir, databag_name)
|
||||||
|
databagitem_attri = self._get_databagitem_attributes(databag_tmpl,
|
||||||
|
vars_dict)
|
||||||
|
|
||||||
|
for item, item_values in databagitem_attri.iteritems():
|
||||||
|
databagitem = chef.DataBagItem(databag, item,
|
||||||
|
api=self.chef_api)
|
||||||
|
for key, value in item_values.iteritems():
|
||||||
|
databagitem[key] = value
|
||||||
|
databagitem.save()
|
||||||
|
|
||||||
|
def _get_host_tmpl_vars(self, host_id, global_vars_dict):
|
||||||
|
"""Get templates variables dictionary for cheetah searchList based
|
||||||
|
on host package config.
|
||||||
|
|
||||||
|
:param int host_id: The host ID.
|
||||||
|
:param dict global_vars_dict: The vars_dict got from cluster level
|
||||||
|
package_config.
|
||||||
|
"""
|
||||||
|
vars_dict = {}
|
||||||
|
if global_vars_dict:
|
||||||
|
temp = global_vars_dict[const.CLUSTER][const.DEPLOYED_PK_CONFIG]
|
||||||
|
vars_dict[const.DEPLOYED_PK_CONFIG] = temp
|
||||||
|
|
||||||
|
host_baseinfo = self.config_manager.get_host_baseinfo(host_id)
|
||||||
|
util.merge_dict(vars_dict, host_baseinfo)
|
||||||
|
|
||||||
|
pk_config = self.config_manager.get_host_package_config(host_id)
|
||||||
|
if pk_config:
|
||||||
|
# Get host template variables and merge to vars_dict
|
||||||
|
metadata = self.config_manager.get_pk_config_meatadata()
|
||||||
|
host_dict = self.get_tmpl_vars_from_metadata(metadata, pk_config)
|
||||||
|
util.merge_dict(vars_dict[const.DEPLOYED_PK_CONFIG], host_dict)
|
||||||
|
|
||||||
|
# Set role_mapping for host
|
||||||
|
mapping = self.config_manager.get_host_roles_mapping(host_id)
|
||||||
|
vars_dict[const.DEPLOYED_PK_CONFIG][const.ROLES_MAPPING] = mapping
|
||||||
|
|
||||||
|
return {const.HOST: vars_dict}
|
||||||
|
|
||||||
|
def _get_cluster_tmpl_vars(self):
|
||||||
|
vars_dict = {}
|
||||||
|
cluster_baseinfo = self.config_manager.get_cluster_baseinfo()
|
||||||
|
util.merge_dict(vars_dict, cluster_baseinfo)
|
||||||
|
|
||||||
|
pk_metadata = self.config_manager.get_pk_config_meatadata()
|
||||||
|
pk_config = self.config_manager.get_cluster_package_config()
|
||||||
|
meta_dict = self.get_tmpl_vars_from_metadata(pk_metadata, pk_config)
|
||||||
|
vars_dict[const.DEPLOYED_PK_CONFIG] = meta_dict
|
||||||
|
|
||||||
|
mapping = self.config_manager.get_cluster_roles_mapping()
|
||||||
|
vars_dict[const.DEPLOYED_PK_CONFIG][const.ROLES_MAPPING] = mapping
|
||||||
|
|
||||||
|
return {const.CLUSTER: vars_dict}
|
||||||
|
|
||||||
|
def deploy(self):
|
||||||
|
"""Start to deploy a distributed system. Return both cluster and hosts
|
||||||
|
deployed configs. The return format:
|
||||||
|
{
|
||||||
|
"cluster": {
|
||||||
|
"id": 1,
|
||||||
|
"deployed_package_config": {...}
|
||||||
|
},
|
||||||
|
"hosts": {
|
||||||
|
1($clusterhost_id): {
|
||||||
|
"deployed_package_config": {...}
|
||||||
|
},
|
||||||
|
....
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
adapter_name = self.config_manager.get_adapter_name()
|
||||||
|
cluster_id = self.config_manager.get_cluster_id()
|
||||||
|
env_name = self.get_env_name(adapter_name, str(cluster_id))
|
||||||
|
|
||||||
|
global_vars_dict = self._get_cluster_tmpl_vars()
|
||||||
|
# Update environment
|
||||||
|
self.update_environment(env_name, global_vars_dict)
|
||||||
|
|
||||||
|
# Update Databag item
|
||||||
|
self.update_databags(global_vars_dict)
|
||||||
|
|
||||||
|
host_list = self.config_manager.get_host_id_list()
|
||||||
|
hosts_deployed_configs = {}
|
||||||
|
|
||||||
|
for host_id in host_list:
|
||||||
|
node_name = self.config_manager.get_host_name(host_id)
|
||||||
|
roles = self.config_manager.get_host_roles(host_id)
|
||||||
|
|
||||||
|
node = self.get_node(node_name, env_name)
|
||||||
|
vars_dict = self._get_host_tmpl_vars(host_id, global_vars_dict)
|
||||||
|
self.update_node(node, roles, vars_dict)
|
||||||
|
|
||||||
|
# set each host deployed config
|
||||||
|
tmp = self.config_manager.get_host_deployed_package_config(host_id)
|
||||||
|
tmp[const.TMPL_VARS_DICT] = vars_dict
|
||||||
|
hosts_deployed_configs[host_id] = tmp
|
||||||
|
|
||||||
|
# set cluster deployed config
|
||||||
|
cl_config = self.config_manager.get_cluster_deployed_package_config()
|
||||||
|
cl_config[const.TMPL_VARS_DICT] = global_vars_dict
|
||||||
|
|
||||||
|
return {
|
||||||
|
const.CLUSTER: {
|
||||||
|
const.ID: cluster_id,
|
||||||
|
const.DEPLOYED_PK_CONFIG: cl_config
|
||||||
|
},
|
||||||
|
const.HOSTS: hosts_deployed_configs
|
||||||
|
}
|
||||||
|
|
||||||
|
def generate_installer_config(self):
|
||||||
|
"""Render chef config file (client.rb) by OS installing right after
|
||||||
|
OS is installed successfully.
|
||||||
|
The output format:
|
||||||
|
{
|
||||||
|
'1'($host_id/clusterhost_id):{
|
||||||
|
'tool': 'chef',
|
||||||
|
'chef_url': 'https://xxx',
|
||||||
|
'chef_client_name': '$host_name',
|
||||||
|
'chef_node_name': '$host_name'
|
||||||
|
},
|
||||||
|
.....
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
host_ids = self.config_manager.get_host_id_list()
|
||||||
|
os_installer_configs = {}
|
||||||
|
for host_id in host_ids:
|
||||||
|
fullname = self.config_manager.get_host_name(host_id)
|
||||||
|
temp = {
|
||||||
|
"tool": "chef",
|
||||||
|
"chef_url": self.installer_url
|
||||||
|
}
|
||||||
|
temp['chef_client_name'] = fullname
|
||||||
|
temp['chef_node_name'] = fullname
|
||||||
|
os_installer_configs[host_id] = temp
|
||||||
|
|
||||||
|
return os_installer_configs
|
||||||
|
|
||||||
|
def clean_progress(self):
|
||||||
|
"""Clean all installing log about the node."""
|
||||||
|
log_dir_prefix = compass_setting.INSTALLATION_LOGDIR[self.NAME]
|
||||||
|
hosts_list = self.config_manager.get_host_id_list()
|
||||||
|
for host_id in hosts_list:
|
||||||
|
fullname = self.config_manager.get_host_name()
|
||||||
|
self._clean_log(log_dir_prefix, fullname)
|
||||||
|
|
||||||
|
def _clean_log(self, log_dir_prefix, node_name):
|
||||||
|
log_dir = os.path.join(log_dir_prefix, node_name)
|
||||||
|
shutil.rmtree(log_dir, True)
|
||||||
|
|
||||||
|
def get_supported_dist_systems(self):
|
||||||
|
"""get target systems from chef. All target_systems for compass will
|
||||||
|
be stored in the databag called "compass".
|
||||||
|
"""
|
||||||
|
databag = self.__get_compass_databag()
|
||||||
|
target_systems = {}
|
||||||
|
for system_name, item in databag:
|
||||||
|
target_systems[system_name] = item
|
||||||
|
|
||||||
|
return target_systems
|
||||||
|
|
||||||
|
def _clean_databag_item(self, databag, item_name):
|
||||||
|
"""clean databag item."""
|
||||||
|
import chef
|
||||||
|
if item_name not in chef.DataBagItem.list(api=self.chef_api):
|
||||||
|
logging.info("Databag item '%s' is not found!", item_name)
|
||||||
|
return
|
||||||
|
|
||||||
|
bag_item = databag[item_name]
|
||||||
|
try:
|
||||||
|
bag_item.delete()
|
||||||
|
logging.debug('databag item %s is removed from databag',
|
||||||
|
item_name)
|
||||||
|
except Exception as error:
|
||||||
|
logging.debug('Failed to delete item %s from databag! Error: %s',
|
||||||
|
item_name, error)
|
||||||
|
databag.save()
|
||||||
|
|
||||||
|
def redeploy(self):
|
||||||
|
"""reinstall host."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ChefConfigManager(BaseConfigManager):
|
||||||
|
TMPL_DIR = 'tmpl_dir'
|
||||||
|
DATABAGS = "databags"
|
||||||
|
CHEFSERVER_URL = "chef_url"
|
||||||
|
KEY_DIR = "key_dir"
|
||||||
|
CLIENT = "client_name"
|
||||||
|
|
||||||
|
def __init__(self, adapter_info, cluster_info, hosts_info):
|
||||||
|
super(ChefConfigManager, self).__init__(adapter_info,
|
||||||
|
cluster_info,
|
||||||
|
hosts_info)
|
||||||
|
|
||||||
|
def get_chef_url(self):
|
||||||
|
pk_installer_settings = self.get_pk_installer_settings()
|
||||||
|
if self.CHEFSERVER_URL not in pk_installer_settings:
|
||||||
|
raise KeyError("'%s' must be set in package settings!",
|
||||||
|
self.CHEFSERVER_URL)
|
||||||
|
|
||||||
|
return pk_installer_settings[self.CHEFSERVER_URL]
|
||||||
|
|
||||||
|
def get_chef_credentials(self):
|
||||||
|
installer_settings = self.get_pk_installer_settings()
|
||||||
|
key_dir = installer_settings.setdefault(self.KEY_DIR, None)
|
||||||
|
client = installer_settings.setdefault(self.CLIENT, None)
|
||||||
|
|
||||||
|
return (key_dir, client)
|
||||||
|
|
||||||
|
def get_chef_databag_names(self):
|
||||||
|
pk_installer_settings = self.get_pk_installer_settings()
|
||||||
|
if self.DATABAGS in pk_installer_settings:
|
||||||
|
logging.info("No databags is set!")
|
||||||
|
return None
|
||||||
|
|
||||||
|
return pk_installer_settings[self.DATABAGS]
|
15
compass/deployment/utils/__init__.py
Normal file
15
compass/deployment/utils/__init__.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
__author__ = "Grace Yu (grace.yu@huawei.com)"
|
75
compass/deployment/utils/constants.py
Normal file
75
compass/deployment/utils/constants.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
__author__ = "Grace Yu (grace.yu@huawei.com)"
|
||||||
|
|
||||||
|
|
||||||
|
"""All keywords variables in deployment are defined in this module."""
|
||||||
|
|
||||||
|
|
||||||
|
# General keywords
|
||||||
|
CLUSTER = 'cluster'
|
||||||
|
HOST = 'host'
|
||||||
|
HOSTS = 'hosts'
|
||||||
|
ID = 'id'
|
||||||
|
NAME = 'name'
|
||||||
|
PASSWORD = 'password'
|
||||||
|
USERNAME = 'username'
|
||||||
|
|
||||||
|
|
||||||
|
# Adapter info related keywords
|
||||||
|
DIST_SYS_NAME = 'distributed_system_name'
|
||||||
|
INSTALLER_SETTINGS = 'settings'
|
||||||
|
METADATA = 'metadata'
|
||||||
|
OS_INSTALLER = 'os_installer'
|
||||||
|
PK_INSTALLER = 'pk_installer'
|
||||||
|
SUPPORT_OSES = 'supported_oses'
|
||||||
|
|
||||||
|
|
||||||
|
# Cluster info related keywords
|
||||||
|
ADAPTER_ID = 'adapter_id'
|
||||||
|
OS_VERSION = 'os_name'
|
||||||
|
|
||||||
|
|
||||||
|
# Host info related keywords
|
||||||
|
DNS = 'dns'
|
||||||
|
DOMAIN = 'domain'
|
||||||
|
HOST_ID = 'host_id'
|
||||||
|
HOSTNAME = 'hostname'
|
||||||
|
IP_ADDR = 'ip'
|
||||||
|
IPMI = 'ipmi'
|
||||||
|
IPMI_CREDS = 'ipmi_credentials'
|
||||||
|
MAC_ADDR = 'mac'
|
||||||
|
MGMT_NIC_FLAG = 'is_mgmt'
|
||||||
|
NETMASK = 'netmask'
|
||||||
|
NETWORKS = 'networks'
|
||||||
|
NIC = 'interface'
|
||||||
|
ORIGIN_CLUSTER_ID = 'origin_cluster_id'
|
||||||
|
PROMISCUOUS_FLAG = 'is_promiscuous'
|
||||||
|
REINSTALL_OS_FLAG = 'reinstall_os'
|
||||||
|
SUBNET = 'subnet'
|
||||||
|
|
||||||
|
|
||||||
|
# Cluster/host config related keywords
|
||||||
|
COMPLETED_PK_CONFIG = 'completed_package_config'
|
||||||
|
COMPLETED_OS_CONFIG = 'completed_os_config'
|
||||||
|
DEPLOYED_OS_CONFIG = 'deployed_os_config'
|
||||||
|
DEPLOYED_PK_CONFIG = 'deployed_package_config'
|
||||||
|
NETWORK_MAPPING = 'network_mapping'
|
||||||
|
OS_CONFIG = 'os_config'
|
||||||
|
OS_CONFIG_GENERAL = 'general'
|
||||||
|
PK_CONFIG = 'package_config'
|
||||||
|
ROLES = 'roles'
|
||||||
|
ROLES_MAPPING = 'roles_mapping'
|
||||||
|
TMPL_VARS_DICT = 'vars_dict'
|
@ -19,11 +19,9 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from celery.signals import celeryd_init
|
from celery.signals import celeryd_init
|
||||||
from celery.signals import setup_logging
|
|
||||||
|
|
||||||
from compass.actions import deploy
|
from compass.actions import deploy
|
||||||
from compass.actions import poll_switch
|
from compass.actions import poll_switch
|
||||||
from compass.actions import reinstall
|
|
||||||
from compass.actions import update_progress
|
from compass.actions import update_progress
|
||||||
from compass.db.api import adapter_holder as adapter_api
|
from compass.db.api import adapter_holder as adapter_api
|
||||||
from compass.db.api import database
|
from compass.db.api import database
|
||||||
@ -78,7 +76,10 @@ def deploy_cluster(deployer_email, cluster_id, clusterhost_ids):
|
|||||||
:param cluster_hosts: the cluster and hosts of each cluster to deploy.
|
:param cluster_hosts: the cluster and hosts of each cluster to deploy.
|
||||||
:type cluster_hosts: dict of int to list of int
|
:type cluster_hosts: dict of int to list of int
|
||||||
"""
|
"""
|
||||||
pass
|
try:
|
||||||
|
deploy.deploy(cluster_id, clusterhost_ids, deployer_email)
|
||||||
|
except Exception as error:
|
||||||
|
logging.exception(error)
|
||||||
|
|
||||||
|
|
||||||
@celery.task(name='compass.tasks.reinstall_cluster')
|
@celery.task(name='compass.tasks.reinstall_cluster')
|
||||||
|
13
compass/tests/actions/__init__.py
Normal file
13
compass/tests/actions/__init__.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
13
compass/tests/actions/deploy/__init__.py
Normal file
13
compass/tests/actions/deploy/__init__.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
151
compass/tests/actions/deploy/test_deploy.py
Normal file
151
compass/tests/actions/deploy/test_deploy.py
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
|
||||||
|
"""Test deploy action module."""
|
||||||
|
|
||||||
|
|
||||||
|
from mock import patch
|
||||||
|
import os
|
||||||
|
import unittest2
|
||||||
|
|
||||||
|
|
||||||
|
os.environ['COMPASS_IGNORE_SETTING'] = 'true'
|
||||||
|
|
||||||
|
|
||||||
|
from compass.actions import deploy
|
||||||
|
from compass.utils import setting_wrapper as setting
|
||||||
|
reload(setting)
|
||||||
|
|
||||||
|
|
||||||
|
class TestDeployAction(unittest2.TestCase):
|
||||||
|
"""Test deploy moudle functions in actions."""
|
||||||
|
def setUp(self):
|
||||||
|
super(TestDeployAction, self).setUp()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super(TestDeployAction, self).tearDown()
|
||||||
|
|
||||||
|
@patch('compass.db.api.cluster.get_cluster_metadata')
|
||||||
|
@patch('compass.db.api.adapter_holder.get_adapter')
|
||||||
|
def test_get_adatper_info(self, mock_get_adapter, mock_get_cluster_meta):
|
||||||
|
mock_get_adapter.return_value = {
|
||||||
|
"id": 1,
|
||||||
|
"name": "test_adapter",
|
||||||
|
"roles": [
|
||||||
|
{
|
||||||
|
"name": "test-role-1",
|
||||||
|
"display_name": "test role 1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "test-role-2",
|
||||||
|
"display_name": "test role 2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"os_installer": {
|
||||||
|
"name": "test_os_installer",
|
||||||
|
"settings": {
|
||||||
|
"url": "http://127.0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pk_installer": {
|
||||||
|
"name": "test_pk_installer",
|
||||||
|
"settings": {
|
||||||
|
"url": "http://127.0.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mock_get_cluster_meta.return_value = {
|
||||||
|
"os_config": {},
|
||||||
|
"package_config": {}
|
||||||
|
}
|
||||||
|
expected_output = {
|
||||||
|
"id": 1,
|
||||||
|
"name": "test_adapter",
|
||||||
|
"roles": ["test-role-1", "test-role-2"],
|
||||||
|
"os_installer": {
|
||||||
|
"name": "test_os_installer",
|
||||||
|
"settings": {
|
||||||
|
"url": "http://127.0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pk_installer": {
|
||||||
|
"name": "test_pk_installer",
|
||||||
|
"settings": {
|
||||||
|
"url": "http://127.0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"os_config": {},
|
||||||
|
"package_config": {}
|
||||||
|
}
|
||||||
|
output = deploy.ActionHelper.get_adapter_info(1, 1, None)
|
||||||
|
self.maxDiff = None
|
||||||
|
self.assertDictEqual(expected_output, output)
|
||||||
|
|
||||||
|
@patch('compass.db.api.cluster.get_cluster_host_config')
|
||||||
|
@patch('compass.db.api.host.get_host')
|
||||||
|
@patch('compass.db.api.cluster.get_clusterhost')
|
||||||
|
def test_get_hosts_info(self, mock_get_clusterhost, mock_get_host,
|
||||||
|
mock_get_cluster_host_config):
|
||||||
|
mock_get_clusterhost.return_value = {
|
||||||
|
"id": 1,
|
||||||
|
"host_id": 10,
|
||||||
|
"name": "test"
|
||||||
|
}
|
||||||
|
mock_get_host.return_value = {
|
||||||
|
"id": 10,
|
||||||
|
"mac": "00:89:23:a1:e9:10",
|
||||||
|
"hostname": "server01",
|
||||||
|
"networks": [
|
||||||
|
{
|
||||||
|
"interface": "eth0",
|
||||||
|
"ip": "127.0.0.1",
|
||||||
|
"netmask": "255.255.255.0",
|
||||||
|
"is_mgmt": True,
|
||||||
|
"subnet": "127.0.0.0/24",
|
||||||
|
"is_promiscuous": False
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
mock_get_cluster_host_config.return_value = {
|
||||||
|
"os_config": {},
|
||||||
|
"package_config": {},
|
||||||
|
"deployed_os_config": {},
|
||||||
|
"deployed_package_config": {}
|
||||||
|
}
|
||||||
|
expected_output = {
|
||||||
|
1: {
|
||||||
|
"id": 1,
|
||||||
|
"host_id": 10,
|
||||||
|
"name": "test",
|
||||||
|
"mac": "00:89:23:a1:e9:10",
|
||||||
|
"hostname": "server01",
|
||||||
|
"networks": {
|
||||||
|
"eth0": {
|
||||||
|
"ip": "127.0.0.1",
|
||||||
|
"netmask": "255.255.255.0",
|
||||||
|
"is_mgmt": True,
|
||||||
|
"subnet": "127.0.0.0/24",
|
||||||
|
"is_promiscuous": False
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"os_config": {},
|
||||||
|
"package_config": {},
|
||||||
|
"deployed_os_config": {},
|
||||||
|
"deployed_package_config": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output = deploy.ActionHelper.get_hosts_info(1, [1], None)
|
||||||
|
self.maxDiff = None
|
||||||
|
self.assertDictEqual(expected_output, output)
|
13
compass/tests/deployment/__init__.py
Normal file
13
compass/tests/deployment/__init__.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
13
compass/tests/deployment/installers/__init__.py
Normal file
13
compass/tests/deployment/installers/__init__.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
@ -0,0 +1,13 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
@ -0,0 +1,13 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
@ -0,0 +1,173 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
#
|
||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
__author__ = "Grace Yu (grace.yu@huawei.com)"
|
||||||
|
|
||||||
|
|
||||||
|
"""Test cobbler installer module."""
|
||||||
|
|
||||||
|
from copy import deepcopy
|
||||||
|
from mock import Mock
|
||||||
|
import os
|
||||||
|
import unittest2
|
||||||
|
|
||||||
|
|
||||||
|
os.environ['COMPASS_IGNORE_SETTING'] = 'true'
|
||||||
|
|
||||||
|
|
||||||
|
from compass.deployment.installers.os_installers.cobbler.cobbler \
|
||||||
|
import CobblerInstaller
|
||||||
|
from compass.tests.deployment.test_data import config_data
|
||||||
|
from compass.utils import setting_wrapper as compass_setting
|
||||||
|
reload(compass_setting)
|
||||||
|
|
||||||
|
|
||||||
|
class TestCobblerInstaller(unittest2.TestCase):
|
||||||
|
"""Test CobblerInstaller methods."""
|
||||||
|
def setUp(self):
|
||||||
|
super(TestCobblerInstaller, self).setUp()
|
||||||
|
self.test_cobbler = self._get_cobbler_installer()
|
||||||
|
self.expected_host_vars_dict = {
|
||||||
|
"host": {
|
||||||
|
"mac": "00:0c:29:3e:60:e9",
|
||||||
|
"name": "server01.test",
|
||||||
|
"profile": "Ubuntu-12.04-x86_64",
|
||||||
|
"hostname": "server01",
|
||||||
|
"dns": "server01.test.ods.com",
|
||||||
|
"reinstall_os": True,
|
||||||
|
"networks": {
|
||||||
|
"vnet0": {
|
||||||
|
"ip": "12.234.32.100",
|
||||||
|
"netmask": "255.255.255.0",
|
||||||
|
"is_mgmt": True,
|
||||||
|
"is_promiscuous": False,
|
||||||
|
"subnet": "12.234.32.0/24"
|
||||||
|
},
|
||||||
|
"vnet1": {
|
||||||
|
"ip": "172.16.1.1",
|
||||||
|
"netmask": "255.255.255.0",
|
||||||
|
"is_mgmt": False,
|
||||||
|
"is_promiscuous": False,
|
||||||
|
"subnet": "172.16.1.0/24"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"partition": {
|
||||||
|
"/var": {
|
||||||
|
"vol_size": 30,
|
||||||
|
"vol_percentage": 30
|
||||||
|
},
|
||||||
|
"/home": {
|
||||||
|
"vol_size": 50,
|
||||||
|
"vol_percentage": 40
|
||||||
|
},
|
||||||
|
"/test": {
|
||||||
|
"vol_size": 10,
|
||||||
|
"vol_percentage": 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"server_credentials": {
|
||||||
|
"username": "root",
|
||||||
|
"password": "huawei"
|
||||||
|
},
|
||||||
|
"language": "EN",
|
||||||
|
"timezone": "UTC",
|
||||||
|
"http_proxy": "http://127.0.0.1:3128",
|
||||||
|
"https_proxy": "",
|
||||||
|
"ntp_server": "127.0.0.1",
|
||||||
|
"nameservers": ["127.0.0.1"],
|
||||||
|
"search_path": ["1.ods.com", "ods.com"],
|
||||||
|
"gateway": "10.145.88.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super(TestCobblerInstaller, self).tearDown()
|
||||||
|
del self.test_cobbler
|
||||||
|
|
||||||
|
def _get_cobbler_installer(self):
|
||||||
|
adapter_info = deepcopy(config_data.adapter_test_config)
|
||||||
|
cluster_info = deepcopy(config_data.cluster_test_config)
|
||||||
|
hosts_info = deepcopy(config_data.hosts_test_config)
|
||||||
|
# In config_data, only hosts with ID 1 and 2 needs to install OS.
|
||||||
|
del hosts_info[3]
|
||||||
|
|
||||||
|
CobblerInstaller._get_cobbler_server = Mock()
|
||||||
|
CobblerInstaller._get_cobbler_server.return_value = "mock_server"
|
||||||
|
CobblerInstaller._get_token = Mock()
|
||||||
|
CobblerInstaller._get_token.return_value = "mock_token"
|
||||||
|
|
||||||
|
CobblerInstaller.get_tmpl_path = Mock()
|
||||||
|
test_tmpl_dir = os.path.join(config_data.test_tmpl_dir, 'cobbler')
|
||||||
|
CobblerInstaller.get_tmpl_path.return_value = test_tmpl_dir
|
||||||
|
return CobblerInstaller(adapter_info, cluster_info, hosts_info)
|
||||||
|
|
||||||
|
def test_get_host_tmpl_vars_dict(self):
|
||||||
|
host_id = 1
|
||||||
|
profile = 'Ubuntu-12.04-x86_64'
|
||||||
|
global_vars_dict = self.test_cobbler._get_cluster_tmpl_vars_dict()
|
||||||
|
output = self.test_cobbler._get_host_tmpl_vars_dict(host_id,
|
||||||
|
global_vars_dict,
|
||||||
|
profile=profile)
|
||||||
|
self.maxDiff = None
|
||||||
|
self.assertDictEqual(self.expected_host_vars_dict, output)
|
||||||
|
|
||||||
|
def test_get_system_config(self):
|
||||||
|
expected_system_config = {
|
||||||
|
"name": "server01.test",
|
||||||
|
"hostname": "server01",
|
||||||
|
"profile": "Ubuntu-12.04-x86_64",
|
||||||
|
"gateway": "10.145.88.1",
|
||||||
|
"name_servers": ["127.0.0.1"],
|
||||||
|
"name_servers_search": "1.ods.com ods.com",
|
||||||
|
"proxy": "http://127.0.0.1:3128",
|
||||||
|
"modify_interface": {
|
||||||
|
"ipaddress-vnet0": "12.234.32.100",
|
||||||
|
"netmask-vnet0": "255.255.255.0",
|
||||||
|
"management-vnet0": True,
|
||||||
|
"macaddress-vnet0": "00:0c:29:3e:60:e9",
|
||||||
|
"dns-vnet0": "server01.test.ods.com",
|
||||||
|
"static-vnet0": True,
|
||||||
|
"ipaddress-vnet1": "172.16.1.1",
|
||||||
|
"netmask-vnet1": "255.255.255.0",
|
||||||
|
"management-vnet1": False,
|
||||||
|
"static-vnet1": True
|
||||||
|
},
|
||||||
|
"ksmeta": {
|
||||||
|
"promisc_nics": "",
|
||||||
|
"timezone": "UTC",
|
||||||
|
"partition": "/test 10%;/var 30%;/home 40%",
|
||||||
|
"https_proxy": "",
|
||||||
|
"ntp_server": "127.0.0.1",
|
||||||
|
"chef_url": "https://127.0.0.1",
|
||||||
|
"chef_client_name": "server01.test",
|
||||||
|
"chef_node_name": "server01.test",
|
||||||
|
"tool": "chef"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
package_config = {
|
||||||
|
1: {
|
||||||
|
"chef_url": "https://127.0.0.1",
|
||||||
|
"chef_client_name": "server01.test",
|
||||||
|
"chef_node_name": "server01.test",
|
||||||
|
"tool": "chef"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
host_id = 1
|
||||||
|
self.test_cobbler.set_package_installer_config(package_config)
|
||||||
|
output = self.test_cobbler._get_system_config(
|
||||||
|
host_id, self.expected_host_vars_dict)
|
||||||
|
self.maxDiff = None
|
||||||
|
self.assertEqual(expected_system_config, output)
|
@ -0,0 +1,13 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
@ -0,0 +1,13 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
@ -0,0 +1,131 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
#
|
||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
__author__ = "Grace Yu (grace.yu@huawei.com)"
|
||||||
|
|
||||||
|
|
||||||
|
"""Test Chef installer module.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from copy import deepcopy
|
||||||
|
from mock import Mock
|
||||||
|
import os
|
||||||
|
import unittest2
|
||||||
|
|
||||||
|
|
||||||
|
os.environ['COMPASS_IGNORE_SETTING'] = 'true'
|
||||||
|
|
||||||
|
from compass.tests.deployment.test_data import config_data
|
||||||
|
from compass.utils import setting_wrapper as compass_setting
|
||||||
|
reload(compass_setting)
|
||||||
|
|
||||||
|
|
||||||
|
from compass.deployment.installers.pk_installers.chef_installer.chef_installer\
|
||||||
|
import ChefInstaller
|
||||||
|
|
||||||
|
|
||||||
|
class TestChefInstaller(unittest2.TestCase):
|
||||||
|
"""Test installer functionality."""
|
||||||
|
def setUp(self):
|
||||||
|
super(TestChefInstaller, self).setUp()
|
||||||
|
self.test_chef = self._get_chef_installer()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super(TestChefInstaller, self).tearDown()
|
||||||
|
|
||||||
|
def _get_chef_installer(self):
|
||||||
|
adapter_info = deepcopy(config_data.adapter_test_config)
|
||||||
|
cluster_info = deepcopy(config_data.cluster_test_config)
|
||||||
|
hosts_info = deepcopy(config_data.hosts_test_config)
|
||||||
|
|
||||||
|
ChefInstaller.get_tmpl_path = Mock()
|
||||||
|
test_tmpl_dir = os.path.join(os.path.join(config_data.test_tmpl_dir,
|
||||||
|
'chef_installer'),
|
||||||
|
'openstack_icehouse')
|
||||||
|
ChefInstaller.get_tmpl_path.return_value = test_tmpl_dir
|
||||||
|
|
||||||
|
ChefInstaller._get_chef_api = Mock()
|
||||||
|
ChefInstaller._get_chef_api.return_value = 'mock_server'
|
||||||
|
chef_installer = ChefInstaller(adapter_info, cluster_info, hosts_info)
|
||||||
|
return chef_installer
|
||||||
|
|
||||||
|
def test_get_tmpl_vars(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_get_node_attributes(self):
|
||||||
|
cluster_dict = self.test_chef._get_cluster_tmpl_vars()
|
||||||
|
vars_dict = self.test_chef._get_host_tmpl_vars(2, cluster_dict)
|
||||||
|
expected_node_attr = {
|
||||||
|
"override_attributes": {
|
||||||
|
"endpoints": {
|
||||||
|
"compute-vnc-bind": {
|
||||||
|
"host": "12.234.32.101"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output = self.test_chef._get_node_attributes(['os-compute'], vars_dict)
|
||||||
|
self.maxDiff = None
|
||||||
|
self.assertDictEqual(expected_node_attr, output)
|
||||||
|
|
||||||
|
def test_get_env_attributes(self):
|
||||||
|
expected_env = {
|
||||||
|
"name": "testing",
|
||||||
|
"description": "Environment",
|
||||||
|
"cookbook_versions": {
|
||||||
|
},
|
||||||
|
"json_class": "Chef::Environment",
|
||||||
|
"chef_type": "environment",
|
||||||
|
"default_attributes": {
|
||||||
|
},
|
||||||
|
"override_attributes": {
|
||||||
|
"compute": {
|
||||||
|
"syslog": {
|
||||||
|
"use": False
|
||||||
|
},
|
||||||
|
"libvirt": {
|
||||||
|
"bind_interface": "eth0"
|
||||||
|
},
|
||||||
|
"novnc_proxy": {
|
||||||
|
"bind_interface": "vnet0"
|
||||||
|
},
|
||||||
|
"xvpvnc_proxy": {
|
||||||
|
"bind_interface": "eth0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"db": {
|
||||||
|
"bind_interface": "vnet0",
|
||||||
|
"compute": {
|
||||||
|
"host": "12.234.32.100"
|
||||||
|
},
|
||||||
|
"identity": {
|
||||||
|
"host": "12.234.32.100"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mq": {
|
||||||
|
"user": "guest",
|
||||||
|
"password": "test",
|
||||||
|
"vhost": "/nova",
|
||||||
|
"network": {
|
||||||
|
"service_type": "rabbitmq"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vars_dict = self.test_chef._get_cluster_tmpl_vars()
|
||||||
|
output = self.test_chef._get_env_attributes(vars_dict)
|
||||||
|
self.maxDiff = None
|
||||||
|
self.assertDictEqual(expected_env, output)
|
13
compass/tests/deployment/installers/test_config_manager.py
Normal file
13
compass/tests/deployment/installers/test_config_manager.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
13
compass/tests/deployment/installers/test_installer.py
Normal file
13
compass/tests/deployment/installers/test_installer.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
13
compass/tests/deployment/test_data/__init__.py
Normal file
13
compass/tests/deployment/test_data/__init__.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
366
compass/tests/deployment/test_data/config_data.py
Normal file
366
compass/tests/deployment/test_data/config_data.py
Normal file
@ -0,0 +1,366 @@
|
|||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
__author__ = "Grace Yu (grace.yu@huawei.com)"
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
curr_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
test_tmpl_dir = os.path.join(curr_dir, 'templates')
|
||||||
|
|
||||||
|
|
||||||
|
adapter_test_config = {
|
||||||
|
"name": "openstack_icehouse",
|
||||||
|
"distributed_system_name": "openstack_icehouse",
|
||||||
|
"roles": ["os-controller", "os-compute-worker", "os-network"],
|
||||||
|
"os_installer": {
|
||||||
|
"name": "cobbler",
|
||||||
|
"settings": {
|
||||||
|
"cobbler_url": "http://127.0.0.1/cobbler_api",
|
||||||
|
"credentials": {
|
||||||
|
"username": "cobbler",
|
||||||
|
"password": "cobbler"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pk_installer": {
|
||||||
|
"name": "chef_installer",
|
||||||
|
"settings": {
|
||||||
|
"chef_url": "https://127.0.0.1",
|
||||||
|
"key_dir": "xxx",
|
||||||
|
"client_name": "xxx"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"os_config": {
|
||||||
|
"_self": {},
|
||||||
|
"general": {
|
||||||
|
"_self": {"mapping_to": ""},
|
||||||
|
"language": {
|
||||||
|
"_self": {
|
||||||
|
"mapping_to": "language",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"timezone": {
|
||||||
|
"_self": {
|
||||||
|
"mapping_to": "timezone"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default_gateway": {
|
||||||
|
"_self": {
|
||||||
|
"mapping_to": "gateway"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"domain": {
|
||||||
|
"_self": {"mapping_to": ""}
|
||||||
|
},
|
||||||
|
"http_proxy": {
|
||||||
|
"_self": {
|
||||||
|
"mapping_to": "http_proxy"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ntp_server": {
|
||||||
|
"_self": {"mapping_to": "ntp_server"}
|
||||||
|
},
|
||||||
|
"dns_servers": {
|
||||||
|
"_self": {"mapping_to": "nameservers"}
|
||||||
|
},
|
||||||
|
"search_path": {
|
||||||
|
"_self": {"mapping_to": "search_path"}
|
||||||
|
},
|
||||||
|
"https_proxy": {
|
||||||
|
"_self": {"mapping_to": "https_proxy"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"partition": {
|
||||||
|
"_self": {
|
||||||
|
"mapping_to": "partition"
|
||||||
|
},
|
||||||
|
"$path": {
|
||||||
|
"_self": {"mapping_to": ""},
|
||||||
|
"max_size": {
|
||||||
|
"_self": {"mapping_to": "vol_size"}
|
||||||
|
},
|
||||||
|
"size_percentage": {
|
||||||
|
"_self": {"mapping_to": "vol_percentage"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"server_credentials": {
|
||||||
|
"_self": {
|
||||||
|
"mapping_to": "server_credentials"
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"_self": {"mapping_to": "username"}
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
"_self": {"mapping_to": "password"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"package_config": {
|
||||||
|
"_self": {},
|
||||||
|
"security": {
|
||||||
|
"_self": {},
|
||||||
|
"service_credentials": {
|
||||||
|
"_self": {
|
||||||
|
"mapping_to": "service_credentials"
|
||||||
|
},
|
||||||
|
"rabbit_mq": {
|
||||||
|
"_self": {
|
||||||
|
"mapping_to": "mq"
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"_self": {
|
||||||
|
"mapping_to": "username"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
"_self": {
|
||||||
|
"mapping_to": "password"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"network_mapping": {
|
||||||
|
"_self": {},
|
||||||
|
"management": {
|
||||||
|
"_self": {},
|
||||||
|
"interface": {
|
||||||
|
"_self": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"public": {
|
||||||
|
"_self": {},
|
||||||
|
"interface": {
|
||||||
|
"_self": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tenant": {
|
||||||
|
"_self": {},
|
||||||
|
"interface": {
|
||||||
|
"_self": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"_self": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cluster_test_config = {
|
||||||
|
"id": 1,
|
||||||
|
"os_name": "Ubuntu-12.04-x86_64",
|
||||||
|
"name": "test",
|
||||||
|
"os_config": {
|
||||||
|
"general": {
|
||||||
|
"language": "EN",
|
||||||
|
"timezone": "UTC",
|
||||||
|
"default_gateway": "12.234.32.1",
|
||||||
|
"domain": "ods.com",
|
||||||
|
"http_proxy": "http://127.0.0.1:3128",
|
||||||
|
"https_proxy": "",
|
||||||
|
"ntp_server": "127.0.0.1",
|
||||||
|
"dns_servers": ["127.0.0.1"],
|
||||||
|
"search_path": ["1.ods.com", "ods.com"]
|
||||||
|
},
|
||||||
|
"partition": {
|
||||||
|
"/var": {
|
||||||
|
"max_size": 20,
|
||||||
|
"size_percentage": 20
|
||||||
|
},
|
||||||
|
"/home": {
|
||||||
|
"max_size": 50,
|
||||||
|
"size_percentage": 40
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"server_credentials": {
|
||||||
|
"username": "root",
|
||||||
|
"password": "huawei"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"package_config": {
|
||||||
|
"security": {
|
||||||
|
"service_credentials": {
|
||||||
|
"rabbit_mq": {
|
||||||
|
"username": "guest",
|
||||||
|
"password": "test"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"network_mapping": {
|
||||||
|
"management": {
|
||||||
|
"interface": "eth0"
|
||||||
|
},
|
||||||
|
"public": {
|
||||||
|
"interface": "eth2"
|
||||||
|
},
|
||||||
|
"tenant": {
|
||||||
|
"interface": "eth1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hosts_test_config = {
|
||||||
|
1: {
|
||||||
|
"host_id": 1,
|
||||||
|
"reinstall_os": True,
|
||||||
|
"mac": "00:0c:29:3e:60:e9",
|
||||||
|
"name": "server01.test",
|
||||||
|
"hostname": "server01",
|
||||||
|
"networks": {
|
||||||
|
"vnet0": {
|
||||||
|
"ip": "12.234.32.100",
|
||||||
|
"netmask": "255.255.255.0",
|
||||||
|
"is_mgmt": True,
|
||||||
|
"is_promiscuous": False,
|
||||||
|
"subnet": "12.234.32.0/24"
|
||||||
|
},
|
||||||
|
"vnet1": {
|
||||||
|
"ip": "172.16.1.1",
|
||||||
|
"netmask": "255.255.255.0",
|
||||||
|
"is_mgmt": False,
|
||||||
|
"is_promiscuous": False,
|
||||||
|
"subnet": "172.16.1.0/24"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"os_config": {
|
||||||
|
"general": {
|
||||||
|
"default_gateway": "10.145.88.1",
|
||||||
|
},
|
||||||
|
"partition": {
|
||||||
|
"/var": {
|
||||||
|
"max_size": 30,
|
||||||
|
"size_percentage": 30
|
||||||
|
},
|
||||||
|
"/test": {
|
||||||
|
"max_size": 10,
|
||||||
|
"size_percentage": 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"package_config": {
|
||||||
|
"network_mapping": {
|
||||||
|
"management": {
|
||||||
|
"interface": "vnet0"
|
||||||
|
},
|
||||||
|
"tenant": {
|
||||||
|
"interface": "vnet1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"roles": ["os-controller"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
"host_id": 2,
|
||||||
|
"reinstall_os": True,
|
||||||
|
"mac": "00:0c:29:3e:60:a1",
|
||||||
|
"name": "server02.test",
|
||||||
|
"hostname": "server02",
|
||||||
|
"networks": {
|
||||||
|
"eth0": {
|
||||||
|
"ip": "12.234.32.101",
|
||||||
|
"netmask": "255.255.255.0",
|
||||||
|
"is_mgmt": True,
|
||||||
|
"is_promiscuous": False,
|
||||||
|
"subnet": "12.234.32.0/24"
|
||||||
|
},
|
||||||
|
"eth1": {
|
||||||
|
"ip": "172.16.1.2",
|
||||||
|
"netmask": "255.255.255.0",
|
||||||
|
"is_mgmt": False,
|
||||||
|
"is_promiscuous": False,
|
||||||
|
"subnet": "172.16.1.0/24"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"os_config": {
|
||||||
|
"general": {
|
||||||
|
"language": "EN",
|
||||||
|
"timezone": "UTC",
|
||||||
|
"domain": "ods.com"
|
||||||
|
},
|
||||||
|
"partition": {
|
||||||
|
"/test": {
|
||||||
|
"max_size": 10,
|
||||||
|
"size_percentage": 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"package_config": {
|
||||||
|
"roles": ["os-compute"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
3: {
|
||||||
|
"host_id": 10,
|
||||||
|
"reinstall_os": False,
|
||||||
|
"mac_address": "00:0c:29:3e:60:a2",
|
||||||
|
"name": "server03.test",
|
||||||
|
"hostname": "server03",
|
||||||
|
"networks": {
|
||||||
|
"eth0": {
|
||||||
|
"ip": "12.234.32.103",
|
||||||
|
"netmask": "255.255.255.0",
|
||||||
|
"is_mgmt": True,
|
||||||
|
"is_promiscuous": False,
|
||||||
|
"subnet": "12.234.32.0/24"
|
||||||
|
},
|
||||||
|
"eth1": {
|
||||||
|
"ip": "172.16.1.3",
|
||||||
|
"netmask": "255.255.255.0",
|
||||||
|
"is_mgmt": False,
|
||||||
|
"is_promiscuous": False,
|
||||||
|
"subnet": "172.16.1.0/24"
|
||||||
|
},
|
||||||
|
"eth2": {
|
||||||
|
"ip": "10.0.0.1",
|
||||||
|
"netmask": "255.255.255.0",
|
||||||
|
"is_mgmt": False,
|
||||||
|
"is_promiscuous": True,
|
||||||
|
"subnet": "10.0.0.0/24"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"os_config": {
|
||||||
|
"general": {
|
||||||
|
"language": "EN",
|
||||||
|
"timezone": "UTC",
|
||||||
|
"default_gateway": "12.234.32.1",
|
||||||
|
"domain": "ods.com",
|
||||||
|
"http_proxy": "http://10.145.88.211:3128",
|
||||||
|
"https_proxy": "",
|
||||||
|
"ntp_server": "10.145.88.211",
|
||||||
|
"dns_servers": "10.145.88.211",
|
||||||
|
"search_path": "1.ods.com ods.com"
|
||||||
|
},
|
||||||
|
"partition": {
|
||||||
|
"/var": {
|
||||||
|
"max_size": 20,
|
||||||
|
"size_percentage": 20
|
||||||
|
},
|
||||||
|
"/home": {
|
||||||
|
"max_size": 50,
|
||||||
|
"size_percentage": 40
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"package_config": {
|
||||||
|
"roles": ["os-network"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
#set config = $cluster.deployed_package_config
|
||||||
|
#set mappings = $config.roles_mapping
|
||||||
|
#set credentials = $config.service_credentials
|
||||||
|
{
|
||||||
|
"name": "testing",
|
||||||
|
"description": "Environment",
|
||||||
|
"cookbook_versions": {
|
||||||
|
},
|
||||||
|
"json_class": "Chef::Environment",
|
||||||
|
"chef_type": "environment",
|
||||||
|
"default_attributes": {
|
||||||
|
},
|
||||||
|
"override_attributes": {
|
||||||
|
"compute": {
|
||||||
|
"syslog": {
|
||||||
|
"use": false
|
||||||
|
},
|
||||||
|
"libvirt": {
|
||||||
|
"bind_interface": "$mappings.os_compute.management.interface"
|
||||||
|
},
|
||||||
|
"novnc_proxy": {
|
||||||
|
"bind_interface": "$mappings.os_controller.management.interface"
|
||||||
|
},
|
||||||
|
"xvpvnc_proxy": {
|
||||||
|
"bind_interface": "eth0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"db": {
|
||||||
|
"bind_interface": "$mappings.os_controller.management.interface",
|
||||||
|
"compute": {
|
||||||
|
"host": "$mappings.os_controller.management.ip"
|
||||||
|
},
|
||||||
|
"identity": {
|
||||||
|
"host": "$mappings.os_controller.management.ip"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mq": {
|
||||||
|
"user": "$credentials.mq.username",
|
||||||
|
"password": "$credentials.mq.password",
|
||||||
|
"vhost": "/nova",
|
||||||
|
"network": {
|
||||||
|
"service_type": "rabbitmq"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"override_attributes": {
|
||||||
|
"endpoints": {
|
||||||
|
"compute-vnc-bind": {
|
||||||
|
"host":"$host.deployed_package_config.roles_mapping.os_compute.management.ip"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"name": "$host.name",
|
||||||
|
"hostname": "$host.hostname",
|
||||||
|
"profile": "$host.profile",
|
||||||
|
"gateway": "$host.gateway",
|
||||||
|
#import simplejson as json
|
||||||
|
#set nameservers = json.dumps($host.nameservers, encoding='utf-8')
|
||||||
|
"name_servers": $nameservers,
|
||||||
|
#set search_path = ' '.join($host.search_path)
|
||||||
|
"name_servers_search": "$search_path",
|
||||||
|
"proxy": "$host.http_proxy",
|
||||||
|
"modify_interface":
|
||||||
|
#set networks = $host.networks
|
||||||
|
#set rekeyed = {}
|
||||||
|
#set promicnic = ""
|
||||||
|
#for $nic, $val in $networks.iteritems():
|
||||||
|
#set ip_key = '-'.join(('ipaddress', $nic))
|
||||||
|
#set netmask_key = '-'.join(('netmask', $nic))
|
||||||
|
#set mgmt_key = '-'.join(('management', $nic))
|
||||||
|
#set static_key = '-'.join(('static', $nic))
|
||||||
|
#set $rekeyed[$ip_key] = $val.ip
|
||||||
|
#set $rekeyed[$netmask_key] = $val.netmask
|
||||||
|
#set $rekeyed[$mgmt_key] = $val.is_mgmt
|
||||||
|
#set $rekeyed[$static_key] = True
|
||||||
|
|
||||||
|
#if $val.is_promiscuous:
|
||||||
|
#set promicnic = $nic
|
||||||
|
#end if
|
||||||
|
#if $val.is_mgmt:
|
||||||
|
#set mac_key = '-'.join(('macaddress', $nic))
|
||||||
|
#set dns_key = '-'.join(('dns', $nic))
|
||||||
|
#set $rekeyed[$mac_key] = $host.mac
|
||||||
|
#set $rekeyed[$dns_key] = $host.dns
|
||||||
|
#end if
|
||||||
|
#end for
|
||||||
|
#set nic_info = json.dumps($rekeyed, encoding='utf-8')
|
||||||
|
$nic_info
|
||||||
|
,
|
||||||
|
"ksmeta":{
|
||||||
|
#set partition_config = ''
|
||||||
|
#for k, v in $host.partition.iteritems():
|
||||||
|
#set path = ''
|
||||||
|
#if v['vol_percentage']:
|
||||||
|
#set $path = k + ' ' + str(v['vol_percentage']) + '%'
|
||||||
|
#else:
|
||||||
|
#set $path = k + ' ' + str(v['vol_size'])
|
||||||
|
#end if
|
||||||
|
#set partition_config = ';'.join((partition_config, $path))
|
||||||
|
#end for
|
||||||
|
#set partition_config = partition_config[1:]
|
||||||
|
"promisc_nics": "$promicnic",
|
||||||
|
"partition": "$partition_config",
|
||||||
|
"https_proxy": "$host.https_proxy",
|
||||||
|
"ntp_server": "$host.ntp_server",
|
||||||
|
"timezone": "$host.timezone"
|
||||||
|
}
|
||||||
|
}
|
62
compass/tests/deployment/test_deploy_manager.py
Normal file
62
compass/tests/deployment/test_deploy_manager.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
#
|
||||||
|
# Copyright 2014 Huawei Technologies Co. Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
__author__ = "Grace Yu (grace.yu@huawei.com)"
|
||||||
|
|
||||||
|
|
||||||
|
"""Test deploy_manager module."""
|
||||||
|
|
||||||
|
from mock import Mock
|
||||||
|
import os
|
||||||
|
import unittest2
|
||||||
|
|
||||||
|
|
||||||
|
os.environ['COMPASS_IGNORE_SETTING'] = 'true'
|
||||||
|
|
||||||
|
|
||||||
|
from compass.utils import setting_wrapper as setting
|
||||||
|
from copy import deepcopy
|
||||||
|
reload(setting)
|
||||||
|
|
||||||
|
|
||||||
|
from compass.deployment.deploy_manager import DeployManager
|
||||||
|
from compass.tests.deployment.test_data import config_data
|
||||||
|
|
||||||
|
|
||||||
|
class TestDeployManager(unittest2.TestCase):
|
||||||
|
"""Test DeployManager methods."""
|
||||||
|
def setUp(self):
|
||||||
|
super(TestDeployManager, self).setUp()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super(TestDeployManager, self).tearDown()
|
||||||
|
|
||||||
|
def test_init_DeployManager(self):
|
||||||
|
adapter_info = deepcopy(config_data.adapter_test_config)
|
||||||
|
cluster_info = deepcopy(config_data.cluster_test_config)
|
||||||
|
hosts_info = deepcopy(config_data.hosts_test_config)
|
||||||
|
|
||||||
|
DeployManager._get_installer = Mock()
|
||||||
|
DeployManager._get_installer.return_value = "mock_installer"
|
||||||
|
|
||||||
|
test_manager = DeployManager(adapter_info, cluster_info, hosts_info)
|
||||||
|
self.assertIsNotNone(test_manager)
|
||||||
|
|
||||||
|
# Test hepler function _get_hosts_for_os_installation return correct
|
||||||
|
# number of hosts config for os deployment. In config_data, two out of
|
||||||
|
# three hosts need to install OS.
|
||||||
|
hosts_list = test_manager._get_hosts_for_os_installation(hosts_info)
|
||||||
|
self.assertEqual(2, len(hosts_list))
|
@ -70,6 +70,7 @@ OS_FIELD_DIR = '/etc/compass/os_field'
|
|||||||
PACKAGE_FIELD_DIR = '/etc/compass/package_field'
|
PACKAGE_FIELD_DIR = '/etc/compass/package_field'
|
||||||
ADAPTER_ROLE_DIR = '/etc/compass/role'
|
ADAPTER_ROLE_DIR = '/etc/compass/role'
|
||||||
VALIDATOR_DIR = '/etc/compass/validator'
|
VALIDATOR_DIR = '/etc/compass/validator'
|
||||||
|
TMPL_DIR = '/etc/compass/templates'
|
||||||
if (
|
if (
|
||||||
'COMPASS_IGNORE_SETTING' in os.environ and
|
'COMPASS_IGNORE_SETTING' in os.environ and
|
||||||
os.environ['COMPASS_IGNORE_SETTING']
|
os.environ['COMPASS_IGNORE_SETTING']
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
NAME = 'openstack(chef)'
|
NAME = 'openstack_icehouse'
|
||||||
DISPLAY_NAME = 'openstack(chef)'
|
DISPLAY_NAME = 'OpenStack Icehouse'
|
||||||
PARENT = 'openstack'
|
PARENT = 'openstack'
|
||||||
PACKAGE_INSTALLER = 'chef(icehouse)'
|
PACKAGE_INSTALLER = 'chef_installer'
|
||||||
OS_INSTALLER = 'cobbler'
|
OS_INSTALLER = 'cobbler'
|
||||||
SUPPORTED_OS_PATTERNS = ['(?i)centos.*', '(?i)ubuntu.*']
|
SUPPORTED_OS_PATTERNS = ['(?i)centos.*', '(?i)ubuntu.*']
|
||||||
DEPLOYABLE = True
|
DEPLOYABLE = True
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
NAME = 'cobbler'
|
NAME = 'cobbler'
|
||||||
INSTANCE_NAME = 'cobbler'
|
INSTANCE_NAME = 'cobbler'
|
||||||
SETTINGS = {
|
SETTINGS = {
|
||||||
'url': 'http://127.0.0.1/cobbler_api',
|
'cobbler_url': 'http://127.0.0.1/cobbler_api',
|
||||||
'token': ('cobbler', 'cobbler')
|
'credentials': {
|
||||||
|
'username': 'cobbler',
|
||||||
|
'password': 'cobbler'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,13 @@ METADATA = {
|
|||||||
'field': 'general',
|
'field': 'general',
|
||||||
'default_value': 'EN',
|
'default_value': 'EN',
|
||||||
'options': ['EN', 'CN'],
|
'options': ['EN', 'CN'],
|
||||||
|
'mapping_to': 'language'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'timezone': {
|
'timezone': {
|
||||||
'_self': {
|
'_self': {
|
||||||
'field': 'general',
|
'field': 'general',
|
||||||
'default_value': 'GMT -8:00',
|
'default_value': 'UTC',
|
||||||
'options': [
|
'options': [
|
||||||
'GMT -12:00', 'GMT -11:00', 'GMT -10:00', 'GMT -9:00',
|
'GMT -12:00', 'GMT -11:00', 'GMT -10:00', 'GMT -9:00',
|
||||||
'GMT -8:00', 'GMT -7:00', 'GMT -6:00', 'GMT -5:00',
|
'GMT -8:00', 'GMT -7:00', 'GMT -6:00', 'GMT -5:00',
|
||||||
@ -22,8 +23,9 @@ METADATA = {
|
|||||||
'GMT 0:00', 'GMT +1:00', 'GMT +2:00', 'GMT +3:00',
|
'GMT 0:00', 'GMT +1:00', 'GMT +2:00', 'GMT +3:00',
|
||||||
'GMT +4:00', 'GMT +5:00', 'GMT +6:00', 'GMT +7:00',
|
'GMT +4:00', 'GMT +5:00', 'GMT +6:00', 'GMT +7:00',
|
||||||
'GMT +8:00', 'GMT +9:00', 'GMT +10:00', 'GMT +11:00',
|
'GMT +8:00', 'GMT +9:00', 'GMT +10:00', 'GMT +11:00',
|
||||||
'GMT +12:00'
|
'GMT +12:00', UTC
|
||||||
],
|
],
|
||||||
|
'mapping_to': 'timezone'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'http_proxy': {
|
'http_proxy': {
|
||||||
@ -33,6 +35,7 @@ METADATA = {
|
|||||||
'options': [
|
'options': [
|
||||||
'http://10.145.88.211:3128'
|
'http://10.145.88.211:3128'
|
||||||
],
|
],
|
||||||
|
'mapping_to': 'http_proxy'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'https_proxy': {
|
'https_proxy': {
|
||||||
@ -42,6 +45,7 @@ METADATA = {
|
|||||||
'options': [
|
'options': [
|
||||||
'http://10.145.88.211:3128'
|
'http://10.145.88.211:3128'
|
||||||
],
|
],
|
||||||
|
'mapping_to': 'https_proxy'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'no_proxy': {
|
'no_proxy': {
|
||||||
@ -56,7 +60,8 @@ METADATA = {
|
|||||||
'127.0.0.1',
|
'127.0.0.1',
|
||||||
'compass',
|
'compass',
|
||||||
'10.145.88.211'
|
'10.145.88.211'
|
||||||
]
|
],
|
||||||
|
'mapping_to': 'no_proxy'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'ntp_server': {
|
'ntp_server': {
|
||||||
@ -66,7 +71,8 @@ METADATA = {
|
|||||||
'default_value': '10.145.88.211',
|
'default_value': '10.145.88.211',
|
||||||
'options': [
|
'options': [
|
||||||
'10.145.88.211'
|
'10.145.88.211'
|
||||||
]
|
],
|
||||||
|
'mapping_to': 'ntp_server'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'dns_servers': {
|
'dns_servers': {
|
||||||
@ -78,7 +84,8 @@ METADATA = {
|
|||||||
],
|
],
|
||||||
'options': [
|
'options': [
|
||||||
'10.145.88.211'
|
'10.145.88.211'
|
||||||
]
|
],
|
||||||
|
'mapping_to': 'nameservers'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'domain': {
|
'domain': {
|
||||||
@ -95,7 +102,8 @@ METADATA = {
|
|||||||
'default_value': [
|
'default_value': [
|
||||||
'ods.com'
|
'ods.com'
|
||||||
],
|
],
|
||||||
'options': ['ods.com']
|
'options': ['ods.com'],
|
||||||
|
'mapping_to': 'search_path'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'default_gateway': {
|
'default_gateway': {
|
||||||
@ -103,23 +111,27 @@ METADATA = {
|
|||||||
'is_required': True,
|
'is_required': True,
|
||||||
'field': 'ip',
|
'field': 'ip',
|
||||||
'default_value': '10.145.88.1',
|
'default_value': '10.145.88.1',
|
||||||
|
'mapping_to': 'gateway'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'server_credentials': {
|
'server_credentials': {
|
||||||
'_self': {
|
'_self': {
|
||||||
'required_in_whole_config': True,
|
'required_in_whole_config': True,
|
||||||
|
'mapping_to': 'server_credentials'
|
||||||
},
|
},
|
||||||
'username': {
|
'username': {
|
||||||
'_self': {
|
'_self': {
|
||||||
'is_required': True,
|
'is_required': True,
|
||||||
'field': 'username',
|
'field': 'username',
|
||||||
|
'mapping_to': 'username'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'password': {
|
'password': {
|
||||||
'_self': {
|
'_self': {
|
||||||
'is_required': True,
|
'is_required': True,
|
||||||
'field': 'password'
|
'field': 'password',
|
||||||
|
'mapping_to': 'password'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -127,6 +139,7 @@ METADATA = {
|
|||||||
'_self': {
|
'_self': {
|
||||||
'required_in_whole_config': True,
|
'required_in_whole_config': True,
|
||||||
'options': ['/boot', 'swap', '/var', '/home'],
|
'options': ['/boot', 'swap', '/var', '/home'],
|
||||||
|
'mapping_to': 'partition'
|
||||||
},
|
},
|
||||||
'$partition': {
|
'$partition': {
|
||||||
'_self': {
|
'_self': {
|
||||||
@ -134,17 +147,20 @@ METADATA = {
|
|||||||
},
|
},
|
||||||
'max_size': {
|
'max_size': {
|
||||||
'_self': {
|
'_self': {
|
||||||
'field': 'size'
|
'field': 'size',
|
||||||
|
'mapping_to': 'max_vol_size'
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'percentage': {
|
'percentage': {
|
||||||
'_self': {
|
'_self': {
|
||||||
'field': 'percentage',
|
'field': 'percentage',
|
||||||
|
'mapping_to': 'vol_percentage'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'size': {
|
'size': {
|
||||||
'_self': {
|
'_self': {
|
||||||
'field': 'size'
|
'field': 'size',
|
||||||
|
'mapping_to': 'vol_size'
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
NAME = 'chef'
|
NAME = 'chef_installer'
|
||||||
INSTANCE_NAME = 'chef(icehouse)'
|
INSTANCE_NAME = 'chef_installer'
|
||||||
SETTINGS = {
|
SETTINGS = {
|
||||||
'url': 'https://127.0.0.1'
|
'chef_url': 'https://10.145.88.150',
|
||||||
|
'key_dir': '/root/grace.pem',
|
||||||
|
'client_name': 'grace'
|
||||||
}
|
}
|
||||||
|
@ -4,18 +4,41 @@ METADATA = {
|
|||||||
'_self': {
|
'_self': {
|
||||||
'required_in_whole_config': True,
|
'required_in_whole_config': True,
|
||||||
},
|
},
|
||||||
'$credential_type': {
|
'service_credentials': {
|
||||||
'$credential': {
|
'_self': {
|
||||||
|
'mapping_to': 'service_credentials'
|
||||||
|
},
|
||||||
|
'$service': {
|
||||||
'username': {
|
'username': {
|
||||||
'_self': {
|
'_self': {
|
||||||
'is_required': True,
|
'is_required': True,
|
||||||
'field': 'username',
|
'field': 'username',
|
||||||
|
'mapping_to': 'username'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'password': {
|
'password': {
|
||||||
'_self': {
|
'_self': {
|
||||||
'is_required': True,
|
'is_required': True,
|
||||||
'field': 'password'
|
'field': 'password',
|
||||||
|
'mapping_to': 'password'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'console_credentials': {
|
||||||
|
'$console': {
|
||||||
|
'username': {
|
||||||
|
'_self': {
|
||||||
|
'is_required': True,
|
||||||
|
'field': 'username',
|
||||||
|
'mapping_to': 'username'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'password': {
|
||||||
|
'_self': {
|
||||||
|
'is_required': True,
|
||||||
|
'field': 'password',
|
||||||
|
'mapping_to': 'password'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,3 +26,4 @@ PROGRESS_UPDATE_INTERVAL=30
|
|||||||
POLLSWITCH_INTERVAL=60
|
POLLSWITCH_INTERVAL=60
|
||||||
SWITCHES = [
|
SWITCHES = [
|
||||||
]
|
]
|
||||||
|
TMPL_DIR = '/etc/compass/templates'
|
||||||
|
@ -4,6 +4,7 @@ flask-restful
|
|||||||
flask-sqlalchemy
|
flask-sqlalchemy
|
||||||
flask-login
|
flask-login
|
||||||
celery
|
celery
|
||||||
|
cheetah
|
||||||
netaddr
|
netaddr
|
||||||
paramiko==1.7.5
|
paramiko==1.7.5
|
||||||
simplejson
|
simplejson
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"nova": {
|
||||||
|
"nova": "mypass"
|
||||||
|
},
|
||||||
|
"horizon": {
|
||||||
|
"horizon": "horizon"
|
||||||
|
},
|
||||||
|
"keystone": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
317
templates/chef_installer/openstack_icehouse/env.tmpl
Normal file
317
templates/chef_installer/openstack_icehouse/env.tmpl
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
#set config = $cluster.deployed_package_config
|
||||||
|
#set mappings = $config.roles_mapping
|
||||||
|
#set credentials = $config.service_credentials
|
||||||
|
#set allinone_compute_mgmt_nic = $mappings.allinone_compute.management.interface
|
||||||
|
#set allinone_compute_mgmt_ip = $mappings.allinone_compute.management.ip
|
||||||
|
#set allinone_compute_mgmt_nic = $mappings.allinone_compute.management.interface
|
||||||
|
{
|
||||||
|
"name": "testing",
|
||||||
|
"description": "Environment used in testing the upstream cookbooks and reference Chef repository",
|
||||||
|
"cookbook_versions": {
|
||||||
|
},
|
||||||
|
"json_class": "Chef::Environment",
|
||||||
|
"chef_type": "environment",
|
||||||
|
"default_attributes": {
|
||||||
|
},
|
||||||
|
"override_attributes": {
|
||||||
|
"mysql": {
|
||||||
|
"server_root_password": "test",
|
||||||
|
"server_debian_password": "root",
|
||||||
|
"server_repl_password": "root",
|
||||||
|
"allow_remote_root": true,
|
||||||
|
"root_network_acl": "%"
|
||||||
|
},
|
||||||
|
"openstack": {
|
||||||
|
"auth": {
|
||||||
|
"validate_certs": false
|
||||||
|
},
|
||||||
|
"block-storage": {
|
||||||
|
"syslog": {
|
||||||
|
"use": false
|
||||||
|
},
|
||||||
|
"api": {
|
||||||
|
"ratelimit": "False"
|
||||||
|
},
|
||||||
|
"debug": true,
|
||||||
|
"image_api_chef_role": "os-image",
|
||||||
|
"identity_service_chef_role": "os-identity",
|
||||||
|
"rabbit_server_chef_role": "os-ops-messaging"
|
||||||
|
},
|
||||||
|
"dashboard": {
|
||||||
|
"use_ssl": "false"
|
||||||
|
},
|
||||||
|
"compute": {
|
||||||
|
"syslog": {
|
||||||
|
"use": false
|
||||||
|
},
|
||||||
|
"libvirt": {
|
||||||
|
"bind_interface": "$allinone_compute_mgmt_nic"
|
||||||
|
},
|
||||||
|
"novnc_proxy": {
|
||||||
|
"bind_interface": "$allinone_compute_mgmt_nic"
|
||||||
|
},
|
||||||
|
"xvpvnc_proxy": {
|
||||||
|
"bind_interface": "$allinone_compute_mgmt_nic"
|
||||||
|
},
|
||||||
|
"image_api_chef_role": "os-image",
|
||||||
|
"identity_service_chef_role": "os-identity",
|
||||||
|
"nova_setup_chef_role": "os-compute-api",
|
||||||
|
"rabbit_server_chef_role": "os-ops-messaging",
|
||||||
|
"ratelimit": {
|
||||||
|
"api": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"volume": {
|
||||||
|
"enabled": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"network": {
|
||||||
|
"service_type": "neutron",
|
||||||
|
"fixed_range": "10.0.0.0/8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"network": {
|
||||||
|
"verbose": "True",
|
||||||
|
"debug": "True",
|
||||||
|
"service_plugins": [
|
||||||
|
"router"
|
||||||
|
],
|
||||||
|
"ml2": {
|
||||||
|
"type_drivers": "local,flat,vlan,gre",
|
||||||
|
"tenant_network_types": "vlan,gre",
|
||||||
|
"network_vlan_ranges": "physnet1:1000:2999",
|
||||||
|
"enable_security_group": "True"
|
||||||
|
},
|
||||||
|
"openvswitch": {
|
||||||
|
"tenant_network_type": "vlan",
|
||||||
|
"network_vlan_ranges": "physnet1:1000:2999",
|
||||||
|
"bridge_mappings": "physnet1:br-eth1",
|
||||||
|
"fw_driver": "neutron.agent.firewall.NoopFirewallDriver"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"db": {
|
||||||
|
"bind_interface": "$allinone_compute_mgmt_nic",
|
||||||
|
"compute": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip"
|
||||||
|
},
|
||||||
|
"identity": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip"
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip"
|
||||||
|
},
|
||||||
|
"network": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip"
|
||||||
|
},
|
||||||
|
"volume": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip"
|
||||||
|
},
|
||||||
|
"dashboard": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip"
|
||||||
|
},
|
||||||
|
"telemetry": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip"
|
||||||
|
},
|
||||||
|
"orchestration": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"developer_mode": true,
|
||||||
|
"endpoints": {
|
||||||
|
"db": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip"
|
||||||
|
},
|
||||||
|
"mq": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip"
|
||||||
|
},
|
||||||
|
"compute-api": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "8774",
|
||||||
|
"path": "/v2/%(tenant_id)s"
|
||||||
|
},
|
||||||
|
"compute-api-bind": {
|
||||||
|
"bind_interface": "$allinone_compute_mgmt_nic"
|
||||||
|
},
|
||||||
|
"compute-ec2-admin": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "8773",
|
||||||
|
"path": "/services/Admin"
|
||||||
|
},
|
||||||
|
"compute-ec2-api": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "8773",
|
||||||
|
"path": "/services/Cloud"
|
||||||
|
},
|
||||||
|
"compute-xvpvnc": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "6081",
|
||||||
|
"path": "/console"
|
||||||
|
},
|
||||||
|
"compute-novnc": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "6080",
|
||||||
|
"path": "/vnc_auto.html"
|
||||||
|
},
|
||||||
|
"compute-novnc-bind": {
|
||||||
|
"bind_interface": "$allinone_compute_mgmt_nic"
|
||||||
|
},
|
||||||
|
"vnc_bind": {
|
||||||
|
"bind_interface": "$allinone_compute_mgmt_nic"
|
||||||
|
},
|
||||||
|
"image-api": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "9292",
|
||||||
|
"path": "/v2"
|
||||||
|
},
|
||||||
|
"image-api-bind": {
|
||||||
|
"bind_interface": "$allinone_compute_mgmt_nic"
|
||||||
|
},
|
||||||
|
"image-registry": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "9191",
|
||||||
|
"path": "/v2"
|
||||||
|
},
|
||||||
|
"image-registry-bind": {
|
||||||
|
"bind_interface": "$allinone_compute_mgmt_nic"
|
||||||
|
},
|
||||||
|
"identity-bind": {
|
||||||
|
"bind_interface": "$allinone_compute_mgmt_nic"
|
||||||
|
},
|
||||||
|
"identity-api": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "5000",
|
||||||
|
"path": "/v2.0"
|
||||||
|
},
|
||||||
|
"identity-admin": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "35357",
|
||||||
|
"path": "/v2.0"
|
||||||
|
},
|
||||||
|
"block-storage-api": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "8776",
|
||||||
|
"path": "/v1/%(tenant_id)s"
|
||||||
|
},
|
||||||
|
"block-storage-api-bind": {
|
||||||
|
"bind_interface": "$allinone_compute_mgmt_nic"
|
||||||
|
},
|
||||||
|
"telemetry-api": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "8777",
|
||||||
|
"path": "/v1"
|
||||||
|
},
|
||||||
|
"network-api": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "9696",
|
||||||
|
"path": ""
|
||||||
|
},
|
||||||
|
"network-api-bind": {
|
||||||
|
"bind_interface": "$allinone_compute_mgmt_nic"
|
||||||
|
},
|
||||||
|
"network-openvswitch": {
|
||||||
|
"bind_interface": "$allinone_compute_mgmt_nic"
|
||||||
|
},
|
||||||
|
"orchestration-api": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "8004",
|
||||||
|
"path": "/v1/%(tenant_id)s"
|
||||||
|
},
|
||||||
|
"orchestration-api-cfn": {
|
||||||
|
"host": "$allinone_compute_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "8000",
|
||||||
|
"path": "/v1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"identity": {
|
||||||
|
"admin_user": "admin",
|
||||||
|
"bind_interface": "$allinone_compute_mgmt_nic",
|
||||||
|
"catalog": {
|
||||||
|
"backend": "sql"
|
||||||
|
},
|
||||||
|
"debug": true,
|
||||||
|
"rabbit_server_chef_role": "os-ops-messaging",
|
||||||
|
"roles": [
|
||||||
|
"admin",
|
||||||
|
"keystone_admin",
|
||||||
|
"keystone_service_admin",
|
||||||
|
"member",
|
||||||
|
"netadmin",
|
||||||
|
"sysadmin"
|
||||||
|
],
|
||||||
|
"syslog": {
|
||||||
|
"use": false
|
||||||
|
},
|
||||||
|
"tenants": [
|
||||||
|
"admin",
|
||||||
|
"service",
|
||||||
|
"demo"
|
||||||
|
],
|
||||||
|
"token": {
|
||||||
|
"backend": "sql"
|
||||||
|
},
|
||||||
|
"users": {
|
||||||
|
"admin": {
|
||||||
|
"password": "admin",
|
||||||
|
"default_tenant": "admin",
|
||||||
|
"roles": {
|
||||||
|
"admin": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"keystone_admin": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"keystone_service_admin": [
|
||||||
|
"admin"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"api": {
|
||||||
|
"bind_interface": "eth0"
|
||||||
|
},
|
||||||
|
"debug": true,
|
||||||
|
"identity_service_chef_role": "os-identity",
|
||||||
|
"rabbit_server_chef_role": "os-ops-messaging",
|
||||||
|
"registry": {
|
||||||
|
"bind_interface": "eth0"
|
||||||
|
},
|
||||||
|
"syslog": {
|
||||||
|
"use": false
|
||||||
|
},
|
||||||
|
"upload_image": {
|
||||||
|
"cirros": "http://download.cirros-cloud.net/0.3.2/cirros-0.3.2-x86_64-disk.img"
|
||||||
|
},
|
||||||
|
"upload_images": [
|
||||||
|
"cirros"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"memcached_servers": [
|
||||||
|
"$allinone_compute_mgmt_nic:11211"
|
||||||
|
],
|
||||||
|
"mq": {
|
||||||
|
"user": "$credentials.rabbitmq.username",
|
||||||
|
"password": "$credentials.rabbitmq.password",
|
||||||
|
"vhost": "/nova",
|
||||||
|
"network": {
|
||||||
|
"service_type": "rabbitmq"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
317
templates/chef_installer/openstack_icehouse/env.tmpl.multiroles
Normal file
317
templates/chef_installer/openstack_icehouse/env.tmpl.multiroles
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
#set config = $cluster.deploy_package_config
|
||||||
|
#set mappings = $config.roles_mapping
|
||||||
|
#set credentials = $config.service_credentials
|
||||||
|
#set compute_mgmt_nic = $mappings.os_compute.management.interface
|
||||||
|
#set controller_mgmt_ip = $mappings.os_controller.management.ip
|
||||||
|
#set controller_mgmt_nic = $mappings.os_controller.management.interface
|
||||||
|
{
|
||||||
|
"name": "testing",
|
||||||
|
"description": "Environment used in testing the upstream cookbooks and reference Chef repository",
|
||||||
|
"cookbook_versions": {
|
||||||
|
},
|
||||||
|
"json_class": "Chef::Environment",
|
||||||
|
"chef_type": "environment",
|
||||||
|
"default_attributes": {
|
||||||
|
},
|
||||||
|
"override_attributes": {
|
||||||
|
"mysql": {
|
||||||
|
"server_root_password": "test",
|
||||||
|
"server_debian_password": "root",
|
||||||
|
"server_repl_password": "root",
|
||||||
|
"allow_remote_root": true,
|
||||||
|
"root_network_acl": "%"
|
||||||
|
},
|
||||||
|
"openstack": {
|
||||||
|
"auth": {
|
||||||
|
"validate_certs": false
|
||||||
|
},
|
||||||
|
"block-storage": {
|
||||||
|
"syslog": {
|
||||||
|
"use": false
|
||||||
|
},
|
||||||
|
"api": {
|
||||||
|
"ratelimit": "False"
|
||||||
|
},
|
||||||
|
"debug": true,
|
||||||
|
"image_api_chef_role": "os-image",
|
||||||
|
"identity_service_chef_role": "os-identity",
|
||||||
|
"rabbit_server_chef_role": "os-ops-messaging"
|
||||||
|
},
|
||||||
|
"dashboard": {
|
||||||
|
"use_ssl": "false"
|
||||||
|
},
|
||||||
|
"compute": {
|
||||||
|
"syslog": {
|
||||||
|
"use": false
|
||||||
|
},
|
||||||
|
"libvirt": {
|
||||||
|
"bind_interface": "$compute_mgmt_nic"
|
||||||
|
},
|
||||||
|
"novnc_proxy": {
|
||||||
|
"bind_interface": "$controller_mgmt_nic"
|
||||||
|
},
|
||||||
|
"xvpvnc_proxy": {
|
||||||
|
"bind_interface": "$controller_mgmt_nic"
|
||||||
|
},
|
||||||
|
"image_api_chef_role": "os-image",
|
||||||
|
"identity_service_chef_role": "os-identity",
|
||||||
|
"nova_setup_chef_role": "os-compute-api",
|
||||||
|
"rabbit_server_chef_role": "os-ops-messaging",
|
||||||
|
"ratelimit": {
|
||||||
|
"api": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"volume": {
|
||||||
|
"enabled": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"network": {
|
||||||
|
"service_type": "neutron",
|
||||||
|
"fixed_range": "10.0.0.0/8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"network": {
|
||||||
|
"verbose": "True",
|
||||||
|
"debug": "True",
|
||||||
|
"service_plugins": [
|
||||||
|
"router"
|
||||||
|
],
|
||||||
|
"ml2": {
|
||||||
|
"type_drivers": "local,flat,vlan,gre",
|
||||||
|
"tenant_network_types": "vlan,gre",
|
||||||
|
"network_vlan_ranges": "physnet1:1000:2999",
|
||||||
|
"enable_security_group": "True"
|
||||||
|
},
|
||||||
|
"openvswitch": {
|
||||||
|
"tenant_network_type": "vlan",
|
||||||
|
"network_vlan_ranges": "physnet1:1000:2999",
|
||||||
|
"bridge_mappings": "physnet1:br-eth1",
|
||||||
|
"fw_driver": "neutron.agent.firewall.NoopFirewallDriver"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"db": {
|
||||||
|
"bind_interface": "$controller_mgmt_nic",
|
||||||
|
"compute": {
|
||||||
|
"host": "$controller_mgmt_ip"
|
||||||
|
},
|
||||||
|
"identity": {
|
||||||
|
"host": "$controller_mgmt_ip"
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"host": "$controller_mgmt_ip"
|
||||||
|
},
|
||||||
|
"network": {
|
||||||
|
"host": "$controller_mgmt_ip"
|
||||||
|
},
|
||||||
|
"volume": {
|
||||||
|
"host": "$controller_mgmt_ip"
|
||||||
|
},
|
||||||
|
"dashboard": {
|
||||||
|
"host": "$controller_mgmt_ip"
|
||||||
|
},
|
||||||
|
"telemetry": {
|
||||||
|
"host": "$controller_mgmt_ip"
|
||||||
|
},
|
||||||
|
"orchestration": {
|
||||||
|
"host": "$controller_mgmt_ip"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"developer_mode": true,
|
||||||
|
"endpoints": {
|
||||||
|
"db": {
|
||||||
|
"host": "$controller_mgmt_ip"
|
||||||
|
},
|
||||||
|
"mq": {
|
||||||
|
"host": "$controller_mgmt_ip"
|
||||||
|
},
|
||||||
|
"compute-api": {
|
||||||
|
"host": "$controller_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "8774",
|
||||||
|
"path": "/v2/%(tenant_id)s"
|
||||||
|
},
|
||||||
|
"compute-api-bind": {
|
||||||
|
"bind_interface": "$controller_mgmt_nic"
|
||||||
|
},
|
||||||
|
"compute-ec2-admin": {
|
||||||
|
"host": "$controller_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "8773",
|
||||||
|
"path": "/services/Admin"
|
||||||
|
},
|
||||||
|
"compute-ec2-api": {
|
||||||
|
"host": "$controller_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "8773",
|
||||||
|
"path": "/services/Cloud"
|
||||||
|
},
|
||||||
|
"compute-xvpvnc": {
|
||||||
|
"host": "$controller_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "6081",
|
||||||
|
"path": "/console"
|
||||||
|
},
|
||||||
|
"compute-novnc": {
|
||||||
|
"host": "$controller_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "6080",
|
||||||
|
"path": "/vnc_auto.html"
|
||||||
|
},
|
||||||
|
"compute-novnc-bind": {
|
||||||
|
"bind_interface": "$controller_mgmt_nic"
|
||||||
|
},
|
||||||
|
"vnc_bind": {
|
||||||
|
"bind_interface": "$controller_mgmt_nic"
|
||||||
|
},
|
||||||
|
"image-api": {
|
||||||
|
"host": "$controller_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "9292",
|
||||||
|
"path": "/v2"
|
||||||
|
},
|
||||||
|
"image-api-bind": {
|
||||||
|
"bind_interface": "$controller_mgmt_nic"
|
||||||
|
},
|
||||||
|
"image-registry": {
|
||||||
|
"host": "$controller_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "9191",
|
||||||
|
"path": "/v2"
|
||||||
|
},
|
||||||
|
"image-registry-bind": {
|
||||||
|
"bind_interface": "$controller_mgmt_nic"
|
||||||
|
},
|
||||||
|
"identity-bind": {
|
||||||
|
"bind_interface": "$controller_mgmt_nic"
|
||||||
|
},
|
||||||
|
"identity-api": {
|
||||||
|
"host": "$controller_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "5000",
|
||||||
|
"path": "/v2.0"
|
||||||
|
},
|
||||||
|
"identity-admin": {
|
||||||
|
"host": "$controller_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "35357",
|
||||||
|
"path": "/v2.0"
|
||||||
|
},
|
||||||
|
"block-storage-api": {
|
||||||
|
"host": "$controller_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "8776",
|
||||||
|
"path": "/v1/%(tenant_id)s"
|
||||||
|
},
|
||||||
|
"block-storage-api-bind": {
|
||||||
|
"bind_interface": "$controller_mgmt_nic"
|
||||||
|
},
|
||||||
|
"telemetry-api": {
|
||||||
|
"host": "$controller_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "8777",
|
||||||
|
"path": "/v1"
|
||||||
|
},
|
||||||
|
"network-api": {
|
||||||
|
"host": "$controller_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "9696",
|
||||||
|
"path": ""
|
||||||
|
},
|
||||||
|
"network-api-bind": {
|
||||||
|
"bind_interface": "$controller_mgmt_nic"
|
||||||
|
},
|
||||||
|
"network-openvswitch": {
|
||||||
|
"bind_interface": "$controller_mgmt_nic"
|
||||||
|
},
|
||||||
|
"orchestration-api": {
|
||||||
|
"host": "$controller_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "8004",
|
||||||
|
"path": "/v1/%(tenant_id)s"
|
||||||
|
},
|
||||||
|
"orchestration-api-cfn": {
|
||||||
|
"host": "$controller_mgmt_ip",
|
||||||
|
"scheme": "http",
|
||||||
|
"port": "8000",
|
||||||
|
"path": "/v1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"identity": {
|
||||||
|
"admin_user": "admin",
|
||||||
|
"bind_interface": "$controller_mgmt_nic",
|
||||||
|
"catalog": {
|
||||||
|
"backend": "sql"
|
||||||
|
},
|
||||||
|
"debug": true,
|
||||||
|
"rabbit_server_chef_role": "os-ops-messaging",
|
||||||
|
"roles": [
|
||||||
|
"admin",
|
||||||
|
"keystone_admin",
|
||||||
|
"keystone_service_admin",
|
||||||
|
"member",
|
||||||
|
"netadmin",
|
||||||
|
"sysadmin"
|
||||||
|
],
|
||||||
|
"syslog": {
|
||||||
|
"use": false
|
||||||
|
},
|
||||||
|
"tenants": [
|
||||||
|
"admin",
|
||||||
|
"service",
|
||||||
|
"demo"
|
||||||
|
],
|
||||||
|
"token": {
|
||||||
|
"backend": "sql"
|
||||||
|
},
|
||||||
|
"users": {
|
||||||
|
"admin": {
|
||||||
|
"password": "admin",
|
||||||
|
"default_tenant": "admin",
|
||||||
|
"roles": {
|
||||||
|
"admin": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"keystone_admin": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"keystone_service_admin": [
|
||||||
|
"admin"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"api": {
|
||||||
|
"bind_interface": "eth0"
|
||||||
|
},
|
||||||
|
"debug": true,
|
||||||
|
"identity_service_chef_role": "os-identity",
|
||||||
|
"rabbit_server_chef_role": "os-ops-messaging",
|
||||||
|
"registry": {
|
||||||
|
"bind_interface": "eth0"
|
||||||
|
},
|
||||||
|
"syslog": {
|
||||||
|
"use": false
|
||||||
|
},
|
||||||
|
"upload_image": {
|
||||||
|
"cirros": "http://download.cirros-cloud.net/0.3.2/cirros-0.3.2-x86_64-disk.img"
|
||||||
|
},
|
||||||
|
"upload_images": [
|
||||||
|
"cirros"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"memcached_servers": [
|
||||||
|
"$controller_mgmt_nic:11211"
|
||||||
|
],
|
||||||
|
"mq": {
|
||||||
|
"user": "$credentials.mq.username",
|
||||||
|
"password": "$credentials.mq.password",
|
||||||
|
"vhost": "/nova",
|
||||||
|
"network": {
|
||||||
|
"service_type": "rabbitmq"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"override_attributes": {
|
||||||
|
"endpoints": {
|
||||||
|
"compute-vnc-bind": {
|
||||||
|
"host":"$host.deployed_package_config.roles_mapping.os_compute.management.ip"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
62
templates/cobbler/CentOS-6.5-x86_64/system.tmpl
Normal file
62
templates/cobbler/CentOS-6.5-x86_64/system.tmpl
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"name": "$host.name",
|
||||||
|
"hostname": "$host.hostname",
|
||||||
|
"profile": "$host.profile",
|
||||||
|
"gateway": "$host.gateway",
|
||||||
|
#import simplejson as json
|
||||||
|
#set nameservers = json.dumps($host.nameservers, encoding='utf-8')
|
||||||
|
"name_servers": $nameservers,
|
||||||
|
#set search_path = ' '.join($host.search_path)
|
||||||
|
"name_servers_search": "$search_path",
|
||||||
|
"proxy": "$host.http_proxy",
|
||||||
|
"modify_interface":
|
||||||
|
#set networks = $host.networks
|
||||||
|
#set rekeyed = {}
|
||||||
|
#set promicnic = ""
|
||||||
|
#for $nic, $val in $networks.iteritems():
|
||||||
|
#set ip_key = '-'.join(('ipaddress', $nic))
|
||||||
|
#set netmask_key = '-'.join(('netmask', $nic))
|
||||||
|
#set mgmt_key = '-'.join(('management', $nic))
|
||||||
|
#set static_key = '-'.join(('static', $nic))
|
||||||
|
#set $rekeyed[$ip_key] = $val.ip
|
||||||
|
#set $rekeyed[$netmask_key] = $val.netmask
|
||||||
|
#set $rekeyed[$mgmt_key] = $val.is_mgmt
|
||||||
|
#set $rekeyed[$static_key] = True
|
||||||
|
|
||||||
|
#if $val.is_promiscuous:
|
||||||
|
#set promicnic = $nic
|
||||||
|
#end if
|
||||||
|
#if $val.is_mgmt:
|
||||||
|
#set mac_key = '-'.join(('macaddress', $nic))
|
||||||
|
#set dns_key = '-'.join(('dns', $nic))
|
||||||
|
#set $rekeyed[$mac_key] = $host.mac
|
||||||
|
#set $rekeyed[$dns_key] = $host.dns
|
||||||
|
#end if
|
||||||
|
#end for
|
||||||
|
#set nic_info = json.dumps($rekeyed, encoding='utf-8')
|
||||||
|
$nic_info
|
||||||
|
,
|
||||||
|
"ksmeta":{
|
||||||
|
#set partition_config = ''
|
||||||
|
#for k, v in $host.partition.iteritems():
|
||||||
|
#set path = ''
|
||||||
|
#if v['vol_percentage']:
|
||||||
|
#set $path = k + ' ' + str(v['vol_percentage']) + '%'
|
||||||
|
#else:
|
||||||
|
#set $path = k + ' ' + str(v['vol_size'])
|
||||||
|
#end if
|
||||||
|
#set partition_config = ';'.join((partition_config, $path))
|
||||||
|
#end for
|
||||||
|
#set partition_config = partition_config[1:]
|
||||||
|
#set $password = crypt.crypt($host.server_credentials.password, "az")
|
||||||
|
#set no_proxy = ','.join($host.no_proxy)
|
||||||
|
"username": "$host.server_credentials.username",
|
||||||
|
"password": "$password",
|
||||||
|
"promisc_nics": "$promicnic",
|
||||||
|
"partition": "$partition_config",
|
||||||
|
"https_proxy": "$host.https_proxy",
|
||||||
|
"ntp_server": "$host.ntp_server",
|
||||||
|
"timezone": "$host.timezone",
|
||||||
|
"ignore_proxy": "$no_proxy"
|
||||||
|
}
|
||||||
|
}
|
36
templates/cobbler/Ubuntu-12.04-x86_64/system.tmpl
Normal file
36
templates/cobbler/Ubuntu-12.04-x86_64/system.tmpl
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "$host.fullname",
|
||||||
|
"hostname": "$host.hostname",
|
||||||
|
"profile": "$host.profile",
|
||||||
|
"gateway": "$host.gateway",
|
||||||
|
"name_servers": "$host.name_servers",
|
||||||
|
"name_servers_search": "$host.search_path",
|
||||||
|
"proxy": "$host.http_proxy",
|
||||||
|
"modify_interface":
|
||||||
|
#import simplejson
|
||||||
|
#set interfaces = $host.networks.interfaces
|
||||||
|
#set rekeyed = {}
|
||||||
|
#for $nic, $val in $interfaces.iteritems():
|
||||||
|
#set $rekeyed = { "ipaddress-vnet0" : $val.ip, "netmask-vnet0": $val.netmask, "management-vnet0": $val.is_mgmt, "static-vnet0" : True }
|
||||||
|
#if $val.is_mgmt:
|
||||||
|
#set $rekeyed["macaddress-vnet0"] = $host.mac_address
|
||||||
|
#set $rekeyed["dnsname-vnet0"] = $host.dns
|
||||||
|
#end if
|
||||||
|
#end for
|
||||||
|
#set $str=simplejson.dumps($rekeyed, encoding='utf-8')
|
||||||
|
$str
|
||||||
|
,
|
||||||
|
"ksmeta":{
|
||||||
|
"username": "$host.server_credentials.username",
|
||||||
|
#import crypt
|
||||||
|
#set $password = crypt.crypt($host.server_credentials.password, "az")
|
||||||
|
"password": "$password",
|
||||||
|
#set f=[(k + ' ' + v['vol_percentage'] or v['vol_size']) for k,v in $host.partition.iteritems()]
|
||||||
|
#set $partition_config = '; '.join($f)
|
||||||
|
"partition": "$partition_config",
|
||||||
|
"https_proxy": "$host.https_proxy",
|
||||||
|
"ignore_proxy": "$host.ignore_proxy",
|
||||||
|
"ntp_server": "$host.ntp_server"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user