Skip to content

Commit 832a235

Browse files
Miha Pleškomatejart
authored andcommitted
1 parent 58b88e9 commit 832a235

File tree

9 files changed

+387
-47
lines changed

9 files changed

+387
-47
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.9.4 on 2016-03-10 09:41
3+
from __future__ import unicode_literals
4+
5+
from django.db import migrations, models
6+
import django.db.models.deletion
7+
import uuid
8+
9+
10+
class Migration(migrations.Migration):
11+
12+
dependencies = [
13+
('cfy_wrapper', '0001_initial'),
14+
]
15+
16+
operations = [
17+
migrations.CreateModel(
18+
name='Container',
19+
fields=[
20+
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
21+
('blueprint', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='cfy_wrapper.Blueprint')),
22+
],
23+
options={
24+
'abstract': False,
25+
},
26+
),
27+
]

dice_deploy_django/cfy_wrapper/models.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from django.db import models
33
from rest_framework.exceptions import NotFound
44
from enum import Enum
5+
from django.db import IntegrityError
56

67

78
class Base(models.Model):
@@ -42,3 +43,36 @@ def cfy_id(self):
4243
@property
4344
def state_name(self):
4445
return Blueprint.State(self.state).name
46+
47+
def pipe_deploy_blueprint(self):
48+
""" Defines and starts async pipeline for deploying blueprint to cloudify """
49+
from cfy_wrapper import tasks
50+
pipe = (
51+
tasks.upload_blueprint.si(self.cfy_id) |
52+
tasks.create_deployment.si(self.cfy_id) |
53+
tasks.install.si(self.cfy_id)
54+
)
55+
pipe.apply_async()
56+
57+
def pipe_undeploy_blueprint(self):
58+
""" Defines and starts async pipeline for undeploying blueprint from cloudify """
59+
from cfy_wrapper import tasks
60+
pipe = (
61+
tasks.uninstall.si(self.cfy_id) |
62+
tasks.delete_deployment.si(self.cfy_id) |
63+
tasks.delete_blueprint.si(self.cfy_id)
64+
)
65+
pipe.apply_async()
66+
67+
68+
class Container(Base):
69+
# Fields
70+
id = models.UUIDField(
71+
primary_key=True, default=uuid.uuid4, editable=False
72+
)
73+
blueprint = models.ForeignKey(Blueprint, null=True)
74+
75+
def delete(self, using=None, keep_parents=False):
76+
if self.blueprint is not None:
77+
raise IntegrityError('Cannot delete container with existing blueprint')
78+
super(Container, self).delete(using, keep_parents)
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
from rest_framework import serializers
22

3-
from .models import Blueprint
3+
from .models import Blueprint, Container
44

55

66
class BlueprintSerializer(serializers.ModelSerializer):
77
class Meta:
88
model = Blueprint
99
fields = ("state_name", "cfy_id")
10+
11+
12+
class ContainerSerializer(serializers.ModelSerializer):
13+
blueprint = BlueprintSerializer()
14+
15+
class Meta:
16+
model = Container
17+
fields = ("id", "blueprint")

dice_deploy_django/cfy_wrapper/urls.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,24 @@
44
DebugView,
55
BlueprintsView,
66
BlueprintIdView,
7+
ContainersView,
8+
ContainerIdView,
9+
ContainerBlueprint
710
)
811

912
urlpatterns = [
1013
url(r"^debug/?$",
1114
DebugView.as_view(), name="debug"),
15+
# blueprint
1216
url(r"^blueprints/?$",
1317
BlueprintsView.as_view(), name="blueprints"),
1418
url(r"^blueprints/(?P<blueprint_id>[0-9a-f-]+)/?$",
1519
BlueprintIdView.as_view(), name="blueprint_id"),
20+
# container
21+
url(r"^containers/?$",
22+
ContainersView.as_view(), name="containers"),
23+
url(r"^containers/(?P<container_id>[0-9a-f-]+)/?$",
24+
ContainerIdView.as_view(), name="container_id"),
25+
url(r"^containers/(?P<container_id>[0-9a-f-]+)/blueprints?$",
26+
ContainerBlueprint.as_view(), name="container_blueprint"),
1627
]

dice_deploy_django/cfy_wrapper/views.py

Lines changed: 76 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
from rest_framework.views import APIView
44
from rest_framework.response import Response
55
from rest_framework.parsers import MultiPartParser, FileUploadParser
6+
from rest_framework import status
7+
from django.db import IntegrityError
68

79
from . import tasks
8-
from .models import Blueprint
9-
from .serializers import BlueprintSerializer
10+
from .models import Blueprint, Container
11+
from .serializers import BlueprintSerializer, ContainerSerializer
1012

1113
logger = logging.getLogger("views")
1214

@@ -23,43 +25,90 @@ class BlueprintsView(APIView):
2325

2426
def get(self, request):
2527
"""
26-
# List all available blueprints
28+
List all available blueprints
2729
"""
2830
s = BlueprintSerializer(Blueprint.objects.all(), many=True)
2931
return Response(s.data)
3032

31-
def put(self, request):
32-
"""
33-
# Upload new blueprint archive
34-
"""
35-
b = Blueprint.objects.create(archive=request.data["file"])
36-
s = BlueprintSerializer(b)
37-
pipe = (
38-
tasks.upload_blueprint.si(b.cfy_id) |
39-
tasks.create_deployment.si(b.cfy_id) |
40-
tasks.install.si(b.cfy_id)
41-
)
42-
pipe.apply_async()
43-
return Response(s.data, status=201)
44-
4533

4634
class BlueprintIdView(APIView):
4735
def get(self, request, blueprint_id):
4836
"""
49-
# Return selected blueprint details
37+
Return selected blueprint details
5038
"""
5139
s = BlueprintSerializer(Blueprint.get(blueprint_id))
5240
return Response(s.data)
5341

5442
def delete(self, request, blueprint_id):
5543
"""
56-
# Delete selected blueprint
44+
Delete selected blueprint
45+
"""
46+
blueprint = Blueprint.get(blueprint_id)
47+
blueprint.pipe_undeploy_blueprint()
48+
return Response(status=status.HTTP_202_ACCEPTED)
49+
50+
51+
class ContainersView(APIView):
52+
def get(self, request):
53+
"""
54+
List all virtual containers and their status information
55+
"""
56+
contaiers = Container.objects.all()
57+
s = ContainerSerializer(contaiers, many=True)
58+
return Response(data=s.data)
59+
60+
def post(self, request):
61+
container = Container()
62+
container.save() # all default is good
63+
s = ContainerSerializer(container)
64+
return Response(data=s.data, status=status.HTTP_201_CREATED)
65+
66+
67+
class ContainerIdView(APIView):
68+
def get(self, request, container_id):
69+
"""
70+
Display the status information about the selected virtual container
71+
"""
72+
container = Container.get(container_id)
73+
s = ContainerSerializer(container)
74+
return Response(s.data)
75+
76+
def delete(self, request, container_id):
77+
"""
78+
Remove virtual container and undeploy its blueprint.
5779
"""
58-
b = Blueprint.get(blueprint_id)
59-
pipe = (
60-
tasks.uninstall.si(b.cfy_id) |
61-
tasks.delete_deployment.si(b.cfy_id) |
62-
tasks.delete_blueprint.si(b.cfy_id)
63-
)
64-
pipe.apply_async()
65-
return Response(status=202)
80+
container = Container.get(container_id)
81+
try:
82+
container.delete()
83+
except IntegrityError, e:
84+
return Response({'msg': e.message}, status=status.HTTP_400_BAD_REQUEST)
85+
86+
return Response(status=status.HTTP_204_NO_CONTENT)
87+
88+
89+
class ContainerBlueprint(APIView):
90+
def post(self, request, container_id):
91+
cont = Container.get(container_id)
92+
blueprint_old = cont.blueprint
93+
blueprint_new = Blueprint.objects.create(archive=request.data["file"])
94+
95+
# bind new blueprint to this container
96+
cont.blueprint = blueprint_new
97+
cont.save()
98+
99+
# deploy the new blueprint
100+
blueprint_new.pipe_deploy_blueprint()
101+
102+
# undeploy the old blueprint
103+
if blueprint_old:
104+
# TODO: keep container-blueprint binding to old blueprint until cloudify undeploys it
105+
blueprint_old.pipe_undeploy_blueprint()
106+
107+
cont_ser = ContainerSerializer(cont).data
108+
return Response(cont_ser, status=status.HTTP_202_ACCEPTED)
109+
110+
111+
112+
113+
114+

dice_deploy_django/requirements.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ cloudify_rest_client
55
celery
66
enum34
77
flower
8+
django-factory-boy

dice_deploy_django/requirements.txt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,25 @@
66
#
77
amqp==1.4.7 # via kombu
88
anyjson==0.3.3 # via kombu
9+
babel==2.2.0 # via flower
10+
backports.ssl-match-hostname==3.5.0.1 # via tornado
911
billiard==3.3.0.20 # via celery
1012
celery==3.1.18
13+
certifi==2016.2.28 # via tornado
1114
cloudify-rest-client==3.2.1
15+
django-factory-boy==1.0.0
1216
django==1.9.4
1317
djangorestframework==3.2.4
1418
enum34==1.0.4
19+
factory-boy==2.6.1 # via django-factory-boy
20+
fake-factory==0.5.7 # via factory-boy
21+
flower==0.8.4
22+
futures==3.0.5 # via flower
23+
ipaddress==1.0.16 # via fake-factory
1524
kombu==3.0.28 # via celery
1625
markdown==2.6.2
17-
pytz==2015.6 # via celery
26+
python-dateutil==2.5.0 # via fake-factory
27+
pytz==2015.7 # via babel, celery, flower
1828
requests==2.7.0 # via cloudify-rest-client
19-
flower==0.8.4
29+
six==1.10.0 # via fake-factory, python-dateutil
30+
tornado==4.2.0 # via flower
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import factory
2+
from cfy_wrapper.models import Container, Blueprint
3+
from django.conf import settings
4+
5+
6+
class BlueprintPendingFactory(factory.DjangoModelFactory):
7+
state = Blueprint.State.pending.value
8+
archive = factory.django.FileField(from_path=settings.TEST_FILE_BLUEPRINT_EXAMPLE)
9+
10+
class Meta:
11+
model = Blueprint
12+
13+
14+
class BlueprintDeployedFactory(factory.DjangoModelFactory):
15+
state = Blueprint.State.deployed.value
16+
archive = factory.django.FileField(from_path=settings.TEST_FILE_BLUEPRINT_EXAMPLE)
17+
18+
class Meta:
19+
model = Blueprint
20+
21+
22+
class ContainerEmptyFactory(factory.DjangoModelFactory):
23+
class Meta:
24+
model = Container
25+
26+
27+
class ContainerFullFactory(factory.DjangoModelFactory):
28+
blueprint = factory.SubFactory(BlueprintDeployedFactory)
29+
30+
class Meta:
31+
model = Container
32+
33+
34+

0 commit comments

Comments
 (0)