diff --git a/lib/backend.py b/lib/backend.py
index 51a06bbfaa3e28d3df162bf72f83e725ac674b8d..48cfde0b9c253bb63a80444b8ace4d1322aba768 100644
--- a/lib/backend.py
+++ b/lib/backend.py
@@ -1519,6 +1519,34 @@ def GetMigrationStatus(instance):
   except Exception, err:  # pylint: disable=W0703
     _Fail("Failed to get migration status: %s", err, exc=True)
 
+def HotAddDisk(instance, disk, dev_path, seq):
+  """Hot add a nic
+
+  """
+  hyper = hypervisor.GetHypervisor(instance.hypervisor)
+  return hyper.HotAddDisk(instance, disk, dev_path, seq)
+
+def HotDelDisk(instance, disk, seq):
+  """Hot add a nic
+
+  """
+  hyper = hypervisor.GetHypervisor(instance.hypervisor)
+  return hyper.HotDelDisk(instance, disk, seq)
+
+def HotAddNic(instance, nic, seq):
+  """Hot add a nic
+
+  """
+  hyper = hypervisor.GetHypervisor(instance.hypervisor)
+  return hyper.HotAddNic(instance, nic, seq)
+
+def HotDelNic(instance, nic, seq):
+  """Hot add a nic
+
+  """
+  hyper = hypervisor.GetHypervisor(instance.hypervisor)
+  return hyper.HotDelNic(instance, nic, seq)
+
 
 def BlockdevCreate(disk, size, owner, on_primary, info):
   """Creates a block device for an instance.
diff --git a/lib/rpc.py b/lib/rpc.py
index 136532ff5a290880c0e3b8abfa92a84723a1b3cf..cceebe29fc2912effca577b3f006aeeb4731a495 100644
--- a/lib/rpc.py
+++ b/lib/rpc.py
@@ -35,6 +35,7 @@ import zlib
 import base64
 import pycurl
 import threading
+import copy
 
 from ganeti import utils
 from ganeti import objects
@@ -663,6 +664,7 @@ class RpcRunner(_RpcClientBase,
       rpc_defs.ED_INST_DICT: self._InstDict,
       rpc_defs.ED_INST_DICT_HVP_BEP: self._InstDictHvpBep,
       rpc_defs.ED_INST_DICT_OSP_DP: self._InstDictOspDp,
+      rpc_defs.ED_NIC_DICT: self._NicDict,
 
       # Encoders annotating disk parameters
       rpc_defs.ED_DISKS_DICT_DP: self._DisksDictDP,
@@ -688,6 +690,13 @@ class RpcRunner(_RpcClientBase,
     _generated_rpc.RpcClientDnsOnly.__init__(self)
     _generated_rpc.RpcClientDefault.__init__(self)
 
+  def _NicDict(self, nic):
+    """Convert the given nic to a dict and encapsulate netinfo
+
+    """
+    n = copy.deepcopy(nic)
+    return n.ToDict()
+
   def _InstDict(self, instance, hvp=None, bep=None, osp=None):
     """Convert the given instance to a dict.
 
diff --git a/lib/rpc_defs.py b/lib/rpc_defs.py
index 2e8841b430261b94344ffbdec54ab2b293415efa..965d968d5610d567c179b81f72c061c4b9a8d6e9 100644
--- a/lib/rpc_defs.py
+++ b/lib/rpc_defs.py
@@ -73,7 +73,8 @@ ACCEPT_OFFLINE_NODE = object()
  ED_COMPRESS,
  ED_BLOCKDEV_RENAME,
  ED_DISKS_DICT_DP,
- ED_SINGLE_DISK_DICT_DP) = range(1, 14)
+ ED_SINGLE_DISK_DICT_DP,
+ ED_NIC_DICT) = range(1, 15)
 
 
 def _Prepare(calls):
@@ -274,6 +275,27 @@ _INSTANCE_CALLS = [
     ("reinstall", None, None),
     ("debug", None, None),
     ], None, None, "Starts an instance"),
+  ("hot_add_nic", SINGLE, None, TMO_NORMAL, [
+    ("instance", ED_INST_DICT, "Instance object"),
+    ("nic", ED_NIC_DICT, "Nic dict to hotplug"),
+    ("seq", None, "Nic seq to hotplug"),
+    ], None, None, "Adds a nic to a running instance"),
+  ("hot_del_nic", SINGLE, None, TMO_NORMAL, [
+    ("instance", ED_INST_DICT, "Instance object"),
+    ("nic", ED_NIC_DICT, "nic dict to remove"),
+    ("seq", None, "Nic seq to hotplug"),
+    ], None, None, "Removes a nic to a running instance"),
+  ("hot_add_disk", SINGLE, None, TMO_NORMAL, [
+    ("instance", ED_INST_DICT, "Instance object"),
+    ("disk", ED_OBJECT_DICT, "Disk dict to hotplug"),
+    ("dev_path", None, "Device path"),
+    ("seq", None, "Disk seq to hotplug"),
+    ], None, None, "Adds a nic to a running instance"),
+  ("hot_del_disk", SINGLE, None, TMO_NORMAL, [
+    ("instance", ED_INST_DICT, "Instance object"),
+    ("disk", ED_OBJECT_DICT, "Disk dict to remove"),
+    ("seq", None, "Disk seq to hotplug"),
+    ], None, None, "Removes a nic to a running instance"),
   ]
 
 _IMPEXP_CALLS = [
diff --git a/lib/server/noded.py b/lib/server/noded.py
index d95680a55655827b119abd7b0bc1887ed75cd375..1f3de35b8ead9e5fb675d71aad080d3ed5f81a6a 100644
--- a/lib/server/noded.py
+++ b/lib/server/noded.py
@@ -558,6 +558,50 @@ class NodeRequestHandler(http.server.HttpServerHandler):
     instance = objects.Instance.FromDict(instance_name)
     return backend.StartInstance(instance, startup_paused)
 
+  @staticmethod
+  def perspective_hot_add_disk(params):
+    """Hotplugs a nic to a running instance.
+
+    """
+    (idict, ddict, dev_path, seq) = params
+    logging.info("%s %s", idict, ddict)
+    instance = objects.Instance.FromDict(idict)
+    disk = objects.Disk.FromDict(ddict)
+    return backend.HotAddDisk(instance, disk, dev_path, seq)
+
+  @staticmethod
+  def perspective_hot_del_disk(params):
+    """Hotplugs a nic to a running instance.
+
+    """
+    (idict, ddict, seq) = params
+    logging.info("%s %s", idict, ddict)
+    instance = objects.Instance.FromDict(idict)
+    disk = objects.Disk.FromDict(ddict)
+    return backend.HotDelDisk(instance, disk, seq)
+
+  @staticmethod
+  def perspective_hot_add_nic(params):
+    """Hotplugs a nic to a running instance.
+
+    """
+    (idict, ndict, seq) = params
+    logging.info("%s %s", idict, ndict)
+    instance = objects.Instance.FromDict(idict)
+    nic = objects.NIC.FromDict(ndict)
+    return backend.HotAddNic(instance, nic, seq)
+
+  @staticmethod
+  def perspective_hot_del_nic(params):
+    """Hotplugs a nic to a running instance.
+
+    """
+    (idict, ndict, seq) = params
+    logging.info("%s %s", idict, ndict)
+    instance = objects.Instance.FromDict(idict)
+    nic = objects.NIC.FromDict(ndict)
+    return backend.HotDelNic(instance, nic, seq)
+
   @staticmethod
   def perspective_migration_info(params):
     """Gather information about an instance to be migrated.