diff --git a/lib/rapi/client.py b/lib/rapi/client.py
index 97d89e003e76420c353ef9e0a642e8e615e5a0d9..dadb820d8d60de4004c4f58a47807325df353b79 100644
--- a/lib/rapi/client.py
+++ b/lib/rapi/client.py
@@ -56,6 +56,10 @@ NODE_ROLE_MASTER = "master"
 NODE_ROLE_OFFLINE = "offline"
 NODE_ROLE_REGULAR = "regular"
 
+# Internal constants
+_REQ_DATA_VERSION_FIELD = "__version__"
+_INST_CREATE_REQV1 = "instance-create-reqv1"
+
 
 class Error(Exception):
   """Base error class for this module.
@@ -555,23 +559,64 @@ class GanetiRapiClient(object):
                              ("/%s/instances/%s" %
                               (GANETI_RAPI_VERSION, instance)), None, None)
 
-  def CreateInstance(self, dry_run=False):
+  def CreateInstance(self, mode, name, disk_template, disks, nics,
+                     **kwargs):
     """Creates a new instance.
 
+    More details for parameters can be found in the RAPI documentation.
+
+    @type mode: string
+    @param mode: Instance creation mode
+    @type name: string
+    @param name: Hostname of the instance to create
+    @type disk_template: string
+    @param disk_template: Disk template for instance (e.g. plain, diskless,
+                          file, or drbd)
+    @type disks: list of dicts
+    @param disks: List of disk definitions
+    @type nics: list of dicts
+    @param nics: List of NIC definitions
     @type dry_run: bool
-    @param dry_run: whether to perform a dry run
+    @keyword dry_run: whether to perform a dry run
 
     @rtype: int
     @return: job id
 
     """
-    # TODO: Pass arguments needed to actually create an instance.
     query = []
-    if dry_run:
+
+    if kwargs.get("dry_run"):
       query.append(("dry-run", 1))
 
+    if _INST_CREATE_REQV1 in self.GetFeatures():
+      # All required fields for request data version 1
+      body = {
+        _REQ_DATA_VERSION_FIELD: 1,
+        "mode": mode,
+        "name": name,
+        "disk_template": disk_template,
+        "disks": disks,
+        "nics": nics,
+        }
+
+      conflicts = set(kwargs.iterkeys()) & set(body.iterkeys())
+      if conflicts:
+        raise GanetiApiError("Required fields can not be specified as"
+                             " keywords: %s" % ", ".join(conflicts))
+
+      body.update((key, value) for key, value in kwargs.iteritems()
+                  if key != "dry_run")
+    else:
+      # TODO: Implement instance creation request data version 0
+      # When implementing version 0, care should be taken to refuse unknown
+      # parameters and invalid values. The interface of this function must stay
+      # exactly the same for version 0 and 1 (e.g. they aren't allowed to
+      # require different data types).
+      raise NotImplementedError("Support for instance creation request data"
+                                " version 0 is not yet implemented")
+
     return self._SendRequest(HTTP_POST, "/%s/instances" % GANETI_RAPI_VERSION,
-                             query, None)
+                             query, body)
 
   def DeleteInstance(self, instance, dry_run=False):
     """Deletes an instance.
diff --git a/test/ganeti.rapi.client_unittest.py b/test/ganeti.rapi.client_unittest.py
index 8840a4b2ab14ebd2d649a18c52a4b764b69238b1..f06a5bf9336a05a2b5e50d323296b005b9115edf 100755
--- a/test/ganeti.rapi.client_unittest.py
+++ b/test/ganeti.rapi.client_unittest.py
@@ -239,12 +239,50 @@ class GanetiRapiClientTests(testutils.GanetiTestCase):
     self.assertHandler(rlib2.R_2_instances_name)
     self.assertItems(["instance"])
 
+  def testCreateInstanceOldVersion(self):
+    self.rapi.AddResponse(serializer.DumpJson([]))
+    self.assertRaises(NotImplementedError, self.client.CreateInstance,
+                      "create", "inst1.example.com", "plain", [], [],
+                      dry_run=True)
+
   def testCreateInstance(self):
-    self.rapi.AddResponse("1234")
-    self.assertEqual(1234, self.client.CreateInstance(dry_run=True))
+    self.rapi.AddResponse(serializer.DumpJson([rlib2._INST_CREATE_REQV1]))
+    self.rapi.AddResponse("23030")
+    job_id = self.client.CreateInstance("create", "inst1.example.com",
+                                        "plain", [], [], dry_run=True)
+    self.assertEqual(job_id, 23030)
     self.assertHandler(rlib2.R_2_instances)
     self.assertDryRun()
 
+    data = serializer.LoadJson(self.http.last_request.data)
+
+    for field in ["dry_run", "beparams", "hvparams", "start"]:
+      self.assertFalse(field in data)
+
+    self.assertEqual(data["name"], "inst1.example.com")
+    self.assertEqual(data["disk_template"], "plain")
+
+  def testCreateInstance2(self):
+    self.rapi.AddResponse(serializer.DumpJson([rlib2._INST_CREATE_REQV1]))
+    self.rapi.AddResponse("24740")
+    job_id = self.client.CreateInstance("import", "inst2.example.com",
+                                        "drbd8", [{"size": 100,}],
+                                        [{}, {"bridge": "br1", }],
+                                        dry_run=False, start=True,
+                                        pnode="node1", snode="node9",
+                                        ip_check=False)
+    self.assertEqual(job_id, 24740)
+    self.assertHandler(rlib2.R_2_instances)
+
+    data = serializer.LoadJson(self.http.last_request.data)
+    self.assertEqual(data[rlib2._REQ_DATA_VERSION], 1)
+    self.assertEqual(data["name"], "inst2.example.com")
+    self.assertEqual(data["disk_template"], "drbd8")
+    self.assertEqual(data["start"], True)
+    self.assertEqual(data["ip_check"], False)
+    self.assertEqualValues(data["disks"], [{"size": 100,}])
+    self.assertEqualValues(data["nics"], [{}, {"bridge": "br1", }])
+
   def testDeleteInstance(self):
     self.rapi.AddResponse("1234")
     self.assertEqual(1234, self.client.DeleteInstance("instance", dry_run=True))