diff --git a/ovm/scripts/vm/hypervisor/ovm/OvmCommonModule.py b/ovm/scripts/vm/hypervisor/ovm/OvmCommonModule.py index 511d8d30a53..ff99390a4d5 100755 --- a/ovm/scripts/vm/hypervisor/ovm/OvmCommonModule.py +++ b/ovm/scripts/vm/hypervisor/ovm/OvmCommonModule.py @@ -13,7 +13,8 @@ from OvmObjectModule import * import types import logging import popen2 -from OvmFaultConstants import toErrCode, dispatchErrCode, NoVmFoundException +import subprocess +from OvmFaultConstants import toErrCode, dispatchErrCode, NoVmFoundException, ShellExceutedFailedException from xmlrpclib import Fault as XmlRpcFault from OVSCommons import * from OvmLoggerModule import OvmLogger @@ -26,6 +27,7 @@ HEARTBEAT_DIR='heart_beat' ETC_HOSTS='/etc/hosts' HOSTNAME_FILE='/etc/sysconfig/network' OWNER_FILE_PREFIX='host_' +OCFS2_CONF='/etc/ocfs2/cluster.conf' logger = OvmLogger('OvmCommon') @@ -93,10 +95,18 @@ def BytesToM(bytes): def BytesToG(bytes): return bytes/(1024*1024*1024) +def runCmd(cmds): + process = subprocess.Popen(cmds, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = process.communicate() + if process.returncode != 0: + raise ShellExceutedFailedException(stderr, process.returncode) + return stdout + def doCmd(lst): cmds = [str(i) for i in lst] - logger.debug(doCmd, ' '.join(cmds)) - res = run_cmd(cmds) + cmdStr = ' '.join(cmds) + logger.debug(doCmd, cmdStr) + res = runCmd(cmdStr) logger.debug(doCmd, 'result:' + res) return res diff --git a/ovm/scripts/vm/hypervisor/ovm/OvmFaultConstants.py b/ovm/scripts/vm/hypervisor/ovm/OvmFaultConstants.py index 09d2b15f5b8..3a5f9b84ef8 100755 --- a/ovm/scripts/vm/hypervisor/ovm/OvmFaultConstants.py +++ b/ovm/scripts/vm/hypervisor/ovm/OvmFaultConstants.py @@ -4,10 +4,20 @@ OvmVmErrCodeStub = 2000 OvmStoragePoolErrCodeStub = 3000 OvmNetworkErrCodeStub = 4000 OvmVolumeErrCodeStub = 5000 +OvmOCFS2ErrCodeStub = 6000 class NoVmFoundException(Exception): pass +class ShellExceutedFailedException(Exception): + stderr = '' + errCode = -1000 + + def __init__(self, err, code): + Exception.__init__(self, "%s, return code:%s"%(err, code)) + self.stderr = err + self.errCode = code + errCode = { # OvmDispatch is not class, these error codes are reserved "OvmDispatch.InvalidCallMethodFormat":OvmDispatcherStub+1, @@ -55,6 +65,8 @@ errCode = { "OvmVolume.createDataDisk":OvmVolumeErrCodeStub+1, "OvmVolume.createFromTemplate":OvmVolumeErrCodeStub+2, "OvmVolume.destroy":OvmVolumeErrCodeStub+3, + + "OvmOCFS2._addNode":OvmOCFS2ErrCodeStub+1, } diff --git a/ovm/scripts/vm/hypervisor/ovm/OvmOCFS2Module.py b/ovm/scripts/vm/hypervisor/ovm/OvmOCFS2Module.py new file mode 100755 index 00000000000..ea2edd801da --- /dev/null +++ b/ovm/scripts/vm/hypervisor/ovm/OvmOCFS2Module.py @@ -0,0 +1,62 @@ +from OvmCommonModule import * + +logger = OvmLogger('OvmOCFS2') +class OvmOCFS2(OvmObject): + def _prepareConf(self, cluster): + conf = '''cluster: + node_count = 0 + name = %s + '''%cluster + dir = dirname(OCFS2_CONF) + if not isdir(dir): + os.makedirs(dir) + + fd = open(OCFS2_CONF, 'w') + fd.write(conf) + fd.close() + + def _addNode(self, name, nodeNum, ip, port, cluster, isOnline=True): + nodePath = '/sys/kernel/config/cluster/%s/node/%s'%(cluster, name) + if exists(nodePath): + logger.debug(OvmOCFS2._addNode, "node %s already exists, skip it(%s)"%(name, nodePath)) + return + + if not isOnline: + cmds = ['o2cb_ctl -C -n', name, '-t node', '-a number=%s'%nodeNum, '-a ip_address=%s'%ip, '-a ip_port=%s'%port, '-a cluster=%s'%cluster] + else: + cmds = ['o2cb_ctl -C -i -n', name, '-t node', '-a number=%s'%nodeNum, '-a ip_address=%s'%ip, '-a ip_port=%s'%port, '-a cluster=%s'%cluster] + + try: + doCmd(cmds) + except ShellExceutedFailedException, e: + if e.errCode == 239 or "already exists" in e.stderr: + logger.debug(OvmOCFS2._addNode, "node %s already exists, skip it(%s)"%(name, e.stderr)) + else: + raise e + + def _isClusterOnline(self, cluster): + cmds = ['service o2cb status', cluster] + res = doCmd(cmds) + for line in res.split('\n'): + if not 'Checking O2CB cluster' in line: continue + return not 'Offline' in line + + def _start(self, cluster): + #blank line are answer by clicking enter + cmd = ['service o2cb load'] + doCmd(cmd) + config=''' +y +o2cb +%s + + + + +EOF +'''%cluster + cmd = ['service o2cb configure', '< 255: raise Exception("%s nodes beyond maximum 255 allowed by OCFS2"%len(nodes)) - if compareClusterConfig(nodes): - logger.debug(OvmStoragePool.prepareOCFS2Nodes, "Nodes configure are the same, return") - rs = SUCC() - return rs - - lines = [] - for n in nodes: - lines.append("node:\n") - lines.append("\tip_port = %s\n" % "7777") - lines.append("\tip_address = %s\n" % n["ip_address"]) - lines.append("\tnumber = %s\n" % n["number"]) - lines.append("\tname = %s\n" % n["name"]) - lines.append("\tcluster = %s\n" % clusterName) - lines.append("\n") - lines.append("cluster:\n") - lines.append("\tnode_count = %d\n" % len(nodes)) - lines.append("\tname = %s\n" % clusterName) - lines.append("\n") - conf = "".join(lines) - configureHostName(nodes) configureEtcHosts(nodes) - clusterm_set_ocfs2_cluster_conf(conf) - clusterm_start_o2cb_service() - logger.debug(OvmStoragePool.prepareOCFS2Nodes, "Configure cluster.conf to:\n%s"%conf) + addNodes(nodes, clusterName) + OvmOCFS2()._start(clusterName) + fd = open(OCFS2_CONF, 'r') + conf = fd.readlines() + fd.close() + logger.debug(OvmStoragePool.prepareOCFS2Nodes, "Configure cluster.conf to:\n%s"%' '.join(conf)) rs = SUCC() return rs