Commit 915faf72 authored by René Nussbaumer's avatar René Nussbaumer
Browse files

Adding RAPI client for instance multi allocation



It was very easy to refactor CreateInstance to repurpose some part of it
for the instance multi allocation request. So we do this.
Signed-off-by: default avatarRené Nussbaumer <rn@google.com>
Reviewed-by: default avatarMichael Hanselmann <hansmi@google.com>
parent e5ff1a47
......@@ -674,6 +674,78 @@ class GanetiRapiClient(object): # pylint: disable=R0904
("/%s/instances/%s/info" %
(GANETI_RAPI_VERSION, instance)), query, None)
@staticmethod
def _UpdateWithKwargs(base, **kwargs):
"""Updates the base with params from kwargs.
@param base: The base dict, filled with required fields
@note: This is an inplace update of base
"""
conflicts = set(kwargs.iterkeys()) & set(base.iterkeys())
if conflicts:
raise GanetiApiError("Required fields can not be specified as"
" keywords: %s" % ", ".join(conflicts))
base.update((key, value) for key, value in kwargs.iteritems()
if key != "dry_run")
def InstanceAllocation(self, mode, name, disk_template, disks, nics,
**kwargs):
"""Generates an instance allocation as used by multiallocate.
More details for parameters can be found in the RAPI documentation.
It is the same as used by CreateInstance.
@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
@return: A dict with the generated entry
"""
# All required fields for request data version 1
alloc = {
"mode": mode,
"name": name,
"disk_template": disk_template,
"disks": disks,
"nics": nics,
}
self._UpdateWithKwargs(alloc, **kwargs)
return alloc
def InstancesMultiAlloc(self, instances, **kwargs):
"""Tries to allocate multiple instances.
More details for parameters can be found in the RAPI documentation.
@param instances: A list of L{InstanceAllocation} results
"""
query = []
body = {
"instances": instances,
}
self._UpdateWithKwargs(body, **kwargs)
_AppendDryRunIf(query, kwargs.get("dry_run"))
return self._SendRequest(HTTP_POST,
"/%s/instances-multi-alloc" % GANETI_RAPI_VERSION,
query, body)
def CreateInstance(self, mode, name, disk_template, disks, nics,
**kwargs):
"""Creates a new instance.
......@@ -703,23 +775,9 @@ class GanetiRapiClient(object): # pylint: disable=R0904
_AppendDryRunIf(query, kwargs.get("dry_run"))
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")
body = self.InstanceAllocation(mode, name, disk_template, disks, nics,
**kwargs)
body[_REQ_DATA_VERSION_FIELD] = 1
else:
raise GanetiApiError("Server does not support new-style (version 1)"
" instance creation requests")
......
......@@ -26,6 +26,7 @@ import unittest
import warnings
import pycurl
from ganeti import opcodes
from ganeti import constants
from ganeti import http
from ganeti import serializer
......@@ -46,7 +47,6 @@ import testutils
_KNOWN_UNUSED = set([
rlib2.R_root,
rlib2.R_2,
rlib2.R_2_instances_multi_alloc,
])
# Global variable for collecting used handlers
......@@ -481,6 +481,21 @@ class GanetiRapiClientTests(testutils.GanetiTestCase):
self.assertItems(["inst32"])
self.assertQuery("static", ["1"])
def testInstancesMultiAlloc(self):
response = {
constants.JOB_IDS_KEY: ["23423"],
opcodes.OpInstanceMultiAlloc.ALLOCATABLE_KEY: ["foobar"],
opcodes.OpInstanceMultiAlloc.FAILED_KEY: ["foobar2"],
}
self.rapi.AddResponse(serializer.DumpJson(response))
insts = [self.client.InstanceAllocation("create", "foobar",
"plain", [], []),
self.client.InstanceAllocation("create", "foobar2",
"drbd8", [{"size": 100}], [])]
resp = self.client.InstancesMultiAlloc(insts)
self.assertEqual(resp, response)
self.assertHandler(rlib2.R_2_instances_multi_alloc)
def testCreateInstanceOldVersion(self):
# The old request format, version 0, is no longer supported
self.rapi.AddResponse(None, code=404)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment