[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [Cluster-devel] [PATCH 1/3] New fencing script for Citrix XenServer and XCP.



There are many ways to do it, but honestly, I don't have time to write a
full git guideline ;)

Easier way is to do a new clone from upstream and work on that one.

It doesn't matter to me if it comes in 1 or 5 patches. Whatever you
prefer is fine.

Fabio

On 04/17/2011 09:44 AM, Matt Clark wrote:
> Sure, no problem.
> 
> Is there a way to uncommit the three patches so that I can merge
> everything into 1 patch, or do I need to add a 4th patch that fixes
> everything up? I did have a bit of a search, but the only relevant info
> I could find mentioned altering the most recent commit. Not rolling
> three commits back or merging multiple commits together.
> 
> Sorry, I am used to using svn and git seems to be a bit of a different
> animal.
> 
>> Date: Fri, 15 Apr 2011 10:13:11 +0200
>> From: fdinitto redhat com
>> To: mattjclark0407 hotmail com
>> CC: cluster-devel redhat com; mgrac redhat com
>> Subject: Re: [Cluster-devel] [PATCH 1/3] New fencing script for Citrix
> XenServer and XCP.
>>
>> hi Matt,
>>
>> Marek said the code is fine, can you please resubmit with the build fixes?
>>
>> Thanks
>> fabio
>>
>> On 4/12/2011 4:46 AM, Matt Clark wrote:
>> > Hi Fabio,
>> >
>> > Looks like I had a few problems moving the code over to git. Your
>> > comments all sound perfectly valid. Do you want me to fix up and
> resubmit?
>> >
>> > Cheers,
>> > Matt.
>> >
>> >> Date: Mon, 11 Apr 2011 07:01:29 +0200
>> >> From: fdinitto redhat com
>> >> To: cluster-devel redhat com; mgrac redhat com
>> >> Subject: Re: [Cluster-devel] [PATCH 1/3] New fencing script for Citrix
>> > XenServer and XCP.
>> >>
>> >> Hi Matt,
>> >>
>> >> I'll leave the comments to the code to Marek, but we will need to do a
>> >> few adjustments here and there to get this into the tree.
>> >>
>> >> XenAPI.py being a fence library needs to move into the libs/
> section. It
>> >> is not parsed/built/installed in this patch set.
>> >>
>> >> You sent us pre-built sources and that's not really ok. See for example
>> >> the hardcoded path to the fence library and the addition of
>> >> RELEASE_VERSION and BUILD_DATE at the end of the code for fence_xenapi.
>> >> Those should be generated dynamically at build time to reflect the
> build
>> >> info.
>> >>
>> >> Because I really like to make sure that COPYRIGHT and licences
>> >> information are as exact and clear as possible, please also update
>> >> docs/COPYRIGHT in the "exception" area. While the information in the
>> >> file are absolutely fine, most people tend to look for a
>> >> COPYRIGHT/LICENCE file rather than editing the file itself. It's fair
>> >> that your contribution deserves the right credit and such.
>> >>
>> >> Cheers
>> >> Fabio
>> >>
>> >> On 04/09/2011 06:54 AM, Matt Clark wrote:
>> >> > Fencing script that uses the XenAPI to allow remote switch, status
>> > and list of virtual machines running on Citrix XenServer and Xen Cloud
>> > Platform hosts.
>> >> > ---
>> >> > fence/agents/xenapi/Makefile.am | 17 +++
>> >> > fence/agents/xenapi/XenAPI.py | 209 ++++++++++++++++++++++++++++++++
>> >> > fence/agents/xenapi/fence_xenapi.py | 227
>> > +++++++++++++++++++++++++++++++++++
>> >> > 3 files changed, 453 insertions(+), 0 deletions(-)
>> >> > create mode 100644 fence/agents/xenapi/Makefile.am
>> >> > create mode 100755 fence/agents/xenapi/XenAPI.py
>> >> > create mode 100644 fence/agents/xenapi/fence_xenapi.py
>> >> >
>> >> > diff --git a/fence/agents/xenapi/Makefile.am
>> > b/fence/agents/xenapi/Makefile.am
>> >> > new file mode 100644
>> >> > index 0000000..781975e
>> >> > --- /dev/null
>> >> > +++ b/fence/agents/xenapi/Makefile.am
>> >> > @@ -0,0 +1,17 @@
>> >> > +MAINTAINERCLEANFILES = Makefile.in
>> >> > +
>> >> > +TARGET = fence_xenapi
>> >> > +
>> >> > +SRC = $(TARGET).py
>> >> > +
>> >> > +EXTRA_DIST = $(SRC)
>> >> > +
>> >> > +sbin_SCRIPTS = $(TARGET)
>> >> > +
>> >> > +man_MANS = $(TARGET).8
>> >> > +
>> >> > +include $(top_srcdir)/make/fencebuild.mk
>> >> > +include $(top_srcdir)/make/fenceman.mk
>> >> > +
>> >> > +clean-local: clean-man
>> >> > + rm -f $(TARGET)
>> >> > diff --git a/fence/agents/xenapi/XenAPI.py
>> > b/fence/agents/xenapi/XenAPI.py
>> >> > new file mode 100755
>> >> > index 0000000..4f27ef5
>> >> > --- /dev/null
>> >> > +++ b/fence/agents/xenapi/XenAPI.py
>> >> > @@ -0,0 +1,209 @@
>> >> >
>> >
> +#============================================================================
>> >> > +# This library is free software; you can redistribute it and/or
>> >> > +# modify it under the terms of version 2.1 of the GNU Lesser
>> > General Public
>> >> > +# License as published by the Free Software Foundation.
>> >> > +#
>> >> > +# This library 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
>> >> > +# Lesser General Public License for more details.
>> >> > +#
>> >> > +# You should have received a copy of the GNU Lesser General Public
>> >> > +# License along with this library; if not, write to the Free
> Software
>> >> > +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
>> > 02111-1307 USA
>> >> >
>> >
> +#============================================================================
>> >> > +# Copyright (C) 2006 XenSource Inc.
>> >> >
>> >
> +#============================================================================
>> >> > +#
>> >> > +# Parts of this file are based upon xmlrpclib.py, the XML-RPC client
>> >> > +# interface included in the Python distribution.
>> >> > +#
>> >> > +# Copyright (c) 1999-2002 by Secret Labs AB
>> >> > +# Copyright (c) 1999-2002 by Fredrik Lundh
>> >> > +#
>> >> > +# By obtaining, using, and/or copying this software and/or its
>> >> > +# associated documentation, you agree that you have read,
> understood,
>> >> > +# and will comply with the following terms and conditions:
>> >> > +#
>> >> > +# Permission to use, copy, modify, and distribute this software and
>> >> > +# its associated documentation for any purpose and without fee is
>> >> > +# hereby granted, provided that the above copyright notice
> appears in
>> >> > +# all copies, and that both that copyright notice and this
> permission
>> >> > +# notice appear in supporting documentation, and that the name of
>> >> > +# Secret Labs AB or the author not be used in advertising or
> publicity
>> >> > +# pertaining to distribution of the software without specific,
> written
>> >> > +# prior permission.
>> >> > +#
>> >> > +# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
>> >> > +# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
>> >> > +# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE
> AUTHOR
>> >> > +# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
> OR ANY
>> >> > +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
>> >> > +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
>> >> > +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
> PERFORMANCE
>> >> > +# OF THIS SOFTWARE.
>> >> > +#
> --------------------------------------------------------------------
>> >> > +
>> >> > +import gettext
>> >> > +import xmlrpclib
>> >> > +import httplib
>> >> > +import socket
>> >> > +
>> >> > +translation = gettext.translation('xen-xm', fallback = True)
>> >> > +
>> >> > +class Failure(Exception):
>> >> > + def __init__(self, details):
>> >> > + try:
>> >> > + # If this failure is MESSAGE_PARAMETER_COUNT_MISMATCH, then we
>> >> > + # correct the return values here, to account for the fact that we
>> >> > + # transparently add the session handle as the first argument.
>> >> > + if details[0] == 'MESSAGE_PARAMETER_COUNT_MISMATCH':
>> >> > + details[2] = str(int(details[2]) - 1)
>> >> > + details[3] = str(int(details[3]) - 1)
>> >> > +
>> >> > + self.details = details
>> >> > + except Exception, exn:
>> >> > + self.details = ['INTERNAL_ERROR', 'Client-side: ' + str(exn)]
>> >> > +
>> >> > + def __str__(self):
>> >> > + try:
>> >> > + return translation.ugettext(self.details[0]) % self._details_map()
>> >> > + except TypeError, exn:
>> >> > + return "Message database broken: %s.\nXen-API failure: %s" % \
>> >> > + (exn, str(self.details))
>> >> > + except Exception, exn:
>> >> > + import sys
>> >> > + print >>sys.stderr, exn
>> >> > + return "Xen-API failure: %s" % str(self.details)
>> >> > +
>> >> > + def _details_map(self):
>> >> > + return dict([(str(i), self.details[i])
>> >> > + for i in range(len(self.details))])
>> >> > +
>> >> > +
>> >> > +_RECONNECT_AND_RETRY = (lambda _ : ())
>> >> > +
>> >> > +class UDSHTTPConnection(httplib.HTTPConnection):
>> >> > + """ Stupid hacked up HTTPConnection subclass to allow HTTP over
>> > Unix domain
>> >> > + sockets. """
>> >> > + def connect(self):
>> >> > + path = self.host.replace("_", "/")
>> >> > + self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
>> >> > + self.sock.connect(path)
>> >> > +
>> >> > +class UDSHTTP(httplib.HTTP):
>> >> > + _connection_class = UDSHTTPConnection
>> >> > +
>> >> > +class UDSTransport(xmlrpclib.Transport):
>> >> > + def make_connection(self, host):
>> >> > + return UDSHTTP(host)
>> >> > +
>> >> > +class Session(xmlrpclib.ServerProxy):
>> >> > + """A server proxy and session manager for communicating with Xend
>> > using
>> >> > + the Xen-API.
>> >> > +
>> >> > + Example:
>> >> > +
>> >> > + session = Session('http://localhost:9363/')
>> >> > + session.login_with_password('me', 'mypassword')
>> >> > + session.xenapi.VM.start(vm_uuid)
>> >> > + session.xenapi.session.logout()
>> >> > +
>> >> > + For now, this class also supports the legacy XML-RPC API, using
>> >> > + session.xend.domain('Domain-0') and similar. This support will
>> > disappear
>> >> > + once there is a working Xen-API replacement for every call in the
>> > legacy
>> >> > + API.
>> >> > + """
>> >> > +
>> >> > + def __init__(self, uri, transport=None, encoding=None, verbose=0,
>> >> > + allow_none=1):
>> >> > + xmlrpclib.ServerProxy.__init__(self, uri, transport, encoding,
>> >> > + verbose, allow_none)
>> >> > + self._session = None
>> >> > + self.last_login_method = None
>> >> > + self.last_login_params = None
>> >> > +
>> >> > +
>> >> > + def xenapi_request(self, methodname, params):
>> >> > + if methodname.startswith('login'):
>> >> > + self._login(methodname, params)
>> >> > + return None
>> >> > + else:
>> >> > + retry_count = 0
>> >> > + while retry_count < 3:
>> >> > + full_params = (self._session,) + params
>> >> > + result = _parse_result(getattr(self, methodname)(*full_params))
>> >> > + if result == _RECONNECT_AND_RETRY:
>> >> > + retry_count += 1
>> >> > + if self.last_login_method:
>> >> > + self._login(self.last_login_method,
>> >> > + self.last_login_params)
>> >> > + else:
>> >> > + raise xmlrpclib.Fault(401, 'You must log in')
>> >> > + else:
>> >> > + return result
>> >> > + raise xmlrpclib.Fault(
>> >> > + 500, 'Tried 3 times to get a valid session, but failed')
>> >> > +
>> >> > +
>> >> > + def _login(self, method, params):
>> >> > + result = _parse_result(getattr(self, 'session.%s' %
> method)(*params))
>> >> > + if result == _RECONNECT_AND_RETRY:
>> >> > + raise xmlrpclib.Fault(
>> >> > + 500, 'Received SESSION_INVALID when logging in')
>> >> > + self._session = result
>> >> > + self.last_login_method = method
>> >> > + self.last_login_params = params
>> >> > +
>> >> > +
>> >> > + def __getattr__(self, name):
>> >> > + if name == 'xenapi':
>> >> > + return _Dispatcher(self.xenapi_request, None)
>> >> > + elif name.startswith('login'):
>> >> > + return lambda *params: self._login(name, params)
>> >> > + else:
>> >> > + return xmlrpclib.ServerProxy.__getattr__(self, name)
>> >> > +
>> >> > +def xapi_local():
>> >> > + return Session("http://_var_xapi_xapi/";, transport=UDSTransport())
>> >> > +
>> >> > +def _parse_result(result):
>> >> > + if type(result) != dict or 'Status' not in result:
>> >> > + raise xmlrpclib.Fault(500, 'Missing Status in response from
>> > server' + result)
>> >> > + if result['Status'] == 'Success':
>> >> > + if 'Value' in result:
>> >> > + return result['Value']
>> >> > + else:
>> >> > + raise xmlrpclib.Fault(500,
>> >> > + 'Missing Value in response from server')
>> >> > + else:
>> >> > + if 'ErrorDescription' in result:
>> >> > + if result['ErrorDescription'][0] == 'SESSION_INVALID':
>> >> > + return _RECONNECT_AND_RETRY
>> >> > + else:
>> >> > + raise Failure(result['ErrorDescription'])
>> >> > + else:
>> >> > + raise xmlrpclib.Fault(
>> >> > + 500, 'Missing ErrorDescription in response from server')
>> >> > +
>> >> > +
>> >> > +# Based upon _Method from xmlrpclib.
>> >> > +class _Dispatcher:
>> >> > + def __init__(self, send, name):
>> >> > + self.__send = send
>> >> > + self.__name = name
>> >> > +
>> >> > + def __repr__(self):
>> >> > + if self.__name:
>> >> > + return '<XenAPI._Dispatcher for %s>' % self.__name
>> >> > + else:
>> >> > + return '<XenAPI._Dispatcher>'
>> >> > +
>> >> > + def __getattr__(self, name):
>> >> > + if self.__name is None:
>> >> > + return _Dispatcher(self.__send, name)
>> >> > + else:
>> >> > + return _Dispatcher(self.__send, "%s.%s" % (self.__name, name))
>> >> > +
>> >> > + def __call__(self, *args):
>> >> > + return self.__send(self.__name, args)
>> >> > diff --git a/fence/agents/xenapi/fence_xenapi.py
>> > b/fence/agents/xenapi/fence_xenapi.py
>> >> > new file mode 100644
>> >> > index 0000000..0657f4e
>> >> > --- /dev/null
>> >> > +++ b/fence/agents/xenapi/fence_xenapi.py
>> >> > @@ -0,0 +1,227 @@
>> >> > +#!/usr/bin/python
>> >> > +#
>> >> >
>> >
> +#############################################################################
>> >> > +# Copyright 2011 Matt 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
> <http://www.gnu.org/licenses/>.
>> >> > +
>> >> > +# 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("/usr/lib/fence")
>> >> > +from fencing import *
>> >> > +import XenAPI
>> >> > +
>> >> > +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 = [ "help", "version", "agent", "quiet", "verbose",
>> > "debug", "action",
>> >> > + "login", "passwd", "passwd_script", "port", "test", "separator",
>> >> > + "no_login", "no_password", "power_timeout", "shell_timeout",
>> >> > + "login_timeout", "power_wait", "session_url", "uuid" ]
>> >> > +
>> >> > + atexit.register(atexit_handler)
>> >> > +
>> >> > + options=process_input(device_opt)
>> >> > +
>> >> > + options = check_input(device_opt, options)
>> >> > +
>> >> > + 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()
>> >> > +RELEASE_VERSION="3.1.2.11-2b5b-dirty"
>> >> > +BUILD_DATE="(built Fri Mar 25 22:57:28 EST 2011)"
>> >>
>>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]