393 lines
11 KiB
Python
393 lines
11 KiB
Python
import os
|
|
|
|
import celery
|
|
from piston.handler import BaseHandler
|
|
from piston.utils import rc, validate
|
|
from django.core.exceptions import ObjectDoesNotExist
|
|
from django.conf import settings
|
|
|
|
from nailgun.models import Cluster, Node, Recipe, Role, Release
|
|
from nailgun.api.validators import validate_json
|
|
from nailgun.api.forms import ClusterForm, RecipeForm, RoleForm, \
|
|
NodeCreationForm, NodeForm, ReleaseCreationForm
|
|
from nailgun.tasks import deploy_cluster
|
|
|
|
|
|
class JSONHandler(BaseHandler):
|
|
"""
|
|
Basic JSON handler
|
|
"""
|
|
fields = None
|
|
special_fields = None
|
|
|
|
@classmethod
|
|
def render(cls, item, fields=None):
|
|
json_data = {}
|
|
use_fields = fields if fields else cls.fields
|
|
if not use_fields:
|
|
raise ValueError("No fields for serialize")
|
|
for field in use_fields:
|
|
if cls is JSONHandler or cls.special_fields and \
|
|
field not in cls.special_fields:
|
|
json_data[field] = getattr(item, field)
|
|
return json_data
|
|
|
|
|
|
class TaskHandler(BaseHandler):
|
|
|
|
allowed_methods = ('GET',)
|
|
fields = ('task_id', 'status')
|
|
special_fields = ('result',)
|
|
|
|
@classmethod
|
|
def render(cls, task):
|
|
# TODO show meta?
|
|
json_data = {
|
|
"task_id": task.task_id,
|
|
"status": task.state,
|
|
}
|
|
|
|
json_data['results'] = [t.result for t in task.result.results]
|
|
|
|
return json_data
|
|
|
|
def read(self, request, task_id):
|
|
try:
|
|
task = celery.result.AsyncResult(task_id)
|
|
except:
|
|
return rc.NOT_FOUND
|
|
return TaskHandler.render(task)
|
|
|
|
|
|
class ConfigHandler(BaseHandler):
|
|
|
|
allowed_methods = ('POST',)
|
|
|
|
def create(self, request, cluster_id):
|
|
task = deploy_cluster.delay(cluster_id)
|
|
|
|
response = rc.ACCEPTED
|
|
response.content = TaskHandler.render(task)
|
|
return response
|
|
|
|
|
|
class ClusterCollectionHandler(BaseHandler):
|
|
|
|
allowed_methods = ('GET', 'POST')
|
|
model = Cluster
|
|
|
|
def read(self, request):
|
|
json_data = map(
|
|
ClusterHandler.render,
|
|
Cluster.objects.all()
|
|
)
|
|
return json_data
|
|
|
|
@validate_json(ClusterForm)
|
|
def create(self, request):
|
|
cluster = Cluster()
|
|
for key, value in request.form.cleaned_data.items():
|
|
if key in request.form.data:
|
|
setattr(cluster, key, value)
|
|
cluster.save()
|
|
|
|
return ClusterHandler.render(cluster)
|
|
|
|
|
|
class ClusterHandler(JSONHandler):
|
|
|
|
allowed_methods = ('GET', 'PUT')
|
|
model = Cluster
|
|
fields = ('id', 'name')
|
|
special_fields = ('nodes',)
|
|
|
|
@classmethod
|
|
def render(cls, cluster, fields=None):
|
|
json_data = JSONHandler.render(cluster, fields=fields or cls.fields)
|
|
for field in cls.special_fields:
|
|
if field in ('nodes',):
|
|
json_data[field] = map(
|
|
NodeHandler.render,
|
|
cluster.nodes.all()
|
|
)
|
|
return json_data
|
|
|
|
def read(self, request, cluster_id):
|
|
try:
|
|
cluster = Cluster.objects.get(id=cluster_id)
|
|
return ClusterHandler.render(cluster)
|
|
except ObjectDoesNotExist:
|
|
return rc.NOT_FOUND
|
|
|
|
@validate_json(ClusterForm)
|
|
def update(self, request, cluster_id):
|
|
try:
|
|
cluster = Cluster.objects.get(id=cluster_id)
|
|
for key, value in request.form.cleaned_data.items():
|
|
if key in request.form.data:
|
|
if key == 'nodes':
|
|
new_nodes = Node.objects.filter(id__in=value)
|
|
cluster.nodes.clear()
|
|
cluster.nodes.add(*new_nodes)
|
|
else:
|
|
setattr(cluster, key, value)
|
|
|
|
cluster.save()
|
|
return ClusterHandler.render(cluster)
|
|
except ObjectDoesNotExist:
|
|
return rc.NOT_FOUND
|
|
|
|
|
|
class NodeCollectionHandler(BaseHandler):
|
|
|
|
allowed_methods = ('GET', 'POST')
|
|
model = Node
|
|
|
|
@validate(NodeForm, 'GET')
|
|
def read(self, request):
|
|
nodes = Node.objects.all()
|
|
if 'cluster_id' in request.form.data:
|
|
nodes = nodes.filter(
|
|
cluster_id=request.form.cleaned_data['cluster_id'])
|
|
return map(NodeHandler.render, nodes)
|
|
|
|
@validate_json(NodeCreationForm)
|
|
def create(self, request):
|
|
node = Node()
|
|
for key, value in request.form.cleaned_data.items():
|
|
if key in request.form.data:
|
|
if key == 'roles':
|
|
new_roles = Role.objects.filter(id__in=value)
|
|
node.roles.clear()
|
|
node.roles.add(*new_roles)
|
|
else:
|
|
setattr(node, key, value)
|
|
|
|
node.save()
|
|
return NodeHandler.render(node)
|
|
|
|
|
|
class NodeHandler(JSONHandler):
|
|
|
|
allowed_methods = ('GET', 'PUT')
|
|
model = Node
|
|
fields = ('id', 'name', 'cluster_id', 'metadata',
|
|
'status', 'mac', 'fqdn', 'ip')
|
|
special_fields = ('roles',)
|
|
|
|
@classmethod
|
|
def render(cls, node, fields=None):
|
|
json_data = JSONHandler.render(node, fields=fields or cls.fields)
|
|
for field in cls.special_fields:
|
|
if field in ('roles',):
|
|
json_data[field] = map(
|
|
RoleHandler.render,
|
|
node.roles.all()
|
|
)
|
|
return json_data
|
|
|
|
def read(self, request, node_id):
|
|
try:
|
|
node = Node.objects.get(id=node_id)
|
|
return NodeHandler.render(node)
|
|
except ObjectDoesNotExist:
|
|
return rc.NOT_FOUND
|
|
|
|
@validate_json(NodeForm)
|
|
def update(self, request, node_id):
|
|
node, is_created = Node.objects.get_or_create(id=node_id)
|
|
for key, value in request.form.cleaned_data.items():
|
|
if key in request.form.data:
|
|
if key == 'cluster_id' and value is not None and \
|
|
node.cluster_id is not None:
|
|
response = rc.BAD_REQUEST
|
|
response.content = \
|
|
'Changing cluster is not allowed'
|
|
return response
|
|
elif key == 'roles':
|
|
new_roles = Role.objects.filter(id__in=value)
|
|
node.roles.clear()
|
|
node.roles.add(*new_roles)
|
|
else:
|
|
setattr(node, key, value)
|
|
|
|
node.save()
|
|
return NodeHandler.render(node)
|
|
|
|
|
|
class NodeRoleAvailable(BaseHandler):
|
|
|
|
allowed_methods = ('GET',)
|
|
model = Role
|
|
|
|
def read(self, request, node_id, role_id):
|
|
# TODO: it's a stub!
|
|
return {'available': True, 'error': None}
|
|
|
|
|
|
class RecipeCollectionHandler(BaseHandler):
|
|
|
|
allowed_methods = ('GET', 'POST')
|
|
model = Recipe
|
|
|
|
def read(self, request):
|
|
return map(
|
|
RecipeHandler.render,
|
|
Recipe.objects.all()
|
|
)
|
|
|
|
@validate_json(RecipeForm)
|
|
def create(self, request):
|
|
data = request.form.cleaned_data
|
|
try:
|
|
release = Recipe.objects.get(
|
|
recipe=data['recipe']
|
|
)
|
|
return rc.DUPLICATE_ENTRY
|
|
except Recipe.DoesNotExist:
|
|
pass
|
|
|
|
recipe = Recipe()
|
|
for key, value in data.items():
|
|
if key in request.form.data:
|
|
setattr(recipe, key, value)
|
|
recipe.save()
|
|
|
|
return RecipeHandler.render(recipe)
|
|
|
|
|
|
class RecipeHandler(JSONHandler):
|
|
|
|
allowed_methods = ('GET',)
|
|
model = Recipe
|
|
special_fields = ('recipe',)
|
|
|
|
@classmethod
|
|
def render(cls, recipe, fields=None):
|
|
return getattr(recipe, 'recipe')
|
|
|
|
def read(self, request, recipe_id):
|
|
try:
|
|
recipe = Recipe.objects.get(id=recipe_id)
|
|
return RecipeHandler.render(recipe)
|
|
except ObjectDoesNotExist:
|
|
return rc.NOT_FOUND
|
|
|
|
|
|
class RoleCollectionHandler(BaseHandler):
|
|
|
|
allowed_methods = ('GET', 'POST')
|
|
model = Role
|
|
|
|
def read(self, request):
|
|
return map(
|
|
RoleHandler.render,
|
|
Role.objects.all()
|
|
)
|
|
|
|
@validate_json(RoleForm)
|
|
def create(self, request):
|
|
data = request.form.cleaned_data
|
|
recipes = Recipe.objects.filter(recipe__in=data['recipes'])
|
|
role = Role(name=data["name"])
|
|
role.save()
|
|
map(role.recipes.add, recipes)
|
|
role.save()
|
|
|
|
return RoleHandler.render(role)
|
|
|
|
|
|
class RoleHandler(JSONHandler):
|
|
|
|
allowed_methods = ('GET',)
|
|
model = Role
|
|
fields = ('id', 'name')
|
|
special_fields = ('recipes',)
|
|
|
|
@classmethod
|
|
def render(cls, role, fields=None):
|
|
json_data = JSONHandler.render(role, fields=fields or cls.fields)
|
|
for field in cls.special_fields:
|
|
if field in ('recipes',):
|
|
json_data[field] = map(
|
|
RecipeHandler.render,
|
|
role.recipes.all()
|
|
)
|
|
return json_data
|
|
|
|
def read(self, request, role_id):
|
|
try:
|
|
role = Role.objects.get(id=role_id)
|
|
RoleHandler.render(role)
|
|
except ObjectDoesNotExist:
|
|
return rc.NOT_FOUND
|
|
|
|
|
|
class ReleaseCollectionHandler(BaseHandler):
|
|
|
|
allowed_methods = ('GET', 'POST')
|
|
model = Release
|
|
|
|
def read(self, request):
|
|
return map(
|
|
ReleaseHandler.render,
|
|
Release.objects.all()
|
|
)
|
|
|
|
@validate_json(ReleaseCreationForm)
|
|
def create(self, request):
|
|
data = request.form.cleaned_data
|
|
|
|
try:
|
|
release = Release.objects.get(
|
|
name=data['name'],
|
|
version=data['version']
|
|
)
|
|
return rc.DUPLICATE_ENTRY
|
|
except Release.DoesNotExist:
|
|
pass
|
|
|
|
release = Release(
|
|
name=data["name"],
|
|
version=data["version"],
|
|
description=data["description"]
|
|
)
|
|
release.save()
|
|
|
|
for role in data["roles"]:
|
|
rl = Role(name=role["name"])
|
|
rl.save()
|
|
recipes = Recipe.objects.filter(recipe__in=role["recipes"])
|
|
map(rl.recipes.add, recipes)
|
|
rl.save()
|
|
release.roles.add(rl)
|
|
|
|
release.save()
|
|
return ReleaseHandler.render(release)
|
|
|
|
|
|
class ReleaseHandler(JSONHandler):
|
|
|
|
allowed_methods = ('GET',)
|
|
model = Release
|
|
fields = ('name', 'version', 'description')
|
|
special_fields = ('roles',)
|
|
|
|
@classmethod
|
|
def render(cls, release, fields=None):
|
|
json_data = JSONHandler.render(release, fields=fields or cls.fields)
|
|
for field in cls.special_fields:
|
|
if field in ('roles',):
|
|
json_data[field] = map(
|
|
RoleHandler.render,
|
|
release.roles.all()
|
|
)
|
|
return json_data
|
|
|
|
def read(self, request, release_id):
|
|
try:
|
|
release = Release.objects.get(id=release_id)
|
|
return ReleaseHandler.render(release)
|
|
except ObjectDoesNotExist:
|
|
return rc.NOT_FOUND
|