diff --git a/fence/agents/ibmblade/fence_ibmblade.py b/fence/agents/ibmblade/fence_ibmblade.py index 16a18df6..f9ee9552 100644 --- a/fence/agents/ibmblade/fence_ibmblade.py +++ b/fence/agents/ibmblade/fence_ibmblade.py @@ -1,82 +1,80 @@ #!/usr/bin/python import sys sys.path.append("@FENCEAGENTSLIBDIR@") from fencing import * from fencing_snmp import * #BEGIN_VERSION_GENERATION RELEASE_VERSION="IBM Blade SNMP fence agent" REDHAT_COPYRIGHT="" BUILD_DATE="" #END_VERSION_GENERATION ### CONSTANTS ### # From fence_ibmblade.pl STATUSES_OID = ".1.3.6.1.4.1.2.3.51.2.22.1.5.1.1.4" # remoteControlBladePowerState CONTROL_OID = ".1.3.6.1.4.1.2.3.51.2.22.1.6.1.1.7" # powerOnOffBlade # Status constants returned as value from SNMP STATUS_DOWN = 0 STATUS_UP = 1 # Status constants to set as value to SNMP STATUS_SET_OFF = 0 STATUS_SET_ON = 1 ### FUNCTIONS ### def get_power_status(conn, options): (oid,status) = conn.get("%s.%s"%(STATUSES_OID, options["-n"])) return (status==str(STATUS_UP) and "on" or "off") def set_power_status(conn, options): conn.set("%s.%s"%(CONTROL_OID, options["-n"]), (options["-o"]=="on" and STATUS_SET_ON or STATUS_SET_OFF)) def get_outlets_status(conn, options): result = {} res_blades = conn.walk(STATUSES_OID, 30) for x in res_blades: port_num = x[0].split('.')[-1] port_alias = "" port_status = (x[1]==str(STATUS_UP) and "on" or "off") result[port_num] = (port_alias, port_status) return result # Main agent method def main(): - global port_oid - device_opt = [ "ipaddr", "login", "passwd", "passwd_script", "test", "port", "separator", "no_login", "no_password", "snmp_version", "community", "snmp_auth_prot", "snmp_sec_level", "snmp_priv_prot", "snmp_priv_passwd", "snmp_priv_passwd_script", "udpport", "inet4_only", "inet6_only" ] atexit.register(atexit_handler) snmp_define_defaults() all_opt["snmp_version"]["default"] = "1" options = check_input(device_opt, process_input(device_opt)) docs = { } docs["shortdesc"] = "Fence agent for IBM BladeCenter over SNMP" docs["longdesc"] = "fence_ibmblade is an I/O Fencing agent \ which can be used with IBM BladeCenter chassis. It issues SNMP Set \ request to BladeCenter chassis, rebooting, powering up or down \ the specified Blade Server." docs["vendorurl"] = "http://www.ibm.com" show_docs(options, docs) # Operate the fencing device result = fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status) sys.exit(result) if __name__ == "__main__": main() diff --git a/fence/agents/lib/fencing_snmp.py.py b/fence/agents/lib/fencing_snmp.py.py index f478c53b..e4c46361 100644 --- a/fence/agents/lib/fencing_snmp.py.py +++ b/fence/agents/lib/fencing_snmp.py.py @@ -1,131 +1,131 @@ #!/usr/bin/python # For example of use please see fence_cisco_mds import re, pexpect from fencing import * ## do not add code here. #BEGIN_VERSION_GENERATION RELEASE_VERSION = "" REDHAT_COPYRIGHT = "" BUILD_DATE = "" #END_VERSION_GENERATION # Fix for RHBZ#527844 def snmp_define_defaults (): all_opt["udpport"]["default"] = "161" all_opt["ipport"]["default"] = "161" class FencingSnmp: def __init__(self, options): self.options = options # Log message if user set verbose option def log_command(self, message): if self.options["log"] >= LOG_MODE_VERBOSE: self.options["debug_fh"].write(message+"\n") - def quote_for_run(self, str): - return ''.join(map(lambda x:x==r"'" and "'\\''" or x, str)) + def quote_for_run(self, string): + return ''.join(map(lambda x:x==r"'" and "'\\''" or x, string)) def complete_missed_params(self): mapping = [ [['P','p','!E'],'self.options["-E"]="authPriv"'], [['!d','c','!l','!P','!p'],'self.options["-d"]="2c"'] ] for val in mapping: e = val[0] res = True for item in e: if ((item[0]=='!') and (self.options.has_key("-"+item[1]))): res = False break if ((item[0]!='!') and (not self.options.has_key("-"+item[0]))): res = False break if res: exec(val[1]) def prepare_cmd(self, command): cmd = "@SNMPBIN@/%s -m '' -Oeqn "% (command) self.complete_missed_params() #mapping from our option to snmpcmd option mapping = (('d', 'v'),('c', 'c')) for item in mapping: if (self.options.has_key("-"+item[0])): cmd += " -%s '%s'"% (item[1], self.quote_for_run(self.options["-" + item[0]])) # Some options make sense only for v3 (and for v1/2c can cause "problems") if (self.options.has_key("-d")) and (self.options["-d"] == "3"): # Mapping from our options to snmpcmd options for v3 mapping_v3 = (('b','a'),('E','l'),('B','x'),('P','X'),('p','A'),('l','u')) for item in mapping_v3: if (self.options.has_key("-"+item[0])): cmd += " -%s '%s'"% (item[1], self.quote_for_run(self.options["-" + item[0]])) force_ipvx = "" if (self.options.has_key("-6")): force_ipvx = "udp6:" if (self.options.has_key("-4")): force_ipvx = "udp:" cmd += " '%s%s%s'"% (force_ipvx, self.quote_for_run(self.options["-a"]), self.options.has_key("-u") and self.quote_for_run(":" + str (self.options["-u"])) or "") return cmd def run_command(self, command, additional_timemout=0): try: self.log_command(command) (res_output, res_code) = pexpect.run(command, int(self.options["-Y"]) + int(self.options["-y"]) + additional_timemout, True) if (res_code==None): fail(EC_TIMED_OUT) self.log_command(res_output) if (res_code!=0) or (re.search("^Error ", res_output, re.MULTILINE) != None): fail_usage("Returned %d: %s"% (res_code, res_output)) except pexpect.ExceptionPexpect: fail_usage("Cannot run command %s"%(command)) return res_output def get(self, oid, additional_timemout=0): cmd = "%s '%s'"% (self.prepare_cmd("snmpget"), self.quote_for_run(oid)) output = self.run_command(cmd, additional_timemout).splitlines() return output[len(output)-1].split(None, 1) def set(self, oid, value, additional_timemout=0): mapping = ((int, 'i'), (str, 's')) - type = '' + type_of_value = '' for item in mapping: if (isinstance(value, item[0])): - type = item[1] + type_of_value = item[1] break - cmd = "%s '%s' %s '%s'"% (self.prepare_cmd("snmpset"), self.quote_for_run(oid), type, self.quote_for_run(str(value))) + cmd = "%s '%s' %s '%s'"% (self.prepare_cmd("snmpset"), self.quote_for_run(oid), type_of_value, self.quote_for_run(str(value))) self.run_command(cmd, additional_timemout) def walk(self, oid, additional_timemout=0): cmd = "%s '%s'"% (self.prepare_cmd("snmpwalk"), self.quote_for_run(oid)) output = self.run_command(cmd, additional_timemout).splitlines() return map(lambda x:x.split(None, 1), filter(lambda y:len(y)>0 and y[0]=='.', output)) diff --git a/fence/agents/vmware_soap/fence_vmware_soap.py b/fence/agents/vmware_soap/fence_vmware_soap.py index 41da8c02..2710603f 100644 --- a/fence/agents/vmware_soap/fence_vmware_soap.py +++ b/fence/agents/vmware_soap/fence_vmware_soap.py @@ -1,201 +1,200 @@ #!/usr/bin/python import sys, exceptions sys.path.append("@FENCEAGENTSLIBDIR@") from suds.client import Client from suds.sudsobject import Property from fencing import * #BEGIN_VERSION_GENERATION RELEASE_VERSION="New VMWare Agent - test release on steroids" REDHAT_COPYRIGHT="" BUILD_DATE="April, 2011" #END_VERSION_GENERATION def soap_login(options): if options.has_key("-z"): url = "https://" else: url = "http://" url += options["-a"] + ":" + str(options["-u"]) + "/sdk" conn = Client(url + "/vimService.wsdl") conn.set_options(location = url) mo_ServiceInstance = Property('ServiceInstance') mo_ServiceInstance._type = 'ServiceInstance' ServiceContent = conn.service.RetrieveServiceContent(mo_ServiceInstance) mo_SessionManager = Property(ServiceContent.sessionManager.value) mo_SessionManager._type = 'SessionManager' try: SessionManager = conn.service.Login(mo_SessionManager, options["-l"], options["-p"]) except Exception, ex: fail(EC_LOGIN_DENIED) options["ServiceContent"] = ServiceContent options["mo_SessionManager"] = mo_SessionManager return conn def process_results(results, machines, uuid, mappingToUUID): for m in results.objects: info = {} for i in m.propSet: info[i.name] = i.val # Prevent error KeyError: 'config.uuid' when reaching systems which P2V failed, # since these systems don't have a valid UUID if info.has_key("config.uuid"): machines[info["name"]] = (info["config.uuid"], info["summary.runtime.powerState"]) uuid[info["config.uuid"]] = info["summary.runtime.powerState"] mappingToUUID[m.obj.value] = info["config.uuid"] return (machines, uuid, mappingToUUID) def get_power_status(conn, options): mo_ViewManager = Property(options["ServiceContent"].viewManager.value) mo_ViewManager._type = "ViewManager" mo_RootFolder = Property(options["ServiceContent"].rootFolder.value) mo_RootFolder._type = "Folder" mo_PropertyCollector = Property(options["ServiceContent"].propertyCollector.value) mo_PropertyCollector._type = 'PropertyCollector' ContainerView = conn.service.CreateContainerView(mo_ViewManager, recursive = 1, container = mo_RootFolder, type = ['VirtualMachine']) mo_ContainerView = Property(ContainerView.value) mo_ContainerView._type = "ContainerView" FolderTraversalSpec = conn.factory.create('ns0:TraversalSpec') FolderTraversalSpec.name = "traverseEntities" FolderTraversalSpec.path = "view" FolderTraversalSpec.skip = False FolderTraversalSpec.type = "ContainerView" objSpec = conn.factory.create('ns0:ObjectSpec') objSpec.obj = mo_ContainerView objSpec.selectSet = [ FolderTraversalSpec ] objSpec.skip = True propSpec = conn.factory.create('ns0:PropertySpec') propSpec.all = False propSpec.pathSet = ["name", "summary.runtime.powerState", "config.uuid"] propSpec.type = "VirtualMachine" propFilterSpec = conn.factory.create('ns0:PropertyFilterSpec') propFilterSpec.propSet = [ propSpec ] propFilterSpec.objectSet = [ objSpec ] try: raw_machines = conn.service.RetrievePropertiesEx(mo_PropertyCollector, propFilterSpec) except Exception, ex: fail(EC_STATUS) (machines, uuid, mappingToUUID) = process_results(raw_machines, {}, {}, {}) # Probably need to loop over the ContinueRetreive if there are more results after 1 iteration. while (hasattr(raw_machines, 'token') == True): try: raw_machines = conn.service.ContinueRetrievePropertiesEx(mo_PropertyCollector, raw_machines.token) except Exception, ex: fail(EC_STATUS) (more_machines, more_uuid, more_mappingToUUID) = process_results(raw_machines, {}, {}, {}) machines.update(more_machines) uuid.update(more_uuid) mappingToUUID.update(more_mappingToUUID) # Do not run unnecessary SOAP requests if options.has_key("-U") and options["-U"] in uuid: break if ["list", "monitor"].count(options["-o"]) == 1: return machines else: if options.has_key("-U") == False: if options["-n"].startswith('/'): ## Transform InventoryPath to UUID mo_SearchIndex = Property(options["ServiceContent"].searchIndex.value) mo_SearchIndex._type = "SearchIndex" vm = conn.service.FindByInventoryPath(mo_SearchIndex, options["-n"]) try: options["-U"] = mappingToUUID[vm.value] except KeyError, ex: fail(EC_STATUS) except AttributeError, ex: fail(EC_STATUS) else: ## Name of virtual machine instead of path ## warning: if you have same names of machines this won't work correctly try: (options["-U"], _) = machines[options["-n"]] except KeyError, ex: fail(EC_STATUS) except AttributeError, ex: fail(EC_STATUS) try: if uuid[options["-U"]] == "poweredOn": return "on" else: return "off" - return status except KeyError, ex: fail(EC_STATUS) def set_power_status(conn, options): mo_SearchIndex = Property(options["ServiceContent"].searchIndex.value) mo_SearchIndex._type = "SearchIndex" vm = conn.service.FindByUuid(mo_SearchIndex, vmSearch = 1, uuid = options["-U"]) mo_machine = Property(vm.value) mo_machine._type = "VirtualMachine" if options["-o"] == "on": conn.service.PowerOnVM_Task(mo_machine) else: conn.service.PowerOffVM_Task(mo_machine) def main(): device_opt = [ "ipaddr", "login", "passwd", "passwd_script", "ssl", "port", "uuid", "separator", "ipport" ] atexit.register(atexit_handler) options = check_input(device_opt, process_input(device_opt)) ## ## Fence agent specific defaults ##### docs = { } docs["shortdesc"] = "Fence agent for VMWare over SOAP API" docs["longdesc"] = "fence_vmware_soap is an I/O Fencing agent \ which can be used with the virtual machines managed by VMWare products \ that have SOAP API v4.1+. \ \n.P\n\ Name of virtual machine (-n / port) has to be used in inventory path \ format (e.g. /datacenter/vm/Discovered virtual machine/myMachine). \ In the cases when name of yours VM is unique you can use it instead. \ Alternatively you can always use UUID (-U / uuid) to access virtual machine." docs["vendorurl"] = "http://www.vmware.com" show_docs(options, docs) ## ## Operate the fencing device #### conn = soap_login(options) result = fence_action(conn, options, set_power_status, get_power_status, get_power_status) ## ## Logout from system ##### try: conn.service.Logout(options["mo_SessionManager"]) except Exception, ex: pass sys.exit(result) if __name__ == "__main__": main() diff --git a/fence/agents/wti/fence_wti.py b/fence/agents/wti/fence_wti.py index 555fb98e..1f353bee 100644 --- a/fence/agents/wti/fence_wti.py +++ b/fence/agents/wti/fence_wti.py @@ -1,169 +1,174 @@ #!/usr/bin/python ##### ## ## The Following Agent Has Been Tested On: ## ## Version Firmware ## +-----------------+---------------------------+ ## WTI RSM-8R4 ?? unable to find out ?? ## WTI MPC-??? ?? unable to find out ?? ## WTI IPS-800-CE v1.40h (no username) ('list' tested) ##### import sys, re, pexpect, exceptions sys.path.append("@FENCEAGENTSLIBDIR@") from fencing import * #BEGIN_VERSION_GENERATION RELEASE_VERSION="New WTI Agent - test release on steroids" REDHAT_COPYRIGHT="" BUILD_DATE="March, 2008" #END_VERSION_GENERATION def get_power_status(conn, options): listing = "" try: conn.send("/S"+"\r\n") if isinstance(options["-c"], list): re_all = list(options["-c"]) else: re_all = [options["-c"]] re_next = re.compile("Enter: ", re.IGNORECASE) re_all.append(re_next) result = conn.log_expect(options, re_all, int(options["-Y"])) listing = conn.before if result == (len(re_all) - 1): conn.send("\r\n") conn.log_expect(options, options["-c"], int(options["-Y"])) listing += conn.before except pexpect.EOF: fail(EC_CONNECTION_LOST) except pexpect.TIMEOUT: fail(EC_TIMED_OUT) plug_section = 0 + plug_index = -1 + name_index = -1 + status_index = -1 + plug_header = list() outlets = {} + for line in listing.splitlines(): if (plug_section == 2) and line.find("|") >= 0 and line.startswith("PLUG") == False: plug_line = [x.strip().lower() for x in line.split("|")] if len(plug_line) < len(plug_header): plug_section = -1 pass if ["list", "monitor"].count(options["-o"]) == 0 and options["-n"].lower() == plug_line[plug_index]: return plug_line[status_index] else: ## We already believe that first column contains plug number if len(plug_line[0]) != 0: outlets[plug_line[0]] = (plug_line[name_index], plug_line[status_index]) elif (plug_section == 1): plug_section = 2 elif (line.upper().startswith("PLUG")): plug_section = 1 plug_header = [x.strip().lower() for x in line.split("|")] plug_index = plug_header.index("plug") name_index = plug_header.index("name") status_index = plug_header.index("status") if ["list", "monitor"].count(options["-o"]) == 1: return outlets else: return "PROBLEM" def set_power_status(conn, options): action = { 'on' : "/on", 'off': "/off" }[options["-o"]] try: conn.send(action + " " + options["-n"] + ",y\r\n") conn.log_expect(options, options["-c"], int(options["-g"])) except pexpect.EOF: fail(EC_CONNECTION_LOST) except pexpect.TIMEOUT: fail(EC_TIMED_OUT) def main(): device_opt = [ "ipaddr", "login", "passwd", "passwd_script", "cmd_prompt", "secure", "identity_file", "port", "no_login", "no_password", "test", "separator", "inet4_only", "inet6_only", "ipport" ] atexit.register(atexit_handler) all_opt["cmd_prompt"]["default"] = [ "RSM>", "MPC>", "IPS>", "TPS>", "NBB>", "NPS>", "VMR>" ] options = check_input(device_opt, process_input(device_opt)) docs = { } docs["shortdesc"] = "Fence agent for WTI" docs["longdesc"] = "fence_wti is an I/O Fencing agent \ which can be used with the WTI Network Power Switch (NPS). It logs \ into an NPS via telnet or ssh and boots a specified plug. \ Lengthy telnet connections to the NPS should be avoided while a GFS cluster \ is running because the connection will block any necessary fencing actions." docs["vendorurl"] = "http://www.wti.com" show_docs(options, docs) ## ## Operate the fencing device ## ## @note: if it possible that this device does not need either login, password or both of them ##### if 0 == options.has_key("-x"): try: try: conn = fspawn(options, TELNET_PATH) conn.send("set binary\n") conn.send("open %s -%s\n"%(options["-a"], options["-u"])) except pexpect.ExceptionPexpect, ex: sys.stderr.write(str(ex) + "\n") sys.stderr.write("Due to limitations, binary dependencies on fence agents " "are not in the spec file and must be installed separately." + "\n") sys.exit(EC_GENERIC_ERROR) re_login = re.compile("(login: )|(Login Name: )|(username: )|(User Name :)", re.IGNORECASE) re_prompt = re.compile("|".join(map (lambda x: "(" + x + ")", options["-c"])), re.IGNORECASE) result = conn.log_expect(options, [ re_login, "Password: ", re_prompt ], int(options["-Y"])) if result == 0: if options.has_key("-l"): conn.send(options["-l"]+"\r\n") result = conn.log_expect(options, [ re_login, "Password: ", re_prompt ], int(options["-Y"])) else: fail_usage("Failed: You have to set login name") if result == 1: if options.has_key("-p"): conn.send(options["-p"]+"\r\n") conn.log_expect(options, options["-c"], int(options["-Y"])) else: fail_usage("Failed: You have to enter password or password script") except pexpect.EOF: fail(EC_LOGIN_DENIED) except pexpect.TIMEOUT: fail(EC_LOGIN_DENIED) else: conn = fence_login(options) result = fence_action(conn, options, set_power_status, get_power_status, get_power_status) ## ## Logout from system ###### try: conn.send("/X"+"\r\n") conn.close() except exceptions.OSError: pass except pexpect.ExceptionPexpect: pass sys.exit(result) if __name__ == "__main__": main() diff --git a/fence/agents/xenapi/fence_xenapi.py b/fence/agents/xenapi/fence_xenapi.py index f583ea51..599f7a5e 100644 --- a/fence/agents/xenapi/fence_xenapi.py +++ b/fence/agents/xenapi/fence_xenapi.py @@ -1,232 +1,228 @@ #!/usr/bin/python # ############################################################################# # Copyright 2011 Matthew Clark # This file is part of fence-xenserver # # fence-xenserver 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 2 of the License, or # (at your option) any later version. # # fence-xenserver 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 . # Please let me know if you are using this script so that I can work out # whether I should continue support for it. mattjclark0407 at hotmail dot com ############################################################################# ############################################################################# # It's only just begun... # Current status: completely usable. This script is now working well and, # has a lot of functionality as a result of the fencing.py library and the # XenAPI libary. ############################################################################# # Please let me know if you are using this script so that I can work out # whether I should continue support for it. mattjclark0407 at hotmail dot com import sys sys.path.append("@FENCEAGENTSLIBDIR@") from fencing import * import XenAPI #BEGIN_VERSION_GENERATION RELEASE_VERSION="" REDHAT_COPYRIGHT="" BUILD_DATE="" #END_VERSION_GENERATION EC_BAD_SESSION = 1 # Find the status of the port given in the -U flag of options. def get_power_fn(session, options): if options.has_key("-v"): verbose = True else: verbose = False try: # Get a reference to the vm specified in the UUID or vm_name/port parameter vm = return_vm_reference(session, options) # Query the VM for its' associated parameters record = session.xenapi.VM.get_record(vm) # Check that we are not trying to manipulate a template or a control # domain as they show up as VM's with specific properties. if not(record["is_a_template"]) and not(record["is_control_domain"]): status = record["power_state"] if verbose: print "UUID:", record["uuid"], "NAME:", record["name_label"], "POWER STATUS:", record["power_state"] # Note that the VM can be in the following states (from the XenAPI document) # Halted: VM is offline and not using any resources. # Paused: All resources have been allocated but the VM itself is paused and its vCPUs are not running # Running: Running # Paused: VM state has been saved to disk and it is nolonger running. Note that disks remain in-Use while # We want to make sure that we only return the status "off" if the machine is actually halted as the status # is checked before a fencing action. Only when the machine is Halted is it not consuming resources which # may include whatever you are trying to protect with this fencing action. return (status=="Halted" and "off" or "on") except Exception, exn: print str(exn) return "Error" # Set the state of the port given in the -U flag of options. def set_power_fn(session, options): action = options["-o"].lower() - if options.has_key("-v"): - verbose = True - else: - verbose = False try: # Get a reference to the vm specified in the UUID or vm_name/port parameter vm = return_vm_reference(session, options) # Query the VM for its' associated parameters record = session.xenapi.VM.get_record(vm) # Check that we are not trying to manipulate a template or a control # domain as they show up as VM's with specific properties. if not(record["is_a_template"]) and not(record["is_control_domain"]): if( action == "on" ): # Start the VM session.xenapi.VM.start(vm, False, True) elif( action == "off" ): # Force shutdown the VM session.xenapi.VM.hard_shutdown(vm) elif( action == "reboot" ): # Force reboot the VM session.xenapi.VM.hard_reboot(vm) except Exception, exn: print str(exn) # Function to populate an array of virtual machines and their status def get_outlet_list(session, options): result = {} if options.has_key("-v"): verbose = True else: verbose = False try: # Return an array of all the VM's on the host vms = session.xenapi.VM.get_all() for vm in vms: # Query the VM for its' associated parameters record = session.xenapi.VM.get_record(vm) # Check that we are not trying to manipulate a template or a control # domain as they show up as VM's with specific properties. if not(record["is_a_template"]) and not(record["is_control_domain"]): name = record["name_label"] uuid = record["uuid"] status = record["power_state"] result[uuid] = (name, status) if verbose: print "UUID:", record["uuid"], "NAME:", name, "POWER STATUS:", record["power_state"] except Exception, exn: print str(exn) return result # Function to initiate the XenServer session via the XenAPI library. def connect_and_login(options): url = options["-s"] username = options["-l"] password = options["-p"] try: # Create the XML RPC session to the specified URL. session = XenAPI.Session(url) # Login using the supplied credentials. session.xenapi.login_with_password(username, password) except Exception, exn: print str(exn) # http://sources.redhat.com/cluster/wiki/FenceAgentAPI says that for no connectivity # the exit value should be 1. It doesn't say anything about failed logins, so # until I hear otherwise it is best to keep this exit the same to make sure that # anything calling this script (that uses the same information in the web page # above) knows that this is an error condition, not a msg signifying a down port. sys.exit(EC_BAD_SESSION) return session # return a reference to the VM by either using the UUID or the vm_name/port. If the UUID is set then # this is tried first as this is the only properly unique identifier. # Exceptions are not handled in this function, code that calls this must be ready to handle them. def return_vm_reference(session, options): if options.has_key("-v"): verbose = True else: verbose = False # Case where the UUID has been specified if options.has_key("-U"): uuid = options["-U"].lower() # When using the -n parameter for name, we get an error message (in verbose # mode) that tells us that we didn't find a VM. To immitate that here we # need to catch and re-raise the exception produced by get_by_uuid. try: return session.xenapi.VM.get_by_uuid(uuid) except Exception, exn: if verbose: print "No VM's found with a UUID of \"%s\"" % uuid raise # Case where the vm_name/port has been specified if options.has_key("-n"): vm_name = options["-n"] vm_arr = session.xenapi.VM.get_by_name_label(vm_name) # Need to make sure that we only have one result as the vm_name may # not be unique. Average case, so do it first. if len(vm_arr) == 1: return vm_arr[0] else: if len(vm_arr) == 0: if verbose: print "No VM's found with a name of \"%s\"" % vm_name # NAME_INVALID used as the XenAPI throws a UUID_INVALID if it can't find # a VM with the specified UUID. This should make the output look fairly # consistent. raise Exception("NAME_INVALID") else: if verbose: print "Multiple VM's have the name \"%s\", use UUID instead" % vm_name raise Exception("MULTIPLE_VMS_FOUND") # We should never get to this case as the input processing checks that either the UUID or # the name parameter is set. Regardless of whether or not a VM is found the above if # statements will return to the calling function (either by exception or by a reference # to the VM). raise Exception("VM_LOGIC_ERROR") def main(): device_opt = [ "login", "passwd", "passwd_script", "port", "test", "separator", "no_login", "no_password", "session_url", "uuid" ] atexit.register(atexit_handler) options = check_input(device_opt, process_input(device_opt)) docs = { } docs["shortdesc"] = "XenAPI based fencing for the Citrix XenServer virtual machines." docs["longdesc"] = "\ fence_cxs is an I/O Fencing agent used on Citrix XenServer hosts. \ It uses the XenAPI, supplied by Citrix, to establish an XML-RPC sesssion \ to a XenServer host. Once the session is established, further XML-RPC \ commands are issued in order to switch on, switch off, restart and query \ the status of virtual machines running on the host." show_docs(options, docs) xenSession = connect_and_login(options) # Operate the fencing device result = fence_action(xenSession, options, set_power_fn, get_power_fn, get_outlet_list) sys.exit(result) if __name__ == "__main__": main()