Changing a Guest's desired state, waiting for result

This code, connects to Manager, authenticates and gets a list of all Guests present in that installation.

Implements the following arguments:

  • -m: Manager's address (required)
  • -g: Guest where this action is going to be applied (required)
  • -a: Action to be executed on the Guest (required, either "start", "startonce", "stop", "suspend", "resume", "pause", "resume" or "shutdown" )
  • -p: Manager's password (optional, if not present, password will be asked)

 

#!/usr/bin/env python
  
import ssl
# Recent Python versions require a valid certificate. You can comment this
# if you've loaded a valid certificate in your Manager instance
if hasattr(ssl, '_create_unverified_context'):
    ssl._create_default_https_context = ssl._create_unverified_context
  
import sys
import json
import time
import getpass
from optparse import OptionParser
from optparse import OptionGroup
import urllib2
from urllib2 import Request, urlopen, URLError, HTTPError
from cookielib import CookieJar
  
if __name__ == "__main__":
    ACTIONS = ["start", "startonce", "stop", "suspend", "resume", "pause", "resume", "shutdown"]
    parser = OptionParser(conflict_handler="resolve")
    parser.add_option("-m", "--manager", dest="manager",
                      help="connect to this Manager ", metavar="MANAGER")
    parser.add_option("-p", "--password", dest="password",
                      help="admin password", metavar="PASSWORD")
    parser.add_option("-g", "--guest", dest="guestId",
                      help="guest to be started", metavar="GUESTID")
    parser.add_option("-a", "--action", dest="action",
                      help="action to be applied on guest", metavar="ACTION")
  
    if len(sys.argv) < 2:
        parser.print_help()
        sys.exit(-1)
  
    (options, args) = parser.parse_args(sys.argv[1:])
  
    if options.manager is None:
        parser.print_help()
        sys.exit(-1)
 
    if options.guestId is None:
        parser.print_help()
        sys.exit(-1)
 
    if options.action is None:
        parser.print_help()
        sys.exit(-1)
    elif not options.action in ACTIONS:
        print 'Option ' + options.action + ' is not supported.'
        print 'Try one of these: ' + str(ACTIONS)
        print
        sys.exit(-1)
  
    if options.password is None:
        options.password = getpass.getpass('Enter admin password: ')
  
    # We need to use CookieJar to store the session ID injected by Manager
    cj = CookieJar()
    opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
  
    # Prepare an Authenticate Object
    authenticate = {'username': 'admin',
                    'password': options.password}
  
    # Prepare urllib2 request, converting auth_object to JSON in the process
    authUrl = 'https://' + options.manager + '/authenticate'
    request = urllib2.Request(authUrl, json.dumps(authenticate))
    request.add_header('Content-type', 'application/json')
    response = opener.open(request)
    rawData = response.read()
  
    # Try to parse response as an AuthResult Object
    try:
        authResult = json.loads(rawData)
    except Exception as ex:
        print 'Can\'t parse Manager response as AuthResult Object'
        print 'Data: ' + rawData
        print
        sys.exit(-1)
    if 'status' in authResult:
        if authResult['status'] != 'OK':
            print 'Manager reject this credentials'
            print
            sys.exit(-1)
    else:
        print 'Invalid answer from Manager'
        print 'JSON Data: ' + authResult
        print
        sys.exit(-1)
  
    # Prepare a GuestAction object
    guestAction = {'repeat': '0',
                   'retries': '0',
                   'type': 'guest_action',
                   'guest_id': options.guestId,
                   'action': options.action}
    createTaskUrl = 'https://' + options.manager + '/tasks/create'
    request = urllib2.Request(createTaskUrl, json.dumps(guestAction))
    request.add_header('Content-type', 'application/json')
    response = opener.open(request)
    rawData = response.read()
  
    # Try to parse answer as a TaskResult Object
    try:
        taskResult = json.loads(rawData)
        status = taskResult['status']
        taskId = taskResult['message']
    except Exception as ex:
        print 'Can\'t parse Manager answer a TaskResult Object'
        print 'Data: ' + rawData
        print
        sys.exit(-1)
 
    if status != "OK":
        print 'There was an error trying to create Task'
        print 'Error: ' + taskId
        print
        sys.exit(-1)
 
    print 'Task created with ID=' + taskId
 
    # We have to use sys.stdout.write instead print because:
    #  1.- We don't want a newline
    #  2.- Python sucks
    sys.stdout.write('Waiting for completion...')
    sys.stdout.flush()
 
    count = 0
    # Wait for task completion to obtain its result
    while True:
        # Sleep a little to give some time to complete the Task
        time.sleep(1)
 
        # Request the state for this Task
        thisTaskUrl = 'https://' + options.manager + '/tasks/' + taskId
        request = urllib2.Request(thisTaskUrl)
        response = opener.open(request)
        rawData = response.read()
 
        # Try to parse answer as a JSON dictionary
        try:
            taskState = json.loads(rawData)
        except Exception as ex:
            print 'Can\'t parse Manager answer as a JSON dictionary'
            print 'Data: ' + rawData
            print
            sys.exit(-1)
 
        # Break the Task has completed
        if taskState['state'] == 'completed':
            break
 
        # Bail out if we've waiting for more than 10 seconds
        if count > 10:
            print 'Timed out waiting for Task completion'
            print
            sys.exit(-1)
             
        count += 1
        sys.stdout.write('.')
        sys.stdout.flush()
 
    print ' done'
 
    # Get task result and notify user
    result = taskState['result']
    message = taskState['result_msg']
    if result != 'success':
        print 'Action ' + options.action + ' failed on guest ' + options.guestId
        print 'Message from Manager: ' + message
        print
        sys.exit(-1)
    else:
        print 'Action ' + options.action + ' succeed on guest ' + options.guestId
        print 'Message from Manager: ' + message
        sys.exit(0)