[Libguestfs] [PATCH] Converter: Fixes to Xen metadata conversion

Matthew Booth mbooth at redhat.com
Wed Jan 6 17:03:39 UTC 2010


Specifically fixes the issue where <script path='vif-bridge'/> would be
corrupted rather than removed properly. Makes metadata conversion less generic.
---
 lib/Sys/VirtV2V/Converter.pm |  144 +++++++++++++++++++++---------------------
 1 files changed, 73 insertions(+), 71 deletions(-)

diff --git a/lib/Sys/VirtV2V/Converter.pm b/lib/Sys/VirtV2V/Converter.pm
index a6eba45..64a5a46 100644
--- a/lib/Sys/VirtV2V/Converter.pm
+++ b/lib/Sys/VirtV2V/Converter.pm
@@ -194,37 +194,7 @@ sub _unconfigure_hvs
     die("unconfigure_hvs called without default_dom argument")
         unless defined($default_dom);
 
-    # Get a list of source HV specific metadata nodes
-    my @nodeinfo = _find_hv_metadata($dom);
-
-    for(my $i = 0; $i < $#nodeinfo; $i += 2) {
-        my $node = $nodeinfo[$i];
-        my $xpath = $nodeinfo[$i + 1]->[0];
-        my $required = $nodeinfo[$i + 1]->[1];
-
-        # Look for a replacement in the defaults
-        my ($default) = $default_dom->findnodes($xpath);
-        if(defined($default)) {
-            if($node->isa('XML::DOM::Attr')) {
-                $node->setNodeValue($default->getNodeValue());
-            } else {
-                my $replacement = $default->cloneNode(1);
-                $replacement->setOwnerDocument($dom);
-
-                $node->getParentNode()->replaceChild($replacement, $node);
-            }
-        }
-
-        else {
-            # Warn if a replacement is required, but none was found
-            print STDERR user_message
-                (__x("WARNING: No replacement found for {xpath} in ".
-                     "domain XML. The node was removed.",
-                     xpath => $xpath)) if($required);
-
-            $node->getParentNode()->removeChild($node);
-        }
-    }
+    _unconfigure_xen_metadata($dom, $default_dom);
 }
 
 sub _configure_os
@@ -303,7 +273,8 @@ sub _configure_capabilities
         if(!$found) {
             print STDERR user_message
                 (__x("The connected hypervisor does not support a ".
-                     "machine type of {machine}.",
+                     "machine type of {machine}. It will be set to the ".
+                     "current default.",
                      machine => $machine->getValue()));
 
             my ($type) = $dom->findnodes('/domain/os/type');
@@ -347,7 +318,9 @@ sub _unconfigure_bootloaders
         '/domain/os/kernel',
         '/domain/os/initrd',
         '/domain/os/root',
-        '/domain/os/cmdline'
+        '/domain/os/cmdline',
+        '/domain/bootloader',
+        '/domain/bootloader_args'
     );
 
     foreach my $path (@bootloader_paths) {
@@ -396,64 +369,93 @@ sub _configure_drivers
     }
 }
 
-sub _find_hv_metadata
+sub _replace_with_default_metadata
 {
-    my ($dom) = @_;
+    my ($node, $xpath, $default_dom) = @_;
+
+    # Look for a replacement in the defaults
+    my ($default) = $default_dom->findnodes($xpath);
+    if(defined($default)) {
+        if($node->isa('XML::DOM::Attr')) {
+            $node->setNodeValue($default->getNodeValue());
+        } else {
+            my $replacement = $default->cloneNode(1);
+            $replacement->setOwnerDocument($node->getOwnerDocument());
+
+            $node->getParentNode()->replaceChild($replacement, $node);
+        }
+    }
+
+    else {
+        # Warn if no replacement was found
+        print STDERR user_message
+            (__x("WARNING: No replacement found for {xpath} in ".
+                 "domain XML. The node was removed.",
+                 xpath => $xpath));
 
-    return _find_xen_metadata($dom);
+        $node->getParentNode()->removeChild($node);
+    }
 }
 
-sub _find_xen_metadata
+sub _unconfigure_xen_metadata
 {
-    my $dom = shift;
-    defined($dom) or carp("find_metadata called without dom argument");
-
-    # List of nodes requiring changes if they exist and match a particular
-    # pattern, and whether they need to be replaced for a guest to function
-    # Most of this is taken from inspection of domain.rng
-    my @check_nodes = (
-        [ '/domain/@type', 'xen', 1 ],
-        [ '/domain/devices/emulator', 'xen', 0 ],
-        [ '/domain/devices/input/@bus', 'xen', 1 ],
-        [ '/domain/devices/interface/script/@path', 'vif-bridge', 0],
-        [ '/domain/os/loader', 'xen', 0 ],
-        [ '/domain/os/type/@machine', '(xenpv|xenfv|xenner)', 0 ],
-        [ '/domain/devices/disk/target/@bus', 'xen', 0 ],
-        [ '/domain/bootloader', undef, 0],
-        [ '/domain/bootloader_args', undef, 0]
-    );
+    my ($dom, $default_dom) = @_;
+
+    # The list of target xen-specific nodes is mostly taken from inspection of
+    # domain.rng
 
-    my @nodeinfo = ();
-    foreach my $check_node (@check_nodes) {
-        my $xpath = $check_node->[0];
-        my $pattern = $check_node->[1];
-        my $required = $check_node->[2];
+    # Nodes which should be replaced with a default if they are present
+    foreach my $hv_node (
+        [ '/domain/@type', 'xen' ],
+        [ '/domain/devices/input/@bus', 'xen' ]
+    ) {
+        my $xpath = $hv_node->[0];
+        my $pattern = $hv_node->[1];
 
         foreach my $node ($dom->findnodes($xpath)) {
             if(defined($pattern)) {
-                my $value;
-                if($node->isa('XML::DOM::Attr')) {
-                    $value = $node->getNodeValue();
-                } else {
-                    my ($text) = $node->findnodes('text()');
-                    $value = $text->getNodeValue();
-                }
-
-                next unless($value =~ m{$pattern});
+                next unless($node->getNodeValue() =~ m{$pattern});
             }
 
-            push(@nodeinfo, $node => [ $xpath, $required ]);
+            _replace_with_default_metadata($node, $xpath, $default_dom);
+        }
+    }
+
+    # Remove machine if it has a xen-specific value
+    # We could replace it with the generic 'pc', but 'pc' is a moving target
+    # across QEMU releases. By removing it entirely, libvirt will automatically
+    # add the latest machine type (e.g. pc-0.11), which is stable.
+    foreach my $machine_type ($dom->findnodes('/domain/os/type/@machine')) {
+        if ($machine_type->getNodeValue() =~ /(xenpv|xenfv|xenner)/) {
+            my ($type) = $dom->findnodes('/domain/os/type[@machine = "'.
+                                         $machine_type->getNodeValue().'"]');
+            $type->getAttributes()->removeNamedItem("machine");
         }
     }
 
-    return @nodeinfo;
+    # Remove emulator if it is defined
+    foreach my $emulator ($dom->findnodes('/domain/devices/emulator')) {
+        $emulator->getParent()->removeChild($emulator);
+    }
+
+    # Remove the script element if its path attribute is 'vif-bridge'
+    foreach my $script ($dom->findnodes('/domain/devices/interface/script[@path = "vif-bridge"]'))
+    {
+        $script->getParent()->removeChild($script);
+    }
+
+    # Other Xen related metadata is handled separately
+    # /domain/devices/disk/target/@bus = 'xen'
+    # /domain/os/loader = 'xen'
+    # /domain/bootloader
+    # /domain/bootloader_args
 }
 
 =back
 
 =head1 COPYRIGHT
 
-Copyright (C) 2009 Red Hat Inc.
+Copyright (C) 2009,2010 Red Hat Inc.
 
 =head1 LICENSE
 
-- 
1.6.5.2




More information about the Libguestfs mailing list