api: add serial console API calls v2
Adds a new REST APIv2 to call service serial console Co-Authored-By: Ian Wells <iawells@cisco.com> Co-Authored-By: Sushma Korati <sushma_korati@persistent.co.in> Co-Authored-By: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@redhat.com> Patial-Implements: blueprint serial-ports Change-Id: I35d94c1924caa9cbc0fcdd9c637d28e95ff31ab2
This commit is contained in:
parent
9364cdaa3e
commit
e89eaf9a7d
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"os-getSerialConsole": {
|
||||
"type": "serial"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<os-getSerialConsole type="serial" />
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"console": {
|
||||
"type": "serial",
|
||||
"url":"http://127.0.0.1:6083/?token=f9906a48-b71e-4f18-baca-c987da3ebdb3"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<console>
|
||||
<type>serial</type>
|
||||
<url>http://127.0.0.1:6083/?token=f9906a48-b71e-4f18-baca-c987da3ebdb3</url>
|
||||
</console>
|
|
@ -107,6 +107,30 @@ class ConsolesController(wsgi.Controller):
|
|||
|
||||
return {'console': {'type': console_type, 'url': output['url']}}
|
||||
|
||||
@wsgi.action('os-getSerialConsole')
|
||||
def get_serial_console(self, req, id, body):
|
||||
"""Get connection to a serial console."""
|
||||
context = req.environ['nova.context']
|
||||
authorize(context)
|
||||
|
||||
# If type is not supplied or unknown get_serial_console below will cope
|
||||
console_type = body['os-getSerialConsole'].get('type')
|
||||
try:
|
||||
instance = self.compute_api.get(context, id, want_objects=True)
|
||||
output = self.compute_api.get_serial_console(context,
|
||||
instance,
|
||||
console_type)
|
||||
except exception.InstanceNotFound as e:
|
||||
raise webob.exc.HTTPNotFound(explanation=e.format_message())
|
||||
except exception.InstanceNotReady as e:
|
||||
raise webob.exc.HTTPConflict(explanation=e.format_message())
|
||||
except NotImplementedError:
|
||||
msg = _("Unable to get serial console, "
|
||||
"functionality not implemented")
|
||||
raise webob.exc.HTTPNotImplemented(explanation=msg)
|
||||
|
||||
return {'console': {'type': console_type, 'url': output['url']}}
|
||||
|
||||
|
||||
class Consoles(extensions.ExtensionDescriptor):
|
||||
"""Interactive Console support."""
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
import webob
|
||||
|
||||
from nova.compute import api as compute_api
|
||||
|
@ -34,6 +35,10 @@ def fake_get_rdp_console(self, _context, _instance, _console_type):
|
|||
return {'url': 'http://fake'}
|
||||
|
||||
|
||||
def fake_get_serial_console(self, _context, _instance, _console_type):
|
||||
return {'url': 'http://fake'}
|
||||
|
||||
|
||||
def fake_get_vnc_console_invalid_type(self, _context,
|
||||
_instance, _console_type):
|
||||
raise exception.ConsoleTypeInvalid(console_type=_console_type)
|
||||
|
@ -113,6 +118,8 @@ class ConsolesExtensionTestV21(test.NoDBTestCase):
|
|||
fake_get_spice_console)
|
||||
self.stubs.Set(compute_api.API, 'get_rdp_console',
|
||||
fake_get_rdp_console)
|
||||
self.stubs.Set(compute_api.API, 'get_serial_console',
|
||||
fake_get_serial_console)
|
||||
self.stubs.Set(compute_api.API, 'get', fake_get)
|
||||
self._setup_wsgi()
|
||||
|
||||
|
@ -443,3 +450,139 @@ class ConsolesExtensionTestV2(ConsolesExtensionTestV21):
|
|||
|
||||
def test_get_rdp_console_with_undefined_param(self):
|
||||
pass
|
||||
|
||||
def test_get_serial_console(self):
|
||||
body = {'os-getSerialConsole': {'type': 'serial'}}
|
||||
req = webob.Request.blank(self.url)
|
||||
req.method = "POST"
|
||||
req.body = jsonutils.dumps(body)
|
||||
req.headers["content-type"] = "application/json"
|
||||
|
||||
res = req.get_response(self.app)
|
||||
output = jsonutils.loads(res.body)
|
||||
self.assertEqual(200, res.status_int)
|
||||
self.assertEqual({u'console': {u'url': u'http://fake',
|
||||
u'type': u'serial'}},
|
||||
output)
|
||||
|
||||
@mock.patch.object(compute_api.API, 'get_serial_console')
|
||||
def test_get_serial_console_not_enable(self, get_serial_console):
|
||||
get_serial_console.side_effect = exception.ConsoleTypeUnavailable(
|
||||
console_type="serial")
|
||||
|
||||
body = {'os-getSerialConsole': {'type': 'serial'}}
|
||||
req = webob.Request.blank(self.url)
|
||||
req.method = "POST"
|
||||
req.body = jsonutils.dumps(body)
|
||||
req.headers["content-type"] = "application/json"
|
||||
|
||||
res = req.get_response(self.app)
|
||||
self.assertEqual(res.status_int, 400)
|
||||
self.assertTrue(get_serial_console.called)
|
||||
|
||||
@mock.patch.object(compute_api.API, 'get_serial_console')
|
||||
def test_get_serial_console_invalid_type(self, get_serial_console):
|
||||
get_serial_console.side_effect = (
|
||||
exception.ConsoleTypeInvalid(console_type='invalid'))
|
||||
|
||||
body = {'os-getSerialConsole': {'type': 'invalid'}}
|
||||
req = webob.Request.blank(self.url)
|
||||
req.method = "POST"
|
||||
req.body = jsonutils.dumps(body)
|
||||
req.headers["content-type"] = "application/json"
|
||||
|
||||
res = req.get_response(self.app)
|
||||
self.assertEqual(res.status_int, 400)
|
||||
self.assertTrue(get_serial_console.called)
|
||||
|
||||
@mock.patch.object(compute_api.API, 'get_serial_console')
|
||||
def test_get_serial_console_no_type(self, get_serial_console):
|
||||
get_serial_console.side_effect = (
|
||||
exception.ConsoleTypeInvalid(console_type=''))
|
||||
|
||||
body = {'os-getSerialConsole': {}}
|
||||
req = webob.Request.blank(self.url)
|
||||
req.method = "POST"
|
||||
req.body = jsonutils.dumps(body)
|
||||
req.headers["content-type"] = "application/json"
|
||||
|
||||
res = req.get_response(self.app)
|
||||
self.assertEqual(res.status_int, 400)
|
||||
self.assertTrue(get_serial_console.called)
|
||||
|
||||
@mock.patch.object(compute_api.API, 'get_serial_console')
|
||||
def test_get_serial_console_no_instance(self, get_serial_console):
|
||||
get_serial_console.side_effect = (
|
||||
exception.InstanceNotFound(instance_id='xxx'))
|
||||
|
||||
body = {'os-getSerialConsole': {'type': 'serial'}}
|
||||
req = webob.Request.blank(self.url)
|
||||
req.method = "POST"
|
||||
req.body = jsonutils.dumps(body)
|
||||
req.headers["content-type"] = "application/json"
|
||||
|
||||
res = req.get_response(self.app)
|
||||
self.assertEqual(res.status_int, 404)
|
||||
self.assertTrue(get_serial_console.called)
|
||||
|
||||
@mock.patch.object(compute_api.API, 'get_serial_console')
|
||||
def test_get_serial_console_instance_not_ready(self, get_serial_console):
|
||||
get_serial_console.side_effect = (
|
||||
exception.InstanceNotReady(instance_id='xxx'))
|
||||
|
||||
body = {'os-getSerialConsole': {'type': 'serial'}}
|
||||
req = webob.Request.blank(self.url)
|
||||
req.method = "POST"
|
||||
req.body = jsonutils.dumps(body)
|
||||
req.headers["content-type"] = "application/json"
|
||||
|
||||
res = req.get_response(self.app)
|
||||
self.assertEqual(res.status_int, 409)
|
||||
self.assertTrue(get_serial_console.called)
|
||||
|
||||
@mock.patch.object(compute_api.API, 'get_serial_console')
|
||||
def test_get_serial_console_socket_exhausted(self, get_serial_console):
|
||||
get_serial_console.side_effect = (
|
||||
exception.SocketPortRangeExhaustedException(
|
||||
host='127.0.0.1'))
|
||||
|
||||
body = {'os-getSerialConsole': {'type': 'serial'}}
|
||||
req = webob.Request.blank(self.url)
|
||||
req.method = "POST"
|
||||
req.body = jsonutils.dumps(body)
|
||||
req.headers["content-type"] = "application/json"
|
||||
|
||||
res = req.get_response(self.app)
|
||||
self.assertEqual(res.status_int, 500)
|
||||
self.assertTrue(get_serial_console.called)
|
||||
|
||||
@mock.patch.object(compute_api.API, 'get_serial_console')
|
||||
def test_get_serial_console_image_nport_invalid(self, get_serial_console):
|
||||
get_serial_console.side_effect = (
|
||||
exception.ImageSerialPortNumberInvalid(
|
||||
num_ports='x', property="hw_serial_port_count"))
|
||||
|
||||
body = {'os-getSerialConsole': {'type': 'serial'}}
|
||||
req = webob.Request.blank(self.url)
|
||||
req.method = "POST"
|
||||
req.body = jsonutils.dumps(body)
|
||||
req.headers["content-type"] = "application/json"
|
||||
|
||||
res = req.get_response(self.app)
|
||||
self.assertEqual(res.status_int, 400)
|
||||
self.assertTrue(get_serial_console.called)
|
||||
|
||||
@mock.patch.object(compute_api.API, 'get_serial_console')
|
||||
def test_get_serial_console_image_nport_exceed(self, get_serial_console):
|
||||
get_serial_console.side_effect = (
|
||||
exception.ImageSerialPortNumberExceedFlavorValue())
|
||||
|
||||
body = {'os-getSerialConsole': {'type': 'serial'}}
|
||||
req = webob.Request.blank(self.url)
|
||||
req.method = "POST"
|
||||
req.body = jsonutils.dumps(body)
|
||||
req.headers["content-type"] = "application/json"
|
||||
|
||||
res = req.get_response(self.app)
|
||||
self.assertEqual(res.status_int, 400)
|
||||
self.assertTrue(get_serial_console.called)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"os-getSerialConsole": {
|
||||
"type": "serial"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<os-getSerialConsole>
|
||||
<type>serial</type>
|
||||
</os-getSerialConsole>
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"console": {
|
||||
"type": "serial",
|
||||
"url":"%(url)s"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<console>
|
||||
<type>serial</type>
|
||||
<url>%(url)s</url>
|
||||
</console>
|
|
@ -2086,6 +2086,7 @@ class ConsolesSampleJsonTests(ServersSampleBase):
|
|||
self.flags(vnc_enabled=True)
|
||||
self.flags(enabled=True, group='spice')
|
||||
self.flags(enabled=True, group='rdp')
|
||||
self.flags(enabled=True, group='serial_console')
|
||||
|
||||
def test_get_vnc_console(self):
|
||||
uuid = self._post_server()
|
||||
|
@ -2119,6 +2120,17 @@ class ConsolesSampleJsonTests(ServersSampleBase):
|
|||
self._verify_response('get-rdp-console-post-resp', subs,
|
||||
response, 200)
|
||||
|
||||
def test_get_serial_console(self):
|
||||
uuid = self._post_server()
|
||||
response = self._do_post('servers/%s/action' % uuid,
|
||||
'get-serial-console-post-req',
|
||||
{'action': 'os-getSerialConsole'})
|
||||
subs = self._get_regexes()
|
||||
subs["url"] = \
|
||||
"((https?):((//)|(\\\\))+([\w\d:#@%/;$()~_?\+-=\\\.&](#!)?)*)"
|
||||
self._verify_response('get-serial-console-post-resp', subs,
|
||||
response, 200)
|
||||
|
||||
|
||||
class ConsolesSampleXmlTests(ConsolesSampleJsonTests):
|
||||
ctype = 'xml'
|
||||
|
|
Loading…
Reference in New Issue