* 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