cde8ca2 qemu: fix <clock offset='variable' basis='localtime'/>

Authored and Committed by Laine Stump 9 years ago
    qemu: fix <clock offset='variable' basis='localtime'/>
    
    For a clock element as above, libvirt simply converts current system
    time with localtime_r(), then starts qemu with a time string that
    doesn't contain any timezone information. So, from qemu's point of
    view, the -rtc string it gets for:
    
       <clock offset='variable' basis='utc' adjustment='10800'/>
    
    is identical to the -rtc string it gets for:
    
       <clock offset='variable' basis='localtime' adjustment='0'/>
    
    (assuming the host is in a timezone that is 10800 seconds ahead of
    UTC, as is the case on the machine where this message is being
    written).
    
    Since the commandlines are identical, qemu will behave identically
    after this point in either case.
    
    There are two problems in the case of basis='localtime' though:
    
    Problem 1) If the guest modifies its RTC, for example to add 20
    seconds, the RTC_CHANGE event from qemu will then contain offset:20 in
    both cases. But libvirt will have saved the original adjustment into
    adjustment0, and will add that value onto the offset in the
    event. This means that in the case of basis=;utc', it will properly
    emit an event with offset:10820, but in the case of basis='localtime'
    the event will contain offset:20, which is *not* the new offset of the
    RTC from UTC (as the event it documented to provide).
    
    Problem 2) If the guest is migrated to another host that is in a
    different timezone, or if it is migrated or saved/restored after the
    DST status has changed from what it was when the guest was originally
    started, the newly restarted guest will have a different RTC (since it
    will be based on the new localtime, which could have shifted by
    several hours).
    
    The solution to both of these problems is simple - rather than
    maintaining the original adjustment value along with
    "basis='localtime'" in the domain status, when the domain is started
    we convert the adjustment offset to one relative to UTC, and set the
    status to "basis='utc'". Thus, whatever the RTC offset was from UTC
    when it was initially started, that offset will be maintained when
    migrating across timezones and DST settings, and the RTC_CHANGE events
    will automatically contain the proper offset (which should by
    definition always be relative to UTC).
    
    This fixes a problem that was implied but not openly stated in:
    
      https://bugzilla.redhat.com/show_bug.cgi?id=964177
    
        
file modified
+22 -11