X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/4b10fb65a69049a0d032dab7f5db130423a79b6e..bcd87e22bb462c87c50fc07a2cca14a977e79253:/qa/qa_rapi.py diff --git a/qa/qa_rapi.py b/qa/qa_rapi.py index 2e19bf5..cdf454a 100644 --- a/qa/qa_rapi.py +++ b/qa/qa_rapi.py @@ -1,6 +1,6 @@ # -# Copyright (C) 2007, 2008, 2009, 2010 Google Inc. +# Copyright (C) 2007, 2008, 2009, 2010, 2011 Google Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -23,23 +23,26 @@ """ import tempfile +import random from ganeti import utils from ganeti import constants from ganeti import errors -from ganeti import serializer from ganeti import cli from ganeti import rapi +from ganeti import objects +from ganeti import query +from ganeti import compat +from ganeti import qlang -import ganeti.rapi.client +import ganeti.rapi.client # pylint: disable-msg=W0611 import ganeti.rapi.client_utils import qa_config import qa_utils import qa_error -from qa_utils import (AssertEqual, AssertNotEqual, AssertIn, AssertMatch, - StartLocalCommand) +from qa_utils import (AssertEqual, AssertIn, AssertMatch, StartLocalCommand) _rapi_ca = None @@ -52,6 +55,8 @@ def Setup(username, password): """Configures the RAPI client. """ + # pylint: disable-msg=W0603 + # due to global usage global _rapi_ca global _rapi_client global _rapi_username @@ -117,6 +122,8 @@ def Enabled(): def _DoTests(uris): + # pylint: disable-msg=W0212 + # due to _SendRequest usage results = [] for uri, verify, method, body in uris: @@ -217,6 +224,122 @@ def TestEmptyCluster(): raise qa_error.Error("Non-implemented method didn't fail") +def TestRapiQuery(): + """Testing resource queries via remote API. + + """ + master_name = qa_utils.ResolveNodeName(qa_config.GetMasterNode()) + rnd = random.Random(7818) + + for what in constants.QR_VIA_RAPI: + all_fields = query.ALL_FIELDS[what].keys() + rnd.shuffle(all_fields) + + # No fields, should return everything + result = _rapi_client.QueryFields(what) + qresult = objects.QueryFieldsResponse.FromDict(result) + AssertEqual(len(qresult.fields), len(all_fields)) + + # One field + result = _rapi_client.QueryFields(what, fields=["name"]) + qresult = objects.QueryFieldsResponse.FromDict(result) + AssertEqual(len(qresult.fields), 1) + + # Specify all fields, order must be correct + result = _rapi_client.QueryFields(what, fields=all_fields) + qresult = objects.QueryFieldsResponse.FromDict(result) + AssertEqual(len(qresult.fields), len(all_fields)) + AssertEqual([fdef.name for fdef in qresult.fields], all_fields) + + # Unknown field + result = _rapi_client.QueryFields(what, fields=["_unknown!"]) + qresult = objects.QueryFieldsResponse.FromDict(result) + AssertEqual(len(qresult.fields), 1) + AssertEqual(qresult.fields[0].name, "_unknown!") + AssertEqual(qresult.fields[0].kind, constants.QFT_UNKNOWN) + + # Try once more, this time without the client + _DoTests([ + ("/2/query/%s/fields" % what, None, "GET", None), + ("/2/query/%s/fields?fields=name,name,%s" % (what, all_fields[0]), + None, "GET", None), + ]) + + # Try missing query argument + try: + _DoTests([ + ("/2/query/%s" % what, None, "GET", None), + ]) + except rapi.client.GanetiApiError, err: + AssertEqual(err.code, 400) + else: + raise qa_error.Error("Request missing 'fields' parameter didn't fail") + + def _Check(exp_fields, data): + qresult = objects.QueryResponse.FromDict(data) + AssertEqual([fdef.name for fdef in qresult.fields], exp_fields) + if not isinstance(qresult.data, list): + raise qa_error.Error("Query did not return a list") + + _DoTests([ + # Specify fields in query + ("/2/query/%s?fields=%s" % (what, ",".join(all_fields)), + compat.partial(_Check, all_fields), "GET", None), + + ("/2/query/%s?fields=name" % what, + compat.partial(_Check, ["name"]), "GET", None), + + # Note the spaces + ("/2/query/%s?fields=name,%%20name%%09,name%%20" % what, + compat.partial(_Check, ["name"] * 3), "GET", None), + + # PUT with fields in query + ("/2/query/%s?fields=name" % what, + compat.partial(_Check, ["name"]), "PUT", {}), + + # Fields in body + ("/2/query/%s" % what, compat.partial(_Check, all_fields), "PUT", { + "fields": all_fields, + }), + + ("/2/query/%s" % what, compat.partial(_Check, ["name"] * 4), "PUT", { + "fields": ["name"] * 4, + }), + ]) + + def _CheckFilter(): + _DoTests([ + # With filter + ("/2/query/%s" % what, compat.partial(_Check, all_fields), "PUT", { + "fields": all_fields, + "filter": [qlang.OP_TRUE, "name"], + }), + ]) + + if what == constants.QR_LOCK: + # Locks can't be filtered + try: + _CheckFilter() + except rapi.client.GanetiApiError, err: + AssertEqual(err.code, 500) + else: + raise qa_error.Error("Filtering locks didn't fail") + else: + _CheckFilter() + + if what == constants.QR_NODE: + # Test with filter + (nodes, ) = _DoTests([("/2/query/%s" % what, + compat.partial(_Check, ["name", "master"]), "PUT", { + "fields": ["name", "master"], + "filter": [qlang.OP_TRUE, "master"], + })]) + qresult = objects.QueryResponse.FromDict(nodes) + AssertEqual(qresult.data, [ + [[constants.RS_NORMAL, master_name], [constants.RS_NORMAL, True]], + ]) + + def TestInstance(instance): """Testing getting instance(s) info via remote API. @@ -244,7 +367,7 @@ def TestInstance(instance): _VerifyReturnsJob, 'PUT', None), ]) - # Test OpPrepareExport + # Test OpBackupPrepare (job_id, ) = _DoTests([ ("/2/instances/%s/prepare-export?mode=%s" % (instance["name"], constants.EXPORT_MODE_REMOTE), @@ -292,17 +415,19 @@ def TestTags(kind, name, tags): uri = "/2/nodes/%s/tags" % name elif kind == constants.TAG_INSTANCE: uri = "/2/instances/%s/tags" % name + elif kind == constants.TAG_NODEGROUP: + uri = "/2/groups/%s/tags" % name else: raise errors.ProgrammerError("Unknown tag kind") def _VerifyTags(data): AssertEqual(sorted(tags), sorted(data)) - query = "&".join("tag=%s" % i for i in tags) + queryargs = "&".join("tag=%s" % i for i in tags) # Add tags (job_id, ) = _DoTests([ - ("%s?%s" % (uri, query), _VerifyReturnsJob, "PUT", None), + ("%s?%s" % (uri, queryargs), _VerifyReturnsJob, "PUT", None), ]) _WaitForRapiJob(job_id) @@ -313,7 +438,7 @@ def TestTags(kind, name, tags): # Remove tags (job_id, ) = _DoTests([ - ("%s?%s" % (uri, query), _VerifyReturnsJob, "DELETE", None), + ("%s?%s" % (uri, queryargs), _VerifyReturnsJob, "DELETE", None), ]) _WaitForRapiJob(job_id) @@ -322,8 +447,6 @@ def _WaitForRapiJob(job_id): """Waits for a job to finish. """ - master = qa_config.GetMasterNode() - def _VerifyJob(data): AssertEqual(data["id"], job_id) for field in JOB_FIELDS: @@ -405,15 +528,14 @@ def TestRapiInstanceAdd(node, use_client): try: memory = utils.ParseUnit(qa_config.get("mem")) disk_sizes = [utils.ParseUnit(size) for size in qa_config.get("disk")] + disks = [{"size": size} for size in disk_sizes] + nics = [{}] - if use_client: - disks = [{"size": size} for size in disk_sizes] - nics = [{}] - - beparams = { - constants.BE_MEMORY: memory, - } + beparams = { + constants.BE_MEMORY: memory, + } + if use_client: job_id = _rapi_client.CreateInstance(constants.INSTANCE_CREATE, instance["name"], constants.DT_PLAIN, @@ -423,12 +545,15 @@ def TestRapiInstanceAdd(node, use_client): beparams=beparams) else: body = { + "__version__": 1, + "mode": constants.INSTANCE_CREATE, "name": instance["name"], - "os": qa_config.get("os"), + "os_type": qa_config.get("os"), "disk_template": constants.DT_PLAIN, "pnode": node["primary"], - "memory": memory, - "disks": disk_sizes, + "beparams": beparams, + "disks": disks, + "nics": nics, } (job_id, ) = _DoTests([ @@ -470,6 +595,11 @@ def TestRapiInstanceRename(rename_source, rename_target): _WaitForRapiJob(_rapi_client.RenameInstance(rename_source, rename_target)) +def TestRapiInstanceReinstall(instance): + """Test reinstalling an instance via RAPI""" + _WaitForRapiJob(_rapi_client.ReinstallInstance(instance["name"])) + + def TestRapiInstanceModify(instance): """Test modifying instance via RAPI""" def _ModifyInstance(**kwargs): @@ -492,6 +622,32 @@ def TestRapiInstanceModify(instance): }) +def TestRapiInstanceConsole(instance): + """Test getting instance console information via RAPI""" + result = _rapi_client.GetInstanceConsole(instance["name"]) + console = objects.InstanceConsole.FromDict(result) + AssertEqual(console.Validate(), True) + AssertEqual(console.instance, qa_utils.ResolveInstanceName(instance["name"])) + + +def TestRapiStoppedInstanceConsole(instance): + """Test getting stopped instance's console information via RAPI""" + try: + _rapi_client.GetInstanceConsole(instance["name"]) + except rapi.client.GanetiApiError, err: + AssertEqual(err.code, 503) + else: + raise qa_error.Error("Getting console for stopped instance didn't" + " return HTTP 503") + + +def GetOperatingSystems(): + """Retrieves a list of all available operating systems. + + """ + return _rapi_client.GetOperatingSystems() + + def TestInterClusterInstanceMove(src_instance, dest_instance, pnode, snode, tnode): """Test tools/move-instance"""