summaryrefslogtreecommitdiffstats
path: root/src/com.gluster.storage.management.gateway.scripts
diff options
context:
space:
mode:
authorTim <timothyasir@gluster.com>2011-08-01 13:26:55 +0530
committerTim <timothyasir@gluster.com>2011-08-01 13:26:55 +0530
commitb6dc76c7dad5dfc695b8f875e770a17c93e9d318 (patch)
tree3dbf1cc296953cab941e1247863bb98a93dbd957 /src/com.gluster.storage.management.gateway.scripts
parent65bb504695643445293726656a5b79427da06b14 (diff)
parent0d12b25f91cfcbb09687d774389d85b8c8ffa249 (diff)
Merge remote branch 'upstream/master'
Diffstat (limited to 'src/com.gluster.storage.management.gateway.scripts')
-rw-r--r--src/com.gluster.storage.management.gateway.scripts/.project17
-rw-r--r--src/com.gluster.storage.management.gateway.scripts/.pydevproject10
-rw-r--r--src/com.gluster.storage.management.gateway.scripts/src/Commands.py78
-rw-r--r--src/com.gluster.storage.management.gateway.scripts/src/Common.py20
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/Disk.py140
-rw-r--r--src/com.gluster.storage.management.gateway.scripts/src/DiskUtils.py939
-rw-r--r--src/com.gluster.storage.management.gateway.scripts/src/FsTabUtils.py92
-rw-r--r--src/com.gluster.storage.management.gateway.scripts/src/GetServerNetworkConfig.py96
-rw-r--r--src/com.gluster.storage.management.gateway.scripts/src/Globals.py123
-rw-r--r--src/com.gluster.storage.management.gateway.scripts/src/GlusterdUtils.py250
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/NetworkUtils.py483
-rw-r--r--src/com.gluster.storage.management.gateway.scripts/src/Protocol.py438
-rw-r--r--src/com.gluster.storage.management.gateway.scripts/src/RRDUtils.py72
-rw-r--r--src/com.gluster.storage.management.gateway.scripts/src/ServerUtils.py308
-rw-r--r--src/com.gluster.storage.management.gateway.scripts/src/Utils.py1059
-rw-r--r--src/com.gluster.storage.management.gateway.scripts/src/VolumeUtils.py612
-rw-r--r--src/com.gluster.storage.management.gateway.scripts/src/XmlHandler.py346
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/add_user_cifs.py37
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/clear_volume_directory.py97
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/create_volume_cifs.py33
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/create_volume_directory.py82
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/delete_user_cifs.py24
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/delete_volume_cifs.py32
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/disable-ssh-password-auth.sh30
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/format_device.py87
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/get_brick_status.py40
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/get_disk_mount_point.py62
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/get_disk_name_by_path.py68
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/get_file.py130
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/get_format_device_status.py124
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/get_rrd_cpu_details.py55
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/get_rrd_memory_details.py89
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/get_rrd_net_details.py52
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/get_server_details.py118
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/get_server_status.py22
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/get_volume_brick_log.py103
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/get_volume_log.py131
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/gluster_provision_block_wrapper.py109
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/modify_volume_cifs.py28
-rw-r--r--src/com.gluster.storage.management.gateway.scripts/src/multicast_response.py74
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/rrd_cpu.pl84
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/rrd_mem.pl100
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/rrd_net.pl74
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/rrd_update_cpu_details.py90
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/rrd_update_memory_details.py90
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/setup_cifs_config.py81
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/start_volume_cifs.py41
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/stop_volume_cifs.py38
48 files changed, 7308 insertions, 0 deletions
diff --git a/src/com.gluster.storage.management.gateway.scripts/.project b/src/com.gluster.storage.management.gateway.scripts/.project
new file mode 100644
index 00000000..110db62b
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>com.gluster.storage.management.gateway.scripts</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.python.pydev.PyDevBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.python.pydev.pythonNature</nature>
+ </natures>
+</projectDescription>
diff --git a/src/com.gluster.storage.management.gateway.scripts/.pydevproject b/src/com.gluster.storage.management.gateway.scripts/.pydevproject
new file mode 100644
index 00000000..c327cd69
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/.pydevproject
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?eclipse-pydev version="1.0"?>
+
+<pydev_project>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 3.0</pydev_property>
+<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
+<path>/com.gluster.storage.management.gateway.scripts/src</path>
+</pydev_pathproperty>
+</pydev_project>
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/Commands.py b/src/com.gluster.storage.management.gateway.scripts/src/Commands.py
new file mode 100644
index 00000000..c728b565
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/Commands.py
@@ -0,0 +1,78 @@
+COMMAND_CREATE_VOLUME = "create-volume"
+COMMAND_DELETE_VOLUME = "delete-volume"
+COMMAND_START_VOLUME = "start-volume"
+COMMAND_STOP_VOLUME = "stop-volume"
+COMMAND_GET_VOLUME_HEALTH_STATUS = "get-volume-health-status"
+COMMAND_GET_VOLUME_LIST = "get-volume-list"
+COMMAND_GET_VOLUME_LOG = "get-volume-log"
+COMMAND_CLEAR_VOLUME_LOGS = "clear-volume-logs"
+COMMAND_GET_VOLUME_PROPERTY = "get-volume-property"
+COMMAND_SET_VOLUME_PROPERTY = "set-volume-property"
+COMMAND_GET_VOLUME_STATUS = "get-volume-status"
+COMMAND_DOWNLOAD_VOLUME_LOGS = "download-volume-logs"
+COMMAND_DELETE_SERVER = "delete-server"
+COMMAND_GET_SERVER_DATE = "get-server-date"
+COMMAND_GET_SERVER_VERSION_INFO = "get-server-version-info"
+COMMAND_GET_INSTALLER_INFO = "get-installer-info"
+COMMAND_GET_SERVER_LIST = "get-server-list"
+COMMAND_GET_SERVER_SERVICE_STATUS = "get-server-service-status"
+COMMAND_GET_STORAGE_SERVER_POOL_INFO = "get-storage-server-pool-info"
+COMMAND_INSTALL_SERVER_BACKGROUND = "install-server-background"
+COMMAND_PREPARE_DATA_DISK_BACKGROUND = "prepare-data-disk-background"
+COMMAND_SET_SERVER_DATE = "set-server-date"
+COMMAND_SET_SERVER_NETWORK_CONFIG = "set-server-network-config"
+COMMAND_SET_STORAGE_SERVER_POOL_INFO = "set-storage-server-pool-info"
+COMMAND_GET_SERVER_NETWORK_CONFIG = "get-server-network-config"
+COMMAND_INSTALL_SERVER_STATUS = "install-server-status"
+COMMAND_GET_SERVER_DISK_LIST = "get-server-disk-list"
+COMMAND_PREPARE_DATA_DISK_STATUS = "prepare-data-disk-status"
+COMMAND_GET_SERVER_SYSTEM_RESOURCE = "get-server-system-resource"
+COMMAND_GET_SERVER_RESOURCE_RRD = "get-server-resource-rrd"
+COMMAND_RUN_SERVER_SERVICE = "run-server-service"
+COMMAND_SHUTDOWN_SERVER = "shutdown-server"
+COMMAND_GET_SERVER_STATUS = "get-server-status"
+COMMAND_GET_SERVER_LOG = "get-server-log"
+COMMAND_DOWNLOAD_SERVER_LOGS = "download-server-logs"
+COMMAND_CLEAR_SERVER_LOGS = "clear-server-logs"
+COMMAND_GET_SERVER_RESOURCE_RRD = "get-server-resource-rrd"
+COMMAND_GET_GSN_USER_INFO = "get-gsn-user-info"
+COMMAND_SET_GSN_USER_INFO = "set-gsn-user-info"
+COMMAND_GET_GLUSTER_UPDATE_INFO = "get-gluster-update-info"
+COMMAND_DOWNLOAD_GLUSTER_UPDATE_BACKGROUND = "download-gluster-update-background"
+COMMAND_DOWNLOAD_GLUSTER_UPDATE_STATUS = "download-gluster-update-status"
+COMMAND_INSTALL_GLUSTER_UPDATE = "install-gluster-update"
+COMMAND_EXPORT_CONFIG = "export-config"
+COMMAND_IMPORT_CONFIG = "import-config"
+COMMAND_SET_SYSTEM_PASSWORD = "set-system-password"
+COMMAND_GET_SERVER_VOLUME_LIST = "get-server-volume-list"
+COMMAND_RECONFIGURE_VOLUME = "reconfigure-volume"
+COMMAND_SET_SERVER_DIRECTORY_SERVICE_CONFIG = "set-server-directory-service-config"
+COMMAND_GET_SERVER_DIRECTORY_SERVICE_CONFIG = "get-server-directory-service-config"
+COMMAND_JOIN_SERVER_TO_DIRECTORY_SERVICE = "join-server-to-directory-service"
+COMMAND_SET_SERVER_TIME_CONFIG = "set-server-time-config"
+COMMAND_GET_SERVER_TIME_CONFIG = "get-server-time-config"
+COMMAND_LOGIN = "login"
+COMMAND_LOGOUT = "logout"
+COMMAND_GET_LOGIN_STATUS = "get-login-status"
+COMMAND_GET_SERVER_TRANSPORT_LIST = "get-server-transport-list"
+COMMAND_ADD_SERVER_PARTITION = "add-server-partition"
+COMMAND_ADD_VOLUME_USER = "add-volume-user"
+COMMAND_GET_PARTITION_VOLUME_LIST = "get-partition-volume-list"
+COMMAND_GET_VOLUME_USER_INFO = "get-volume-user-info"
+COMMAND_GET_VOLUME_USER_LIST = "get-volume-user-list"
+COMMAND_MIGRATE_PARTITION_BACKGROUND = "migrate-partition-background"
+COMMAND_MIGRATE_PARTITION_STATUS = "migrate-partition-status"
+COMMAND_MIGRATE_VOLUME_SERVER_PARTITION_BACKGROUND = "migrate-volume-server-partition-background"
+COMMAND_MIGRATE_VOLUME_SERVER_PARTITION_STATUS = "migrate-volume-server-partition-status"
+COMMAND_REMOVE_SERVER_PARTITION = "remove-server-partition"
+COMMAND_REMOVE_VOLUME_USER = "remove-volume-user"
+COMMAND_RENAME_VOLUME_USER = "rename-volume-user"
+COMMAND_RENAME_VOLUME = "rename-volume"
+COMMAND_RUN_SERVER_SERVICE = "run-server-service"
+COMMAND_SET_VOLUME_USER_PASSWORD = "set-volume-user-password"
+COMMAND_STOP_PARTITION_MIGRATION = "stop-partition-migration"
+COMMAND_STOP_VOLUME_SERVER_PARTITION_MIGRATION = "stop-volume-server-partition-migration"
+COMMAND_GET_SERVER_DISK_INFO = "get-server-disk-info"
+COMMAND_INITIALIZE_SERVER_DISK = "initialize-server-disk"
+COMMAND_SET_SERVER_COUNT = "set-server-count"
+COMMAND_GET_SERVER_COUNT = "get-server-count"
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/Common.py b/src/com.gluster.storage.management.gateway.scripts/src/Common.py
new file mode 100644
index 00000000..c85e9a2b
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/Common.py
@@ -0,0 +1,20 @@
+# Copyright (c) 2009 Gluster, Inc. <http://www.gluster.com>
+# This file is part of GlusterSP.
+#
+# GlusterSP 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.
+#
+# GlusterSP 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 sys
+import syslog
+
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/Disk.py b/src/com.gluster.storage.management.gateway.scripts/src/Disk.py
new file mode 100755
index 00000000..2c47d396
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/Disk.py
@@ -0,0 +1,140 @@
+# Copyright (c) 2009 Gluster, Inc. <http://www.gluster.com>
+# This file is part of GlusterSP.
+#
+# GlusterSP 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.
+#
+# GlusterSP 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 dbus
+
+class Disk:
+ def __init__(self):
+ """init"""
+
+ self.volumes = []
+ self.disks = []
+ self.bus = dbus.SystemBus()
+ self.hal_obj = self.bus.get_object("org.freedesktop.Hal",
+ "/org/freedesktop/Hal/Manager")
+ self.hal = dbus.Interface(self.hal_obj, "org.freedesktop.Hal.Manager")
+ self.devices = []
+ self.devices = self.hal.FindDeviceByCapability("storage")
+
+ self.detect_disks()
+ self.detect_mountable_volumes()
+
+ def getDiskList(self):
+
+ return self.disks
+
+ def getMountableDiskList(self):
+
+ return self.volumes
+
+ def detect_disks(self):
+ for device in self.devices:
+ dev = self._get_device(device)
+ if dev.GetProperty("storage.drive_type") != "cdrom":
+ if not dev.GetProperty("block.is_volume"):
+ self._add_disks(dev)
+ continue
+
+ def _add_disks(self, dev):
+ disk = str(dev.GetProperty('block.device'))
+ disk_size = str(int(dev.GetProperty('storage.size')) / 1024**2)
+
+ try:
+ if dev.GetProperty('storage.removable'):
+ disk_size = str(int(dev.GetProperty('storage.removable.media_size')) / 1024**2)
+ except:
+ return
+
+ self.disks.append({
+ 'device': disk,
+ 'description': str(dev.GetProperty('storage.model')) + " " + str(dev.GetProperty('storage.vendor')),
+ 'interface': str(dev.GetProperty('storage.bus')),
+ 'size': disk_size,
+ 'drive_type': str(dev.GetProperty('storage.drive_type'))
+ })
+
+ def detect_mountable_volumes(self):
+ """ Detect all mountable volumes using HAL via D-Bus """
+ for device in self.devices:
+ dev = self._get_device(device)
+ if dev.GetProperty("storage.drive_type") != "cdrom":
+ if dev.GetProperty("block.is_volume"):
+ self._add_volume(dev)
+ continue
+ else: # iterate over children looking for a volume
+ children = self.hal.FindDeviceStringMatch("info.parent",
+ device)
+ if not children and "disk" == dev.GetProperty("storage.drive_type"):
+ self._add_volume(dev)
+ for child in children:
+ child = self._get_device(child)
+ if child.GetProperty("block.is_volume"):
+ self._add_volume(child, parent=dev)
+ #break # don't break, allow all partitions
+
+ def _add_volume(self, dev, parent=None):
+ volume = str(dev.GetProperty('block.device'))
+ if not parent:
+ self.volumes.append ({
+ 'device' : volume,
+ 'label' : str(dev.GetProperty('block.device')),
+ 'fstype' : None,
+ 'fsversion': None,
+ 'uuid' : None,
+ 'interface': str(dev.GetProperty('storage.bus')),
+ 'parent' : None,
+ 'description': str(dev.GetProperty('storage.model')) + " " + str(dev.GetProperty('storage.vendor')),
+ 'size' : None,
+ 'totalsize' : str(int(dev.GetProperty('storage.size')) / 1024**2),
+ 'drive_type': str(dev.GetProperty('storage.drive_type')),
+ 'mount_point': "NA"
+ })
+ return
+
+ self.volumes.append ({
+ 'device' : volume,
+ 'label' : str(dev.GetProperty('volume.label')),
+ 'fstype' : str(dev.GetProperty('volume.fstype')),
+ 'fsversion': str(dev.GetProperty('volume.fsversion')),
+ 'uuid' : str(dev.GetProperty('volume.uuid')),
+ 'interface': str(parent.GetProperty('storage.bus')),
+ 'parent' : str(parent.GetProperty('block.device')),
+ 'description': str(parent.GetProperty('storage.model')) + " " + str(parent.GetProperty('storage.vendor')),
+ 'size' : str(int(dev.GetProperty('volume.size')) / 1024**2),
+ 'totalsize' : str(int(parent.GetProperty('storage.size')) / 1024**2),
+ 'drive_type': str(parent.GetProperty('storage.drive_type')),
+ 'mount_point': str(dev.GetProperty('volume.mount_point'))
+ })
+ return
+
+ def _get_device(self, udi):
+ """ Return a dbus Interface to a specific HAL device UDI """
+ dev_obj = self.bus.get_object("org.freedesktop.Hal", udi)
+ return dbus.Interface(dev_obj, "org.freedesktop.Hal.Device")
+
+ def get_free_bytes(self, device=None):
+ """ Return the number of available bytes on our device """
+ import statvfs
+ stat = os.statvfs(device)
+ return stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]
+
+ def get_used_bytes(self, device=None):
+ """ Return the number of used bytes on our device """
+ import statvfs
+ stat = os.statvfs(device)
+ return ((stat[statvfs.F_BSIZE] * stat[statvfs.F_BLOCKS]) - (stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]))
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/DiskUtils.py b/src/com.gluster.storage.management.gateway.scripts/src/DiskUtils.py
new file mode 100644
index 00000000..a0e5d802
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/DiskUtils.py
@@ -0,0 +1,939 @@
+# 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
+from copy import deepcopy
+import dbus
+import Globals
+import time
+import Utils
+import Disk
+import Protocol
+from FsTabUtils import *
+
+ONE_MB_SIZE = 1048576
+
+
+def _stripDev(device):
+ if Utils.isString(device) and device.startswith("/dev/"):
+ return device[5:]
+ return device
+
+
+def _addDev(deviceName):
+ if Utils.isString(deviceName) and not deviceName.startswith("/dev/"):
+ return "/dev/" + deviceName
+ return deviceName
+
+
+def getDeviceName(device):
+ if type(device) == type([]):
+ nameList = []
+ for d in device:
+ nameList.append(_stripDev(d))
+ return nameList
+ return _stripDev(device)
+
+
+def getDevice(deviceName):
+ if Utils.isString(deviceName):
+ return _addDev(deviceName)
+ if type(deviceName) == type([]):
+ nameList = []
+ for d in deviceName:
+ nameList.append(_addDev(d))
+ return nameList
+ return _addDev(deviceName)
+
+
+def getDiskPartitionByUuid(uuid):
+ uuidFile = "/dev/disk/by-uuid/%s" % uuid
+ if os.path.exists(uuidFile):
+ return getDeviceName(os.path.realpath(uuidFile))
+ return None
+
+
+def getUuidByDiskPartition(device):
+ for uuidFile in glob.glob("/dev/disk/by-uuid/*"):
+ if os.path.realpath(uuidFile) == device:
+ return os.path.basename(uuidFile)
+ return None
+
+
+def getDiskPartitionUuid(partition):
+ Utils.log("WARNING: getDiskPartitionUuid() is deprecated by getUuidByDiskPartition()")
+ return getUuidByDiskPartition(partition)
+
+
+def getDiskPartitionByLabel(label):
+ ## TODO: Finding needs to be enhanced
+ labelFile = "/dev/disk/by-label/%s" % label
+ if os.path.exists(labelFile):
+ if os.path.islink(labelFile):
+ return getDeviceName(os.path.realpath(labelFile))
+ return None
+
+
+def getDeviceByLabel(label):
+ Utils.log("WARNING: getDeviceByLabel() is deprecated by getDiskPartitionByLabel()")
+ return getDiskPartitionByLabel(label)
+
+
+def getDiskPartitionLabel(device):
+ rv = Utils.runCommandFG(["sudo", "e2label", device], stdout=True)
+ if rv["Status"] == 0:
+ return rv["Stdout"].strip()
+ return False
+
+
+def readFile(fileName):
+ lines = None
+ try:
+ fp = open(fileName)
+ lines = fp.readlines()
+ fp.close()
+ except IOError, e:
+ Utils.log("failed to read file %s: %s" % (file, str(e)))
+ return lines
+
+
+def getRootPartition(fsTabFile=Globals.FSTAB_FILE):
+ fsTabEntryList = readFsTab(fsTabFile)
+ for fsTabEntry in fsTabEntryList:
+ if fsTabEntry["MountPoint"] == "/":
+ if fsTabEntry["Device"].startswith("UUID="):
+ return getDiskPartitionByUuid(fsTabEntry["Device"].split("UUID=")[-1])
+ if fsTabEntry["Device"].startswith("LABEL="):
+ partitionName = getDiskPartitionByLabel(fsTabEntry["Device"].split("LABEL=")[-1])
+ if partitionName:
+ return partitionName
+ return getDeviceName(fsTabEntry["Device"])
+ return None
+
+def getMounts():
+ mounts = {}
+ for line in readFile("/proc/mounts"):
+ str = line.strip()
+ if str.startswith("/dev/"):
+ tokens = str.split()
+ device = {}
+ mountPoint = tokens[1].strip()
+ device["MountPoint"] = mountPoint
+ device["FsType"] = tokens[2].strip()
+ device["Uuid"] = getDiskPartitionUuid(tokens[0].strip())
+ device["Status"] = "INITIALIZED"
+ if mountPoint:
+ if mountPoint in ["/", "/boot"]:
+ device["Type"] = "BOOT"
+ else:
+ device["Type"] = "DATA"
+ mounts[tokens[0].strip()] = device
+ return mounts
+
+def getRaidDisk():
+ array = []
+ arrayList = []
+ mdFound = False
+
+ try:
+ fp = open("/proc/mdstat")
+ for line in fp:
+ str = line.strip()
+ if str.startswith("md"):
+ array.append(str)
+ mdFound = True
+ continue
+ if mdFound:
+ if str:
+ array.append(str)
+ else:
+ arrayList.append(array)
+ array = []
+ mdFound = False
+ fp.close()
+ except IOError, e:
+ return None
+
+ raidList = {}
+ for array in arrayList:
+ raid = {}
+ tokens = array[0].split()
+ raid['Interface'] = tokens[3]
+ device = getDevice(tokens[0])
+ raid['MountPoint'] = getDeviceMountPoint(device)
+ if raid['MountPoint']:
+ raid['Type'] = "DATA"
+ rv = Utils.runCommand("blkid -c /dev/null %s" % (device), output=True, root=True)
+ raid['Uuid'] = None
+ raid['FsType'] = None
+ raid['Status'] = "UNINITIALIZED"
+ if isDiskInFormatting(device):
+ raid['Status'] = "INITIALIZING"
+ if not rv["Stderr"]:
+ words = rv["Stdout"].strip().split()
+ if words:
+ raid['Status'] = "INITIALIZED"
+ if len(words) > 2:
+ raid['Uuid'] = words[1].split("UUID=")[-1].split('"')[1]
+ raid['FsType'] = words[2].split("TYPE=")[-1].split('"')[1]
+
+ used = 0
+ rv = Utils.runCommand("df %s" % (device), output=True, root=True)
+ if rv["Status"] == 0:
+ try:
+ used = long(rv["Stdout"].split("\n")[1].split()[2]) / 1024
+ except IndexError:
+ pass
+ except ValueError:
+ pass
+ raid['SpaceInUse'] = used
+ raid['Disks'] = [x.split('[')[0] for x in tokens[4:]]
+ raid['Size'] = float(array[1].split()[0]) / 1024.0
+ raidList[tokens[0]] = raid
+ return raidList
+
+
+def getOsDisk():
+ Utils.log("WARNING: getOsDisk() is deprecated by getRootPartition()")
+ return getRootPartition()
+
+
+def getDiskInfo(diskDeviceList=None):
+ diskDeviceList = getDevice(diskDeviceList)
+ if Utils.isString(diskDeviceList):
+ diskDeviceList = [diskDeviceList]
+
+ mounts = getMounts()
+ if Utils.runCommand("/usr/bin/lshal") != 0:
+ Utils.log("failed running /usr/bin/lshal")
+
+ dbusSystemBus = dbus.SystemBus()
+ halObj = dbusSystemBus.get_object("org.freedesktop.Hal",
+ "/org/freedesktop/Hal/Manager")
+ halManager = dbus.Interface(halObj, "org.freedesktop.Hal.Manager")
+ storageUdiList = halManager.FindDeviceByCapability("storage")
+
+ diskInfo = {}
+ diskList = []
+ for udi in storageUdiList:
+ halDeviceObj = dbusSystemBus.get_object("org.freedesktop.Hal", udi)
+ halDevice = dbus.Interface(halDeviceObj,
+ "org.freedesktop.Hal.Device")
+ if halDevice.GetProperty("storage.drive_type") in ["cdrom", "floppy"] or \
+ halDevice.GetProperty("block.is_volume"):
+ continue
+ disk = {}
+ disk["Device"] = str(halDevice.GetProperty('block.device'))
+ if diskDeviceList and disk["Device"] not in diskDeviceList:
+ continue
+ disk["Description"] = str(halDevice.GetProperty('storage.vendor')) + " " + str(halDevice.GetProperty('storage.model'))
+ if halDevice.GetProperty('storage.removable'):
+ disk["Size"] = long(halDevice.GetProperty('storage.removable.media_size'))
+ else:
+ disk["Size"] = long(halDevice.GetProperty('storage.size')) / 1024**2
+ disk["Interface"] = str(halDevice.GetProperty('storage.bus'))
+ disk["DriveType"] = str(halDevice.GetProperty('storage.drive_type'))
+ disk["Status"] = None
+ disk["Uuid"] = None
+ disk["Init"] = False
+ disk["Type"] = None
+ disk["FsType"] = None
+ disk["FsVersion"] = None
+ disk["MountPoint"] = None
+ disk["ReadOnlyAccess"] = None
+ disk["SpaceInUse"] = None
+
+ partitionUdiList = halManager.FindDeviceStringMatch("info.parent", udi)
+ if isDiskInFormatting(disk["Device"]):
+ disk["Status"] = "INITIALIZING"
+ else:
+ if partitionUdiList:
+ disk["Status"] = "INITIALIZED"
+ else:
+ disk["Status"] = "UNINITIALIZED"
+ disk["Type"] = "UNKNOWN"
+
+ if mounts and mounts.has_key(disk["Device"]):
+ disk["Uuid"] = mounts[disk["Device"]]["Uuid"]
+ disk["Type"] = mounts[disk["Device"]]["Type"]
+ disk["Status"] = mounts[disk["Device"]]["Status"]
+ disk["FsType"] = mounts[disk["Device"]]["FsType"]
+ disk["MountPoint"] = mounts[disk["Device"]]["MountPoint"]
+
+ partitionList = []
+ diskSpaceInUse = 0
+ for partitionUdi in partitionUdiList:
+ used = 0
+ partitionHalDeviceObj = dbusSystemBus.get_object("org.freedesktop.Hal",
+ partitionUdi)
+ partitionHalDevice = dbus.Interface(partitionHalDeviceObj,
+ "org.freedesktop.Hal.Device")
+ if not partitionHalDevice.GetProperty("block.is_volume"):
+ continue
+ partitionDevice = str(partitionHalDevice.GetProperty('block.device'))
+ if partitionHalDevice.GetProperty("volume.is_mounted"):
+ rv = Utils.runCommandFG(["df", str(partitionHalDevice.GetProperty('volume.mount_point'))], stdout=True)
+ if rv["Status"] == 0:
+ try:
+ used = long(rv["Stdout"].split("\n")[1].split()[2]) / 1024
+ diskSpaceInUse += used
+ except IndexError:
+ pass
+ except ValueError:
+ pass
+
+ if disk["Device"] == partitionDevice:
+ disk["Uuid"] = str(partitionHalDevice.GetProperty('volume.uuid'))
+ disk["Init"] = True # TODO: use isDataDiskPartitionFormatted function to cross verify this
+ disk["Status"] = "INITIALIZED"
+ mountPoint = str(partitionHalDevice.GetProperty('volume.mount_point'))
+ if mountPoint:
+ if mountPoint in ["/", "/boot"]:
+ disk["Type"] = "BOOT"
+ else:
+ disk["Type"] = "DATA"
+ disk["FsType"] = str(partitionHalDevice.GetProperty('volume.fstype'))
+ if disk["FsType"] and "UNINITIALIZED" == disk["Status"]:
+ disk["Status"] = "INITIALIZED"
+ disk["FsVersion"] = str(partitionHalDevice.GetProperty('volume.fsversion'))
+ disk["MountPoint"] = str(partitionHalDevice.GetProperty('volume.mount_point'))
+ disk["ReadOnlyAccess"] = str(partitionHalDevice.GetProperty('volume.is_mounted_read_only'))
+ if not disk["Size"]:
+ disk["Size"] = long(partitionHalDevice.GetProperty('volume.size')) / 1024**2
+ disk["SpaceInUse"] = used
+ continue
+
+ partition = {}
+ partition["Init"] = False
+ partition["Type"] = "UNKNOWN"
+ partition["Device"] = partitionDevice
+ partition["Uuid"] = str(partitionHalDevice.GetProperty('volume.uuid'))
+ partition["Size"] = long(partitionHalDevice.GetProperty('volume.size')) / 1024**2
+ partition["FsType"] = str(partitionHalDevice.GetProperty('volume.fstype'))
+ partition["FsVersion"] = str(partitionHalDevice.GetProperty('volume.fsversion'))
+ partition["Label"] = str(partitionHalDevice.GetProperty('volume.label'))
+ partition["MountPoint"] = str(partitionHalDevice.GetProperty('volume.mount_point'))
+ partition["Size"] = long(partitionHalDevice.GetProperty('volume.size')) / 1024**2
+
+ if isDiskInFormatting(partitionDevice):
+ partition["Status"] = "INITIALIZING"
+ else:
+ if partition["FsType"]:
+ partition["Status"] = "INITIALIZED"
+ else:
+ partition["Status"] = "UNINITIALIZED"
+
+ partition["SpaceInUse"] = used
+ if partition["MountPoint"] or isDataDiskPartitionFormatted(partitionDevice):
+ partition["Init"] = True
+ partition["Status"] = "INITIALIZED"
+ if partition["MountPoint"]:
+ if partition["MountPoint"] in ["/", "/boot"]:
+ partition["Type"] = "BOOT"
+ else:
+ partition["Type"] = "DATA"
+ else:
+ if "SWAP" == partition["FsType"].strip().upper():
+ partition["Type"] = "SWAP"
+ partition["ReadOnlyAccess"] = str(partitionHalDevice.GetProperty('volume.is_mounted_read_only'))
+ partitionList.append(partition)
+ disk["Partitions"] = partitionList
+ if not disk["SpaceInUse"]:
+ disk["SpaceInUse"] = diskSpaceInUse
+ diskList.append(disk)
+ diskInfo["disks"] = diskList
+ if diskList:
+ return diskInfo
+ for line in readFile("/proc/partitions")[2:]:
+ disk = {}
+ tokens = line.split()
+ if tokens[3].startswith("md"):
+ continue
+ disk["Device"] = tokens[3]
+ ## if diskDeviceList and disk["Device"] not in diskDeviceList:
+ ## continue
+ disk["Description"] = None
+ disk["Size"] = long(tokens[2]) / 1024
+ disk["Status"] = None
+ disk["Interface"] = None
+ disk["DriveType"] = None
+ disk["Uuid"] = None
+ disk["Init"] = False
+ disk["Type"] = None
+ disk["FsType"] = None
+ disk["FsVersion"] = None
+ disk["MountPoint"] = None
+ disk["ReadOnlyAccess"] = None
+ disk["SpaceInUse"] = None
+ disk["Partitions"] = []
+ diskList.append(disk)
+ diskInfo["disks"] = diskList
+ return diskInfo
+
+def getDiskList(diskDeviceList=None):
+ return diskInfo["disks"]
+
+def readFsTab(fsTabFile=Globals.FSTAB_FILE):
+ try:
+ fsTabfp = open(fsTabFile)
+ except IOError, e:
+ Utils.log("readFsTab(): " + str(e))
+ return None
+
+ fsTabEntryList = []
+ for line in fsTabfp:
+ tokens = line.strip().split()
+ if not tokens or tokens[0].startswith('#'):
+ continue
+ fsTabEntry = {}
+ fsTabEntry["Device"] = None
+ fsTabEntry["MountPoint"] = None
+ fsTabEntry["FsType"] = None
+ fsTabEntry["Options"] = None
+ fsTabEntry["DumpOption"] = 0
+ fsTabEntry["fsckOrder"] = 0
+ try:
+ fsTabEntry["Device"] = tokens[0]
+ fsTabEntry["MountPoint"] = tokens[1]
+ fsTabEntry["FsType"] = tokens[2]
+ fsTabEntry["Options"] = tokens[3]
+ fsTabEntry["DumpOption"] = tokens[4]
+ fsTabEntry["fsckOrder"] = tokens[5]
+ except IndexError:
+ pass
+ if fsTabEntry["Device"] and fsTabEntry["MountPoint"] and fsTabEntry["FsType"] and fsTabEntry["Options"]:
+ fsTabEntryList.append(fsTabEntry)
+ fsTabfp.close()
+ return fsTabEntryList
+
+
+def checkDiskMountPoint(diskMountPoint):
+ try:
+ fstabEntries = open(Globals.FSTAB_FILE).readlines()
+ except IOError:
+ fstabEntries = []
+ found = False
+ for entry in fstabEntries:
+ entry = entry.strip()
+ if not entry:
+ continue
+ entries = entry.split()
+ if entries and len(entries) > 1 and entries[0].startswith("UUID=") and entries[1].upper() == diskMountPoint.upper():
+ return True
+ return False
+
+
+def getMountPointByUuid(partitionUuid):
+ # check uuid in etc/fstab
+ try:
+ fstabEntries = open(Globals.FSTAB_FILE).readlines()
+ except IOError:
+ fstabEntries = []
+ found = False
+ for entry in fstabEntries:
+ entry = entry.strip()
+ if not entry:
+ continue
+ if entry.split()[0] == "UUID=" + partitionUuid:
+ return entry.split()[1]
+ return None
+
+
+def getDiskSizeInfo(partition):
+ # get values from df output
+ total = None
+ used = None
+ free = None
+ command = "df -kl -t ext3 -t ext4 -t xfs"
+ rv = Utils.runCommandFG(command, stdout=True, root=True)
+ message = Utils.stripEmptyLines(rv["Stdout"])
+ if rv["Stderr"]:
+ Utils.log("failed to get disk details. %s" % Utils.stripEmptyLines(rv["Stdout"]))
+ return None, None, None
+ for line in rv["Stdout"].split("\n"):
+ tokens = line.split()
+ if len(tokens) < 4:
+ continue
+ if tokens[0] == partition:
+ total = int(tokens[1]) / 1024.0
+ used = int(tokens[2]) / 1024.0
+ free = int(tokens[3]) / 1024.0
+ break
+
+ if total:
+ return total, used, free
+
+ # get total size from parted output
+ for i in range(len(partition), 0, -1):
+ pos = i - 1
+ if not partition[pos].isdigit():
+ break
+ disk = partition[:pos+1]
+ partitionNumber = partition[pos+1:]
+ if not partitionNumber.isdigit():
+ return None, None, None
+
+ number = int(partitionNumber)
+ command = "parted -ms %s unit kb print" % disk
+ rv = Utils.runCommandFG(command, stdout=True, root=True)
+ message = Utils.stripEmptyLines(rv["Stdout"])
+ if rv["Stderr"]:
+ Utils.log("failed to get disk details. %s" % Utils.stripEmptyLines(rv["Stdout"]))
+ return None, None, None
+
+ lines = rv["Stdout"].split(";\n")
+ if len(lines) < 3:
+ return None,None,None
+
+ for line in lines[2:]:
+ tokens = line.split(':')
+ if len(tokens) < 4:
+ continue
+ if tokens[0] == str(number):
+ total = int(tokens[3].split('kB')[0]) / 1024.0
+ break
+ return total, used, free
+
+
+def isDataDiskPartitionFormatted(device):
+ #Todo: Proper label needs to be added for data partition
+ #if getDiskPartitionLabel(device) != Globals.DATA_PARTITION_LABEL:
+ # return False
+ device = getDeviceName(device)
+ diskObj = Disk.Disk()
+ for disk in diskObj.getMountableDiskList():
+ if disk['device'].upper() == device.upper():
+ mountPoint = disk['mount_point']
+ if not mountPoint:
+ return False
+ if not os.path.exists(mountPoint):
+ return False
+
+ uuid = getUuidByDiskPartition(device)
+ if not uuid:
+ return False
+
+ for fsTabEntry in readFsTab():
+ if fsTabEntry["Device"] == ("UUID=%s" % uuid) and fsTabEntry["MountPoint"] == mountPoint:
+ return True
+ return False
+
+
+def getDiskDom(diskDeviceList=None, bootPartition=None, skipDisk=None):
+ diskDeviceList = getDevice(diskDeviceList)
+ if Utils.isString(diskDeviceList):
+ diskDeviceList = [diskDeviceList]
+
+ if skipDisk:
+ skipDisk = getDevice(skipDisk)
+ if Utils.isString(skipDisk):
+ skipDisk = [skipDisk]
+
+ diskInfo = getDiskInfo(diskDeviceList)
+ diskList = diskInfo["disks"]
+ if not diskList:
+ return None
+
+ raidPartitions = {}
+ raidDisk = getRaidDisk()
+
+ for k, v in raidDisk.iteritems():
+ for i in v['Disks']:
+ raidPartitions[i] = k
+
+ #for partition in raidDisk.values():
+ # raidDiskPartitions += partition['disks']
+
+ diskDom = Protocol.XDOM()
+ disksTag = diskDom.createTag("disks", None)
+ raidDisks = {}
+ if not bootPartition:
+ bootPartition = getRootPartition()
+ for disk in diskList:
+ if skipDisk and disk["Device"] in skipDisk:
+ continue
+ diskTag = diskDom.createTag("disk", None)
+ diskDevice = getDeviceName(disk["Device"])
+ diskTag.appendChild(diskDom.createTag("name", diskDevice))
+ diskTag.appendChild(diskDom.createTag("description", disk["Description"]))
+ diskTag.appendChild(diskDom.createTag("uuid", disk["Uuid"]))
+ diskTag.appendChild(diskDom.createTag("status", disk["Status"]))
+ diskTag.appendChild(diskDom.createTag("interface", disk["Interface"]))
+
+ #if not disk["Partitions"]:
+ diskTag.appendChild(diskDom.createTag("type", disk["Type"]))
+ #diskTag.appendChild(diskDom.createTag("init", str(disk["Init"]).lower()))
+ diskTag.appendChild(diskDom.createTag("fsType", disk["FsType"]))
+ diskTag.appendChild(diskDom.createTag("fsVersion", disk["FsVersion"]))
+ diskTag.appendChild(diskDom.createTag("mountPoint", disk["MountPoint"]))
+
+ diskTag.appendChild(diskDom.createTag("size", disk["Size"]))
+ diskTag.appendChild(diskDom.createTag("spaceInUse", disk["SpaceInUse"]))
+ partitionsTag = diskDom.createTag("partitions", None)
+ if raidPartitions.has_key(diskDevice):
+ rdList = {}
+ rdList[diskDevice] = [deepcopy(diskTag)]
+ if not raidDisks.has_key(raidPartitions[diskDevice]):
+ raidDisks[raidPartitions[diskDevice]] = []
+ raidDisks[raidPartitions[diskDevice]] += [rdList]
+ continue
+ for partition in disk["Partitions"]:
+ partitionTag = diskDom.createTag("partition", None)
+ device = getDeviceName(partition["Device"])
+ partitionTag.appendChild(diskDom.createTag("name", device))
+ if partition["Uuid"]: #TODO: Move this verification and findings to getDiskInfo function
+ partitionTag.appendChild(diskDom.createTag("uuid", partition["Uuid"]))
+ else:
+ partitionTag.appendChild(diskDom.createTag("uuid", getUuidByDiskPartition("/dev/" + device)))
+ partitionTag.appendChild(diskDom.createTag("status", partition["Status"]))
+ #partitionTag.appendChild(diskDom.createTag("init", str(partition["Init"]).lower()))
+ partitionTag.appendChild(diskDom.createTag("type", str(partition["Type"])))
+ partitionTag.appendChild(diskDom.createTag("fsType", partition["FsType"]))
+ partitionTag.appendChild(diskDom.createTag("mountPoint", partition['MountPoint']))
+ partitionTag.appendChild(diskDom.createTag("size", partition["Size"]))
+ partitionTag.appendChild(diskDom.createTag("spaceInUse", partition["SpaceInUse"]))
+ if raidPartitions.has_key(device):
+ tempPartitionTag = diskDom.createTag("partitions", None)
+ if raidDisks.has_key(raidPartitions[device]):
+ rdList = raidDisks[raidPartitions[device]]
+ for rdItem in rdList:
+ if not rdItem.has_key(diskDevice):
+ rdItem[diskDevice] = [deepcopy(diskTag), tempPartitionTag]
+ rdItem[diskDevice][0].appendChild(tempPartitionTag)
+ rdItem[diskDevice][-1].appendChild(partitionTag)
+ continue
+ rdList = {}
+ rdList[diskDevice] = [deepcopy(diskTag), tempPartitionTag]
+ tempPartitionTag.appendChild(partitionTag)
+ rdList[diskDevice][0].appendChild(tempPartitionTag)
+ raidDisks[raidPartitions[device]] = [rdList]
+ continue
+ partitionsTag.appendChild(partitionTag)
+ diskTag.appendChild(partitionsTag)
+ disksTag.appendChild(diskTag)
+
+ for rdisk in raidDisk.keys():
+ raidDiskTag = diskDom.createTag("disk", None)
+ raidDiskTag.appendChild(diskDom.createTag("name", rdisk))
+ raidDiskTag.appendChild(diskDom.createTag("description"))
+ raidDiskTag.appendChild(diskDom.createTag("uuid", raidDisk[rdisk]['Uuid']))
+ raidDiskTag.appendChild(diskDom.createTag("type", raidDisk[rdisk]['Type']))
+ raidDiskTag.appendChild(diskDom.createTag("mountPoint", raidDisk[rdisk]['MountPoint']))
+ raidDiskTag.appendChild(diskDom.createTag("status", raidDisk[rdisk]['Status']))
+ raidDiskTag.appendChild(diskDom.createTag("interface", raidDisk[rdisk]['Interface']))
+ raidDiskTag.appendChild(diskDom.createTag("fsType", raidDisk[rdisk]['FsType']))
+ raidDiskTag.appendChild(diskDom.createTag("fsVersion"))
+ raidDiskTag.appendChild(diskDom.createTag("size", raidDisk[rdisk]['Size']))
+ raidDiskTag.appendChild(diskDom.createTag("spaceInUse", raidDisk[rdisk]['SpaceInUse']))
+ raidDisksTag = diskDom.createTag("raidDisks", None)
+ if raidDisks.has_key(rdisk):
+ for item in raidDisks[rdisk]:
+ for diskTag in item.values():
+ raidDisksTag.appendChild(diskTag[0])
+ raidDiskTag.appendChild(raidDisksTag)
+ disksTag.appendChild(raidDiskTag)
+ diskDom.addTag(disksTag)
+ return diskDom
+
+
+def initializeDisk(disk, boot=False, startSize=0, sudo=False):
+ if boot and startSize > 0:
+ return False
+
+ disk = getDevice(disk)
+ diskObj = getDiskList(disk)[0]
+
+ if boot or startSize == 0:
+ command = "dd if=/dev/zero of=%s bs=1024K count=1" % diskObj["Device"]
+ if runCommandFG(command, root=sudo) != 0:
+ if boot:
+ Utils.log("failed to clear boot sector of disk %s" % diskObj["Device"])
+ return False
+ Utils.log("failed to clear boot sector of disk %s. ignoring" % diskObj["Device"])
+
+ command = "parted -s %s mklabel gpt" % diskObj["Device"]
+ if runCommandFG(command, root=sudo) != 0:
+ return False
+
+ if boot:
+ command = "parted -s %s mkpart primary ext3 0MB %sMB" % (diskObj["Device"], Globals.OS_PARTITION_SIZE)
+ if runCommandFG(command, root=sudo) != 0:
+ return False
+ command = "parted -s %s set 1 boot on" % (diskObj["Device"])
+ if runCommandFG(command, root=sudo) != 0:
+ return False
+ startSize = Globals.OS_PARTITION_SIZE
+
+ size = (diskObj["Size"] / ONE_MB_SIZE) - startSize
+ while size > Globals.MAX_PARTITION_SIZE:
+ endSize = startSize + Globals.MAX_PARTITION_SIZE
+ command = "parted -s %s mkpart primary ext3 %sMB %sMB" % (diskObj["Device"], startSize, endSize)
+ if runCommandFG(command, root=sudo) != 0:
+ return False
+ size -= Globals.MAX_PARTITION_SIZE
+ startSize = endSize
+
+ if size:
+ command = "parted -s %s mkpart primary ext3 %sMB 100%%" % (diskObj["Device"], startSize)
+ if runCommandFG(command, root=sudo) != 0:
+ return False
+
+ if runCommandFG("udevadm settle", root=sudo) != 0:
+ if runCommandFG("udevadm settle", root=sudo) != 0:
+ Utils.log("udevadm settle for disk %s failed. ignoring" % diskObj["Device"])
+ time.sleep(1)
+
+ if runCommandFG("partprobe %s" % diskObj["Device"], root=sudo) != 0:
+ Utils.log("partprobe %s failed" % diskObj["Device"])
+ return False
+
+ if runCommandFG("gptsync %s" % diskObj["Device"], root=sudo) != 0:
+ Utils.log("gptsync %s failed. ignoring" % diskObj["Device"])
+
+ # wait forcefully to appear devices in /dev
+ time.sleep(2)
+ return True
+
+
+def initializeOsDisk(diskObj):
+ Utils.log("WARNING: initializeOsDisk() is deprecated by initializeDisk(boot=True)")
+ return initializeDisk(diskObj, boot=True)
+
+
+def initializeDataDisk(diskObj):
+ Utils.log("WARNING: initializeDataDisk() is deprecated by initializeDisk()")
+ return initializeDisk(diskObj)
+
+def getBootPartition(serverName):
+ diskDom = XDOM()
+ diskDom.parseFile("%s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName))
+ if not diskDom:
+ return None
+ partitionDom = XDOM()
+ partitionUuid = None
+ partitionName = None
+ for partitionTag in diskDom.getElementsByTagRoute("disk.partition"):
+ partitionDom.setDomObj(partitionTag)
+ boot = partitionDom.getTextByTagRoute("boot")
+ if boot and boot.strip().upper() == 'YES':
+ partitionUuid = partitionDom.getTextByTagRoute("uuid")
+ partitionName = partitionDom.getTextByTagRoute("device")
+ break
+ if not (partitionUuid and partitionName):
+ return None
+
+ # check device label name
+ deviceBaseName = os.path.basename(partitionName)
+ process = runCommandBG(['sudo', 'e2label', partitionName])
+ if type(process) == type(True):
+ return None
+ if process.wait() != 0:
+ return None
+ output = process.communicate()
+ deviceLabel = output[0].split()[0]
+ if deviceLabel != Globals.BOOT_PARTITION_LABEL:
+ return None
+
+ # check uuid in etc/fstab
+ try:
+ fstabEntries = open(Globals.FSTAB_FILE).readlines()
+ except IOError:
+ fstabEntries = []
+ found = False
+ for entry in fstabEntries:
+ entry = entry.strip()
+ if not entry:
+ continue
+ if entry.split()[0] == "UUID=" + partitionUuid:
+ found = True
+ break
+ if not found:
+ return None
+ return partitionName
+
+
+def isDiskInFormatting(device):
+ DEVICE_FORMAT_LOCK_FILE = "/var/lock/%s.lock" % device
+ return os.path.exists(DEVICE_FORMAT_LOCK_FILE)
+
+
+def isDiskInFormat(device):
+ Utils.log("WARNING: isDiskInFormat() is deprecated by isDataDiskPartitionFormatted()")
+ return isDataDiskPartitionFormatted(device)
+
+
+def diskOrder(serverExportList):
+ newServerExportList = []
+ while serverExportList:
+ serverExport = deepcopy(serverExportList[0])
+ if newServerExportList and serverExport.split(":")[0] == newServerExportList[-1].split(":")[0]:
+ inserted = False
+ for i in range(0, len(newServerExportList) - 1):
+ if serverExport.split(":")[0] == newServerExportList[i].split(":")[0]:
+ continue
+ if i == 0:
+ newServerExportList.insert(i, serverExport)
+ inserted = True
+ break
+ if serverExport.split(":")[0] == newServerExportList[i - 1].split(":")[0]:
+ continue
+ newServerExportList.insert(i, serverExport)
+ inserted = True
+ break
+ if not inserted:
+ newServerExportList.append(serverExport)
+ else:
+ newServerExportList.append(serverExport)
+ serverExportList.remove(serverExport)
+ i = 0
+ while serverExportList and i < len(serverExportList):
+ if serverExport.split(":")[0] == serverExportList[i].split(":")[0]:
+ i += 1
+ continue
+ serverExport = deepcopy(serverExportList[i])
+ newServerExportList.append(serverExport)
+ serverExportList.remove(serverExport)
+ return newServerExportList
+
+
+def updateServerDiskConfig(serverName, diskDom, requestFlag=True, partitionFlag=True):
+ command = "command.server."
+ if not requestFlag:
+ command = ""
+ diskList = {}
+ for tagE in diskDom.getElementsByTagRoute(command + "disk"):
+ diskList[diskDom.getTextByTagRoute(command + "device")] = tagE
+ configDom = XDOM()
+ if not configDom.parseFile("%s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)):
+ return diskDom.writexml("%s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName))
+ diskTag = configDom.getElementsByTagRoute("disks.disk")
+ disks = configDom.getElementsByTagRoute("disks")
+ if not (diskTag or disks):
+ return None
+ for tagE in diskTag:
+ diskDom = XDOM()
+ diskDom.setDomObj(tagE)
+ device = diskDom.getTextByTagRoute("device")
+ if partitionFlag and device in diskList:
+ disks[0].removeChild(tagE)
+ disks[0].appendChild(deepcopy(diskList[device]))
+ continue
+ if not partitionFlag and device in diskList:
+ partitionList = []
+ for childNodeTag in tagE.childNodes:
+ if childNodeTag.nodeName == 'partition':
+ partitionList.append(childNodeTag)
+ tagE.childNodes = []
+ tagE.childNodes = diskList[device].childNodes + partitionList
+ return configDom.writexml("%s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName))
+
+
+def compareDisksDom(diskDomA, diskDomB, requestFlag=True):
+ command = "command.server.disk."
+ if not requestFlag:
+ command = ""
+ sourceDiskList = {}
+ sourceDisk = {}
+ for tagE in diskDomA.getElementsByTagRoute("disk"):
+ sourceDisk["description"] = diskDomA.getTextByTagRoute("description")
+ sourceDisk["size"] = diskDomA.getTextByTagRoute("size")
+ sourceDisk["init"] = diskDomA.getTextByTagRoute("init")
+ sourceDisk["interface"] = diskDomA.getTextByTagRoute("interface")
+ sourceDiskList[diskDomA.getTextByTagRoute("device")] = sourceDisk
+ objDiskList = {}
+ objDisk = {}
+ for tagE in diskDomB.getElementsByTagRoute("disk"):
+ objDisk["description"] = diskDomB.getTextByTagRoute("description")
+ objDisk["size"] = diskDomB.getTextByTagRoute("size")
+ objDisk["init"] = diskDomB.getTextByTagRoute("init")
+ objDisk["interface"] = diskDomB.getTextByTagRoute("interface")
+ objDiskList[diskDomB.getTextByTagRoute("device")] = objDisk
+ return sourceDiskList == objDiskList
+
+
+def compareDiskDom(diskDomA, diskDomB, requestFlag=True):
+ command = "command.server.disk."
+ if not requestFlag:
+ command = ""
+ sourceDisk = {}
+ sourceDisk["device"] = diskDomA.getTextByTagRoute("device")
+ sourceDisk["description"] = diskDomA.getTextByTagRoute("description")
+ sourceDisk["size"] = diskDomA.getTextByTagRoute("size")
+ sourceDisk["init"] = diskDomA.getTextByTagRoute("init")
+ sourceDisk["interface"] = diskDomA.getTextByTagRoute("interface")
+ for tagE in diskDomA.getElementsByTagRoute("partition"):
+ sourceDiskPartitions = {}
+ partitionDom = XDOM()
+ partitionDom.setDomObj(tagE)
+ sourceDiskPartitions["size"] = partitionDom.getTextByTagRoute("size")
+ #sourceDiskPartitions["free"] = partitionDom.getTextByTagRoute("free")
+ sourceDiskPartitions["format"] = partitionDom.getTextByTagRoute("format")
+ sourceDiskPartitions["uuid"] = partitionDom.getTextByTagRoute("uuid")
+ sourceDisk[partitionDom.getTextByTagRoute("device")] = sourceDiskPartitions
+
+ objDisk = {}
+ objDisk["device"] = diskDomB.getTextByTagRoute(command + "device")
+ objDisk["description"] = diskDomB.getTextByTagRoute(command + "description")
+ objDisk["size"] = diskDomB.getTextByTagRoute(command + "size")
+ objDisk["init"] = diskDomB.getTextByTagRoute(command + "init")
+ objDisk["interface"] = diskDomB.getTextByTagRoute(command + "interface")
+ for tagE in diskDomB.getElementsByTagRoute(command + "partition"):
+ objDiskPartitions = {}
+ partitionDom = XDOM()
+ partitionDom.setDomObj(tagE)
+ objDiskPartitions["size"] = partitionDom.getTextByTagRoute("size")
+ #objDiskPartitions["free"] = partitionDom.getTextByTagRoute("free")
+ objDiskPartitions["format"] = partitionDom.getTextByTagRoute("format")
+ objDiskPartitions["uuid"] = partitionDom.getTextByTagRoute("uuid")
+ objDisk[partitionDom.getTextByTagRoute("device")] = objDiskPartitions
+ return sourceDisk == objDisk
+
+
+def getServerConfigDiskDom(serverName, diskName=None):
+ diskConfigDom = XDOM()
+ if not diskConfigDom.parseFile("%s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)):
+ Utils.log("Unable to parse %s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName))
+ return None
+ diskTag = diskConfigDom.getElementsByTagRoute("disks.disk")
+ if not diskTag:
+ Utils.log("Unable to reterive disk information %s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName))
+ return None
+ if diskName:
+ for tagE in diskTag:
+ diskDom = XDOM()
+ diskDom.setDomObj(tagE)
+ if diskName == diskDom.getTextByTagRoute("device"):
+ return diskDom
+ return None
+
+ for tagE in diskTag:
+ for partitionTag in tagE.getElementsByTagName("partition"):
+ tagE.removeChild(partitionTag)
+ return diskConfigDom
+
+
+def getDeviceMountPoint(device):
+ try:
+ fp = open("/proc/mounts")
+ for token in [line.strip().split() for line in fp.readlines()]:
+ if token and len(token) > 2 and token[0] == device:
+ return token[1]
+ fp.close()
+ except IOError, e:
+ return None
+
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/FsTabUtils.py b/src/com.gluster.storage.management.gateway.scripts/src/FsTabUtils.py
new file mode 100644
index 00000000..fcac4196
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/FsTabUtils.py
@@ -0,0 +1,92 @@
+# 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 Globals
+
+def readFsTab(fsTabFile=Globals.FSTAB_FILE):
+ try:
+ fsTabfp = open(fsTabFile)
+ except IOError, e:
+ log("readFsTab(): " + str(e))
+ return None
+
+ fsTabEntryList = []
+ for line in fsTabfp:
+ tokens = line.strip().split()
+ if not tokens or tokens[0].startswith('#'):
+ continue
+ fsTabEntry = {}
+ fsTabEntry["Device"] = None
+ fsTabEntry["MountPoint"] = None
+ fsTabEntry["FsType"] = None
+ fsTabEntry["Options"] = None
+ fsTabEntry["DumpOption"] = 0
+ fsTabEntry["fsckOrder"] = 0
+ try:
+ fsTabEntry["Device"] = tokens[0]
+ fsTabEntry["MountPoint"] = tokens[1]
+ fsTabEntry["FsType"] = tokens[2]
+ fsTabEntry["Options"] = tokens[3]
+ fsTabEntry["DumpOption"] = tokens[4]
+ fsTabEntry["fsckOrder"] = tokens[5]
+ except IndexError:
+ pass
+ if fsTabEntry["Device"] and fsTabEntry["MountPoint"] and fsTabEntry["FsType"] and fsTabEntry["Options"]:
+ fsTabEntryList.append(fsTabEntry)
+
+ fsTabfp.close()
+ return fsTabEntryList
+
+def writeFsTab(fsTabEntryList, fsTabFile=Globals.FSTAB_FILE):
+ try:
+ fsTabfp = open(fsTabFile, "w")
+ for fsTabEntry in fsTabEntryList:
+ fsTabfp.write("%s\t%s\t%s\t%s\t%s\t%s\n" %
+ (fsTabEntry["Device"], fsTabEntry["MountPoint"],
+ fsTabEntry["FsType"], fsTabEntry["Options"],
+ fsTabEntry["DumpOption"], fsTabEntry["fsckOrder"]))
+ fsTabfp.close()
+ except IOError, e:
+ log("writeFsTab(): " + str(e))
+ return False
+ return True
+
+def addFsTabEntry(fsTabEntry, fsTabFile=Globals.FSTAB_FILE):
+ try:
+ fsTabfp = open(fsTabFile, "a")
+ fsTabfp.write("%s\t%s\t%s\t%s\t%s\t%s\n" %
+ (fsTabEntry["Device"], fsTabEntry["MountPoint"],
+ fsTabEntry["FsType"], fsTabEntry["Options"],
+ fsTabEntry["DumpOption"], fsTabEntry["fsckOrder"]))
+ fsTabfp.close()
+ except IOError, e:
+ log("addFsTabEntry(): " + str(e))
+ return False
+ return True
+
+def removeFsTabEntry(fsTabEntry, fsTabFile=Globals.FSTAB_FILE):
+ fsTabEntryList = readFsTab(fsTabFile)
+ if not fsTabEntryList:
+ return False
+
+ try:
+ fsTabEntryList.remove(fsTabEntry)
+ except ValueError:
+ return False
+
+ return writeFsTab(fsTabEntryList, fsTabFile)
+
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/GetServerNetworkConfig.py b/src/com.gluster.storage.management.gateway.scripts/src/GetServerNetworkConfig.py
new file mode 100644
index 00000000..3311eb56
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/GetServerNetworkConfig.py
@@ -0,0 +1,96 @@
+# Copyright (C) 2009 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 sys
+import syslog
+import Globals
+import Commands
+import re
+from ServerUtils import *
+from Protocol import *
+from NetworkUtils import *
+
+def getServerNetworkConfig(requestXml):
+ serverName = requestXml.getTextByTagRoute("command.server-name")
+ version = requestXml.getVersion()
+ messageId = requestXml.getAttribute("id")
+
+ if not serverName:
+ responseDom = ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, "No server name given", messageId, version)
+ responseDom.appendTagRoute("server.name", serverName)
+ return responseDom
+ responseDom = ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, "OK", messageId, version)
+ serverTag = responseDom.createTag("server", None)
+ serverTag.appendChild(responseDom.createTag("name", serverName))
+ nameServerList, domain, searchDomain = readResolvConfFile()
+ if domain:
+ domainName = domain[0]
+ else:
+ domainName = None
+ serverTag.appendChild(responseDom.createTag("domainname", domainName))
+ i = 1
+ for dns in nameServerList:
+ serverTag.appendChild(responseDom.createTag("dns%s" % i, dns))
+ i += 1
+ #TODO: probe and retrieve timezone, ntp-server, preferred-network details and update the tags
+ configDom = XDOM()
+ if configDom.parseFile("%s/%s/network.xml" % (Globals.SERVER_CONF_DIR, serverName)):
+ serverTag.appendChild(responseDom.createTag("timezone", configDom.getTextByTagRoute("network.timezone")))
+ serverTag.appendChild(responseDom.createTag("ntp-server", configDom.getTextByTagRoute("network.ntp-server")))
+ preferredNetwork = configDom.getTextByTagRoute("network.preferred-network")
+ if not preferredNetwork:
+ preferredNetwork = "any"
+ serverTag.appendChild(responseDom.createTag("preferred-network", preferredNetwork))
+
+ deviceList = {}
+ for device in getNetDeviceList():
+ deviceList[device["device"]] = device
+ try:
+ macAddress = open("/sys/class/net/%s/address" % device["device"]).read().strip()
+ except IOError:
+ continue
+ interfaceTag = responseDom.createTag("interface", None)
+ interfaceTag.appendChild(responseDom.createTag("device", device["device"]))
+ interfaceTag.appendChild(responseDom.createTag("description", device["description"]))
+ interfaceTag.appendChild(responseDom.createTag("hwaddr", macAddress))
+ if deviceList[device["device"]]:
+ if deviceList[device["device"]]["onboot"]:
+ interfaceTag.appendChild(responseDom.createTag("onboot", "yes"))
+ else:
+ interfaceTag.appendChild(responseDom.createTag("onboot", "no"))
+ interfaceTag.appendChild(responseDom.createTag("bootproto", deviceList[device["device"]]["bootproto"]))
+ interfaceTag.appendChild(responseDom.createTag("ipaddr", deviceList[device["device"]]["ipaddr"]))
+ interfaceTag.appendChild(responseDom.createTag("netmask", deviceList[device["device"]]["netmask"]))
+ interfaceTag.appendChild(responseDom.createTag("gateway", deviceList[device["device"]]["gateway"]))
+ if deviceList[device["device"]]["mode"]:
+ interfaceTag.appendChild(responseDom.createTag("mode", deviceList[device["device"]]["mode"]))
+ if deviceList[device["device"]]["master"]:
+ interfaceTag.appendChild(responseDom.createTag("bonding", "yes"))
+ spliter = re.compile(r'[\D]')
+ interfaceTag.appendChild(responseDom.createTag("bondid", spliter.split(device["master"])[-1]))
+ else:
+ interfaceTag.appendChild(responseDom.createTag("onboot", "no"))
+ interfaceTag.appendChild(responseDom.createTag("bootproto", "none"))
+ serverTag.appendChild(interfaceTag)
+ responseDom.appendTag(serverTag)
+ return responseDom
+
+def test():
+ requestString = """<command request="get-server-network-config" id="123" version="3.1.2.2">
+<server-name>s1</server-name></command>"""
+ requestDom = RequestXml(requestString)
+ print getServerNetworkConfig(requestDom).toxml()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/Globals.py b/src/com.gluster.storage.management.gateway.scripts/src/Globals.py
new file mode 100644
index 00000000..f8a07c25
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/Globals.py
@@ -0,0 +1,123 @@
+# 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/>.
+
+MULTICAST_GROUP = '224.224.1.1'
+MULTICAST_PORT = 5353
+GLUSTER_PLATFORM_VERSION = "3.2"
+
+## System configuration constants
+SYSCONFIG_NETWORK_DIR = "/etc/sysconfig/network-scripts"
+DNSMASQ_CONF_DIR = "/etc/dnsmasq.d"
+
+FSTAB_FILE = "/etc/fstab"
+NFS_EXPORTS_FILE = "/etc/exports"
+SAMBA_CONF_FILE = "/etc/samba/smb.conf"
+TIMEZONE_FILE = "/etc/timezone"
+ZONEINFO_DIR = "/usr/share/zoneinfo"
+LOCALTIME_FILE = "/etc/localtime"
+KERBEROS_CONF_FILE = "/etc/krb5.conf"
+NSSWITCH_CONF_FILE = "/etc/nsswitch.conf"
+NTP_CONF_FILE = "/etc/ntp.conf"
+MODPROBE_CONF_FILE = "/etc/modprobe.d/bonding.conf"
+SYSCONFIG_NETWORK_FILE = "/etc/sysconfig/network"
+RESOLV_CONF_FILE = "/etc/resolv.conf"
+DNSMASQ_LEASE_FILE = "/var/tmp/dnsmasq.leases"
+LIVE_MODE_FILE = "/etc/live"
+ADD_SERVER_COMPLETED_FILE = "/var/tmp/installation-completed"
+
+DNSMASQ_DNS_CONF_FILE = DNSMASQ_CONF_DIR + "/dns.conf"
+DNSMASQ_DHCP_CONF_FILE = DNSMASQ_CONF_DIR + "/dhcp.conf"
+##
+
+## Base constants
+MAX_PARTITION_SIZE = 16777216 # 16 TB
+OS_PARTITION_SIZE = 4000 # 4 GB
+SESSION_TIMEOUT = 1800 # 30 minutes
+SERVER_AGENT_PORT = 50000
+
+BOOT_PARTITION_LABEL = "GLUSTEROS"
+DATA_PARTITION_LABEL = "GLUSTERDATA"
+VOLUME_USER_DESCRIPTION = "Gluster Volume User"
+SERVER_AGENT_RUN_USERNAME = "gluster"
+INSTALLER_SERVER_NAME = "$installer$"
+
+GLUSTER_BASE_DIR = "/etc/glustermg"
+GLUSTER_LUN_DIR = "/data"
+REEXPORT_DIR = "/reexport"
+NFS_EXPORT_DIR = "/nfs"
+CIFS_EXPORT_DIR = "/cifs"
+WEBDAV_DOCUMENT_ROOT_DIR = "/var/www/html"
+UPDATES_DIR = "/UPDATES"
+TRANSPORT_HOME_DIR = "/transport"
+GLUSTERFS_LOG_DIR = "/var/log/glusterfs"
+LOG_DIR = "/var/log/glustermg"
+
+GLUSTER_UPDATES_FILE = "updates.xml"
+INSTALLER_STATUS_FILE = "/var/log/install-server-status.log"
+INSTALL_PLATFORM_LOCK_FILE = "/var/lock/install-gluster-platform.lock"
+LAST_ACCESSED_NETWORK_FILE = "last-accessed-network"
+PREPARE_DATA_DISK_LOCK_FILE = "/var/tmp/prepare-data-disk.lock"
+##
+
+## Derived constants
+GLUSTER_CONF_DIR = GLUSTER_BASE_DIR + "/conf"
+GLUSTER_TMP_DIR = GLUSTER_BASE_DIR + "/tmp"
+VOLUME_CONF_DIR = GLUSTER_BASE_DIR + "/volumes"
+SERVER_CONF_DIR = GLUSTER_BASE_DIR + "/servers"
+DNS_RECORDS_DIR = GLUSTER_BASE_DIR + "/dns-records"
+INSTALLER_CONF_DIR = SERVER_CONF_DIR + "/" + INSTALLER_SERVER_NAME
+
+GSN_USER_INFO_FILE = GLUSTER_BASE_DIR + "/gsn-user.info"
+GLUSTER_VERSION_FILE = GLUSTER_BASE_DIR + "/version"
+GLUSTER_UPDATE_SITE_FILE = GLUSTER_BASE_DIR + "/update-site"
+GLUSTER_DIRECTORY_SERVICE_CONF_FILE = GLUSTER_BASE_DIR + "/directory.xml"
+GLUSTER_TIME_CONF_FILE = GLUSTER_BASE_DIR + "/timeconfig.xml"
+TRANSACTION_KEY_FILE = GLUSTER_BASE_DIR + "/transaction.key"
+SERVER_COUNT_FILE = GLUSTER_BASE_DIR + "/server-count"
+SIGNATURE_FILE = GLUSTER_BASE_DIR + "/.signature"
+GLUSTER_SERVER_POOL_FILE = GLUSTER_BASE_DIR + "/pool"
+GLUSTER_ADMIN_FILE = GLUSTER_BASE_DIR + "/.password"
+
+VOLUME_SMBCONF_FILE = VOLUME_CONF_DIR + "/volumes.smbconf.list"
+
+GLOBAL_NETWORK_FILE = INSTALLER_CONF_DIR + "/network.xml"
+INSTALL_SERVER_CONF_FILE = INSTALLER_CONF_DIR + "/installer.xml"
+INSTALLER_INFO_FILE = INSTALLER_CONF_DIR + "/installer.info"
+INSTALLED_SERVER_COUNT_FILE = INSTALLER_CONF_DIR + "/installed-server-count"
+
+SESSION_FILE = GLUSTER_TMP_DIR + "/login.sessions"
+
+GENERAL_LOG_FILE = LOG_DIR + "/general.log"
+INSTALLER_LOG_FILE = LOG_DIR + "/installer.log"
+PEER_AGENT_LOG_FILE = LOG_DIR + "/peeragent.log"
+SERVER_AGENT_LOG_FILE = LOG_DIR + "/serveragent.log"
+TRANSPORT_AGENT_LOG_FILE = LOG_DIR + "/transport.log"
+##
+
+
+## Global variables
+## TODO: These should be removed
+DOWNLOAD_GLUSTER_UPDATE_PROCESS = None
+DOWNLOAD_GLUSTER_UPDATE_LEVEL = None
+DOWNLOAD_GLUSTER_CURRENT_UPDATE_LEVEL = None
+DOWNLOAD_GLUSTER_UPDATE_MD5SUM = None
+REQUEST_MAP = {}
+VERSION_DICTONARY = {}
+##
+
+AWS_WEB_SERVICE_URL = "http://169.254.169.254/latest"
+REAL_SAMBA_CONF_FILE = "/etc/samba/real.smb.conf"
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/GlusterdUtils.py b/src/com.gluster.storage.management.gateway.scripts/src/GlusterdUtils.py
new file mode 100644
index 00000000..7c0e899c
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/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.gateway.scripts/src/NetworkUtils.py b/src/com.gluster.storage.management.gateway.scripts/src/NetworkUtils.py
new file mode 100755
index 00000000..42e9892c
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/NetworkUtils.py
@@ -0,0 +1,483 @@
+# 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 sys
+
+if not "/usr/share/system-config-network/" in sys.path:
+ sys.path.append("/usr/share/system-config-network")
+
+import os
+import tempfile
+import Globals
+
+from Utils import *
+#from netconfpkg.NCHardwareList import getHardwareList
+
+def readHostFile(fileName=None):
+ hostEntryList = []
+ if not fileName:
+ fileName = "/etc/hosts"
+ try:
+ for line in open(fileName):
+ tokens = line.split("#")[0].strip().split()
+ if len(tokens) < 2:
+ continue
+ hostEntryList.append({tokens[0] : tokens[1:]})
+ return hostEntryList
+ except IOError:
+ log("failed to read %s file" % fileName)
+ return None
+
+
+def writeHostFile(hostEntryList, fileName=None):
+ if fileName:
+ hostFile = fileName
+ else:
+ hostFile = tempfile.mktemp(prefix="GSPSA")
+ try:
+ fp = open(hostFile, "w")
+ for host in hostEntryList:
+ fp.write("%s\t%s\n" % (host.keys()[0], " ".join(host.values()[0])))
+ fp.close()
+ if hostFile == fileName:
+ return True
+ except IOError:
+ log("failed to write %s file" % hostFile)
+ return False
+ if runCommandFG("mv -f %s /etc/hosts" % hostFile, root=True) != 0:
+ log("failed to rename file %s to /etc/hosts" % hostFile)
+ return False
+ return True
+
+
+def readResolvConfFile(fileName=None, includeLocalHost=False):
+ nameServerList = []
+ domain = None
+ searchDomain = None
+ if not fileName:
+ fileName = Globals.RESOLV_CONF_FILE
+ try:
+ for line in open(fileName):
+ tokens = line.split("#")[0].strip().split()
+ if len(tokens) < 2:
+ continue
+ if tokens[0].upper() == "NAMESERVER":
+ if includeLocalHost == False and tokens[1] == "127.0.0.1":
+ continue
+ nameServerList.append(tokens[1])
+ continue
+ if tokens[0].upper() == "DOMAIN":
+ domain = tokens[1:]
+ continue
+ if tokens[0].upper() == "SEARCH":
+ searchDomain = tokens[1:]
+ continue
+ return nameServerList, domain, searchDomain
+ except IOError:
+ log("failed to read %s file" % fileName)
+ return None, None, None
+
+
+def writeResolvConfFile(nameServerList, domain, searchDomain, fileName=None, appendLocalHost=True):
+ if fileName:
+ resolvConfFile = fileName
+ else:
+ resolvConfFile = tempfile.mktemp(prefix="GSPSA")
+ try:
+ fp = open(resolvConfFile, "w")
+ if appendLocalHost:
+ fp.write("nameserver 127.0.0.1\n")
+ for nameServer in nameServerList:
+ fp.write("nameserver %s\n" % nameServer)
+ if domain:
+ fp.write("domain %s\n" % " ".join(domain))
+ if searchDomain:
+ fp.write("search %s\n" % " ".join(searchDomain))
+ fp.close()
+ if resolvConfFile == fileName:
+ return True
+ except IOError:
+ log("failed to write %s file" % resolvConfFile)
+ return False
+ if runCommandFG("mv -f %s %s" % (resolvConfFile, Globals.RESOLV_CONF_FILE), root=True) != 0:
+ log("failed to rename file %s to %s" % (resolvConfFile, Globals.RESOLV_CONF_FILE))
+ return False
+ return True
+
+
+def readIfcfgConfFile(deviceName, root=""):
+ conf = {}
+ fileName = "%s%s/ifcfg-%s" % (root, Globals.SYSCONFIG_NETWORK_DIR, deviceName)
+ try:
+ for line in open(fileName):
+ tokens = line.split("#")[0].split("=")
+ if len(tokens) != 2:
+ continue
+ conf[tokens[0].strip().lower()] = tokens[1].strip()
+ return conf
+ except IOError:
+ log("failed to read %s file" % fileName)
+ return None
+
+
+def writeIfcfgConfFile(deviceName, conf, root="", deviceFile=None):
+ if not deviceFile:
+ deviceFile = "%s%s/ifcfg-%s" % (root, Globals.SYSCONFIG_NETWORK_DIR, deviceName)
+ if root:
+ ifcfgConfFile = deviceFile
+ else:
+ ifcfgConfFile = tempfile.mktemp(prefix="GSPSA")
+ try:
+ fp = open(ifcfgConfFile, "w")
+ for key in conf.keys():
+ if key == "description":
+ fp.write("#%s=%s\n" % (key.upper(), conf[key]))
+ continue
+ if key in ['link', 'mode']:
+ continue
+ if conf["device"].startswith("bond") and key in ['hwaddr', 'master', 'slave']:
+ continue
+ if key == "slave" and conf['master']:
+ fp.write("SLAVE=yes\n")
+ continue
+ if key == "onboot":
+ if conf[key] == True:
+ fp.write("ONBOOT=yes\n")
+ elif isString(conf[key]) and conf[key].upper() == "YES":
+ fp.write("ONBOOT=yes\n")
+ else:
+ fp.write("ONBOOT=no\n")
+ continue
+ if not conf[key]:
+ continue
+ fp.write("%s=%s\n" % (key.upper(), conf[key]))
+ fp.close()
+ if ifcfgConfFile == deviceFile:
+ return True
+ except IOError:
+ log("failed to write %s file" % ifcfgConfFile)
+ return False
+ if runCommandFG("mv -f %s %s" % (ifcfgConfFile, deviceFile), root=True) != 0:
+ log("failed to rename file %s to %s" % (ifcfgConfFile, deviceFile))
+ return False
+ return True
+
+def getNetDeviceDetail(deviceName):
+ deviceDetail = {}
+ deviceDetail['Name'] = deviceName
+ rv = runCommandFG("ifconfig %s" % deviceName, stdout=True, root=True)
+ if rv["Status"] != 0:
+ return False
+ for line in rv["Stdout"].split():
+ tokens = line.strip().split(":")
+ if tokens[0].upper() == "ENCAP":
+ deviceDetail['Model'] = tokens[1].strip().upper()
+ break
+
+ for line in rv["Stdout"].split("\n"):
+ if line.strip().startswith("inet addr:"):
+ tokens = line.strip().split(":")
+ if tokens[0].upper() == "INET ADDR":
+ try:
+ deviceDetail['Ip'] = tokens[1].strip().split()[0]
+ deviceDetail['Mask'] = tokens[-1].strip()
+ except IndexError:
+ pass
+ break
+ return deviceDetail
+
+def getNetDeviceGateway(deviceName):
+ rv = runCommand("route -n", output=True, root=True)
+ if rv["Status"] != 0:
+ return None
+ if not rv["Stdout"]:
+ return None
+ lines = [line for line in rv["Stdout"].split("\n") if line.find("UG") != -1 and line.find(deviceName)]
+ if not lines:
+ return None
+ line = lines[-1].split()
+ if line and len(line) > 1:
+ return line[1]
+ return None
+
+def getNetSpeed(deviceName):
+ rv = runCommandFG("ethtool %s" % deviceName, stdout=True, root=True)
+ if rv["Status"] != 0:
+ return False
+ for line in rv["Stdout"].split("\n"):
+ tokens = line.strip().split(":")
+ if tokens[0].upper() == "SPEED":
+ return tokens[1].strip().upper().split("MB")[0]
+ return None
+
+def getLinkStatus(deviceName):
+ return True
+ ## ethtool takes very long time to respond. So its disabled now
+ rv = runCommandFG("ethtool %s" % deviceName, stdout=True, root=True)
+ if rv["Status"] != 0:
+ return False
+ for line in rv["Stdout"].split("\n"):
+ tokens = line.strip().split(":")
+ if tokens[0].upper() == "LINK DETECTED":
+ if tokens[1].strip().upper() == "YES":
+ return True
+ else:
+ return False
+ return False
+
+
+def getBondMode(deviceName, fileName=None):
+ if not fileName:
+ fileName = Globals.MODPROBE_CONF_FILE
+ try:
+ for line in open(fileName):
+ tokens = line.split("#")[0].split()
+ if len(tokens) < 4:
+ continue
+ if tokens[0].upper() == "OPTIONS" and tokens[1] == deviceName:
+ if tokens[2].startswith("mode="):
+ return tokens[2].split("=")[1]
+ if tokens[3].startswith("mode="):
+ return tokens[3].split("=")[1]
+ if tokens[4].startswith("mode="):
+ return tokens[4].split("=")[1]
+ if tokens[5].startswith("mode="):
+ return tokens[5].split("=")[1]
+ return None
+ except IOError:
+ log("failed to read %s file" % fileName)
+ return None
+
+
+def setBondMode(deviceName, mode, fileName=None):
+ if not fileName:
+ fileName = Globals.MODPROBE_CONF_FILE
+ tempFileName = getTempFileName()
+ try:
+ fp = open(tempFileName, "w")
+ lines = open(fileName).readlines()
+ except IOError:
+ log("unable to open file %s" % Globals.MODPROBE_CONF_FILE)
+ return False
+ for line in lines:
+ tokens = line.split()
+ if len(tokens) > 1 and "OPTIONS" == tokens[0].upper() and "BOND" in tokens[1].upper() and deviceName == tokens[1]:
+ fp.write("options %s max_bonds=2 mode=%s miimon=100\n" % (deviceName, mode))
+ deviceName = None
+ continue
+ fp.write(line)
+ if deviceName:
+ fp.write("alias %s bonding\n" % deviceName)
+ fp.write("options %s max_bonds=2 mode=%s miimon=100\n" % (deviceName, mode))
+ fp.close()
+ if runCommandFG(["mv", "-f", tempFileName, fileName], root=True) != 0:
+ log("unable to move file from %s to %s" % (tempFileName, fileName))
+ return False
+ return True
+
+def getNetDeviceList(root=""):
+ netDeviceList = []
+ for deviceName in os.listdir("/sys/class/net/"):
+ netDevice = {}
+ netDevice["device"] = None
+ netDevice["description"] = None
+ netDevice["hwaddr"] = None
+ netDevice["type"] = None
+ netDevice["onboot"] = None
+ netDevice["bootproto"] = None
+ netDevice["gateway"] = None
+ netDevice["peerdns"] = None
+ netDevice["autodns"] = None
+ netDevice["dns1"] = None
+ netDevice["dns2"] = None
+ netDevice["dns3"] = None
+ netDevice["master"] = None
+ netDevice["slave"] = None
+ netDevice["nmcontrolled"] = None
+ netDevice["link"] = None
+ netDevice["mode"] = None
+
+ #netDevice["device"] = device.Name
+ netDevice["device"] = deviceName
+ #netDevice["description"] = device.Description
+ netDevice["description"] = deviceName
+ #netDevice["type"] = device.Type
+ netDevice["type"] = None
+ netDevice["link"] = getLinkStatus(deviceName)
+ netDevice["mode"] = getBondMode(deviceName, root + Globals.MODPROBE_CONF_FILE)
+ deviceDetail = getNetDeviceDetail(deviceName)
+ if deviceDetail.has_key('Model'):
+ netDevice["model"] = deviceDetail['Model']
+ else:
+ netDevice["model"] = None
+ if deviceDetail.has_key('Ip'):
+ netDevice["ipaddr"] = deviceDetail['Ip']
+ else:
+ netDevice["ipaddr"] = None
+ if deviceDetail.has_key('Mask'):
+ netDevice["netmask"] = deviceDetail['Mask']
+ else:
+ netDevice["netmask"] = None
+ netDevice["speed"] = getNetSpeed(deviceName)
+ try:
+ netDevice["hwaddr"] = open("/sys/class/net/%s/address" % deviceName).read().strip()
+ except IOError:
+ pass
+
+ netDeviceList.append(netDevice)
+
+ conf = readIfcfgConfFile(deviceName, root)
+ if not conf:
+ continue
+ try:
+ netDevice["onboot"] = conf["onboot"]
+ except KeyError:
+ pass
+ try:
+ netDevice["bootproto"] = conf["bootproto"]
+ except KeyError:
+ pass
+ if conf.has_key("ipaddr") and conf["ipaddr"]:
+ netDevice["ipaddr"] = conf["ipaddr"]
+ try:
+ netDevice["netmask"] = conf["netmask"]
+ except KeyError:
+ pass
+ if conf.has_key("gateway") and conf["gateway"]:
+ netDevice["gateway"] = conf["gateway"]
+ else:
+ netDevice["gateway"] = getNetDeviceGateway(deviceName)
+ try:
+ netDevice["peerdns"] = conf["peerdns"]
+ except KeyError:
+ pass
+ try:
+ netDevice["autodns"] = conf["autodns"]
+ except KeyError:
+ pass
+ try:
+ netDevice["dns1"] = conf["dns1"]
+ except KeyError:
+ pass
+ try:
+ netDevice["dns2"] = conf["dns2"]
+ except KeyError:
+ pass
+ try:
+ netDevice["dns3"] = conf["dns3"]
+ except KeyError:
+ pass
+ try:
+ netDevice["master"] = conf["master"]
+ except KeyError:
+ pass
+ try:
+ netDevice["slave"] = conf["slave"]
+ except KeyError:
+ pass
+ try:
+ netDevice["nmcontrolled"] = conf["nmcontrolled"]
+ except KeyError:
+ pass
+
+ return netDeviceList
+
+ ## bondDevices = [os.path.basename(device) for device in glob.glob("/sys/class/net/bond*")]
+
+ ## bondDevices = [os.path.basename(device) for device in glob.glob("/sys/class/net/bond*")]
+ ## for deviceName in bondDevices:
+ ## if deviceName in linkedBondList:
+ ## if deviceName in sysConfigDeviceList:
+ ## deviceList[deviceName] = sysConfigDeviceList[deviceName]
+ ## else:
+ ## deviceList[deviceName] = {'device':deviceName, 'onboot':'no', 'bootproto':'none'}
+ ## continue
+ ## if len(ethDevices) > 2:
+ ## deviceList[deviceName] = {'device':deviceName, 'onboot':'no', 'bootproto':'none'}
+
+
+def configureDhcpServer(serverIpAddress, dhcpIpAddress):
+ tmpDhcpConfFile = tempfile.mktemp(prefix="GSPSA")
+
+ serverPortString = "68"
+ try:
+ for arg in open("/proc/cmdline").read().strip().split():
+ token = arg.split("=")
+ if token[0] == "dhcp":
+ serverPortString = token[1]
+ break
+ except IOError:
+ log(syslog.LOG_ERR, "Failed to read /proc/cmdline. Continuing with default port 68")
+ try:
+ serverPort = int(serverPortString)
+ except ValueError:
+ log(syslog.LOG_ERR, "Invalid dhcp port '%s' in /proc/cmdline. Continuing with default port 68" % serverPortString)
+ serverPort = 68
+
+ try:
+ fp = open(tmpDhcpConfFile, "w")
+ fp.write("bind-interfaces\n")
+ fp.write("except-interface=lo\n")
+ fp.write("dhcp-range=%s,%s\n" % (dhcpIpAddress, dhcpIpAddress))
+ fp.write("dhcp-lease-max=1\n")
+ fp.write("dhcp-alternate-port=%s\n" % serverPort)
+ fp.write("dhcp-leasefile=%s\n" % Globals.DNSMASQ_LEASE_FILE)
+ #fp.write("server=%s\n" % serverIpAddress)
+ #fp.write("dhcp-script=/usr/sbin/server-info\n")
+ fp.close()
+ except IOError:
+ log(syslog.LOG_ERR, "unable to write dnsmasq dhcp configuration %s" % tmpDhcpConfFile)
+ return False
+ if runCommandFG("mv -f %s %s" % (tmpDhcpConfFile, Globals.DNSMASQ_DHCP_CONF_FILE), root=True) != 0:
+ log(syslog.LOG_ERR, "unable to copy dnsmasq dhcp configuration to %s" % Globals.DNSMASQ_DHCP_CONF_FILE)
+ return False
+ return True
+
+
+def isDhcpServer():
+ return os.path.exists(Globals.DNSMASQ_DHCP_CONF_FILE)
+
+
+def getDhcpServerStatus():
+ if runCommandFG("service dnsmasq status", root=True) == 0:
+ return True
+ return False
+
+
+def startDhcpServer():
+ if runCommandFG("service dnsmasq start", root=True) == 0:
+ return True
+ return False
+
+
+def stopDhcpServer():
+ if runCommandFG("service dnsmasq stop", root=True) == 0:
+ runCommandFG("rm -f %s" % Globals.DNSMASQ_LEASE_FILE, root=True)
+ return True
+ return False
+
+
+def restartDhcpServer():
+ stopDhcpServer()
+ runCommandFG("rm -f %s" % Globals.DNSMASQ_LEASE_FILE, root=True)
+ return startDhcpServer()
+
+
+def reloadDhcpServer():
+ if runCommandFG("service dnsmasq reload", root=True) == 0:
+ return True
+ return False
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/Protocol.py b/src/com.gluster.storage.management.gateway.scripts/src/Protocol.py
new file mode 100644
index 00000000..ff073593
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/Protocol.py
@@ -0,0 +1,438 @@
+# Copyright (C) 2009 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 xml
+import xml.parsers.expat
+import xml.dom.minidom as MDOM
+import os
+import Globals
+import copy
+import Utils
+
+XML_STRING = 0
+XML_FILE = 1
+
+class XDOM:
+ _domObj = None
+
+ def __init__(self):
+ self._domObj = MDOM.Document()
+ return
+
+ @classmethod
+ def getText(self, nodeList):
+ rc = ""
+ for node in nodeList:
+ if node.nodeType == node.TEXT_NODE:
+ rc = rc + node.data
+ return rc.strip()
+
+ def parseString(self, requestString):
+ try:
+ self._domObj = MDOM.parseString(requestString)
+ except xml.parsers.expat.ExpatError, e:
+ Utils.log("XML string parse error: %s" % str(e))
+ return False
+ return True
+
+ def parseFile(self, fileName):
+ try:
+ self._domObj = MDOM.parse(fileName)
+ except IOError, e:
+ Utils.log("error reading file: %s" % str(e))
+ return False
+ except xml.parsers.expat.ExpatError, e:
+ Utils.log("XML file %s parse error: %s" % (fileName, str(e)))
+ return False
+ return True
+
+ def setDomObj(self, dom):
+ if dom and type(dom) != type([]):
+ self._domObj = dom
+ return True
+ return False
+
+ def createTextNode(self, text):
+ if not self._domObj:
+ return False
+ if not text:
+ return False
+ return self._domObj.createTextNode(str(text))
+
+ def createTag(self, tag, text=None):
+ if not self._domObj:
+ return None
+ if tag == None:
+ return None
+
+ tagE = self._domObj.createElement(str(tag))
+ if text:
+ tagEText = self._domObj.createTextNode(str(text))
+ tagE.appendChild(tagEText)
+ return tagE
+
+ def addTag(self, tag):
+ if not self._domObj:
+ return False
+ if not tag:
+ return False
+
+ self._domObj.appendChild(tag)
+ return True
+
+ def createTagRoute(self, tagRoute, text=None):
+ if not tagRoute:
+ return False
+
+ tagList = tagRoute.split(".")
+ tag = None
+ previousTag = None
+ for tagName in tagList[:-1]:
+ newTag = self.createTag(tagName, None)
+ if not tag:
+ tag = newTag
+ previousTag = newTag
+ continue
+ previousTag.appendChild(newTag)
+ previousTag = newTag
+
+ if previousTag:
+ previousTag.appendChild(self.createTag(tagList[-1], text))
+ else:
+ tag = self.createTag(tagList[-1], text)
+ return tag
+
+ def appendTagRoute(self, tagRoute, value=None):
+ if not self._domObj:
+ return False
+ if not tagRoute:
+ return False
+
+ parentTagE = self._domObj
+
+ tagNameList = tagRoute.split(".")
+ newTagRoute = tagNameList.pop(-1)
+
+ for i in range(len(tagNameList), 0, -1):
+ tagE = self.getElementsByTagRoute(".".join(tagNameList[:i]))
+ if tagE:
+ parentTagE = tagE[0]
+ break
+ newTagRoute = tagNameList[i-1] + "." + newTagRoute
+
+ newTagE = self.createTagRoute(newTagRoute, value)
+ if not newTagE:
+ return False
+ try:
+ parentTagE.appendChild(newTagE)
+ except xml.dom.HierarchyRequestErr, e:
+ Utils.log("error occured. %s" + str(e))
+ return False
+ return True
+
+ def setTextByTagRoute(self, tagRoute, tagValue):
+ if not self._domObj:
+ return None
+
+ if not tagRoute:
+ return None
+
+ tagE = self.getElementsByTagRoute(tagRoute)
+ if not tagE:
+ return False
+
+ parentTagE = self.getElementsByTagRoute(".".join(tagRoute.split(".")[:-1]))
+ if not parentTagE:
+ return False
+
+ parentTagE[0].childNodes.remove(tagE[0])
+ parentTagE[0].appendChild(self.createTag(tagRoute.split(".")[-1], tagValue))
+ return True
+
+ def getElementsByTagRoute(self, tagRoute):
+ if not self._domObj:
+ return None
+
+ if not tagRoute:
+ return None
+
+ x = None
+ for tag in tagRoute.split("."):
+ if x is None:
+ x = self._domObj.getElementsByTagName(tag)
+ continue
+ if x == []:
+ break
+ x = x[0].getElementsByTagName(tag)
+ return x
+
+ def getTextByTagRoute(self, tagRoute):
+ if not self._domObj:
+ return None
+
+ x = self.getElementsByTagRoute(tagRoute)
+ if x:
+ return self.getText(x[0].childNodes)
+ return None
+
+ def getElementsByTagName(self, name):
+ if not self._domObj:
+ return None
+ return self._domObj.getElementsByTagName(name)
+
+ def writexml(self, fileName, indent="", addindent="", newl=""):
+ if not self._domObj:
+ return None
+ try:
+ fp = open(fileName, "w")
+ self._domObj.writexml(fp, indent, addindent, newl)
+ fp.close()
+ return True
+ except IOError:
+ return False
+
+ def toString(self, indent=" ", newl="\n", encoding = None):
+ if not self._domObj:
+ return None
+ return self._domObj.toprettyxml(indent, newl, encoding)
+
+ def toxml(self, encoding = None):
+ if not self._domObj:
+ return None
+ return self._domObj.toxml(encoding)
+
+ def toprettyxml(self, indent=" ", newl="\n", encoding = None):
+ return self.toString(indent, newl, encoding)
+
+ def getAttribute(self, attributeName):
+ if not attributeName:
+ return None
+ try:
+ return self.getElementsByTagName("command")[0].getAttribute(attributeName)
+ except IndexError:
+ return False
+
+ def setAttribute(self, attributeName, attributeValue):
+ if not (attributeName and attributeValue):
+ return None
+ try:
+ return self.getElementsByTagName("command")[0].setAttribute(attributeName, attributeValue)
+ except IndexError:
+ return False
+
+ def getRequestCommand(self):
+ return self.getAttribute("request")
+
+ def getResponseCommand(self):
+ return self.getAttribute("response")
+
+ def getResponseCode(self):
+ return self.getAttribute("response-code")
+
+ def getMessageId(self):
+ return self.getAttribute("id")
+
+ def getVersion(self):
+ return self.getAttribute("version")
+
+ def getRequestAction(self):
+ return self.getAttribute("action")
+
+ def setVersion(self, value):
+ return self.setAttribute("version", value)
+
+ def setRequestAction(self, value):
+ return self.setAttribute("action", value)
+
+ def createCommandTag(self, command, responseCode, id, version=Globals.GLUSTER_PLATFORM_VERSION):
+ commandTag = self._domObj.createElement("command")
+ commandTag.setAttribute("response", command)
+ commandTag.setAttribute("response-code", responseCode)
+ commandTag.setAttribute("id", id)
+ commandTag.setAttribute("version", version)
+ return commandTag
+##--end of XDOM
+
+class RequestXml(XDOM):
+ def __init__(self, requestString, type=None):
+ if None == requestString:
+ XDOM.__init__(self)
+ return
+ try:
+ if None == type:
+ if os.path.isfile(requestString):
+ self._domObj = MDOM.parse(requestString)
+ else:
+ self._domObj = MDOM.parseString(requestString)
+ elif XML_FILE == type:
+ self._domObj = MDOM.parse(requestString)
+ elif XML_STRING == type:
+ self._domObj = MDOM.parseString(requestString)
+ except IOError:
+ XDOM.__init__(self)
+ except xml.parsers.expat.ExpatError:
+ XDOM.__init__(self)
+
+##--end of RequestXML
+
+class ResponseXml(XDOM):
+ _commandTag = None
+ def __init__(self, command, responseCode, id, version=Globals.GLUSTER_PLATFORM_VERSION):
+ XDOM.__init__(self)
+ if command and responseCode and id:
+ self._commandTag = self.createCommandTag(command, responseCode, id, version)
+ self._domObj.appendChild(self._commandTag)
+
+ def appendCommand(self, command, responseCode, id, version=Globals.GLUSTER_PLATFORM_VERSION):
+ if command and responseCode and id:
+ self._commandTag = self.createCommandTag(command, responseCode, id, version)
+ self._domObj.appendChild(self._commandTag)
+ return True
+ return False
+
+ def append(self, tagName, tagValue=None):
+ if not self._commandTag:
+ return False
+ tag = self.createTag(tagName, tagValue)
+ if tag:
+ self._commandTag.appendChild(tag)
+ return True
+ return False
+
+ def appendTag(self, tag):
+ if not tag:
+ return False
+ if not self._commandTag:
+ return False
+ self._commandTag.appendChild(tag)
+ return True
+
+ def appendTagRoute(self, tagRoute, value=None):
+ if not self._commandTag:
+ return False
+ if not tagRoute:
+ return False
+
+ parentTagE = self._commandTag
+
+ tagNameList = tagRoute.split(".")
+ newTagRoute = tagNameList.pop(-1)
+
+ for i in range(len(tagNameList), 0, -1):
+ tagE = self.getElementsByTagRoute(".".join(["command"] + tagNameList[:i]))
+ if tagE:
+ parentTagE = tagE[0]
+ break
+ newTagRoute = tagNameList[i-1] + "." + newTagRoute
+
+ newTagE = self.createTagRoute(newTagRoute, value)
+ if not newTagE:
+ return False
+ try:
+ parentTagE.appendChild(newTagE)
+ except xml.dom.HierarchyRequestErr, e:
+ Utils.log("error occured. %s" + str(e))
+ return False
+ return True
+
+ def appendTagRouteOld(self, tagRoute, value=None):
+ if not tagRoute:
+ return False
+ if not self._commandTag:
+ return False
+
+ tmpTagRoute = ""
+ previousTagE = self._commandTag
+ tagE = None
+ for tagName in tagRoute.split("."):
+ if not tmpTagRoute:
+ tagE = self.getElementsByTagRoute("command." + tagName)
+ else:
+ tagE = self.getElementsByTagRoute("command." + tmpTagRoute + "." + tagName)
+ if not tagE:
+ break
+ if len(tagE) != 1:
+ return False
+ previousTagE = tagE[0]
+ if not tmpTagRoute:
+ tmpTagRoute = tagName
+ else:
+ tmpTagRoute = tmpTagRoute + "." + tagName
+
+ if tmpTagRoute == tagRoute:
+ return False
+ newTagRoute = tagRoute[len(tmpTagRoute):]
+ if newTagRoute[0] == '.':
+ newTagRoute = newTagRoute[1:]
+
+ if previousTagE.childNodes and previousTagE.childNodes[0].nodeType == previousTagE.TEXT_NODE:
+ return False
+ previousTagE.appendChild(self.createTagRoute(newTagRoute, value))
+ return True
+##--end of ResponseXml
+
+def test():
+ #volumes = RequestXml(VolumeFile, XML_FILE).getElementsByTagRoute("volume-list.volume")
+ requestStr = '''<command request="create-volume" id="123" version="3.1">
+<volume>
+<name>movies1</name>
+<type>cluster mirror</type>
+<start>512000</start>
+<server>zresearch</server>
+<vacl>192.168.20.*</vacl>
+<vacl>192.168.30.*</vacl>
+<nfs>
+<export>no</export>
+</nfs>
+<cifs>
+<export>no</export>
+</cifs>
+<webdav>
+<export>no</export>
+</webdav>
+</volume>
+</command>'''
+
+ requestXml = RequestXml(requestStr)
+ print requestXml.getAttribute("")
+
+def test1():
+ rs = ResponseXml("create-volume", "OK", "xyz")
+ rs.appendTagRoute("volume.detail.name", "music")
+ print rs.toprettyxml()
+ rs.append("volume", "data")
+ print rs.toprettyxml()
+ rs.appendTagRoute("volume.detail.ipaddr", "192.168.10.1")
+ print rs.toprettyxml()
+ print rs.appendTagRoute("volume.detail.ipaddr.v6", "ff:ff::ff::")
+ print rs.toprettyxml()
+
+ print rs.getTextByTagRoute("command.volume.detail")
+
+def test2():
+ rs = ResponseXml("download-volume-logs", "OK", "xyz")
+ te = rs.createTag("interface", None)
+ te.appendChild(rs.createTag("device", "DEVICE1"))
+ te.appendChild(rs.createTag("description", "my device one"))
+ rs.appendTag(te)
+
+ te = rs.createTag("interface", None)
+ te.appendChild(rs.createTag("device", "DEVICE2"))
+ te.appendChild(rs.createTag("description", "my device two"))
+ rs.appendTag(te)
+ print rs.toprettyxml()
+
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/RRDUtils.py b/src/com.gluster.storage.management.gateway.scripts/src/RRDUtils.py
new file mode 100644
index 00000000..1ad0deee
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/RRDUtils.py
@@ -0,0 +1,72 @@
+import rrdtool
+import os
+from socket import gethostname
+from itertools import groupby
+
+class RRD:
+ def __init__ (self):
+ self.COLORS = [0xff7777, 0x7777ff, 0x55ff55, 0xffcc77, 0xff77ff, 0x77ffff,0xffff77, 0x55aaff]
+ self.HOST = gethostname()
+ self.DIR = "/var/lib/collectd"
+
+ def fade_component(self, component):
+ return ((component + 255 * 5) / 6)
+
+ def fade_color(self, color):
+ r = 0;
+ for i in [0,1,2]:
+ shft = (i * 8)
+ component = ((color >> shft) & 255)
+ r |= (self.fade_component(component) << shft)
+ return r
+
+ def generate_pngs(self):
+
+ rrdlist = os.popen ("find %s -type f -name '*.rrd'" % self.DIR)
+
+ for rrd in rrdlist:
+ self.dss = []
+ self.defs = ""
+
+ rrdinfo = rrdtool.info(rrd.strip())
+
+ for key in rrdinfo.keys():
+ if key.split('[')[0] == 'ds':
+ self.dss.append(key.split('[')[1].split(']')[0])
+ self.dss.sort()
+
+ self.dss = [a for a,b in groupby(self.dss)]
+
+ for ds in self.dss:
+ self.defs = self.defs + " DEF:%s_avg=%s:%s:AVERAGE " % (ds, rrd.strip(), ds)
+ self.defs = self.defs + " DEF:%s_max=%s:%s:MAX " % (ds, rrd.strip(), ds)
+
+ j = 0
+ for ds in self.dss:
+ color = self.COLORS[j % len(self.COLORS)]
+ j = j + 1
+ faded_color = self.fade_color(color)
+ self.defs = self.defs + " AREA:%s_max#%06x " % (ds, faded_color)
+
+ j = 0
+ for ds in self.dss:
+ color = self.COLORS[j % len(self.COLORS)]
+ j = j + 1
+ self.defs = self.defs + " LINE2:%s_avg#%06x:%s " % (ds, color, ds)
+ self.defs = self.defs + " GPRINT:%s_avg:AVERAGE:%%5.1lf%%sAvg " % ds
+ self.defs = self.defs + " GPRINT:%s_max:MAX:%%5.1lf%%sMax " % ds
+
+ for span in ['1hour', '1day', '1week', '1month']:
+ os.system ("mkdir -p %s/%s" % (self.DIR, self.HOST))
+ image = os.path.dirname(rrd.strip()) + "-" + span + ".png"
+ cmd = "rrdtool graph " + image + " -t \"%s %s\"" % (os.path.dirname(rrd.strip()), span) + " --imgformat PNG --width 600 --height 100 --start now-" + span + " --end now --interlaced " + self.defs + " >/dev/null 2>&1"
+ os.system(cmd)
+
+
+def main ():
+
+ rrd = RRD ()
+ rrd.generate_pngs ()
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/ServerUtils.py b/src/com.gluster.storage.management.gateway.scripts/src/ServerUtils.py
new file mode 100644
index 00000000..1fec994c
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/ServerUtils.py
@@ -0,0 +1,308 @@
+# 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 re
+import subprocess
+import glob
+import Globals
+from Protocol import *
+from Utils import *
+
+def isValidServer(serverName):
+ for profile in getProfileList():
+ if profile.ProfileName == "default" and profile.Active:
+ if serverName == profile.DNS.Hostname:
+ return True
+ return False
+
+def getHostname():
+ for profile in getProfileList():
+ if profile.ProfileName == "default" and profile.Active:
+ return profile.DNS.Hostname
+ return None
+
+def getDomainName():
+ try:
+ domainName = open(Globals.DOMAINNAME_FILE).read()
+ except IOError:
+ return None
+ return domainName.split()[0]
+
+def replaceServerIp(fileName, findWhat, replaceWith):
+ try:
+ data = open(fileName).read()
+ fp = open(fileName, "w")
+ fp.write(re.sub(findWhat, replaceWith, data))
+ fp.close()
+ return True
+ except IOError:
+ return False
+ except ValueError:
+ return False
+ except OSError:
+ return False
+
+def serverName2IpAddress(serverName):
+ command = "dig %s | grep '^%s'" % (serverName, serverName)
+ ps = subprocess.Popen(command,
+ shell=True,
+ stdout=subprocess.PIPE,
+ stdin=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ close_fds=True)
+ ipAddress = serverName
+ if ps.wait() == 0:
+ output = ps.communicate()
+ ipAddress = output[0].split()[-1]
+ return ipAddress
+
+def getInstallerIp():
+ if not os.path.exists(Globals.INSTALLER_INFO_FILE):
+ return None
+ try:
+ for line in open(Globals.INSTALLER_INFO_FILE):
+ tokens = line.split("=")
+ if tokens[0] == "IP-ADDRESS":
+ return tokens[1].split(",")[0].strip()
+ except IOError:
+ syslog.syslog(syslog.LOG_ERR, "unable to read %s file" % Globals.INSTALLER_INFO_FILE)
+ return False
+
+def setInstallerIp(installerIp):
+ try:
+ open(Globals.INSTALLER_INFO_FILE, "w").write("IP-ADDRESS=%s\n" % installerIp)
+ return True
+ except IOError:
+ log(syslog.LOG_ERR, "unable to create %s file" % Globals.INSTALLER_INFO_FILE)
+ return False
+
+def getCurrentServerName():
+ try:
+ for line in open(Globals.SYSCONFIG_NETWORK_FILE):
+ tokens = line.split("=")
+ if tokens[0] == "HOSTNAME":
+ return tokens[1].strip()
+ except IOError:
+ syslog.syslog(syslog.LOG_ERR, "unable to read %s file" % Globals.SYSCONFIG_NETWORK_FILE)
+ return False
+
+def getLastAccessedNetwork(serverName):
+ lastAccessedNetworkFile = ("/%s/servers/%s/%s" %
+ (Globals.GLUSTER_CONF_DIR, serverName, Globals.LAST_ACCESSED_NETWORK_FILE))
+ try:
+ return open(lastAccessedNetworkFile).read().strip()
+ except IOError:
+ log(syslog.LOG_ERR, "failed to read last accessed network file %s" % lastAccessedNetworkFile)
+ pass
+ return False
+
+def setLastAccessedNetwork(serverName, ipAddress):
+ lastAccessedNetworkFile = ("/%s/servers/%s/%s" %
+ (Globals.GLUSTER_CONF_DIR, serverName, Globals.LAST_ACCESSED_NETWORK_FILE))
+ try:
+ open(lastAccessedNetworkFile, "w").write(ipAddress.strip() + "\n")
+ except IOError:
+ log(syslog.LOG_ERR, "failed to write last accessed network file %s" % lastAccessedNetworkFile)
+ return False
+ return True
+
+def getServerIpList(serverName, preferredNetworkOnly=False):
+ networkXmlFile = ("%s/servers/%s/network.xml" % (Globals.GLUSTER_CONF_DIR, serverName))
+ configDom = XDOM()
+ if not configDom.parseFile(networkXmlFile):
+ log(syslog.LOG_ERR, "failed to read %s file" % networkXmlFile)
+ return None
+ preferredNetwork = configDom.getTextByTagRoute("preferred-network")
+ ipList = []
+ interfaceDom = XDOM()
+ for tagE in configDom.getElementsByTagName("interface"):
+ interfaceDom.setDomObj(tagE)
+ deviceName = interfaceDom.getTextByTagRoute("device")
+ hostIp = interfaceDom.getTextByTagRoute("ipaddr")
+ if not hostIp:
+ continue
+ if preferredNetworkOnly:
+ if preferredNetwork.upper() == "ANY" or preferredNetwork.upper() == deviceName.upper():
+ ipList.append(hostIp)
+ else:
+ ipList.append(hostIp)
+ if preferredNetworkOnly:
+ lastAccessedNetworkIp = getLastAccessedNetwork(serverName)
+ if lastAccessedNetworkIp in ipList:
+ ipList.remove(lastAccessedNetworkIp)
+ ipList = [lastAccessedNetworkIp] + ipList
+ return ipList
+
+def getServerPreferredIpList(serverName):
+ return getServerIpList(serverName, True)
+
+def getExecuteServerList(serverList):
+ executeServerList = {}
+ for serverName in serverList:
+ if serverName == Globals.INSTALLER_SERVER_NAME:
+ installerIp = getInstallerIp()
+ if installerIp:
+ executeServerList[serverName] = [installerIp]
+ continue
+ executeServerList[serverName] = getServerPreferredIpList(serverName)
+ return executeServerList
+
+def getAllServerList():
+ serverList = []
+ for filePath in glob.glob("%s/servers/*" % Globals.GLUSTER_CONF_DIR):
+ if os.path.isdir(filePath):
+ serverList.append(os.path.basename(filePath))
+ try:
+ serverList.remove(Globals.INSTALLER_SERVER_NAME)
+ except ValueError:
+ pass
+ return serverList
+
+def getServerNetworkConfigFromLocalFile(serverName):
+ configDom = XDOM()
+ configDom.parseFile("%s/servers/%s/network.xml" % (Globals.GLUSTER_CONF_DIR, serverName))
+ return configDom
+
+def updateServerNetworkConfigXmlFile(serverName, serverNetworkDom):
+ configDom = XDOM()
+ serverTag = serverNetworkDom.getElementsByTagRoute("server")[0]
+ configDom.setDomObj(serverTag)
+ if not configDom.writexml("%s/%s/network.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)):
+ log("Faild to write xml file %s/%s/network.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName))
+
+def compareServerNetworkDom(serverNetworkDomA, serverNetworkDomB, requestFlag=True):
+ command = "command.server."
+ if not requestFlag:
+ command = ""
+ sourceServer = {}
+ tagText = serverNetworkDomA.getTextByTagRoute("name")
+ if not tagText:
+ taxText = None
+ sourceServer["name"] = tagText
+ tagText = serverNetworkDomA.getTextByTagRoute("domain-name")
+ if not tagText:
+ tagText = None
+ sourceServer["domain-name"] = tagText
+ tagText = serverNetworkDomA.getTextByTagRoute("search-domain")
+ if not tagText:
+ tagText = None
+ sourceServer["search-domain"] = tagText
+ tagText = serverNetworkDomA.getTextByTagRoute("dns1")
+ if not tagText:
+ tagText = None
+ sourceServer["dns1"] = tagText
+ tagText = serverNetworkDomA.getTextByTagRoute("dns2")
+ if not tagText:
+ tagText = None
+ sourceServer["dns2"] = tagText
+ tagText = serverNetworkDomA.getTextByTagRoute("dns3")
+ if not tagText:
+ tagText = None
+ sourceServer["dns3"] = tagText
+ for tagE in serverNetworkDomA.getElementsByTagRoute("interface"):
+ interfaceDom = XDOM()
+ interfaceDom.setDomObj(tagE)
+ sourceServerList = {}
+ tagText = interfaceDom.getTextByTagRoute("description")
+ if not tagText:
+ tagText = None
+ sourceServerList["description"] = tagText
+ tagText = interfaceDom.getTextByTagRoute("hwaddr")
+ if not tagText:
+ tagText = None
+ sourceServerList["hwaddr"] = tagText
+ tagText = interfaceDom.getTextByTagRoute("onboot")
+ if not tagText:
+ tagText = None
+ sourceServerList["onboot"] = tagText
+ tagText = interfaceDom.getTextByTagRoute("bootproto")
+ if not tagText:
+ tagText = None
+ sourceServerList["bootproto"] = tagText
+ tagText = interfaceDom.getTextByTagRoute("ipaddr")
+ if not tagText:
+ tagText = None
+ sourceServerList["ipaddr"] = tagText
+ tagText = interfaceDom.getTextByTagRoute("netmask")
+ if not tagText:
+ tagText = None
+ sourceServerList["netmask"] = tagText
+ tagText = interfaceDom.getTextByTagRoute("gateway")
+ if not tagText:
+ tagText = None
+ sourceServerList["gateway"] = tagText
+ sourceServer[interfaceDom.getTextByTagRoute("device")] = sourceServerList
+ objServer = {}
+ tagText = serverNetworkDomB.getTextByTagRoute(command + "name")
+ if not tagText:
+ taxText = None
+ objServer["name"] = tagText
+ tagText = serverNetworkDomB.getTextByTagRoute(command + "domain-name")
+ if not tagText:
+ tagText = None
+ objServer["domain-name"] = tagText
+ tagText = serverNetworkDomB.getTextByTagRoute(command + "search-domain")
+ if not tagText:
+ tagText = None
+ objServer["search-domain"] = tagText
+ tagText = serverNetworkDomB.getTextByTagRoute(command + "dns1")
+ if not tagText:
+ tagText = None
+ objServer["dns1"] = tagText
+ tagText = serverNetworkDomB.getTextByTagRoute(command + "dns2")
+ if not tagText:
+ tagText = None
+ objServer["dns2"] = tagText
+ tagText = serverNetworkDomB.getTextByTagRoute(command + "dns3")
+ if not tagText:
+ tagText = None
+ objServer["dns3"] = tagText
+ for tagE in serverNetworkDomB.getElementsByTagRoute(command + "interface"):
+ interfaceDom = XDOM()
+ interfaceDom.setDomObj(tagE)
+ objServerList = {}
+ tagText = interfaceDom.getTextByTagRoute("description")
+ if not tagText:
+ tagText = None
+ objServerList["description"] = tagText
+ tagText = interfaceDom.getTextByTagRoute("hwaddr")
+ if not tagText:
+ tagText = None
+ objServerList["hwaddr"] = tagText
+ tagText = interfaceDom.getTextByTagRoute("onboot")
+ if not tagText:
+ tagText = None
+ objServerList["onboot"] = tagText
+ tagText = interfaceDom.getTextByTagRoute("bootproto")
+ if not tagText:
+ tagText = None
+ objServerList["bootproto"] = tagText
+ tagText = interfaceDom.getTextByTagRoute("ipaddr")
+ if not tagText:
+ tagText = None
+ objServerList["ipaddr"] = tagText
+ tagText = interfaceDom.getTextByTagRoute("netmask")
+ if not tagText:
+ tagText = None
+ objServerList["netmask"] = tagText
+ tagText = interfaceDom.getTextByTagRoute("gateway")
+ if not tagText:
+ tagText = None
+ objServerList["gateway"] = tagText
+ objServer[interfaceDom.getTextByTagRoute("device")] = objServerList
+ return sourceServer == objServer
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/Utils.py b/src/com.gluster.storage.management.gateway.scripts/src/Utils.py
new file mode 100644
index 00000000..3408c14a
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/Utils.py
@@ -0,0 +1,1059 @@
+# 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 sys
+import os
+import re
+import socket
+import struct
+import syslog
+import subprocess
+#import spwd
+import time
+#import uuid
+import tempfile
+import grp
+import pwd
+import inspect
+from datetime import datetime
+import urllib
+
+import Globals
+import Protocol
+
+RUN_COMMAND_ERROR = -1024
+LOG_SYSLOG = 1
+SYSLOG_REQUIRED = False
+LOG_FILE_NAME = None
+LOG_FILE_OBJ = None
+
+
+def _getLogCode(priority):
+ if syslog.LOG_EMERG == priority:
+ return "M"
+ elif syslog.LOG_ALERT == priority:
+ return "A"
+ elif syslog.LOG_CRIT == priority:
+ return "C"
+ elif syslog.LOG_ERR == priority:
+ return "E"
+ elif syslog.LOG_WARNING == priority:
+ return "W"
+ elif syslog.LOG_NOTICE == priority:
+ return "N"
+ elif syslog.LOG_INFO == priority:
+ return "I"
+ elif syslog.LOG_DEBUG == priority:
+ return "D"
+ else: # UNKNOWN
+ return "X"
+
+
+def setLogFile(fileName):
+ global LOG_FILE_NAME
+
+ if fileName:
+ LOG_FILE_NAME = fileName
+ return True
+ return False
+
+
+def closeLog():
+ global LOG_FILE_OBJ
+ global SYSLOG_REQUIRED
+
+ if SYSLOG_REQUIRED:
+ syslog.closelog()
+ SYSLOG_REQUIRED = False
+ return True
+
+ if LOG_FILE_OBJ:
+ try:
+ LOG_FILE_OBJ.close()
+ LOG_FILE_OBJ = None
+ except IOError, e:
+ sys.stderr.write("Failed to close file: %s\n" % e)
+ return False
+ return True
+
+
+def openLog(fileName=None):
+ global LOG_FILE_NAME
+ global LOG_FILE_OBJ
+ global SYSLOG_REQUIRED
+
+ if fileName == LOG_SYSLOG:
+ syslog.openlog(os.path.basename(sys.argv[0]))
+ SYSLOG_REQUIRED = True
+ return True
+
+ if fileName:
+ LOG_FILE_NAME = fileName
+
+ if not LOG_FILE_NAME:
+ return False
+
+ closeLog()
+
+ try:
+ LOG_FILE_OBJ = open(LOG_FILE_NAME, "a")
+ except IOError, e:
+ sys.stderr.write("Failed to open file %s: %s\n" % (LOG_FILE_NAME, e))
+ return False
+ return True
+
+def record(priority, message=None):
+ global LOG_FILE_OBJ
+ global SYSLOG_REQUIRED
+
+ stack = inspect.stack()[1]
+ if stack[3] == "<module>":
+ prefix = "%s:%s:%s" % (stack[1], stack[2], stack[3])
+ else:
+ prefix = "%s:%s:%s()" % (stack[1], stack[2], stack[3])
+
+ if type(priority) == type("") or type(priority) == type(u""):
+ logPriority = syslog.LOG_INFO
+ logMessage = priority
+ else:
+ logPriority = priority
+ logMessage = message
+
+ if SYSLOG_REQUIRED:
+ syslog.syslog(logPriority, "[%s]: %s" % (prefix, logMessage))
+ return
+
+ fp = sys.stderr
+ if LOG_FILE_OBJ:
+ fp = LOG_FILE_OBJ
+
+ fp.write("[%s] %s [%s]: %s" % (str(datetime.now()), _getLogCode(logPriority), prefix, logMessage))
+ if logMessage[-1] != '\n':
+ fp.write("\n")
+ fp.flush()
+ return
+
+
+def trace(message):
+ if message:
+ log(syslog.LOG_DEBUG, message)
+
+
+def isString(value):
+ return (type(value) == type("") or type(value) == type(u""))
+
+
+def getTempFileName():
+ filedesc, filename = tempfile.mkstemp(prefix="GSP_")
+ os.close(filedesc)
+ return filename
+
+
+def runCommandBG(command, stdinFileObj=None, stdoutFileObj=None, stderrFileObj=None,
+ shell=False, root=None):
+ log("runCommandBG(): Trying to execute command [%s]" % command)
+
+ if shell:
+ if not isString(command):
+ return None
+ else:
+ if isString(command):
+ command = command.split()
+
+ if root == True:
+ if shell:
+ command = "sudo " + command
+ else:
+ command = ['sudo'] + command
+ elif isString(root):
+ if shell:
+ command = "sudo -u " + root + " " + command
+ else:
+ command = ['sudo', '-u', root] + command
+
+ if not stdinFileObj:
+ stdinFileObj=subprocess.PIPE
+ if not stdoutFileObj:
+ stdoutFileObj=subprocess.PIPE
+ if not stderrFileObj:
+ stderrFileObj=subprocess.PIPE
+
+ try:
+ process = subprocess.Popen(command,
+ bufsize=-1,
+ stdin=stdinFileObj,
+ stdout=stdoutFileObj,
+ stderr=stderrFileObj,
+ shell=shell)
+ return process
+ except OSError, e:
+ log("runCommandBG(): Failed to run command [%s]: %s" % (command, e))
+ return None
+
+
+def runCommand(command,
+ input='', output=False,
+ shell=False, root=None):
+ rv = {}
+ rv["Status"] = RUN_COMMAND_ERROR
+ rv["Stdout"] = None
+ rv["Stderr"] = None
+
+ try:
+ stdinFileName = getTempFileName()
+ stdinFileObj = open(stdinFileName, "w")
+ stdinFileObj.write(input)
+ stdinFileObj.close()
+ stdinFileObj = open(stdinFileName, "r")
+
+ stdoutFileName = getTempFileName()
+ stdoutFileObj = open(stdoutFileName, "w")
+
+ stderrFileName = getTempFileName()
+ stderrFileObj = open(stderrFileName, "w")
+ except IOError, e:
+ log("Failed to create temporary file for executing command [%s]: %s" % (command, e))
+ if output:
+ return rv
+ return rv["Status"]
+
+ stdoutContent = None
+ stderrContent = None
+
+ process = runCommandBG(command,
+ stdinFileObj=stdinFileObj,
+ stdoutFileObj=stdoutFileObj,
+ stderrFileObj=stderrFileObj,
+ shell=shell, root=root)
+ if process:
+ rv['Status'] = process.wait()
+ rv['Stdout'] = open(stdoutFileName).read()
+ rv['Stderr'] = open(stderrFileName).read()
+
+ os.remove(stdinFileName)
+ os.remove(stdoutFileName)
+ os.remove(stderrFileName)
+
+ log("runCommand(): execution status of command [%s] = [%s]" % (command, rv))
+
+ if output:
+ return rv
+ return rv["Status"]
+
+
+def runCommandFG(command, stdout=False, stderr=False,
+ shell=False, root=None):
+ if stdout or stderr:
+ output = True
+ else:
+ output = False
+ return runCommand(command, output=output, shell=shell, root=root)
+
+
+def IP2Number(ipString):
+ try:
+ return socket.htonl(struct.unpack("I", socket.inet_aton(ipString))[0])
+ except socket.error:
+ return None
+ except TypeError:
+ return None
+ except struct.error:
+ return None
+
+
+def Number2IP(number):
+ try:
+ return socket.inet_ntoa(struct.pack("I", socket.ntohl(number)))
+ except socket.error:
+ return None
+ except AttributeError:
+ return None
+ except ValueError:
+ return None
+
+
+def computeHostName(hostName):
+ if not hostName:
+ return False
+
+ hostPrefix = ""
+ for i in range(len(hostName), 0, -1):
+ pos = i - 1
+ if hostName[pos].isdigit():
+ continue
+ break
+ hostPrefix = hostName[:pos+1]
+ try:
+ hostIndex = int(hostName[pos+1:])
+ except ValueError:
+ hostIndex = 0
+ # TODO: Check the availablity of the (server) name
+ return "%s%s" % (hostPrefix, hostIndex + 1)
+
+
+def daemonize():
+ try:
+ pid = os.fork()
+ if pid > 0:
+ # exit first parent
+ sys.exit(0)
+ except OSError, e:
+ #sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
+ return False
+
+ # decouple from parent environment
+ os.chdir("/")
+ os.setsid()
+ os.umask(0)
+
+ # do second fork
+ try:
+ pid = os.fork()
+ if pid > 0:
+ # exit from second parent
+ sys.exit(0)
+ except OSError, e:
+ #sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
+ return False
+
+ # redirect standard file descriptors
+ sys.stdout.flush()
+ sys.stderr.flush()
+ si = file("/dev/null", 'r')
+ so = file("/dev/null", 'a+')
+ se = file("/dev/null", 'a+', 0)
+ os.dup2(si.fileno(), sys.stdin.fileno())
+ os.dup2(so.fileno(), sys.stdout.fileno())
+ os.dup2(se.fileno(), sys.stderr.fileno())
+ return True
+
+
+def getDownloadStatus(fileName):
+ try:
+ lines = [line for line in open(fileName)
+ if "saved" in line or "%" in line]
+ except IOError:
+ return 0
+ if not lines:
+ return 0
+ if "saved" in lines[-1]:
+ return 100
+ return lines[-1].split("%")[0].split()[-1]
+
+
+def getMeminfo():
+ """-> dict of data from meminfo (str:int).
+ Values are in kilobytes.
+ """
+ import re
+ re_parser = re.compile(r'^(?P<key>\S*):\s*(?P<value>\d*)\s*kB' )
+ result = {}
+ for line in open('/proc/meminfo'):
+ match = re_parser.match(line)
+ if not match:
+ continue # skip lines that don't parse
+ key, value = match.groups(['key', 'value'])
+ result[key] = int(value)
+ result['MemUsed'] = (result['MemTotal'] - result['MemFree'])
+ return result
+
+
+def getCpuUsage():
+ """-> dict of cpuid : (usertime, nicetime, systemtime, idletime)
+ cpuid "cpu" means the total for all CPUs.
+ cpuid "cpuN" means the value for CPU N.
+ """
+ wanted_records = [line for line in open('/proc/stat') if
+ line.startswith('cpu')]
+ result = {}
+ for cpuline in wanted_records:
+ fields = cpuline.split()[:5]
+ data = map(int, fields[1:])
+ result[fields[0]] = tuple(data)
+ return result
+
+def _getCpuStatList():
+ try:
+ fp = open("/proc/stat")
+ cpuStatList = map(float, fp.readline().split()[1:])
+ fp.close()
+ return cpuStatList
+ except IOError, e:
+ Utils.log("Failed to open /proc/stat: %s" % str(e))
+ return None
+
+def getCpuUsageAvg():
+ st1 = _getCpuStatList()
+ time.sleep(2)
+ st2 = _getCpuStatList()
+ if not (st1 and st2):
+ return None
+ delta = [st2[i] - st1[i] for i in range(len(st1))]
+ cpuPercent = sum(delta[:3]) / delta[3] * 100.0
+ return str('%.4f' % cpuPercent)
+
+def getLoadavg():
+ try:
+ loadavgstr = open('/proc/loadavg', 'r').readline().strip()
+ except IOError:
+ syslog.syslog(syslog.LOG_ERR, "failed to find cpu load")
+ return None
+
+ data = map(float, loadavgstr.split()[1:])
+ # returns 1 minute load average
+ return data[0]
+
+
+def getInfinibandPortStatus():
+
+ """ Check for availability of infiniband port
+ and return which port is active in a key pair value
+ """
+
+ # Check for existence of infiniband ports
+ value = os.popen ("ls /sys/class/infiniband").readline().strip()
+
+ if not value:
+ return None
+
+ portlist = os.popen ("echo /sys/class/infiniband/*/ports/*").readline().split()
+
+ portkeys = {}
+
+ for port in portlist:
+ value = os.popen ("cat %s/state" %
+ port.strip()).readline().split(':')[1].strip()
+ portkeys[port.strip()] = value
+
+ return portkeys
+
+
+def getServerCount():
+ try:
+ return int(open(Globals.SERVER_COUNT_FILE).read().strip())
+ except IOError:
+ log("failed to read file %s" % Globals.SERVER_COUNT_FILE)
+ return 1
+ except ValueError:
+ log("invalid number format in file %s" % Globals.SERVER_COUNT_FILE)
+ return 1
+
+
+def setServerCount(count):
+ try:
+ open(Globals.SERVER_COUNT_FILE, "w").write("%s\n" % count)
+ return True
+ except IOError:
+ log("failed to write file %s" % Globals.SERVER_COUNT_FILE)
+ return False
+
+
+def getInstalledServerCount():
+ try:
+ return int(open(Globals.INSTALLED_SERVER_COUNT_FILE).read().strip())
+ except IOError:
+ log("failed to read file %s" % Globals.INSTALLED_SERVER_COUNT_FILE)
+ return 1
+ except ValueError:
+ log("invalid number format in file %s" % Globals.INSTALLED_SERVER_COUNT_FILE)
+ return 1
+
+
+def setInstalledServerCount(count):
+ try:
+ open(Globals.INSTALLED_SERVER_COUNT_FILE, "w").write("%s\n" % count)
+ return True
+ except IOError:
+ log("failed to write file %s" % Globals.INSTALLED_SERVER_COUNT_FILE)
+ return False
+
+
+def getLastInstalledServerIpList():
+ ipList = {}
+ networkDom = Protocol.XDOM()
+ if not networkDom.parseFile(Globals.GLOBAL_NETWORK_FILE):
+ log("failed to parse file %s" % Globals.GLOBAL_NETWORK_FILE)
+ for tagE in networkDom.getElementsByTagRoute("server.interface"):
+ interfaceDom = Protocol.XDOM()
+ interfaceDom.setDomObj(tagE)
+ ipAddress = interfaceDom.getTextByTagRoute("ipaddr")
+ if ipAddress:
+ ipList[interfaceDom.getTextByTagRoute("device")] = ipAddress
+ return ipList
+
+
+def getFreeIpAddress(device=None):
+ serverCount = getServerCount()
+ installedServerCount = getInstalledServerCount()
+ if serverCount == installedServerCount:
+ return None
+
+ availableServerCount = serverCount - installedServerCount
+ ipList = getLastInstalledServerIpList()
+
+ if not ipList:
+ return None
+
+ if device:
+ if device not in ipList.keys():
+ return None
+ deviceIpAddress = ipList[device]
+ else:
+ deviceIpAddress = ipList.values()[0]
+ ipNumber = IP2Number(deviceIpAddress)
+
+ for i in range((ipNumber + availableServerCount), ipNumber, -1):
+ ipAddress = Number2IP(i)
+ if runCommandFG(["ping", "-qnc", "1", ipAddress]) != 0:
+ return ipAddress
+ return None
+
+
+def getPasswordHash(userName):
+ try:
+ #return spwd.getspnam(userName).sp_pwd
+ return "Not implimented"
+ except KeyError:
+ return None
+
+
+def getTransactionKey():
+ try:
+ tokens = open(Globals.TRANSACTION_KEY_FILE).read().split(',')
+ except IOError:
+ return None, None
+ return tokens
+
+
+def generateSignature():
+ #return str(uuid.uuid4()) + ('--%f' % time.time())
+ return ('--%f' % time.time())
+
+
+def getSignature():
+ try:
+ return open(Globals.SIGNATURE_FILE).read().strip()
+ except IOError:
+ log(syslog.LOG_ERR, "unable to read signaure from %s file" % Globals.SIGNATURE_FILE)
+ return False
+
+
+def storeSignature(signature, fileName=Globals.SIGNATURE_FILE):
+ try:
+ open(fileName, "w").write(signature + "\n")
+ except IOError:
+ log(syslog.LOG_ERR, "unable to write signature %s to %s file" % (signature, fileName))
+ return False
+ return True
+
+
+def isUserExist(userName):
+ try:
+ grp.getgrnam(userName).gr_gid
+ return True
+ except KeyError:
+ pass
+ try:
+ pwd.getpwnam(userName).pw_uid
+ return True
+ except KeyError:
+ pass
+ return False
+
+
+def getGsnUserInfo(fileName=Globals.GSN_USER_INFO_FILE):
+ userInfo = {}
+ userInfo["UserId"] = None
+ userInfo["Password"] = None
+ try:
+ for line in open(fileName):
+ line = line.strip()
+ k = line[:line.index("=")]
+ v = line[line.index("=") + 1:]
+ if v[0] == "'" or v[0] == '"':
+ v = v[1:]
+ if v[-1] == "'" or v[-1] == '"':
+ v = v[:-1]
+ if k.upper() == "GSN_ID":
+ userInfo["UserId"] = v
+ if k.upper() == "GSN_PASSWORD":
+ userInfo["Password"] = v
+ except IOError, e:
+ log("Failed to read file %s: %s" % (fileName, e))
+ return userInfo
+
+
+def setGsnUserInfo(userInfo, fileName=Globals.GSN_USER_INFO_FILE):
+ try:
+ fp = open(fileName, "w")
+ fp.write("GSN_ID=%s\n" % userInfo["UserId"])
+ fp.write("GSN_PASSWORD=%s\n" % userInfo["Password"])
+ fp.close()
+ return True
+ except IOError, e:
+ log("Failed to write file %s: %s" % (fileName, e))
+ return False
+
+
+def getPlatformVersion(fileName=Globals.GLUSTER_VERSION_FILE):
+ versionInfo = {}
+ versionInfo["Version"] = None
+ versionInfo["Update"] = None
+ try:
+ lines = open(Globals.GLUSTER_VERSION_FILE).readlines()
+ for line in open(fileName):
+ line = line.strip()
+ k = line[:line.index("=")]
+ v = line[line.index("=") + 1:]
+ if v[0] == "'" or v[0] == '"':
+ v = v[1:]
+ if v[-1] == "'" or v[-1] == '"':
+ v = v[:-1]
+ if k.upper() == "VERSION":
+ versionInfo["Version"] = v
+ if k.upper() == "UPDATE":
+ versionInfo["Update"] = v
+ except IOError, e:
+ log("Failed to read file %s: %s" % (fileName, e))
+ return versionInfo
+
+
+def setPlatformVersion(versionInfo, fileName=Globals.GLUSTER_VERSION_FILE):
+ if isString(versionInfo):
+ tokens = versionInfo.strip().split(".")
+ if len(tokens) < 2:
+ log("Invalid version format %s. Expecting <MAJOR>.<MINOR>.<PATCHLEVEL>" % versionInfo)
+ return False
+ version = ".".join(tokens[:2])
+ update = ".".join(tokens[2:])
+ if not update:
+ update = "0"
+ else:
+ version = versionInfo["Version"]
+ update = versionInfo["Update"]
+ try:
+ fp = open(fileName, "w")
+ fp.write("VERSION=%s\n" % version)
+ fp.write("UPDATE=%s\n" % update)
+ fp.close()
+ return True
+ except IOError, e:
+ log("Failed to write file %s: %s" % (fileName, e))
+ return False
+
+
+def getGlusterUpdateDom(serverVersion):
+ errorMessage = ""
+ updateInfoDom = None
+ try:
+ baseUrl = open(Globals.GLUSTER_UPDATE_SITE_FILE).read().strip()
+ except IOError, e:
+ log("Failed to read file %s: %s" % (Globals.GLUSTER_UPDATE_SITE_FILE, e))
+ errorMessage = "Failed to read update site file"
+ return updateInfoDom, errorMessage
+
+ try:
+ url = "%s/%s/%s" % (baseUrl, serverVersion, Globals.GLUSTER_UPDATES_FILE)
+ connection = urllib.urlopen(url)
+ if connection.getcode() != 200:
+ connection.close()
+ errorMessage = "Error received from server to open URL %s" % url
+ return updateInfoDom, errorMessage
+ updateInfoString = connection.read()
+ connection.close()
+ except IOError, e:
+ log("Failed to get update information from URL %s: %s" % (url, e))
+ errorMessage = "Error getting update information"
+ return updateInfoDom, errorMessage
+
+ updateInfoDom = Protocol.XDOM()
+ if not updateInfoDom.parseString(updateInfoString):
+ log("XML parse error on update information content [%s]" % updateInfoString)
+ errorMessage = "Parse error on update information"
+ updateInfoDom = None
+ return updateInfoDom, errorMessage
+
+
+def removeFile(fileName, root=False):
+ if root:
+ if runCommand("rm %s" % fileName, root=True) == 0:
+ return True
+ return False
+ try:
+ os.remove(fileName)
+ return True
+ except OSError, e:
+ log("Failed to remove file %s: %s" % (fileName, e))
+ return False
+
+
+def isLiveMode():
+ return os.path.exists(Globals.LIVE_MODE_FILE)
+
+def convertKbToMb(kb):
+ return kb / 1024.0
+
+
+def getIPIndex(indexFile):
+ try:
+ fp = open(indexFile)
+ line = fp.readline()
+ fp.close()
+ index = int(line)
+ except IOError:
+ index = 0
+ except ValueError:
+ index = False
+ return index
+
+def setIPIndex(index, indexFile):
+ try:
+ fp = open(indexFile, "w")
+ fp.write(str(index))
+ fp.close()
+ except IOError:
+ return False
+ return True
+
+def IP2Number(ipString):
+ try:
+ return socket.htonl(struct.unpack("I", socket.inet_aton(ipString))[0])
+ except socket.error:
+ return None
+ except TypeError:
+ return None
+ except struct.error:
+ return None
+
+def Number2IP(number):
+ try:
+ return socket.inet_ntoa(struct.pack("I", socket.ntohl(number)))
+ except socket.error:
+ return None
+ except AttributeError:
+ return None
+ except ValueError:
+ return None
+
+def hasEntryFoundInFile(searchString, dnsEntryFileName):
+ try:
+ addServerEntryList = open(dnsEntryFileName).read().split()
+ except IOError:
+ return None
+ if searchString in addServerEntryList:
+ return True
+ return False
+
+
+def computeIpAddress(ipAddress, startIp, endIp):
+ startIpNumber = IP2Number(startIp)
+ endIpNumber = IP2Number(endIp)
+ if not ipAddress:
+ return startIp
+ nextIpNumber = IP2Number(ipAddress)
+ while True:
+ nextIpNumber = nextIpNumber + 1
+ ipAddress = Number2IP(nextIpNumber)
+ rv = runCommandFG(["ping", "-qnc", "1", ipAddress])
+ if type(rv) == type(True):
+ return False
+ if rv != 0:
+ break
+
+ if nextIpNumber >= startIpNumber and nextIpNumber <= endIpNumber:
+ return ipAddress
+
+ nextIpNumber = IP2Number(startIp)
+ while True:
+ ipAddress = Number2IP(nextIpNumber)
+ nextIpNumber = nextIpNumber + 1
+ rv = runCommandFG(["ping", "-qnc", "1", ipAddress])
+ if type(rv) == type(True):
+ return False
+ if rv != 0:
+ break
+
+ if IP2Number(ipAddress) >= startIpNumber and IP2Number(ipAddress) <= endIpNumber:
+ return ipAddress
+ return False
+
+
+def setHostNameAndIp(hostName, ipAddress, lastAddServerDetailFile):
+ try:
+ fp = open(lastAddServerDetailFile, "w")
+ fp.write("HOSTNAME=" + hostName + "\n")
+ fp.write("IPADDRESS=" + ipAddress);
+ fp.close()
+ except IOError:
+ return False
+ return True
+
+def getPort():
+ try:
+ fd = open(Globals.PORT_FILE, "r")
+ portString = fd.readline()
+ fd.close()
+ port = int(portString)
+ except IOError:
+ port = Globals.DEFAULT_PORT - 2
+ except ValueError:
+ port = Globals.DEFAULT_PORT - 2
+ return port
+
+def setPort(port):
+ try:
+ fd = open(Globals.PORT_FILE, "w")
+ fd.write(str(port))
+ fd.close()
+ except IOError:
+ return False
+ return True
+
+def getServerAgentCredentials():
+ try:
+ lines = open(Globals.SERVERAGENT_AUTH_FILE).readlines()
+ except IOError:
+ return None,None
+
+ userName = None
+ password = None
+
+ for l in lines:
+ if l[-1] == '\n':
+ l = l[:-1]
+ k = l[:l.index('=')]
+ v = l[l.index('=') + 1:]
+ if v[0] == "'" or v[0] == '"':
+ v = v[1:]
+ if v[-1] == "'" or v[-1] == '"':
+ v = v[:-1]
+ if k.upper() == "AGENT_ID":
+ userName = v
+ if k.upper() == "AGENT_PASSWORD":
+ password = v
+
+ return userName, password
+
+def getGatewayAgentCredentials():
+ try:
+ lines = open(Globals.GATEWAYAGENT_AUTH_FILE).readlines()
+ except IOError:
+ return None
+
+ #userName = None
+ password = None
+
+ for l in lines:
+ if l[-1] == '\n':
+ l = l[:-1]
+ k = l[:l.index('=')]
+ v = l[l.index('=') + 1:]
+ if v[0] == "'" or v[0] == '"':
+ v = v[1:]
+ if v[-1] == "'" or v[-1] == '"':
+ v = v[:-1]
+ #if k.upper() == "AGENT_ID":
+ # userName = v
+ if k.upper() == "AGENT_PASSWORD":
+ password = v
+
+ return password
+
+def getWebAgentCredentials():
+ try:
+ lines = open(Globals.WEBAGENT_AUTH_FILE).readlines()
+ except IOError:
+ return None,None
+
+ userName = None
+ password = None
+
+ for l in lines:
+ if l[-1] == '\n':
+ l = l[:-1]
+ k = l[:l.index('=')]
+ v = l[l.index('=') + 1:]
+ if v[0] == "'" or v[0] == '"':
+ v = v[1:]
+ if v[-1] == "'" or v[-1] == '"':
+ v = v[:-1]
+ if k.upper() == "AGENT_ID":
+ userName = v
+ if k.upper() == "AGENT_PASSWORD":
+ password = v
+
+ return userName, password
+
+def daemonize():
+ try:
+ pid = os.fork()
+ if pid > 0:
+ # exit first parent
+ sys.exit(0)
+ except OSError, e:
+ #sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
+ return False
+
+ # decouple from parent environment
+ os.chdir("/")
+ os.setsid()
+ os.umask(0)
+
+ # do second fork
+ try:
+ pid = os.fork()
+ if pid > 0:
+ # exit from second parent
+ sys.exit(0)
+ except OSError, e:
+ #sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
+ return False
+
+ # redirect standard file descriptors
+ sys.stdout.flush()
+ sys.stderr.flush()
+ si = file("/dev/null", 'r')
+ so = file("/dev/null", 'a+')
+ se = file("/dev/null", 'a+', 0)
+ os.dup2(si.fileno(), sys.stdin.fileno())
+ os.dup2(so.fileno(), sys.stdout.fileno())
+ os.dup2(se.fileno(), sys.stderr.fileno())
+ return True
+
+def getFreeIpAddress():
+ startRange, endRange = getStoragePoolInfo()
+ if not (startRange and endRange):
+ return None
+
+ startIpNumber = IP2Number(startRange)
+ endIpNumber = IP2Number(endRange)
+
+ for ipNumber in range(endIpNumber, startIpNumber, -1):
+ rv = runCommandFG(["ping", "-qnc", "1", Number2IP(ipNumber)])
+ if type(rv) == type(True):
+ return None
+ if rv != 0:
+ return Number2IP(ipNumber)
+ return None
+
+def getDhcpServerStatus():
+ status = runCommandFG(["sudo", "service", "dnsmasq", " status"])
+ if type(status) == type(True) or 0 != status:
+ return False
+ return True
+
+def startDhcpServer():
+ status = runCommandFG(["sudo", "service", "dnsmasq", " start"])
+ if type(status) == type(True) or 0 != status:
+ return False
+ return True
+
+def stopDhcpServer():
+ status = runCommandFG(["sudo", "service", "dnsmasq", " stop"])
+ if type(status) == type(True) or 0 != status:
+ return False
+ return True
+
+def getStoragePoolInfo():
+ startRange = None
+ endRange = None
+ try:
+ for line in open(Globals.GLUSTER_SERVER_POOL_FILE):
+ tokens = line.split("=")
+ if tokens[0] == "STARTRANGE":
+ startRange = tokens[1].strip()
+ if tokens[0] == "ENDRANGE":
+ endRange = tokens[1].strip()
+ except IOError:
+ log(syslog.LOG_ERR, "unable to read %s file" % Globals.GLUSTER_SERVER_POOL_FILE)
+ return startRange, endRange
+
+def configureDnsmasq(serverIpAddress, dhcpIpAddress):
+ dnsmasqConfFile = Globals.GLUSTER_CONF_CONF_DIR + "/dnsmasq.conf"
+ serverPortString = "68"
+ try:
+ for arg in open("/proc/cmdline").read().strip().split():
+ token = arg.split("=")
+ if token[0] == "dhcp":
+ serverPortString = token[1]
+ break
+ except IOError:
+ log(syslog.LOG_ERR, "Failed to read /proc/cmdline. Continuing with default port 68")
+ try:
+ serverPort = int(serverPortString)
+ except ValueError:
+ log(syslog.LOG_ERR, "Invalid dhcp port '%s' in /proc/cmdline. Continuing with default port 68" % serverPortString)
+ serverPort = 68
+
+ try:
+ fp = open(dnsmasqConfFile, "w")
+ fp.write("no-hosts\n")
+ #fp.write("addn-hosts=%s\n" % Globals.GLUSTER_DNS_ENTRIES)
+ fp.write("bind-interfaces\n")
+ fp.write("except-interface=lo\n")
+ fp.write("dhcp-range=%s,%s\n" % (dhcpIpAddress, dhcpIpAddress))
+ fp.write("dhcp-lease-max=1\n")
+ #fp.write("dhcp-option=option:router,%s\n" % serverIp)
+ #fp.write("dhcp-option=option:ntp-server,%s\n" % serverIp)
+ fp.write("dhcp-alternate-port=%s\n" % serverPort)
+ fp.write("server=%s\n" % serverIpAddress)
+ fp.write("dhcp-script=/usr/sbin/server-info\n")
+ fp.close()
+ except IOError:
+ log(syslog.LOG_ERR, "unable to write dnsmasq configuration %s" % dnsmasqConfFile)
+ return False
+ status = runCommandFG(["sudo", "cp", "-f", Globals.GLUSTER_CONF_CONF_DIR + "/dnsmasq.conf", Globals.DNSMASQ_CONF_FILE])
+ if type(status) == type(True) or 0 != status:
+ log(syslog.LOG_ERR, "unable to copy dnsmasq configuration to " + Globals.DNSMASQ_CONF_FILE)
+ return False
+ return True
+
+def configureDhcpServer(serverIpAddress, dhcpIpAddress):
+ return configureDnsmasq(serverIpAddress, dhcpIpAddress)
+
+def log(priority, message=None):
+ if type(priority) == type(""):
+ logPriority = syslog.LOG_INFO
+ logMessage = priority
+ else:
+ logPriority = priority
+ logMessage = message
+ if not logMessage:
+ return
+ #if Globals.DEBUG:
+ # sys.stderr.write(logMessage)
+ else:
+ syslog.syslog(logPriority, logMessage)
+ return
+
+
+def stripEmptyLines(content):
+ ret = ""
+ for line in content.split("\n"):
+ if line.strip() != "":
+ ret += line
+ return ret
+
+
+def getDeviceFormatStatusFile(device):
+ return "/var/tmp/format_%s.status" % device.replace('/', '_')
+
+def getDeviceFormatLockFile(device):
+ return "/var/lock/format_%s.lock" % device.replace('/', '_')
+
+def getDeviceFormatOutputFile(device):
+ return "/var/tmp/format_%s.out" % device.replace('/', '_')
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/VolumeUtils.py b/src/com.gluster.storage.management.gateway.scripts/src/VolumeUtils.py
new file mode 100644
index 00000000..b1031ccc
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/VolumeUtils.py
@@ -0,0 +1,612 @@
+# 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)
+ return True
+ except OSError, e:
+ log("Failed to remove file %s: %s" % (volumeFile, str(e)))
+ return False
+
+
+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.gateway.scripts/src/XmlHandler.py b/src/com.gluster.storage.management.gateway.scripts/src/XmlHandler.py
new file mode 100644
index 00000000..72164ffb
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/XmlHandler.py
@@ -0,0 +1,346 @@
+# Copyright (C) 2009 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 xml
+import xml.parsers.expat
+import xml.dom.minidom as MDOM
+import os
+import Globals
+import copy
+import Utils
+
+XML_STRING = 0
+XML_FILE = 1
+
+class XDOM:
+ _domObj = None
+
+ def __init__(self):
+ self._domObj = MDOM.Document()
+ return
+
+ @classmethod
+ def getText(self, nodeList):
+ rc = ""
+ for node in nodeList:
+ if node.nodeType == node.TEXT_NODE:
+ rc = rc + node.data
+ return rc
+
+ def parseString(self, requestString):
+ try:
+ self._domObj = MDOM.parseString(requestString)
+ except xml.parsers.expat.ExpatError, e:
+ Utils.log("XML string parse error: %s" % str(e))
+ return False
+ return True
+
+ def parseFile(self, fileName):
+ try:
+ self._domObj = MDOM.parse(fileName)
+ except IOError, e:
+ Utils.log("error reading file: %s" % str(e))
+ return False
+ except xml.parsers.expat.ExpatError, e:
+ Utils.log("XML file %s parse error: %s" % (fileName, str(e)))
+ return False
+ return True
+
+ def setDomObj(self, dom):
+ if dom and type(dom) != type([]):
+ self._domObj = dom
+ return True
+ return False
+
+ def createTag(self, tag, text=None):
+ if not self._domObj:
+ return None
+ if tag == None:
+ return None
+
+ tagE = self._domObj.createElement(str(tag))
+ if text:
+ tagEText = self._domObj.createTextNode(str(text))
+ tagE.appendChild(tagEText)
+ return tagE
+
+ def addTag(self, tag):
+ if not self._domObj:
+ return False
+ if not tag:
+ return False
+
+ self._domObj.appendChild(tag)
+ return True
+
+ def createTagRoute(self, tagRoute, text=None):
+ if not tagRoute:
+ return False
+
+ tagList = tagRoute.split(".")
+ tag = None
+ previousTag = None
+ for tagName in tagList[:-1]:
+ newTag = self.createTag(tagName, None)
+ if not tag:
+ tag = newTag
+ previousTag = newTag
+ continue
+ previousTag.appendChild(newTag)
+ previousTag = newTag
+
+ if previousTag:
+ previousTag.appendChild(self.createTag(tagList[-1], text))
+ else:
+ tag = self.createTag(tagList[-1], text)
+ return tag
+
+ def appendTagRoute(self, tagRoute, value=None):
+ if not self._domObj:
+ return False
+ if not tagRoute:
+ return False
+
+ parentTagE = self._domObj
+
+ tagNameList = tagRoute.split(".")
+ newTagRoute = tagNameList.pop(-1)
+
+ for i in range(len(tagNameList), 0, -1):
+ tagE = self.getElementsByTagRoute(".".join(tagNameList[:i]))
+ if tagE:
+ parentTagE = tagE[0]
+ break
+ newTagRoute = tagNameList[i-1] + "." + newTagRoute
+
+ newTagE = self.createTagRoute(newTagRoute, value)
+ if not newTagE:
+ return False
+ try:
+ parentTagE.appendChild(newTagE)
+ except xml.dom.HierarchyRequestErr, e:
+ Utils.log("error occured. %s" + str(e))
+ return False
+ return True
+
+ def setTextByTagRoute(self, tagRoute, tagValue):
+ if not self._domObj:
+ return None
+
+ if not tagRoute:
+ return None
+
+ tagE = self.getElementsByTagRoute(tagRoute)
+ if not tagE:
+ return False
+
+ parentTagE = self.getElementsByTagRoute(".".join(tagRoute.split(".")[:-1]))
+ if not parentTagE:
+ return False
+
+ parentTagE[0].childNodes.remove(tagE[0])
+ parentTagE[0].appendChild(self.createTag(tagRoute.split(".")[-1], tagValue))
+ return True
+
+ def getElementsByTagRoute(self, tagRoute):
+ if not self._domObj:
+ return None
+
+ if not tagRoute:
+ return None
+
+ x = None
+ for tag in tagRoute.split("."):
+ if x is None:
+ x = self._domObj.getElementsByTagName(tag)
+ continue
+ if x == []:
+ break
+ x = x[0].getElementsByTagName(tag)
+ return x
+
+ def getTextByTagRoute(self, tagRoute):
+ if not self._domObj:
+ return None
+
+ x = self.getElementsByTagRoute(tagRoute)
+ if x:
+ return self.getText(x[0].childNodes)
+ return None
+
+ def getElementsByTagName(self, name):
+ if not self._domObj:
+ return None
+ return self._domObj.getElementsByTagName(name)
+
+ def writexml(self, fileName, indent="", addindent="", newl=""):
+ if not self._domObj:
+ return None
+ try:
+ fp = open(fileName, "w")
+ self._domObj.writexml(fp, indent, addindent, newl)
+ fp.close()
+ return True
+ except IOError:
+ return False
+
+ def toString(self, indent=" ", newl="\n", encoding = None):
+ if not self._domObj:
+ return None
+ return self._domObj.toprettyxml(indent, newl, encoding)
+
+ def toxml(self, encoding = None):
+ if not self._domObj:
+ return None
+ return self._domObj.toxml(encoding)
+
+ def toprettyxml(self, indent=" ", newl="\n", encoding = None):
+ return self.toString(indent, newl, encoding)
+
+ def createResponseTag(self):
+ responseTag = self._domObj.createElement("response")
+ return responseTag
+##--end of XDOM
+
+class RequestXml(XDOM):
+ def __init__(self, requestString, type=None):
+ if None == requestString:
+ XDOM.__init__(self)
+ return
+ try:
+ if None == type:
+ if os.path.isfile(requestString):
+ self._domObj = MDOM.parse(requestString)
+ else:
+ self._domObj = MDOM.parseString(requestString)
+ elif XML_FILE == type:
+ self._domObj = MDOM.parse(requestString)
+ elif XML_STRING == type:
+ self._domObj = MDOM.parseString(requestString)
+ except IOError:
+ XDOM.__init__(self)
+ except xml.parsers.expat.ExpatError:
+ XDOM.__init__(self)
+
+##--end of RequestXML
+
+
+class ResponseXml(XDOM):
+ _responseTag = None
+ def __init__(self):
+ XDOM.__init__(self)
+ self._responseTag = self.createResponseTag()
+ self._domObj.appendChild(self._responseTag)
+
+ @classmethod
+ def errorResponse(self, message):
+ if not self.responseTag:
+ return False
+ self.appendTagRoute("status.code", "-1");
+ self.appendTagRoute("status.message", message)
+
+ def append(self, tagName, tagValue=None):
+ if not self._responseTag:
+ return False
+ tag = self.createTag(tagName, tagValue)
+ if tag:
+ self._responseTag.appendChild(tag)
+ return True
+ return False
+
+ def appendTag(self, tag):
+ if not tag:
+ return False
+ if not self._responseTag:
+ return False
+ self._responseTag.appendChild(tag)
+ return True
+
+ def appendTagRoute(self, tagRoute, value=None):
+ if not self._responseTag:
+ return None
+ if not tagRoute:
+ return None
+
+ parentTagE = self._responseTag
+
+ tagNameList = tagRoute.split(".")
+ newTagRoute = tagNameList.pop(-1)
+
+ for i in range(len(tagNameList), 0, -1):
+ tagE = self.getElementsByTagRoute(".".join(["response"] + tagNameList[:i]))
+ if tagE:
+ parentTagE = tagE[0]
+ break
+ newTagRoute = tagNameList[i-1] + "." + newTagRoute
+
+ newTagE = self.createTagRoute(newTagRoute, value)
+ if not newTagE:
+ return None
+ try:
+ parentTagE.appendChild(newTagE)
+ except xml.dom.HierarchyRequestErr, e:
+ Utils.log("error occured. %s" + str(e))
+ return None
+ return newTagE
+
+ def appendTagRouteOld(self, tagRoute, value=None):
+ if not self._responseTag:
+ return False
+ if not tagRoute:
+ return False
+
+ parentTagE = self._responseTag
+
+ tagNameList = tagRoute.split(".")
+ newTagRoute = tagNameList.pop(-1)
+
+ for i in range(len(tagNameList), 0, -1):
+ tagE = self.getElementsByTagRoute(".".join(["response"] + tagNameList[:i]))
+ if tagE:
+ parentTagE = tagE[0]
+ break
+ newTagRoute = tagNameList[i-1] + "." + newTagRoute
+
+ newTagE = self.createTagRoute(newTagRoute, value)
+ if not newTagE:
+ return False
+ try:
+ parentTagE.appendChild(newTagE)
+ except xml.dom.HierarchyRequestErr, e:
+ Utils.log("error occured. %s" + str(e))
+ return False
+ return True
+##--end of ResponseXml
+
+def test():
+ rs = ResponseXml()
+ rs.appendTagRoute("status.code", "0");
+ rs.appendTagRoute("status.message", "SUCCESS")
+ serverTag = rs.appendTagRoute("server.name", "Server1")
+ networkInterfaces = rs.appendTagRoute("server.networkInterfaces", None)
+ networkTag = rs.createTag("networkInterface", None)
+ networkTag.appendChild(rs.createTag("name", "interface1"))
+ networkTag.appendChild(rs.createTag("ipaddress", "192.168.1.40"))
+ networkInterfaces.appendChild(networkTag)
+ networkTag = rs.createTag("networkInterface", None)
+ networkTag.appendChild(rs.createTag("name", "interface2"))
+ networkTag.appendChild(rs.createTag("ipaddress", "192.168.1.41"))
+ networkInterfaces.appendChild(networkTag)
+ print rs.toprettyxml()
+
+#test()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/add_user_cifs.py b/src/com.gluster.storage.management.gateway.scripts/src/add_user_cifs.py
new file mode 100755
index 00000000..7b9650d1
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/add_user_cifs.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python
+# Copyright (C) 2011 Gluster, Inc. <http://www.gluster.com>
+# This file is part of Gluster Management Gateway.
+#
+
+import os
+import sys
+import Globals
+import Utils
+
+def main():
+ if len(sys.argv) < 4:
+ sys.stderr.write("usage: %s UID USERNAME PASSWORD\n" % os.path.basename(sys.argv[0]))
+ sys.exit(-1)
+
+ uid = sys.argv[1]
+ userName = sys.argv[2]
+ password = sys.argv[3]
+
+ if Utils.runCommand("groupadd -g %s %s" % (uid, userName)) != 0:
+ Utils.log("failed to add group gid:%s, name:%s\n" % (uid, userName))
+ sys.exit(1)
+
+ command = ["useradd", "-c", Globals.VOLUME_USER_DESCRIPTION, "-M", "-d", "/", "-s", "/sbin/nologin", "-u", uid, "-g", uid, userName]
+ if Utils.runCommand(command) != 0:
+ Utils.log("failed to add user uid:%s, name:%s\n" % (uid, userName))
+ sys.exit(2)
+
+ if Utils.runCommand("smbpasswd -s -a %s" % userName,
+ input="%s\n%s\n" % (password, password)) != 0:
+ Utils.log("failed to set smbpassword of user uid:%s, name:%s\n" % (uid, userName))
+ sys.exit(3)
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/clear_volume_directory.py b/src/com.gluster.storage.management.gateway.scripts/src/clear_volume_directory.py
new file mode 100755
index 00000000..96677f56
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/clear_volume_directory.py
@@ -0,0 +1,97 @@
+#!/usr/bin/python
+# 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 sys
+import syslog
+import time
+from XmlHandler import ResponseXml
+import DiskUtils
+import Utils
+from optparse import OptionParser
+
+def clearVolumeDirectory(diskMountPoint, volumeName, todelete):
+ rs = ResponseXml()
+ if not DiskUtils.checkDiskMountPoint(diskMountPoint):
+ Utils.log("failed to find disk mount point %s" % diskMountPoint)
+ rs.appendTagRoute("status.code", "-1")
+ rs.appendTagRoute("status.message", "Error: Mount point does not exists")
+ return rs.toprettyxml()
+
+ if not os.path.exists(diskMountPoint):
+ rs.appendTagRoute("status.code", "-2")
+ rs.appendTagRoute("status.message", "Error: Mount point path does not exists")
+ return rs.toprettyxml()
+
+ # clear volume directory from the disk
+ volumeDirectory = "%s/%s" % (diskMountPoint, volumeName)
+ if not os.path.exists(volumeDirectory):
+ rs.appendTagRoute("status.code", "-3")
+ rs.appendTagRoute("status.message", "Error: Volume directory does not exists")
+ return rs.toprettyxml()
+
+ newVolumeDirectoryName = "%s_%s" % (volumeDirectory, time.time())
+ command = ["sudo", "mv", "-f", volumeDirectory, newVolumeDirectoryName]
+ rv = Utils.runCommandFG(command, stdout=True, root=True)
+ message = Utils.stripEmptyLines(rv["Stdout"])
+ if rv["Stderr"]:
+ error = Utils.stripEmptyLines(rv["Stderr"])
+ message += "Error: [%s]" % (error)
+ Utils.log("failed to rename volume directory %s, %s" % (volumeDirectory, error))
+ rs.appendTagRoute("status.code", rv["Status"])
+ rs.appendTagRoute("status.message", message)
+ return rs.toprettyxml()
+
+ if not todelete:
+ rv["Status"] = "0"
+ rs.appendTagRoute("status.code", rv["Status"])
+ rs.appendTagRoute("status.message", message)
+ return rs.toprettyxml()
+
+ command = ["sudo", "rm", "-fr", newVolumeDirectoryName]
+ rv = Utils.runCommandFG(command, stdout=True, root=True)
+ message = Utils.stripEmptyLines(rv["Stdout"])
+ if rv["Stderr"]:
+ error = Utils.stripEmptyLines(rv["Stderr"])
+ message += "Error: [%s]" % (error)
+ Utils.log("failed to clear volume directory %s, %s" % (newVolumeDirectoryName, error))
+ rs.appendTagRoute("status.code", rv["Status"])
+ rs.appendTagRoute("status.message", message)
+ return rs.toprettyxml()
+
+ if not rv["Status"]:
+ rv["Status"] = "0"
+ rs.appendTagRoute("status.code", rv["Status"])
+ rs.appendTagRoute("status.message", message)
+ return rs.toprettyxml()
+
+def main():
+ parser = OptionParser()
+ parser.add_option("-d", "--delete", dest="deletedir", action="store_true", default=False, help="force delete")
+ (options, args) = parser.parse_args()
+
+ if len(args) != 2:
+ sys.stderr.write("usage: %s <disk mount point> <volume name> [-d/--delete]\n" % os.path.basename(sys.argv[0]))
+ sys.exit(-1)
+
+ diskMountPoint = args[0]
+ volumeName = args[1]
+ print clearVolumeDirectory(diskMountPoint, volumeName, options.deletedir)
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/create_volume_cifs.py b/src/com.gluster.storage.management.gateway.scripts/src/create_volume_cifs.py
new file mode 100755
index 00000000..a81b165b
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/create_volume_cifs.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+# Copyright (C) 2011 Gluster, Inc. <http://www.gluster.com>
+# This file is part of Gluster Management Gateway.
+#
+
+import os
+import sys
+import Globals
+import Utils
+import VolumeUtils
+
+def main():
+ if len(sys.argv) < 3:
+ sys.stderr.write("usage: %s VOLUME_NAME USER1 USER2 ...\n" % os.path.basename(sys.argv[0]))
+ sys.exit(-1)
+
+ volumeName = sys.argv[1]
+ userList = sys.argv[2:]
+
+ volumeMountDirName = "%s/%s" % (Globals.REEXPORT_DIR, volumeName)
+ try:
+ os.mkdir(volumeMountDirName)
+ except OSError, e:
+ Utils.log("failed creating %s: %s\n" % (volumeMountDirName, str(e)))
+ sys.exit(1)
+
+ if VolumeUtils.writeVolumeCifsConfiguration(volumeName, userList):
+ sys.exit(0)
+ sys.exit(2)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/create_volume_directory.py b/src/com.gluster.storage.management.gateway.scripts/src/create_volume_directory.py
new file mode 100755
index 00000000..3e633697
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/create_volume_directory.py
@@ -0,0 +1,82 @@
+#!/usr/bin/python
+# 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 sys
+from XmlHandler import ResponseXml
+import DiskUtils
+import Utils
+
+def createDirectory(disk, volumeName):
+ # Retrieving disk uuid
+ diskUuid = DiskUtils.getUuidByDiskPartition(DiskUtils.getDevice(disk))
+
+ rs = ResponseXml()
+ if not diskUuid:
+ Utils.log("failed to find disk:%s uuid" % disk)
+ rs.appendTagRoute("status.code", "-1")
+ rs.appendTagRoute("status.message", "Error: Unable to find disk uuid")
+ return rs.toprettyxml()
+
+ # Retrieving disk mount point using disk uuid
+ diskMountPoint = DiskUtils.getMountPointByUuid(diskUuid)
+ if not os.path.exists(diskMountPoint):
+ Utils.log("failed to retrieve disk:%s mount point" % disk)
+ rs.appendTagRoute("status.code", "-1")
+ rs.appendTagRoute("status.message", "Error: Failed to retrieve disk details")
+ return rs.toprettyxml()
+
+ # creating volume directory under disk mount point
+ volumeDirectory = "%s/%s" % (diskMountPoint, volumeName)
+ if os.path.exists(volumeDirectory):
+ Utils.log("Volume directory:%s already exists" % (volumeDirectory))
+ rs.appendTagRoute("status.code", "-2")
+ rs.appendTagRoute("status.message", "Volume directory already exists!")
+ return rs.toprettyxml()
+
+ if not os.path.exists(volumeDirectory):
+ command = ["sudo", "mkdir", volumeDirectory]
+ rv = Utils.runCommandFG(command, stdout=True, root=True)
+ message = Utils.stripEmptyLines(rv["Stdout"])
+ if rv["Stderr"]:
+ error = Utils.stripEmptyLines(rv["Stderr"])
+ message += "Error: [%s]" % (error)
+ Utils.log("failed to create volume directory %s, %s" % (volumeDirectory, error))
+ rs.appendTagRoute("status.code", rv["Status"])
+ rs.appendTagRoute("status.message", message)
+ return rs.toprettyxml()
+
+ if not rv["Status"]:
+ rv["Status"] = "0"
+ if rv["Status"] == "0":
+ message = volumeDirectory
+ rs.appendTagRoute("status.code", rv["Status"])
+ rs.appendTagRoute("status.message", message)
+ return rs.toprettyxml()
+
+def main():
+ if len(sys.argv) != 3:
+ sys.stderr.write("usage: %s <disk name> <volume name>\n" % os.path.basename(sys.argv[0]))
+ sys.exit(-1)
+
+ disk = sys.argv[1]
+ volumeName = sys.argv[2]
+ print createDirectory(disk, volumeName)
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/delete_user_cifs.py b/src/com.gluster.storage.management.gateway.scripts/src/delete_user_cifs.py
new file mode 100755
index 00000000..e5cda957
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/delete_user_cifs.py
@@ -0,0 +1,24 @@
+#!/usr/bin/python
+# Copyright (C) 2011 Gluster, Inc. <http://www.gluster.com>
+# This file is part of Gluster Management Gateway.
+#
+
+import os
+import sys
+import Utils
+
+def main():
+ if len(sys.argv) < 2:
+ sys.stderr.write("usage: %s USERNAME\n" % os.path.basename(sys.argv[0]))
+ sys.exit(-1)
+
+ userName = sys.argv[1]
+
+ if Utils.runCommand("userdel %s" % userName) != 0:
+ Utils.log("failed to remove user name:%s\n" % userName)
+ sys.exit(1)
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/delete_volume_cifs.py b/src/com.gluster.storage.management.gateway.scripts/src/delete_volume_cifs.py
new file mode 100755
index 00000000..fd1febc9
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/delete_volume_cifs.py
@@ -0,0 +1,32 @@
+#!/usr/bin/python
+# Copyright (C) 2011 Gluster, Inc. <http://www.gluster.com>
+# This file is part of Gluster Management Gateway.
+#
+
+import os
+import sys
+import Globals
+import Utils
+import VolumeUtils
+
+def main():
+ if len(sys.argv) != 2:
+ sys.stderr.write("usage: %s VOLUME_NAME\n" % os.path.basename(sys.argv[0]))
+ sys.exit(-1)
+
+ volumeName = sys.argv[1]
+
+ volumeMountDirName = "%s/%s" % (Globals.REEXPORT_DIR, volumeName)
+ try:
+ os.rmdir(volumeMountDirName)
+ except OSError, e:
+ Utils.log("failed deleting %s: %s\n" % (volumeMountDirName, str(e)))
+ sys.exit(1)
+
+ if VolumeUtils.removeVolumeCifsConfiguration(volumeName):
+ sys.exit(0)
+ sys.exit(2)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/disable-ssh-password-auth.sh b/src/com.gluster.storage.management.gateway.scripts/src/disable-ssh-password-auth.sh
new file mode 100755
index 00000000..07ee1a3a
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/disable-ssh-password-auth.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+#-----------------------------------------------------------------------------
+# disable-ssh-password-auth.sh
+# Script for disabling SSH password authentication. This is used by the
+# management gateway after installing the public key, so that the gluster
+# node can be accessed (using ssh) only from the management gateway.
+#-----------------------------------------------------------------------------
+
+CONFIG_FILE="/etc/ssh/sshd_config"
+TIMESTAMP=`date +%d%m%Y%H%M%S`
+BACKUP_FILE="${CONFIG_FILE}_${TIMESTAMP}"
+TEMP_FILE="/tmp/new_sshd_config_${TIMESTAMP}"
+
+# Modify config file to disable password authentication, redirect to a temp file
+# TODO: disable only if enabled!
+sed "s/^PasswordAuthentication yes$/PasswordAuthentication no/g" ${CONFIG_FILE} > ${TEMP_FILE}
+
+# Secure the file by changing permissions (600)
+chmod 600 ${TEMP_FILE}
+
+# Take backup of config file
+cp ${CONFIG_FILE} ${BACKUP_FILE}
+
+# Overwrite config file with the modified one
+mv ${TEMP_FILE} ${CONFIG_FILE}
+
+# Re-start ssh daemon
+/etc/init.d/sshd restart
+
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/format_device.py b/src/com.gluster.storage.management.gateway.scripts/src/format_device.py
new file mode 100755
index 00000000..3bc70532
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/format_device.py
@@ -0,0 +1,87 @@
+#!/usr/bin/python
+# 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 sys
+import Globals
+import Utils
+import DiskUtils
+from optparse import OptionParser
+
+
+def main():
+ if Utils.runCommand("wget -q -O /dev/null %s" % Globals.AWS_WEB_SERVICE_URL) == 0:
+ sys.stderr.write("format device unsupported")
+ sys.exit(1)
+
+ parser = OptionParser()
+ parser.add_option("-t", "--type", action="store", type="string", dest="fstype")
+ (options, args) = parser.parse_args()
+
+ if len(args) != 1:
+ sys.stderr.write("usage: %s [-t FSTYPE] DEVICE_NAME\n" % os.path.basename(sys.argv[0]))
+ sys.exit(-1)
+
+ device = DiskUtils.getDevice(args[0])
+ deviceFormatLockFile = Utils.getDeviceFormatLockFile(device)
+ deviceFormatStatusFile = Utils.getDeviceFormatStatusFile(device)
+ deviceFormatOutputFile = Utils.getDeviceFormatOutputFile(device)
+
+ if DiskUtils.isDataDiskPartitionFormatted(device):
+ sys.stderr.write("Device already formatted\n")
+ sys.exit(2)
+
+ if os.path.exists(deviceFormatStatusFile):
+ Utils.log("format status file %s exists" % deviceFormatStatusFile)
+ try:
+ fp = open(deviceFormatStatusFile)
+ line = fp.read()
+ fp.close()
+ if line.strip().upper() == "COMPLETED":
+ sys.stderr.write("Device already formatted\n")
+ sys.exit(3)
+ else:
+ sys.stderr.write("Device format already running\n")
+ sys.exit(4)
+ except IOError, e:
+ Utils.log("failed to read format status file %s: %s" % (deviceFormatStatusFile, str(e)))
+ sys.stderr.write("%s\n" % str(e))
+ sys.exit(-2)
+
+ if os.path.exists(deviceFormatLockFile):
+ Utils.log("lock file %s exists" % deviceFormatLockFile)
+ sys.stderr.write("Device format already running\n")
+ sys.exit(5)
+
+ if options.fstype:
+ command = ["gluster_provision_block_wrapper.py", "-t", "%s" % (options.fstype), "%s" % (device)]
+ else:
+ command = ["gluster_provision_block_wrapper.py", "%s" % (device)]
+
+ try:
+ pid = os.fork()
+ except OSError, e:
+ Utils.log("failed to fork a child process: %s" % str(e))
+ sys.exit(6)
+ if pid == 0:
+ os.execv("/usr/sbin/gluster_provision_block_wrapper.py", command)
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_brick_status.py b/src/com.gluster.storage.management.gateway.scripts/src/get_brick_status.py
new file mode 100755
index 00000000..cf84080b
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/get_brick_status.py
@@ -0,0 +1,40 @@
+#!/usr/bin/python
+# Copyright (C) 2011 Gluster, Inc. <http://www.gluster.com>
+# This file is part of Gluster Management Console.
+#
+
+import os
+import sys
+import Utils
+
+def main():
+ if len(sys.argv) != 3:
+ sys.stderr.write("usage: %s VOLUME_NAME BRICK_NAME\n" % os.path.basename(sys.argv[0]))
+ sys.exit(-1)
+
+ volumeName = sys.argv[1]
+ brickName = sys.argv[2]
+ pidFile = "/etc/glusterd/vols/%s/run/%s.pid" % (volumeName, brickName.replace(":", "").replace("/", "-"))
+
+ if not os.path.exists(pidFile):
+ print "OFFLINE"
+ else:
+ try:
+ fp = open(pidFile)
+ pidString = fp.readline()
+ fp.close()
+ os.getpgid(int(pidString))
+ print "ONLINE"
+ except IOError, e:
+ Utils.log("failed to open file %s: %s" % (pidFile, str(e)))
+ print "UNKNOWN"
+ except ValueError, e:
+ Utils.log("invalid pid %s in file %s: %s" % (pidString, pidFile, str(e)))
+ print "UNKNOWN"
+ except OSError, e:
+ #Utils.log("failed to get process detail of pid %s: %s" % (pidString, str(e)))
+ print "OFFLINE"
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_disk_mount_point.py b/src/com.gluster.storage.management.gateway.scripts/src/get_disk_mount_point.py
new file mode 100755
index 00000000..2f4a39c3
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/get_disk_mount_point.py
@@ -0,0 +1,62 @@
+#!/usr/bin/python
+# 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
+from DiskUtils import *
+from XmlHandler import ResponseXml
+
+
+def getmountpoint(path):
+ if not path:
+ Utils.log("Not a valid path:%s" % path)
+ rs.appendTagRoute("status.code", "-1")
+ rs.appendTagRoute("status.message", "Error: given path name is empty")
+ return rs.toprettyxml()
+
+ rs = ResponseXml()
+ mountPoint = None
+
+ for line in readFsTab():
+ if path.startswith(line['MountPoint']):
+ if not mountPoint:
+ mountPoint = line['MountPoint']
+ if len(line['MountPoint']) > len(mountPoint):
+ mountPoint = line['MountPoint']
+
+ if "/" == mountPoint or not mountPoint:
+ Utils.log("failed to find mount point of the given path:%s" % path)
+ rs.appendTagRoute("status.code", "-1")
+ rs.appendTagRoute("status.message", "Error: Unable to find disk mount point")
+ return rs.toprettyxml()
+
+ rs.appendTagRoute("status.code", "0")
+ rs.appendTagRoute("status.message", mountPoint)
+ return rs.toprettyxml()
+
+def main():
+ if len(sys.argv) != 2:
+ sys.stderr.write("usage: %s <path>\n" % os.path.basename(sys.argv[0]))
+ sys.exit(-1)
+
+ path = sys.argv[1]
+ print getmountpoint(path)
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_disk_name_by_path.py b/src/com.gluster.storage.management.gateway.scripts/src/get_disk_name_by_path.py
new file mode 100755
index 00000000..08e80b7e
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/get_disk_name_by_path.py
@@ -0,0 +1,68 @@
+#!/usr/bin/python
+# 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
+from DiskUtils import *
+from XmlHandler import ResponseXml
+
+
+def getmountpoint(path):
+ if not path:
+ Utils.log("Not a valid path:%s" % path)
+ rs.appendTagRoute("status.code", "-1")
+ rs.appendTagRoute("status.message", "Error: given path name is empty")
+ return rs.toprettyxml()
+
+ rs = ResponseXml()
+ mountPoint = None
+ fsTabEntry = None
+ for line in readFsTab():
+ if path.startswith(line['MountPoint']):
+ if not mountPoint:
+ mountPoint = line['MountPoint']
+ fsTabEntry = line
+ if len(line['MountPoint']) > len(mountPoint):
+ mountPoint = line['MountPoint']
+ fsTabEntry = line
+
+ if "/" == mountPoint or not mountPoint:
+ Utils.log("failed to find mount point of the given path:%s" % path)
+ rs.appendTagRoute("status.code", "-1")
+ rs.appendTagRoute("status.message", "Error: Unable to find disk mount point")
+ return rs.toprettyxml()
+
+ rs.appendTagRoute("status.code", "0")
+ if fsTabEntry["Device"].startswith("UUID="):
+ rs.appendTagRoute("status.message", getDiskPartitionByUuid(fsTabEntry["Device"].split("UUID=")[-1]))
+ else:
+ rs.appendTagRoute("status.message", "Unable to find disk name")
+ return rs.toprettyxml()
+
+def main():
+ if len(sys.argv) != 2:
+ sys.stderr.write("usage: %s <path>\n" % os.path.basename(sys.argv[0]))
+ sys.exit(-1)
+
+ path = sys.argv[1]
+ print getmountpoint(path)
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
+
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_file.py b/src/com.gluster.storage.management.gateway.scripts/src/get_file.py
new file mode 100755
index 00000000..61c33eba
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/get_file.py
@@ -0,0 +1,130 @@
+# 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 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()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_format_device_status.py b/src/com.gluster.storage.management.gateway.scripts/src/get_format_device_status.py
new file mode 100755
index 00000000..57fc0455
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/get_format_device_status.py
@@ -0,0 +1,124 @@
+#!/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 os
+import sys
+import time
+import Utils
+import DiskUtils
+from XmlHandler import ResponseXml
+
+def main():
+ if len(sys.argv) != 2:
+ sys.stderr.write("usage: %s DEVICE_NAME\n" % os.path.basename(sys.argv[0]))
+ sys.exit(-1)
+
+ device = DiskUtils.getDevice(sys.argv[1])
+
+ deviceFormatLockFile = Utils.getDeviceFormatLockFile(device)
+ deviceFormatStatusFile = Utils.getDeviceFormatStatusFile(device)
+ deviceFormatOutputFile = Utils.getDeviceFormatOutputFile(device)
+
+ time.sleep(1)
+ if not os.path.exists(deviceFormatLockFile):
+ if not os.path.exists(deviceFormatStatusFile):
+ sys.stderr.write("Device format not initiated\n")
+ sys.exit(1)
+
+ if os.path.exists(deviceFormatStatusFile):
+ try:
+ fp = open(deviceFormatStatusFile)
+ line = fp.read()
+ fp.close()
+ line = line.strip()
+
+ Utils.removeFile(deviceFormatOutputFile)
+ Utils.removeFile(deviceFormatStatusFile)
+
+ responseDom = ResponseXml()
+ responseDom.appendTagRoute("device", sys.argv[1])
+ responseDom.appendTagRoute("completedBlocks", "0")
+ responseDom.appendTagRoute("totalBlocks", "0")
+ responseDom.appendTagRoute("message", line)
+ if line.upper() == "COMPLETED":
+ responseDom.appendTagRoute("formatStatus", "COMPLETED")
+ else:
+ responseDom.appendTagRoute("formatStatus", "NOT_RUNNING")
+ print responseDom.toxml()
+ sys.exit(0)
+ except IOError, e:
+ Utils.log("failed to read format status file %s: %s" % (deviceFormatStatusFile, str(e)))
+ sys.stderr.write("%s\n" % str(e))
+ sys.exit(-2)
+
+ if not os.path.exists(deviceFormatOutputFile):
+ responseDom = ResponseXml()
+ responseDom.appendTagRoute("device", sys.argv[1])
+ responseDom.appendTagRoute("completedBlocks", "0")
+ responseDom.appendTagRoute("totalBlocks", "0")
+ responseDom.appendTagRoute("message", None)
+ responseDom.appendTagRoute("formatStatus", "IN_PROGRESS")
+ print responseDom.toxml()
+ sys.exit(0)
+
+ try:
+ fp = open(deviceFormatOutputFile)
+ content = fp.read()
+ fp.close()
+ except IOError, e:
+ Utils.log("failed to read format output file %s: %s" % (deviceFormatOutputFile, str(e)))
+ responseDom = ResponseXml()
+ responseDom.appendTagRoute("device", sys.argv[1])
+ responseDom.appendTagRoute("completedBlocks", "0")
+ responseDom.appendTagRoute("totalBlocks", "0")
+ responseDom.appendTagRoute("message", None)
+ responseDom.appendTagRoute("formatStatus", "IN_PROGRESS")
+ print responseDom.toxml()
+ sys.exit(0)
+
+ lines = [line for line in content
+ if "Writing inode tables" in line]
+ if not lines:
+ responseDom = ResponseXml()
+ responseDom.appendTagRoute("device", sys.argv[1])
+ responseDom.appendTagRoute("completedBlocks", "0")
+ responseDom.appendTagRoute("totalBlocks", "0")
+ if content:
+ responseDom.appendTagRoute("message", content[-1])
+ else:
+ responseDom.appendTagRoute("message")
+ responseDom.appendTagRoute("formatStatus", "IN_PROGRESS")
+ print responseDom.toxml()
+ sys.exit(0)
+
+ tokens = [token for token in lines[-1].split("\x08") if token]
+ if "done" in tokens[-1]:
+ values = tokens[-2].split(':')[-1].strip().split('/')
+ else:
+ values = tokens[-1].split(':')[-1].strip().split('/')
+
+ responseDom.appendTagRoute("device", sys.argv[1])
+ responseDom.appendTagRoute("completedBlocks", values[0])
+ responseDom.appendTagRoute("totalBlocks", values[1])
+ responseDom.appendTagRoute("message", lines[-1])
+ responseDom.appendTagRoute("formatStatus", "IN_PROGRESS")
+ print responseDom.toxml()
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_rrd_cpu_details.py b/src/com.gluster.storage.management.gateway.scripts/src/get_rrd_cpu_details.py
new file mode 100755
index 00000000..546aec31
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/get_rrd_cpu_details.py
@@ -0,0 +1,55 @@
+#!/usr/bin/python
+# 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 sys
+from XmlHandler import ResponseXml
+import Utils
+
+def getCpuData(period):
+ cpuRrdFile = "/var/lib/rrd/cpu.rrd"
+ rs = ResponseXml()
+ command = "rrdtool xport --start -%s \
+ DEF:cpuuser=%s:user:AVERAGE \
+ DEF:cpusystem=%s:system:AVERAGE \
+ CDEF:total=cpuuser,cpusystem,+ \
+ XPORT:cpuuser:user \
+ XPORT:cpusystem:system \
+ XPORT:total:total" % (period, cpuRrdFile, cpuRrdFile)
+
+ rv = Utils.runCommand(command, output=True, root=True)
+ message = Utils.stripEmptyLines(rv["Stdout"])
+ if rv["Stderr"]:
+ error = Utils.stripEmptyLines(rv["Stderr"])
+ message += "Error: [%s]" % (error)
+ Utils.log("failed to create RRD file for cpu usages %s" % file)
+ rs.appendTagRoute("status.code", rv["Status"])
+ rs.appendTagRoute("status.message", message)
+ return rs.toxml()
+ return rv["Stdout"]
+
+def main():
+ if len(sys.argv) != 2:
+ sys.stderr.write("usage: %s <period>\n" % os.path.basename(sys.argv[0]))
+ sys.exit(-1)
+
+ period = sys.argv[1]
+ print getCpuData(period)
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_rrd_memory_details.py b/src/com.gluster.storage.management.gateway.scripts/src/get_rrd_memory_details.py
new file mode 100755
index 00000000..f7c3031b
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/get_rrd_memory_details.py
@@ -0,0 +1,89 @@
+#!/usr/bin/python
+# 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/>.
+
+# Input command: get_rrd_memory_details.py 1hour
+# OUTPUT as bellow:
+# <?xml version="1.0" encoding="ISO-8859-1"?>
+#
+# <xport>
+# <meta>
+# <start>1310455500</start>
+# <step>300</step>
+# <end>1310459100</end>
+# <rows>13</rows>
+# <columns>5</columns>
+# <legend>
+# <entry>memoryUsed</entry>
+# <entry>memoryFree</entry>
+# <entry>memoryCache</entry>
+# <entry>memoryBuffer</entry>
+# <entry>totalMemory</entry>
+# </legend>
+# </meta>
+# <data>
+# <row><t>1310455500</t><v>1.9181091707e+06</v><v>1.5819754974e+06</v><v>1.2528146351e+06</v><v>1.2528146351e+06</v><v>3.5000846681e+06</v></row>
+# ---
+# ---
+# </data>
+# </xport>
+
+import os
+import sys
+import syslog
+from XmlHandler import ResponseXml
+import Utils
+
+def getMemData(period):
+ memRrdFile = "/var/lib/rrd/mem.rrd"
+ rs = ResponseXml()
+ command = "rrdtool xport --start -%s \
+ DEF:free=%s:memfree:AVERAGE \
+ DEF:used=%s:memused:AVERAGE \
+ DEF:cache=%s:memcache:AVERAGE \
+ DEF:buffer=%s:membuffer:AVERAGE \
+ CDEF:total1=used,free,+ \
+ CDEF:used1=used,buffer,cache,-,- \
+ CDEF:total=total1,used1,+ \
+ XPORT:used:memoryUsed \
+ XPORT:free:memoryFree \
+ XPORT:cache:memoryCache \
+ XPORT:buffer:memoryBuffer \
+ XPORT:total:totalMemory" % (period, memRrdFile, memRrdFile, memRrdFile, memRrdFile)
+
+ rv = Utils.runCommand(command, output=True, root=True)
+ message = Utils.stripEmptyLines(rv["Stdout"])
+ if rv["Stderr"]:
+ error = Utils.stripEmptyLines(rv["Stderr"])
+ message += "Error: [%s]" % (error)
+ Utils.log("failed to create RRD file for memory usages %s" % file)
+ rs.appendTagRoute("status.code", rv["Status"])
+ rs.appendTagRoute("status.message", message)
+ return rs.toxml()
+ return rv["Stdout"]
+
+def main():
+ if len(sys.argv) != 2:
+ sys.stderr.write("usage: %s <period>\n" % os.path.basename(sys.argv[0]))
+ sys.exit(-1)
+
+ period = sys.argv[1]
+ print getMemData(period)
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_rrd_net_details.py b/src/com.gluster.storage.management.gateway.scripts/src/get_rrd_net_details.py
new file mode 100755
index 00000000..6a31cde8
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/get_rrd_net_details.py
@@ -0,0 +1,52 @@
+#!/usr/bin/python
+# 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 sys
+from XmlHandler import ResponseXml
+import Utils
+
+def main():
+ if len(sys.argv) != 3:
+ sys.stderr.write("usage: %s <DEVICE> <PERIOD>\n" % os.path.basename(sys.argv[0]))
+ sys.exit(-1)
+
+ device = sys.argv[1]
+ period = sys.argv[2]
+
+ rs = ResponseXml()
+ command = "rrdtool xport --start -%s \
+ DEF:received=/var/lib/rrd/network-%s.rrd:received:AVERAGE \
+ DEF:transmitted=/var/lib/rrd/network-%s.rrd:transmitted:AVERAGE \
+ CDEF:total=received,transmitted,+ \
+ XPORT:received:received \
+ XPORT:transmitted:transmitted \
+ XPORT:total:total" % (period, device, device)
+ rv = Utils.runCommand(command, output=True, root=True)
+ message = Utils.stripEmptyLines(rv["Stdout"])
+ if rv["Stderr"]:
+ error = Utils.stripEmptyLines(rv["Stderr"])
+ message += "Error: [%s]" % (error)
+ Utils.log("failed to get RRD information of device %s" % file)
+ rs.appendTagRoute("status.code", rv["Status"])
+ rs.appendTagRoute("status.message", message)
+ print rs.toxml()
+ print rv["Stdout"]
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_server_details.py b/src/com.gluster.storage.management.gateway.scripts/src/get_server_details.py
new file mode 100755
index 00000000..9c3da741
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/get_server_details.py
@@ -0,0 +1,118 @@
+#!/usr/bin/python
+# Copyright (C) 2009 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 sys
+import socket
+import re
+import Utils
+import DiskUtils
+from NetworkUtils import *
+from Disk import *
+from XmlHandler import ResponseXml
+from optparse import OptionParser
+
+
+def getServerDetails(listall):
+ serverName = socket.gethostname()
+ meminfo = getMeminfo()
+ cpu = getCpuUsageAvg()
+ nameServerList, domain, searchDomain = readResolvConfFile()
+ if not domain:
+ domain = [None]
+
+ responseDom = ResponseXml()
+ serverTag = responseDom.appendTagRoute("server")
+ serverTag.appendChild(responseDom.createTag("name", serverName))
+ serverTag.appendChild(responseDom.createTag("domainname", domain[0]))
+ if Utils.runCommand("pidof glusterd") == 0:
+ serverTag.appendChild(responseDom.createTag("status", "ONLINE"))
+ else:
+ serverTag.appendChild(responseDom.createTag("status", "OFFLINE"))
+ serverTag.appendChild(responseDom.createTag("cpuUsage", str(cpu)))
+ serverTag.appendChild(responseDom.createTag("totalMemory", str(convertKbToMb(meminfo['MemTotal']))))
+ serverTag.appendChild(responseDom.createTag("memoryInUse", str(convertKbToMb(meminfo['MemUsed']))))
+ serverTag.appendChild(responseDom.createTag("uuid", None))
+
+ for dns in nameServerList:
+ serverTag.appendChild(responseDom.createTag("dns%s" % str(nameServerList.index(dns) +1) , dns))
+
+ #TODO: probe and retrieve timezone, ntp-server details and update the tags
+
+ deviceList = {}
+ interfaces = responseDom.createTag("networkInterfaces", None)
+ for device in getNetDeviceList():
+ if device["model"] in ['LOCAL', 'IPV6-IN-IPV4']:
+ continue
+ deviceList[device["device"]] = device
+ try:
+ macAddress = open("/sys/class/net/%s/address" % device["device"]).read().strip()
+ except IOError:
+ continue
+ interfaceTag = responseDom.createTag("networkInterface", None)
+ interfaceTag.appendChild(responseDom.createTag("name", device["device"]))
+ interfaceTag.appendChild(responseDom.createTag("hwAddr",macAddress))
+ interfaceTag.appendChild(responseDom.createTag("speed", device["speed"]))
+ interfaceTag.appendChild(responseDom.createTag("model", device["model"]))
+ if deviceList[device["device"]]:
+ if deviceList[device["device"]]["onboot"]:
+ interfaceTag.appendChild(responseDom.createTag("onboot", "yes"))
+ else:
+ interfaceTag.appendChild(responseDom.createTag("onBoot", "no"))
+ interfaceTag.appendChild(responseDom.createTag("bootProto", deviceList[device["device"]]["bootproto"]))
+ interfaceTag.appendChild(responseDom.createTag("ipAddress", deviceList[device["device"]]["ipaddr"]))
+ interfaceTag.appendChild(responseDom.createTag("netMask", deviceList[device["device"]]["netmask"]))
+ interfaceTag.appendChild(responseDom.createTag("defaultGateway", deviceList[device["device"]]["gateway"]))
+ if deviceList[device["device"]]["mode"]:
+ interfaceTag.appendChild(responseDom.createTag("mode", deviceList[device["device"]]["mode"]))
+ if deviceList[device["device"]]["master"]:
+ interfaceTag.appendChild(responseDom.createTag("bonding", "yes"))
+ spliter = re.compile(r'[\D]')
+ interfaceTag.appendChild(responseDom.createTag("bondid", spliter.split(device["master"])[-1]))
+ else:
+ interfaceTag.appendChild(responseDom.createTag("onBoot", "no"))
+ interfaceTag.appendChild(responseDom.createTag("bootProto", "none"))
+ interfaces.appendChild(interfaceTag)
+ serverTag.appendChild(interfaces)
+
+ responseDom.appendTag(serverTag)
+ serverTag.appendChild(responseDom.createTag("numOfCPUs", int(os.sysconf('SC_NPROCESSORS_ONLN'))))
+
+ diskDom = DiskUtils.getDiskDom()
+ if not diskDom:
+ sys.stderr.write("No disk found!")
+ Utils.log("Failed to get disk details")
+ sys.exit(1)
+
+ serverTag.appendChild(diskDom.getElementsByTagRoute("disks")[0])
+ return serverTag
+
+def main():
+ parser = OptionParser()
+ parser.add_option("-N", "--only-data-disks",
+ action="store_false", dest="listall", default=True,
+ help="List only data disks")
+
+ (options, args) = parser.parse_args()
+ responseXml = getServerDetails(options.listall)
+ if responseXml:
+ print responseXml.toxml()
+
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_server_status.py b/src/com.gluster.storage.management.gateway.scripts/src/get_server_status.py
new file mode 100755
index 00000000..a57428b6
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/get_server_status.py
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+# Copyright (C) 2011 Gluster, Inc. <http://www.gluster.com>
+# This file is part of Gluster Management Console.
+#
+
+import os
+import sys
+import Utils
+
+def main():
+ if len(sys.argv) != 1:
+ sys.stderr.write("usage: %s\n" % os.path.basename(sys.argv[0]))
+ sys.exit(-1)
+
+ if Utils.runCommand("pidof glusterd") == 0:
+ print "ONLINE"
+ else:
+ print "OFFLINE"
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_volume_brick_log.py b/src/com.gluster.storage.management.gateway.scripts/src/get_volume_brick_log.py
new file mode 100755
index 00000000..fd7361da
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/get_volume_brick_log.py
@@ -0,0 +1,103 @@
+#!/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 XDOM
+
+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, logMessagesTag, loginfo):
+ logMessageTag = responseDom.createTag("logMessage")
+ logMessageTag.appendChild(responseDom.createTag("timestamp", loginfo[0] + " " + loginfo[1]))
+ logMessageTag.appendChild(responseDom.createTag("severity", enumLogType(loginfo[2])))
+ logMessageTag.appendChild(responseDom.createTag("message", loginfo[3]))
+ logMessagesTag.appendChild(logMessageTag);
+ 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 = XDOM()
+ if not logFilePath:
+ print >> sys.stderr, "No log file path given"
+ sys.exit(-1);
+
+ if not tailCount:
+ print >> sys.stderr, "No tail count given"
+ sys.exit(-1);
+
+ pattern = '\[\d{4}-\d{2}-\d{2}\s{1}\d{2}:\d{2}:\d{2}.\d+\]\s{1}([MACEWNIDT]){1}\s+'
+ if not os.path.exists(logFilePath):
+ print >> sys.stderr, "volume log file [%s] not found!" % logFilePath
+ sys.exit(-1);
+
+ fp = open(logFilePath)
+ lines = [line for line in fp if re.match(pattern, line)]
+ fp.close()
+ i = len(lines) - int(tailCount)
+ if i < 0:
+ i = 0
+ logMessagesTag = rs.createTag("logMessages")
+ rs.addTag(logMessagesTag)
+ for log in lines[i:]:
+ loginfo = logSplit(log)
+ addLog(rs, logMessagesTag, loginfo)
+ return rs.toxml()
+##--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.gateway.scripts/src/get_volume_log.py b/src/com.gluster.storage.management.gateway.scripts/src/get_volume_log.py
new file mode 100755
index 00000000..b906c002
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/get_volume_log.py
@@ -0,0 +1,131 @@
+# 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 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()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/gluster_provision_block_wrapper.py b/src/com.gluster.storage.management.gateway.scripts/src/gluster_provision_block_wrapper.py
new file mode 100755
index 00000000..a3b2776d
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/gluster_provision_block_wrapper.py
@@ -0,0 +1,109 @@
+#!/usr/bin/python
+# 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 sys
+import subprocess
+import Utils
+import DiskUtils
+from optparse import OptionParser
+
+def writeStatus(deviceFormatStatusFile, message):
+ try:
+ fp = open(deviceFormatStatusFile, "w")
+ fp.write(message)
+ fp.close()
+ except IOError, e:
+ Utils.log("Failed to update log file %s: %s" % (deviceFormatStatusFile, str(e)))
+ return False
+ return True
+
+
+def main():
+ parser = OptionParser()
+ parser.add_option("-t", "--type", action="store", type="string", dest="fstype")
+ (options, args) = parser.parse_args()
+
+ if len(args) != 1:
+ sys.stderr.write("usage: %s [-t FSTYPE] DEVICE" % os.path.basename(sys.argv[0]))
+ sys.exit(-1)
+
+ device = args[0]
+ deviceFormatLockFile = Utils.getDeviceFormatLockFile(device)
+ deviceFormatStatusFile = Utils.getDeviceFormatStatusFile(device)
+ deviceFormatOutputFile = Utils.getDeviceFormatOutputFile(device)
+
+ if os.path.exists(deviceFormatStatusFile):
+ Utils.log("device format status file %s exists" % deviceFormatStatusFile)
+ sys.exit(1)
+
+ if os.path.exists(deviceFormatLockFile):
+ Utils.log("device format lock file %s exists" % deviceFormatLockFile)
+ sys.exit(2)
+
+ try:
+ fp = open(deviceFormatLockFile, "w")
+ fp.close()
+ except OSError, e:
+ Utils.log("failed to create lock file %s: %s" % (deviceFormatLockFile, str(e)))
+ writeStatus(deviceFormatStatusFile, "Lock file creation failed\n")
+ sys.exit(3)
+
+ try:
+ fptr = open(deviceFormatOutputFile, 'w')
+ except IOError, e:
+ Utils.log("failed to create output file %s" % deviceFormatOutputFile)
+ writeStatus(deviceFormatStatusFile, "Output file creation failed\n")
+ Utils.removeFile(deviceFormatLockFile)
+ sys.exit(4)
+
+ if options.fstype:
+ command = "gluster-provision-block -t %s %s" % (options.fstype, device)
+ else:
+ command = "gluster-provision-block %s" % (device)
+
+ process = Utils.runCommandBG(command,
+ stdinFileObj=subprocess.PIPE,
+ stdoutFileObj=fptr,
+ stderrFileObj=subprocess.PIPE)
+ if process:
+ status = process.wait()
+ else:
+ Utils.removeFile(deviceFormatOutputFile)
+ Utils.removeFile(deviceFormatLockFile)
+ writeStatus(deviceFormatStatusFile, "Device format failed\n")
+ sys.exit(5)
+
+ if status != 0:
+ Utils.removeFile(deviceFormatOutputFile)
+ Utils.removeFile(deviceFormatLockFile)
+ writeStatus(deviceFormatStatusFile, "Device format failed\n")
+ sys.exit(6)
+
+ if Utils.runCommand("/sbin/udevtrigger") != 0:
+ Utils.log("failed running /sbin/udevtrigger")
+
+ if Utils.runCommand("/usr/bin/lshal") != 0:
+ Utils.log("failed running /usr/bin/lshal")
+ writeStatus(deviceFormatStatusFile, "Completed\n")
+ Utils.removeFile(deviceFormatOutputFile)
+ Utils.removeFile(deviceFormatLockFile)
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/modify_volume_cifs.py b/src/com.gluster.storage.management.gateway.scripts/src/modify_volume_cifs.py
new file mode 100755
index 00000000..f6bacfc4
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/modify_volume_cifs.py
@@ -0,0 +1,28 @@
+#!/usr/bin/python
+# Copyright (C) 2011 Gluster, Inc. <http://www.gluster.com>
+# This file is part of Gluster Management Gateway.
+#
+
+import os
+import sys
+import Utils
+import VolumeUtils
+
+def main():
+ if len(sys.argv) <= 2:
+ sys.stderr.write("usage: %s VOLUME_NAME USER1 USER2 ...\n" % os.path.basename(sys.argv[0]))
+ sys.exit(-1)
+
+ volumeName = sys.argv[1]
+ userList = sys.argv[2:]
+
+ if not VolumeUtils.writeVolumeCifsConfiguration(volumeName, userList):
+ sys.exit(1)
+ if Utils.runCommand("service smb reload") != 0:
+ Utils.log("Failed to reload smb service")
+ sys.exit(2)
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/multicast_response.py b/src/com.gluster.storage.management.gateway.scripts/src/multicast_response.py
new file mode 100644
index 00000000..18cf89ae
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/multicast_response.py
@@ -0,0 +1,74 @@
+#!/usr/bin/python
+# Copyright (C) 2009 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 string
+import time
+import Utils
+import socket
+import struct
+import Globals
+from XmlHandler import *
+
+def isInPeer():
+ command = "gluster peer status"
+ status = Utils.runCommand(command, output=True, root=True)
+ if status["Status"] == 0:
+ if status["Stdout"].strip().upper() != "NO PEERS PRESENT":
+ return True
+ return False
+ Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"])))
+ return False
+
+def response(multiCastGroup, port):
+ # waiting for the request!
+ socketRequest = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
+ socketRequest.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ socketRequest.bind(('', port))
+ mreq = struct.pack("4sl", socket.inet_aton(multiCastGroup), socket.INADDR_ANY)
+ socketRequest.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
+
+ socketSend = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
+ socketSend.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
+
+ #TODO: Remove infinite loop and make this as a deamon (service)
+ while True:
+ request = socketRequest.recvfrom(1024)
+ if not request:
+ continue
+ dom = XDOM()
+ dom.parseString(request[0])
+ if not dom:
+ continue
+ if not dom.getTextByTagRoute("request.name"):
+ continue
+ requesttime = dom.getTextByTagRoute("request.time")
+ if not requesttime:
+ continue
+ if isInPeer():
+ time.sleep(5)
+ continue
+ socketSend.sendto("<response><servername>%s</servername><time>%s</time></response>" % (socket.gethostname(), requesttime),
+ (multiCastGroup, port))
+ request = None
+
+def main():
+ response(Globals.MULTICAST_GROUP, Globals.MULTICAST_PORT)
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/rrd_cpu.pl b/src/com.gluster.storage.management.gateway.scripts/src/rrd_cpu.pl
new file mode 100755
index 00000000..7b070812
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/rrd_cpu.pl
@@ -0,0 +1,84 @@
+#!/usr/bin/perl
+
+use RRDs;
+
+my $rrdlog = '/var/lib/rrd';
+my $graphs = '/var/lib/rrd';
+
+updatecpudata();
+#updatecpugraph('day');
+#updatecpugraph('week');
+#updatecpugraph('month');
+#updatecpugraph('year');
+
+sub updatecpugraph {
+ my $period = $_[0];
+
+ RRDs::graph ("$graphs/cpu-$period.png",
+ "--start", "-1$period", "-aPNG", "-i", "-z",
+ "--alt-y-grid", "-w 300", "-h 50", "-l 0", "-u 100", "-r",
+ "--color", "SHADEA#FFFFFF",
+ "--color", "SHADEB#FFFFFF",
+ "--color", "BACK#FFFFFF",
+ "-t cpu usage per $period",
+ "DEF:user=$rrdlog/cpu.rrd:user:AVERAGE",
+ "DEF:system=$rrdlog/cpu.rrd:system:AVERAGE",
+ "DEF:idle=$rrdlog/cpu.rrd:idle:AVERAGE",
+
+ "CDEF:total=user,system,idle,+,+",
+ "CDEF:userpct=100,user,total,/,*",
+ "CDEF:systempct=100,system,total,/,*",
+ "CDEF:idlepct=100,idle,total,/,*",
+
+ "AREA:userpct#0000FF:User cpu usage\\j",
+ "STACK:systempct#FF0000:system cpu usage\\j",
+ "STACK:idlepct#00FF00:idle cpu usage\\j");
+
+ # "GPRINT:userpct:MAX:maximal user cpu\\:%3.2lf%%",
+ # "GPRINT:userpct:AVERAGE:average user cpu\\:%3.2lf%%",
+ # "GPRINT:userpct:LAST:current user cpu\\:%3.2lf%%\\j",
+ # "GPRINT:systempct:MAX:maximal system cpu\\:%3.2lf%%",
+ # "GPRINT:systempct:AVERAGE:average system cpu\\:%3.2lf%%",
+ # "GPRINT:systempct:LAST:current system cpu\\:%3.2lf%%\\j",
+ # "GPRINT:idlepct:MAX:maximal idle cpu\\:%3.2lf%%",
+ # "GPRINT:idlepct:AVERAGE:average idle cpu\\:%3.2lf%%",
+ # "GPRINT:idlepct:LAST:current idle cpu\\:%3.2lf%%\\j");
+ $ERROR = RRDs::error;
+ print "Error in RRD::graph for cpu: $ERROR\n" if $ERROR;
+}
+
+sub updatecpudata {
+ if ( ! -e "$rrdlog/cpu.rrd") {
+ RRDs::create ("$rrdlog/cpu.rrd", "--step=300",
+ "DS:user:COUNTER:600:0:U",
+ "DS:system:COUNTER:600:0:U",
+ "DS:idle:COUNTER:600:0:U",
+
+ "RRA:AVERAGE:0.5:1:576",
+ "RRA:AVERAGE:0.5:6:672",
+ "RRA:AVERAGE:0.5:24:732",
+ "RRA:AVERAGE:0.5:144:1460");
+ $ERROR = RRDs::error;
+ print "Error in RRD::create for cpu: $ERROR\n" if $ERROR;
+ }
+
+ my ($cpu, $user, $nice, $system,$idle);
+
+ open STAT, "/proc/stat";
+ while(<STAT>) {
+ chomp;
+ /^cpu\s/ or next;
+ ($cpu, $user, $nice, $system, $idle) = split /\s+/;
+ last;
+ }
+ close STAT;
+ $user += $nice;
+
+ RRDs::update ("$rrdlog/cpu.rrd",
+ "-t", "user:system:idle",
+ "N:$user:$system:$idle");
+ $ERROR = RRDs::error;
+ print "Error in RRD::update for cpu: $ERROR\n" if $ERROR;
+
+ print "N:$user:$system:$idle\n";
+}
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/rrd_mem.pl b/src/com.gluster.storage.management.gateway.scripts/src/rrd_mem.pl
new file mode 100755
index 00000000..5c47cd81
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/rrd_mem.pl
@@ -0,0 +1,100 @@
+#!/usr/bin/perl
+
+use RRDs;
+
+my $rrdlog = '/var/lib/rrd';
+my $graphs = '/var/lib/rrd';
+
+updatememdata ();
+#updatememgraph ('day');
+#updatememgraph ('week');
+#updatememgraph ('month');
+#updatememgraph ('year');
+
+sub updatememgraph {
+ my $period = $_[0];
+
+ RRDs::graph ("$graphs/memory-$period.png",
+ "--start", "-1$period", "-aPNG", "-i", "-z",
+ "--alt-y-grid", "-w 300", "-h 50", "-l 0", "-u 100", "-r",
+ "--color", "SHADEA#FFFFFF",
+ "--color", "SHADEB#FFFFFF",
+ "--color", "BACK#FFFFFF",
+ "-t memory usage per $period",
+ "DEF:used=$rrdlog/mem.rrd:memused:AVERAGE",
+ "DEF:free=$rrdlog/mem.rrd:memfree:AVERAGE",
+ "DEF:cache=$rrdlog/mem.rrd:memcache:AVERAGE",
+ "CDEF:total=used,free,+",
+ "CDEF:used1=used,buffer,cache,-,-",
+ "CDEF:usedpct=100,used1,total,/,*",
+ "CDEF:free1=total,used1,-",
+ "CDEF:cachepct=100,cache,total,/,*",
+ "CDEF:freepct=100,free1,total,/,*",
+ "AREA:usedpct#0000FF:used memory\\j",
+ "STACK:cachepct#FFFF00:cached memory\\j",
+ "STACK:freepct#00FF00:free memory\\j");
+ $ERROR = RRDs::error;
+ print "Error in RRD::graph for mem: $ERROR\n" if $ERROR;
+
+ RRDs::graph ("$graphs/swap-$period.png",
+ "--start", "-1$period", "-aPNG", "-i", "-z",
+ "--alt-y-grid", "-w 300", "-h 50", "-l 0", "-u 100", "-r",
+ "--color", "SHADEA#FFFFFF",
+ "--color", "SHADEB#FFFFFF",
+ "--color", "BACK#FFFFFF",
+ "-t swap usage per $period",
+ "DEF:used=$rrdlog/mem.rrd:swapused:AVERAGE",
+ "DEF:free=$rrdlog/mem.rrd:swapfree:AVERAGE",
+ "CDEF:total=used,free,+",
+ "CDEF:usedpct=100,used,total,/,*",
+ "CDEF:freepct=100,free,total,/,*",
+ "AREA:usedpct#0000FF:used swap\\j",
+ "STACK:freepct#00FF00:free swap\\j");
+ $ERROR = RRDs::error;
+ print "Error in RRD::graph for swap: $ERROR\n" if $ERROR;
+}
+
+sub updatememdata {
+ my ($memused, $memfree, $memshared, $membuffers, $memcache, $swapused, $swapfree);
+ if ( ! -e "$rrdlog/mem.rrd") {
+ RRDs::create ("$rrdlog/mem.rrd", "--step=300",
+ "DS:memused:ABSOLUTE:600:0:U",
+ "DS:memfree:ABSOLUTE:600:0:U",
+ "DS:memcache:ABSOLUTE:600:0:U",
+ "DS:membuffer:ABSOLUTE:600:0:U",
+ "DS:swapused:ABSOLUTE:600:0:U",
+ "DS:swapfree:ABSOLUTE:600:0:U",
+ "RRA:AVERAGE:0.5:1:576",
+ "RRA:AVERAGE:0.5:6:672",
+ "RRA:AVERAGE:0.5:24:732",
+ "RRA:AVERAGE:0.5:144:1460");
+ $ERROR = RRDs::error;
+ print "Error in RRD::create for mem: $ERROR\n" if $ERROR;
+ }
+
+ my @memdata = `free -b -o`;
+
+ my $temp = $memdata[1];
+
+ chomp( $temp );
+ my @tempa = split (/\s+/, $temp);
+ $memused = $tempa [2];
+ $memfree = $tempa [3];
+ $memshared = $tempa [4];
+ $membuffers = $tempa [5];
+ $memcache = $tempa [6];
+
+ $temp = $memdata[2];
+ chomp( $temp );
+ @tempa = split (/\s+/, $temp);
+ $swapused = $tempa [2];
+ $swapfree = $tempa [3];
+
+
+ RRDs::update ("$rrdlog/mem.rrd",
+ "-t", "memused:memfree:memcache:membuffer:swapused:swapfree",
+ "N:$memused:$memfree:$memcache:$membuffers:$swapused:$swapfree");
+
+ $ERROR = RRDs::error;
+ print "Error in RRD::update for mem: $ERROR\n" if $ERROR;
+}
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/rrd_net.pl b/src/com.gluster.storage.management.gateway.scripts/src/rrd_net.pl
new file mode 100755
index 00000000..03f4f492
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/rrd_net.pl
@@ -0,0 +1,74 @@
+#!/usr/bin/perl
+
+use RRDs;
+
+my $rrdlog = '/var/lib/rrd';
+my $graphs = '/var/lib/rrd';
+
+updatenetdata();
+#updatenetgraph('hour');
+#updatenetgraph('day');
+#updatenetgraph('week');
+#updatenetgraph('month');
+#updatenetgraph('year');
+
+sub updatenetgraph {
+ my $period = $_[0];
+
+ foreach $rrdfile (<$rrdlog/network-*.rrd>) {
+ RRDs::graph ("$graphs/network-$device-$period.png",
+ "--start", "-1$period", "-aPNG", "-i", "-z",
+ "--alt-y-grid", "-w 800", "-h 400", "-l 0", "-u 10000000", "-r",
+ "--color", "SHADEA#FFFFFF",
+ "--color", "SHADEB#FFFFFF",
+ "--color", "BACK#FFFFFF",
+ "-t $device load per $period",
+ "DEF:received=$rrdfile:received:AVERAGE",
+ "DEF:transmitted=$rrdfile:transmitted:AVERAGE",
+
+ "LINE2:received#FF0000:received load\\j",
+ "LINE1:transmitted#0000FF:transmitted load\\j");
+
+ $ERROR = RRDs::error;
+ print "Error in RRD::graph for network $device: $ERROR\n" if $ERROR;
+ }
+}
+
+sub updatenetdata {
+ open NETDEV, "/proc/net/dev";
+ while (<NETDEV>) {
+ chomp;
+ s/^\s+//; # remove left side whitespaces
+ /:.+/ or next; # if input line contains ':' else continue
+ next if /^lo:\s/; # continue if input line starts with 'lo:'
+
+ @tokens1 = split /:/;
+ @tokens2 = split(/\s+/, $tokens1[1]);
+
+ $device = $tokens1[0];
+ $received = $tokens2[0];
+ $transmitted = $tokens2[8];
+
+ #print "$device, $received, $transmitted \n";
+
+ if ( ! -e "$rrdlog/network-$device.rrd") {
+ RRDs::create ("$rrdlog/network-$device.rrd", "--step=300",
+ "DS:received:COUNTER:600:0:U",
+ "DS:transmitted:COUNTER:600:0:U",
+
+ "RRA:AVERAGE:0.5:1:576",
+ "RRA:AVERAGE:0.5:6:672",
+ "RRA:AVERAGE:0.5:24:732",
+ "RRA:AVERAGE:0.5:144:1460");
+ $ERROR = RRDs::error;
+ print "Error in RRD::create for device $device: $ERROR\n" if $ERROR;
+ }
+
+ RRDs::update ("$rrdlog/network-$device.rrd",
+ "-t", "received:transmitted",
+ "N:$received:$transmitted");
+ $ERROR = RRDs::error;
+ print "Error in RRD::update for net: $ERROR\n" if $ERROR;
+ }
+ close NETDEV
+}
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/rrd_update_cpu_details.py b/src/com.gluster.storage.management.gateway.scripts/src/rrd_update_cpu_details.py
new file mode 100755
index 00000000..73982971
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/rrd_update_cpu_details.py
@@ -0,0 +1,90 @@
+#!/usr/bin/python
+# 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 sys
+from XmlHandler import ResponseXml
+import Utils
+
+def createMemData(file, step):
+ rs = ResponseXml()
+ command = ["rrdtool", "create", file, "--step=%s" % step,
+ "DS:user:COUNTER:600:0:U",
+ "DS:system:COUNTER:600:0:U",
+ "DS:idle:COUNTER:600:0:U",
+ "RRA:AVERAGE:0.5:1:576",
+ "RRA:AVERAGE:0.5:6:672",
+ "RRA:AVERAGE:0.5:24:732",
+ "RRA:AVERAGE:0.5:144:1460"]
+
+ rv = Utils.runCommand(command, output=True, root=True)
+ message = Utils.stripEmptyLines(rv["Stdout"])
+ if rv["Stderr"]:
+ error = Utils.stripEmptyLines(rv["Stderr"])
+ message += "Error: [%s]" % (error)
+ Utils.log("failed to create RRD file for cpu usages %s" % file)
+ rs.appendTagRoute("status.code", rv["Status"])
+ rs.appendTagRoute("status.message", message)
+ return rs.toxml()
+ return None
+
+def updateMemData(file):
+ rs = ResponseXml()
+ user = None
+ system = None
+ idle = None
+ for line in open("/proc/stat").readlines():
+ if line.startswith("cpu"):
+ cpudetails = line.split()
+ if "cpu" == cpudetails[0]:
+ user = cpudetails[1]
+ system = cpudetails[3]
+ idle = cpudetails[4]
+ break
+
+ if None == user:
+ Utils.log("failed to fetch cpu details from /proc/stat")
+ rs.appendTagRoute("status.code", "-1")
+ rs.appendTagRoute("status.message", "failed to fetch cpu details")
+ return rs.toxml()
+
+ command = ["rrdtool", "update", file, "-t", "user:system:idle",
+ "N:%s:%s:%s" % (user, system, idle)]
+ rv = Utils.runCommand(command, output=True, root=True)
+ if rv["Stderr"]:
+ error = Utils.stripEmptyLines(rv["Stderr"])
+ message = "Error: [%s]" % (error)
+ Utils.log("failed to update cpu usage into rrd file %s" % file)
+ rs.appendTagRoute("status.code", rv["Status"])
+ rs.appendTagRoute("status.message", message)
+ return rs.toxml()
+ return None
+
+
+def main():
+ cpuRrdFile = "/var/lib/rrd/cpu.rrd"
+ if not os.path.exists(cpuRrdFile):
+ status = createMemData(cpuRrdFile, 100)
+ if status:
+ print status
+ status = updateMemData(cpuRrdFile)
+ if status:
+ print status
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/rrd_update_memory_details.py b/src/com.gluster.storage.management.gateway.scripts/src/rrd_update_memory_details.py
new file mode 100755
index 00000000..fe4fcce6
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/rrd_update_memory_details.py
@@ -0,0 +1,90 @@
+#!/usr/bin/python
+# 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 sys
+from XmlHandler import ResponseXml
+import Utils
+
+def createMemData(file, step):
+ rs = ResponseXml()
+ command = ["rrdtool", "create", file, "--step=%s" % step,
+ "DS:memused:ABSOLUTE:600:0:U",
+ "DS:memfree:ABSOLUTE:600:0:U",
+ "DS:memcache:ABSOLUTE:600:0:U",
+ "DS:swapused:ABSOLUTE:600:0:U",
+ "DS:swapfree:ABSOLUTE:600:0:U",
+ "RRA:AVERAGE:0.5:1:576",
+ "RRA:AVERAGE:0.5:6:672",
+ "RRA:AVERAGE:0.5:24:732",
+ "RRA:AVERAGE:0.5:144:1460"]
+
+ rv = Utils.runCommand(command, output=True, root=True)
+ message = Utils.stripEmptyLines(rv["Stdout"])
+ if rv["Stderr"]:
+ error = Utils.stripEmptyLines(rv["Stderr"])
+ message += "Error: [%s]" % (error)
+ Utils.log("failed to create RRD file for memory usages %s" % file)
+ rs.appendTagRoute("status.code", rv["Status"])
+ rs.appendTagRoute("status.message", message)
+ return rs.toxml()
+ return None
+
+def updateMemData(file):
+ rs = ResponseXml()
+ command = ["free", "-b", "-o"]
+ rv = Utils.runCommand(command, output=True, root=True)
+ if rv["Stderr"]:
+ error = Utils.stripEmptyLines(rv["Stderr"])
+ message += "Error: [%s]" % (error)
+ Utils.log("failed to retrieve memory details")
+ rs.appendTagRoute("status.code", rv["Status"])
+ rs.appendTagRoute("status.message", message)
+ return rs.toxml()
+
+ message = rv["Stdout"].split()
+ command = ["rrdtool", "update", file, "-t", "memused:memfree:memcache:swapused:swapfree",
+ "N:%s:%s:%s:%s:%s" % (message[8], message[9], message[12], message[14], message[15])]
+ rv = Utils.runCommand(command, output=True, root=True)
+ if rv["Stderr"]:
+ error = Utils.stripEmptyLines(rv["Stderr"])
+ message += "Error: [%s]" % (error)
+ Utils.log(syslog.LOG_ERR, "failed to update memory usage into rrd file %s" % file)
+ rs.appendTagRoute("status.code", rv["Status"])
+ rs.appendTagRoute("status.message", message)
+ return rs.toxml()
+ return None
+
+
+def main():
+ #if len(sys.argv) != 2:
+ # print >> sys.stderr, "usage: %s <step>" % sys.argv[0]
+ # sys.exit(-1)
+ #step = sys.argv[1]
+
+ memRrdFile = "mem.rrd"
+ if not os.path.exists(memRrdFile):
+ status = createMemData(memRrdFile, 100)
+ if status:
+ print status
+ status = updateMemData(memRrdFile)
+ if status:
+ print status
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/setup_cifs_config.py b/src/com.gluster.storage.management.gateway.scripts/src/setup_cifs_config.py
new file mode 100755
index 00000000..2cc35acc
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/setup_cifs_config.py
@@ -0,0 +1,81 @@
+#!/usr/bin/python
+# Copyright (C) 2011 Gluster, Inc. <http://www.gluster.com>
+# This file is part of Gluster Management Gateway.
+#
+
+import os
+import sys
+import Globals
+import Utils
+
+def main():
+ try:
+ os.mkdir(Globals.GLUSTER_BASE_DIR)
+ os.mkdir(Globals.VOLUME_CONF_DIR)
+ os.mkdir(Globals.CIFS_EXPORT_DIR)
+ os.mkdir(Globals.REEXPORT_DIR)
+ except OSError, e:
+ Utils.log("failed to create directory: %s" % str(e))
+ sys.exit(1)
+ try:
+ fp = open(Globals.VOLUME_SMBCONF_FILE, "w")
+ fp.close()
+ except IOError, e:
+ Utils.log("Failed to create file %s: %s" % (Globals.VOLUME_SMBCONF_FILE, str(e)))
+ sys.exit(2)
+ try:
+ os.rename(Globals.SAMBA_CONF_FILE, "%s.orig" % Globals.SAMBA_CONF_FILE)
+ except IOError, e:
+ Utils.log("Ignoring rename %s to %s: %s" % (Globals.SAMBA_CONF_FILE, "%s.orig" % Globals.SAMBA_CONF_FILE, str(e)))
+ try:
+ fp = open(Globals.SAMBA_CONF_FILE, "w")
+ fp.write("##\n")
+ fp.write("## THIS FILE SHOULD NOT BE MODIFIED. IF YOU WANT TO MODIFY SAMBA\n")
+ fp.write("## CONFIGURATIONS, USE /etc/samba/real.smb.conf FILE\n")
+ fp.write("##\n")
+ fp.write("include = %s\n\n" % Globals.REAL_SAMBA_CONF_FILE)
+ fp.write("## CAUTION: DO NOT REMOVE BELOW LINE. REMOVAL OF THE LINE DISABLES\n")
+ fp.write("## CIFS REEXPORT OF GLUSTER VOLUMES\n")
+ fp.write("include = %s\n" % Globals.VOLUME_SMBCONF_FILE)
+ fp.close()
+ except IOError, e:
+ Utils.log("Failed to create samba configuration file %s: %s" % (Globals.SAMBA_CONF_FILE, str(e)))
+ sys.exit(3)
+ try:
+ fp = open(Globals.REAL_SAMBA_CONF_FILE, "w")
+ fp.write("[global]\n")
+ fp.write("## CAUTION: DO NOT REMOVE BELOW INCLUDE LINE. REMOVAL OF THE LINE\n")
+ fp.write("## DISABLES SERVER/CIFS HIGH AVAILABILITY\n")
+ #fp.write("include = %s\n" % Globals.CTDB_SAMBA_CONF_FILE)
+ fp.write("##\n")
+ fp.write("socket options = TCP_NODELAY IPTOS_LOWDELAY SO_SNDBUF=131072 SO_RCVBUF=131072\n")
+ fp.write("read raw = yes\n")
+ fp.write("server string = %h\n")
+ fp.write("write raw = yes\n")
+ fp.write("oplocks = yes\n")
+ fp.write("max xmit = 131072\n")
+ fp.write("dead time = 15\n")
+ fp.write("getwd cache = yes\n")
+ fp.write("#read size = 131072\n")
+ fp.write("use sendfile=yes\n")
+ fp.write("block size = 131072\n")
+ fp.write("printcap name = /etc/printcap\n")
+ fp.write("load printers = no\n")
+ fp.close()
+ except IOError, e:
+ Utils.log("Failed to create samba configuration file %s: %s" % (Globals.REAL_SAMBA_CONF_FILE, str(e)))
+ sys.exit(4)
+
+
+ if Utils.runCommand("setsebool -P samba_share_fusefs on") != 0:
+ Utils.log("failed to set SELinux samba_share_fusefs")
+ sys.exit(5)
+
+ if Utils.runCommand("service smb restart") != 0:
+ Utils.log("failed to restart smb service")
+ sys.exit(6)
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/start_volume_cifs.py b/src/com.gluster.storage.management.gateway.scripts/src/start_volume_cifs.py
new file mode 100755
index 00000000..239216c3
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/start_volume_cifs.py
@@ -0,0 +1,41 @@
+#!/usr/bin/python
+# Copyright (C) 2011 Gluster, Inc. <http://www.gluster.com>
+# This file is part of Gluster Management Gateway.
+#
+
+import os
+import sys
+import Globals
+import Utils
+import VolumeUtils
+
+def main():
+ if len(sys.argv) != 2:
+ sys.stderr.write("usage: %s VOLUME_NAME\n" % os.path.basename(sys.argv[0]))
+ sys.exit(-1)
+
+ volumeName = sys.argv[1]
+
+ volumeMountDirName = "%s/%s" % (Globals.REEXPORT_DIR, volumeName)
+ cifsDirName = "%s/%s" % (Globals.CIFS_EXPORT_DIR, volumeName)
+
+ if Utils.runCommand("mount -t glusterfs 127.0.0.1:%s %s" % (volumeName, volumeMountDirName)) != 0:
+ Utils.log("Failed to mount volume %s" % (volumeName))
+ sys.exit(1)
+ if Utils.runCommand("ln -fTs %s %s" % (volumeMountDirName, cifsDirName)) != 0:
+ Utils.log("Failed to create reexport link %s" % cifsDirName)
+ sys.exit(2)
+ if Utils.runCommand("chcon -t samba_share_t %s -h" % cifsDirName) != 0:
+ Utils.log("Failed to change security context for the link %s" % cifsDirName)
+ sys.exit(2)
+ if not VolumeUtils.includeVolume(volumeName):
+ Utils.log("Failed to include volume for CIFS reexport")
+ sys.exit(3)
+ if Utils.runCommand("service smb reload") != 0:
+ Utils.log("Failed to reload smb service")
+ sys.exit(4)
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.gateway.scripts/src/stop_volume_cifs.py b/src/com.gluster.storage.management.gateway.scripts/src/stop_volume_cifs.py
new file mode 100755
index 00000000..99ac4750
--- /dev/null
+++ b/src/com.gluster.storage.management.gateway.scripts/src/stop_volume_cifs.py
@@ -0,0 +1,38 @@
+#!/usr/bin/python
+# Copyright (C) 2011 Gluster, Inc. <http://www.gluster.com>
+# This file is part of Gluster Management Gateway.
+#
+
+import os
+import sys
+import Globals
+import Utils
+import VolumeUtils
+
+def main():
+ if len(sys.argv) != 2:
+ sys.stderr.write("usage: %s VOLUME_NAME\n" % os.path.basename(sys.argv[0]))
+ sys.exit(-1)
+
+ volumeName = sys.argv[1]
+
+ volumeMountDirName = "%s/%s" % (Globals.REEXPORT_DIR, volumeName)
+ cifsDirName = "%s/%s" % (Globals.CIFS_EXPORT_DIR, volumeName)
+
+ if not Utils.removeFile(cifsDirName):
+ Utils.log("Failed to remove reexport link %s" % cifsDirName)
+ sys.exit(1)
+ if not VolumeUtils.excludeVolume(volumeName):
+ Utils.log("Failed to exclude volume for CIFS reexport")
+ sys.exit(2)
+ if Utils.runCommand("service smb reload") != 0:
+ Utils.log("Failed to reload smb service")
+ sys.exit(3)
+ if Utils.runCommand("umount %s" % (volumeMountDirName)) != 0:
+ Utils.log("Failed to unmount volume %s" % (volumeName))
+ sys.exit(4)
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()