Commit 2cd38e18 by Chif Gergő

Merge DEV to instance_view

parents e28c1606 b50c79c7
.vscode/ .vscode/
.idea/ recircle/db.sqlite3
recircle/clouds.yaml
environment.sh environment.sh
.idea/
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
example.py
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don’t work, or not
# install all needed dependencies.
#Pipfile.lock
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# Cloud configure
clouds.yaml
# pyc files
*.pyc
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "2adbcb2f6437576c7ac5794c996bf94a73714555a6ccc0e393fcb24bf184c1da" "sha256": "f991f85fb7c006559ee78cb35cc3a18089dfd0065a565f2b194c197cbf772a50"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
...@@ -144,11 +144,11 @@ ...@@ -144,11 +144,11 @@
}, },
"djangorestframework": { "djangorestframework": {
"hashes": [ "hashes": [
"sha256:376f4b50340a46c15ae15ddd0c853085f4e66058f97e4dbe7d43ed62f5e60651", "sha256:1ca4a5599a5ec31f3d6238a687fcc1dd4c41b1d90edab9ad398fcbf87872b7ba",
"sha256:c12869cfd83c33d579b17b3cb28a2ae7322a53c3ce85580c2a2ebe4e3f56c4fb" "sha256:c3c5edfdbc5dd33f9121bb84305bfd603d2c791f20cff9782772f44a7684a4e4"
], ],
"index": "pypi", "index": "pypi",
"version": "==3.9.4" "version": "==3.10.1"
}, },
"djoser": { "djoser": {
"hashes": [ "hashes": [
...@@ -202,11 +202,11 @@ ...@@ -202,11 +202,11 @@
}, },
"keystoneauth1": { "keystoneauth1": {
"hashes": [ "hashes": [
"sha256:b14f363d02142177c968cfffeb9eb37113682c03ac3c65d483424e203dd602c3", "sha256:3fabba6a87b64ec9a7ec09522e508a849f255cc8a8b6f7ad87d894a4bcc9ae58",
"sha256:b1e3910e09b01f88e84ce4c873f271f2b076b4ad266c2815c16ee3aef8319192" "sha256:439f7dcf6edde5ea5a16ef90603d198e118a03f529aba0f8a6d19d5f6433de95"
], ],
"index": "pypi", "index": "pypi",
"version": "==3.14.0" "version": "==3.15.0"
}, },
"msgpack": { "msgpack": {
"hashes": [ "hashes": [
...@@ -308,10 +308,10 @@ ...@@ -308,10 +308,10 @@
}, },
"pbr": { "pbr": {
"hashes": [ "hashes": [
"sha256:36ebd78196e8c9588c972f5571230a059ff83783fabbbbedecc07be263ccd7e6", "sha256:0ca44dc9fd3b04a22297c2a91082d8df2894862e8f4c86a49dac69eae9e85ca0",
"sha256:5a03f59455ad54f01a94c15829b8b70065462b7bd8d5d7e983306b59127fc841" "sha256:4aed6c1b1fa5020def0f22aed663d87b81bb3235f112490b07d2643d7a98c5b5"
], ],
"version": "==5.4.0" "version": "==5.4.1"
}, },
"prettytable": { "prettytable": {
"hashes": [ "hashes": [
...@@ -329,18 +329,18 @@ ...@@ -329,18 +329,18 @@
}, },
"pyparsing": { "pyparsing": {
"hashes": [ "hashes": [
"sha256:1873c03321fc118f4e9746baf201ff990ceb915f433f23b395f5580d1840cb2a", "sha256:530d8bf8cc93a34019d08142593cf4d78a05c890da8cf87ffa3120af53772238",
"sha256:9b6323ef4ab914af344ba97510e966d64ba91055d6b9afa6b30799340e89cc03" "sha256:f78e99616b6f1a4745c0580e170251ef1bbafc0d0513e270c4bd281bf29d2800"
], ],
"version": "==2.4.0" "version": "==2.4.1"
}, },
"python-novaclient": { "python-novaclient": {
"hashes": [ "hashes": [
"sha256:882ae865ff5cebfaa0c323978da20486876ea17e500466cdabcd91038906a86b", "sha256:42f4cabc151850c2b2a590e4253866523abaf669dca310b58a439352972a02d2",
"sha256:9a4477862a77155e1267207685a4ae487ce12f0e9e37cff56a6c1b43fe390e79" "sha256:5cb54a23e3413d4bf63bcacee8fd6b7b5ec33a4eb4183a95c86f6241c071959e"
], ],
"index": "pypi", "index": "pypi",
"version": "==14.1.0" "version": "==14.2.0"
}, },
"pytz": { "pytz": {
"hashes": [ "hashes": [
...@@ -507,11 +507,11 @@ ...@@ -507,11 +507,11 @@
}, },
"djangorestframework": { "djangorestframework": {
"hashes": [ "hashes": [
"sha256:376f4b50340a46c15ae15ddd0c853085f4e66058f97e4dbe7d43ed62f5e60651", "sha256:1ca4a5599a5ec31f3d6238a687fcc1dd4c41b1d90edab9ad398fcbf87872b7ba",
"sha256:c12869cfd83c33d579b17b3cb28a2ae7322a53c3ce85580c2a2ebe4e3f56c4fb" "sha256:c3c5edfdbc5dd33f9121bb84305bfd603d2c791f20cff9782772f44a7684a4e4"
], ],
"index": "pypi", "index": "pypi",
"version": "==3.9.4" "version": "==3.10.1"
}, },
"entrypoints": { "entrypoints": {
"hashes": [ "hashes": [
...@@ -522,11 +522,11 @@ ...@@ -522,11 +522,11 @@
}, },
"flake8": { "flake8": {
"hashes": [ "hashes": [
"sha256:859996073f341f2670741b51ec1e67a01da142831aa1fdc6242dbf88dffbe661", "sha256:19241c1cbc971b9962473e4438a2ca19749a7dd002dd1a946eaba171b4114548",
"sha256:a796a115208f5c03b18f332f7c11729812c8c3ded6c46319c59b53efd3819da8" "sha256:8e9dfa3cecb2400b3738a42c54c3043e821682b9c840b0448c0503f781130696"
], ],
"index": "pypi", "index": "pypi",
"version": "==3.7.7" "version": "==3.7.8"
}, },
"httpie": { "httpie": {
"hashes": [ "hashes": [
......
# from django.contrib import admin from django.contrib import admin
# Register your models here. from image.models import Image
from image.models import Disk
admin.site.register(Image)
admin.site.register(Disk)
# Generated by Django 2.2.3 on 2019-07-15 13:54
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('image', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Image',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(help_text='Human readable name of image.', max_length=100, verbose_name='name')),
('description', models.TextField(blank=True, help_text='Description of the image.', verbose_name='description')),
('remote_ID', models.CharField(help_text='ID, which helps access the image.', max_length=40, unique=True, verbose_name='remote_ID')),
('created_at', models.DateTimeField(auto_now_add=True, help_text='Date, when the image created.')),
],
),
]
# Generated by Django 2.2.3 on 2019-07-16 11:51
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('image', '0002_image'),
]
operations = [
migrations.RenameField(
model_name='disk',
old_name='remote_ID',
new_name='remote_id',
),
migrations.RenameField(
model_name='image',
old_name='remote_ID',
new_name='remote_id',
),
migrations.AddField(
model_name='image',
name='created_by',
field=models.ForeignKey(default=0, help_text='The user, who create the image', on_delete=django.db.models.deletion.DO_NOTHING, related_name='created_images', to=settings.AUTH_USER_MODEL),
preserve_default=False,
),
migrations.AddField(
model_name='image',
name='uploaded_by_user',
field=models.BooleanField(default=True, editable=False, help_text='The field is false if the image created from instance'),
),
]
from django.db import models from django.db import models
from django.contrib.auth.models import User
from django.conf import settings
from interface_openstack.implementation.vm.instance import OSVirtualMachineManager
from interface_openstack.implementation.image.openstack_image_manager import OpenstackImageManager
class Disk(models.Model): class Disk(models.Model):
...@@ -9,9 +14,86 @@ class Disk(models.Model): ...@@ -9,9 +14,86 @@ class Disk(models.Model):
name = models.CharField( name = models.CharField(
blank=True, max_length=100, verbose_name="name", help_text="Name of the disk" blank=True, max_length=100, verbose_name="name", help_text="Name of the disk"
) )
remote_ID = models.CharField( remote_id = models.CharField(
max_length=40, max_length=40,
unique=True, unique=True,
verbose_name="remote_ID", verbose_name="remote_ID",
help_text="ID, which helps access the disk", help_text="ID, which helps access the disk",
) )
class Image(models.Model):
"""A virtual image.
"""
name = models.CharField(
max_length=100,
verbose_name="name",
help_text="Human readable name of image."
)
description = models.TextField(
verbose_name="description",
blank=True,
help_text="Description of the image."
)
remote_id = models.CharField(
max_length=40,
unique=True,
verbose_name="remote_ID",
help_text="ID, which helps access the image."
)
created_at = models.DateTimeField(
auto_now_add=True,
editable=False,
help_text="Date, when the image created."
)
uploaded_by_user = models.BooleanField(
default=True,
editable=False,
help_text="The field is false if the image created from instance"
)
created_by = models.ForeignKey(
User,
on_delete=models.DO_NOTHING,
related_name="created_images",
help_text="The user, who create the image"
)
@classmethod
def create(cls, name, description, remote_id, uploaded_by_user, created_by):
inst = cls(name=name, description=description, uploaded_by_user=uploaded_by_user,
remote_id=remote_id, created_by=created_by)
inst.full_clean()
inst.save()
return inst
@classmethod
def create_from_instance(cls, user, instance, description):
interface = OSVirtualMachineManager(settings.CONNECTION)
remote_image = interface.create_image(instance.remote_id)
remote_id = remote_image.id
name = remote_image.name
new_image = cls.create(
name=name,
remote_id=remote_id,
created_by=user,
uploaded_by_user=False,
description=description
)
return new_image
@classmethod
def create_from_user(cls, description, file_format, image_file, name, user):
interface = OpenstackImageManager(settings.CONNECTION)
remote_image = interface.upload_file(name=name, path=image_file.temporary_file_path(),
format=file_format)
new_image = cls.create(
name=name,
remote_id=remote_image.id,
created_by=user,
uploaded_by_user=True,
description=description
)
return new_image
from rest_framework import serializers from rest_framework import serializers
from .models import Disk from .models import Image
class DiskSerializer(serializers.ModelSerializer): class ImageSerializer(serializers.ModelSerializer):
image_file = serializers.FileField(write_only=True)
file_format = serializers.CharField(max_length=10, write_only=True)
class Meta: class Meta:
model = Disk model = Image
fields = ("name", "remote_ID") fields = (
"name",
"remote_id",
"description",
"image_file",
"file_format",
"created_at",
"uploaded_by_user",
"created_by",
)
read_only_fields = ("created_at", "uploaded_by_user", "created_by", "remote_id", )
from django.urls import path from rest_framework import routers
from rest_framework.urlpatterns import format_suffix_patterns
from image import views from image import views
urlpatterns = [path("", views.DiskList.as_view())] router = routers.DefaultRouter()
router.register(r"images", views.ImageViewSet, basename="image")
urlpatterns = format_suffix_patterns(urlpatterns) urlpatterns = router.urls
from image.models import Disk
from image.serializers import DiskSerializer
# from django.shortcuts import render # from django.shortcuts import render
from rest_framework.views import APIView from rest_framework.viewsets import ModelViewSet
from rest_framework.response import Response from rest_framework.response import Response
from interface_openstack.implementation.image.openstack_image_manager import (
OpenstackImageManager,
)
from django.conf import settings
from image.models import Image
from image.serializers import ImageSerializer
class DiskList(APIView):
def get(self, request, format=None):
# OpenStack
interface = OpenstackImageManager(settings.CONNECTION)
return Response([disk.__dict__ for disk in interface.list()])
# Create response class ImageViewSet(ModelViewSet):
disks = Disk.object.all() serializer_class = ImageSerializer
serializer = DiskSerializer(disks, many=True) queryset = Image.objects.all()
# def list(self, request):
# return HttpResponse("list")
def create(self, request):
serializer = ImageSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
data = serializer.validated_data
new_image = Image.create_from_user(
description=data['description'],
file_format=data['file_format'],
image_file=data['image_file'],
name=data['name'],
user=request.user
)
serializer = ImageSerializer(instance=new_image)
return Response(serializer.data) return Response(serializer.data)
# def retrieve(self, request, pk=None):
# return HttpResponse("retrive")
# def update(self, request, pk=None):
# return HttpResponse("update")
# def partial_update(self, request, pk=None):
# return HttpResponse("patch")
# def destroy(self, request, pk=None):
# return HttpResponse("delete")
# Generated by Django 2.2.3 on 2019-07-15 13:54
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('instance', '0008_auto_20190704_1310'),
]
operations = [
migrations.AlterField(
model_name='instance',
name='flavor',
field=models.ForeignKey(help_text='Reasources given to the vm', on_delete='CASCADE', related_name='instances', to='instance.Flavor', verbose_name='flavor'),
),
migrations.AlterField(
model_name='instance',
name='lease',
field=models.ForeignKey(on_delete='CASCADE', related_name='instances', to='instance.Lease'),
),
]
...@@ -4,11 +4,13 @@ from django.conf import settings ...@@ -4,11 +4,13 @@ from django.conf import settings
from rest_framework.viewsets import ViewSet, ModelViewSet from rest_framework.viewsets import ViewSet, ModelViewSet
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework import status from rest_framework import status
from interface_openstack.implementation.vm.instance import ( from interface_openstack.implementation.vm.instance import (
OSVirtualMachineManager OSVirtualMachineManager
) )
from template.models import InstanceTemplate
from instance.models import Instance, Flavor, Lease from instance.models import Instance, Flavor, Lease
from instance.serializers import InstanceSerializer, FlavorSerializer
from template.models import ImageTemplate
class InstanceViewSet(ViewSet): class InstanceViewSet(ViewSet):
...@@ -25,7 +27,7 @@ class InstanceViewSet(ViewSet): ...@@ -25,7 +27,7 @@ class InstanceViewSet(ViewSet):
def create(self, request): def create(self, request):
data = request.data data = request.data
template = InstanceTemplate.objects.get(pk=data["template"]) template = ImageTemplate.objects.get(pk=data["template"])
flavor = Flavor.objects.get(pk=data["flavor"]) flavor = Flavor.objects.get(pk=data["flavor"])
lease = Lease.objects.get(pk=data["lease"]) lease = Lease.objects.get(pk=data["lease"])
......
...@@ -21,8 +21,9 @@ from rest_framework_swagger.views import get_swagger_view ...@@ -21,8 +21,9 @@ from rest_framework_swagger.views import get_swagger_view
schema_view = get_swagger_view(title="RECIRCLE API") schema_view = get_swagger_view(title="RECIRCLE API")
urlpatterns = [ urlpatterns = [
path("images/", include("image.urls")), path("api/v1/", include("image.urls")),
path("api/v1/", include("instance.urls")), path("api/v1/", include("instance.urls")),
path("api/v1/", include("template.urls")),
path("admin/", admin.site.urls), path("admin/", admin.site.urls),
re_path(r"^auth/", include("djoser.urls")), re_path(r"^auth/", include("djoser.urls")),
re_path(r"^auth/", include("djoser.urls.authtoken")), re_path(r"^auth/", include("djoser.urls.authtoken")),
......
# from django.contrib import admin from django.contrib import admin
# Register your models here. from template.models import ImageTemplate
admin.site.register(ImageTemplate)
# Generated by Django 2.2.1 on 2019-07-04 12:12 # Generated by Django 2.2.3 on 2019-07-03 12:09
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):
...@@ -8,16 +9,26 @@ class Migration(migrations.Migration): ...@@ -8,16 +9,26 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
('image', '0001_initial'),
] ]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='InstanceTemplate', name='BaseTemplate',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(help_text='Human readable name of template.', max_length=100, verbose_name='name')), ('name', models.CharField(help_text='Human readable name of template.', max_length=100, verbose_name='name')),
('description', models.TextField(blank=True, help_text='Description of the template.', verbose_name='description')), ('description', models.TextField(blank=True, help_text='Description of the template.', verbose_name='description')),
('remote_ID', models.CharField(help_text='ID, which helps access the template.', max_length=40, unique=True, verbose_name='remote_ID')), ('remote_ID', models.CharField(help_text='ID, which helps access the template.', max_length=40, unique=True, verbose_name='remote_ID')),
('created_at', models.DateTimeField(auto_now_add=True, help_text='Date, when the template created.')),
], ],
), ),
migrations.CreateModel(
name='Template',
fields=[
('basetemplate_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='template.BaseTemplate')),
('disk', models.ForeignKey(help_text='The disk where the template is located.', on_delete=django.db.models.deletion.CASCADE, related_name='templates', to='image.Disk')),
],
bases=('template.basetemplate',),
),
] ]
# Generated by Django 2.2.3 on 2019-07-15 13:54
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('image', '0002_image'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('template', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='basetemplate',
name='created_by',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.DO_NOTHING, related_name='created_templates', to=settings.AUTH_USER_MODEL),
preserve_default=False,
),
migrations.CreateModel(
name='PureTemplate',
fields=[
('basetemplate_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='template.BaseTemplate')),
('images', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='templates', to='image.Image')),
],
bases=('template.basetemplate',),
),
]
# Generated by Django 2.2.3 on 2019-07-16 11:51
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('image', '0003_auto_20190716_1151'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('template', '0002_auto_20190715_1354'),
]
operations = [
migrations.RenameModel(
old_name='Template',
new_name='DiskTemplate',
),
migrations.RenameModel(
old_name='PureTemplate',
new_name='ImageTemplate',
),
migrations.RemoveField(
model_name='basetemplate',
name='remote_ID',
),
migrations.AlterField(
model_name='basetemplate',
name='created_by',
field=models.ForeignKey(help_text='The user, who create the template', on_delete=django.db.models.deletion.DO_NOTHING, related_name='created_templates', to=settings.AUTH_USER_MODEL),
),
]
# Generated by Django 2.2.3 on 2019-07-16 12:27
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('template', '0003_auto_20190716_1151'),
]
operations = [
migrations.RenameField(
model_name='imagetemplate',
old_name='images',
new_name='image',
),
]
# Generated by Django 2.2.3 on 2019-07-17 09:48
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('instance', '0009_auto_20190715_1354'),
('template', '0004_auto_20190716_1227'),
]
operations = [
migrations.AddField(
model_name='basetemplate',
name='flavor',
field=models.ForeignKey(default=1, help_text='Reasources given to the vm', on_delete='CASCADE', related_name='templates', to='instance.Flavor', verbose_name='flavor'),
preserve_default=False,
),
migrations.AddField(
model_name='basetemplate',
name='lease',
field=models.ForeignKey(default=1, on_delete='CASCADE', related_name='templates', to='instance.Lease'),
preserve_default=False,
),
migrations.AddField(
model_name='imagetemplate',
name='type',
field=models.CharField(choices=[('U', 'User create the template from image'), ('I', 'Template created from instance'), ('D', 'Default "Pure" template')], default='I', max_length=10),
preserve_default=False,
),
]
# Generated by Django 2.2.3 on 2019-07-19 14:16
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('template', '0005_auto_20190717_0948'),
]
operations = [
migrations.AlterField(
model_name='imagetemplate',
name='type',
field=models.CharField(choices=[('U', 'User create the template from image'), ('I', 'Template created from instance'), ('P', '"Pure" template')], default='U', max_length=10),
),
]
from django.db import models from django.db import models
from django.contrib.auth.models import User
from django.conf import settings
from image.models import Disk
from image.models import Image
from instance.models import Lease
from instance.models import Flavor
from interface_openstack.implementation.storage.openstack_snapshot_manager import SnapshotManager
class InstanceTemplate(models.Model):
class BaseTemplate(models.Model):
"""Virtual machine template. """Virtual machine template.
""" """
...@@ -9,15 +17,93 @@ class InstanceTemplate(models.Model): ...@@ -9,15 +17,93 @@ class InstanceTemplate(models.Model):
name = models.CharField( name = models.CharField(
max_length=100, max_length=100,
verbose_name="name", verbose_name="name",
help_text="Human readable name of template.", help_text="Human readable name of template."
) )
description = models.TextField( description = models.TextField(
verbose_name="description", blank=True, help_text="Description of the template." verbose_name="description",
blank=True,
help_text="Description of the template."
)
# remote_id = models.CharField(
# max_length=40,
# unique=True,
# verbose_name="remote_ID",
# help_text="ID, which helps access the template."
# )
created_at = models.DateTimeField(
auto_now_add=True,
editable=False,
help_text="Date, when the template created."
) )
# owner = models.ForeignKey(User) created_by = models.ForeignKey(
remote_ID = models.CharField( User,
max_length=40, on_delete=models.DO_NOTHING,
unique=True, related_name="created_templates",
verbose_name="remote_ID", help_text="The user, who create the template"
help_text="ID, which helps access the template.",
) )
flavor = models.ForeignKey(Flavor, help_text="Reasources given to the vm",
verbose_name="flavor", on_delete="CASCADE",
related_name='templates')
lease = models.ForeignKey(Lease, on_delete="CASCADE",
related_name='templates')
class DiskTemplate(BaseTemplate):
disk = models.ForeignKey(
Disk,
related_name="templates",
on_delete=models.CASCADE,
help_text="The disk where the template is located."
)
@classmethod
def create_from_volume(cls, name, description, disk, user):
interface = SnapshotManager(settings.CONNECTION)
remote_template = interface.create_from_volume(disk.remote_id)
remote_id = remote_template.id
new_template = cls.create(
name=name,
description=description,
disk=disk,
remote_id=remote_id,
created_by=user
)
return new_template
class ImageTemplate(BaseTemplate):
TYPES = (
('U', 'User create the template from image'),
('I', 'Template created from instance'),
('P', '"Pure" template'),
)
image = models.ForeignKey(
Image,
related_name="templates",
on_delete=models.CASCADE,
help_text=""
)
type = models.CharField(max_length=10, choices=TYPES, default="U")
@classmethod
def create(cls, name, description, image, lease, flavor, created_by, type='U'):
inst = cls(name=name, description=description, image=image, lease=lease,
flavor=flavor, created_by=created_by, type=type)
inst.full_clean()
inst.save()
return inst
@classmethod
def create_from_instance(cls, name, description, instance, user):
image = Image.create_from_instance(user, instance, description)
new_template = cls.create(
name=name,
description=description,
created_by=user,
image=image,
lease=instance.lease,
flavor=instance.flavor,
type="I"
)
return new_template
from rest_framework import serializers from rest_framework import serializers
from .models import InstanceTemplate from template.models import ImageTemplate
class InstanceTemplateSerializer(serializers.ModelSerializer): class InstanceFromTemplateSerializer(serializers.Serializer):
name = serializers.CharField()
description = serializers.CharField()
class ImageTemplateModelSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = InstanceTemplate model = ImageTemplate
fields = ("name", "description", "owner", "remote_ID") fields = (
"name",
"description",
"created_at",
"created_by",
"image",
"flavor",
"lease",
"type",
)
read_only_fields = (
"created_at",
"created_by",
"type",
)
from rest_framework import routers
from template import views
router = routers.DefaultRouter()
router.register(r"templates/image-templates", views.ImageTemplateViewSet, basename="image-template")
urlpatterns = router.urls
# from django.shortcuts import render # from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from rest_framework.decorators import action
# Create your views here. from template.serializers import InstanceFromTemplateSerializer
from template.serializers import ImageTemplateModelSerializer
from template.models import ImageTemplate
class ImageTemplateViewSet(ModelViewSet):
serializer_class = ImageTemplateModelSerializer
queryset = ImageTemplate.objects.all()
def create(self, request):
serializer = ImageTemplateModelSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
data = serializer.validated_data
new_template = ImageTemplate.create(
name=data["name"],
description=data["description"],
created_by=request.user,
image=data["image"],
lease=data["lease"],
flavor=data["flavor"],
type="U"
)
serializer = ImageTemplateModelSerializer(instance=new_template)
return Response(serializer.data)
def update(self, request, *args, **kwargs):
# only the name, description, lease, flavor can be updated
allowed_keys = ["name", "description", "lease", "flavor"]
# delete not allowed key
for key in request.data.keys():
if key not in allowed_keys:
request.data.pop(key, None)
return super(ImageTemplateViewSet, self).update(request, partial=True)
@action(detail=True, methods=["post"])
def template(self, request, pk):
instance = self.get_object(pk)
serializer = InstanceFromTemplateSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
data = serializer.validated_data
new_template = ImageTemplate.create_from_instance(data["name"], data["description"],
instance, request.user)
serializer = ImageTemplateModelSerializer(instance=new_template)
return Response(serializer.data)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment