320 lines
11 KiB
Python
Executable File
320 lines
11 KiB
Python
Executable File
# Copyright 2013 OpenStack Foundation
|
|
# All Rights Reserved.
|
|
#
|
|
# 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.
|
|
|
|
"""
|
|
/install endpoint for zenic API
|
|
"""
|
|
import os
|
|
import copy
|
|
import subprocess
|
|
from oslo_log import log as logging
|
|
from webob.exc import HTTPBadRequest
|
|
|
|
from daisy import i18n
|
|
|
|
from daisy.common import exception
|
|
import daisy.registry.client.v1.api as registry
|
|
import daisy.api.backends.common as daisy_cmn
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
_ = i18n._
|
|
_LE = i18n._LE
|
|
_LI = i18n._LI
|
|
_LW = i18n._LW
|
|
|
|
daisy_zenic_path = '/var/lib/daisy/zenic/'
|
|
ZENIC_STATE = {
|
|
'INIT': 'init',
|
|
'INSTALLING': 'installing',
|
|
'ACTIVE': 'active',
|
|
'INSTALL_FAILED': 'install-failed',
|
|
'UNINSTALLING': 'uninstalling',
|
|
'UNINSTALL_FAILED': 'uninstall-failed',
|
|
'UPDATING': 'updating',
|
|
'UPDATE_FAILED': 'update-failed',
|
|
}
|
|
|
|
|
|
def get_cluster_hosts(req, cluster_id):
|
|
try:
|
|
cluster_hosts = registry.get_cluster_hosts(req.context, cluster_id)
|
|
except exception.Invalid as e:
|
|
raise HTTPBadRequest(explanation=e.msg, request=req)
|
|
return cluster_hosts
|
|
|
|
|
|
def get_host_detail(req, host_id):
|
|
try:
|
|
host_detail = registry.get_host_metadata(req.context, host_id)
|
|
except exception.Invalid as e:
|
|
raise HTTPBadRequest(explanation=e.msg, request=req)
|
|
return host_detail
|
|
|
|
|
|
def get_roles_detail(req):
|
|
try:
|
|
roles = registry.get_roles_detail(req.context)
|
|
except exception.Invalid as e:
|
|
raise HTTPBadRequest(explanation=e.msg, request=req)
|
|
return roles
|
|
|
|
|
|
def get_hosts_of_role(req, role_id):
|
|
try:
|
|
hosts = registry.get_role_host_metadata(req.context, role_id)
|
|
except exception.Invalid as e:
|
|
raise HTTPBadRequest(explanation=e.msg, request=req)
|
|
return hosts
|
|
|
|
|
|
def get_role_detail(req, role_id):
|
|
try:
|
|
role = registry.get_role_metadata(req.context, role_id)
|
|
except exception.Invalid as e:
|
|
raise HTTPBadRequest(explanation=e.msg, request=req)
|
|
return role
|
|
|
|
|
|
def update_role(req, role_id, role_meta):
|
|
try:
|
|
registry.update_role_metadata(req.context, role_id, role_meta)
|
|
except exception.Invalid as e:
|
|
raise HTTPBadRequest(explanation=e.msg, request=req)
|
|
|
|
|
|
def update_role_host(req, role_id, role_host):
|
|
try:
|
|
registry.update_role_host_metadata(req.context, role_id, role_host)
|
|
except exception.Invalid as e:
|
|
raise HTTPBadRequest(explanation=e.msg, request=req)
|
|
|
|
|
|
def delete_role_hosts(req, role_id):
|
|
try:
|
|
registry.delete_role_host_metadata(req.context, role_id)
|
|
except exception.Invalid as e:
|
|
raise HTTPBadRequest(explanation=e.msg, request=req)
|
|
|
|
|
|
def _get_cluster_network(cluster_networks, network_type):
|
|
network = [cn for cn in cluster_networks
|
|
if cn['name'] in network_type]
|
|
if not network or not network[0]:
|
|
msg = "network %s is not exist" % (network_type)
|
|
raise exception.InvalidNetworkConfig(msg)
|
|
else:
|
|
return network[0]
|
|
|
|
|
|
def get_host_interface_by_network(host_detail, network_type):
|
|
host_detail_info = copy.deepcopy(host_detail)
|
|
interface_list = [hi for hi in host_detail_info['interfaces']
|
|
for assigned_network in hi['assigned_networks']
|
|
if assigned_network and
|
|
network_type == assigned_network['name']]
|
|
interface = {}
|
|
if interface_list:
|
|
interface = interface_list[0]
|
|
|
|
if not interface:
|
|
msg = "network %s of host %s is not exist" % (
|
|
network_type, host_detail_info['id'])
|
|
raise exception.InvalidNetworkConfig(msg)
|
|
|
|
return interface
|
|
|
|
|
|
def get_host_network_ip(req, host_detail, cluster_networks, network_type):
|
|
interface_network_ip = ''
|
|
host_interface = get_host_interface_by_network(host_detail, network_type)
|
|
if host_interface:
|
|
network = _get_cluster_network(cluster_networks, network_type)
|
|
assigned_network = daisy_cmn.get_assigned_network(req,
|
|
host_interface['id'],
|
|
network['id'])
|
|
interface_network_ip = assigned_network['ip']
|
|
|
|
if not interface_network_ip:
|
|
msg = "%s network ip of host %s can't be empty" % (
|
|
network_type, host_detail['id'])
|
|
raise exception.InvalidNetworkConfig(msg)
|
|
return interface_network_ip
|
|
|
|
|
|
def get_deploy_node_cfg(req, host_detail, cluster_networks):
|
|
host_deploy_network = get_host_interface_by_network(
|
|
host_detail, 'DEPLOYMENT')
|
|
host_deploy_ip = get_host_network_ip(
|
|
req, host_detail, cluster_networks, 'DEPLOYMENT')
|
|
if not host_deploy_ip:
|
|
msg = "deployment ip of host %s can't be empty" % host_detail['id']
|
|
raise exception.InvalidNetworkConfig(msg)
|
|
host_deploy_macname = host_deploy_network['name']
|
|
if not host_deploy_macname:
|
|
msg = "deployment macname of host %s can't be empty" % host_detail[
|
|
'id']
|
|
raise exception.InvalidNetworkConfig(msg)
|
|
|
|
host_mgt_ip = get_host_network_ip(
|
|
req, host_detail, cluster_networks, 'MANAGEMENT')
|
|
if not host_mgt_ip:
|
|
msg = "management ip of host %s can't be empty" % host_detail['id']
|
|
raise exception.InvalidNetworkConfig(msg)
|
|
|
|
memmode = 'tiny'
|
|
host_memory = 0
|
|
|
|
# if host_detail.has_key('memory'):
|
|
if 'memory' in host_detail:
|
|
host_memory = (
|
|
int(host_detail['memory'][
|
|
'total'].strip().split()[0])) / (1024 * 1024)
|
|
|
|
if host_memory < 8:
|
|
memmode = 'tiny'
|
|
elif host_memory < 16:
|
|
memmode = 'small'
|
|
elif host_memory < 32:
|
|
memmode = 'medium'
|
|
else:
|
|
memmode = 'large'
|
|
|
|
deploy_node_cfg = {}
|
|
deploy_node_cfg.update({'hostid': host_detail['id']})
|
|
deploy_node_cfg.update({'hostname': host_detail['name']})
|
|
deploy_node_cfg.update({'nodeip': host_deploy_ip})
|
|
deploy_node_cfg.update({'MacName': host_deploy_macname})
|
|
deploy_node_cfg.update({'memmode': memmode})
|
|
deploy_node_cfg.update({'mgtip': host_mgt_ip})
|
|
return deploy_node_cfg
|
|
|
|
|
|
def get_roles_and_hosts_list(req, cluster_id):
|
|
roles_id_list = set()
|
|
hosts_id_list = set()
|
|
hosts_list = []
|
|
|
|
cluster_networks = daisy_cmn.get_cluster_networks_detail(req, cluster_id)
|
|
roles = daisy_cmn.get_cluster_roles_detail(req, cluster_id)
|
|
for role in roles:
|
|
if role['deployment_backend'] != daisy_cmn.zenic_backend_name:
|
|
continue
|
|
role_hosts = daisy_cmn.get_hosts_of_role(req, role['id'])
|
|
if role_hosts:
|
|
for role_host in role_hosts:
|
|
if role_host['host_id'] not in hosts_id_list:
|
|
host = daisy_cmn.get_host_detail(req, role_host['host_id'])
|
|
host_ip = get_host_network_ip(
|
|
req, host, cluster_networks, 'MANAGEMENT')
|
|
hosts_id_list.add(host['id'])
|
|
|
|
host_cfg = {}
|
|
host_cfg['mgtip'] = host_ip
|
|
host_cfg['rootpwd'] = host['root_pwd']
|
|
hosts_list.append(host_cfg)
|
|
|
|
roles_id_list.add(role['id'])
|
|
|
|
return (roles_id_list, hosts_list)
|
|
|
|
|
|
def check_and_get_zenic_version(daisy_zenic_pkg_path):
|
|
zenic_version_pkg_file = ""
|
|
zenic_version_pkg_name = ""
|
|
get_zenic_version_pkg = "ls %s| grep ^ZENIC.*\.zip$" % daisy_zenic_pkg_path
|
|
obj = subprocess.Popen(get_zenic_version_pkg,
|
|
shell=True,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE)
|
|
(stdoutput, erroutput) = obj.communicate()
|
|
if stdoutput:
|
|
zenic_version_pkg_name = stdoutput.split('\n')[0]
|
|
zenic_version_pkg_file = daisy_zenic_pkg_path + zenic_version_pkg_name
|
|
chmod_for_zenic_version = 'chmod +x %s' % zenic_version_pkg_file
|
|
daisy_cmn.subprocess_call(chmod_for_zenic_version)
|
|
return (zenic_version_pkg_file, zenic_version_pkg_name)
|
|
|
|
|
|
class ZenicShellExector():
|
|
|
|
"""
|
|
Class config task before install zenic bin.
|
|
"""
|
|
|
|
def __init__(self, mgt_ip, task_type, params={}):
|
|
self.task_type = task_type
|
|
self.mgt_ip = mgt_ip
|
|
self.params = params
|
|
self.clush_cmd = ""
|
|
self.PKG_NAME = self.params['pkg_name']
|
|
self.PKG_PATH = daisy_zenic_path + self.PKG_NAME
|
|
self.CFG_PATH = daisy_zenic_path + mgt_ip + "_zenic.conf"
|
|
self.oper_type = {
|
|
'install': self._install_pkg
|
|
}
|
|
self.oper_shell = {
|
|
'CMD_SSHPASS_PRE': "sshpass -p ossdbg1 %(ssh_ip)s %(cmd)s",
|
|
'CMD_CFG_SCP': "scp %(path)s root@%(ssh_ip)s:/etc/zenic/config" %
|
|
{'path': self.CFG_PATH, 'ssh_ip': mgt_ip},
|
|
'CMD_PKG_UNZIP': "unzip /home/workspace/%(pkg_name)s \
|
|
-d /home/workspace/PKG" % {'pkg_name': self.PKG_NAME},
|
|
'CMD_PKG_SCP': "scp %(path)s root@%(ssh_ip)s:/home/workspace/" %
|
|
{'path': self.PKG_PATH, 'ssh_ip': mgt_ip}
|
|
}
|
|
|
|
self._execute()
|
|
|
|
def _install_pkg(self):
|
|
if not os.path.exists(self.CFG_PATH):
|
|
LOG.error(_("<<<CFG %s not exist>>>" % self.CFG_PATH))
|
|
return
|
|
|
|
if not os.path.exists(self.PKG_PATH):
|
|
LOG.error(_("<<<PKG %s not exist>>>" % self.PKG_PATH))
|
|
return
|
|
|
|
self.clush_cmd = "%s;%s;%s" % \
|
|
(self.oper_shell['CMD_SSHPASS_PRE'] %
|
|
{"ssh_ip": "", "cmd": self.oper_shell['CMD_PKG_SCP']},
|
|
self.oper_shell['CMD_SSHPASS_PRE'] %
|
|
{"ssh_ip": "", "cmd": self.oper_shell['CMD_CFG_SCP']},
|
|
self.oper_shell['CMD_SSHPASS_PRE'] %
|
|
{"ssh_ip": "ssh " + self.mgt_ip, "cmd": self.oper_shell[
|
|
'CMD_PKG_UNZIP']})
|
|
|
|
subprocess.check_output(
|
|
self.clush_cmd, shell=True, stderr=subprocess.STDOUT)
|
|
|
|
def _execute(self):
|
|
try:
|
|
if not self.task_type or not self.mgt_ip:
|
|
LOG.error(
|
|
_("<<<ZenicShellExector::execute, \
|
|
input params invalid!>>>"))
|
|
return
|
|
|
|
self.oper_type[self.task_type]()
|
|
except subprocess.CalledProcessError as e:
|
|
LOG.warn(
|
|
_("<<<ZenicShellExector::execute:Execute command failed! Reason\
|
|
:%s>>>" % e.output.strip()))
|
|
except Exception as e:
|
|
LOG.exception(_(e.message))
|
|
else:
|
|
LOG.info(
|
|
_("<<<ZenicShellExector::execute:Execute command:\
|
|
%s,successful!>>>" % self.clush_cmd))
|