diff --git a/lib/backend.py b/lib/backend.py
index 601a3f3627debdecb8f7ad903485b9d4cc674b3b..9b98a7675e239552141f4a6c4ba0df2de6e80c30 100644
--- a/lib/backend.py
+++ b/lib/backend.py
@@ -2109,7 +2109,7 @@ def FinalizeExport(instance, snap_disks):
 
   utils.WriteFile(utils.PathJoin(destdir, constants.EXPORT_CONF_FILE),
                   data=config.Dumps())
-  shutil.rmtree(finaldestdir, True)
+  shutil.rmtree(finaldestdir, ignore_errors=True)
   shutil.move(destdir, finaldestdir)
 
 
@@ -2273,7 +2273,7 @@ def _TransformFileStorageDir(file_storage_dir):
   cfg = _GetConfig()
   file_storage_dir = os.path.normpath(file_storage_dir)
   base_file_storage_dir = cfg.GetFileStorageDir()
-  if (not os.path.commonprefix([file_storage_dir, base_file_storage_dir]) ==
+  if (os.path.commonprefix([file_storage_dir, base_file_storage_dir]) !=
       base_file_storage_dir):
     _Fail("File storage directory '%s' is not under base file"
           " storage directory '%s'", file_storage_dir, base_file_storage_dir)
diff --git a/lib/cli.py b/lib/cli.py
index c178bb62188cddda0cff1fc3622c3d606f28bf63..2a5dc17b3a163f2f6b7f9c891150ca4441b8a57c 100644
--- a/lib/cli.py
+++ b/lib/cli.py
@@ -91,6 +91,7 @@ __all__ = [
   "NODE_PLACEMENT_OPT",
   "NOHDR_OPT",
   "NOIPCHECK_OPT",
+  "NO_INSTALL_OPT",
   "NONAMECHECK_OPT",
   "NOLVM_STORAGE_OPT",
   "NOMODIFY_ETCHOSTS_OPT",
@@ -126,6 +127,7 @@ __all__ = [
   "TAG_SRC_OPT",
   "TIMEOUT_OPT",
   "USEUNITS_OPT",
+  "USE_REPL_NET_OPT",
   "VERBOSE_OPT",
   "VG_NAME_OPT",
   "YES_DOIT_OPT",
@@ -595,6 +597,11 @@ FORCE_VARIANT_OPT = cli_option("--force-variant", dest="force_variant",
                                action="store_true", default=False,
                                help="Force an unknown variant")
 
+NO_INSTALL_OPT = cli_option("--no-install", dest="no_install",
+                            action="store_true", default=False,
+                            help="Do not install the OS (will"
+                            " enable no-start)")
+
 BACKEND_OPT = cli_option("-B", "--backend-parameters", dest="beparams",
                          type="keyval", default={},
                          help="Backend parameters")
@@ -911,6 +918,12 @@ NEW_CLUSTER_DOMAIN_SECRET_OPT = cli_option("--new-cluster-domain-secret",
                                            help=("Create a new cluster domain"
                                                  " secret"))
 
+USE_REPL_NET_OPT = cli_option("--use-replication-network",
+                              dest="use_replication_network",
+                              help="Whether to use the replication network"
+                              " for talking to the nodes",
+                              action="store_true", default=False)
+
 
 def _ParseArgs(argv, commands, aliases):
   """Parser for the command line arguments.
@@ -1580,11 +1593,13 @@ def GenericInstanceCreate(mode, opts, args):
     os_type = opts.os
     src_node = None
     src_path = None
+    no_install = opts.no_install
   elif mode == constants.INSTANCE_IMPORT:
     start = False
     os_type = None
     src_node = opts.src_node
     src_path = opts.src_dir
+    no_install = None
   else:
     raise errors.ProgrammerError("Invalid creation mode %s" % mode)
 
@@ -1606,7 +1621,8 @@ def GenericInstanceCreate(mode, opts, args):
                                 start=start,
                                 os_type=os_type,
                                 src_node=src_node,
-                                src_path=src_path)
+                                src_path=src_path,
+                                no_install=no_install)
 
   SubmitOrSend(op, opts)
   return 0
@@ -1901,7 +1917,8 @@ def ParseTimespec(value):
   return value
 
 
-def GetOnlineNodes(nodes, cl=None, nowarn=False):
+def GetOnlineNodes(nodes, cl=None, nowarn=False, secondary_ips=False,
+                   filter_master=False):
   """Returns the names of online nodes.
 
   This function will also log a warning on stderr with the names of
@@ -1914,17 +1931,36 @@ def GetOnlineNodes(nodes, cl=None, nowarn=False):
   @param nowarn: by default, this function will output a note with the
       offline nodes that are skipped; if this parameter is True the
       note is not displayed
+  @type secondary_ips: boolean
+  @param secondary_ips: if True, return the secondary IPs instead of the
+      names, useful for doing network traffic over the replication interface
+      (if any)
+  @type filter_master: boolean
+  @param filter_master: if True, do not return the master node in the list
+      (useful in coordination with secondary_ips where we cannot check our
+      node name against the list)
 
   """
   if cl is None:
     cl = GetClient()
 
-  result = cl.QueryNodes(names=nodes, fields=["name", "offline"],
+  if secondary_ips:
+    name_idx = 2
+  else:
+    name_idx = 0
+
+  if filter_master:
+    master_node = cl.QueryConfigValues(["master_node"])[0]
+    filter_fn = lambda x: x != master_node
+  else:
+    filter_fn = lambda _: True
+
+  result = cl.QueryNodes(names=nodes, fields=["name", "offline", "sip"],
                          use_locking=False)
   offline = [row[0] for row in result if row[1]]
   if offline and not nowarn:
     ToStderr("Note: skipping offline node(s): %s" % utils.CommaJoin(offline))
-  return [row[0] for row in result if not row[1]]
+  return [row[name_idx] for row in result if not row[1] and filter_fn(row[0])]
 
 
 def _ToStream(stream, txt, *args):
diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index cf25d9037b5eccc0715175fd65ab3a92376a7bb4..f15cd14b622c53ddcdefab8059044b2eaa9fd700 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -542,6 +542,24 @@ def _CheckNodeNotDrained(lu, node):
                                errors.ECODE_INVAL)
 
 
+def _CheckNodeHasOS(lu, node, os_name, force_variant):
+  """Ensure that a node supports a given OS.
+
+  @param lu: the LU on behalf of which we make the check
+  @param node: the node to check
+  @param os_name: the OS to query about
+  @param force_variant: whether to ignore variant errors
+  @raise errors.OpPrereqError: if the node is not supporting the OS
+
+  """
+  result = lu.rpc.call_os_get(node, os_name)
+  result.Raise("OS '%s' not in supported OS list for node %s" %
+               (os_name, node),
+               prereq=True, ecode=errors.ECODE_INVAL)
+  if not force_variant:
+    _CheckOSVariant(result.payload, os_name)
+
+
 def _CheckDiskTemplate(template):
   """Ensure a given disk template is valid.
 
@@ -4139,12 +4157,7 @@ class LUReinstallInstance(LogicalUnit):
     if self.op.os_type is not None:
       # OS verification
       pnode = _ExpandNodeName(self.cfg, instance.primary_node)
-      result = self.rpc.call_os_get(pnode, self.op.os_type)
-      result.Raise("OS '%s' not in supported OS list for primary node %s" %
-                   (self.op.os_type, pnode),
-                   prereq=True, ecode=errors.ECODE_INVAL)
-      if not self.op.force_variant:
-        _CheckOSVariant(result.payload, self.op.os_type)
+      _CheckNodeHasOS(self, pnode, self.op.os_type, self.op.force_variant)
 
     self.instance = instance
 
@@ -5824,6 +5837,11 @@ class LUCreateInstance(LogicalUnit):
     # for tools
     if not hasattr(self.op, "name_check"):
       self.op.name_check = True
+    if not hasattr(self.op, "no_install"):
+      self.op.no_install = False
+    if self.op.no_install and self.op.start:
+      self.LogInfo("No-installation mode selected, disabling startup")
+      self.op.start = False
     # validate/normalize the instance name
     self.op.instance_name = utils.HostInfo.NormalizeName(self.op.instance_name)
     if self.op.ip_check and not self.op.name_check:
@@ -6068,6 +6086,9 @@ class LUCreateInstance(LogicalUnit):
       # works again!
       self.op.force_variant = True
 
+      if self.op.no_install:
+        self.LogInfo("No-installation mode has no effect during import")
+
     else: # INSTANCE_CREATE
       if getattr(self.op, "os_type", None) is None:
         raise errors.OpPrereqError("No guest OS specified",
@@ -6316,13 +6337,7 @@ class LUCreateInstance(LogicalUnit):
 
     _CheckHVParams(self, nodenames, self.op.hypervisor, self.op.hvparams)
 
-    # os verification
-    result = self.rpc.call_os_get(pnode.name, self.op.os_type)
-    result.Raise("OS '%s' not in supported os list for primary node %s" %
-                 (self.op.os_type, pnode.name),
-                 prereq=True, ecode=errors.ECODE_INVAL)
-    if not self.op.force_variant:
-      _CheckOSVariant(result.payload, self.op.os_type)
+    _CheckNodeHasOS(self, pnode.name, self.op.os_type, self.op.force_variant)
 
     _CheckNicsBridgesExist(self, self.nics, self.pnode.name)
 
@@ -6440,12 +6455,13 @@ class LUCreateInstance(LogicalUnit):
 
     if iobj.disk_template != constants.DT_DISKLESS and not self.adopt_disks:
       if self.op.mode == constants.INSTANCE_CREATE:
-        feedback_fn("* running the instance OS create scripts...")
-        # FIXME: pass debug option from opcode to backend
-        result = self.rpc.call_instance_os_add(pnode_name, iobj, False,
-                                               self.op.debug_level)
-        result.Raise("Could not add os for instance %s"
-                     " on node %s" % (instance, pnode_name))
+        if not self.op.no_install:
+          feedback_fn("* running the instance OS create scripts...")
+          # FIXME: pass debug option from opcode to backend
+          result = self.rpc.call_instance_os_add(pnode_name, iobj, False,
+                                                 self.op.debug_level)
+          result.Raise("Could not add os for instance %s"
+                       " on node %s" % (instance, pnode_name))
 
       elif self.op.mode == constants.INSTANCE_IMPORT:
         feedback_fn("* running the instance OS import scripts...")
@@ -7743,9 +7759,13 @@ class LUSetInstanceParams(LogicalUnit):
       self.op.disk_template = None
     if not hasattr(self.op, "remote_node"):
       self.op.remote_node = None
+    if not hasattr(self.op, "os_name"):
+      self.op.os_name = None
+    if not hasattr(self.op, "force_variant"):
+      self.op.force_variant = False
     self.op.force = getattr(self.op, "force", False)
     if not (self.op.nics or self.op.disks or self.op.disk_template or
-            self.op.hvparams or self.op.beparams):
+            self.op.hvparams or self.op.beparams or self.op.os_name):
       raise errors.OpPrereqError("No changes submitted", errors.ECODE_INVAL)
 
     if self.op.hvparams:
@@ -8173,6 +8193,11 @@ class LUSetInstanceParams(LogicalUnit):
                                      (disk_op, len(instance.disks)),
                                      errors.ECODE_INVAL)
 
+    # OS change
+    if self.op.os_name and not self.op.force:
+      _CheckNodeHasOS(self, instance.primary_node, self.op.os_name,
+                      self.op.force_variant)
+
     return
 
   def _ConvertPlainToDrbd(self, feedback_fn):
@@ -8383,6 +8408,10 @@ class LUSetInstanceParams(LogicalUnit):
       for key, val in self.op.beparams.iteritems():
         result.append(("be/%s" % key, val))
 
+    # OS change
+    if self.op.os_name:
+      instance.os = self.op.os_name
+
     self.cfg.Update(instance, feedback_fn)
 
     return result
diff --git a/lib/opcodes.py b/lib/opcodes.py
index e718a8e7b740fb83904df1a9ceed1b6e7ab94467..d6d026ae69ff4a4729dac5e8ed1b3eb67e9656fc 100644
--- a/lib/opcodes.py
+++ b/lib/opcodes.py
@@ -460,7 +460,8 @@ class OpCreateInstance(OpCode):
   OP_ID = "OP_INSTANCE_CREATE"
   OP_DSC_FIELD = "instance_name"
   __slots__ = [
-    "instance_name", "os_type", "force_variant",
+    "instance_name",
+    "os_type", "force_variant", "no_install",
     "pnode", "disk_template", "snode", "mode",
     "disks", "nics",
     "src_node", "src_path", "start",
@@ -621,7 +622,7 @@ class OpSetInstanceParams(OpCode):
     "instance_name",
     "hvparams", "beparams", "force",
     "nics", "disks", "disk_template",
-    "remote_node",
+    "remote_node", "os_name", "force_variant",
     ]
 
 
diff --git a/man/gnt-cluster.sgml b/man/gnt-cluster.sgml
index 6ee98c2d83bb4a777477529807442199c2228602..a54b1c4117288a1e237398328c6c310006bd4fdf 100644
--- a/man/gnt-cluster.sgml
+++ b/man/gnt-cluster.sgml
@@ -138,6 +138,7 @@
 
       <cmdsynopsis>
         <command>copyfile</command>
+        <arg>--use-replication-network</arg>
         <arg>-n <replaceable>node</replaceable></arg>
         <arg choice="req"><replaceable>file</replaceable></arg>
       </cmdsynopsis>
@@ -150,6 +151,10 @@
         <option>-n</option> is not given at all, the file will be
         copied to all nodes.
 
+        Passing the <option>--use-replication-network</option> option
+        will cause the copy to be done over the replication network
+        (only matters if the primary/secondary IPs are different).
+
         Example:
         <screen>
           # gnt-cluster -n node1.example.com -n node2.example.com copyfile /tmp/test
diff --git a/man/gnt-instance.sgml b/man/gnt-instance.sgml
index b8ed14b3a03d1c145f43c2c1faca65842168f501..178a3596fd6d7cb6b06e5df8a848b82e15c0844a 100644
--- a/man/gnt-instance.sgml
+++ b/man/gnt-instance.sgml
@@ -85,6 +85,7 @@
           <arg>--no-ip-check</arg>
           <arg>--no-name-check</arg>
           <arg>--no-start</arg>
+          <arg>--no-install</arg>
           <sbr>
           <group>
             <arg rep="repeat">--net=<replaceable>N</replaceable><arg rep="repeat">:options</arg></arg>
@@ -243,7 +244,13 @@
         <para>
           The <option>-o</option> options specifies the operating
           system to be installed. The available operating systems can
-          be listed with <command>gnt-os list</command>.
+          be listed with <command>gnt-os
+          list</command>. Passing <option>--no-install</option> will
+          however skip the OS installation, allowing a manual import
+          if so desired. Note that the no-installation mode will
+          automatically disable the start-up of the instance (without
+          an OS, it most likely won't be able to start-up
+          successfully).
         </para>
 
         <para>
@@ -1403,6 +1410,8 @@ instance5: 11225
               <arg>drbd</arg>
             </group></arg>
 
+          <sbr>
+            <arg>--os-name=<replaceable>OS</replaceable> <arg>--force-variant</arg></arg>
 
           <sbr>
           <arg>--submit</arg>
@@ -1453,6 +1462,16 @@ instance5: 11225
           option will change the parameters of the Nth instance NIC.
         </para>
 
+        <para>
+          The option <option>--os-name</option> will change the OS
+          name for the instance (without reinstallation). In case an
+          OS variant is specified that is not found, then by default
+          the modification is refused,
+          unless <option>--force-variant</option> is passed. An
+          invalid OS will also be refused, unless
+          the <option>--force</option> option is given.
+        </para>
+
         <para>
           The <option>--submit</option> option is used to send the job to
           the master daemon but not wait for its completion. The job
diff --git a/scripts/gnt-cluster b/scripts/gnt-cluster
index c51b73dd13a7476635166fa86bdb1b26a2d92e23..8adfff26e119fe4b404424f5a433c8e5425c7d32 100755
--- a/scripts/gnt-cluster
+++ b/scripts/gnt-cluster
@@ -300,12 +300,10 @@ def ClusterCopyFile(opts, args):
 
   cl = GetClient()
 
-  myname = utils.GetHostInfo().name
-
   cluster_name = cl.QueryConfigValues(["cluster_name"])[0]
 
-  results = GetOnlineNodes(nodes=opts.nodes, cl=cl)
-  results = [name for name in results if name != myname]
+  results = GetOnlineNodes(nodes=opts.nodes, cl=cl, filter_master=True,
+                           secondary_ips=opts.use_replication_network)
 
   srun = ssh.SshRunner(cluster_name=cluster_name)
   for node in results:
@@ -777,7 +775,7 @@ commands = {
     "", "Shows the cluster master"),
   'copyfile': (
     ClusterCopyFile, [ArgFile(min=1, max=1)],
-    [NODE_LIST_OPT],
+    [NODE_LIST_OPT, USE_REPL_NET_OPT],
     "[-n node...] <filename>", "Copies a file to all (or only some) nodes"),
   'command': (
     RunClusterCommand, [ArgCommand(min=1)],
diff --git a/scripts/gnt-instance b/scripts/gnt-instance
index 45444f11afa76dcc6ac30e018c088f229e3341a4..406325348400fe2f9c18060491f68fbc5a767477 100755
--- a/scripts/gnt-instance
+++ b/scripts/gnt-instance
@@ -1208,7 +1208,7 @@ def SetInstanceParams(opts, args):
 
   """
   if not (opts.nics or opts.disks or opts.disk_template or
-          opts.hvparams or opts.beparams):
+          opts.hvparams or opts.beparams or opts.os):
     ToStderr("Please give at least one of the parameters.")
     return 1
 
@@ -1261,6 +1261,8 @@ def SetInstanceParams(opts, args):
                                    remote_node=opts.node,
                                    hvparams=opts.hvparams,
                                    beparams=opts.beparams,
+                                   os_name=opts.os,
+                                   force_variant=opts.force_variant,
                                    force=opts.force)
 
   # even if here we process the result, we allow submit only
@@ -1339,6 +1341,7 @@ add_opts = [
   NWSYNC_OPT,
   OS_OPT,
   FORCE_VARIANT_OPT,
+  NO_INSTALL_OPT,
   OS_SIZE_OPT,
   SUBMIT_OPT,
   ]
@@ -1417,7 +1420,7 @@ commands = {
   'modify': (
     SetInstanceParams, ARGS_ONE_INSTANCE,
     [BACKEND_OPT, DISK_OPT, FORCE_OPT, HVOPTS_OPT, NET_OPT, SUBMIT_OPT,
-     DISK_TEMPLATE_OPT, SINGLE_NODE_OPT],
+     DISK_TEMPLATE_OPT, SINGLE_NODE_OPT, OS_OPT, FORCE_VARIANT_OPT],
     "<instance>", "Alters the parameters of an instance"),
   'shutdown': (
     GenericManyOps("shutdown", _ShutdownInstance), [ArgInstance()],