[libvirt] [test-API][PATCH 1/2] Update define module with remote define

Wayne Sun gsun at redhat.com
Fri Oct 14 10:34:12 UTC 2011


  * Add support for define domain on remote host
    Added optional argument target_machine, username and password. If they
    are provided, define domain on remote host, else define domain on
    local.
  * added new optional argument uuid
    it supports define domain with given static uuid if it's provided in
    conf file, else dynamic uuid will be created for domain.

    For remote define with static uuid, use following:
    domain:define
        guestname
            $defaultos
        guesttype
            $defaulthv
        uuid
            $static_uuid
        target_machine
            $target_machine
        username
            $target_user
        password
            $target_password

    For local define with static uuid, use following:
    domain:define
        guestname
            $defaultos
        guesttype
            $defaulthv
        uuid
            $static_uuid

    For local define with dynamic created uuid, use following:
    domain:define
        guestname
            $defaultos
        guesttype
            $defaulthv
---
 repos/domain/define.py |  141 ++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 131 insertions(+), 10 deletions(-)

diff --git a/repos/domain/define.py b/repos/domain/define.py
index d965f63..8f0095a 100644
--- a/repos/domain/define.py
+++ b/repos/domain/define.py
@@ -3,7 +3,8 @@
    define domain from xml
    mandatory arguments:guesttype
                        guestname
-   optional arguments: memory
+   optional arguments: uuid
+                       memory
                        vcpu
                        disksize
                        fullimagepath
@@ -24,6 +25,9 @@ __all__ = ['usage', 'check_define_domain', 'define']
 import os
 import re
 import sys
+import commands
+import string
+import pexpect
 
 def append_path(path):
     """Append root path of package"""
@@ -40,11 +44,16 @@ from lib import connectAPI
 from lib import domainAPI
 from utils.Python import utils
 from utils.Python import xmlbuilder
+from exception import LibvirtAPI
+
+SSH_KEYGEN = "ssh-keygen -t rsa"
+SSH_COPY_ID = "ssh-copy-id"
 
 def usage():
     print '''usage: mandatory arguments:guesttype
                            guestname
-       optional arguments: memory
+       optional arguments: uuid
+                           memory
                            vcpu
                            disksize
                            fullimagepath
@@ -54,6 +63,9 @@ def usage():
                            macaddr
                            ifacetype
                            source
+                           target_machine
+                           username
+                           password
           '''
 
 def check_params(params):
@@ -67,7 +79,61 @@ def check_params(params):
             return 1
     return 0
 
-def check_define_domain(guestname, guesttype, logger):
+def ssh_keygen(logger):
+    """using pexpect to generate RSA"""
+    logger.info("generate ssh RSA \"%s\"" % SSH_KEYGEN)
+    child = pexpect.spawn(SSH_KEYGEN)
+    while True:
+        index = child.expect(['Enter file in which to save the key ',
+                              'Enter passphrase ',
+                              'Enter same passphrase again: ',
+                               pexpect.EOF,
+                               pexpect.TIMEOUT])
+        if index == 0:
+            child.sendline("\r")
+        elif index == 1:
+            child.sendline("\r")
+        elif index == 2:
+            child.sendline("\r")
+        elif index == 3:
+            logger.debug(string.strip(child.before))
+            child.close()
+            return 0
+        elif index == 4:
+            logger.error("ssh_keygen timeout")
+            logger.debug(string.strip(child.before))
+            child.close()
+            return 1
+
+    return 0
+
+def ssh_tunnel(hostname, username, password, logger):
+    """setup a tunnel to a give host"""
+    logger.info("setup ssh tunnel with host %s" % hostname)
+    user_host = "%s@%s" % (username, hostname)
+    child = pexpect.spawn(SSH_COPY_ID, [ user_host])
+    while True:
+        index = child.expect(['yes\/no', 'password: ',
+                               pexpect.EOF,
+                               pexpect.TIMEOUT])
+        if index == 0:
+            child.sendline("yes")
+        elif index == 1:
+            child.sendline(password)
+        elif index == 2:
+            logger.debug(string.strip(child.before))
+            child.close()
+            return 0
+        elif index == 3:
+            logger.error("setup tunnel timeout")
+            logger.debug(string.strip(child.before))
+            child.close()
+            return 1
+
+    return 0
+
+def check_define_domain(guestname, guesttype, target_machine, username, \
+                        password, util, logger):
     """Check define domain result, if define domain is successful,
        guestname.xml will exist under /etc/libvirt/qemu/
        and can use virt-xml-validate tool to check the file validity
@@ -78,10 +144,21 @@ def check_define_domain(guestname, guesttype, logger):
         path = "/etc/xen/%s" % guestname
     else:
         logger.error("unknown guest type")
-    if os.access(path, os.R_OK):
-        return True
+
+    if target_machine:
+        cmd = "ls %s" % path
+        ret, output = util.remote_exec_pexpect(target_machine, username, \
+                                               password, cmd)
+        if ret:
+            logger.error("guest %s xml file doesn't exsits" % guestname)
+            return False
+        else:
+            return True
     else:
-        return False
+        if os.access(path, os.R_OK):
+            return True
+        else:
+            return False
 
 def define(params):
     """Define a domain from xml"""
@@ -94,9 +171,39 @@ def define(params):
     guesttype = params['guesttype']
     test_result = False
 
-    # Connect to local hypervisor connection URI
+    if params.has_key('target_machine'):
+        logger.info("define domain on remote host")
+        target_machine = params['target_machine']
+        username = params['username']
+        password = params['password']
+    else:
+        logger.info("define domain on local host")
+        target_machine = None
+        username = None
+        password = None
+
+    # Connect to hypervisor connection URI
     util = utils.Utils()
-    uri = util.get_uri('127.0.0.1')
+    if target_machine:
+        uri = util.get_uri(target_machine)
+
+        #generate ssh key pair
+        ret = ssh_keygen(logger)
+        if ret:
+            logger.error("failed to generate RSA key")
+            return 1
+        #setup ssh tunnel with target machine
+        ret = ssh_tunnel(target_machine, username, password, logger)
+        if ret:
+            logger.error("faild to setup ssh tunnel with target machine %s" % \
+                          target_machine)
+            return 1
+
+        commands.getstatusoutput("ssh-add")
+
+    else:
+        uri = util.get_uri('127.0.0.1')
+
     conn = connectAPI.ConnectAPI()
     virconn = conn.open(uri)
 
@@ -117,19 +224,33 @@ def define(params):
     try:
         try:
             dom_obj.define(dom_xml)
-            if  check_define_domain(guestname, guesttype, logger):
+            if check_define_domain(guestname, guesttype, target_machine, \
+                                   username, password, util, logger):
                 logger.info("define a domain form xml is successful")
                 test_result = True
             else:
                 logger.error("fail to check define domain")
                 test_result = False
-        except:
+        except LibvirtAPI, e:
             logger.error("fail to define a domain from xml")
             test_result = False
     finally:
         conn.close()
         logger.info("closed hypervisor connection")
 
+    if target_machine:
+        REMOVE_SSH = "ssh %s \"rm -rf /root/.ssh/*\"" % (target_machine)
+        logger.info("remove ssh key on remote machine")
+        status, ret = util.exec_cmd(REMOVE_SSH, shell=True)
+        if status:
+            logger.error("failed to remove ssh key")
+
+        REMOVE_LOCAL_SSH = "rm -rf /root/.ssh/*"
+        logger.info("remove local ssh key")
+        status, ret = util.exec_cmd(REMOVE_LOCAL_SSH, shell=True)
+        if status:
+            logger.error("failed to remove local ssh key")
+
     if test_result:
         return 0
     else:
-- 
1.7.1




More information about the libvir-list mailing list