diff options
| author | Shireesh Anjal <shireesh@gluster.com> | 2011-03-25 15:43:32 +0530 |
|---|---|---|
| committer | Shireesh Anjal <shireesh@gluster.com> | 2011-03-25 15:43:32 +0530 |
| commit | e40556bdf8fd27e35878a8c1942573da46204b7e (patch) | |
| tree | b4cf1ec243bf13aee4269981d8f8aeeaa57f1c15 /com.gluster.storage.management.server.scripts/src/common | |
| parent | 9e2122cf8ae1273bb8cdcbcc0f8fb2176f14a428 (diff) | |
Server agent and transport agent
Diffstat (limited to 'com.gluster.storage.management.server.scripts/src/common')
7 files changed, 1795 insertions, 0 deletions
diff --git a/com.gluster.storage.management.server.scripts/src/common/Commands.py b/com.gluster.storage.management.server.scripts/src/common/Commands.py new file mode 100644 index 00000000..c728b565 --- /dev/null +++ b/com.gluster.storage.management.server.scripts/src/common/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/com.gluster.storage.management.server.scripts/src/common/Common.py b/com.gluster.storage.management.server.scripts/src/common/Common.py new file mode 100644 index 00000000..60f200fe --- /dev/null +++ b/com.gluster.storage.management.server.scripts/src/common/Common.py @@ -0,0 +1,34 @@ +# 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
+
+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
diff --git a/com.gluster.storage.management.server.scripts/src/common/Globals.py b/com.gluster.storage.management.server.scripts/src/common/Globals.py new file mode 100644 index 00000000..365d4af7 --- /dev/null +++ b/com.gluster.storage.management.server.scripts/src/common/Globals.py @@ -0,0 +1,119 @@ +# 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 = "transport" +INSTALLER_SERVER_NAME = "$installer$" + +GLUSTER_BASE_DIR = "/GLUSTER" +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/platform" + +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" +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 = {} +## diff --git a/com.gluster.storage.management.server.scripts/src/common/NetworkUtils.py b/com.gluster.storage.management.server.scripts/src/common/NetworkUtils.py new file mode 100644 index 00000000..1ce1b132 --- /dev/null +++ b/com.gluster.storage.management.server.scripts/src/common/NetworkUtils.py @@ -0,0 +1,422 @@ +# 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 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 device in getHardwareList(): + netDevice = {} + netDevice["device"] = None + netDevice["description"] = None + netDevice["hwaddr"] = None + netDevice["type"] = None + netDevice["onboot"] = None + netDevice["bootproto"] = None + netDevice["ipaddr"] = None + netDevice["netmask"] = 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["description"] = device.Description + netDevice["type"] = device.Type + netDevice["link"] = getLinkStatus(device.Name) + netDevice["mode"] = getBondMode(device.Name, root + Globals.MODPROBE_CONF_FILE) + try: + netDevice["hwaddr"] = open("/sys/class/net/%s/address" % device.Name).read().strip() + except IOError: + pass + netDeviceList.append(netDevice) + + conf = readIfcfgConfFile(device.Name, root) + if not conf: + continue + try: + netDevice["onboot"] = conf["onboot"] + except KeyError: + pass + try: + netDevice["bootproto"] = conf["bootproto"] + except KeyError: + pass + try: + netDevice["ipaddr"] = conf["ipaddr"] + except KeyError: + pass + try: + netDevice["netmask"] = conf["netmask"] + except KeyError: + pass + try: + netDevice["gateway"] = conf["gateway"] + except KeyError: + pass + 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/com.gluster.storage.management.server.scripts/src/common/Protocol.py b/com.gluster.storage.management.server.scripts/src/common/Protocol.py new file mode 100644 index 00000000..ff073593 --- /dev/null +++ b/com.gluster.storage.management.server.scripts/src/common/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/com.gluster.storage.management.server.scripts/src/common/Utils.py b/com.gluster.storage.management.server.scripts/src/common/Utils.py new file mode 100644 index 00000000..c605eecd --- /dev/null +++ b/com.gluster.storage.management.server.scripts/src/common/Utils.py @@ -0,0 +1,704 @@ +# 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 log(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(): + return tempfile.mkstemp(prefix="GSP_")[1] + + +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) + 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 getLoadavg(): + """-> 5-tuple containing the following numbers in order: + - 1-minute load average (float) + - 5-minute load average (float) + - 15-minute load average (float) + - Number of threads/processes currently executing (<= number of + CPUs) (int) + - Number of threads/processes that exist on the system (int) + - The PID of the most recently-created process on the system (int) + """ + loadavgstr = open('/proc/loadavg', 'r').readline().strip() + data = loadavgstr.split() + avg1, avg5, avg15 = map(float, data[:3]) + threads_and_procs_running, threads_and_procs_total = map(int, + data[3].split('/')) + most_recent_pid = int(data[4]) + ncpus = 1 + final_avg = "" + if hasattr(os, "sysconf"): + if os.sysconf_names.has_key("SC_NPROCESSORS_ONLN"): + # Linux + ncpus = os.sysconf("SC_NPROCESSORS_ONLN") + if isinstance(ncpus, int) and ncpus > 0: + final_avg = "%.2f" % (1.0 * avg1 / ncpus) + + # Future return everything when needed + # Commenting this for the time being + # avg5, avg15, threads_and_procs_running, threads_and_procs_total, most_recent_pid + return final_avg + + +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: + Utils.log("Failed to remove file %s: %s" % (fileName, e)) + return False + + +def isLiveMode(): + return os.path.exists(Globals.LIVE_MODE_FILE) diff --git a/com.gluster.storage.management.server.scripts/src/common/system-config-network-tui-1.3.99.18-1.el5.noarch.rpm b/com.gluster.storage.management.server.scripts/src/common/system-config-network-tui-1.3.99.18-1.el5.noarch.rpm Binary files differnew file mode 100644 index 00000000..4b07c4e4 --- /dev/null +++ b/com.gluster.storage.management.server.scripts/src/common/system-config-network-tui-1.3.99.18-1.el5.noarch.rpm |
