* Chris Evich <cev...@redhat.com> [2012-06-08 10:45:29]:

> On 06/08/2012 02:06 AM, Onkar N Mahajan wrote:
> > On Thu, 2012-06-07 at 10:52 -0400, Chris Evich wrote:
> >> On 06/07/2012 04:46 AM, Onkar N Mahajan wrote:
> >>> Hello All,
> >>>
> >>>   With this patch , you will be able to run tests that use multiple VMs 
> >>> with libvirt. One such
> >>> test is VLAN test ; Which libvirt autotest currently is not capable of 
> >>> running.
> >>>   Capability to run multiple VMs simultaneoulsy and 'explicit' 
> >>> sharing/restricting of resources with
> >>> permissions important for my forthcoming security patches which will test 
> >>> libvirt security infrastructure
> >>> (namely svirt). This patch only attempts segregate VM disk resources 
> >>> (CDROM, VM images) under a VM
> >>> directory which is created per VM at the time of installation. 
> >>> Forthcoming patches will address
> >>> *explicit* sharing/restricting of resources with configuration options.
> >>
> >> Cool! I can't wait to see them!

Hello Lucas, 

Please let us know, if any changes needed for this patch.
We would like to send security patches based on this approach. 

--Pradeep

> >>
> >>>   My intention here was to 'do more with less code' , i.e., minimally 
> >>> disturb existing autotest code.
> >>>   For unattended_install , all you need to do is :
> >>
> >> Great, this is a good mentality/approach.  As-is, most of the libvirt
> >> Autotest code was 'organically' developed/evolved.  We'll be the first
> >> to admit, some if it is pretty scary.  Since it's still very immature,
> >> please don't be afraid of helping (or asking us to) fix broken areas.
> >> It's much better for the long run if we spend a little extra time to get
> >> the fundamentals proper, before more and more tests are added.
> >>
> >>> (1)  create a VM directory under /tmp/libvirt_autotest_root/ whose name 
> >>> must exactly match
> >>>        param 'main_vm' ( in base.cfg ) for e.g., 
> >>> /tmp/libvirt_autotest_root/vm1/ , and
> >>> (2)  create iso directory under VM directory 
> >>> (/tmp/libvirt_autotest_root/vm1/)- namely
> >>>        'linux/iso' (or simply 'iso' - recommended , but requires small 
> >>> change in guest-os.cfg for
> >>>        your guest at param 'cdrom_cd1' , for instance originally your 
> >>> 'cdrom_cd1' would look like
> >>>        'cdrom_cd1 = isos/linux/RHELX.iso' , but now it can just be 
> >>> 'cdrom_cd1 = isos/RHELX.iso' )
> >>> (3)  Place your guest CDROM in the driectory created in (1) and (2)
> >>>        i.e., /tmp/libvirt_autotest_root/vm1/linux/iso ( or simply 
> >>> /tmp/libvirt_autotest_root/vm1/iso
> >>>        , see recomendation in (2))
> >>>
> >>> Signed-off-by: Onkar N Mahajan<onkar.n.maha...@linux.vnet.ibm.com>
> >>>
> >>> ---
> >>>    client/tests/libvirt/tests-shared.cfg.sample |   12 ++--
> >>>    client/virt/libvirt_vm.py                    |   69 
> >>> +++++++++++++++++++++++++-
> >>>    client/virt/virt_utils.py                    |    3 +
> >>>    3 files changed, 77 insertions(+), 7 deletions(-)
> >>>
> >>> diff --git a/client/tests/libvirt/tests-shared.cfg.sample 
> >>> b/client/tests/libvirt/tests-shared.cfg.sample
> >>> index 1fe0894..64cf516 100644
> >>> --- a/client/tests/libvirt/tests-shared.cfg.sample
> >>> +++ b/client/tests/libvirt/tests-shared.cfg.sample
> >>> @@ -28,13 +28,13 @@ include virtio-win.cfg
> >>>    # * The parameters cdrom_unattended, floppy, kernel and initrd are 
> >>> generated
> >>>    #   by LIBVIRT autotest, so remember to put them under a writable 
> >>> location
> >>>    #   (for example, the cdrom share can be read only)
> >>> -image_name(_.*)? ?<= /tmp/libvirt_autotest_root/images/
> >>> -cdrom(_.*)? ?<= /tmp/libvirt_autotest_root/
> >>> -floppy ?<= /tmp/libvirt_autotest_root/
> >>> -image_dir = /tmp/libvirt_autotest_root/
> >>> +image_name(_.*)? ?<= /tmp/libvirt_autotest_root/$main_vm/
> >>> +cdrom(_.*)? ?<= /tmp/libvirt_autotest_root/$main_vm/
> >>> +floppy ?<= /tmp/libvirt_autotest_root/$main_vm/
> >>> +image_dir = /tmp/libvirt_autotest_root/$main_vm/
> >>>    Linux..unattended_install:
> >>> -    kernel ?<= /tmp/libvirt_autotest_root/
> >>> -    initrd ?<= /tmp/libvirt_autotest_root/
> >>> +    kernel ?<= /tmp/libvirt_autotest_root/$main_vm/
> >>> +    initrd ?<= /tmp/libvirt_autotest_root/$main_vm/
> >>>
> >>>    # Uncomment the following lines to enable abort-on-error mode:
> >>>    #abort_on_error = yes
> >>
> >> I don't quite follow the need for vm-specific directories.  Are you
> >> intending to use them for explicit selinux contexts and permissions
> >> testing?  If so, this is probably okay, but:
> >>
> > Yes, for every device (resource) used by the VM , libvirt (dynamic
> > seclabel) or admin (static seclebel) will assign explicit seclebels
> > which would be used by selinux to protect the VMs from being
> > unauthorized access.
> >> My concern for svirt testing this way (and our using /tmp/... in
> >> general) is just making things more difficult and further from the
> >> intended end-user use-case.
> >>
> >> In both Fedora and RHEL, default SELinux policy and file contexts are
> >> already setup for using /var/lib/libvirt/... under many different
> >> scenarios.
> >
> > As mentioned earlier, this segregation of resources was done with
> > minimal  changes to what already exists and is a convention in autotest,
> > for specific needs like storing images at default location used by
> > libvirt ( /var/lib/libvirt/ ...) requires minor (to be precise 6 lines)
> > changes in the configuration file tests-shared.cfg. And this works !!
> >
> >> I'm wondering if there's a good reason for libvirt autotest
> >> to even use /tmp at all, or if it's just done to mirror kvm autotest.
> >>
> > Virtualization testing , not all is performed using autotest , so to avoid
> > security and other tests from interfering with other tests (which might be
> > performed manually in parallel) this is required. But if this interference 
> > is
> > acceptable - configuration option mentioned above is available. For now, 
> > IMHO
> > we can continue with this , and later when *need arises* we can think of
> > changing to default libvirt directory.
> >
> 
> Yes, well explained, you're right, and it can be changed back to the 
> default.  Okay, I'm fine with this change then.
> 
> >> I've always thought we should roll with the defaults more, with most of
> >> this stuff under /var/lib/libvirt/... where it's expected anyway.  i.e.
> >> I think there's more value from a testing perspective in exercising it
> >> the way it was intended to be used first, and secondarily supporting
> >> special-case setups as needed.
> >>
> > Default location is just one type of storage pool
> > ( http://libvirt.org/storage.html ) under libvirt , there are others
> > too,  which are more likely to be used in production scenarios ( due to
> > their obvious performance benefits over the default pool (dir)), with
> > storage management (and security) prospective. These are also important
> > and need to be tested.
> >> IIRC, there's nothing stopping setting non-standard contexts/permissions
> >> on stuff under /var/lib/libvirt/...
> >>
> > yes, as mentioned above , this is possible with this implementation with
> > trivial configuration changes.
> >
> >> Can anyone think of a reason libvirt autotest should not default to the
> >> defaults???
> >>
> >> N.B. 3-4 months ago, I was successful in testing a move of everything
> >> under /var/lib/libvirt and running with selinux enabled/enforcing w/o
> >> complaint.  So it's possible to do.
> >>
> > yes , I agree that this is possible , but can you think of , for now,
> > any erroneous test results as a result of using this standard autotest
> > directory convention ?
> >
> 
> I guess my main fear of not testing the default, by default is that 
> things which are to work out-of-the-box might not be tested.  I guess it 
> comes down to a difference in testing methodology.  Either way, I'm okay 
> with this as-is, and as you mentioned it's easy to fix later if needed.
> 
> >>> diff --git a/client/virt/libvirt_vm.py b/client/virt/libvirt_vm.py
> >>> index cbed8aa..035cedb 100644
> >>> --- a/client/virt/libvirt_vm.py
> >>> +++ b/client/virt/libvirt_vm.py
> >>> @@ -457,6 +457,34 @@ def virsh_detach_device(name, xml_file, extra = "", 
> >>> uri = ""):
> >>>            logging.error("Detaching device from VM %s failed." % name)
> >>>            return False
> >>>
> >>> +def virsh_list(option="--all", uri = ""):
> >>> +    """
> >>> +    - list domains -
> >>> +    @param option: Can take various values see 'virsh help list'
> >>> +                   for more details.
> >>> +    @param uri   : connect uri
> >>> +
> >>> +    Returns a list :
> >>> +    (<rc of virsh list command>   ,<dictionary 'dom-name':
> >>> +    [<dom-id>   ,<dom-status>   ])
> >>
> >> This return seems a bit convoluted since only a True/False rc is
> >> returned anyway.  Why not just return the list of dictionaries, and
> >> throwing exceptions to signal problems (see below also)?
> > First , It makes sense to peep into the dictionary only if virsh has
> > returned successfully.
> 
> I agree, though throwing an exception on error doesn't prevent this either.
> 
> > In virsh_list(), the context is wether 'virsh list' has passed or failed
> > - we need to log this for easier debugging in case of failure.
> 
> This is also possible through the exception mechanism.  However by 
> throwing an exception, callers don't need to be written 'defensively' by 
> default.  This design is more inline with "the python-way" and the style 
> used elsewhere in autotest.  Granted this is a subtle difference, but I 
> think there's value in keeping with the same style and conventions. 
> Plus, lmr doesn't like functions/methods that return multiple values anyway.
> 
> > This error will be logged in the log file :
> > logging.error("Failed listing domains : %s" % (detail))
> > Then this unclean exit signal will be propagated upwards until in
> > nxt_free_vnc_port() :
> > Here we are concerned wether or not we are able to get the peer domain
> > information (in this case vnc ports) , if we are not able to get it ,
> > then we must throw an obvious error message :
> > logging.error("Unable to get peer domain information")
> > by seeing at this we can easily get to the conclusion that something is
> > wrong with libvirt - more investigation on this will reveal the "Failed
> > listing domains ..." message with details of failure.
> 
> Yep, and this flow is fine.  The only difference is in using a 
> try/except vs if/else :D
> 
> >
> > Secondly, in cases where we only need to check if 'virsh list' works,
> > we just need to use the rc status. This might be needed in some future
> > tests.
> >
> 
> This usage is also supported by using exceptions, and in fact it's even 
> easier since you don't need to catch anything.  If it breaks and raises, 
> the test fails w/o needing any extra code.
> 
> >>
> >>> +
> >>> +    """
> >>> +    cmd = "list %s" % option
> >>> +    try:
> >>> +        cmd_res = virsh_cmd(cmd, uri)
> >>> +        d = {}
> >>> +        for line in cmd_res.split("\n"):
> >>> +            l = []
> >>> +            m = re.search('^\s([0-9]*\-?)\s+(\w+)\s+(.*)', line)
> >>
> >> Would '^\s*([0-9]*\-?)\s+(\w+)\s+(.*)' be safer in case starting
> >> whitespace gets lost for whatever reason?
> >>
> > ^\s* in the above regex , addresses this issue.
> >
> >>> +            if m:
> >>> +                l.append(m.group(1))
> >>> +                l.append(m.group(3))
> >>> +                d[m.group(2)] = l
> >>> +        return (True, d)
> >>> +    except error.CmdError, detail:
> >>
> >> If we catch exceptions at this low level, it will negate 'error testing'
> >> possibilities - granted testing 'virsh list' with invalid options is of
> >> arguable value.  However IMHO we should leave options open.
> >>
> > explained earlier
> >
> >>> +        logging.error("Failed listing domains : %s" % (detail))
> >>> +        return (False, None)
> >>> +
> >>>
> >>>    class VM(virt_vm.BaseVM):
> >>>        """
> >>> @@ -529,6 +557,43 @@ class VM(virt_vm.BaseVM):
> >>>            """
> >>>            return virsh_is_alive(self.name, self.connect_uri)
> >>>
> >>> +    def list_peer_domain(self, option="--all"):
> >>
> >> Can we call this list_peer_domains (plural)?  I think it will 'read'
> >> better in test code.
> >>> +        """
> >>> +        Returns list of domains for the uri
> >>> +        """
> >>> +        (rc, val) = virsh_list(option, self.connect_uri)
> >>> +        return (rc, val)
> >>
> >> This is fine.
> >>
> >>> +
> >>> +
> >>> +    def nxt_free_vnc_port(self):
> >>> +        """
> >>> +        Returns max VNC port in use for a particular uri
> >>> +        """
> >>> +        (rc, val) =  self.list_peer_domain()
> >>> +        if not rc:
> >>> +            logging.error("Unable to get peer domain information")
> >>> +            sys.exit(1)
> >>> +        else:
> >>> +            port = 0
> >>> +            for key in val.keys():
> >>> +                """
> >>> +                This currently , only works with VMs installed with
> >>> +                valid VNC port , and doesn't work with domains installed
> >>> +                with<graphics type='vnc' port='-1' autoport='yes'/>. So
> >>> +                domains installed with autotest will be installed with 
> >>> valid
> >>> +                port numbers , externally installed VMs (installed with 
> >>> for
> >>> +                instance virt-manager, virt-install - must be started 
> >>> before this
> >>> +                test is performed.To get valid results and for libvirt
> >>> +                autotest to work successfully.
> >>> +                """
> >>> +                cmd_res = virsh_cmd("vncdisplay %s" % key, 
> >>> self.connect_uri)
> >>> +                m = re.search('(.*)\:(\d+)', cmd_res)
> >>> +                if m.group(2)>= port:
> >>> +                    port = m.group(2)
> >>> +            p = int(port)
> >>> +            if p<= self.vnc_port:
> >>> +                p += self.vnc_port
> >>> +        return p+1
> >> This is a VERY specific/limited use method that doesn't throw exceptions
> >> when expectations aren't met.  However, libvirt autotest's handling of
> >> vnc/spice/etc graphics is fairly 'wonky' and I've been meaning to clean
> >> it up for a while now.
> >>
> > See, I have tried making nxt_free_vnc_port() available for general usage
> > (vnc/spice/etc) as you mentioned , but this requires virsh to have
> > vncdisplay counterparts to spice/etc - which AFAIK are currently not
> > available.
> 
> Annoyingly, it must be extracted from the xml :(  However, you're right 
> in that virsh only has a vncdisplay command.  Along those lines, how 
> about adding a lower-level and more generic virsh_vncdisplay() function 
> that returns the port and ip address?
> 
> I'd like the the vm class methods to support a wider usage, even if all 
> the capabilities aren't there immediately.  When possible, methods 
> should not be tied closely to underlying implementation details.
> 
> For example with graphics, I'd prefer a vm.graphics_info() (or similar 
> name) method provides details independent of the underlying graphics 
> device type.  But it's perfectly acceptable if support for other types 
> gets added at a later date, and it just throws exceptions for the stubs.
> 
> With this deign, we can easily extend the tests (later) by adding 
> support for additional graphics.  It also allows for extending the 
> underlying support w/o disturbing the callers.  Make sense?
> 
> > see line :  cmd_res = virsh_cmd("vncdisplay %s" % key, self.connect_uri)
> >
> > And so this function has been named nxt_free_*vnc*_port() to emphasize
> > that this is currently only for VNC.
> >
> > I agree , that there are other means to get the ports , but this
> > requires more work for now.
> >
> >> What are your thoughts (and testing ideas) on if we got rid of all the
> >> ancillary port finding code and just rely on libvirt to auto-assign by
> >> default?  Maybe that would make this method unnecessary?
> > AFAIK , this will cause problems with network filters tests.
> >
> >>
> >> N/B: runtime auto-assign is what KVM autotest does.
> >
> >>
> >>>        def is_dead(self):
> >>>            """
> >>> @@ -1161,7 +1226,9 @@ class VM(virt_vm.BaseVM):
> >>>
> >>>                # Find available VNC port, if needed
> >>>                if params.get("display") == "vnc":
> >>> -                self.vnc_port = virt_utils.find_free_port(5900, 6100)
> >>> +                p = self.nxt_free_vnc_port()
> >>> +                self.vnc_port = virt_utils.find_free_port(p, 6100)
> >>> +
> >>>
> >>>                # Find available spice port, if needed
> >>>                if params.get("spice"):
> >>> diff --git a/client/virt/virt_utils.py b/client/virt/virt_utils.py
> >>> index 4bbfc7b..e9ce755 100644
> >>> --- a/client/virt/virt_utils.py
> >>> +++ b/client/virt/virt_utils.py
> >>> @@ -678,6 +678,9 @@ def create_image(params, root_dir):
> >>>        """
> >>>        format = params.get("image_format", "qcow2")
> >>>        image_filename = get_image_filename(params, root_dir)
> >>> +
> >>> +    if not os.path.exists(os.path.dirname(image_filename)):
> >>> +        os.mkdir(os.path.dirname(image_filename))
> >>>        size = params.get("image_size", "10G")
> >>>        if params.get("create_with_dd") == "yes" and format == "raw":
> >>>            # maps K,M,G,T =>   (count, bs)
> >>> --
> >>> 1.7.4.4
> >>>
> >>>
> >>
> >>
> > Thanks a lot for taking time to review my patch.
> >
> >
> > Thank you very much.
> 
> Absolutely, together we can do more than any individual can alone :) 
> Thank for your contributions!
> 
> -- 
> Chris Evich, RHCA, RHCE, RHCDS, RHCSS
> Quality Assurance Engineer
> e-mail: cevich + `@' + redhat.com o: 1-888-RED-HAT1 x44214
> _______________________________________________
> Autotest mailing list
> Autotest@test.kernel.org
> http://test.kernel.org/cgi-bin/mailman/listinfo/autotest
> 

_______________________________________________
Autotest mailing list
Autotest@test.kernel.org
http://test.kernel.org/cgi-bin/mailman/listinfo/autotest

Reply via email to