diff --git a/daemons/ganeti-noded b/daemons/ganeti-noded index aa9b386ad376e53249a0b88e8621a16e031b20be..c1e8776f7b60e08797fade4fade1fc004bc54a53 100755 --- a/daemons/ganeti-noded +++ b/daemons/ganeti-noded @@ -241,7 +241,9 @@ class NodeHttpServer(http.HttpServer): dest_node = params[1] instance = objects.Instance.FromDict(params[2]) cluster_name = params[3] - return backend.ExportSnapshot(disk, dest_node, instance, cluster_name) + dev_idx = params[4] + return backend.ExportSnapshot(disk, dest_node, instance, + cluster_name, dev_idx) @staticmethod def perspective_finalize_export(params): diff --git a/lib/backend.py b/lib/backend.py index 8f2758db690bc61589475c53dbf287a9224f2368..5f77000b40c1f2a82e4813a1258ba150c3814608 100644 --- a/lib/backend.py +++ b/lib/backend.py @@ -1331,16 +1331,22 @@ def SnapshotBlockDevice(disk): (disk.unique_id, disk.dev_type)) -def ExportSnapshot(disk, dest_node, instance, cluster_name): +def ExportSnapshot(disk, dest_node, instance, cluster_name, idx): """Export a block device snapshot to a remote node. - Args: - disk: the snapshot block device - dest_node: the node to send the image to - instance: instance being exported - - Returns: - True if successful, False otherwise. + @type disk: L{objects.Disk} + @param disk: the description of the disk to export + @type dest_node: str + @param dest_node: the destination node to export to + @type instance: L{objects.Instance} + @param instance: the instance object to whom the disk belongs + @type cluster_name: str + @param cluster_name: the cluster name, needed for SSH hostalias + @type idx: int + @param idx: the index of the disk in the instance's disk list, + used to export to the OS scripts environment + @rtype: bool + @return: the success of the operation """ export_env = OSEnvironment(instance) @@ -1359,6 +1365,7 @@ def ExportSnapshot(disk, dest_node, instance, cluster_name): real_disk.Open() export_env['EXPORT_DEVICE'] = real_disk.dev_path + export_env['EXPORT_INDEX'] = str(idx) destdir = os.path.join(constants.EXPORT_DIR, instance.name + ".new") destfile = disk.physical_id[1] @@ -1512,6 +1519,7 @@ def ImportOSIntoInstance(instance, src_node, src_images, cluster_name): destcmd) command = '|'.join([utils.ShellQuoteArgs(remotecmd), comprcmd, impcmd]) import_env['IMPORT_DEVICE'] = import_env['DISK_%d_PATH' % idx] + import_env['IMPORT_INDEX'] = str(idx) result = utils.RunCmd(command, env=import_env) if result.failed: logging.error("disk import command '%s' returned error: %s" diff --git a/lib/cmdlib.py b/lib/cmdlib.py index 7ab093238ccc5eb67164c242abe50b0bd284e756..6814a2d4f5f0a7fb4646c6935dec51a967d128f5 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -4912,10 +4912,10 @@ class LUExportInstance(LogicalUnit): # TODO: check for size cluster_name = self.cfg.GetClusterName() - for dev in snap_disks: + for idx, dev in enumerate(snap_disks): if dev: if not self.rpc.call_snapshot_export(src_node, dev, dst_node.name, - instance, cluster_name): + instance, cluster_name, idx): self.LogWarning("Could not export block device %s from node %s to" " node %s", dev.logical_id[1], src_node, dst_node.name) diff --git a/lib/rpc.py b/lib/rpc.py index e49237193d1901f56030afb247c4a82b49310b7f..1ab4b7015cd84a12df0607a100577cae4ab265a2 100644 --- a/lib/rpc.py +++ b/lib/rpc.py @@ -787,14 +787,14 @@ class RpcRunner(object): return c.GetResults().get(node, False) def call_snapshot_export(self, node, snap_bdev, dest_node, instance, - cluster_name): + cluster_name, idx): """Request the export of a given snapshot. This is a single-node call. """ params = [snap_bdev.ToDict(), dest_node, - self._InstDict(instance), cluster_name] + self._InstDict(instance), cluster_name, idx] c = Client("snapshot_export", params) self._ConnectNode(c, node) c.Run()