proxmaster/proxmaster.py

261 lines
7.7 KiB
Python
Raw Normal View History

2016-02-15 05:30:43 -05:00
#. -*- coding: utf-8 -
# required proxmox permissions: PVESysAdmin, PVEVMAdmin
#
# afx 2015-2016
# import site packages
import logging
import falcon
import sys
import json
#import local packages
import ioconfig
import grid
import plugin
config = ioconfig.parser
logger = ioconfig.logger
2016-04-01 21:29:22 -04:00
2016-02-15 05:30:43 -05:00
def welcome():
"""displays motd in log as welcome message"""
logger.info('# proxmaster ][ (c) 2015-2016 afx #')
2016-04-01 21:29:22 -04:00
2016-04-09 18:53:15 -04:00
def selector(fn, req, vmid=0):
2016-04-09 23:37:32 -04:00
""" try to exec commands """
2016-04-09 18:53:15 -04:00
json = req.context['doc']
2016-10-17 05:10:41 -04:00
#print(json)
2016-04-09 18:53:15 -04:00
apipass = json['apikey']
if apipass != config.get('general', 'apipass'):
2016-04-11 07:54:34 -04:00
status = falcon.HTTP_403
body = falcon.HTTP_403
2016-04-09 18:53:15 -04:00
logger.error('grid> access denied. bad api key!')
2016-04-11 07:54:34 -04:00
return status, body
2016-04-09 18:53:15 -04:00
try:
2016-11-03 00:05:51 -04:00
if fn == 'vmcreate':
2016-04-09 23:37:32 -04:00
body = plugin.vmcreate(json)
2016-06-25 11:27:45 -04:00
elif fn == 'vmstatus':
2016-04-09 23:37:32 -04:00
body = plugin.vmstatus(vmid)
2016-06-25 11:27:45 -04:00
elif fn == 'vmdelete':
2016-04-09 23:37:32 -04:00
body = plugin.vmdelete(vmid)
2016-06-25 11:27:45 -04:00
elif fn == 'vmsuspend':
2016-04-09 23:37:32 -04:00
body = plugin.vmsuspend(vmid)
2016-06-25 11:27:45 -04:00
elif fn == 'vmresume':
2016-04-09 23:37:32 -04:00
body = plugin.vmresume(vmid)
2016-06-25 11:27:45 -04:00
elif fn == 'vmstart':
2016-04-09 23:37:32 -04:00
body = plugin.vmstart(vmid)
2016-06-25 11:27:45 -04:00
elif fn == 'vmshutdown':
2016-04-09 23:37:32 -04:00
body = plugin.vmshutdown(vmid)
2016-06-25 11:27:45 -04:00
elif fn == 'vmstop':
2016-04-09 23:37:32 -04:00
body = plugin.vmstop(vmid)
2016-06-26 11:09:22 -04:00
elif fn == 'vmrrd':
body = plugin.vmrrd(vmid)
2016-06-25 11:27:45 -04:00
elif fn == 'vmvnc':
2016-04-09 23:37:32 -04:00
body = plugin.vmvnc(vmid)
2016-04-09 18:53:15 -04:00
except:
2016-05-22 18:55:56 -04:00
logger.critical('grid> {} error'.format(fn))
status = falcon.HTTP_404
2016-04-09 23:37:32 -04:00
raise
2016-04-09 18:53:15 -04:00
else:
2016-05-22 18:55:56 -04:00
#logger.info('grid> {} ok'.format(fn))
2016-04-09 18:53:15 -04:00
status = falcon.HTTP_202
return status, body
2016-04-08 10:48:18 -04:00
class RequireJSON(object):
def process_request(self, req, resp):
if not req.client_accepts_json:
raise falcon.HTTPNotAcceptable(
'This API only supports responses encoded as JSON.',
href='http://docs.examples.com/api/json')
if req.method in ('POST', 'PUT'):
if 'application/json' not in req.content_type:
raise falcon.HTTPUnsupportedMediaType(
'This API only supports requests encoded as JSON.',
href='http://docs.examples.com/api/json')
class JSONTranslator(object):
def process_request(self, req, resp):
# req.stream corresponds to the WSGI wsgi.input environ variable,
# and allows you to read bytes from the request body.
#
# See also: PEP 3333
if req.content_length in (None, 0):
# Nothing to do
return
body = req.stream.read()
if not body:
raise falcon.HTTPBadRequest('Empty request body',
'A valid JSON document is required.')
try:
req.context['doc'] = json.loads(body.decode('utf-8'))
except (ValueError, UnicodeDecodeError):
2016-04-09 23:37:32 -04:00
raise falcon.HTTPError(falcon.HTTP_400,
2016-04-08 10:48:18 -04:00
'Malformed JSON',
'Could not decode the request body. The '
'JSON was incorrect or not encoded as '
'UTF-8.')
def process_response(self, req, resp, resource):
if 'result' not in req.context:
return
resp.body = json.dumps(req.context['result'])
def max_body(limit):
def hook(req, resp, resource, params):
length = req.content_length
if length is not None and length > limit:
msg = ('The size of the request is too large. The body must not '
'exceed ' + str(limit) + ' bytes in length.')
raise falcon.HTTPRequestEntityTooLarge(
'Request body is too large', msg)
return hook
2016-04-09 23:37:32 -04:00
class CreateResource(object):
2016-04-08 21:10:07 -04:00
@falcon.before(max_body(64 * 1024))
2016-02-15 05:30:43 -05:00
def on_post(self, req, resp):
"""Create a cluster node, returns array of: status, vmid, pass, ipv4, """
logger.info('grid> create ' + str(req.params))
2016-06-25 12:07:27 -04:00
resp.status, response = selector('vmcreate', req)
2016-04-09 18:53:15 -04:00
req.context['result'] = response
2016-04-01 21:29:22 -04:00
2016-02-15 05:30:43 -05:00
class StatusResource(object):
2016-04-09 18:53:15 -04:00
@falcon.before(max_body(64 * 1024))
def on_post(self, req, resp, vmid):
2016-02-15 05:30:43 -05:00
""" check vm status """
logger.info('grid> status ' + str(vmid))
2016-06-25 12:07:27 -04:00
resp.status, response = selector('vmstatus', req, vmid)
2016-04-09 18:53:15 -04:00
req.context['result'] = response
2016-03-07 12:25:13 -05:00
2016-02-15 05:30:43 -05:00
class DeleteResource(object):
2016-04-08 21:10:07 -04:00
@falcon.before(max_body(64 * 1024))
2016-02-15 05:30:43 -05:00
def on_post(self, req, resp, vmid):
""" delete machine completely"""
logger.info('grid> delete ' + str(vmid))
2016-06-25 12:07:27 -04:00
resp.status, response = selector('vmdelete', req, vmid)
2016-04-09 18:53:15 -04:00
req.context['result'] = response
2016-04-01 21:29:22 -04:00
2016-04-09 23:37:32 -04:00
class SuspendResource(object):
2016-04-08 21:10:07 -04:00
@falcon.before(max_body(64 * 1024))
2016-02-15 05:30:43 -05:00
def on_post(self, req, resp, vmid):
""" Temporary suspend the instance """
logger.info('grid> suspend ' + str(vmid))
2016-06-25 12:07:27 -04:00
resp.status, response = selector('vmsuspend', req, vmid)
2016-04-09 18:53:15 -04:00
req.context['result'] = response
2016-04-01 21:29:22 -04:00
2016-04-09 23:37:32 -04:00
class ResumeResource(object):
2016-04-08 21:10:07 -04:00
@falcon.before(max_body(64 * 1024))
2016-02-15 05:30:43 -05:00
def on_post(self, req, resp, vmid):
""" Unuspend the instance """
logger.info('grid> resume ' + str(vmid))
2016-06-25 12:07:27 -04:00
resp.status, response = selector('vmresume', req, vmid)
2016-04-09 18:53:15 -04:00
req.context['result'] = response
2016-04-01 21:29:22 -04:00
2016-02-15 05:30:43 -05:00
class StartResource(object):
2016-04-08 21:10:07 -04:00
@falcon.before(max_body(64 * 1024))
2016-02-15 05:30:43 -05:00
def on_post(self, req, resp, vmid):
""" Start the instance """
logger.info('grid> start ' + str(vmid))
2016-06-25 12:07:27 -04:00
resp.status, response = selector('vmstart', req, vmid)
2016-04-09 18:53:15 -04:00
req.context['result'] = response
2016-02-15 05:30:43 -05:00
class ShutdownResource(object):
2016-04-08 21:10:07 -04:00
@falcon.before(max_body(64 * 1024))
2016-02-15 05:30:43 -05:00
def on_post(self, req, resp, vmid):
""" ACPI Shutdown the instance """
logger.info('grid> shutdown ' + str(vmid))
2016-06-25 12:07:27 -04:00
resp.status, response = selector('vmshutdown', req, vmid)
2016-04-09 18:53:15 -04:00
req.context['result'] = response
2016-02-15 05:30:43 -05:00
class StopResource(object):
2016-04-08 21:10:07 -04:00
@falcon.before(max_body(64 * 1024))
2016-02-15 05:30:43 -05:00
def on_post(self, req, resp, vmid):
""" Stop the instance """
logger.info('grid> stop ' + str(vmid))
2016-06-25 12:07:27 -04:00
resp.status, response = selector('vmstop', req, vmid)
2016-04-09 18:53:15 -04:00
req.context['result'] = response
2016-02-15 05:30:43 -05:00
2016-06-26 11:09:22 -04:00
class RRDResource(object):
@falcon.before(max_body(64 * 1024))
def on_post(self, req, resp, vmid):
""" Generate rrd pngs """
logger.info('grid> rrd ' + str(vmid))
resp.status, response = selector('vmrrd', req, vmid)
2016-06-26 11:54:27 -04:00
req.context['result'] = response
2016-06-26 11:09:22 -04:00
2016-02-15 05:30:43 -05:00
class VNCResource(object):
2016-04-08 21:10:07 -04:00
@falcon.before(max_body(64 * 1024))
2016-02-15 05:30:43 -05:00
def on_post(self, req, resp, vmid):
""" Create a VNC link to the instance """
logger.info('grid> vnc ' + str(vmid))
2016-06-25 12:07:27 -04:00
resp.status, response = selector('vmvnc', req, vmid)
2016-04-09 18:53:15 -04:00
req.context['result'] = response
2016-02-15 05:30:43 -05:00
if __name__ == '__main__':
sys.exit("invoke proxmaster via uwsgi. thanks. bye. o/")
2016-04-08 10:48:18 -04:00
wsgi_app = api = application = falcon.API(middleware=[
RequireJSON(),
JSONTranslator(),
])
2016-02-15 05:30:43 -05:00
# setup routes
2016-04-09 23:37:32 -04:00
res_create = CreateResource()
2016-06-25 12:07:27 -04:00
api.add_route('/vmcreate', res_create)
2016-02-15 05:30:43 -05:00
res_status = StatusResource()
2016-06-25 12:07:27 -04:00
api.add_route('/vmstatus/{vmid}', res_status)
2016-02-15 05:30:43 -05:00
res_delete = DeleteResource()
2016-06-25 12:07:27 -04:00
api.add_route('/vmdelete/{vmid}', res_delete)
2016-02-15 05:30:43 -05:00
2016-04-09 23:37:32 -04:00
res_suspend = SuspendResource()
2016-06-25 12:07:27 -04:00
api.add_route('/vmsuspend/{vmid}', res_suspend)
2016-02-15 05:30:43 -05:00
2016-04-09 23:37:32 -04:00
res_resume = ResumeResource()
2016-06-25 12:07:27 -04:00
api.add_route('/vmresume/{vmid}', res_resume)
2016-02-15 05:30:43 -05:00
res_start = StartResource()
2016-06-25 12:07:27 -04:00
api.add_route('/vmstart/{vmid}', res_start)
2016-02-15 05:30:43 -05:00
res_shutdown = ShutdownResource()
2016-06-25 12:07:27 -04:00
api.add_route('/vmshutdown/{vmid}', res_shutdown)
2016-02-15 05:30:43 -05:00
res_stop = StopResource()
2016-06-25 12:07:27 -04:00
api.add_route('/vmstop/{vmid}', res_stop)
2016-02-15 05:30:43 -05:00
2016-06-26 11:09:22 -04:00
res_rrd = RRDResource()
2016-06-26 11:54:27 -04:00
api.add_route('/vmrrd/{vmid}', res_rrd)
2016-06-26 11:09:22 -04:00
2016-02-15 05:30:43 -05:00
res_vnc = VNCResource()
2016-06-25 12:07:27 -04:00
api.add_route('/vmvnc/{vmid}', res_vnc)
2016-02-15 05:30:43 -05:00
2016-04-09 18:53:15 -04:00
#display motd
welcome()