Revision b82d4c5e

b/doc/rapi.rst
984 984
  Whether to force an unknown variant.
985 985

  
986 986

  
987
``/2/instances/[instance_name]/console``
988
++++++++++++++++++++++++++++++++++++++++
989

  
990
Request information for connecting to instance's console.
991

  
992
Supports the following commands: ``GET``.
993

  
994
``GET``
995
~~~~~~~
996

  
997
Returns a dictionary containing information about the instance's
998
console. Contained keys:
999

  
1000
``instance``
1001
  Instance name.
1002
``kind``
1003
  Console type, one of ``ssh``, ``vnc`` or ``msg``.
1004
``message``
1005
  Message to display (``msg`` type only).
1006
``host``
1007
  Host to connect to (``ssh`` and ``vnc`` only).
1008
``port``
1009
  TCP port to connect to (``vnc`` only).
1010
``user``
1011
  Username to use (``ssh`` only).
1012
``command``
1013
  Command to execute on machine (``ssh`` only)
1014
``display``
1015
  VNC display number (``vnc`` only).
1016

  
1017

  
987 1018
``/2/instances/[instance_name]/tags``
988 1019
+++++++++++++++++++++++++++++++++++++
989 1020

  
b/lib/rapi/client.py
1124 1124
                             ("/%s/instances/%s/rename" %
1125 1125
                              (GANETI_RAPI_VERSION, instance)), None, body)
1126 1126

  
1127
  def GetInstanceConsole(self, instance):
1128
    """Request information for connecting to instance's console.
1129

  
1130
    @type instance: string
1131
    @param instance: Instance name
1132

  
1133
    """
1134
    return self._SendRequest(HTTP_GET,
1135
                             ("/%s/instances/%s/console" %
1136
                              (GANETI_RAPI_VERSION, instance)), None, None)
1137

  
1127 1138
  def GetJobs(self):
1128 1139
    """Gets all jobs for the cluster.
1129 1140

  
b/lib/rapi/connector.py
217 217
    re.compile(r"^/2/instances/(%s)/disk/(%s)/grow$" %
218 218
               (instance_name_pattern, disk_pattern)):
219 219
      rlib2.R_2_instances_name_disk_grow,
220
    re.compile(r'^/2/instances/(%s)/console$' % instance_name_pattern):
221
      rlib2.R_2_instances_name_console,
220 222

  
221 223
    "/2/groups": rlib2.R_2_groups,
222 224
    re.compile(r'^/2/groups/(%s)$' % group_name_pattern):
b/lib/rapi/rlib2.py
1336 1336
    return baserlib.SubmitJob([op])
1337 1337

  
1338 1338

  
1339
class R_2_instances_name_console(baserlib.R_Generic):
1340
  """/2/instances/[instance_name]/console resource.
1341

  
1342
  """
1343
  GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
1344

  
1345
  def GET(self):
1346
    """Request information for connecting to instance's console.
1347

  
1348
    @return: Serialized instance console description, see
1349
             L{objects.InstanceConsole}
1350

  
1351
    """
1352
    client = baserlib.GetClient()
1353

  
1354
    ((console, ), ) = client.QueryInstances([self.items[0]], ["console"], False)
1355

  
1356
    if console is None:
1357
      raise http.HttpServiceUnavailable("Instance console unavailable")
1358

  
1359
    assert isinstance(console, dict)
1360
    return console
1361

  
1362

  
1339 1363
class _R_Tags(baserlib.R_Generic):
1340 1364
  """ Quasiclass for tagging resources
1341 1365

  
b/qa/ganeti-qa.py
196 196

  
197 197
  """
198 198
  RunTestIf("instance-shutdown", qa_instance.TestInstanceShutdown, instance)
199
  RunTestIf(["instance-shutdown", "instance-console", "rapi"],
200
            qa_rapi.TestRapiStoppedInstanceConsole, instance)
199 201
  RunTestIf("instance-shutdown", qa_instance.TestInstanceStartup, instance)
200 202

  
201 203
  RunTestIf("instance-list", qa_instance.TestInstanceList)
......
207 209
            qa_rapi.TestRapiInstanceModify, instance)
208 210

  
209 211
  RunTestIf("instance-console", qa_instance.TestInstanceConsole, instance)
212
  RunTestIf(["instance-console", "rapi"],
213
            qa_rapi.TestRapiInstanceConsole, instance)
210 214

  
211 215
  RunTestIf("instance-reinstall", qa_instance.TestInstanceShutdown, instance)
212 216
  RunTestIf("instance-reinstall", qa_instance.TestInstanceReinstall, instance)
b/qa/qa_rapi.py
29 29
from ganeti import errors
30 30
from ganeti import cli
31 31
from ganeti import rapi
32
from ganeti import objects
32 33

  
33 34
import ganeti.rapi.client        # pylint: disable-msg=W0611
34 35
import ganeti.rapi.client_utils
......
492 493
    })
493 494

  
494 495

  
496
def TestRapiInstanceConsole(instance):
497
  """Test getting instance console information via RAPI"""
498
  result = _rapi_client.GetInstanceConsole(instance["name"])
499
  console = objects.InstanceConsole.FromDict(result)
500
  AssertEqual(console.Validate(), True)
501
  AssertEqual(console.instance, qa_utils.ResolveInstanceName(instance["name"]))
502

  
503

  
504
def TestRapiStoppedInstanceConsole(instance):
505
  """Test getting stopped instance's console information via RAPI"""
506
  try:
507
    _rapi_client.GetInstanceConsole(instance["name"])
508
  except rapi.client.GanetiApiError, err:
509
    AssertEqual(err.code, 503)
510
  else:
511
    raise qa_error.Error("Getting console for stopped instance didn't"
512
                         " return HTTP 503")
513

  
514

  
495 515
def TestInterClusterInstanceMove(src_instance, dest_instance,
496 516
                                 pnode, snode, tnode):
497 517
  """Test tools/move-instance"""
b/test/ganeti.rapi.client_unittest.py
1123 1123
    self.assertHandler(rlib2.R_2_instances_name_deactivate_disks)
1124 1124
    self.assertFalse(self.rapi.GetLastHandler().queryargs)
1125 1125

  
1126
  def testGetInstanceConsole(self):
1127
    self.rapi.AddResponse("26876")
1128
    job_id = self.client.GetInstanceConsole("inst21491")
1129
    self.assertEqual(job_id, 26876)
1130
    self.assertItems(["inst21491"])
1131
    self.assertHandler(rlib2.R_2_instances_name_console)
1132
    self.assertFalse(self.rapi.GetLastHandler().queryargs)
1133
    self.assertFalse(self.rapi.GetLastRequestData())
1134

  
1126 1135
  def testGrowInstanceDisk(self):
1127 1136
    for idx, wait_for_sync in enumerate([None, False, True]):
1128 1137
      amount = 128 + (512 * idx)
b/test/ganeti.rapi.rlib2_unittest.py
31 31
from ganeti import opcodes
32 32
from ganeti import compat
33 33
from ganeti import http
34
from ganeti import query
34 35

  
35 36
from ganeti.rapi import rlib2
36 37

  
37 38
import testutils
38 39

  
39 40

  
41
class TestConstants(unittest.TestCase):
42
  def testConsole(self):
43
    # Exporting the console field without authentication might expose
44
    # information
45
    assert "console" in query.INSTANCE_FIELDS
46
    self.assertTrue("console" not in rlib2.I_FIELDS)
47

  
48

  
40 49
class TestParseInstanceCreateRequestVersion1(testutils.GanetiTestCase):
41 50
  def setUp(self):
42 51
    testutils.GanetiTestCase.setUp(self)

Also available in: Unified diff