[libvirt] [test-API][PATCH] Add test case for start domain on nfs storage

Guannan Ren gren at redhat.com
Wed Sep 7 11:34:38 UTC 2011


On 09/06/2011 06:28 PM, Wayne Sun wrote:
>    * This test is for start a domain with img file on nfs storage.
>     Under SElinux boolean virt_use_nfs on or off, combine with
>     setting the dynamic_ownership in /etc/libvirt/qemu.conf,
>     check whether the guest can be started or not. The nfs could
>     be root_squash or no_root_squash. SElinux should be enabled
>     and enforcing on host.
> ---
>   repos/sVirt/domain_nfs_start.py |  476 +++++++++++++++++++++++++++++++++++++++
>   1 files changed, 476 insertions(+), 0 deletions(-)
>   create mode 100644 repos/sVirt/__init__.py
>   create mode 100644 repos/sVirt/domain_nfs_start.py
>
> diff --git a/repos/sVirt/__init__.py b/repos/sVirt/__init__.py
> new file mode 100644
> index 0000000..e69de29
> diff --git a/repos/sVirt/domain_nfs_start.py b/repos/sVirt/domain_nfs_start.py
> new file mode 100644
> index 0000000..0b66128
> --- /dev/null
> +++ b/repos/sVirt/domain_nfs_start.py
> @@ -0,0 +1,476 @@
> +#!/usr/bin/env python
> +"""This test is for start a guest with img file on nfs storage.
> +   Under SElinux boolean virt_use_nfs on or off, combine with
> +   setting the dynamic_ownership in /etc/libvirt/qemu.conf,
> +   check whether the guest can be started or not. The nfs could
> +   be root_squash or no_root_squash. SElinux should be enabled
> +   and enforcing on host.
> +   sVirt:domain_nfs_start
> +       guestname
> +           #GUESTNAME#
> +       dynamic_ownership
> +           enable|disable
> +       virt_use_nfs
> +           on|off
> +       root_squash
> +           yes|no
> +"""
> +
> +__author__ = 'Wayne Sun: gsun at redhat.com'
> +__date__ = 'Mon Sep 2, 2011'
> +__version__ = '0.1.0'
> +__credits__ = 'Copyright (C) 2011 Red Hat, Inc.'
> +__all__ = ['domain_nfs_start']
> +
> +import os
> +import re
> +import sys
> +
> +QEMU_CONF = "/etc/libvirt/qemu.conf"
> +
> +def append_path(path):
> +    """Append root path of package"""
> +    if path in sys.path:
> +        pass
> +    else:
> +        sys.path.append(path)
> +
> +from lib import connectAPI
> +from lib import domainAPI
> +from utils.Python import utils
> +from exception import LibvirtAPI
> +
> +pwd = os.getcwd()
> +result = re.search('(.*)libvirt-test-API', pwd)
> +append_path(result.group(0))
> +
> +def return_close(conn, logger, ret):
> +    """close hypervisor connection and return the given value"""
> +    conn.close()
> +    logger.info("closed hypervisor connection")
> +    return ret
> +
> +def check_params(params):
> +    """Verify inputing parameter dictionary"""
> +    logger = params['logger']
> +    keys = ['guestname', 'dynamic_ownership', 'virt_use_nfs', 'root_squash']
> +    for key in keys:
> +        if key not in params:
> +            logger.error("%s is required" %key)
> +            return 1
> +    return 0
> +
> +def nfs_setup(util, root_squash, logger):
> +    """setup nfs on localhost
> +    """
> +    logger.info("set nfs service")
> +    if root_squash == "yes":
> +        option = "root_squash"
> +    elif root_squash == "no":
> +        option = "no_root_squash"
> +
> +    cmd = "echo /tmp *\(rw,%s\)>>  /etc/exports" % option
> +    ret, out = util.exec_cmd(cmd, shell=True)
> +    if ret:
> +        logger.error("failed to config nfs export")
> +        return 1
> +
> +    logger.info("restart nfs service")
> +    cmd = "service nfs restart"
> +    ret, out = util.exec_cmd(cmd, shell=True)
> +    if ret:
> +        logger.error("failed to restart nfs service")
> +        return 1
> +    else:
> +        for i in range(len(out)):
> +            logger.info(out[i])
> +
> +    return 0
> +
> +def prepare_env(util, d_ownership, virt_use_nfs, guestname, root_squash, \
> +                disk_file, img_dir, logger):
> +    """set virt_use_nfs SElinux boolean, configure
> +       dynamic_ownership in /etc/libvirt/qemu.conf
> +    """
> +    logger.info("set virt_use_nfs selinux boolean")
> +    cmd = "setsebool virt_use_nfs %s" % virt_use_nfs
> +    ret, out = util.exec_cmd(cmd, shell=True)
> +    if ret:
> +        logger.error("failed to set virt_use_nfs SElinux boolean")
> +        return 1
> +
> +    logger.info("set the dynamic ownership in %s as %s" % \
> +                (QEMU_CONF, d_ownership))
> +    if d_ownership == "enable":
> +        option = 1
> +    elif d_ownership == "disable":
> +        option = 0
> +    set_cmd = "echo dynamic_ownership = %s>>  %s" % \
> +               (option, QEMU_CONF)
> +    ret, out = util.exec_cmd(set_cmd, shell=True)
> +    if ret:
> +        logger.error("failed to set dynamic ownership")
> +        return 1
> +
> +    logger.info("restart libvirtd")
> +    restart_cmd = "service libvirtd restart"
> +    ret, out = util.exec_cmd(restart_cmd, shell=True)
> +    if ret:
> +        logger.error("failed to restart libvirtd")
> +        for i in range(len(out)):
> +            logger.info(out[i])
> +        return 1
> +    else:
> +        for i in range(len(out)):
> +            logger.info(out[i])
> +
> +    logger.info("copy %s img file to nfs path" %guestname)
> +    cmd = "cp %s /tmp" % disk_file

            remove the disk_file in /tmp before copying would be better,
            because the cp command is interactive by default.
            By the way, the shutil module could handle directory and file
            operation in many situations. It's better to use python module
            instead of wrapping shell command.


> +    ret, out = util.exec_cmd(cmd, shell=True)
> +    if ret:
> +        logger.error("failed to cp %s img file to nfs path" % guestname)
> +        return 1
> +
> +    logger.info("set up nfs service on localhost")
> +    ret = nfs_setup(util, root_squash, logger)
> +    if ret:
> +        return 1
> +
> +    logger.info("mount nfs to img dir path")
> +    mount_cmd = "mount -o vers=3 127.0.0.1:/tmp %s" % img_dir
> +    ret, out = util.exec_cmd(mount_cmd, shell=True)
> +    if ret:
> +        logger.error("Failed to mount the nfs path")
> +        for i in range(len(out)):
> +            logger.info(out[i])
> +        return 1
> +
> +    return 0
> +
> +def domain_nfs_start(params):
> +    """start domain with img on nfs"""
> +    # Initiate and check parameters
> +    params_check_result = check_params(params)
> +    if params_check_result:
> +        return 1
> +
> +    logger = params['logger']
> +    guestname = params['guestname']
> +    dynamic_ownership = params['dynamic_ownership']
> +    virt_use_nfs = params['virt_use_nfs']
> +    root_squash = params['root_squash']
> +
> +    util = utils.Utils()
> +
> +    # Connect to local hypervisor connection URI
> +    uri = util.get_uri('127.0.0.1')
> +    conn = connectAPI.ConnectAPI()
> +    virconn = conn.open(uri)
> +    domobj = domainAPI.DomainAPI(virconn)
> +
> +    logger.info("get the domain state")
> +    try:
> +        state = domobj.get_state(guestname)
> +        logger.info("domain %s is %s" % (guestname, state))
> +    except LibvirtAPI, e:
> +        logger.error("API error message: %s, error code is %s" % \
> +                      (e.response()['message'], e.response()['code']))
> +        logger.error("Error: fail to get domain %s state" % guestname)
> +        return return_close(conn, logger, 1)
> +
> +    if state != "shutoff":
> +        logger.info("shut down the domain %s" % guestname)
> +        try:
> +            domobj.destroy(guestname)
> +        except LibvirtAPI, e:
> +            logger.error("API error message: %s, error code is %s" % \
> +                          (e.response()['message'], e.response()['code']))
> +            logger.error("Error: fail to destroy domain %s" % guestname)
> +            return return_close(conn, logger, 1)
> +
> +    logger.info("get guest img file path")
> +    try:
> +        dom_xml = domobj.get_xml_desc(guestname)
> +        disk_file = util.get_disk_path(dom_xml)
> +        logger.info("%s disk file path is %s" % (guestname, disk_file))
> +        img_dir = os.path.dirname(disk_file)
> +    except LibvirtAPI, e:
> +        logger.error("API error message: %s, error code is %s" % \
> +                      (e.response()['message'], e.response()['code']))
> +        logger.error("Error: fail to get domain %s xml" % guestname)
> +        return return_close(conn, logger, 1)
> +
> +    # set env
> +    logger.info("prepare the environment")
> +    ret = prepare_env(util, dynamic_ownership, virt_use_nfs, guestname,\
> +                      root_squash, disk_file, img_dir, logger)
> +    if ret:
> +        logger.error("failed to prepare the environment")
> +        return return_close(conn, logger, 1)
> +
> +    # some operation cause the connection broke, so reconnect here. Unsure the
> +    # reason, need fix on this
> +    conn.close()
> +    conn = connectAPI.ConnectAPI()
> +    virconn = conn.open(uri)
> +    domobj = domainAPI.DomainAPI(virconn)

            Sorry, we have to figure out what the problem is.
            We couldn't leave it here.


> +
> +    logger.info("begin to test start domain from nfs storage")
> +    logger.info("First, start the domain without chown the img file to qemu")
> +    logger.info("start domain %s" % guestname)
> +    if root_squash == "yes":
> +        if virt_use_nfs == "on":
> +            if dynamic_ownership == "enable":
> +                try:
> +                    domobj.start(guestname)
> +                    logger.error("Domain %s started, this is not expected" % \
> +                                  guestname)
> +                    return return_close(conn, logger, 1)
> +                except LibvirtAPI, e:
> +                    logger.info("API error message: %s, error code is %s" % \
> +                                  (e.response()['message'], e.response()['code']))
> +                    logger.info("Fail to start domain %s, this is expected" % \
> +                                 guestname)
> +
> +            elif dynamic_ownership == "disable":
> +                try:
> +                    domobj.start(guestname)
> +                    logger.error("Domain %s started, this is not expected" % \
> +                                  guestname)
> +                    return return_close(conn, logger, 1)
> +                except LibvirtAPI, e:
> +                    logger.info("API error message: %s, error code is %s" % \
> +                                  (e.response()['message'], e.response()['code']))
> +                    logger.info("Fail to start domain %s, this is expected" % \
> +                                 guestname)
> +        elif virt_use_nfs == "off":
> +            if dynamic_ownership == "enable":
> +                try:
> +                    domobj.start(guestname)
> +                    logger.error("Domain %s started, this is not expected" % \
> +                                  guestname)
> +                    return return_close(conn, logger, 1)
> +                except LibvirtAPI, e:
> +                    logger.info("API error message: %s, error code is %s" % \
> +                                  (e.response()['message'], e.response()['code']))
> +                    logger.info("Fail to start domain %s, this is expected" % \
> +                                 guestname)
> +
> +            elif dynamic_ownership == "disable":
> +                try:
> +                    domobj.start(guestname)
> +                    logger.error("Domain %s started, this is not expected" % \
> +                                  guestname)
> +                    return return_close(conn, logger, 1)
> +                except LibvirtAPI, e:
> +                    logger.info("API error message: %s, error code is %s" % \
> +                                  (e.response()['message'], e.response()['code']))
> +                    logger.info("Fail to start domain %s, this is expected" % \
> +                                 guestname)
> +    elif root_squash == "no":
> +        if virt_use_nfs == "on":
> +            if dynamic_ownership == "enable":
> +                try:
> +                    domobj.start(guestname)
> +                    logger.info("Success start domain %s" % guestname)
> +                except LibvirtAPI, e:
> +                    logger.error("API error message: %s, error code is %s" % \
> +                                  (e.response()['message'], e.response()['code']))
> +                    logger.error("Fail to start domain %s" % guestname)
> +                    return return_close(conn, logger, 1)
> +
> +            elif dynamic_ownership == "disable":
> +                try:
> +                    domobj.start(guestname)
> +                    logger.error("Domain %s started, this is not expected" % \
> +                                  guestname)
> +                    return return_close(conn, logger, 1)
> +                except LibvirtAPI, e:
> +                    logger.info("API error message: %s, error code is %s" % \
> +                                  (e.response()['message'], e.response()['code']))
> +                    logger.info("Fail to start domain %s, this is expected" % \
> +                                 guestname)
> +        elif virt_use_nfs == "off":
> +            if dynamic_ownership == "enable":
> +                try:
> +                    domobj.start(guestname)
> +                    logger.error("Domain %s started, this is not expected" % \
> +                                  guestname)
> +                    return return_close(conn, logger, 1)
> +                except LibvirtAPI, e:
> +                    logger.info("API error message: %s, error code is %s" % \
> +                                  (e.response()['message'], e.response()['code']))
> +                    logger.info("Fail to start domain %s, this is expected" % \
> +                                 guestname)
> +
> +            elif dynamic_ownership == "disable":
> +                try:
> +                    domobj.start(guestname)
> +                    logger.error("Domain %s started, this is not expected" % \
> +                                  guestname)
> +                    return return_close(conn, logger, 1)
> +                except LibvirtAPI, e:
> +                    logger.info("API error message: %s, error code is %s" % \
> +                                  (e.response()['message'], e.response()['code']))
> +                    logger.info("Fail to start domain %s, this is expected" % \
> +                                 guestname)
> +
> +    logger.info("get the domain state")
> +    try:
> +        state = domobj.get_state(guestname)
> +        logger.info("domain %s is %s" % (guestname, state))
> +    except LibvirtAPI, e:
> +        logger.error("API error message: %s, error code is %s" % \
> +                      (e.response()['message'], e.response()['code']))
> +        logger.error("Error: fail to get domain %s state" % guestname)
> +        return return_close(conn, logger, 1)
> +
> +    if state != "shutoff":
> +        logger.info("shut down the domain %s" % guestname)
> +        try:
> +            domobj.destroy(guestname)
> +        except LibvirtAPI, e:
> +            logger.error("API error message: %s, error code is %s" % \
> +                          (e.response()['message'], e.response()['code']))
> +            logger.error("Error: fail to destroy domain %s" % guestname)
> +            return return_close(conn, logger, 1)
> +
> +    logger.info("Second, start the domain after chown the img file to qemu")
> +
> +    file_name = os.path.basename(disk_file)
> +    filepath = "/tmp/%s" % file_name
> +    logger.info("set chown of %s as 107:107" % filepath)
> +    chown_cmd = "chown 107:107 %s" % filepath
> +    ret, out = util.exec_cmd(chown_cmd, shell=True)
> +    if ret:
> +        logger.error("failed to chown %s to qemu:qemu" % filepath)
> +        return return_close(conn, logger, 1)
> +
> +    logger.info("start domain %s" % guestname)
> +    if root_squash == "yes":
> +        if virt_use_nfs == "on":
> +            if dynamic_ownership == "enable":
> +                try:
> +                    domobj.start(guestname)
> +                    logger.info("Success start domain %s" % guestname)
> +                except LibvirtAPI, e:
> +                    logger.error("API error message: %s, error code is %s" % \
> +                                  (e.response()['message'], e.response()['code']))
> +                    logger.error("Fail to start domain %s" % guestname)
> +                    return return_close(conn, logger, 1)
> +
> +            elif dynamic_ownership == "disable":
> +                try:
> +                    domobj.start(guestname)
> +                    logger.info("Success start domain %s" % guestname)
> +                except LibvirtAPI, e:
> +                    logger.error("API error message: %s, error code is %s" % \
> +                                  (e.response()['message'], e.response()['code']))
> +                    logger.error("Fail to start domain %s" % guestname)
> +                    return return_close(conn, logger, 1)
> +
> +        elif virt_use_nfs == "off":
> +            if dynamic_ownership == "enable":
> +                try:
> +                    domobj.start(guestname)
> +                    logger.error("Domain %s started, this is not expected" % \
> +                                  guestname)
> +                    return return_close(conn, logger, 1)
> +                except LibvirtAPI, e:
> +                    logger.info("API error message: %s, error code is %s" % \
> +                                  (e.response()['message'], e.response()['code']))
> +                    logger.info("Fail to start domain %s, this is expected" % \
> +                                 guestname)
> +
> +            elif dynamic_ownership == "disable":
> +                try:
> +                    domobj.start(guestname)
> +                    logger.error("Domain %s started, this is not expected" % \
> +                                  guestname)
> +                    return return_close(conn, logger, 1)
> +                except LibvirtAPI, e:
> +                    logger.info("API error message: %s, error code is %s" % \
> +                                  (e.response()['message'], e.response()['code']))
> +                    logger.info("Fail to start domain %s, this is expected" % \
> +                                 guestname)
> +    elif root_squash == "no":
> +        if virt_use_nfs == "on":
> +            if dynamic_ownership == "enable":
> +                try:
> +                    domobj.start(guestname)
> +                    logger.info("Success start domain %s" % guestname)
> +                except LibvirtAPI, e:
> +                    logger.error("API error message: %s, error code is %s" % \
> +                                  (e.response()['message'], e.response()['code']))
> +                    logger.error("Fail to start domain %s" % guestname)
> +                    return return_close(conn, logger, 1)
> +
> +            elif dynamic_ownership == "disable":
> +                try:
> +                    domobj.start(guestname)
> +                    logger.info("Success start Domain %s" % guestname)
> +                except LibvirtAPI, e:
> +                    logger.error("API error message: %s, error code is %s" % \
> +                                  (e.response()['message'], e.response()['code']))
> +                    logger.error("Fail to start domain %s" % guestname)
> +                    return return_close(conn, logger, 1)
> +
> +        elif virt_use_nfs == "off":
> +            if dynamic_ownership == "enable":
> +                try:
> +                    domobj.start(guestname)
> +                    logger.error("Domain %s started, this is not expected" % \
> +                                  guestname)
> +                    return return_close(conn, logger, 1)
> +                except LibvirtAPI, e:
> +                    logger.info("API error message: %s, error code is %s" % \
> +                                  (e.response()['message'], e.response()['code']))
> +                    logger.info("Fail to start domain %s, this is expected" % \
> +                                 guestname)
> +
> +            elif dynamic_ownership == "disable":
> +                try:
> +                    domobj.start(guestname)
> +                    logger.error("Domain %s started, this is not expected" % \
> +                                  guestname)
> +                    return return_close(conn, logger, 1)
> +                except LibvirtAPI, e:
> +                    logger.info("API error message: %s, error code is %s" % \
> +                                  (e.response()['message'], e.response()['code']))
> +                    logger.info("Fail to start domain %s, this is expected" % \
> +                                 guestname)
> +
> +    return return_close(conn, logger, 0)
> +
> +def domain_nfs_start_clean(params):
> +    """clean testing environment"""
> +    logger = params['logger']
> +    guestname = params['guestname']
> +
> +    util = utils.Utils()
> +
> +    # Connect to local hypervisor connection URI
> +    uri = util.get_uri('127.0.0.1')
> +    conn = connectAPI.ConnectAPI()
> +    virconn = conn.open(uri)
> +    domobj = domainAPI.DomainAPI(virconn)
> +
> +    if domobj.get_state(guestname) != "shutoff":
> +        domobj.destroy(guestname)
> +
> +    dom_xml = domobj.get_xml_desc(guestname)
> +    disk_file = util.get_disk_path(dom_xml)
> +    img_dir = os.path.dirname(disk_file)
> +    file_name = os.path.basename(disk_file)
> +    temp_file = "/tmp/%s" % file_name
> +
> +    umount_cmd = "umount -f %s" % img_dir
> +    ret, out = util.exec_cmd(umount_cmd, shell=True)
> +    if ret:
> +        logger.error("failed to umount %s" % img_dir)

         It's better to use os.path.ismount() to check whether a path is 
a mount point.
         then decide umount action or not.

> +
> +    if os.path.exists(temp_file):
> +        os.remove(temp_file)
> +
> +    conn.close()
> +

       Others is fine.

       Guannan Ren




More information about the libvir-list mailing list