Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
RECIRCLE
/
portal
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
11
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
b1fc3c9d
authored
Aug 14, 2019
by
Bodor Máté
Browse files
Options
Browse Files
Download
Plain Diff
Merge DEV to image_model_test
parents
44c637b3
3a808815
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
375 additions
and
154 deletions
+375
-154
.gitignore
+83
-3
Pipfile
+1
-1
Pipfile.lock
+27
-25
recircle/image/models.py
+24
-2
recircle/image/serializers.py
+10
-2
recircle/image/views.py
+38
-14
recircle/instance/migrations/0009_auto_20190715_0929.py
+0
-23
recircle/instance/migrations/0010_instance_template.py
+8
-3
recircle/instance/models.py
+57
-15
recircle/instance/serializers.py
+18
-2
recircle/instance/urls.py
+7
-9
recircle/instance/views.py
+74
-36
recircle/interface_openstack
+1
-1
recircle/template/migrations/0007_basetemplate_network_id.py
+18
-0
recircle/template/models.py
+9
-4
recircle/template/views.py
+0
-14
No files found.
.gitignore
View file @
b1fc3c9d
# IDEs
.vscode/
recircle/db.sqlite3
recircle/clouds.yaml
environment.sh
.idea/
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# 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
# 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
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
environment.sh
# Cloud configure
clouds.yaml
Pipfile
View file @
b1fc3c9d
...
...
@@ -13,11 +13,11 @@ django-nose = "*"
[packages]
django = "*"
djangorestframework = "*"
djoser = "*"
django-cors-headers = "*"
openstacksdk = "*"
python-novaclient = "*"
keystoneauth1 = "*"
djoser = "*"
[requires]
python_version = "3.6"
Pipfile.lock
View file @
b1fc3c9d
...
...
@@ -121,11 +121,11 @@
},
"django": {
"hashes": [
"sha256:
4d23f61b26892bac785f07401bc38cbf8fa4cec993f400e9cd9ddf28fd51c0ea
",
"sha256:
6e974d4b57e3b29e4882b244d40171d6a75202ab8d2402b8e8adbd182e25cf0c
"
"sha256:
16a5d54411599780ac9dfe3b9b38f90f785c51259a584e0b24b6f14a7f69aae8
",
"sha256:
9a2f98211ab474c710fcdad29c82f30fc14ce9917c7a70c3682162a624de4035
"
],
"index": "pypi",
"version": "==2.2.
3
"
"version": "==2.2.
4
"
},
"django-cors-headers": {
"hashes": [
...
...
@@ -272,11 +272,11 @@
},
"openstacksdk": {
"hashes": [
"sha256:
dc1232a58e30876ed6b28ee7bf5fee281b70048b187e88acd8a53cc3b63f9d8a
",
"sha256:
f6e045d2e0a111d3a8dd157d111a04f1354ad6cc7819f6c1db073426bea7734f
"
"sha256:
ae521b4083ecc3395e27b6a7d0f119a737cefb2f76277f16dc5b626a3c4d5c52
",
"sha256:
e3a1346a238d57d4f398f345a79d03b6705e229a4453f8b73acdcd00d04e6328
"
],
"index": "pypi",
"version": "==0.3
1.2
"
"version": "==0.3
2.0
"
},
"os-service-types": {
"hashes": [
...
...
@@ -308,10 +308,10 @@
},
"pbr": {
"hashes": [
"sha256:
0ca44dc9fd3b04a22297c2a91082d8df2894862e8f4c86a49dac69eae9e85ca0
",
"sha256:
4aed6c1b1fa5020def0f22aed663d87b81bb3235f112490b07d2643d7a98c5b5
"
"sha256:
56e52299170b9492513c64be44736d27a512fa7e606f21942160b68ce510b4bc
",
"sha256:
9b321c204a88d8ab5082699469f52cc94c5da45c51f114113d01b3d993c24cdf
"
],
"version": "==5.4.
1
"
"version": "==5.4.
2
"
},
"prettytable": {
"hashes": [
...
...
@@ -344,26 +344,28 @@
},
"pytz": {
"hashes": [
"sha256:
303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda
",
"sha256:
d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141
"
"sha256:
26c0b32e437e54a18161324a2fca3c4b9846b74a8dccddd843113109e1116b32
",
"sha256:
c894d57500a4cd2d5c71114aaab77dbab5eabd9022308ce5ac9bb93a60a6f0c7
"
],
"version": "==2019.
1
"
"version": "==2019.
2
"
},
"pyyaml": {
"hashes": [
"sha256:57acc1d8533cbe51f6662a55434f0dbecfa2b9eaf115bede8f6fd00115a0c0d3",
"sha256:588c94b3d16b76cfed8e0be54932e5729cc185caffaa5a451e7ad2f7ed8b4043",
"sha256:68c8dd247f29f9a0d09375c9c6b8fdc64b60810ebf07ba4cdd64ceee3a58c7b7",
"sha256:70d9818f1c9cd5c48bb87804f2efc8692f1023dac7f1a1a5c61d454043c1d265",
"sha256:86a93cccd50f8c125286e637328ff4eef108400dd7089b46a7be3445eecfa391",
"sha256:a0f329125a926876f647c9fa0ef32801587a12328b4a3c741270464e3e4fa778",
"sha256:a3c252ab0fa1bb0d5a3f6449a4826732f3eb6c0270925548cac342bc9b22c225",
"sha256:b4bb4d3f5e232425e25dda21c070ce05168a786ac9eda43768ab7f3ac2770955",
"sha256:cd0618c5ba5bda5f4039b9398bb7fb6a317bb8298218c3de25c47c4740e4b95e",
"sha256:ceacb9e5f8474dcf45b940578591c7f3d960e82f926c707788a570b51ba59190",
"sha256:fe6a88094b64132c4bb3b631412e90032e8cfe9745a58370462240b8cb7553cd"
],
"version": "==5.1.1"
"sha256:0113bc0ec2ad727182326b61326afa3d1d8280ae1122493553fd6f4397f33df9",
"sha256:01adf0b6c6f61bd11af6e10ca52b7d4057dd0be0343eb9283c878cf3af56aee4",
"sha256:5124373960b0b3f4aa7df1707e63e9f109b5263eca5976c66e08b1c552d4eaf8",
"sha256:5ca4f10adbddae56d824b2c09668e91219bb178a1eee1faa56af6f99f11bf696",
"sha256:7907be34ffa3c5a32b60b95f4d95ea25361c951383a894fec31be7252b2b6f34",
"sha256:7ec9b2a4ed5cad025c2278a1e6a19c011c80a3caaac804fd2d329e9cc2c287c9",
"sha256:87ae4c829bb25b9fe99cf71fbb2140c448f534e24c998cc60f39ae4f94396a73",
"sha256:9de9919becc9cc2ff03637872a440195ac4241c80536632fffeb6a1e25a74299",
"sha256:a5a85b10e450c66b49f98846937e8cfca1db3127a9d5d1e31ca45c3d0bef4c5b",
"sha256:b0997827b4f6a7c286c01c5f60384d218dca4ed7d9efa945c3e1aa623d5709ae",
"sha256:b631ef96d3222e62861443cc89d6563ba3eeb816eeb96b2629345ab795e53681",
"sha256:bf47c0607522fdbca6c9e817a6e81b08491de50f3766a7a0e6a5be7905961b41",
"sha256:f81025eddd0327c7d4cfe9b62cf33190e1e736cc6e97502b3ec425f574b3e7a8"
],
"version": "==5.1.2"
},
"requests": {
"hashes": [
...
...
recircle/image/models.py
View file @
b1fc3c9d
...
...
@@ -86,7 +86,9 @@ class Image(models.Model):
uploaded_by_user
=
False
,
description
=
description
)
return
new_image
for
attr
,
value
in
new_image
.
__dict__
.
items
():
setattr
(
remote_image
,
attr
,
value
)
return
remote_image
@classmethod
def
create_from_user
(
cls
,
description
,
...
...
@@ -102,4 +104,24 @@ class Image(models.Model):
uploaded_by_user
=
True
,
description
=
description
)
return
new_image
for
attr
,
value
in
new_image
.
__dict__
.
items
():
setattr
(
remote_image
,
attr
,
value
)
return
remote_image
def
delete
(
self
):
interface
=
OpenstackImageManager
(
settings
.
CONNECTION
)
if
interface
.
delete
(
self
.
remote_id
):
super
()
.
delete
()
def
get
(
self
):
interface
=
OpenstackImageManager
(
settings
.
CONNECTION
)
image
=
interface
.
get
(
self
.
remote_id
)
for
attr
,
value
in
self
.
__dict__
.
items
():
setattr
(
image
,
attr
,
value
)
return
image
def
update
(
self
,
data
):
for
(
key
,
value
)
in
data
.
items
():
setattr
(
self
,
key
,
value
)
self
.
save
()
return
self
.
get
()
recircle/image/serializers.py
View file @
b1fc3c9d
...
...
@@ -3,9 +3,15 @@ from rest_framework import serializers
from
.models
import
Image
class
ImageUpdateSerializer
(
serializers
.
Serializer
):
name
=
serializers
.
CharField
(
required
=
False
)
description
=
serializers
.
CharField
(
required
=
False
)
class
ImageSerializer
(
serializers
.
ModelSerializer
):
image_file
=
serializers
.
FileField
(
write_only
=
True
)
file_format
=
serializers
.
CharField
(
max_length
=
10
,
write_only
=
True
)
file_format
=
serializers
.
CharField
(
max_length
=
10
)
size
=
serializers
.
IntegerField
()
class
Meta
:
model
=
Image
...
...
@@ -18,5 +24,7 @@ class ImageSerializer(serializers.ModelSerializer):
"created_at"
,
"uploaded_by_user"
,
"created_by"
,
"id"
,
"size"
,
)
read_only_fields
=
(
"created_at"
,
"uploaded_by_user"
,
"created_by"
,
"remote_id"
,
)
read_only_fields
=
(
"created_at"
,
"uploaded_by_user"
,
"created_by"
,
"remote_id"
,
"size"
,
)
recircle/image/views.py
View file @
b1fc3c9d
# from django.shortcuts import render
from
rest_framework.viewsets
import
Model
ViewSet
from
rest_framework.viewsets
import
ViewSet
from
rest_framework.response
import
Response
from
django.shortcuts
import
get_object_or_404
from
rest_framework
import
status
from
django.core.exceptions
import
ObjectDoesNotExist
from
image.models
import
Image
from
image.serializers
import
ImageSerializer
from
image.serializers
import
ImageUpdateSerializer
class
ImageViewSet
(
ModelViewSet
):
serializer_class
=
ImageSerializer
queryset
=
Image
.
objects
.
all
()
# def list(self, request):
# return HttpResponse("list")
class
ImageViewSet
(
ViewSet
):
def
list
(
self
,
request
):
image_list
=
[]
images
=
Image
.
objects
.
all
()
for
image
in
images
:
image_list
.
append
(
image
.
get
())
serializer
=
ImageSerializer
(
image_list
,
many
=
True
)
return
Response
(
serializer
.
data
)
def
create
(
self
,
request
):
serializer
=
ImageSerializer
(
data
=
request
.
data
)
...
...
@@ -26,14 +34,30 @@ class ImageViewSet(ModelViewSet):
serializer
=
ImageSerializer
(
instance
=
new_image
)
return
Response
(
serializer
.
data
)
# def retrieve(self, request, pk=None):
# return HttpResponse("retrive")
def
retrieve
(
self
,
request
,
pk
=
None
):
queryset
=
Image
.
objects
.
all
()
image
=
get_object_or_404
(
queryset
,
pk
=
pk
)
serializer
=
ImageSerializer
(
instance
=
image
)
image
=
image
.
get
()
serializer
=
ImageSerializer
(
instance
=
image
)
return
Response
(
serializer
.
data
)
# def update(self, request, pk=None):
# return HttpResponse("update")
def
update
(
self
,
request
,
pk
=
None
):
serializer
=
ImageUpdateSerializer
(
data
=
request
.
data
)
serializer
.
is_valid
(
raise_exception
=
True
)
queryset
=
Image
.
objects
.
all
()
image
=
get_object_or_404
(
queryset
,
pk
=
pk
)
image
=
image
.
update
(
serializer
.
validated_data
)
serializer
=
ImageSerializer
(
instance
=
image
)
return
Response
(
serializer
.
data
)
#
def partial_update(self, request, pk=None):
# return HttpResponse("patch"
)
def
partial_update
(
self
,
request
,
pk
=
None
):
return
self
.
update
(
request
,
pk
)
# def destroy(self, request, pk=None):
# return HttpResponse("delete")
def
destroy
(
self
,
request
,
pk
=
None
):
try
:
image
=
Image
.
objects
.
get
(
id
=
pk
)
image
.
delete
()
return
Response
(
status
=
status
.
HTTP_204_NO_CONTENT
)
except
ObjectDoesNotExist
:
return
Response
(
status
=
status
.
HTTP_204_NO_CONTENT
)
recircle/instance/migrations/0009_auto_20190715_0929.py
deleted
100644 → 0
View file @
44c637b3
# Generated by Django 2.2.3 on 2019-07-15 09:29
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'
),
),
]
recircle/instance/migrations/0010_
merge_20190731_1215
.py
→
recircle/instance/migrations/0010_
instance_template
.py
View file @
b1fc3c9d
# Generated by Django 2.2.
3 on 2019-07-31 12:15
# Generated by Django 2.2.
4 on 2019-08-08 10:41
from
django.db
import
migrations
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'
instance'
,
'0009_auto_20190715_0929
'
),
(
'
template'
,
'0007_basetemplate_network_id
'
),
(
'instance'
,
'0009_auto_20190715_1354'
),
]
operations
=
[
migrations
.
AddField
(
model_name
=
'instance'
,
name
=
'template'
,
field
=
models
.
ForeignKey
(
help_text
=
'The base image of the vm'
,
null
=
True
,
on_delete
=
'DO_NOTHING'
,
related_name
=
'vm'
,
to
=
'template.ImageTemplate'
),
),
]
recircle/instance/models.py
View file @
b1fc3c9d
...
...
@@ -15,6 +15,17 @@ ACCESS_METHODS = tuple(
[(
key
,
val
[
0
])
for
key
,
val
in
settings
.
VM_ACCESS_PROTOCOLS
.
items
()]
)
interface
=
OSVirtualMachineManager
(
settings
.
CONNECTION
)
ACTIONS
=
{
"start"
:
interface
.
start_vm
,
"stop"
:
interface
.
stop_vm
,
"suspend"
:
interface
.
suspend_vm
,
"wake_up"
:
interface
.
wake_up_vm
,
"reset"
:
interface
.
reset_vm
,
"reboot"
:
interface
.
reboot_vm
,
}
class
Lease
(
models
.
Model
):
""" Users can use the virtual machine until the lease dates.
...
...
@@ -44,7 +55,6 @@ class Flavor(models.Model):
@classmethod
def
create
(
cls
,
name
,
description
,
ram
=
0
,
vcpu
=
0
,
initial_disk
=
0
,
priority
=
0
):
interface
=
OSVirtualMachineManager
(
settings
.
CONNECTION
)
try
:
remote_flavor
=
interface
.
create_flavor
(
name
,
ram
,
vcpu
,
initial_disk
)
...
...
@@ -55,12 +65,22 @@ class Flavor(models.Model):
return
flavor
except
Exception
as
e
:
logger
.
error
(
str
(
e
))
raise
ValueError
(
"Couldn't create Flavor in remote cloud."
)
raise
ValueError
(
"Can't create Flavor in remote cloud."
)
def
delete
(
self
):
interface
=
OSVirtualMachineManager
(
settings
.
CONNECTION
)
try
:
interface
.
delete_flavor
(
self
.
remote_id
)
super
(
Flavor
,
self
)
.
delete
()
except
Exception
as
e
:
if
e
.
OpenStackError
:
logger
.
error
(
"Can not delete the flavor in remote cloud"
)
class
Instance
(
models
.
Model
):
"""Virtual machine instance.
"""
from
template.models
import
ImageTemplate
name
=
models
.
CharField
(
max_length
=
100
,
help_text
=
"Human readable name of instance"
)
...
...
@@ -92,11 +112,9 @@ class Instance(models.Model):
default
=
False
,
)
# image = models.ForeignKey(TemplateImage, related_name="vm", null=True,
# help_text="The base image of the vm")
#
# snapshot = models.ForeignKey(Snapshot, related_name="vm", null=True,
# help_text="The base snapshot of the vm")
template
=
models
.
ForeignKey
(
ImageTemplate
,
related_name
=
"vm"
,
null
=
True
,
help_text
=
"The base image of the vm"
,
on_delete
=
"DO_NOTHING"
)
disks
=
models
.
ManyToManyField
(
Disk
,
related_name
=
"instance"
,
help_text
=
"Disks attached to instance"
,
...
...
@@ -110,9 +128,11 @@ class Instance(models.Model):
related_name
=
'instances'
)
@classmethod
def
create
(
cls
,
lease
,
owner
,
flavor
,
remote_id
,
params
):
def
create
(
cls
,
lease
,
owner
,
flavor
,
template
,
remote_id
,
params
):
params
[
"password"
]
=
cls
.
generate_password
()
inst
=
cls
(
lease
=
lease
,
flavor
=
flavor
,
owner
=
owner
,
remote_id
=
remote_id
,
**
params
)
remote_id
=
remote_id
,
template
=
template
,
**
params
)
inst
.
full_clean
()
inst
.
save
()
...
...
@@ -123,19 +143,18 @@ class Instance(models.Model):
def
create_instance_from_template
(
cls
,
params
,
template
,
owner
,
lease
,
disks
,
networks
,
flavor
):
# TODO: attach disks when the remote instance created
interface
=
OSVirtualMachineManager
(
settings
.
CONNECTION
)
try
:
remote_i
nst
=
interface
.
create_vm_from_template
(
params
[
"name"
],
template
.
remote_ID
,
remote_i
d
=
interface
.
create_vm_from_template
(
params
[
"name"
],
template
.
image
.
remote_id
,
flavor
.
remote_id
,
networks
,
)
remote_id
=
remote_inst
.
id
new_inst
=
cls
.
create
(
lease
,
owner
,
flavor
,
remote_id
,
params
)
new_inst
=
cls
.
create
(
lease
,
owner
,
flavor
,
template
,
remote_id
,
params
)
return
new_inst
except
Exception
as
e
:
logger
.
error
(
str
(
e
))
raise
ValueError
(
"C
ouldn't create Flavor
in remote cloud."
raise
ValueError
(
"C
an't create Instance
in remote cloud."
"Search the logs for more detail."
)
def
clean
(
self
,
*
args
,
**
kwargs
):
...
...
@@ -153,3 +172,26 @@ class Instance(models.Model):
timezone
.
now
()
+
timedelta
(
seconds
=
lease
.
delete_interval_in_sec
)
)
def
delete
(
self
):
try
:
interface
.
destroy_vm
(
self
.
remote_id
)
super
(
Instance
,
self
)
.
delete
()
except
Exception
as
e
:
if
e
.
OpenStackError
:
logger
.
error
(
"Can not delete the instance in remote cloud"
)
def
execute_common_action
(
self
,
action
):
if
ACTIONS
[
action
]:
return
ACTIONS
[
action
](
self
.
remote_id
)
else
:
raise
ValueError
(
"This action is not supported!"
)
def
get_remote_instance
(
self
):
return
interface
.
get_vm
(
self
.
remote_id
)
@classmethod
def
generate_password
(
self
):
return
User
.
objects
.
make_random_password
(
allowed_chars
=
'abcdefghijklmnopqrstuvwx'
'ABCDEFGHIJKLMNOPQRSTUVWX123456789'
)
recircle/instance/serializers.py
View file @
b1fc3c9d
from
rest_framework
import
serializers
from
.models
import
Flavor
,
Instance
from
.models
import
Flavor
,
Instance
,
Lease
class
InstanceSerializer
(
serializers
.
ModelSerializer
):
...
...
@@ -8,10 +8,26 @@ class InstanceSerializer(serializers.ModelSerializer):
class
Meta
:
model
=
Instance
fields
=
(
"name"
,
"description"
,
"system"
,
"lease"
,
"flavor"
)
fields
=
(
"name"
,
"description"
,
"system"
,
"lease"
,
"flavor"
,
"password"
,
"template"
,
"time_of_suspend"
,
"time_of_delete"
)
read_only_fields
=
(
"password"
,
"template"
,
"time_of_suspend"
,
"time_of_delete"
)
class
FlavorSerializer
(
serializers
.
ModelSerializer
):
class
Meta
:
model
=
Flavor
fields
=
"__all__"
class
LeaseSerializer
(
serializers
.
ModelSerializer
):
class
Meta
:
model
=
Lease
fields
=
'__all__'
recircle/instance/urls.py
View file @
b1fc3c9d
from
django.urls
import
path
from
rest_framework.urlpatterns
import
format_suffix_patterns
from
instance
import
views
from
rest_framework
import
routers
urlpatterns
=
[
path
(
"instances/"
,
views
.
InstanceList
.
as_view
()),
path
(
"instances/<int:pk>/"
,
views
.
InstanceDetail
.
as_view
()),
# path('instances/<int:pk>/action/', views.InstanceAction.as_view())
path
(
"flavors/"
,
views
.
FlavorListView
.
as_view
()),
]
router
=
routers
.
SimpleRouter
()
router
.
register
(
r'instances'
,
views
.
InstanceViewSet
,
basename
=
'instance'
)
router
.
register
(
r'flavors'
,
views
.
FlavorViewSet
,
basename
=
'flavor'
)
router
.
register
(
r'leases'
,
views
.
LeaseViewSet
,
basename
=
'lease'
)
urlpatterns
=
format_suffix_patterns
(
urlpatterns
)
urlpatterns
=
router
.
urls
recircle/instance/views.py
View file @
b1fc3c9d
from
instance.serializers
import
InstanceSerializer
,
FlavorSerializer
,
LeaseSerializer
from
django.http
import
Http404
from
django.conf
import
settings
from
rest_framework.views
import
APIView
from
rest_framework.viewsets
import
ViewSet
,
ModelViewSet
from
rest_framework.response
import
Response
from
rest_framework
import
status
from
rest_framework.decorators
import
action
from
interface_openstack.implementation.vm.instance
import
(
OSVirtualMachineManager
)
from
template.serializers
import
InstanceFromTemplateSerializer
from
instance.models
import
Instance
,
Flavor
,
Lease
from
instance.serializers
import
InstanceSerializer
,
FlavorSerializer
from
template.models
import
ImageTemplate
from
template.serializers
import
ImageTemplateModelSerializer
class
InstanceViewSet
(
ViewSet
):
def
get_object
(
self
,
pk
):
try
:
return
Instance
.
objects
.
get
(
pk
=
pk
)
except
Instance
.
DoesNotExist
:
raise
Http404
class
InstanceList
(
APIView
):
def
get
(
self
,
request
,
format
=
None
):
def
list
(
self
,
request
):
instances
=
Instance
.
objects
.
all
()
return
Response
(
InstanceSerializer
(
instances
,
many
=
True
)
.
data
)
def
post
(
self
,
request
,
format
=
None
):
def
create
(
self
,
request
):
data
=
request
.
data
template
=
ImageTemplate
.
objects
.
get
(
pk
=
data
[
"template"
])
flavor
=
Flavor
.
objects
.
get
(
pk
=
data
[
"flavor"
])
lease
=
Lease
.
objects
.
get
(
pk
=
data
[
"lease"
])
# TODO: if the user can select anouther lease and flavor
# That will be applied, not from the template
# flavor = Flavor.objects.get(pk=data["flavor"])
# lease = Lease.objects.get(pk=data["lease"])
newInstance
=
Instance
.
create_instance_from_template
(
params
=
{
"name"
:
data
[
"name"
],
...
...
@@ -29,40 +39,26 @@ class InstanceList(APIView):
"access_method"
:
data
[
"access"
],
"system"
:
data
[
"system"
],
},
lease
=
lease
,
networks
=
template
.
networks
,
lease
=
template
.
lease
,
networks
=
[{
"uuid"
:
template
.
network_id
}]
,
template
=
template
,
flavor
=
flavor
,
flavor
=
template
.
flavor
,
owner
=
request
.
user
,
disks
=
template
.
disks
disks
=
None
)
return
Response
(
newInstance
.
pk
)
class
InstanceDetail
(
APIView
):
"""
Retrieve, update or delete a snippet instance.
"""
def
get_object
(
self
,
pk
):
try
:
return
Instance
.
objects
.
get
(
pk
=
pk
)
except
Instance
.
DoesNotExist
:
raise
Http404
def
get
(
self
,
request
,
pk
,
format
=
None
):
def
retrieve
(
self
,
request
,
pk
):
instance
=
self
.
get_object
(
pk
)
instanceDict
=
InstanceSerializer
(
instance
)
.
data
interface
=
OSVirtualMachineManager
(
settings
.
CONNECTION
)
remoteInstance
=
interface
.
get_vm
(
instance
.
remote_id
)
remoteInstance
=
instance
.
get_remote_instance
()
remoteInstanceDict
=
remoteInstance
.
__dict__
merged_dict
=
{
**
instanceDict
,
**
remoteInstanceDict
}
return
Response
(
merged_dict
)
def
put
(
self
,
request
,
pk
,
format
=
None
):
def
update
(
self
,
request
,
pk
,
format
=
None
):
instance
=
self
.
get_object
(
pk
)
serializer
=
InstanceSerializer
(
instance
,
data
=
request
.
data
)
if
serializer
.
is_valid
():
...
...
@@ -70,22 +66,48 @@ class InstanceDetail(APIView):
return
Response
(
serializer
.
data
)
return
Response
(
serializer
.
errors
,
status
=
status
.
HTTP_400_BAD_REQUEST
)
def
de
lete
(
self
,
request
,
pk
,
format
=
None
):
def
de
stroy
(
self
,
request
,
pk
,
format
=
None
):
instance
=
self
.
get_object
(
pk
)
instance
.
delete
()
return
Response
(
status
=
status
.
HTTP_204_NO_CONTENT
)
@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
)
class
FlavorListView
(
APIView
):
@action
(
detail
=
True
,
methods
=
[
"POST"
])
def
actions
(
self
,
request
,
pk
):
instance
=
self
.
get_object
(
pk
)
success
=
instance
.
execute_common_action
(
action
=
request
.
data
[
"action"
])
return
Response
(
success
)
class
FlavorViewSet
(
ViewSet
):
"""
Create, update or delete a flavor.
"""
def
get
(
self
,
request
,
format
=
None
):
def
get_object
(
self
,
pk
):
try
:
return
Flavor
.
objects
.
get
(
pk
=
pk
)
except
Flavor
.
DoesNotExist
:
raise
Http404
def
list
(
self
,
request
,
format
=
None
):
flavors
=
Flavor
.
objects
.
all
()
return
Response
(
FlavorSerializer
(
flavors
,
many
=
True
)
.
data
)
def
post
(
self
,
request
,
format
=
None
):
def
create
(
self
,
request
,
format
=
None
):
data
=
request
.
data
new_flavor
=
Flavor
.
create
(
name
=
data
[
"name"
],
description
=
data
[
"description"
],
...
...
@@ -95,3 +117,19 @@ class FlavorListView(APIView):
priority
=
data
[
"priority"
])
return
Response
(
new_flavor
.
pk
)
def
update
(
self
,
request
,
pk
):
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
)
def
partial_update
(
self
,
request
,
pk
):
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
)
def
destroy
(
self
,
request
,
pk
):
flavor
=
self
.
get_object
(
pk
)
flavor
.
delete
()
return
Response
(
status
=
status
.
HTTP_204_NO_CONTENT
)
class
LeaseViewSet
(
ModelViewSet
):
queryset
=
Lease
.
objects
.
all
()
serializer_class
=
LeaseSerializer
interface_openstack
@
1a19e435
Subproject commit
e01d873c78ac17fed0438936f979de3cbaca6a5e
Subproject commit
1a19e4355f4af1abb49a3f6e07dc3a6c3f8bdf47
recircle/template/migrations/0007_basetemplate_network_id.py
0 → 100644
View file @
b1fc3c9d
# Generated by Django 2.2.3 on 2019-08-07 12:19
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'template'
,
'0006_auto_20190719_1416'
),
]
operations
=
[
migrations
.
AddField
(
model_name
=
'basetemplate'
,
name
=
'network_id'
,
field
=
models
.
CharField
(
blank
=
True
,
help_text
=
'The new instance will be in this network.'
,
max_length
=
100
,
null
=
True
,
verbose_name
=
'network_id'
),
),
]
recircle/template/models.py
View file @
b1fc3c9d
...
...
@@ -2,10 +2,8 @@ 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
image.models
import
Disk
,
Image
from
instance.models
import
Lease
,
Flavor
from
interface_openstack.implementation.storage.openstack_snapshot_manager
import
SnapshotManager
...
...
@@ -46,6 +44,13 @@ class BaseTemplate(models.Model):
related_name
=
'templates'
)
lease
=
models
.
ForeignKey
(
Lease
,
on_delete
=
"CASCADE"
,
related_name
=
'templates'
)
network_id
=
models
.
CharField
(
max_length
=
100
,
verbose_name
=
"network_id"
,
help_text
=
"The new instance will be in this network."
,
null
=
True
,
blank
=
True
)
class
DiskTemplate
(
BaseTemplate
):
...
...
recircle/template/views.py
View file @
b1fc3c9d
# from django.shortcuts import render
from
rest_framework.response
import
Response
from
rest_framework.viewsets
import
ModelViewSet
from
rest_framework.decorators
import
action
from
template.serializers
import
InstanceFromTemplateSerializer
from
template.serializers
import
ImageTemplateModelSerializer
from
template.models
import
ImageTemplate
...
...
@@ -38,14 +35,3 @@ class ImageTemplateViewSet(ModelViewSet):
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
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment