Skip to content
This repository has been archived by the owner on Jul 16, 2023. It is now read-only.

Commit

Permalink
added api versioning
Browse files Browse the repository at this point in the history
  • Loading branch information
aibor committed Jun 2, 2015
1 parent 47c1f54 commit 512a4a3
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 47 deletions.
83 changes: 72 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ Or with gunicorn:

List all currently set entries:

curl -u admin:secret http://localhost:5000/pxe
curl -u admin:secret http://localhost:5000/v1/pxe
# [
# {
# "ip_address": "1.2.3.4",
Expand All @@ -119,7 +119,7 @@ password is given, a random password is generated and returned. Takes
JSON Input as well:

curl -u admin:secret --data 'ip_address=10.10.1.1&label=rescue&password=SeCrEt' \
http://localhost:5000/pxe
http://localhost:5000/v1/pxe
# 201 on success
# {
# "ip_address": "10.10.1.1",
Expand All @@ -131,7 +131,7 @@ JSON Input as well:

Check if there is an entry currently set:

curl -u admin:secret http://localhost:5000/pxe/10.10.1.1
curl -u admin:secret http://localhost:5000/v1/pxe/10.10.1.1
# 200 if found
# {
# "ip_address": "10.10.1.1",
Expand All @@ -142,7 +142,7 @@ Check if there is an entry currently set:

Destroy an entry:

curl -u admin:secret -X DELETE http://localhost:5000/pxe/10.10.1.1
curl -u admin:secret -X DELETE http://localhost:5000/v1/pxe/10.10.1.1
# 204 on success


Expand All @@ -152,7 +152,7 @@ Create a new VM:

curl -u admin:secret \
-d 'name=testvm&user=testuser&ip_address=10.10.1.1&memory=1G&disk=10G' \
http://localhost:5000/vm
http://localhost:5000/v1/vm
# 201 on success
# {
# "disks": [
Expand Down Expand Up @@ -182,7 +182,12 @@ Create a new VM:
# },
# "user": "testuser",
# "uuid": "cd412122-ec04-46d7-ba12-a7757aa5af11",
# "vcpu": "1"
# "vcpu": "1",
# "vnc_data": {
# "vnc_port": 5900,
# "ws_port": 5700,
# "password": "gferhhpehrehjrekhtngfmbfdkbkre"
# }
# }
#
# 422 if there is an error
Expand All @@ -191,7 +196,7 @@ Create a new VM:

List all currently defined VMs:

curl -u admin:secret http://localhost:5000/vm
curl -u admin:secret http://localhost:5000/v1/vm
# [
# {
# "disks": [
Expand Down Expand Up @@ -221,14 +226,19 @@ List all currently defined VMs:
# },
# "user": "testuser",
# "uuid": "cd412122-ec04-46d7-ba12-a7757aa5af11",
# "vcpu": "1"
# "vcpu": "1",
# "vnc_data": {
# "vnc_port": 5900,
# "ws_port": 5700,
# "password": "gferhhpehrehjrekhtngfmbfdkbkre"
# }
# }
# ]


Get info for a specific VM:

curl -u admin:secret http://localhost:5000/vm/cd412122-ec04-46d7-ba12-a7757aa5af11
curl -u admin:secret http://localhost:5000/v1/vm/cd412122-ec04-46d7-ba12-a7757aa5af11
# 200 on success
# {
# "disks": [
Expand Down Expand Up @@ -258,16 +268,67 @@ Get info for a specific VM:
# },
# "user": "testuser",
# "uuid": "cd412122-ec04-46d7-ba12-a7757aa5af11",
# "vcpu": "1"
# "vcpu": "1",
# "vnc_data": {
# "vnc_port": 5900,
# "ws_port": 5700,
# "password": "gferhhpehrehjrekhtngfmbfdkbkre"
# }
# }
#
# 404 if the uuid doesn't exist


Update parameters of a VM:

curl -u admin:secret -X PUT -d 'memory=3 GiB&cpu=2&password=sEcReT' \
http://localhost:5000/v1/vm/cd412122-ec04-46d7-ba12-a7757aa5af11

# 200 on success
# {
# "disks": [
# {
# "bus": "virtio",
# "capacity": "10 GiB",
# "device": "disk",
# "path": "/mnt/data/test-pool/testuser_testvm",
# "target": "hda",
# "type": "block"
# }
# ],
# "interfaces": [
# {
# "ip_address": "10.10.1.1",
# "mac_address": "52:54:00:47:b0:09",
# "model": "virtio",
# "network": "default",
# "type": "network"
# }
# ],
# "memory": "3 GiB",
# "name": "test",
# "state": {
# "reason": "unknown",
# "state": "shutoff"
# },
# "user": "testuser",
# "uuid": "cd412122-ec04-46d7-ba12-a7757aa5af11",
# "vcpu": "2",
# "vnc_data": {
# "vnc_port": 5900,
# "ws_port": 5700,
# "password": "sEcReT"
# }
# }
#
# 404 if the uuid doesn't exist
# 422 if input values are not processable


Remove a VM:

curl -u admin:secret -X DELETE \
http://localhost:5000/vm/cd412122-ec04-46d7-ba12-a7757aa5af11
http://localhost:5000/v1/vm/cd412122-ec04-46d7-ba12-a7757aa5af11
# 204 on success


Expand Down
34 changes: 27 additions & 7 deletions marmoset/virt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from .network import Network
from .storage import Storage
from pprint import pprint
import uuid


def create(args):
Expand All @@ -12,20 +13,25 @@ def create(args):
name = "{}_{}".format(args['user'], args['name'])
storage = Storage.find_by('name', Storage.DEFAULT)
disk = storage.create_volume(name, args['disk'])
memory, unit = base.parse_unit(args['memory'])

domain = Domain.create(
domain = Domain.define(
uuid = str(uuid.uuid4()),
name = args['name'],
user = args['user'],
memory = base.parse_unit(args['memory'])[0],
unit = base.parse_unit(args['memory'])[1],
memory = memory,
unit = unit,
vcpu = args['cpu'],
disks = [dict(path = disk.path, bus = 'virtio', target = 'hda')],
interfaces = [dict(model = 'virtio', network = Network.DEFAULT)])
interfaces = [dict(model = 'virtio', network = Network.DEFAULT)],
password = args.get('password', base.generate_password)
)

network.add_host(
domain.interfaces[0].mac_address,
args['ip_address'],
name)
name
)

return domain

Expand All @@ -35,8 +41,22 @@ def list(args):
pprint(domain.attributes())


def edit(args):
domain = Domain.find_by('uuid', args['uuid'])
def edit(domain, args):
memory, unit = base.parse_unit(args.get('memory', domain.memory))
return Domain.define(
name = domain.name,
user = domain.user,
memory = memory,
unit = unit,
vcpu = args.get('cpu', domain.vcpu),
disks = [d.attributes() for d in domain.disks],
interfaces = [i.attributes() for i in domain.interfaces],
password = args.get(
'password',
domain.vnc_data.get('password', base.generate_password())
),
uuid = domain.uuid
)


def remove(args):
Expand Down
17 changes: 13 additions & 4 deletions marmoset/virt/base.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from contextlib import contextmanager, closing
from functools import wraps
from os import path
from os import path, urandom
from re import match
import libvirt
import libvirt, base64
from .exceptions import Error
import xml.etree.ElementTree as ET
from string import Template
Expand All @@ -26,8 +26,12 @@ def with_unit(value):
"""
units = ['b', 'KiB', 'MiB', 'GiB', 'TiB']
for unit in units:
if value < 1024 or unit == units[-1]: break
value = value / 1024
if value < 1024 or unit == units[-1]:
break
elif value < 1024**2 and value % 1024 != 0:
break
else:
value = value / 1024
return "%d %s" % (value, unit)

def parse_unit(obj):
Expand All @@ -40,10 +44,15 @@ def parse_unit(obj):
m = match('^(\d+) *(\w+)?$', obj)
if m:
value, unit = m.groups()
else:
raise Exception('invalid string given to unit parser')
else:
value, unit = obj, None
return int(value), (unit if unit else 'b')

def generate_password(length = 32):
return base64.b64encode(urandom(length)).decode()[:length]


class Virt:

Expand Down
2 changes: 1 addition & 1 deletion marmoset/virt/domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class Domain(base.Parent):
)

@classmethod
def create(cls, **attrs):
def define(cls, **attrs):
for klass in 'Disk', 'Interface':
key = klass.lower() + 's'
klass = getattr(cls, klass)
Expand Down
3 changes: 2 additions & 1 deletion marmoset/virt/templates/domain.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<domain type='kvm'>
<name>${user}_${name}</name>
<uuid>${uuid}</uuid>
<metadata>
<marmoset>
<user>${user}</user>
Expand Down Expand Up @@ -42,6 +43,6 @@
<input type='tablet' bus='usb'>
<alias name='input0'/>
</input>
<graphics type='vnc' port='-1' websocket='-1' keymap='de'/>
<graphics type='vnc' port='-1' websocket='-1' passwd='${password}' keymap='de'/>
</devices>
</domain>
6 changes: 5 additions & 1 deletion marmoset/webserver/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from flask.ext import restful
from .flask import auth

API_VERSION = '1'
config = None

def jsonify_nl(*args, **kwargs):
Expand All @@ -18,7 +19,10 @@ def app(config):
auth.for_all_routes(app)
app.config['SERVER_NAME'] = config['Webserver'].get('ServerName')

api = restful.Api(app)
api = restful.Api(
app = app,
prefix = '/v{}'.format(API_VERSION)
)

if config['Modules'].getboolean('PXE'):
from . import pxe
Expand Down
54 changes: 32 additions & 22 deletions marmoset/webserver/vm.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,6 @@
from .. import virt


parser = reqparse.RequestParser()
parser.add_argument('user', type=str, required=True)
parser.add_argument('name', type=str, required=True)
parser.add_argument('memory', type=str, required=True)
parser.add_argument('cpu', type=int, default=1)
parser.add_argument('disk', type=str, required=True)
parser.add_argument('ip_address', type=str, required=True)

command_parser = reqparse.RequestParser()
command_parser.add_argument('command', type=str, required=True,
choices=['start', 'stop', 'shutdown', 'reset'])
command_parser.add_argument('params', type=str, action='append', default=[])


def find_domain(uuid):
domain = virt.Domain.find_by('uuid', uuid)
if domain is None:
Expand All @@ -33,20 +19,41 @@ def get(self):
return [d.attributes() for d in domains]

def post(self):
parser = reqparse.RequestParser()
parser.add_argument('user', type=str, required=True)
parser.add_argument('name', type=str, required=True)
parser.add_argument('memory', type=str, required=True)
parser.add_argument('cpu', type=int, default=1)
parser.add_argument('disk', type=str, required=True)
parser.add_argument('ip_address', type=str, required=True)
parser.add_argument('password', type=str, default=None)
args = parser.parse_args()
#try:
return virt.create(args).attributes()
#except Exception as e:
# abort(422, message = str(e))
try:
domain = virt.create(args)
return domain.attributes()
except Exception as e:
abort(422, message = str(e))


class VMObject(Resource):

def get(self, uuid):
return find_domain(uuid).attributes()
domain = find_domain(uuid)
return domain.attributes()

def put(self, uuid):
pass
domain = find_domain(uuid)
parser = reqparse.RequestParser()
parser.add_argument('memory', type=str, store_missing=False)
parser.add_argument('cpu', type=int, store_missing=False)
parser.add_argument('password', type=str, store_missing=False)
args = parser.parse_args()
try:
domain = virt.edit(domain, args)
return domain.attributes()
except Exception as e:
abort(422, message = str(e))


def delete(self, uuid):
try:
Expand All @@ -59,8 +66,11 @@ def delete(self, uuid):
class VMCommand(Resource):

def put(self, uuid):
args = command_parser.parse_args()
print(args)
parser = reqparse.RequestParser()
parser.add_argument('command', type=str, required=True,
choices=['start', 'stop', 'shutdown', 'reset'])
parser.add_argument('params', type=str, action='append', default=[])
args = parser.parse_args()
domain = find_domain(uuid)
try:
res = getattr(domain, args.command)(*args.params)
Expand Down

0 comments on commit 512a4a3

Please sign in to comment.