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
A prog2-höz tartozó friss repo anyagok itt elérhetőek:
https://git.iit.bme.hu/
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
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
378 additions
and
157 deletions
+378
-157
.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
+60
-18
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/
.vscode/
recircle/db.sqlite3
recircle/clouds.yaml
environment.sh
.idea/
.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 = "*"
...
@@ -13,11 +13,11 @@ django-nose = "*"
[packages]
[packages]
django = "*"
django = "*"
djangorestframework = "*"
djangorestframework = "*"
djoser = "*"
django-cors-headers = "*"
django-cors-headers = "*"
openstacksdk = "*"
openstacksdk = "*"
python-novaclient = "*"
python-novaclient = "*"
keystoneauth1 = "*"
keystoneauth1 = "*"
djoser = "*"
[requires]
[requires]
python_version = "3.6"
python_version = "3.6"
Pipfile.lock
View file @
b1fc3c9d
...
@@ -121,11 +121,11 @@
...
@@ -121,11 +121,11 @@
},
},
"django": {
"django": {
"hashes": [
"hashes": [
"sha256:
4d23f61b26892bac785f07401bc38cbf8fa4cec993f400e9cd9ddf28fd51c0ea
",
"sha256:
16a5d54411599780ac9dfe3b9b38f90f785c51259a584e0b24b6f14a7f69aae8
",
"sha256:
6e974d4b57e3b29e4882b244d40171d6a75202ab8d2402b8e8adbd182e25cf0c
"
"sha256:
9a2f98211ab474c710fcdad29c82f30fc14ce9917c7a70c3682162a624de4035
"
],
],
"index": "pypi",
"index": "pypi",
"version": "==2.2.
3
"
"version": "==2.2.
4
"
},
},
"django-cors-headers": {
"django-cors-headers": {
"hashes": [
"hashes": [
...
@@ -272,11 +272,11 @@
...
@@ -272,11 +272,11 @@
},
},
"openstacksdk": {
"openstacksdk": {
"hashes": [
"hashes": [
"sha256:
dc1232a58e30876ed6b28ee7bf5fee281b70048b187e88acd8a53cc3b63f9d8a
",
"sha256:
ae521b4083ecc3395e27b6a7d0f119a737cefb2f76277f16dc5b626a3c4d5c52
",
"sha256:
f6e045d2e0a111d3a8dd157d111a04f1354ad6cc7819f6c1db073426bea7734f
"
"sha256:
e3a1346a238d57d4f398f345a79d03b6705e229a4453f8b73acdcd00d04e6328
"
],
],
"index": "pypi",
"index": "pypi",
"version": "==0.3
1.2
"
"version": "==0.3
2.0
"
},
},
"os-service-types": {
"os-service-types": {
"hashes": [
"hashes": [
...
@@ -308,10 +308,10 @@
...
@@ -308,10 +308,10 @@
},
},
"pbr": {
"pbr": {
"hashes": [
"hashes": [
"sha256:
0ca44dc9fd3b04a22297c2a91082d8df2894862e8f4c86a49dac69eae9e85ca0
",
"sha256:
56e52299170b9492513c64be44736d27a512fa7e606f21942160b68ce510b4bc
",
"sha256:
4aed6c1b1fa5020def0f22aed663d87b81bb3235f112490b07d2643d7a98c5b5
"
"sha256:
9b321c204a88d8ab5082699469f52cc94c5da45c51f114113d01b3d993c24cdf
"
],
],
"version": "==5.4.
1
"
"version": "==5.4.
2
"
},
},
"prettytable": {
"prettytable": {
"hashes": [
"hashes": [
...
@@ -344,26 +344,28 @@
...
@@ -344,26 +344,28 @@
},
},
"pytz": {
"pytz": {
"hashes": [
"hashes": [
"sha256:
303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda
",
"sha256:
26c0b32e437e54a18161324a2fca3c4b9846b74a8dccddd843113109e1116b32
",
"sha256:
d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141
"
"sha256:
c894d57500a4cd2d5c71114aaab77dbab5eabd9022308ce5ac9bb93a60a6f0c7
"
],
],
"version": "==2019.
1
"
"version": "==2019.
2
"
},
},
"pyyaml": {
"pyyaml": {
"hashes": [
"hashes": [
"sha256:57acc1d8533cbe51f6662a55434f0dbecfa2b9eaf115bede8f6fd00115a0c0d3",
"sha256:0113bc0ec2ad727182326b61326afa3d1d8280ae1122493553fd6f4397f33df9",
"sha256:588c94b3d16b76cfed8e0be54932e5729cc185caffaa5a451e7ad2f7ed8b4043",
"sha256:01adf0b6c6f61bd11af6e10ca52b7d4057dd0be0343eb9283c878cf3af56aee4",
"sha256:68c8dd247f29f9a0d09375c9c6b8fdc64b60810ebf07ba4cdd64ceee3a58c7b7",
"sha256:5124373960b0b3f4aa7df1707e63e9f109b5263eca5976c66e08b1c552d4eaf8",
"sha256:70d9818f1c9cd5c48bb87804f2efc8692f1023dac7f1a1a5c61d454043c1d265",
"sha256:5ca4f10adbddae56d824b2c09668e91219bb178a1eee1faa56af6f99f11bf696",
"sha256:86a93cccd50f8c125286e637328ff4eef108400dd7089b46a7be3445eecfa391",
"sha256:7907be34ffa3c5a32b60b95f4d95ea25361c951383a894fec31be7252b2b6f34",
"sha256:a0f329125a926876f647c9fa0ef32801587a12328b4a3c741270464e3e4fa778",
"sha256:7ec9b2a4ed5cad025c2278a1e6a19c011c80a3caaac804fd2d329e9cc2c287c9",
"sha256:a3c252ab0fa1bb0d5a3f6449a4826732f3eb6c0270925548cac342bc9b22c225",
"sha256:87ae4c829bb25b9fe99cf71fbb2140c448f534e24c998cc60f39ae4f94396a73",
"sha256:b4bb4d3f5e232425e25dda21c070ce05168a786ac9eda43768ab7f3ac2770955",
"sha256:9de9919becc9cc2ff03637872a440195ac4241c80536632fffeb6a1e25a74299",
"sha256:cd0618c5ba5bda5f4039b9398bb7fb6a317bb8298218c3de25c47c4740e4b95e",
"sha256:a5a85b10e450c66b49f98846937e8cfca1db3127a9d5d1e31ca45c3d0bef4c5b",
"sha256:ceacb9e5f8474dcf45b940578591c7f3d960e82f926c707788a570b51ba59190",
"sha256:b0997827b4f6a7c286c01c5f60384d218dca4ed7d9efa945c3e1aa623d5709ae",
"sha256:fe6a88094b64132c4bb3b631412e90032e8cfe9745a58370462240b8cb7553cd"
"sha256:b631ef96d3222e62861443cc89d6563ba3eeb816eeb96b2629345ab795e53681",
],
"sha256:bf47c0607522fdbca6c9e817a6e81b08491de50f3766a7a0e6a5be7905961b41",
"version": "==5.1.1"
"sha256:f81025eddd0327c7d4cfe9b62cf33190e1e736cc6e97502b3ec425f574b3e7a8"
],
"version": "==5.1.2"
},
},
"requests": {
"requests": {
"hashes": [
"hashes": [
...
...
recircle/image/models.py
View file @
b1fc3c9d
...
@@ -86,7 +86,9 @@ class Image(models.Model):
...
@@ -86,7 +86,9 @@ class Image(models.Model):
uploaded_by_user
=
False
,
uploaded_by_user
=
False
,
description
=
description
description
=
description
)
)
return
new_image
for
attr
,
value
in
new_image
.
__dict__
.
items
():
setattr
(
remote_image
,
attr
,
value
)
return
remote_image
@classmethod
@classmethod
def
create_from_user
(
cls
,
description
,
def
create_from_user
(
cls
,
description
,
...
@@ -102,4 +104,24 @@ class Image(models.Model):
...
@@ -102,4 +104,24 @@ class Image(models.Model):
uploaded_by_user
=
True
,
uploaded_by_user
=
True
,
description
=
description
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
...
@@ -3,9 +3,15 @@ from rest_framework import serializers
from
.models
import
Image
from
.models
import
Image
class
ImageUpdateSerializer
(
serializers
.
Serializer
):
name
=
serializers
.
CharField
(
required
=
False
)
description
=
serializers
.
CharField
(
required
=
False
)
class
ImageSerializer
(
serializers
.
ModelSerializer
):
class
ImageSerializer
(
serializers
.
ModelSerializer
):
image_file
=
serializers
.
FileField
(
write_only
=
True
)
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
:
class
Meta
:
model
=
Image
model
=
Image
...
@@ -18,5 +24,7 @@ class ImageSerializer(serializers.ModelSerializer):
...
@@ -18,5 +24,7 @@ class ImageSerializer(serializers.ModelSerializer):
"created_at"
,
"created_at"
,
"uploaded_by_user"
,
"uploaded_by_user"
,
"created_by"
,
"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 django.shortcuts import render
from
rest_framework.viewsets
import
Model
ViewSet
from
rest_framework.viewsets
import
ViewSet
from
rest_framework.response
import
Response
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.models
import
Image
from
image.serializers
import
ImageSerializer
from
image.serializers
import
ImageSerializer
from
image.serializers
import
ImageUpdateSerializer
class
ImageViewSet
(
ModelViewSet
):
class
ImageViewSet
(
ViewSet
):
serializer_class
=
ImageSerializer
queryset
=
Image
.
objects
.
all
()
def
list
(
self
,
request
):
# def list(self, request):
image_list
=
[]
# return HttpResponse("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
):
def
create
(
self
,
request
):
serializer
=
ImageSerializer
(
data
=
request
.
data
)
serializer
=
ImageSerializer
(
data
=
request
.
data
)
...
@@ -26,14 +34,30 @@ class ImageViewSet(ModelViewSet):
...
@@ -26,14 +34,30 @@ class ImageViewSet(ModelViewSet):
serializer
=
ImageSerializer
(
instance
=
new_image
)
serializer
=
ImageSerializer
(
instance
=
new_image
)
return
Response
(
serializer
.
data
)
return
Response
(
serializer
.
data
)
# def retrieve(self, request, pk=None):
def
retrieve
(
self
,
request
,
pk
=
None
):
# return HttpResponse("retrive")
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):
def
update
(
self
,
request
,
pk
=
None
):
# return HttpResponse("update")
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):
def
partial_update
(
self
,
request
,
pk
=
None
):
# return HttpResponse("patch"
)
return
self
.
update
(
request
,
pk
)
# def destroy(self, request, pk=None):
def
destroy
(
self
,
request
,
pk
=
None
):
# return HttpResponse("delete")
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
):
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
dependencies
=
[
(
'
instance'
,
'0009_auto_20190715_0929
'
),
(
'
template'
,
'0007_basetemplate_network_id
'
),
(
'instance'
,
'0009_auto_20190715_1354'
),
(
'instance'
,
'0009_auto_20190715_1354'
),
]
]
operations
=
[
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(
...
@@ -15,6 +15,17 @@ ACCESS_METHODS = tuple(
[(
key
,
val
[
0
])
for
key
,
val
in
settings
.
VM_ACCESS_PROTOCOLS
.
items
()]
[(
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
):
class
Lease
(
models
.
Model
):
""" Users can use the virtual machine until the lease dates.
""" Users can use the virtual machine until the lease dates.
...
@@ -44,7 +55,6 @@ class Flavor(models.Model):
...
@@ -44,7 +55,6 @@ class Flavor(models.Model):
@classmethod
@classmethod
def
create
(
cls
,
name
,
description
,
ram
=
0
,
vcpu
=
0
,
def
create
(
cls
,
name
,
description
,
ram
=
0
,
vcpu
=
0
,
initial_disk
=
0
,
priority
=
0
):
initial_disk
=
0
,
priority
=
0
):
interface
=
OSVirtualMachineManager
(
settings
.
CONNECTION
)
try
:
try
:
remote_flavor
=
interface
.
create_flavor
(
name
,
ram
,
vcpu
,
initial_disk
)
remote_flavor
=
interface
.
create_flavor
(
name
,
ram
,
vcpu
,
initial_disk
)
...
@@ -55,12 +65,22 @@ class Flavor(models.Model):
...
@@ -55,12 +65,22 @@ class Flavor(models.Model):
return
flavor
return
flavor
except
Exception
as
e
:
except
Exception
as
e
:
logger
.
error
(
str
(
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
):
class
Instance
(
models
.
Model
):
"""Virtual machine instance.
"""Virtual machine instance.
"""
"""
from
template.models
import
ImageTemplate
name
=
models
.
CharField
(
max_length
=
100
,
name
=
models
.
CharField
(
max_length
=
100
,
help_text
=
"Human readable name of instance"
)
help_text
=
"Human readable name of instance"
)
...
@@ -92,11 +112,9 @@ class Instance(models.Model):
...
@@ -92,11 +112,9 @@ class Instance(models.Model):
default
=
False
,
default
=
False
,
)
)
# image = models.ForeignKey(TemplateImage, related_name="vm", null=True,
template
=
models
.
ForeignKey
(
ImageTemplate
,
related_name
=
"vm"
,
null
=
True
,
# help_text="The base image of the vm")
help_text
=
"The base image of the vm"
,
#
on_delete
=
"DO_NOTHING"
)
# snapshot = models.ForeignKey(Snapshot, related_name="vm", null=True,
# help_text="The base snapshot of the vm")
disks
=
models
.
ManyToManyField
(
Disk
,
related_name
=
"instance"
,
disks
=
models
.
ManyToManyField
(
Disk
,
related_name
=
"instance"
,
help_text
=
"Disks attached to instance"
,
help_text
=
"Disks attached to instance"
,
...
@@ -110,9 +128,11 @@ class Instance(models.Model):
...
@@ -110,9 +128,11 @@ class Instance(models.Model):
related_name
=
'instances'
)
related_name
=
'instances'
)
@classmethod
@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
,
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
()
inst
.
save
()
...
@@ -123,19 +143,18 @@ class Instance(models.Model):
...
@@ -123,19 +143,18 @@ class Instance(models.Model):
def
create_instance_from_template
(
cls
,
params
,
template
,
owner
,
lease
,
def
create_instance_from_template
(
cls
,
params
,
template
,
owner
,
lease
,
disks
,
networks
,
flavor
):
disks
,
networks
,
flavor
):
# TODO: attach disks when the remote instance created
# TODO: attach disks when the remote instance created
interface
=
OSVirtualMachineManager
(
settings
.
CONNECTION
)
try
:
try
:
remote_i
nst
=
interface
.
create_vm_from_template
(
params
[
"name"
],
remote_i
d
=
interface
.
create_vm_from_template
(
params
[
"name"
],
template
.
remote_ID
,
template
.
image
.
remote_id
,
flavor
.
remote_id
,
flavor
.
remote_id
,
networks
,
networks
,
)
)
remote_id
=
remote_inst
.
id
new_inst
=
cls
.
create
(
lease
,
owner
,
flavor
,
template
,
new_inst
=
cls
.
create
(
lease
,
owner
,
flavor
,
remote_id
,
params
)
remote_id
,
params
)
return
new_inst
return
new_inst
except
Exception
as
e
:
except
Exception
as
e
:
logger
.
error
(
str
(
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."
)
"Search the logs for more detail."
)
def
clean
(
self
,
*
args
,
**
kwargs
):
def
clean
(
self
,
*
args
,
**
kwargs
):
...
@@ -153,3 +172,26 @@ class Instance(models.Model):
...
@@ -153,3 +172,26 @@ class Instance(models.Model):
timezone
.
now
()
+
timedelta
(
timezone
.
now
()
+
timedelta
(
seconds
=
lease
.
delete_interval_in_sec
)
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
rest_framework
import
serializers
from
.models
import
Flavor
,
Instance
from
.models
import
Flavor
,
Instance
,
Lease
class
InstanceSerializer
(
serializers
.
ModelSerializer
):
class
InstanceSerializer
(
serializers
.
ModelSerializer
):
...
@@ -8,10 +8,26 @@ class InstanceSerializer(serializers.ModelSerializer):
...
@@ -8,10 +8,26 @@ class InstanceSerializer(serializers.ModelSerializer):
class
Meta
:
class
Meta
:
model
=
Instance
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
FlavorSerializer
(
serializers
.
ModelSerializer
):
class
Meta
:
class
Meta
:
model
=
Flavor
model
=
Flavor
fields
=
"__all__"
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
instance
import
views
from
rest_framework
import
routers
urlpatterns
=
[
router
=
routers
.
SimpleRouter
()
path
(
"instances/"
,
views
.
InstanceList
.
as_view
()),
router
.
register
(
r'instances'
,
views
.
InstanceViewSet
,
basename
=
'instance'
)
path
(
"instances/<int:pk>/"
,
views
.
InstanceDetail
.
as_view
()),
router
.
register
(
r'flavors'
,
views
.
FlavorViewSet
,
basename
=
'flavor'
)
# path('instances/<int:pk>/action/', views.InstanceAction.as_view())
router
.
register
(
r'leases'
,
views
.
LeaseViewSet
,
basename
=
'lease'
)
path
(
"flavors/"
,
views
.
FlavorListView
.
as_view
()),
]
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.http
import
Http404
from
django.conf
import
settings
from
rest_framework.viewsets
import
ViewSet
,
ModelViewSet
from
rest_framework.views
import
APIView
from
rest_framework.response
import
Response
from
rest_framework.response
import
Response
from
rest_framework
import
status
from
rest_framework
import
status
from
rest_framework.decorators
import
action
from
interface_openstack.implementation.vm.instance
import
(
from
template.serializers
import
InstanceFromTemplateSerializer
OSVirtualMachineManager
)
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
from
template.models
import
ImageTemplate
from
template.serializers
import
ImageTemplateModelSerializer
class
InstanceList
(
APIView
):
class
InstanceViewSet
(
ViewSet
):
def
get
(
self
,
request
,
format
=
None
):
def
get_object
(
self
,
pk
):
try
:
return
Instance
.
objects
.
get
(
pk
=
pk
)
except
Instance
.
DoesNotExist
:
raise
Http404
def
list
(
self
,
request
):
instances
=
Instance
.
objects
.
all
()
instances
=
Instance
.
objects
.
all
()
return
Response
(
InstanceSerializer
(
instances
,
many
=
True
)
.
data
)
return
Response
(
InstanceSerializer
(
instances
,
many
=
True
)
.
data
)
def
post
(
self
,
request
,
format
=
None
):
def
create
(
self
,
request
):
data
=
request
.
data
data
=
request
.
data
template
=
ImageTemplate
.
objects
.
get
(
pk
=
data
[
"template"
])
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
(
newInstance
=
Instance
.
create_instance_from_template
(
params
=
{
"name"
:
data
[
"name"
],
params
=
{
"name"
:
data
[
"name"
],
...
@@ -29,40 +39,26 @@ class InstanceList(APIView):
...
@@ -29,40 +39,26 @@ class InstanceList(APIView):
"access_method"
:
data
[
"access"
],
"access_method"
:
data
[
"access"
],
"system"
:
data
[
"system"
],
"system"
:
data
[
"system"
],
},
},
lease
=
lease
,
lease
=
template
.
lease
,
networks
=
template
.
networks
,
networks
=
[{
"uuid"
:
template
.
network_id
}]
,
template
=
template
,
template
=
template
,
flavor
=
flavor
,
flavor
=
template
.
flavor
,
owner
=
request
.
user
,
owner
=
request
.
user
,
disks
=
template
.
disks
disks
=
None
)
)
return
Response
(
newInstance
.
pk
)
return
Response
(
newInstance
.
pk
)
def
retrieve
(
self
,
request
,
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
):
instance
=
self
.
get_object
(
pk
)
instance
=
self
.
get_object
(
pk
)
instanceDict
=
InstanceSerializer
(
instance
)
.
data
instanceDict
=
InstanceSerializer
(
instance
)
.
data
remoteInstance
=
instance
.
get_remote_instance
()
interface
=
OSVirtualMachineManager
(
settings
.
CONNECTION
)
remoteInstance
=
interface
.
get_vm
(
instance
.
remote_id
)
remoteInstanceDict
=
remoteInstance
.
__dict__
remoteInstanceDict
=
remoteInstance
.
__dict__
merged_dict
=
{
**
instanceDict
,
**
remoteInstanceDict
}
merged_dict
=
{
**
instanceDict
,
**
remoteInstanceDict
}
return
Response
(
merged_dict
)
return
Response
(
merged_dict
)
def
put
(
self
,
request
,
pk
,
format
=
None
):
def
update
(
self
,
request
,
pk
,
format
=
None
):
instance
=
self
.
get_object
(
pk
)
instance
=
self
.
get_object
(
pk
)
serializer
=
InstanceSerializer
(
instance
,
data
=
request
.
data
)
serializer
=
InstanceSerializer
(
instance
,
data
=
request
.
data
)
if
serializer
.
is_valid
():
if
serializer
.
is_valid
():
...
@@ -70,22 +66,48 @@ class InstanceDetail(APIView):
...
@@ -70,22 +66,48 @@ class InstanceDetail(APIView):
return
Response
(
serializer
.
data
)
return
Response
(
serializer
.
data
)
return
Response
(
serializer
.
errors
,
status
=
status
.
HTTP_400_BAD_REQUEST
)
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
=
self
.
get_object
(
pk
)
instance
.
delete
()
instance
.
delete
()
return
Response
(
status
=
status
.
HTTP_204_NO_CONTENT
)
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
)
@action
(
detail
=
True
,
methods
=
[
"POST"
])
def
actions
(
self
,
request
,
pk
):
instance
=
self
.
get_object
(
pk
)
success
=
instance
.
execute_common_action
(
action
=
request
.
data
[
"action"
])
class
FlavorListView
(
APIView
):
return
Response
(
success
)
class
FlavorViewSet
(
ViewSet
):
"""
"""
Create, update or delete a flavor.
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
()
flavors
=
Flavor
.
objects
.
all
()
return
Response
(
FlavorSerializer
(
flavors
,
many
=
True
)
.
data
)
return
Response
(
FlavorSerializer
(
flavors
,
many
=
True
)
.
data
)
def
post
(
self
,
request
,
format
=
None
):
def
create
(
self
,
request
,
format
=
None
):
data
=
request
.
data
data
=
request
.
data
new_flavor
=
Flavor
.
create
(
name
=
data
[
"name"
],
new_flavor
=
Flavor
.
create
(
name
=
data
[
"name"
],
description
=
data
[
"description"
],
description
=
data
[
"description"
],
...
@@ -95,3 +117,19 @@ class FlavorListView(APIView):
...
@@ -95,3 +117,19 @@ class FlavorListView(APIView):
priority
=
data
[
"priority"
])
priority
=
data
[
"priority"
])
return
Response
(
new_flavor
.
pk
)
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
...
@@ -2,10 +2,8 @@ from django.db import models
from
django.contrib.auth.models
import
User
from
django.contrib.auth.models
import
User
from
django.conf
import
settings
from
django.conf
import
settings
from
image.models
import
Disk
from
image.models
import
Disk
,
Image
from
image.models
import
Image
from
instance.models
import
Lease
,
Flavor
from
instance.models
import
Lease
from
instance.models
import
Flavor
from
interface_openstack.implementation.storage.openstack_snapshot_manager
import
SnapshotManager
from
interface_openstack.implementation.storage.openstack_snapshot_manager
import
SnapshotManager
...
@@ -46,6 +44,13 @@ class BaseTemplate(models.Model):
...
@@ -46,6 +44,13 @@ class BaseTemplate(models.Model):
related_name
=
'templates'
)
related_name
=
'templates'
)
lease
=
models
.
ForeignKey
(
Lease
,
on_delete
=
"CASCADE"
,
lease
=
models
.
ForeignKey
(
Lease
,
on_delete
=
"CASCADE"
,
related_name
=
'templates'
)
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
):
class
DiskTemplate
(
BaseTemplate
):
...
...
recircle/template/views.py
View file @
b1fc3c9d
# from django.shortcuts import render
# from django.shortcuts import render
from
rest_framework.response
import
Response
from
rest_framework.response
import
Response
from
rest_framework.viewsets
import
ModelViewSet
from
rest_framework.viewsets
import
ModelViewSet
from
rest_framework.decorators
import
action
from
template.serializers
import
InstanceFromTemplateSerializer
from
template.serializers
import
ImageTemplateModelSerializer
from
template.serializers
import
ImageTemplateModelSerializer
from
template.models
import
ImageTemplate
from
template.models
import
ImageTemplate
...
@@ -38,14 +35,3 @@ class ImageTemplateViewSet(ModelViewSet):
...
@@ -38,14 +35,3 @@ class ImageTemplateViewSet(ModelViewSet):
request
.
data
.
pop
(
key
,
None
)
request
.
data
.
pop
(
key
,
None
)
return
super
(
ImageTemplateViewSet
,
self
)
.
update
(
request
,
partial
=
True
)
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