提交 d3e25217 编写于 作者: H houjian

Init project for python2

上级 c1d7b6c3
此差异已折叠。
#!/usr/bin/python
# -*-coding:utf-8-*-
# coding: iso-8859-15
import json
import os
from xml.dom.minidom import getDOMImplementation
from common_utils import manager, update
def alarm_get():
re_alarm_info = {}
alarm_info = manager.xml_nodes["cib"].getElementsByTagName("alarmd")[0]
if alarm_info is None or alarm_info == []:
re_alarm_info = {}
re_alarm_info["flag"] = False
re_alarm_info["smtp"] = ""
re_alarm_info["port"] = ""
re_alarm_info["sender"] = ""
re_alarm_info["password"] = ""
re_alarm_info["receiver"] = []
return json.dumps({'action': True, 'data': re_alarm_info})
try:
alarm_email = alarm_info.getElementsByTagName("mail")[0]
re_alarm_info = {}
if alarm_email.getAttribute("flag") == "on":
re_alarm_info["flag"] = True
else:
re_alarm_info["flag"] = False
re_alarm_info["smtp"] = alarm_email.getAttribute("smtp")
re_alarm_info["port"] = alarm_email.getAttribute("port")
re_alarm_info["sender"] = alarm_email.getAttribute("sender")
password_str = alarm_email.getAttribute("password")
# 将密码明文加密
mail_password = ""
cmdstr = "/usr/bin/pwd_decode " + str(password_str)
retfile = os.popen(cmdstr, 'r')
mail_password = retfile.readline()
if mail_password[-1] == '\n':
mail_password = mail_password[0:-1]
retfile.close()
re_alarm_info["password"] = mail_password
re_alarm_info["receiver"] = []
for email in alarm_email.getAttribute("receiver").split(","):
if email != "":
re_alarm_info["receiver"].append(email)
except:
re_alarm_info = {}
re_alarm_info["flag"] = False
re_alarm_info["smtp"] = ""
re_alarm_info["port"] = ""
re_alarm_info["sender"] = ""
re_alarm_info["password"] = ""
re_alarm_info["receiver"] = []
return json.dumps({'action': True, 'data': re_alarm_info})
def alarm_set(item):
impl = getDOMImplementation()
newdoc = impl.createDocument(None, "alarmd", None)
xml_node = newdoc.documentElement
alarm_email = item
if 'flag' in alarm_email:
impl = getDOMImplementation()
newdoc = impl.createDocument(None, "mail", None)
mail = newdoc.documentElement
flag = str(item['flag'])
# 防止传递bool类型数据出现问题
if flag == "True" or flag == "true":
mail.setAttribute("flag", "on")
else:
mail.setAttribute("flag", "off")
mail.setAttribute("smtp", item['smtp'])
mail.setAttribute("port", str(item['port']))
mail.setAttribute("sender", item['sender'])
# 将密码明文加密
mail_password = ""
cmdstr = "/usr/bin/pwd_encode " + item['password']
retfile = os.popen(cmdstr, 'r')
mail_password = retfile.readline()
if mail_password[-1] == '\n':
mail_password = mail_password[0:-1]
retfile.close()
mail.setAttribute("password", mail_password)
email_receive = item['receiver']
alarm_email_receive = ""
for receiver in email_receive:
if len(alarm_email_receive) == 0:
alarm_email_receive = receiver
else:
alarm_email_receive = alarm_email_receive + "," + receiver
mail.setAttribute("receiver", str(alarm_email_receive))
xml_node.appendChild(mail)
xml_str = xml_node.toxml().replace("\n", "")
manager.cib_do_cmd("cib_replace\n%s\n%s" % (str("alarmd"), str(xml_str)))
if manager.failed_reason != "":
return {'action': False, 'error': _(manager.failed_reason)}
failed_reason = manager.failed_reason
update()
if failed_reason != "":
return {'action': False, 'error': _(failed_reason)}
else:
return {'action': True, 'info': _('Set alarm success')}
def alarm_delete():
impl = getDOMImplementation()
newdoc = impl.createDocument(None, "alarmd", None)
xml_node = newdoc.documentElement
xml_str = xml_node.toxml().replace("\n", "")
manager.cib_do_cmd("cib_replace\n%s\n%s" % (str("alarmd"), str(xml_str)))
if manager.failed_reason != "":
return {'action': False, 'error': _(manager.failed_reason)}
failed_reason = manager.failed_reason
update()
if failed_reason != "":
return {'action': False, 'error': _(failed_reason)}
else:
return {'action': True, 'info': _('Delete alarm success')}
CREATE TABLE if not exists notification_info (
id integer NOT NULL primary key,
detail text,
year smallint,
month smallint,
day smallint,
"time" time,
level character varying(255),
read smallint,
-- Joey@20160818: for notification reaction features
grade smallint,
objtype integer,
objkey character varying(255),
objvalue character varying(255),
reactiontype integer,
reactionresult smallint,
remark text,
reactionerrorinfo text,
srcmod character varying(64),
srcid bigint
);
此差异已折叠。
# -*-coding:utf-8-*-
# !/usr/bin/python
# coding: iso-8859-15
from common_utils import update
from common_utils import manager
from common_utils import Remote
import collections
import os
def check_heartbeat_config():
filename = "/etc/corosync/corosync.conf"
if not os.path.exists(filename):
return False
return True
def get_crm_metadata(crm_cmd):
if crm_cmd in ["pengine", "crmd"]:
metadata = manager.get_crm_metadata(crm_cmd)
else:
return {"action": False, "error": _("input error, the cmd must be pengine or crmd")}
name = metadata.name
version = metadata.version
longdesc = metadata.longdesc
shortdesc = metadata.shortdesc
parameters = metadata.parameters
# 节点数
nodecount = len(manager.get_all_nodes())
# 心跳是否已经配置
isconfig = check_heartbeat_config()
crm_config = get_crm_config(metadata)
parameters_value = {}
# 调试param返回值
for param in parameters:
config = {}
config = param
config['value'] = crm_config[param['name']]
parameters_value[param['name']] = config
# 对首选项数据进行排序
sort_parameters_value = collections.OrderedDict()
for param in ['symmetric-cluster', 'no-quorum-policy', 'stonith-enabled', 'start-failure-is-fatal', 'maintenance-mode',
'default-resource-stickiness', 'node-health-strategy', 'node-health-red', 'node-health-yellow', 'node-health-green']:
sort_parameters_value[param] = parameters_value[param]
return {"action": True,
'data': {"isconfig": isconfig, "nodecount": nodecount, "name": name, "version": version,
"longdesc": longdesc, "shortdesc": shortdesc, "parameters": sort_parameters_value}}
def get_crm_config(metadata):
global mode_level
config = {}
for parameter in metadata.parameters:
config[parameter["name"]] = str(parameter["content"]["default"])
cluster_property_sets = manager.xml_nodes["cib"].getElementsByTagName("cluster_property_set")
if len(cluster_property_sets) == 0:
return config
elif len(cluster_property_sets) == 1:
for nvpair in cluster_property_sets[0].getElementsByTagName("nvpair"):
name = nvpair.getAttribute("name")
value = nvpair.getAttribute("value")
if value != "":
config[nvpair.getAttribute("name")] = nvpair.getAttribute("value")
return config
else:
return None
def save_crm_metadata(data):
attribute = data
for name in attribute.keys():
type = 'crm_config'
value = attribute[name]
manager.set_crm_attribute(type, str(name), str(value))
if manager.failed_reason != "":
return {'action': False, 'error': _(manager.failed_reason)}
update()
return {'action': True, 'info': _("Save crm metadata success")}
def cluster_action(nodeauth, action):
if 'nodeauth' in nodeauth:
for node in nodeauth['nodeauth']:
nodeip = node['nodeip']
password = node['password']
remote = Remote(nodeip, password)
if action == 'start':
remote.service_start()
if action == 'stop':
remote.service_stop()
if action == 'restart':
remote.service_restart()
return {'action': True, 'info': _("Action on cluster success")}
return {'action': True, 'error': _("Cluster need auth info")}
if __name__ == '__main__':
# print get_crm_metadata("pengine")
nodeauth = {
"nodeauth": [
{
"nodeid": "ns187",
"nodeip": "10.1.110.187",
"password": "qwer1234"
},
{
"nodeid": "ns188",
"nodeip": "10.1.110.188",
"password": "qwer1234"
}
]
}
cluster_action(nodeauth, "start")
此差异已折叠。
此差异已折叠。
#!/bin/bash
#updated by yangli.wang@cs2c.com.cn in 2016.7.27 for HA7.0
#writen by qi.li
#TODOLIST HA resource alarm
SQL="sqlite3"
DB_FILE="/usr/share/heartbeat-gui/ha-api/audit.db"
local_sql(){
while :
do
$SQL ${DB_FILE} "$1" 2> /dev/null
case $? in
5|6) # locked
sleep 1
;;
*)
break
esac
done
}
alarm_send_to_db()
{
local dc_node
local YEAR MONTH DAY TIME TIME_STR WARNNING_LEVEL READ_DONE WARNNING_DETAIL
WARNNING_DETAIL=$1
check_string=$2
[ $CRM_notify_rc -gt 0 ] || return 1
dc_node=`crm_mon -1 | awk '/Current DC:/{print $3}'`
HOST_NAME=`hostname`
[ $dc_node = $HOST_NAME ] || return 1
YEAR=`date +%Y`
MONTH=`date +%m`
DAY=`date +%d`
TIME=`date +%H:%M:%S`
TIME_STR="'$TIME'"
WARNNING_LEVEL="'2r0'"
READ_DONE=0
WARNNING_DETAIL="$WARNNING_DETAIL""$check_string"
WARNNING_DETAIL="'$WARNNING_DETAIL'"
local_sql "insert into notification_info (detail, year, month, day,time, level, read) VALUES ( $WARNNING_DETAIL,$YEAR,$MONTH,$DAY,$TIME_STR,$WARNNING_LEVEL,$READ_DONE)"
}
WARNNING_DETAIL="Resource $CRM_notify_rsc $CRM_notify_task on $CRM_notify_node failed ($CRM_notify_desc)."
check_string="Please check the resource-parameters and system environment."
alarm_send_to_db "${WARNNING_DETAIL}" "${check_string}"
#!/bin/bash
#3. delete node from HA
del_node=$1
/usr/bin/python /usr/share/heartbeat-gui/ha-api/del_node_constraints.py $del_node
host_name=`crm_node -l | grep lost | cut -d " " -f 2 |grep $del_node`
if [ x$host_name == x ]; then
echo "the $del_node is not lost\n"
exit -1;
fi
crm_node -f -R `crm_node -l | grep lost | cut -d " " -f 1` > /dev/null 2>&1
crm -F configure delete $host_name > /dev/null 2>&1
#!/usr/bin/python
# -*-coding:utf-8-*-
# coding: iso-8859-15
import sys, os, string
sys.path.append("/usr/share/heartbeat-gui")
sys.path.append("/usr/lib64/heartbeat-gui")
import re
from Manager import Manager
from pymgmt import *
manager = Manager()
def del_node_constraints(del_node_id):
location_ids = []
for rsc in manager.get_top_rsc():
constraints = os.popen("crm_resource -a -r %s" % (rsc)).read().split("\n")
for cons in constraints:
m = re.match('^\s*:\sNode\s(.*)\s*\(score=(.*)\,\sid=(.*)\)', cons)
if m is None:
continue
if m.groups()[0].strip() == del_node_id: # location
location_ids.append(m.groups()[2].strip())
rsc_location_rule = []
xml_constraints = manager.xml_nodes["cib"].getElementsByTagName("constraints")[0]
for rsc_location in manager.xml_nodes["cib"].getElementsByTagName("rsc_location"):
id = str(rsc_location.getAttribute("id"))
if id in location_ids:
xml_constraints.removeChild(rsc_location)
else:
for rule in rsc_location.getElementsByTagName("rule"):
id = str(rule.getAttribute("id"))
if id in location_ids:
rsc_location.removeChild(rule)
if len(rsc_location.getElementsByTagName("rule")) == 0:
xml_constraints.removeChild(rsc_location)
xml_str = xml_constraints.toxml().replace("\n", "")
manager.cib_do_cmd("cib_replace\n%s\n%s" % (str("constraints"), str(xml_str)))
if manager.failed_reason != "":
log(manager.failed_reason)
constes_nodes = []
for node in manager.xml_nodes["cib"].getElementsByTagName("conste_nodes"):
if node.getAttribute('rscid') == del_node_id:
constes_nodes.append(node)
for conste in constes_nodes:
xml_str = conste.toxml().replace("\n", "")
manager.cib_do_cmd("cib_delete\nconstes\n%s" % (str(xml_str)))
def is_ha_login():
if not manager.connected:
if manager.login('127.0.0.1', "hacluster", 'qwer1234'):
manager.update()
return True
else:
return False
else:
manager.process_event(None)
manager.update()
return True
if __name__ == '__main__':
if len(sys.argv) < 2:
print "param error"
sys.exit(1)
node = sys.argv[1]
if not is_ha_login():
print 'Please ensure that the HA service has already been started!'
sys.exit(1)
del_node_constraints(node)
if manager.failed_reason != "":
print manager.failed_reason
sys.exit(1)
else:
print "success"
sys.exit(0)
此差异已折叠。
#!/usr/bin/python
# -*-coding:utf-8-*-
# coding: iso-8859-15
from common_utils import is_ha_login
import json
import commands
import re
import os
from xml.dom.minidom import parseString
from xml.dom.minidom import getDOMImplementation
from common_utils import manager, update
import xml
def get_gfs():
re_gfs_info = {}
#all_nodes = manager.get_all_nodes()
for xml_clone in manager.xml_nodes["cib"].getElementsByTagName("nvpair"):
id = str(xml_clone.getAttribute("id"))
if id == "gfs_instance_device":
re_gfs_info['device'] = str(xml_clone.getAttribute("value"))
if id == "gfs_instance_directory":
re_gfs_info['mount_dir'] = str(xml_clone.getAttribute("value"))
if id == "clone-gfs-meta_attributes-clone-max":
re_gfs_info['max_num'] = int(xml_clone.getAttribute("value"))
if manager.failed_reason != "" :
return json.dumps({'action':False, 'error':_(manager.failed_reason)})
else:
return json.dumps({'action':True,'data':re_gfs_info})
def set_gfs(data):
'''
data = {"device": "/dev/vdb", "max_num": 2, "mount_dir": "/drbd"}
'''
if not manager.check_device(data['device']):
return json.dumps({'action':False, 'error':_("please input right share diskpath")})
if len(data['mount_dir'])==0:
return json.dumps({'action':False, 'error':_("please input directory!")})
if os.path.isdir(data['mount_dir'])==False:
return json.dumps({'action':False, 'error':_("directory error!")})
if int(data['max_num']) > int(len(manager.get_all_nodes())):
return json.dumps({'action':False, 'error':_("gfs num must little than the number of cluster nodes")})
if is_existed("clone","clone-gfs") :
ret = edit_filesystem_clone( data['device'],data['mount_dir'],str(data['max_num']))
else:
ret = gfs_create(data['device'],data['mount_dir'],str(data['max_num']))
if ret['action']:
update()
return json.dumps({'action':True, 'info':_("Are you sure you have format the shared disk to gfs?,please execute gfs_init.sh in /usr/sbin first")+_("And then start the resources %s\n")%("clone-gfs")})
update()
return json.dumps(ret)
def del_gfs():
if is_gfs_rsc_running():
return json.dumps({'action':False,'error':_("resources is running,please stop it first")})
ret = delete_resource("clone-gfs")
update()
return json.dumps(ret)
def is_existed(type,resourceid):
xml_resource = {}
for xml_clone in manager.xml_nodes["cib"].getElementsByTagName(type):
id = str(xml_clone.getAttribute("id"))
if id == resourceid:
return True
return False
def is_gfs_rsc_running():
status = manager.get_rsc_status("dlm_controld")
if status == "running":
return True
status = manager.get_rsc_status("gfs")
if status == "running":
return True
return False
def edit_filesystem_clone(diskpath,directory,gfs_num):
xmlresources = manager.xml_nodes["cib"].getElementsByTagName("resources")[0]
for xmlnode in xmlresources.getElementsByTagName("nvpair"):
if xmlnode.getAttribute("id") == "gfs_instance_device":
xmlnode.setAttribute("value",diskpath)
if xmlnode.getAttribute("id") == "gfs_instance_directory":
xmlnode.setAttribute("value",directory)
if xmlnode.getAttribute("id") == "clone-gfs-meta_attributes-clone-max":
xmlnode.setAttribute("value",gfs_num)
cmdxml = xmlresources.toxml().replace("\n","")
manager.cib_do_cmd("cib_replace\n%s\n%s"%(str("resources"),str(cmdxml)))
if manager.failed_reason != "" :
return {'action':False, 'error':_(manager.failed_reason)}
return {'action':True, 'info': _("Modify gfs configuration success")}
def delete_resource(resource_name):
xml_clone = {}
for xml_clone in manager.xml_nodes["cib"].getElementsByTagName("clone"):
id = str(xml_clone.getAttribute("id"))
if id == resource_name:
cmdxml = xml_clone.toxml().replace("\n","")
manager.cib_do_cmd("cib_delete\n%s\n%s"%(str("resources"),str(cmdxml)))
if manager.failed_reason != "" :
return {'action':False, 'error':_(manager.failed_reason)}
else:
return {'action':True, 'info': _("Delete resource success")}
return {'action':True, 'info': _("Delete resource success")}
def gfs_create(diskpath,directory,gfs_num = '-1'):
if is_existed("clone","clone-gfs2") == True:
json.dumps({'action':False, 'error':'the gfs existsed'})
impl = getDOMImplementation()
newdoc = impl.createDocument(None,"clone",None)
clonegfs = newdoc.documentElement
clonegfs.setAttribute("id","clone-gfs")
newdoc = impl.createDocument(None, "meta_attributes", None)
meta = newdoc.documentElement
meta.setAttribute("id","clone-gfs-meta_attributes")
newdoc = impl.createDocument(None, "nvpair", None)
nvpair1 = newdoc.documentElement
nvpair1.setAttribute("id","clone-gfs-meta_attributes-interleave")
nvpair1.setAttribute("name","interleave")
nvpair1.setAttribute("value","true")
meta.appendChild(nvpair1)
newdoc = impl.createDocument(None, "nvpair", None)
nvpair2 = newdoc.documentElement
nvpair2.setAttribute("id","clone-gfs-meta_attributes-target-role")
nvpair2.setAttribute("name","target-role")
nvpair2.setAttribute("value","Stopped")
meta.appendChild(nvpair2)
if gfs_num != '-1':
newdoc = impl.createDocument(None, "nvpair", None)
nvpair3 = newdoc.documentElement
nvpair3.setAttribute("id","clone-gfs-meta_attributes-clone-max")
nvpair3.setAttribute("name","clone-max")
nvpair3.setAttribute("value",gfs_num)
meta.appendChild(nvpair3)
clonegfs.appendChild(meta)
#######groupgfs########
newdoc = impl.createDocument(None, "group", None)
groupgfs = newdoc.documentElement
groupgfs.setAttribute("id","gfs-group")
################### dlm controld #####################
newdoc = impl.createDocument(None, "primitive", None)
primitive = newdoc.documentElement
primitive.setAttribute("class","ocf")
primitive.setAttribute("id","dlm_controld")
primitive.setAttribute("provider","pacemaker")
primitive.setAttribute("type","controld")
newdoc = impl.createDocument(None, "operations", None)
operation = newdoc.documentElement
newdoc = impl.createDocument(None, "op", None)
op = newdoc.documentElement
op.setAttribute("id","dlm_controld-op-monitor-10")
op.setAttribute("interval","10")
op.setAttribute("name","monitor")
op.setAttribute("start-delay","0")
op.setAttribute("timeout","20")
operation.appendChild(op)
primitive.appendChild(operation)
groupgfs.appendChild(primitive)
################## gfs fs ################################
newdoc = impl.createDocument(None, "primitive", None)
primitive = newdoc.documentElement
primitive.setAttribute("class","ocf")
primitive.setAttribute("id","gfs")
primitive.setAttribute("provider","heartbeat") # from common to heartbeat added by jian.hou
primitive.setAttribute("type","Filesystem")
newdoc = impl.createDocument(None, "operations", None)
operation = newdoc.documentElement
newdoc = impl.createDocument(None, "op", None)
op = newdoc.documentElement
op.setAttribute("id","gfs-op-monitor-20")
op.setAttribute("interval","20")
op.setAttribute("name","monitor")
op.setAttribute("timeout","40")
op.setAttribute("timeout","20")
operation.appendChild(op)
newdoc = impl.createDocument(None, "instance_attributes", None)
instance = newdoc.documentElement
instance.setAttribute("id","gfs_instance")
newdoc = impl.createDocument(None, "nvpair", None)
nvpair1 = newdoc.documentElement
nvpair1.setAttribute("id","gfs_instance_device")
nvpair1.setAttribute("name","device")
nvpair1.setAttribute("value",diskpath) #diskpath
newdoc = impl.createDocument(None, "nvpair", None)
nvpair2 = newdoc.documentElement
nvpair2.setAttribute("id","gfs_instance_directory")
nvpair2.setAttribute("name","directory")
nvpair2.setAttribute("value",directory) #directory
newdoc = impl.createDocument(None, "nvpair", None)
nvpair3 = newdoc.documentElement
nvpair3.setAttribute("id","gfs_instance_fstype")
nvpair3.setAttribute("name","fstype")
nvpair3.setAttribute("value","gfs2")
instance.appendChild(nvpair1)
instance.appendChild(nvpair2)
instance.appendChild(nvpair3)
primitive.appendChild(operation)
primitive.appendChild(instance)
groupgfs.appendChild(primitive)
####################################
clonegfs.appendChild(groupgfs)
cmdxml = clonegfs.toxml().replace("\n","")
manager.cib_do_cmd("cib_create\n%s\n%s"%(str("resources"),str(cmdxml)))
if manager.failed_reason != "" :
return {'action':False, 'error':_(manager.failed_reason)}
else:
status, output = commands.getstatusoutput("pcs resource update gfs options=noatime")
if status != 0:
return {'action':False, 'error': output}
return {'action':True, 'info': _("Create gfs success")}
[Unit]
Description=Ha-Api daemon
[Service]
Type = simple
User = root
Group = root
ExecStart=/usr/bin/python /usr/share/heartbeat-gui/ha-api/haclient-api.py
[Install]
WantedBy=multi-user.target
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
import os, sys
import time
import os.path
import commands
from common_utils import Remote
import gettext
from ctypes import *
from os.path import abspath, basename, join, isfile, isdir
import node
class HALicenseInfo(Structure):
"""Equivalence of C Structure containing HALicense Information"""
_fields_ = [("version_id", c_int), ("register_time", c_ulong),
("valid_period", c_int), ("feedback", c_char_p)]
libpath = "/usr/lib64/libhalicense.so"
if os.path.exists(libpath):
haliclib = CDLL(libpath)
halicense_init = haliclib.ha_license_init
halicense_init.restype = POINTER(HALicenseInfo)
halicense_get_fbcode = haliclib.ha_license_get_feedback
halicense_get_fbcode.restype = c_char_p
halicense_is_expired = haliclib.halicense_is_expired
def get_ha_host_license():
license_info = halicense_init()
# 该字段标识license是否被激活,比如说更换网卡
is_active = True
ret = haliclib.halicense_get_info(license_info)
if ret < 0:
is_active = False
time_format = '%Y-%m-%d %H:%M:%S' # eg. 2012-07-31
register_text = time.strftime(time_format, time.localtime(license_info.contents.register_time))
valid_text = time.strftime(time_format, time.localtime(
license_info.contents.register_time + license_info.contents.valid_period * 24 * 3600))
now_time = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
halicense_expired = halicense_is_expired()
license_dic = {
'version_id': license_info.contents.version_id,
'register_time': register_text,
'valid_period': valid_text,
'now_time': now_time,
'halicense_is_expired': halicense_expired,
'is_active': is_active
}
feedback_code = halicense_get_fbcode()
license_dic['feedback'] = feedback_code
return {'action': True, 'data': license_dic}
def get_remote_ha_host_license(nodeauth):
if 'nodeauth' in nodeauth:
node_lic = {}
for nodeinfo in nodeauth['nodeauth']:
nodeid = nodeinfo['nodeid']
# 通过查找配置文件获取nodeid所在主机上的所有ip
nodeips = node.get_node_ip(nodeid)
if 'data' in nodeips and 'ips' in nodeips['data'] and nodeips['data']['ips'] != []:
nodeip = nodeips['data']['ips'][0]
else:
return {'action': False, 'info': str(nodeid) + _(": Node needs to configure IP")}
password = nodeinfo['password']
remote = Remote(nodeip, password)
try:
data = {}
results = remote.get_license_info()
if nodeip in results and results[nodeip] != "":
info = eval(results[nodeip])
if 'data' in info:
data = info['data']
node_lic[nodeid] = data
# fabric 的异常比较特殊, 异常时SystemExit
except SystemExit:
return {'action': False, 'error': _('Get remote license info failed')}
return {'action': True, 'data': node_lic}
return {'action': False, 'error': _('Node need auth info')}
def install_ha_host_license_own(fileinfo):
if fileinfo is None:
return {'action': False, 'error': _('Install license failed')}
buf = fileinfo['file']
filename = '/etc/corosync/license.dat.new'
outfile = open(filename, 'wb')
outfile.write(buf)
outfile.close()
ret = haliclib.halicense_install(filename)
if ret != 0:
return {'action': False, 'error': _('Install license failed')}
else:
ret = get_ha_host_license()
if ret['action'] == True:
ret['info'] = _('Install license success')
return ret
if __name__ == '__main__':
'''
data = {
"nodeauth":[
{
"nodeid":"ns187",
"password":"qwer1234"
},
{
"nodeid":"ns188",
"password":"qwer1234"
}
]
}
'''
# print get_remote_ha_host_license(data)
# 这行必须存在是远程获取license命令
print get_ha_host_license()
#!/usr/bin/python
# -*-coding:utf-8-*-
# coding: iso-8859-15
from bottle import Bottle, run, request, static_file, redirect, response
import sys
import locale
import gettext
import json
sys.path.append("/usr/share/heartbeat-gui")
sys.path.append("/usr/lib64/heartbeat-gui")
import resource
import meta
import rsc_thread
import cluster
import node
import commands
import alarm
import common_utils
from common_utils import AUTH_USER, AUTH_PASSWORD
import config
import ha_license
from datetime import datetime
from functools import wraps
import logging
import drbd
import gfs
import log
import scripts
# from beaker.middleware import SessionMiddleware
app_name = "ha-api"
gettext.bindtextdomain(app_name)
gettext.textdomain(app_name)
gettext.install(app_name, "/usr/share/locale", unicode=1)
gettext.translation(app_name, "/usr/share/locale", languages=["zh_CN"]).install(True)
# 配置日志功能
logger = logging.getLogger('ha-api')
# set up the logger
logger.setLevel(logging.INFO)
file_handler = logging.FileHandler('/var/log/ha-api.log')
formatter = logging.Formatter('%(msg)s')
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
# 设置日志返回信息
def log_to_logger(fn):
'''
Wrap a Bottle request so that a log line is emitted after it's handled.
(This decorator can be extended to take the desired logger as a param.)
'''
@wraps(fn)
def _log_to_logger(*args, **kwargs):
request_time = datetime.now()
actual_response = fn(*args, **kwargs)
# modify this to log exactly what you need:
logger.info('%s %s %s %s %s' % (request.remote_addr,
request_time,
request.method,
request.url,
response.status))
return actual_response
return _log_to_logger
app = Bottle()
app.install(log_to_logger)
# if not common_utils.is_ha_login():
# print "Please ensure that the HA service has already been started, you can run 'systemctl start neokylinha' to start HA service!"
# exit(0)
@app.route('/api/v1/login', method='POST')
def check_auth():
data = request.json
if data is not None and 'username' in data and 'password' in data:
username = data['username']
if username != 'hacluster':
return {'action': False, 'error': _('Username is not allowed to login')}
password = data['password']
ret = common_utils.check_auth(username, password)
if ret:
# 更新 session 信息
session = request.environ.get('beaker.session')
session['user_name'] = username
session['password'] = password
session.save()
return {'action': ret, 'info': _('Login success')}
return {'action': ret, 'error': _('Username or password error')}
return {'action': False, 'error': _('Login failed')}
@app.route('/api/v1/logout', method='POST')
def logout():
session = request.environ.get('beaker.session')
session.delete()
return {'action': True, 'info': _('Login failed')}
@app.route('/api/v1/haclusters/1/resources/meta_attributes/:category', method='GET')
def get_rsc_meta_attributes(category):
if category not in ["clone", "primitive", "group"]:
return {'action': False, 'error': _('The category is not allowed')}
return resource.get_rsc_meta_attributes(category)
@app.route('/api/v1/haclusters/1/nodes/:nodeid/:action', method='PUT')
def node_action(nodeid, action):
action_list = ["start", "stop", "restart", "standby", "unstandby"]
if action not in action_list:
return {'action': False, 'error': _('The node action is not allowed')}
if action in ["start", "stop", "restart"]:
return node.node_action(nodeid, action)
# standby or unstandby
return node.set_node_action(nodeid, action)
@app.route('/api/v1/haclusters/1/localnodes/:action', method='PUT')
def node_local_action(action):
if action in ["start", "stop", "restart"]:
return node.node_local_action(action)
return {'action': False, 'error': _('The node action is not allowed')}
@app.route('/api/v1/haclusters/1/localnodes/:action', method='POST')
def node_local_action_post(action):
if action in ["start", "stop", "restart"]:
return node.node_local_action(action)
return {'action': False, 'error': _('The node action is not allowed')}
@app.route('/api/v1/haclusters/1', method='PUT')
def change_crm_metadata():
return cluster.save_crm_metadata(request.json)
@app.route('/api/v1/haclusters/1/:action', method='PUT')
def cluster_action(action):
return cluster.cluster_action(request.json, action)
@app.route('/api/v1/haclusters/1/resources/:rsc_id', method='PUT')
def set_rsc_info(rsc_id):
data = request.json
# 将获得的bool类型、整形数据转化为字符串
data = resource.data_int_bool_to_str(data)
return resource.set_rsc_info(data, rsc_id)
@app.route('/api/v1/haclusters/1/resources/:rsc_id/:action', method='PUT')
def action_on_rsc1(rsc_id, action):
data = request.json
action_list = ['start', 'stop', 'location', 'colocation', 'order', 'cleanup', 'migrate', 'unmigrate', 'delete']
if action in action_list:
if action in ['start', 'stop']:
return resource.action_on_rsc(rsc_id, action)
if action == "location":
return resource.rsc_run_level(data, rsc_id)
if action == "colocation":
return resource.set_colocation(data, rsc_id)
if action == "order":
return resource.set_order(data, rsc_id)
if action == "cleanup":
return resource.cleanup_rsc(rsc_id)
if action == "migrate":
return resource.migrate_rsc(data, rsc_id)
if action == "unmigrate":
return resource.unmigrate_rsc(rsc_id)
if action == "delete":
return resource.delete_rsc(rsc_id)
return {'action': False, 'error': _('The resource action is not allowed')}
@app.route("/api/v1/haclusters/1/resources/:rsc_id/relations/:relation", method='GET')
def get_localtion(rsc_id, relation):
if relation == "location":
return resource.get_run_level(rsc_id)
if relation == "colocation":
return resource.get_colocation(rsc_id)
if relation == "order":
return resource.get_order(rsc_id)
return {'action': False, 'error': 'The relation is not allowed'}
@app.route('/api/v1/haclusters/1', method='GET')
def get_cluster_info():
return cluster.get_crm_metadata("pengine")
@app.route("/api/v1/haclusters/1/metas", method='GET')
def get_all_meta():
return meta.get_all_rsc_avail()
@app.route('/api/v1/haclusters/1/nodes', method='GET')
def get_all_node_list():
return node.get_all_node_status()
@app.route('/api/v1/haclusters/1/nodes/:nodeid', method='GET')
def get_node_ip(nodeid):
return node.get_node_ip(nodeid)
@app.route('/api/v1/haclusters/1/resources', method='GET')
def get_all_resources():
return resource.get_all_rsc_status_constraints()
@app.route('/api/v1/haclusters/1/resources/:rsc_id', method='GET')
def get_rsc_info(rsc_id):
ret = resource.single_rsc_get_info(rsc_id)
if 'action' in ret and not ret['action']:
return ret
result = ret
data = result['data']
if 'primitive' in data:
result['data'] = resource.rsc_primitive_format(data)
if 'group' in data:
result['data'] = resource.rsc_group_format(data)
if 'clone' in data:
result['data'] = resource.rsc_clone_format(data)
return result
@app.route('/api/v1/haclusters/1/alarms', method='GET')
def get_alarm():
return alarm.alarm_get()
@app.route('/api/v1/haclusters/1/alarms', method='POST')
def set_alarm():
data = request.json
return alarm.alarm_set(data)
@app.route('/api/v1/haclusters/1/alarms', method='DELETE')
def delete_alarm():
return alarm.alarm_delete()
@app.route('/api/v1/haclusters/1/configs', method='GET')
def get_hb_configs():
# 标识是否获取磁盘心跳信息
get_diskhb = True
return config.get_hb_config_org(get_diskhb)
@app.route('/api/v1/haclusters/1/get_diskhb_device', method='GET')
def get_diskhb_device():
return config.get_diskhb_device()
@app.route('/api/v1/haclusters/1/configs', method='POST')
def set_hb_configs():
data = request.json
return config.save_hb_conf(data)
@app.route('/api/v1/haclusters/1/metas/:rsc_class/:rsc_type', method='GET')
@app.route('/api/v1/haclusters/1/metas/:rsc_class/:rsc_type/:rsc_provider', method='GET')
def get_rsc_meta(rsc_class, rsc_type, rsc_provider=None):
return meta.get_rsc_meta(rsc_class, rsc_type, rsc_provider)
@app.route('/api/v1/haclusters/1/resources', method='POST')
def add_rsc():
data = request.json
category = data['category']
# 将获得的bool类型、整形数据转化为字符串
data = resource.data_int_bool_to_str(data)
data.pop('category')
if category == "primitive":
parent_type = "resources"
return resource.add_primitive_rsc(data, parent_type)
if category == "clone":
return resource.rsc_to_clone(data)
if category == "group":
return resource.rscs_to_group(data)
return {'action': False, 'error': _('The category is not allowed')}
@app.route('/api/v1/haclusters/1/rlicenses', method='POST')
def get_remote_license_info():
data = request.json
return ha_license.get_remote_ha_host_license(data)
@app.route('/api/v1/haclusters/1/licenses', method='GET')
def get_license_info():
return ha_license.get_ha_host_license()
@app.route('/api/v1/haclusters/1/licenses', method='POST')
def install_license():
data = request.json
return ha_license.install_ha_host_license_own(data)
@app.route('/api/v1/haclusters/1/drbd', method='GET')
def get_drbd():
return drbd.get_drbd()
@app.route('/api/v1/haclusters/1/drbd', method='POST')
def set_drbd():
data = request.json
return drbd.set_drbd(data)
@app.route('/api/v1/haclusters/1/remotedrbd', method='POST')
def set_drbd():
data = request.json
return drbd.save_local_drbd(data)
@app.route('/api/v1/haclusters/1/drbd', method='DELETE')
def del_drbd():
return drbd.del_drbd()
@app.route('/api/v1/haclusters/1/drbd_status', method='GET')
def get_drbd_status():
return drbd.get_drbd_status()
@app.route('/api/v1/haclusters/1/gfs', method='GET')
def get_gfs():
return gfs.get_gfs()
@app.route('/api/v1/haclusters/1/gfs', method='POST')
def set_gfs():
data = request.json
return gfs.set_gfs(data)
@app.route('/api/v1/haclusters/1/gfs', method='DELETE')
def del_gfs():
return gfs.del_gfs()
@app.route('/api/v1/haclusters/1/hbstatus', method='GET')
def get_hb_status():
return config.get_hb_status()
# 判断远程api是否可连接接口
@app.route('/api/v1/haclusters/1/apistatus', method='GET')
def get_api_status():
return {'action': True}
# 远程调用保存脚本
@app.route('/api/v1/haclusters/1/remoteconfigs', method='POST')
def save_remote_config():
data = request.json
return config.save_local_config(data)
@app.route('/api/v1/haclusters/1/logs', method='GET')
def generate_log():
return log.generate_log()
@app.route('/api/v1/haclusters/1/scripts', method='POST')
def generate_scripts():
data = request.json
return scripts.generate_scripts(data)
@app.route('/api/v1/haclusters/1/remotescripts', method='POST')
def generate_scripts():
data = request.json
return scripts.generate_local_scripts(data)
@app.route('/api/v1/haclusters/1/commands/:cmd_type', method='GET')
def get_commands_result(cmd_type):
command_type = int(cmd_type)
if not isinstance(command_type, int):
{'action': False, 'error': _("Please check input commands type")}
command_table = {0: "All", 1: "crm_mon -1 -o", 2: "crm_simulate -Ls", 3: "pcs config show", 4: "corosync-cfgtool -s", 5: "crm configure verify"}
if command_type != 0 and command_type in command_table:
command_str = command_table[command_type]
status, output = commands.getstatusoutput(command_str)
return {'action': True, 'data': output}
else:
return {'action': False, 'error': _("Please check input commands type")}
@app.route('/api/v1/haclusters/1/commands', method='GET')
def get_commands_list():
command_table = {1: "crm_mon -1 -o", 2: "crm_simulate -Ls", 3: "pcs config show", 4: "corosync-cfgtool -s", 5: "crm configure verify"}
return {'action': True, 'data': command_table}
@app.route('/', method='GET')
def send_index_html():
"""
url mapping for index html file, which with @login_required decorated
"""
# 检查是否已经登录,如果已登录,则继续;如果未登录则检测URL 地址
session = request.environ.get('beaker.session')
user_name = session.get('user_name')
if user_name:
return static_file('index.html', root='/usr/share/heartbeat-gui/ha-api/static/')
redirect('/login')
@app.route('/<filename:re:.+\.(html|js|css|png|woff|ttf|ico|tar)>')
def send_html_static(filename):
"""
url mapping for html files, which also with @login_required decorated
"""
return static_file(filename, root='/usr/share/heartbeat-gui/ha-api/static')
# Add graceful shutdown by ctrl-c signal
import signal
def app_exit(signalnum, frame):
sys.exit(1)
signal.signal(signal.SIGINT, app_exit)
@app.error(404)
def err_404_handler(err):
if request.is_ajax:
return {'action': False, 'error': u'您访问的接口不存在'}
return static_file('index.html', root='/usr/share/heartbeat-gui/ha-api/static/')
from bottle import response, HTTPResponse
@app.hook('before_request')
def login_check():
#print 'run login_check() before request'
# 检查是否已经登录,如果已登录,则继续;如果未登录则检测URL 地址
session = request.environ.get('beaker.session')
user_name = session.get('user_name')
user, pwd = None, None
# 系统的内部接口
if request.path.startswith('/api/v1/haclusters/1/remoteconfigs') and request.method == 'POST' \
or request.path.startswith('/api/v1/haclusters/1/localnodes') and request.method == 'POST' \
or request.path.startswith('/api/v1/haclusters/1/remotescripts') and request.method == 'POST' \
or request.path.startswith('/api/v1/haclusters/1/remotedrbd') and request.method == 'POST' \
or request.path.startswith('/api/v1/haclusters/1/apistatus') and request.method == 'GET':
if request.auth is not None:
user, pwd = request.auth
if user != AUTH_USER and user != AUTH_PASSWORD:
raise HTTPResponse(status=403)
else:
raise HTTPResponse(status=403)
else:
if user_name is None:
if not request.path.startswith('/api/v1/login'):
if request.path.startswith('/api'):
raise HTTPResponse(status=403)
else:
user_name = str(user_name).strip()
password = str(session.get('password')).strip()
# 这两个接口必须允许执行,否认无法登录或者启动服务
if not request.path.startswith('/api/v1/login') and not request.path.startswith('/api/v1/haclusters/1/localnodes') and \
not request.path.startswith('/api/v1/haclusters/1/licenses') and not request.path.startswith('/api/v1/logout') and \
not request.path.startswith('/api/v1/haclusters/1/configs') and not request.path.startswith('/api/v1/haclusters/1/get_diskhb_device'):
if request.path.startswith('/api'):
ret = common_utils.is_ha_login("127.0.0.1", user_name, password)
if not ret:
raise HTTPResponse(status=200, header={'Cache-Control': 'no-store'}, output=json.dumps({'action': False, 'error': _('Please ensure that the HA service has already been started!')}))
if ret == "Busy":
raise HTTPResponse(status=200, header={'Cache-Control': 'no-store'}, output=json.dumps({'action': False, 'error': _('System is busy')}))
@app.hook('after_request')
def ajax_no_cache():
# if this is an ajax request
if request.path.startswith('/api/'):
response.headers['Cache-Control'] = 'no-store'
# Add authentications
from beaker.middleware import SessionMiddleware
# Add cookie-based session support
session_opts = {
'session.type': 'file',
'session.cookie_expires': True,
'session.timeout': 900,
'session.data_dir': './session',
'session.auto': True,
'session.save_accessed_time': True,
'session.encrypt_key': '98763587hkhdaf7*(^*(#%&$*YRhhgda',
'session.validate_key': '98763587hkhdaf7*(^*(#%&$*YRhhgda'}
app = SessionMiddleware(app, session_opts)
# Run the server
rsc_error_thread = rsc_thread.ErrorInfoThread()
rsc_error_thread.start()
#run(app, host='0.0.0.0', port='8088')
# https 运行
ssl_cherry_server = common_utils.init_ssl_cherry_server("0.0.0.0", "8088")
ssl_cherry_server.run(app)
# -*-coding:utf-8-*-
# !/usr/bin/python
# coding: iso-8859-15
import commands
from bottle import static_file
def generate_log():
status, output = commands.getstatusoutput("sh /usr/share/heartbeat-gui/ha-api/loggen.sh")
if status == 0:
file_path = str(output)
return {'action': True, 'data': {'filepath': file_path}}
return {'action': False, "error": "Get neokylinha log failed"}
if __name__ == '__main__':
print generate_log()
#!/usr/bin/bash
rm -rf /tmp/neokylinha-log
hostname=`hostname`
gentime=` date +'%Y%m%d%H%M%S'`
file_path=/usr/share/heartbeat-gui/ha-api/static/neokylinha-log-$hostname-$gentime.tar
file_name=neokylinha-log-$hostname-$gentime.tar
#expect -c '
#spawn sosreport -a --tmp-dir /tmp/neokylinha-log
#expect "Press ENTER to continue, or CTRL-C to quit."
#send "\n"
#expect "Please enter your first initial and last name*"
#send "\n"
#expect "Please enter the case id that you are generating this report for []*"
#send "\n"
#expect eof
#'
temp_dir=/tmp/neokylinha-log-$hostname-$gentime
mkdir $temp_dir
echo "#crm_mon -1" >> $temp_dir/commands.log
crm_mon -1 >> $temp_dir/commands.log
echo "" >> $temp_dir/commands.log
echo "#mount" >> $temp_dir/commands.log
mount >> $temp_dir/commands.log
echo "" >> $temp_dir/commands.log
echo "#iptables -L" >> $temp_dir/commands.log
iptables -L >> $temp_dir/commands.log
echo "" >> $temp_dir/commands.log
echo "#getenforce" >> $temp_dir/commands.log
getenforce >> $temp_dir/commands.log
echo "" >> $temp_dir/commands.log
echo "#ifconfig" >> $temp_dir/commands.log
ifconfig >> $temp_dir/commands.log
echo "" >> $temp_dir/commands.log
echo "#ps -aux|grep -i -e pacemaker -e corosync -e neokylinha -e mgmt" >> $temp_dir/commands.log
ps -aux|grep -i -e pacemaker -e corosync -e neokylinha -e mgmt >> $temp_dir/commands.log
echo "" >> $temp_dir/commands.log
echo "#/etc/rc.d/init.d/ha-api status" >> $temp_dir/commands.log
systemctl status ha-api >> $temp_dir/commands.log
echo "" >> $temp_dir/commands.log
cp -rf /var/log/messages* /var/log/neokylinha* /var/log/pacemaker.log* /var/log/ha-api.log* /var/lib/pacemaker /etc/hosts /etc/corosync $temp_dir
cd /tmp/
tar -cf $file_path neokylinha-log-$hostname-$gentime
echo $file_name
#!/usr/bin/python
# -*-coding:utf-8-*-
# coding: iso-8859-15
from common_utils import manager
import json
import os
import commands
def get_rsc_meta(rsc_class, rsc_type, rsc_provider=None):
# item = {'rsc_class':'ocf', 'rsc_type':'IPaddr', 'rsc_provider': 'common'}
primitive_class = rsc_class
if rsc_class == "stonith":
if rsc_provider is None:
primitive_type = rsc_type
else:
primitive_type = rsc_type + "/" + rsc_provider
primitive_provider = None
else:
primitive_type = rsc_type
primitive_provider = rsc_provider
meta = manager.get_rsc_meta(primitive_class, primitive_type, primitive_provider)
if meta is None:
actions = ["start", "stop", "reload", "monitor", "status", "migrate_from", "migrate_to", "promote", "demote"]
op_name_store = [{'name': op_name, 'interval': "0", 'timeout': '0'} for op_name in actions]
return {'action': True,
'data': {'name': '', 'version': '', 'longdesc': '', 'shortdesc': '', 'parameters': [],
'actions': op_name_store}}
name = meta.name
version = meta.version
longdesc = meta.longdesc
if longdesc is None:
longdesc = ""
else:
longdesc = longdesc.replace(_(". "), _(".\n"))
# longdesc = longdesc.replace("'","&apos;")
shortdesc = meta.shortdesc
if shortdesc is None:
shortdesc = ""
parameters = meta.parameters
for parameter in parameters:
if 'name' in parameter and parameter['name'] == 'cmd_prompt':
parameter["value"] = ""
parameter["content"]["default"] = ""
actions = meta.actions
for action in actions:
# 删除无用的monitor depth属性
if 'depth' in action:
action.pop('depth')
if "interval" not in action.keys():
action["interval"] = "0"
if rsc_class == 'stonith':
pcmk_host_list = {'content': {'default': "", 'type': "string"},
'longdesc': "A list of machines controlled by this device.", 'name': "pcmk_host_list",
'required': "1", 'shortdesc': "", 'unique': "", 'value': ""}
parameters.append(pcmk_host_list)
retjson = {'action': True,
'data': {'name': name, 'version': version, 'longdesc': longdesc, 'shortdesc': shortdesc,
'parameters': parameters, 'actions': actions}}
return retjson
def get_rsc_types(cl):
status, output = commands.getstatusoutput("pcs resource agents " + cl)
if status == 0:
ra_list = output.split('\n')
return ra_list
else:
return None
def get_all_rsc_avail():
ret_class = {}
classes = manager.get_rsc_classes()
for cl in classes:
# 原函数偶尔会发生获取值为None的问题
#ra_list = manager.get_rsc_types(cl)
ra_list = get_rsc_types(cl)
# 有时ra_list数据会获取为空值,添加重连机制
if ra_list is None:
return {'action': False, 'data': _('The System is busy')}
ra_list.sort()
provider_list = []
if cl == "ocf" and ra_list is not None:
ret_provider = {}
for ra in ra_list:
provider_list = manager.get_rsc_providers(cl, ra)
if provider_list is None:
break
for provider in provider_list:
if provider in ret_provider.keys():
# 判断ocf是否存在重复的类型名称,没有则继续添加
if ra not in ret_provider[provider]:
ret_provider[provider].append(ra)
else:
ret_provider[provider] = []
ret_provider[provider].append(ra)
ret_class['ocf'] = ret_provider
elif cl == 'heartbeat':
continue
else:
ra_list_new = list(set(ra_list))
if 'colord' in ra_list_new:
ra_list_new.remove('colord')
ret_class[cl] = ra_list_new
return {'action': True, 'data': ret_class}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
webpackJsonp([0],{1388:function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0}),t.getLicense=t.login=void 0;var u=n(119),a=r(u),s=n(291),c=r(s),i=(t.login=function(){var e=(0,c.default)(a.default.mark(function e(t){return a.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",(0,i.request)({url:l,method:"post",data:t}));case 1:case"end":return e.stop()}},e,this)}));return function(t){return e.apply(this,arguments)}}(),t.getLicense=function(){var e=(0,c.default)(a.default.mark(function e(t){return a.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",(0,i.request)({url:f,method:"get",data:t}));case 1:case"end":return e.stop()}},e,this)}));return function(t){return e.apply(this,arguments)}}(),n(28)),o=i.config.api,l=o.userLogin,f=o.license},610:function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var u=n(3),a=r(u),s=n(193),c=r(s),i=n(119),o=r(i),l=n(293),f=n(1388),d=n(28),p=n(81);t.default={namespace:"login",state:{license:JSON.parse(window.localStorage.getItem(p.prefix+"license"))},effects:{login:o.default.mark(function e(t,n){var r=t.payload,u=n.put,a=n.call;return o.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,a(f.login,r);case 2:return window.localStorage.setItem(p.prefix+"username",r.username),e.next=5,u(l.routerRedux.push("/resource"));case 5:case"end":return e.stop()}},e,this)}),getLicense:o.default.mark(function e(t,n){var r,u,a=n.call,s=n.put;return o.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,a(f.getLicense);case 2:return r=e.sent,u=(0,d.getLicenseType)(r.data),e.next=6,s({type:"updateLicense",payload:{license:u}});case 6:case"end":return e.stop()}},e,this)})},reducers:{updateLicense:function(e,t){var n=t.payload;return window.localStorage.setItem(p.prefix+"license",(0,c.default)(n.license)),(0,a.default)({},e,n)}}},e.exports=t.default}});
\ No newline at end of file
webpackJsonp([1],{1383:function(e,t,a){"use strict";function n(e){return e&&e.__esModule?e:{default:e}}function l(e){var t=!0,a=!1;switch(e.status){case"Master":break;case"Master/Standby":a=!0;break;case"Not Running/Standby":t=!1,a=!0;break;case"Standby":a=!0;break;case"Not Running":t=!1;break;case"Running":t=!0}e.running=t,e.standby=a}function r(e){if(e.drbdStatus&&"0"!==e.drbdStatus)return"error";switch(e.status){case"Running":return"success";case"Not Running":return e.status_message?"error":"default";case"Unmanaged":return"warning";case"Failed":case"Stop Failed":return"error";case"running(Master)":case"running(Slave)":return e.status="Running","success";default:return"default"}}Object.defineProperty(t,"__esModule",{value:!0});var i=a(608),o=n(i),s=a(1389),u=n(s),d=a(194),c=n(d),f=a(71),p=n(f),y=a(10),m=n(y),h=a(195),g=n(h),v=a(1390),b=n(v),k=a(103),E=n(k),R=a(606),C=n(R),x=a(23),S=n(x),w=a(120),_=n(w),O=a(72),I=n(O),N=a(30),M=n(N),V=a(5),T=n(V),P=a(8),F=n(P),L=a(6),j=n(L),q=a(7),D=n(q);a(609),a(1391),a(294),a(82),a(295),a(1392),a(122),a(607),a(83),a(73);var z=a(0),K=n(z),W=a(4),H=n(W),A=a(9),B=n(A),J=a(29),U=a(74),X=a(28),G=a(1394),Q=n(G),Z=function(e){function t(){return(0,T.default)(this,t),(0,j.default)(this,(t.__proto__||(0,M.default)(t)).apply(this,arguments))}return(0,D.default)(t,e),(0,F.default)(t,[{key:"componentDidUpdate",value:function(e){var t=this.props.mainLockVisible;!e.mainLockVisible&&t&&this.showMainLockView()}},{key:"handleRowClick",value:function(e){(0,this.props.dispatch)({type:"resource/updateState",payload:{selectedRowKeys:[e.key],selectedRows:[e]}})}},{key:"handleResourceOperation",value:function(e,t){(0,X.handleOperation)(this.props.dispatch,"resource",e,t)}},{key:"handleReFresh",value:function(){var e=this.props.dispatch;e({type:"resource/query"}),e({type:"node/query"}),e({type:"cluster/queryHeartBeatStatus"})}},{key:"showMainLockView",value:function(){var e=this.props,t=e.dispatch,a=e.autoReFreshId,n=e.autoReFreshTaskId;"0"!==a&&(clearInterval(n),t({type:"app/updateState",payload:{autoReFreshTaskId:0}})),I.default.warning({title:"\u96c6\u7fa4\u5904\u4e8e\u672a\u542f\u52a8\u72b6\u6001\u3002",content:K.default.createElement("div",null,K.default.createElement("p",null,"\u8bf7\u542f\u52a8\u96c6\u7fa4\u540e\u7ee7\u7eed\u64cd\u4f5c\u3002")),okText:"\u542f\u52a8",onOk:function(){return new _.default(function(e){t({type:"node/operateLocal",payload:{action:"start"}}).then(function(){setTimeout(function(){return window.location="/resource",e},2e4)})})}})}},{key:"render",value:function(){var e=this,t=this.props,a=t.rsclist,n=t.nodelist,i=t.selectedRowKeys,s=t.selectedRows,d=t.rightSiderFold,f=t.rightSiderNodeId,y=t.dispatch,h=t.loading,v=t.rscOperateLoading,k=t.tableHeight,R=[{title:"\u8d44\u6e90\u540d",dataIndex:"id",key:"id",sorter:function(e,t){return(0,X.strcmp)(e.id,t.id)}},{title:"\u72b6\u6001",dataIndex:"status",key:"status",sorter:function(e,t){return(0,X.strcmp)(e.status,t.status)},width:"10%",render:function(e,t){var a=t.status_message&&"Not Running"===e?"Failed":e;return t.drbdStatus&&"0"!==t.drbdStatus&&(a=t.drbdMsg),K.default.createElement(E.default,{placement:"right",title:a},K.default.createElement("span",{style:{marginLeft:"10%"}},v&&s[0].id===t.id?K.default.createElement(S.default,{type:"loading",className:Q.default.statusLoading}):K.default.createElement(C.default,{className:t.drbdStatus&&"0"!==t.drbdStatus?Q.default.redTwinkling:"",status:r(t)})))}},{title:"\u8d44\u6e90\u7c7b\u578b",dataIndex:"type",key:"type",width:"15%",sorter:function(e,t){return(0,X.strcmp)(e.type,t.type)}},{title:"\u670d\u52a1",dataIndex:"svc",key:"svc",width:"15%",sorter:function(e,t){return(0,X.strcmp)(e.svc||"",t.svc||"")}}];n.forEach(function(e){l(e),R.push({title:K.default.createElement("a",{onClick:function(){return y({type:"resource/updateState",payload:{rightSiderFold:!1,rightSiderNodeId:e.id}})}},K.default.createElement(E.default,{placement:"top",title:e.status},K.default.createElement(C.default,{dot:e.standby,style:{backgroundColor:"orange"}},K.default.createElement(b.default,{size:"small",icon:"desktop",style:{color:"white",backgroundColor:e.running?"green":"red"}}))),K.default.createElement("span",{className:e.id!==f||d?"":Q.default.selectedNode},"\xa0",e.id)),dataIndex:"running_node",key:e.id,width:36/n.length+"%",render:function(t,a){var n=(0,X.queryArray)(a.location,e.id,"node")||{},l=-1===t.indexOf(e.id)?"default":"success";return K.default.createElement("span",{style:{marginLeft:"10%"}},K.default.createElement(C.default,{status:l,text:n.level}))}})});var x={selectedRowKeys:i,onChange:function(e,t){y({type:"resource/updateState",payload:{selectedRowKeys:e,selectedRows:t}})},type:"radio"},w=K.default.createElement(g.default,{onClick:function(e){y({type:"resource/updateState",payload:{detailModalVisible:!0,metaAttrs:{},rsc:{category:e.key}}}),"primitive"===e.key&&y({type:"resource/queryRscTypes"}),y({type:"resource/queryRscAttrs",payload:{category:e.key}})}},K.default.createElement(g.default.Item,{key:"primitive"},"\u6dfb\u52a0\u666e\u901a\u8d44\u6e90"),K.default.createElement(g.default.Item,{key:"group"},"\u6dfb\u52a0\u7ec4\u8d44\u6e90"),K.default.createElement(g.default.Item,{key:"clone"},"\u6dfb\u52a0\u514b\u9686\u8d44\u6e90")),_=K.default.createElement(g.default,{onClick:function(e){y("location"===e.key?{type:"node/query"}:{type:"resource/query"}),y({type:"resource/queryRscRestriction",payload:{id:s[0].id,relation:e.key}}).then(function(){y({type:"resource/updateState",payload:{rscRestrictionModalVisible:!0,rscRestrictionModalTitle:e.key}})})}},K.default.createElement(g.default.Item,{key:"location"},"\u8d44\u6e90\u4f4d\u7f6e"),K.default.createElement(g.default.Item,{key:"colocation"},"\u8d44\u6e90\u534f\u540c"),K.default.createElement(g.default.Item,{key:"order"},"\u8d44\u6e90\u987a\u5e8f")),O=[{onClick:function(){"primitive"===s[0].type&&y({type:"resource/queryRscTypes"}),y({type:"resource/queryRscAttrs",payload:{category:s[0].type}}),y({type:"resource/detail",payload:{id:s[0].id.split(":")[0],category:s[0].type}}).then(function(){y({type:"resource/updateState",payload:{detailModalVisible:!0}})})},icon:"edit",text:"\u7f16\u8f91",enabled:function(){return 1===i.length&&"ms-drbd"!==s[0].id&&"drbd-ps:0"!==s[0].id&&"drbd-ps:1"!==s[0].id}},{onClick:function(){return e.handleResourceOperation(s[0].id,"start")},icon:"caret-right",text:"\u542f\u52a8",enabled:function(){var e=s;return 1===e.length&&"Running"!==e[0].status}},{onClick:function(){return e.handleResourceOperation(s[0].id,"stop")},icon:"stop",text:"\u505c\u6b62",enabled:function(){return 1===s.length}},{onClick:function(){return e.handleResourceOperation(s[0].id,"cleanup")},icon:"clear",text:"\u6e05\u7406",enabled:function(){return 1===i.length}},{onClick:function(){y({type:"resource/updateState",payload:{rscMigrationModalVisible:!0}})},icon:"export",text:"\u8fc1\u79fb",enabled:function(){var e=s;return 1===e.length&&"Running"===e[0].status&&"clone"!==e[0].type&&!e[0].isChild}},{onClick:function(){return e.handleResourceOperation(s[0].id,"unmigrate",{is_all_rscs:!1})},icon:"import",text:"\u56de\u8fc1",enabled:function(){var e=s;return 1===e.length&&"Running"===e[0].status&&"clone"!==e[0].type&&!e[0].isChild&&e[0].allow_unmigrate}}],I=document.body.clientWidth>1280;return K.default.createElement("div",{className:(0,B.default)(Q.default.container,(0,m.default)({},Q.default.diminish,!d&&document.body.clientWidth>425))},K.default.createElement(U.Loader,{spinning:h}),K.default.createElement("div",{style:{marginBottom:0}},K.default.createElement(p.default.Group,null,K.default.createElement(c.default,{overlay:w},K.default.createElement(p.default,null,K.default.createElement(S.default,{type:"plus"}),"\u6dfb\u52a0...")),O.map(function(e){return K.default.createElement(p.default,{key:e.text,disabled:!e.enabled(),onClick:e.onClick,title:e.text},K.default.createElement(S.default,{type:e.icon}),I&&e.text)}),K.default.createElement(u.default,{placement:"bottom",onConfirm:function(){e.handleResourceOperation(s[0].id,"delete")},title:"\u786e\u8ba4\u5220\u9664\u8d44\u6e90?"},K.default.createElement(p.default,{disabled:!(1===i.length&&!s[0].isChild),title:"\u5220\u9664"},K.default.createElement(S.default,{type:"delete"}),I&&"\u5220\u9664")),K.default.createElement(c.default,{disabled:!(1===i.length&&"clone"!==s[0].type&&!s[0].isChild&&"ms-drbd"!==s[0].id),overlay:_},K.default.createElement(p.default,null,K.default.createElement(S.default,{type:"sharealt"}),"\u5173\u7cfb.."))),K.default.createElement(p.default,{title:"\u5237\u65b0",style:{float:document.body.clientWidth>425?"right":void 0},onClick:this.handleReFresh.bind(this)},K.default.createElement(S.default,{type:"reload"}),I&&"\u5237\u65b0")),K.default.createElement(o.default,{columns:R,rowSelection:x,dataSource:a,scroll:{y:k},pagination:!1,onRow:function(t){return{onClick:function(){return e.handleRowClick(t)}}},locale:{emptyText:"\u6682\u65e0\u6570\u636e"}}),K.default.createElement("div",{className:(0,B.default)(Q.default.rightSider,(0,m.default)({},Q.default.rightSiderFold,d))},K.default.createElement("div",{className:Q.default.button,onClick:function(){return y({type:"resource/updateState",payload:{rightSiderFold:!0}})}},K.default.createElement(S.default,{type:"right"})),K.default.createElement(U.NodeView,null)),K.default.createElement(U.RscDetailModal,null),K.default.createElement(U.RscMigrationModal,null),K.default.createElement(U.RscRestrictions,null))}}]),t}(K.default.PureComponent);Z.propTypes={dispatch:H.default.func,rsclist:H.default.array,nodelist:H.default.array,selectedRowKeys:H.default.array,selectedRows:H.default.array,rightSiderFold:H.default.bool,loading:H.default.bool,rscOperateLoading:H.default.bool,tableHeight:H.default.number,mainLockVisible:H.default.bool};var Y=function(e){var t=e.resource,a=e.node,n=e.loading,l=e.app;return{rsclist:t.list,nodelist:a.list,selectedRowKeys:t.selectedRowKeys,selectedRows:t.selectedRows,rightSiderFold:t.rightSiderFold,rightSiderNodeId:t.rightSiderNodeId,loading:n.effects["resource/firstQuery"],rscOperateLoading:n.effects["resource/operate"],tableHeight:document.body.clientHeight-200,mainLockVisible:t.mainLockVisible,autoReFreshId:l.autoReFreshId,autoReFreshTaskId:l.autoReFreshTaskId}};t.default=(0,J.connect)(Y)(Z),e.exports=t.default},1389:function(e,t,a){"use strict";function n(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var l=a(3),r=n(l),i=a(5),o=n(i),s=a(8),u=n(s),d=a(6),c=n(d),f=a(7),p=n(f),y=a(0),m=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&(t[a]=e[a]);return t.default=e,t}(y),h=a(103),g=n(h),v=a(23),b=n(v),k=a(71),E=n(k),R=a(121),C=n(R),x=a(152),S=n(x),w=function(e,t){var a={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(a[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var l=0,n=Object.getOwnPropertySymbols(e);l<n.length;l++)t.indexOf(n[l])<0&&(a[n[l]]=e[n[l]]);return a},_=function(e){function t(e){(0,o.default)(this,t);var a=(0,c.default)(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return a.onConfirm=function(e){a.setVisible(!1);var t=a.props.onConfirm;t&&t.call(a,e)},a.onCancel=function(e){a.setVisible(!1);var t=a.props.onCancel;t&&t.call(a,e)},a.onVisibleChange=function(e){a.setVisible(e)},a.saveTooltip=function(e){a.tooltip=e},a.renderOverlay=function(e){var t=a.props,n=t.prefixCls,l=t.title,r=t.cancelText,i=t.okText,o=t.okType;return m.createElement("div",null,m.createElement("div",{className:n+"-inner-content"},m.createElement("div",{className:n+"-message"},m.createElement(b.default,{type:"exclamation-circle"}),m.createElement("div",{className:n+"-message-title"},l)),m.createElement("div",{className:n+"-buttons"},m.createElement(E.default,{onClick:a.onCancel,size:"small"},r||e.cancelText),m.createElement(E.default,{onClick:a.onConfirm,type:o,size:"small"},i||e.okText))))},a.state={visible:e.visible},a}return(0,p.default)(t,e),(0,u.default)(t,[{key:"componentWillReceiveProps",value:function(e){"visible"in e&&this.setState({visible:e.visible})}},{key:"getPopupDomNode",value:function(){return this.tooltip.getPopupDomNode()}},{key:"setVisible",value:function(e){var t=this.props;"visible"in t||this.setState({visible:e});var a=t.onVisibleChange;a&&a(e)}},{key:"render",value:function(){var e=this.props,t=e.prefixCls,a=e.placement,n=w(e,["prefixCls","placement"]),l=m.createElement(C.default,{componentName:"Popconfirm",defaultLocale:S.default.Popconfirm},this.renderOverlay);return m.createElement(g.default,(0,r.default)({},n,{prefixCls:t,placement:a,onVisibleChange:this.onVisibleChange,visible:this.state.visible,overlay:l,ref:this.saveTooltip}))}}]),t}(m.Component);t.default=_,_.defaultProps={prefixCls:"ant-popover",transitionName:"zoom-big",placement:"top",trigger:"click",okType:"primary"},e.exports=t.default},1390:function(e,t,a){"use strict";function n(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&(t[a]=e[a]);return t.default=e,t}function l(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=a(3),i=l(r),o=a(10),s=l(o),u=a(5),d=l(u),c=a(8),f=l(c),p=a(6),y=l(p),m=a(7),h=l(m),g=a(0),v=n(g),b=a(13),k=n(b),E=a(23),R=l(E),C=a(9),x=l(C),S=function(e,t){var a={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(a[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var l=0,n=Object.getOwnPropertySymbols(e);l<n.length;l++)t.indexOf(n[l])<0&&(a[n[l]]=e[n[l]]);return a},w=function(e){function t(e){(0,d.default)(this,t);var a=(0,y.default)(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return a.setScale=function(){var e=a.avatarChildren;if(e){var t=e.offsetWidth,n=k.findDOMNode(a),l=n.getBoundingClientRect().width;l-8<t?a.setState({scale:(l-8)/t}):a.setState({scale:1})}},a.handleImgLoadError=function(){return a.setState({isImgExist:!1})},a.state={scale:1,isImgExist:!0},a}return(0,h.default)(t,e),(0,f.default)(t,[{key:"componentDidMount",value:function(){this.setScale()}},{key:"componentDidUpdate",value:function(e,t){(e.children!==this.props.children||t.scale!==this.state.scale&&1===this.state.scale||t.isImgExist!==this.state.isImgExist)&&this.setScale()}},{key:"render",value:function(){var e,t,a=this,n=this.props,l=n.prefixCls,r=n.shape,o=n.size,u=n.src,d=n.icon,c=n.className,f=S(n,["prefixCls","shape","size","src","icon","className"]),p=(0,x.default)((e={},(0,s.default)(e,l+"-lg","large"===o),(0,s.default)(e,l+"-sm","small"===o),e)),y=(0,x.default)(l,c,p,(t={},(0,s.default)(t,l+"-"+r,r),(0,s.default)(t,l+"-image",u&&this.state.isImgExist),(0,s.default)(t,l+"-icon",d),t)),m=this.props.children;if(u&&this.state.isImgExist)m=v.createElement("img",{src:u,onError:this.handleImgLoadError});else if(d)m=v.createElement(R.default,{type:d});else{var h=this.avatarChildren;if(h||1!==this.state.scale){var g={msTransform:"scale("+this.state.scale+")",WebkitTransform:"scale("+this.state.scale+")",transform:"scale("+this.state.scale+")",position:"absolute",display:"inline-block",left:"calc(50% - "+Math.round(h.offsetWidth/2)+"px)"};m=v.createElement("span",{className:l+"-string",ref:function(e){return a.avatarChildren=e},style:g},m)}else m=v.createElement("span",{className:l+"-string",ref:function(e){return a.avatarChildren=e}},m)}return v.createElement("span",(0,i.default)({},f,{className:y}),m)}}]),t}(v.Component);t.default=w,w.defaultProps={prefixCls:"ant-avatar",shape:"circle",size:"default"},e.exports=t.default},1391:function(e,t,a){"use strict";a(16),a(605),a(82)},1392:function(e,t,a){"use strict";a(16),a(1393)},1393:function(e,t){},1394:function(e,t){e.exports={"text-overflow":"_32CXV","icon-button":"_29VBV",redTwinkling:"_3VVet",twinkling:"_2_gpb",rightSider:"bxuXv",button:"n50iD",rightSiderFold:"g2qJx",container:"_2qyLv",diminish:"_2yr1x",statusLoading:"_2ZSh3",selectedNode:"_270Jy"}}});
\ No newline at end of file
webpackJsonp([2],{1384:function(e,t,a){"use strict";function l(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var n=a(154),o=l(n),r=a(71),d=l(r),u=a(153),c=l(u),f=a(123),i=l(f);a(196),a(82),a(104),a(124);var s=a(0),m=l(s),p=a(4),g=l(p),E=a(29),y=a(81),_=a(1395),h=l(_),w=i.default.Item,v=y.featureSwitch.licenseMode,b=function(e){function t(){u(function(e,t){e||l({type:"login/login",payload:t}).then(function(){v&&l({type:"login/getLicense"})}).catch(function(){f({password:""})})})}var a=e.loading,l=e.dispatch,n=e.form,r=n.getFieldDecorator,u=n.validateFieldsAndScroll,f=n.setFieldsValue;return m.default.createElement("div",{className:h.default.form},m.default.createElement("div",{className:h.default.logo},m.default.createElement("img",{alt:"logo",src:y.logo}),m.default.createElement("span",null,y.name)),m.default.createElement("form",null,m.default.createElement(w,{hasFeedback:!0},r("username",{rules:[{required:!0,message:"\u8bf7\u8f93\u5165\u7528\u6237\u540d"}]})(m.default.createElement(c.default,{onPressEnter:t,placeholder:"\u7528\u6237\u540d",autoFocus:!0}))),m.default.createElement(w,{hasFeedback:!0},r("password",{rules:[{required:!0,message:"\u8bf7\u8f93\u5165\u5bc6\u7801"}]})(m.default.createElement(c.default,{type:"password",onPressEnter:t,placeholder:"\u5bc6\u7801"}))),m.default.createElement(o.default,null,m.default.createElement(d.default,{type:"primary",onClick:t,loading:a.effects["login/login"]},"\u767b\u5f55"))))};b.propTypes={form:g.default.object,dispatch:g.default.func,loading:g.default.object},t.default=(0,E.connect)(function(e){return{loading:e.loading}})(i.default.create()(b)),e.exports=t.default},1395:function(e,t){e.exports={"text-overflow":"_2yIpW","icon-button":"_1Ewkq",redTwinkling:"_3gP53",twinkling:"_1yha2",form:"_3y_Bf",logo:"Qzcu0","ant-spin-container":"JNULy","ant-spin-nested-loading":"_3VEcM"}}});
\ No newline at end of file
webpackJsonp([3],{1380:function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var u=n(0),a=r(u),l=n(1385),o=r(l),d=function(){return a.default.createElement("div",{className:"content-inner"},a.default.createElement("div",{className:o.default.error},a.default.createElement("h1",null,"404 Not Found")))};t.default=d,e.exports=t.default},1385:function(e,t){e.exports={error:"_Hd-C"}}});
\ No newline at end of file
webpackJsonp([4],{1381:function(e,t,r){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var n=r(3),u=a(n),s=r(120),c=a(s),d=r(64),i=a(d),o=r(119),p=a(o),l=r(192),f=r(81),y=a(f),h=r(292),v=a(h),b=r(1386),x=r(604),w=r(28),m=y.default.prefix;t.default=(0,v.default)(x.model,{namespace:"resource",state:{list:[],rightSiderFold:!0,rightSiderNodeId:"",selectedRowKeys:[],selectedRows:[],detailModalVisible:!1,types:{},typeDetail:{},selectedInstanceAttrs:[],metaAttrs:{},selectedMetaAttrs:[],selectedActionAttrs:[],rsc:{},rscRestrictionModalVisible:!1,restrictions:null,rscRestrictionModalTitle:"",rscMigrationModalVisible:!1,mainLockVisible:!1},subscriptions:{setup:function(e){var t=e.dispatch;e.history.listen(function(e){var r=e.pathname;"/resource"!==r&&"/"!==r||t({type:"firstQuery"}).then(function(){var e=window.localStorage.getItem(m+"autoReFreshId")?window.localStorage.getItem(m+"autoReFreshId"):"0",r=0;t({type:"cluster/queryHeartBeatStatus"}),"0"!==e&&(r=(0,w.triggerTimedTask)(t,e),t({type:"app/switchAutoReFreshState",payload:{autoReFreshId:e,autoReFreshTaskId:r}}))}).catch(function(e){"\u8bf7\u68c0\u67e5HA\u96c6\u7fa4\u662f\u5426\u5904\u4e8e\u542f\u52a8\u72b6\u6001\uff01"===e.message&&t({type:"updateState",payload:{mainLockVisible:!0}})})})}},effects:{firstQuery:p.default.mark(function e(t,r){var a,n,u=t.payload,s=r.call,c=r.put;return p.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,s(b.query,(0,l.parse)(u));case 2:if(a=e.sent,!(n=(0,w.getDrbdEnable)(a.data))){e.next=7;break}return e.next=7,c({type:"queryDrbdStatus"});case 7:return e.next=9,c({type:"updateState",payload:{rawlist:a.data}});case 9:return e.next=11,c({type:"preprocessingState"});case 11:case"end":return e.stop()}},e,this)}),query:p.default.mark(function e(t,r){var a,n,u=t.payload,s=r.call,c=r.put;return p.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.prev=0,e.next=3,s(b.query,(0,l.parse)(u));case 3:if(a=e.sent,!(n=(0,w.getDrbdEnable)(a.data))){e.next=8;break}return e.next=8,c({type:"queryDrbdStatus"});case 8:return e.next=10,c({type:"updateState",payload:{rawlist:a.data,mainLockVisible:!1}});case 10:return e.next=12,c({type:"preprocessingState"});case 12:e.next=19;break;case 14:if(e.prev=14,e.t0=e.catch(0),"\u8bf7\u68c0\u67e5HA\u96c6\u7fa4\u662f\u5426\u5904\u4e8e\u542f\u52a8\u72b6\u6001\uff01"!==e.t0.message){e.next=19;break}return e.next=19,c({type:"updateState",payload:{mainLockVisible:!0}});case 19:case"end":return e.stop()}},e,this,[[0,14]])}),create:p.default.mark(function e(t,r){var a=t.payload,n=r.call;return p.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,n(b.create,(0,l.parse)(a));case 2:return e.abrupt("return",e.sent);case 3:case"end":return e.stop()}},e,this)}),detail:p.default.mark(function e(t,r){var a,n,u,s,d,o,f,y=t.payload,h=r.call,v=r.put,x=r.select,w=r.take;return p.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,h(b.detail,(0,l.parse)(y));case 2:return a=e.sent,n=a.data,e.next=6,v({type:"updateState",payload:{rsc:n}});case 6:if(!n.meta_attributes){e.next=11;break}return u=[],(0,i.default)(n.meta_attributes).forEach(function(e){u.push(e)}),e.next=11,v({type:"updateState",payload:{selectedMetaAttrs:u}});case 11:if("primitive"===n.category){e.next=13;break}return e.abrupt("return",c.default.resolve());case 13:return e.next=15,v({type:"queryRscType",payload:{class:n.class,provider:n.provider,type:n.type}});case 15:return e.next=17,w("queryRscType/@@end");case 17:return e.next=19,x(function(e){return e.resource});case 19:if(s=e.sent,d=s.typeDetail,!n.instance_attributes){e.next=26;break}return o=[],d.parameters&&d.parameters.forEach(function(e){"1"!==e.required&&n.instance_attributes[e.name]&&o.push(e.name)}),e.next=26,v({type:"updateState",payload:{selectedInstanceAttrs:o}});case 26:if(!n.actions){e.next=31;break}return f=[],n.actions.forEach(function(e){f.push(e.name)}),e.next=31,v({type:"updateState",payload:{selectedActionAttrs:f}});case 31:return e.abrupt("return",c.default.resolve());case 32:case"end":return e.stop()}},e,this)}),update:p.default.mark(function e(t,r){var a=t.payload,n=r.call;return p.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,n(b.update,(0,l.parse)(a));case 2:return e.abrupt("return",e.sent);case 3:case"end":return e.stop()}},e,this)}),operate:p.default.mark(function e(t,r){var a=t.payload,n=r.call;return p.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,n(b.operate,(0,l.parse)(a));case 2:return e.abrupt("return",e.sent);case 3:case"end":return e.stop()}},e,this)}),queryRscTypes:p.default.mark(function e(t,r){var a,n=t.payload,u=r.call,s=r.put;return p.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,u(b.queryRscTypes,(0,l.parse)(n));case 2:return a=e.sent,e.next=5,s({type:"updateState",payload:{types:a.data}});case 5:case"end":return e.stop()}},e,this)}),queryRscType:p.default.mark(function e(t,r){var a,n=t.payload,u=r.call,s=r.put;return p.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,u(b.queryRscType,(0,l.parse)(n));case 2:return a=e.sent,(0,w.transformData)(a.data.parameters),e.next=6,s({type:"updateState",payload:{typeDetail:a.data}});case 6:return e.abrupt("return",c.default.resolve(a.data));case 7:case"end":return e.stop()}},e,this)}),queryRscAttrs:p.default.mark(function e(t,r){var a,n=t.payload,u=r.call,s=r.put;return p.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,u(b.queryRscAttrs,(0,l.parse)(n));case 2:return a=e.sent,(0,w.transformData)(a.data),e.next=6,s({type:"updateState",payload:{metaAttrs:a.data}});case 6:case"end":return e.stop()}},e,this)}),queryRscRestriction:p.default.mark(function e(t,r){var a,n=t.payload,u=r.call,s=r.put;return p.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,u(b.queryRscRestriction,(0,l.parse)(n));case 2:return a=e.sent,"location"===n.relation&&a.data.node_level.forEach(function(e){a.data[e.level]||(a.data[e.level]=[]),a.data[e.level].push(e.node)}),e.next=6,s({type:"updateState",payload:{restrictions:a.data}});case 6:case"end":return e.stop()}},e,this)}),queryDrbdStatus:p.default.mark(function e(t,r){var a,n=r.call,u=r.put;return p.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,n(b.queryDrbdStatus);case 2:return a=e.sent,e.next=5,u({type:"updateListWithDrbdStatus",payload:{drbdStatus:a.data.code,drbdMsg:a.data.message}});case 5:case"end":return e.stop()}},e,this)})},reducers:{clearSelectedRows:function(e){var t={selectedRowKeys:[],selectedRows:[]};return(0,u.default)({},e,t)},preprocessingState:function(e){var t=[],r=e.selectedRowKeys,a=e.selectedRows[0];return e.list=e.rawlist,e.list.forEach(function(e){a&&a.id===e.id&&(t=[e]),e.key=e.id,e.children=e.subrscs,e.children&&e.children.forEach(function(r){a&&a.id===r.id&&(t=[r]),r.isChild=!0,r.children=r.subrscs,r.key=r.id+"-"+e.id,r.children&&r.children.forEach(function(n){a&&a.id===n.id&&(t=[n]),n.isChild=!0,n.key=n.id+"-"+r.id+"-"+e.id})})}),0===t.length&&(r=[]),(0,u.default)({},e,{selectedRows:t,selectedRowKeys:r})},updateListWithDrbdStatus:function(e,t){var r=t.payload,a=r.drbdStatus,n=r.drbdMsg;return e.list.forEach(function(e){"0"===a||"group-fs-ps"!==e.id&&"ms-drbd"!==e.id||(e.drbdStatus=a,e.drbdMsg=n)}),(0,u.default)({},e)}}}),e.exports=t.default},1386:function(e,t,r){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0}),t.queryDrbdStatus=t.queryRscRestriction=t.create=t.queryRscAttrs=t.queryRscType=t.queryRscTypes=t.operate=t.update=t.detail=t.query=void 0;var n=r(119),u=a(n),s=r(291),c=a(s),d=(t.query=function(){var e=(0,c.default)(u.default.mark(function e(t){return u.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",(0,d.request)({url:o,method:"get",data:t}));case 1:case"end":return e.stop()}},e,this)}));return function(t){return e.apply(this,arguments)}}(),t.detail=function(){var e=(0,c.default)(u.default.mark(function e(t){return u.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",(0,d.request)({url:p,method:"get",data:t}));case 1:case"end":return e.stop()}},e,this)}));return function(t){return e.apply(this,arguments)}}(),t.update=function(){var e=(0,c.default)(u.default.mark(function e(t){return u.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",(0,d.request)({url:p,method:"put",data:t}));case 1:case"end":return e.stop()}},e,this)}));return function(t){return e.apply(this,arguments)}}(),t.operate=function(){var e=(0,c.default)(u.default.mark(function e(t){return u.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",(0,d.request)({url:p+"/:action",method:"put",data:t}));case 1:case"end":return e.stop()}},e,this)}));return function(t){return e.apply(this,arguments)}}(),t.queryRscTypes=function(){var e=(0,c.default)(u.default.mark(function e(t){return u.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",(0,d.request)({url:l,method:"get",data:t}));case 1:case"end":return e.stop()}},e,this)}));return function(t){return e.apply(this,arguments)}}(),t.queryRscType=function(){var e=(0,c.default)(u.default.mark(function e(t){return u.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",(0,d.request)({url:f,method:"get",data:t}));case 1:case"end":return e.stop()}},e,this)}));return function(t){return e.apply(this,arguments)}}(),t.queryRscAttrs=function(){var e=(0,c.default)(u.default.mark(function e(t){return u.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",(0,d.request)({url:y,method:"get",data:t}));case 1:case"end":return e.stop()}},e,this)}));return function(t){return e.apply(this,arguments)}}(),t.create=function(){var e=(0,c.default)(u.default.mark(function e(t){return u.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",(0,d.request)({url:o,method:"post",data:t}));case 1:case"end":return e.stop()}},e,this)}));return function(t){return e.apply(this,arguments)}}(),t.queryRscRestriction=function(){var e=(0,c.default)(u.default.mark(function e(t){return u.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",(0,d.request)({url:p+"/relations/:relation",method:"get",data:t}));case 1:case"end":return e.stop()}},e,this)}));return function(t){return e.apply(this,arguments)}}(),t.queryDrbdStatus=function(){var e=(0,c.default)(u.default.mark(function e(t){return u.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",(0,d.request)({url:h,method:"get",data:t}));case 1:case"end":return e.stop()}},e,this)}));return function(t){return e.apply(this,arguments)}}(),r(28)),i=d.config.api,o=i.resources,p=i.resource,l=i.rscTypes,f=i.rscType,y=i.rscAttrs,h=i.drbdStatus}});
\ No newline at end of file
webpackJsonp([5],{1382:function(e,t,r){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var n=r(119),u=a(n),o=r(192),s=r(292),c=a(s),p=r(1387),f=r(604);t.default=(0,c.default)(f.model,{namespace:"node",state:{list:[]},subscriptions:{setup:function(e){var t=e.dispatch;e.history.listen(function(e){var r=e.pathname;"/resource"!==r&&"/"!==r||t({type:"query"})})}},effects:{query:u.default.mark(function e(t,r){var a,n=t.payload,s=r.call,c=r.put;return u.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,s(p.query,(0,o.parse)(n));case 2:return a=e.sent,e.next=5,c({type:"updateState",payload:{list:a.data}});case 5:case"end":return e.stop()}},e,this)}),operate:u.default.mark(function e(t,r){var a=t.payload,n=r.call;return u.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,n(p.operate,(0,o.parse)(a));case 2:return e.abrupt("return",e.sent);case 3:case"end":return e.stop()}},e,this)}),operateLocal:u.default.mark(function e(t,r){var a=t.payload,n=r.call;return u.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,n(p.operateLocal,(0,o.parse)(a));case 2:return e.abrupt("return",e.sent);case 3:case"end":return e.stop()}},e,this)})}}),e.exports=t.default},1387:function(e,t,r){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0}),t.operateLocal=t.operate=t.query=void 0;var n=r(119),u=a(n),o=r(291),s=a(o),c=(t.query=function(){var e=(0,s.default)(u.default.mark(function e(t){return u.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",(0,c.request)({url:f,method:"get",data:t}));case 1:case"end":return e.stop()}},e,this)}));return function(t){return e.apply(this,arguments)}}(),t.operate=function(){var e=(0,s.default)(u.default.mark(function e(t){return u.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",(0,c.request)({url:i+"/:action",method:"put",data:t}));case 1:case"end":return e.stop()}},e,this)}));return function(t){return e.apply(this,arguments)}}(),t.operateLocal=function(){var e=(0,s.default)(u.default.mark(function e(t){return u.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",(0,c.request)({url:l+"/:action",method:"put",data:t}));case 1:case"end":return e.stop()}},e,this)}));return function(t){return e.apply(this,arguments)}}(),r(28)),p=c.config.api,f=p.nodes,i=p.node,l=p.localnodes}});
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="description" content=""><title>中标麒麟高可用集群软件</title><link href="/4.12.7/index.css?731286c3310697b9fe83" rel="stylesheet"></head><body><div id="root"></div><script type="text/javascript" src="/4.12.7/index.js?731286c3310697b9fe83"></script></body></html>
\ No newline at end of file
#!/usr/bin/python
# -*-coding:utf-8-*-
# coding: iso-8859-15
import unittest
import sys
sys.path.append('../')
from haclient-api import *
class TestCommandFunc(unittest.TestCase):
""" Test config func"""
# 获取指令执行结果
def test_get_command_result(self):
'''
{1: "crm_mon -1 -o", 2: "crm_simulate -Ls", 3: "pcs config show", 4: "corosync-cfgtool -s", 5: "crm configure verify"}
'''
get_commands_result(1)
# 获取指令列表
def test_get_commands_list(self):
get_commands_list()
if __name__ == '__main__':
unittest.main()
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册