* 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list