summaryrefslogtreecommitdiffstats
path: root/src/com.gluster.storage.management.server.scripts
diff options
context:
space:
mode:
authorShireesh Anjal <shireesh@gluster.com>2011-04-26 20:09:44 +0530
committerShireesh Anjal <shireesh@gluster.com>2011-04-28 20:40:49 +0530
commit636888037a6fced0753e0095b61edf5fde771a2a (patch)
tree7d3be83529bfaa1f5a675ca8f26cc61453782f57 /src/com.gluster.storage.management.server.scripts
parentbeb2b3893fcde1be5fe1f272637dbdf3e7840287 (diff)
Story#34 - Volume logs
Diffstat (limited to 'src/com.gluster.storage.management.server.scripts')
-rw-r--r--src/com.gluster.storage.management.server.scripts/src/nodes/GlusterdUtils.py250
-rw-r--r--src/com.gluster.storage.management.server.scripts/src/nodes/VolumeUtils.py610
-rwxr-xr-xsrc/com.gluster.storage.management.server.scripts/src/nodes/get_volume_brick_log.py109
-rwxr-xr-xsrc/com.gluster.storage.management.server.scripts/src/nodes/get_volume_log.py132
4 files changed, 1101 insertions, 0 deletions
diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/GlusterdUtils.py b/src/com.gluster.storage.management.server.scripts/src/nodes/GlusterdUtils.py
new file mode 100644
index 00000000..7c0e899c
--- /dev/null
+++ b/src/com.gluster.storage.management.server.scripts/src/nodes/GlusterdUtils.py
@@ -0,0 +1,250 @@
+# Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+# This file is part of Gluster Storage Platform.
+#
+# Gluster Storage Platform is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 3 of
+# the License, or (at your option) any later version.
+#
+# Gluster Storage Platform is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+
+import os
+import Utils
+
+import ServerUtils
+
+
+def getGlusterVolumeInfo(volumeName=None):
+ volumeNameList = None
+ if Utils.isString(volumeName):
+ volumeNameList = [volumeName]
+ if type(volumeName) == type([]):
+ volumeNameList = volumeName
+
+ status = Utils.runCommand("gluster volume info", output=True, root=True)
+ if status["Status"] != 0:
+ Utils.log("Failed to execute 'gluster volume info' command")
+ return None
+
+ volumeInfoDict = {}
+ volumeInfo = {}
+ volumeName = None
+ brickList = []
+ for line in status['Stdout'].split("\n"):
+ if not line:
+ if volumeName and volumeInfo:
+ volumeInfo["Bricks"] = brickList
+ volumeInfoDict[volumeName] = volumeInfo
+ volumeInfo = {}
+ volumeName = None
+ brickList = []
+ continue
+
+ tokens = line.split(":")
+ if tokens[0].strip().upper() == "BRICKS":
+ continue
+ elif tokens[0].strip().upper() == "VOLUME NAME":
+ volumeName = tokens[1].strip()
+ volumeInfo["VolumeName"] = volumeName
+ elif tokens[0].strip().upper() == "TYPE":
+ volumeInfo["VolumeType"] = tokens[1].strip()
+ elif tokens[0].strip().upper() == "STATUS":
+ volumeInfo["VolumeStatus"] = tokens[1].strip()
+ elif tokens[0].strip().upper() == "TRANSPORT-TYPE":
+ volumeInfo["TransportType"] = tokens[1].strip()
+ elif tokens[0].strip().upper().startswith("BRICK"):
+ brickList.append(":".join(tokens[1:]).strip())
+
+ if volumeName and volumeInfo:
+ volumeInfoDict[volumeName] = volumeInfo
+
+ if not volumeNameList:
+ return volumeInfoDict
+
+ # remove unwanted volume info
+ for volumeName in list(set(volumeInfoDict.keys()) - set(volumeNameList)):
+ del volumeInfoDict[volumeName]
+
+ return volumeInfoDict
+
+
+def isVolumeRunning(volumeName):
+ if not volumeName:
+ return False
+ volumeInfo = getGlusterVolumeInfo(volumeName)
+ if not volumeInfo:
+ return False
+ status = volumeInfo[volumeName]["VolumeStatus"]
+ if not status:
+ return False
+ if status.upper() == "STARTED":
+ return True
+ return False
+
+
+def isVolumeExist(volumeName):
+ if not volumeName:
+ return False
+ if getGlusterVolumeInfo(volumeName):
+ return True
+ return False
+
+
+def peerProbe(serverName):
+ command = "gluster peer probe %s" % serverName
+ status = Utils.runCommand(command, output=True, root=True)
+ if status["Status"] == 0:
+ return True
+ Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"])))
+ return False
+
+
+def setAuthAllow(volumeName, authList, includeServers=True):
+ if not (volumeName and authList):
+ return False
+ vacl = []
+ if includeServers:
+ for serverName in ServerUtils.getAllServerList():
+ vacl += ServerUtils.getServerIpList(serverName)
+ vacl += authList
+
+ command = "gluster volume set %s auth.allow %s" % (volumeName, ",".join(list(set(vacl))))
+ status = Utils.runCommand(command, output=True, root=True)
+ if status["Status"] == 0:
+ return True
+ Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"])))
+ return False
+
+
+def volumeCreate(volumeName, volumeType, transportTypeList, brickList):
+ command = "gluster volume create %s" % volumeName
+
+ if volumeType.upper() == "MIRROR":
+ command += " replica 2"
+ elif volumeType.upper() == "STRIPE":
+ command += " stripe 4"
+
+ if "RDMA" in transportTypeList:
+ command += " transport rdma"
+
+ command += " " + " ".join(brickList)
+
+ status = Utils.runCommand(command, output=True, root=True)
+ if status["Status"] == 0:
+ return True
+ Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"])))
+ return False
+
+
+def volumeDelete(volumeName):
+ command = "gluster --mode=script volume delete %s" % volumeName
+ status = Utils.runCommand(command, output=True, root=True)
+ if status["Status"] == 0:
+ return True
+ Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"])))
+ return False
+
+
+def volumeLogFileName(volumeName, brick, logDir):
+ command = "gluster volume log filename %s %s %s" % (volumeName, brick, logDir)
+ status = Utils.runCommand(command, output=True, root=True)
+ if status["Status"] == 0:
+ return True
+ Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"])))
+ return False
+
+
+def startVolumeMigration(volumeName, sourcePath, destinationPath):
+ command = "gluster volume replace-brick %s %s %s start" % (volumeName, sourcePath, destinationPath)
+ status = Utils.runCommand(command, output=True, root=True)
+ if status["Status"] == 0:
+ lines = status["Stdout"].split("\n")
+ if lines[0].split()[-1] == "successfully":
+ return True
+ Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"])))
+ return False
+
+
+def stopVolumeMigration(volumeName, sourcePath, destinationPath):
+ command = "gluster volume replace-brick %s %s %s abort" % (volumeName, sourcePath, destinationPath)
+ status = Utils.runCommand(command, output=True, root=True)
+ if status["Status"] == 0:
+ lines = status["Stdout"].split("\n")
+ if lines[0].split()[-1] == "successful":
+ return True
+ Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"])))
+ return False
+
+
+def commitVolumeMigration(volumeName, sourcePath, destinationPath):
+ command = "gluster volume replace-brick %s %s %s commit" % (volumeName, sourcePath, destinationPath)
+ status = Utils.runCommand(command, output=True, root=True)
+ if status["Status"] == 0:
+ lines = status["Stdout"].split("\n")
+ if lines[0].split()[-1] == "successful":
+ return True
+ Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"])))
+ return False
+
+
+def getMigrationStatus(volumeName, sourcePath, destinationPath):
+ command = "gluster volume replace-brick %s %s %s status" % (volumeName, sourcePath, destinationPath)
+ status = Utils.runCommand(command, output=True, root=True)
+ if status['Status'] == 0 and status['Stdout']:
+ lines = status["Stdout"].split("\n")
+ if "Current file" in lines[0]:
+ return "started"
+ if "Migration complete" in lines[0]:
+ return "completed"
+ Utils.log("command [%s] returns unknown status:%s" % (command, lines[0]))
+ return "failed"
+ #if status['Status'] == 0 and status['Stdout']:
+ # for line in status['Stdout'].split('\n'):
+ # words = line.split()
+ # if words and words[0].upper() == "STATUS:":
+ # return " ".join(words[1:]).upper()
+ Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"])))
+ return None
+
+
+def volumeRebalanceStart(volumeName):
+ command = "gluster volume rebalance %s start" % volumeName
+ status = Utils.runCommand(command, output=True, root=True)
+ if status["Status"] == 0:
+ lines = status["Stdout"].split("\n")
+ if lines[0].split()[-1] == "successful":
+ return True
+ Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"])))
+ return False
+
+
+def volumeRebalanceStop(volumeName):
+ command = "gluster volume rebalance %s stop" % volumeName
+ status = Utils.runCommand(command, output=True, root=True)
+ if status["Status"] == 0:
+ lines = status["Stdout"].split("\n")
+ if lines[0].split()[0] == "stopped":
+ return True
+ Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"])))
+ return False
+
+
+def volumeRebalanceStatus(volumeName):
+ command = "gluster volume rebalance %s status" % volumeName
+ status = Utils.runCommand(command, output=True, root=True)
+ if status["Status"] == 0:
+ lines = status["Stdout"].split("\n")
+ if "rebalance not started" in lines[0]:
+ return "not started"
+ if "rebalance completed" in lines[0]:
+ return "completed"
+ return "running"
+ Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"])))
+ return False
diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/VolumeUtils.py b/src/com.gluster.storage.management.server.scripts/src/nodes/VolumeUtils.py
new file mode 100644
index 00000000..a19ccd62
--- /dev/null
+++ b/src/com.gluster.storage.management.server.scripts/src/nodes/VolumeUtils.py
@@ -0,0 +1,610 @@
+# Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+# This file is part of Gluster Storage Platform.
+#
+# Gluster Storage Platform is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 3 of
+# the License, or (at your option) any later version.
+#
+# Gluster Storage Platform is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+
+import os
+import glob
+import tempfile
+from operator import itemgetter
+import Globals
+from Protocol import *
+from Utils import *
+from DiskUtils import *
+from ServerUtils import *
+import GlusterdUtils as Glusterd
+
+
+def isVolumeExist(volumeName):
+ volumeDom = XDOM()
+ return volumeDom.parseFile("%s/%s.xml" % (Globals.VOLUME_CONF_DIR, volumeName)) and \
+ Glusterd.isVolumeExist(volumeName)
+
+
+def getVolumeUuid(volumeName):
+ fileName = "%s/%s.xml" % (Globals.VOLUME_CONF_DIR, volumeName)
+ volumeDom = XDOM()
+ if not volumeDom.parseFile(fileName):
+ log("Failed to parse volume configuration file %s of %s" % (fileName, volumeName))
+ return None
+ return volumeDom.getTextByTagRoute("uuid")
+
+
+def readVolumeSmbConfFile(fileName=Globals.VOLUME_SMBCONF_FILE):
+ entryList = []
+ try:
+ fp = open(fileName)
+ for line in fp:
+ tokens = line.split("#")[0].strip().split(";")[0].strip().split("=")
+ if len(tokens) != 2:
+ continue
+ if tokens[0].strip().upper() == "INCLUDE":
+ entryList.append(tokens[1].strip())
+ fp.close()
+ except IOError, e:
+ log("Failed to open file %s: %s" % (fileName, str(e)))
+ return entryList
+
+
+def writeVolumeSmbConfFile(entryList, fileName=Globals.VOLUME_SMBCONF_FILE):
+ try:
+ fp = open(fileName, "w")
+ for entry in entryList:
+ fp.write("include = %s\n" % entry)
+ fp.close()
+ return True
+ except IOError, e:
+ log("Failed to write file %s: %s" % (fileName, str(e)))
+ return False
+
+
+def includeVolume(volumeName, fileName=Globals.VOLUME_SMBCONF_FILE):
+ volumeFile = "%s/%s.smbconf" % (Globals.VOLUME_CONF_DIR, volumeName)
+ if not os.path.exists(volumeFile):
+ return False
+ entryList = readVolumeSmbConfFile(fileName)
+ if volumeFile in entryList:
+ return True
+ entryList.append(volumeFile)
+ return writeVolumeSmbConfFile(entryList, fileName)
+
+
+def excludeVolume(volumeName, fileName=Globals.VOLUME_SMBCONF_FILE):
+ volumeFile = "%s/%s.smbconf" % (Globals.VOLUME_CONF_DIR, volumeName)
+ if not os.path.exists(volumeFile):
+ return False
+ entryList = readVolumeSmbConfFile(fileName)
+ if volumeFile not in entryList:
+ return True
+ entryList.remove(volumeFile)
+ log("entryList = %s" % entryList)
+ return writeVolumeSmbConfFile(entryList, fileName)
+
+
+def writeVolumeCifsConfiguration(volumeName, userList, adminUser=None):
+ volumeFile = "%s/%s.smbconf" % (Globals.VOLUME_CONF_DIR, volumeName)
+ try:
+ fp = open(volumeFile, "w")
+ fp.write("[%s]\n" % volumeName)
+ fp.write(" comment = %s volume served by Gluster\n" % volumeName)
+ fp.write(" path = %s/%s\n" % (Globals.CIFS_EXPORT_DIR, volumeName))
+ fp.write(" guest ok = yes\n")
+ fp.write(" public = yes\n")
+ fp.write(" writable = yes\n")
+ if adminUser:
+ fp.write(" admin users = %s, %s\n" % (adminUser, ", ".join(userList)))
+ fp.write(" valid users = %s, %s\n" % (adminUser, ", ".join(userList)))
+ else:
+ fp.write(" admin users = %s\n" % (", ".join(userList)))
+ fp.write(" valid users = %s\n" % (", ".join(userList)))
+ fp.close()
+ return True
+ except IOError, e:
+ log("Failed to write file %s: %s" % (volumeFile, str(e)))
+ return False
+
+
+def removeVolumeCifsConfiguration(volumeName):
+ volumeFile = "%s/%s.smbconf" % (Globals.VOLUME_CONF_DIR, volumeName)
+ try:
+ os.remove(volumeFile)
+ except OSError, e:
+ log("Failed to remove file %s: %s" % (volumeFile, str(e)))
+
+
+def getVolumeListByPartitionName(partitionName):
+ volumeConfigFileList = glob.glob(Globals.VOLUME_CONF_DIR + "/*.xml")
+ if not volumeConfigFileList:
+ return None
+
+ volumeList = []
+ for volumeXmlFile in volumeConfigFileList:
+ volumeDom = XDOM()
+ volumeDom.parseFile(volumeXmlFile)
+ serverTopology = volumeDom.getElementsByTagRoute("volume.topology.group")
+ serverPartitionFound = False
+ for topology in serverTopology:
+ partitionDom = XDOM()
+ for partition in topology.getElementsByTagName("partition"):
+ partitionDom.setDomObj(partition)
+ if partitionDom.getTextByTagRoute("name") == partitionName:
+ serverPartitionFound = True
+ break
+ if serverPartitionFound:
+ volumeList.append(volumeDom.getElementsByTagRoute("volume")[0])
+ break
+ return volumeList
+
+
+def addServerPartitionConfig(inputDom, groupOrder, partitionTag):
+ if not(inputDom and groupOrder and partitionTag):
+ return False
+ groupDom = XDOM()
+ for group in inputDom.getElementsByTagRoute("topology.group"):
+ groupDom.setDomObj(group)
+ order = groupDom.getTextByTagRoute("order")
+ if order and int(order) == groupOrder:
+ group.appendChild(partitionTag)
+ return inputDom
+ return False
+
+
+def removeServerPartitionConfig(inputDom, partitionName):
+ if not(inputDom and partitionName):
+ return False
+ for group in inputDom.getElementsByTagRoute("topology.group"):
+ partitionDom = XDOM()
+ for partition in group.getElementsByTagName("partition"):
+ partitionDom.setDomObj(partition)
+ if partitionDom.getTextByTagRoute("name") == partitionName:
+ group.removeChild(partition)
+ return inputDom
+ return False
+
+
+def updateServerPartitionConfig(inputDom, partitionName, partitionTag):
+ if not(inputDom and partitionName and partitionTag):
+ return False
+ for group in inputDom.getElementsByTagRoute("topology.group"):
+ partitionDom = XDOM()
+ for partition in group.getElementsByTagName("partition"):
+ partitionDom.setDomObj(partition)
+ if partitionDom.getTextByTagRoute("name") == partitionName:
+ try:
+ group.replaceChild(partitionTag, partition)
+ return inputDom
+ except AttributeError:
+ return False
+ return False
+
+
+def getServerPartitionConfigUuid(serverGroupList, serverPartition):
+ for group in serverGroupList:
+ if not group:
+ continue
+ partitionDom = XDOM()
+ for partition in group.getElementsByTagName("partition"):
+ partitionDom.setDomObj(partition)
+ partitionName = partition.getTextByTagName("name")
+ if not partitionName:
+ continue
+ if partitionName == serverPartition:
+ return partitionDom.getTextByTagName("uuid")
+ return False
+
+
+def setServerPartitionConfigProperty(inputDom, partitionName, propertyDict):
+ if not(inputDom and partitionName and propertyDict):
+ return False
+ for group in inputDom.getElementsByTagRoute("topology.group"):
+ partitionDom = XDOM()
+ for partition in group.getElementsByTagName("partition"):
+ partitionDom.setDomObj(partition)
+ if partitionDom.getTextByTagRoute("name") == partitionName:
+ for part in propertyDict.keys():
+ x = partition.getElementsByTagName(part)
+ if x:
+ x[0].childNodes[0].nodeValue = propertyDict[part]
+ return inputDom
+ return False
+
+
+def getSortedServerPartitionConfigProperty(inputDom):
+ groupDict = {}
+ if not inputDom:
+ return None
+ groupDom = XDOM()
+ for group in inputDom.getElementsByTagRoute("topology.group"):
+ groupDom.setDomObj(group)
+ groupOrder = groupDom.getTextByTagRoute("order")
+ if not groupOrder:
+ return None
+ groupOrder = int(groupOrder)
+ if groupOrder < 1:
+ return None
+ partitionDom = XDOM()
+ partitionDict = {}
+ for partition in group.getElementsByTagName("partition"):
+ partitionDom.setDomObj(partition)
+ partitionName = partitionDom.getTextByTagRoute("name")
+ if not partitionName:
+ return None
+ partitionOrder = partitionDom.getTextByTagRoute("order")
+ if not partitionOrder:
+ return None
+ partitionUuid = partitionDom.getTextByTagRoute("uuid")
+ partitionOrder = int(partitionOrder)
+ if partitionOrder < 1:
+ return None
+ partitionDetails = partitionName.split(":")
+ if not partitionDetails or len(partitionDetails) < 1:
+ return None
+ partitionDict[partitionOrder] = { "order":partitionOrder,
+ "servername":partitionDetails[0],
+ "name":partitionDetails[1],
+ "uuid":partitionUuid}
+ groupDict[groupOrder] = partitionDict
+
+ serverList = []
+ groupOrderList = groupDict.keys()
+ groupOrderList.sort()
+ for groupOrder in groupOrderList:
+ partitionOrderList = groupDict[groupOrder].keys()
+ partitionOrderList.sort()
+ for partitionOrder in partitionOrderList:
+ serverList.append(groupDict[groupOrder][partitionOrder])
+
+ return serverList
+
+
+def getSortedServerPartitionList(serverGroupElements):
+ serverPartitionDict = {}
+ groupOrderList = []
+ serverList = []
+ partitionDom = XDOM()
+ for group in serverGroupElements:
+ if not group:
+ continue
+ groupOrderE = group.getElementsByTagName("order")
+ if not (groupOrderE and groupOrderE[0].childNodes):
+ return None
+ value = int(XDOM.getText(groupOrderE[0].childNodes))
+ if value > 0:
+ groupOrderList.append(value)
+ partitionDict = {}
+ for partition in group.getElementsByTagName("partition"):
+ partitionDom.setDomObj(partition)
+
+ partitionName = partitionDom.getTextByTagRoute("name")
+ if not partitionName:
+ return None
+ partitionOrder = partitionDom.getTextByTagRoute("order")
+ if not partitionOrder:
+ return None
+ partitionUuid = partitionDom.getTextByTagRoute("uuid")
+ partitionDict[int(partitionOrder)] = [partitionName, partitionUuid]
+ serverPartitionDict[value] = partitionDict
+ groupOrderList.sort()
+
+ for groupOrder in groupOrderList:
+ items = serverPartitionDict[groupOrder].items()
+ items.sort(key = itemgetter(0))
+ serverList = serverList + [ items[i][1] for i in range(0,len(items))]
+ return serverList
+
+
+def clearExportDirectory(serverList, volumeName, volumeUuid):
+ thisServerName = getCurrentServerName()
+ for exportServer in serverList:
+ serverName, partition = exportServer[0].split(":")
+ if thisServerName != serverName:
+ continue
+ partitionUuid = getUuidByDiskPartition(getDevice(partition))
+ if not partitionUuid:
+ log("unable to find uuid of partition %s" % partition)
+ return False
+ volumeDirName = "%s/%s/%s" % (Globals.GLUSTER_LUN_DIR, partitionUuid, volumeUuid)
+ if os.path.exists(volumeDirName):
+ ## Removing /data/PARTITION-UUID/VOLUME-UUID/
+ ## TODO: Get an option to remove it at this time
+ if runCommandFG("mv -f %s %s.delete" % (volumeDirName, volumeDirName), root=True) != 0:
+ return False
+ if runCommandFG("rm -f %s/%s/volumes/%s" % (Globals.GLUSTER_LUN_DIR, partitionUuid, volumeName), root=True) != 0:
+ return False
+ return True
+
+
+def createExportDirectory(serverList, volumeName, volumeUuid):
+ thisServerName = getCurrentServerName()
+ tempVolumeNameFile = getTempFileName()
+
+ try:
+ fp = open(tempVolumeNameFile, "w")
+ fp.write("VOLUME_NAME=%s\n" % volumeName)
+ fp.write("VOLUME_UUID=%s\n" % volumeUuid)
+ fp.close()
+ except IOError, e:
+ log("failed to create temporary file for volume-name: %s" % (volumeName, str(e)))
+ return False
+
+ for exportServer in serverList:
+ serverName, partition = exportServer[0].split(":")
+ if thisServerName != serverName:
+ continue
+ partitionUuid = getUuidByDiskPartition(getDevice(partition))
+ if not partitionUuid:
+ log("unable to find uuid of partition %s" % partition)
+ return False
+
+ volumeDirName = "%s/%s/%s" % (Globals.GLUSTER_LUN_DIR, partitionUuid, volumeUuid)
+ ## Creating /data/PARTITION-UUID/VOLUME-UUID/
+ if runCommandFG("mkdir %s" % volumeDirName, root=True) != 0:
+ return False
+
+ ## Creating /data/PARTITION-UUID/VOLUME-UUID/exports/
+ ## Creating /data/PARTITION-UUID/VOLUME-UUID/exports/brick1/
+ if runCommandFG("mkdir -p %s/exports/brick1" % volumeDirName, root=True) != 0:
+ return False
+
+ ## Creating /data/PARTITION-UUID/VOLUME-UUID/log/
+ if runCommandFG("mkdir %s/log" % volumeDirName, root=True) != 0:
+ return False
+
+ ## Creating /data/PARTITION-UUID/VOLUME-UUID/config/
+ if runCommandFG("mkdir %s/config" % volumeDirName, root=True) != 0:
+ return False
+
+ volumeLinkDirName = "%s/%s/volumes" % (Globals.GLUSTER_LUN_DIR, partitionUuid)
+ if not os.path.exists(volumeLinkDirName):
+ if runCommandFG("mkdir %s" % volumeLinkDirName, root=True) != 0:
+ return False
+
+ ## Creating symlink
+ ## /data/PARTITION-UUID/volumes/VOLUME-NAME -> /data/PARTITION-UUID/VOLUME-UUID/
+ command = "ln -fTs %s %s/%s" % (volumeDirName,
+ volumeLinkDirName, volumeName)
+ if runCommandFG(command, root=True) != 0:
+ return False
+
+ if runCommandFG("cp -f %s %s/config/volume-name" % (tempVolumeNameFile, volumeDirName), root=True) != 0:
+ return False
+
+ try:
+ os.remove(tempVolumeNameFile)
+ except OSError, e:
+ log("Failed to remove file %s: %s" % (tempVolumeNameFile, str(e)))
+
+ return True
+
+
+def getPartitionListByServerName(volumeDom, serverName, serverPartitionList=None):
+ partitionList = {}
+ if serverPartitionList:
+ for partitionName in serverPartitionList:
+ partitionUuid = getServerDiskPartitionUuid(serverName, partitionName)
+ if not partitionUuid:
+ log(syslog.LOG_ERR, "failed to get disk partition %s uuid of server %s" % (partitionName, serverName))
+ return None
+ partitionList[partitionName] = partitionUuid
+ return partitionList
+ for group in volumeDom.getElementsByTagRoute("topology.group"):
+ for partitionTag in group.getElementsByTagName("partition"):
+ nameE = partitionTag.getElementsByTagName("name")
+ if not nameE:
+ continue
+ partition = XDOM.getText(nameE[0].childNodes)
+ if not partition:
+ continue
+ server, partitionName = partition.split(":")
+ if server != serverName:
+ continue
+ partitionUuid = getServerDiskPartitionUuid(serverName, partitionName)
+ if not partitionUuid:
+ log(syslog.LOG_ERR, "failed to get disk partition %s uuid of server %s" % (partitionName, serverName))
+ return None
+ partitionList[partitionName] = partitionUuid
+ return partitionList
+
+
+def isVolumeRunning(volumeName):
+ return Glusterd.isVolumeRunning(volumeName)
+
+def addVolumeMigrationDetails(sourcePartition, destinationPartition, volumeName):
+ migrationDom = XDOM()
+ if not os.path.exists(Globals.VOLUME_MIGRATION_LIST_FILE):
+ migrationDom.appendTagRoute("volume-migration")
+ else:
+ if not migrationDom.parseFile(Globals.VOLUME_MIGRATION_LIST_FILE):
+ log("Failed to load volume-migration.xml file")
+ return None
+ migrationList = migrationDom.getElementsByTagRoute("volume-migration.migration")
+ for tagE in migrationList:
+ dom = XDOM()
+ dom.setDomObj(tagE)
+ if dom.getTextByTagRoute("source-partition") == sourcePartition and \
+ dom.getTextByTagRoute("destination-partition") == destinationPartition and \
+ dom.getTextByTagRoute("volume-name") == volumeName:
+ return False
+ migrationTag = migrationDom.getElementsByTagRoute("volume-migration")
+ if not migrationTag:
+ return None
+ partitionTag = migrationDom.createTag("migration")
+ partitionTag.appendChild(migrationDom.createTag("source-partition", sourcePartition))
+ partitionTag.appendChild(migrationDom.createTag("destination-partition", destinationPartition))
+ partitionTag.appendChild(migrationDom.createTag("volume-name", volumeName))
+ migrationTag[0].appendChild(partitionTag)
+ if not migrationDom.writexml(Globals.VOLUME_MIGRATION_LIST_FILE):
+ log("Unable to write disk migration details into %s/volume-migration.xml" % Globals.GLUSTER_BASE_DIR)
+ return False
+ return True
+
+
+def removeVolumeMigrationDetails(sourcePartition, destinationPartition, volumeName):
+ migrationDom = XDOM()
+ if not os.path.exists(Globals.VOLUME_MIGRATION_LIST_FILE):
+ return None
+ if not migrationDom.parseFile(Globals.VOLUME_MIGRATION_LIST_FILE):
+ log("Failed to load volume-migration.xml file")
+ return None
+ migrationList = migrationDom.getElementsByTagRoute("volume-migration.migration")
+ for tagE in migrationList:
+ dom = XDOM()
+ dom.setDomObj(tagE)
+ if dom.getTextByTagRoute("source-partition") == sourcePartition and \
+ dom.getTextByTagRoute("destination-partition") == destinationPartition and \
+ dom.getTextByTagRoute("volume-name") == volumeName:
+ migrationDom.getElementsByTagRoute("volume-migration")[0].removeChild(tagE)
+ if not migrationDom.writexml(Globals.VOLUME_MIGRATION_LIST_FILE):
+ log("Unable to write disk migration details into %s/volume-migration.xml" % Globals.GLUSTER_BASE_DIR)
+ return False
+ return True
+
+
+def addPartitionMigrationDetails(sourcePartition, destinationPartition, volumeList=None):
+ migrationDom = XDOM()
+ if not os.path.exists(Globals.MIGRATE_PARTITION_LIST_FILE):
+ migrationDom.appendTagRoute("partition-migration")
+ else:
+ if not migrationDom.parseFile(Globals.MIGRATE_PARTITION_LIST_FILE):
+ log("Failed to load migration.xml file")
+ return None
+ migrationList = migrationDom.getElementsByTagRoute("partition-migration.migration")
+ for tagE in migrationList:
+ dom = XDOM()
+ dom.setDomObj(tagE)
+ if dom.getTextByTagRoute("source-partition") == sourcePartition:
+ return False
+ if dom.getTextByTagRoute("destination-partition") == destinationPartition:
+ return False
+ migrationTag = migrationDom.getElementsByTagRoute("partition-migration")
+ if not migrationTag:
+ return None
+ partitionTag = migrationDom.createTag("migration")
+ partitionTag.appendChild(migrationDom.createTag("source-partition", sourcePartition))
+ partitionTag.appendChild(migrationDom.createTag("destination-partition", destinationPartition))
+ migrationTag[0].appendChild(partitionTag)
+ if not migrationDom.writexml(Globals.MIGRATE_PARTITION_LIST_FILE):
+ log("Unable to write disk migration details into %s/migration.xml" % Globals.GLUSTER_BASE_DIR)
+ return False
+ if volumeList:
+ for volumeName in volumeList:
+ addVolumeMigrationDetails(sourcePartition, destinationPartition, volumeName)
+ return True
+
+
+def removePartitionMigrationDetails(sourcePartition, destinationPartition, volumeList=None):
+ migrationDom = XDOM()
+ if not os.path.exists(Globals.MIGRATE_PARTITION_LIST_FILE):
+ return None
+ if not migrationDom.parseFile(Globals.MIGRATE_PARTITION_LIST_FILE):
+ log("Failed to load migration.xml file")
+ return None
+ migrationList = migrationDom.getElementsByTagRoute("partition-migration.migration")
+ for tagE in migrationList:
+ dom = XDOM()
+ dom.setDomObj(tagE)
+ if dom.getTextByTagRoute("source-partition") == sourcePartition and \
+ dom.getTextByTagRoute("destination-partition") == destinationPartition:
+ migrationDom.getElementsByTagRoute("partition-migration")[0].removeChild(tagE)
+ if not migrationDom.writexml(Globals.MIGRATE_PARTITION_LIST_FILE):
+ log("Unable to write disk migration details into %s/migration.xml" % Globals.GLUSTER_BASE_DIR)
+ return False
+ if volumeList:
+ for volumeName in volumeList:
+ removeVolumeMigrationDetails(sourcePartition, destinationPartition, volumeName)
+ return True
+
+
+def isMigrationInProgress(partition):
+ migrationDom = XDOM()
+ if not os.path.exists(Globals.MIGRATE_PARTITION_LIST_FILE):
+ return None
+ if not migrationDom.parseFile(Globals.MIGRATE_PARTITION_LIST_FILE):
+ log("Failed to load migration.xml file")
+ return None
+ migrationList = migrationDom.getElementsByTagRoute("partition-migration.migration")
+ for tagE in migrationList:
+ dom = XDOM()
+ dom.setDomObj(tagE)
+ if migrationDom.getTextByTagRoute("source-partition") == partition or \
+ migrationDom.getTextByTagRoute("destination-partition") == partition:
+ return True
+ return False
+
+
+def getServerDiskPartitionUuid(serverName, partition):
+ diskConfigDom = XDOM()
+ if not diskConfigDom.parseFile("%s/%s/disk.xml" % (Globals.SERVER_CONF_DIR, serverName)):
+ return None
+ for disk in diskConfigDom.getElementsByTagRoute("disks.disk"):
+ diskDom = XDOM()
+ diskDom.setDomObj(disk)
+ partitionList = diskDom.getElementsByTagRoute("partition")
+ for tagE in partitionList:
+ partitionDom = XDOM()
+ partitionDom.setDomObj(tagE)
+ if partitionDom.getTextByTagRoute("device") == partition:
+ return partitionDom.getTextByTagRoute("uuid")
+
+
+def getVolumeServerList(requestDom, requestFlag=True):
+ if requestFlag:
+ serverGroupElementList = requestDom.getElementsByTagRoute("command.volume.topology.group")
+ else:
+ serverGroupElementList = requestDom.getElementsByTagRoute("volume.topology.group")
+ if not serverGroupElementList:
+ return None
+ serverList = []
+ partitionDom = XDOM()
+ for group in serverGroupElementList:
+ for partition in group.getElementsByTagName("partition"):
+ partitionDom.setDomObj(partition)
+ partitionName = partitionDom.getTextByTagRoute("name")
+ if not partitionName:
+ continue
+ serverPartition = partitionName.split(":")
+ if not(len(serverPartition) > 1 and serverPartition[1]):
+ return None
+ if serverPartition[0] not in serverList:
+ serverList.append(serverPartition[0])
+ return serverList
+
+
+def getVolumeServerListByName(volumeName):
+ serverList = []
+ serverDom = XDOM()
+ volumeDom = XDOM()
+ if not os.path.exists("%s/%s.xml" % (Globals.VOLUME_CONF_DIR, volumeName)):
+ return False
+ if not volumeDom.parseFile("%s/%s.xml" % (Globals.VOLUME_CONF_DIR, volumeName)):
+ return False
+ return getVolumeServerList(volumeDom, False)
+
+
+def getMigrateVolumeServerPartitionInfo(volumeName):
+ volumeMigrationDom = XDOM()
+ if not volumeMigrationDom.parseFile(Globals.VOLUME_MIGRATION_LIST_FILE):
+ Utils.log("Failed to parse file %s" % Globals.VOLUME_MIGRATION_LIST_FILE)
+ return None
+ volumeInfo = {}
+ dom = XDOM()
+ for tagE in volumeMigrationDom.getElementsByTagRoute("volume-migration.migration"):
+ dom.setDomObj(tagE)
+ if dom.getTextByTagRoute("volume-name") == volumeName:
+ volumeInfo['Name'] = volumeName
+ volumeInfo['SourcePartition'] = dom.getTextByTagRoute("source-partition")
+ volumeInfo['DestinationPartition'] = dom.getTextByTagRoute("destination-partition")
+ return volumeInfo
+ return None
diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/get_volume_brick_log.py b/src/com.gluster.storage.management.server.scripts/src/nodes/get_volume_brick_log.py
new file mode 100755
index 00000000..7c912412
--- /dev/null
+++ b/src/com.gluster.storage.management.server.scripts/src/nodes/get_volume_brick_log.py
@@ -0,0 +1,109 @@
+#!/usr/bin/python
+# Copyright (C) 2009,2010 Gluster, Inc. <http://www.gluster.com>
+# This file is part of Gluster Storage Platform.
+#
+# Gluster Storage Platform is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 3 of
+# the License, or (at your option) any later version.
+#
+# Gluster Storage Platform is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+
+import re
+import os
+import sys
+from XmlHandler import ResponseXml
+
+def enumLogType(logCode):
+ if "M" == logCode.upper():
+ return "EMERGENCY"
+ elif "A" == logCode.upper():
+ return "ALERT"
+ elif "C" == logCode.upper():
+ return "CRITICAL"
+ elif "E" == logCode.upper():
+ return "ERROR"
+ elif "W" == logCode.upper():
+ return "WARNING"
+ elif "N" == logCode.upper():
+ return "NOTICE"
+ elif "I" == logCode.upper():
+ return "INFO"
+ elif "D" == logCode.upper():
+ return "DEBUG"
+ elif "T" == logCode.upper():
+ return "TRACE"
+ else:
+ return "UNKNOWN"
+##--end of enumLogType()
+
+def addLog(responseDom, logMessageTag, loginfo):
+ logTag = responseDom.createTag("logMessage", None)
+ logTag.appendChild(responseDom.createTag("timestamp", loginfo[0] + " " + loginfo[1]))
+ logTag.appendChild(responseDom.createTag("severity", enumLogType(loginfo[2])))
+ logTag.appendChild(responseDom.createTag("message", loginfo[3]))
+ logMessageTag.appendChild(logTag)
+ return True
+##--end of addLog()
+
+def logSplit(log):
+ loginfo = log.strip().split(None, 3)
+ loginfo[0] = loginfo[0][1:] #-- Remove '['
+ loginfo[1] = loginfo[1][0:-1] #-- Remove ']'
+ return loginfo
+##--end of logSplit()
+
+def getVolumeLog(logFilePath, tailCount):
+ rs = ResponseXml()
+ if not logFilePath:
+ rs.appendTagRoute("status.code", "-1")
+ rs.appendTagRoute("status.message", "No log file path given")
+ return rs.toprettyxml()
+
+ if not tailCount:
+ rs.appendTagRoute("status.code", "-1")
+ rs.appendTagRoute("status.message", "No tail count given")
+ return rs.toprettyxml()
+
+ pattern = '\[\d{4}-\d{2}-\d{2}\s{1}\d{2}:\d{2}:\d{2}.\d+\]\s{1}([MACEWNIDT]){1}\s+'
+ logMessagesTag = rs.createTag("logMessages")
+ if not os.path.exists(logFilePath):
+ rs.appendTagRoute("status.code", "-1")
+ rs.appendTagRoute("status.message", "volume log file [%s] not found!" % logFilePath)
+ return rs.toprettyxml
+
+ fp = open(logFilePath)
+ #lines = [line for line in fp]
+ lines = [line for line in fp if re.match(pattern, line)]
+ fp.close()
+ i = len(lines) - int(tailCount)
+ if i < 0:
+ i = 0
+ for log in lines[i:]:
+ loginfo = logSplit(log)
+ addLog(rs, logMessagesTag, loginfo)
+ rs.appendTagRoute("status.code", "0")
+ rs.appendTagRoute("status.message", "Success")
+ rs.appendTag(logMessagesTag)
+ return rs.toprettyxml()
+##--end of getVolumeLog()
+
+def main():
+ if len(sys.argv) != 3:
+ print >> sys.stderr, "usage: %s <Log File Path> <Line Count>" % sys.argv[0]
+ sys.exit(-1)
+
+ logFilePath = sys.argv[1]
+ tailCount = sys.argv[2]
+ print getVolumeLog(logFilePath, tailCount)
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/get_volume_log.py b/src/com.gluster.storage.management.server.scripts/src/nodes/get_volume_log.py
new file mode 100755
index 00000000..826ade6e
--- /dev/null
+++ b/src/com.gluster.storage.management.server.scripts/src/nodes/get_volume_log.py
@@ -0,0 +1,132 @@
+# Copyright (C) 2009,2010 Gluster, Inc. <http://www.gluster.com>
+# This file is part of Gluster Storage Platform.
+#
+# Gluster Storage Platform is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 3 of
+# the License, or (at your option) any later version.
+#
+# Gluster Storage Platform is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+
+import Globals
+import syslog
+import Commands
+import Utils
+from VolumeUtils import *
+from XmlHandler import ResponseXml
+
+
+def enumLogType(logCode):
+ if "M" == logCode.upper():
+ return "EMERGENCY"
+ elif "A" == logCode.upper():
+ return "ALERT"
+ elif "C" == logCode.upper():
+ return "CRITICAL"
+ elif "E" == logCode.upper():
+ return "ERROR"
+ elif "W" == logCode.upper():
+ return "WARNING"
+ elif "N" == logCode.upper():
+ return "NOTICE"
+ elif "I" == logCode.upper():
+ return "INFO"
+ elif "D" == logCode.upper():
+ return "DEBUG"
+ elif "T" == logCode.upper():
+ return "TRACE"
+ else:
+ return "UNKNOWN"
+##--end of enumLogType()
+
+
+def addLog(responseDom, logMessageTag, loginfo):
+ logTag = responseDom.createTag("log", None)
+ logTag.appendChild(responseDom.createTag("date", loginfo[0]))
+ logTag.appendChild(responseDom.createTag("time", loginfo[1]))
+ logTag.appendChild(responseDom.createTag("type", enumLogType(loginfo[2])))
+ logTag.appendChild(responseDom.createTag("message", loginfo[3]))
+ logMessageTag.appendChild(logTag)
+ return True
+##--end of addLog()
+
+
+def logSplit(log):
+ loginfo = log.strip().split(None, 3)
+ loginfo[0] = loginfo[0][1:] #-- Remove '['
+ loginfo[1] = loginfo[1][0:-1] #-- Remove ']'
+ return loginfo
+##--end of logSplit()
+
+
+def getVolumeLog(volumeName, tailCount):
+ rs = ResponseXml()
+ if not volumeName:
+ rs.appendTagRoute("status.code", "-1")
+ rs.appendTagRoute("status.message", "No volume name given")
+ return rs.toprettyxml()
+
+ if not tailCount:
+ rs.appendTagRoute("status.code", "-1")
+ rs.appendTagRoute("status.message", "No tail count given")
+ return rs.toprettyxml()
+
+ thisServerName = getCurrentServerName()
+ if not thisServerName:
+ rs.appendTagRoute("status.code", "-2")
+ rs.appendTagRoute("status.message", "Failed to get current server name")
+ return rs.toprettyxml()
+
+ volumeDom = XDOM()
+ partitionList = getPartitionListByServerName(volumeDom, thisServerName)
+ if not partitionList:
+ rs.appendTagRoute("status.code", "-3")
+ rs.appendTagRoute("status.message", "Failed to get server partition details")
+ return rs.toprettyxml()
+
+ pattern = '\[\d{4}-\d{2}-\d{2}\s{1}\d{2}:\d{2}:\d{2}.\d+\]\s{1}([MACEWNIDT]){1}\s+'
+ logMessagesTag = rs.createTag("response.logMessages")
+ for partitionName in partitionList:
+ logMessageTag = rs.createTag("logMessage")
+ logMessageTag.appendChild("disk", "%s:%s" % (thisServerName, partitionName))
+
+ logDirectory = "%s/%s/%s/log" % (Globals.GLUSTER_LUN_DIR, partitionList[partitionName], volumeUuid)
+ logFileName = "%s/%s-%s-%s-exports-brick1.log" % (logDirectory,
+ Globals.GLUSTER_LUN_DIR[1:],
+ partitionList[partitionName],
+ volumeUuid)
+ if not os.path.exists(logFileName):
+ Utils.log("volume log file not found %s" % logFileName)
+ continue
+ fp = open(logFileName)
+ lines = [line for line in fp if re.match(pattern, line)]
+ fp.close()
+ i = len(lines) - int(tailCount)
+ if i < 0:
+ i = 0
+ for log in lines[i:]:
+ loginfo = logSplit(log)
+ addLog(rs, logMessageTag, loginfo)
+ logMessagesTag.appendChild(logMessageTag)
+ return rs.toprettyxml()
+##--end of getVolumeLog()
+
+def main():
+ if len(sys.argv) != 3:
+ print >> sys.stderr, "usage: %s <disk name> <volume name>" % sys.argv[0]
+ sys.exit(-1)
+
+ volumeName = sys.argv[1]
+ tailCount = sys.argv[2]
+ print getVolumeLog(volumeName, tailCount)
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()