Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
CIRCLE
/
cloud
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
94
Merge Requests
10
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
04394fdf
authored
Mar 12, 2017
by
Fukász Rómeó Ervin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
occi: implemented network and storage with the links
compute instances can now be modified minor bug fixes
parent
17a73b8c
Pipeline
#443
failed with stage
in 0 seconds
Changes
9
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
655 additions
and
72 deletions
+655
-72
circle/circle/settings/base.py
+1
-0
circle/occi/forms.py
+18
-0
circle/occi/occi_client_example.py
+70
-8
circle/occi/occi_core.py
+19
-0
circle/occi/occi_infrastructure.py
+244
-35
circle/occi/occi_instances.py
+53
-8
circle/occi/occi_utils.py
+24
-0
circle/occi/urls.py
+25
-1
circle/occi/views.py
+201
-20
No files found.
circle/circle/settings/base.py
View file @
04394fdf
...
@@ -358,6 +358,7 @@ LOCAL_APPS = (
...
@@ -358,6 +358,7 @@ LOCAL_APPS = (
'acl'
,
'acl'
,
'monitor'
,
'monitor'
,
'request'
,
'request'
,
'occi'
,
)
)
# See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
# See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
...
...
circle/occi/forms.py
View file @
04394fdf
# Copyright 2017 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from
django.contrib.auth.forms
import
AuthenticationForm
from
django.contrib.auth.forms
import
AuthenticationForm
from
django.contrib.auth
import
login
from
django.contrib.auth
import
login
class
OcciAuthForm
(
AuthenticationForm
):
class
OcciAuthForm
(
AuthenticationForm
):
""" An authentication form for the OCCI implementation. """
""" An authentication form for the OCCI implementation. """
def
__init__
(
self
,
request
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
request
,
*
args
,
**
kwargs
):
super
(
OcciAuthForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
super
(
OcciAuthForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
request
=
request
self
.
request
=
request
...
...
circle/occi/occi_client_example.py
View file @
04394fdf
# Copyright 2017 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
import
requests
import
requests
import
json
import
json
# import urllib3
# import urllib3
...
@@ -16,6 +33,7 @@ loginData = {"username": username, "password": password}
...
@@ -16,6 +33,7 @@ loginData = {"username": username, "password": password}
# Csinalunk egy sessiont, hogy a cookie ami az auth-ert felelos
# Csinalunk egy sessiont, hogy a cookie ami az auth-ert felelos
# automatikusan benne maradjon az osszes keresunkben
# automatikusan benne maradjon az osszes keresunkben
with
requests
.
Session
()
as
session
:
with
requests
.
Session
()
as
session
:
session
.
timeout
=
None
headers
=
{
"Content-Type"
:
"application/json"
,
"Referer"
:
server
}
headers
=
{
"Content-Type"
:
"application/json"
,
"Referer"
:
server
}
# Csrf-Token a bejelentkezeshez
# Csrf-Token a bejelentkezeshez
req
=
session
.
get
(
server
+
"occi/login/"
,
headers
=
headers
,
req
=
session
.
get
(
server
+
"occi/login/"
,
headers
=
headers
,
...
@@ -68,7 +86,7 @@ with requests.Session() as session:
...
@@ -68,7 +86,7 @@ with requests.Session() as session:
vmid
=
json
.
loads
(
req
.
text
)[
"resources"
][
0
][
"id"
]
vmid
=
json
.
loads
(
req
.
text
)[
"resources"
][
0
][
"id"
]
req
=
session
.
get
(
server
+
"occi/compute/"
+
vmid
+
"/"
,
req
=
session
.
get
(
server
+
"occi/compute/"
+
vmid
+
"/"
,
headers
=
headers
,
verify
=
False
)
headers
=
headers
,
verify
=
False
)
print
(
"compute-"
+
str
(
vmid
))
print
(
"compute-"
+
str
(
vmid
))
print
(
"------------"
)
print
(
"------------"
)
print
(
"status_code: "
+
str
(
req
.
status_code
))
print
(
"status_code: "
+
str
(
req
.
status_code
))
print
print
...
@@ -100,12 +118,12 @@ with requests.Session() as session:
...
@@ -100,12 +118,12 @@ with requests.Session() as session:
headers
[
"X-CSRFToken"
]
=
req
.
cookies
[
'csrftoken'
]
headers
[
"X-CSRFToken"
]
=
req
.
cookies
[
'csrftoken'
]
except
:
except
:
pass
pass
actionatrs
=
{
"method"
:
"
cold
"
}
actionatrs
=
{
"method"
:
"
warm
"
}
actioninv
=
{
"action"
:
action
+
"restart"
,
"attributes"
:
actionatrs
}
actioninv
=
{
"action"
:
action
+
"restart"
,
"attributes"
:
actionatrs
}
req
=
session
.
post
(
server
+
"occi/compute/"
+
vmid
+
"/"
,
req
=
session
.
post
(
server
+
"occi/compute/"
+
vmid
+
"/"
,
headers
=
headers
,
verify
=
False
,
headers
=
headers
,
verify
=
False
,
data
=
json
.
dumps
(
actioninv
))
data
=
json
.
dumps
(
actioninv
))
print
(
"compute-"
+
str
(
vmid
)
+
"-restart"
)
print
(
"compute-"
+
str
(
vmid
)
+
"-restart"
)
print
(
"-----------------"
)
print
(
"-----------------"
)
print
(
"status_code: "
+
str
(
req
.
status_code
))
print
(
"status_code: "
+
str
(
req
.
status_code
))
print
print
...
@@ -118,12 +136,12 @@ with requests.Session() as session:
...
@@ -118,12 +136,12 @@ with requests.Session() as session:
headers
[
"X-CSRFToken"
]
=
req
.
cookies
[
'csrftoken'
]
headers
[
"X-CSRFToken"
]
=
req
.
cookies
[
'csrftoken'
]
except
:
except
:
pass
pass
actioninv
[
"action"
]
=
action
+
"s
uspend
"
actioninv
[
"action"
]
=
action
+
"s
top
"
actioninv
[
"attributes"
][
"method"
]
=
"
suspend
"
actioninv
[
"attributes"
][
"method"
]
=
"
graceful
"
req
=
session
.
post
(
server
+
"occi/compute/"
+
vmid
+
"/"
,
req
=
session
.
post
(
server
+
"occi/compute/"
+
vmid
+
"/"
,
headers
=
headers
,
verify
=
False
,
headers
=
headers
,
verify
=
False
,
data
=
json
.
dumps
(
actioninv
))
data
=
json
.
dumps
(
actioninv
))
print
(
"compute-"
+
str
(
vmid
)
+
"-s
uspend
"
)
print
(
"compute-"
+
str
(
vmid
)
+
"-s
top
"
)
print
(
"-----------------"
)
print
(
"-----------------"
)
print
(
"status_code: "
+
str
(
req
.
status_code
))
print
(
"status_code: "
+
str
(
req
.
status_code
))
print
print
...
@@ -136,11 +154,11 @@ with requests.Session() as session:
...
@@ -136,11 +154,11 @@ with requests.Session() as session:
headers
[
"X-CSRFToken"
]
=
req
.
cookies
[
"csrftoken"
]
headers
[
"X-CSRFToken"
]
=
req
.
cookies
[
"csrftoken"
]
except
:
except
:
pass
pass
actioninv
[
"action"
]
=
action
+
"
noaction
"
actioninv
[
"action"
]
=
action
+
"
renew
"
req
=
session
.
post
(
server
+
"occi/compute/"
+
vmid
+
"/"
,
req
=
session
.
post
(
server
+
"occi/compute/"
+
vmid
+
"/"
,
headers
=
headers
,
verify
=
False
,
headers
=
headers
,
verify
=
False
,
data
=
json
.
dumps
(
actioninv
))
data
=
json
.
dumps
(
actioninv
))
print
(
"compute-"
+
str
(
vmid
)
+
"-
noaction
"
)
print
(
"compute-"
+
str
(
vmid
)
+
"-
renew
"
)
print
(
"-------------------"
)
print
(
"-------------------"
)
print
(
"status_code: "
+
str
(
req
.
status_code
))
print
(
"status_code: "
+
str
(
req
.
status_code
))
print
print
...
@@ -186,6 +204,50 @@ with requests.Session() as session:
...
@@ -186,6 +204,50 @@ with requests.Session() as session:
indent
=
4
,
separators
=
(
","
,
": "
)))
indent
=
4
,
separators
=
(
","
,
": "
)))
print
print
try
:
headers
[
"X-CSRFToken"
]
=
req
.
cookies
[
"csrftoken"
]
except
:
pass
req
=
session
.
get
(
server
+
"occi/network/1/"
,
headers
=
headers
,
verify
=
False
)
print
(
"storage"
)
print
(
"-------"
)
print
(
"status_code "
+
str
(
req
.
status_code
))
print
print
(
json
.
dumps
(
json
.
loads
(
req
.
text
),
sort_keys
=
True
,
indent
=
4
,
separators
=
(
","
,
": "
)))
try
:
headers
[
"X-CSRFToken"
]
=
req
.
cookies
[
"csrftoken"
]
except
:
pass
req
=
session
.
post
(
server
+
"occi/network/1/"
,
headers
=
headers
,
verify
=
False
,
data
=
json
.
dumps
({
"action"
:
"online"
}))
print
(
"storage"
)
print
(
"-------"
)
print
(
"status_code "
+
str
(
req
.
status_code
))
print
print
(
json
.
dumps
(
json
.
loads
(
req
.
text
),
sort_keys
=
True
,
indent
=
4
,
separators
=
(
","
,
": "
)))
try
:
headers
[
"X-CSRFToken"
]
=
req
.
cookies
[
"csrftoken"
]
except
:
pass
req
=
session
.
post
(
server
+
"occi/compute/96/"
,
headers
=
headers
,
verify
=
False
,
data
=
json
.
dumps
(
{
"attributes"
:
{
"occi.compute.memory"
:
0.250
}
}))
print
(
"computerehelelel"
)
print
(
"-------"
)
print
(
"status_code "
+
str
(
req
.
status_code
))
print
print
(
json
.
dumps
(
json
.
loads
(
req
.
text
),
sort_keys
=
True
,
indent
=
4
,
separators
=
(
","
,
": "
)))
# Kijelentkezes
# Kijelentkezes
req
=
session
.
get
(
server
+
"occi/logout/"
,
headers
=
headers
,
req
=
session
.
get
(
server
+
"occi/logout/"
,
headers
=
headers
,
verify
=
False
)
verify
=
False
)
...
...
circle/occi/occi_core.py
View file @
04394fdf
# Copyright 2017 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
""" Implementation of the OCCI - Core model classes """
""" Implementation of the OCCI - Core model classes """
...
@@ -75,6 +93,7 @@ class Kind(Category):
...
@@ -75,6 +93,7 @@ class Kind(Category):
class
Action
(
Category
):
class
Action
(
Category
):
""" OCCI 1.2 - CORE - Classification - Action """
""" OCCI 1.2 - CORE - Classification - Action """
def
__init
(
self
,
*
args
,
**
kwargs
):
def
__init
(
self
,
*
args
,
**
kwargs
):
super
(
Action
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
super
(
Action
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
...
...
circle/occi/occi_infrastructure.py
View file @
04394fdf
# Copyright 2017 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
""" Implementation of the OCCI - Infrastructure extension classes """
""" Implementation of the OCCI - Infrastructure extension classes """
from
occi_core
import
Resource
from
occi_core
import
Resource
,
Link
from
occi_utils
import
action_list_for_resource
,
OcciActionInvocationError
from
occi_utils
import
action_list_for_resource
,
OcciActionInvocationError
from
occi_instances
import
COMPUTE_ACTIONS
from
occi_instances
import
(
COMPUTE_ACTIONS
,
LEASETIME_ACTIONS
,
STORAGE_ACTIONS
,
NETWORK_ACTIONS
)
from
common.models
import
HumanReadableException
from
common.models
import
HumanReadableException
from
vm.models
import
InstanceActivity
from
celery.exceptions
import
TimeoutError
import
logging
logger
=
logging
.
getLogger
(
__name__
)
COMPUTE_STATES
=
{
COMPUTE_STATES
=
{
...
@@ -36,16 +59,21 @@ COMPUTE_ARCHITECTURES = {"x86_64": "x64",
...
@@ -36,16 +59,21 @@ COMPUTE_ARCHITECTURES = {"x86_64": "x64",
class
Compute
(
Resource
):
class
Compute
(
Resource
):
""" OCCI 1.2 - Infrastructure extension - Compute """
""" OCCI 1.2 - Infrastructure extension - Compute """
def
__init__
(
self
,
vm
):
def
__init__
(
self
,
vm
):
""" Creates a Compute instance of a VM instance object """
""" Creates a Compute instance of a VM instance object """
super
(
Compute
,
self
)
.
__init__
(
super
(
Compute
,
self
)
.
__init__
(
"http://schemas.ogf.org/occi/infrastructure#compute"
,
"http://schemas.ogf.org/occi/infrastructure#compute"
,
str
(
vm
.
pk
))
str
(
vm
.
pk
),
title
=
vm
.
name
)
self
.
vm
=
vm
self
.
vm
=
vm
self
.
attributes
=
self
.
set_attributes
()
self
.
attributes
=
self
.
set_attributes
()
self
.
actions
=
action_list_for_resource
(
COMPUTE_ACTIONS
)
self
.
links
=
self
.
set_links
()
self
.
actions
=
action_list_for_resource
(
COMPUTE_ACTIONS
+
LEASETIME_ACTIONS
)
self
.
mixins
=
[
self
.
mixins
=
[
"http://circlecloud.org/occi/infrastructure#credentials"
,
"http://circlecloud.org/occi/infrastructure/compute#credentials"
,
"http://circlecloud.org/occi/infrastructure/compute#leasetime"
,
]
]
if
vm
.
template
:
if
vm
.
template
:
self
.
mixins
.
append
(
self
.
mixins
.
append
(
...
@@ -56,7 +84,6 @@ class Compute(Resource):
...
@@ -56,7 +84,6 @@ class Compute(Resource):
""" Sets the attributes of the Compute object based on the VM
""" Sets the attributes of the Compute object based on the VM
instance. """
instance. """
attributes
=
{}
attributes
=
{}
attributes
[
"occi.core.title"
]
=
self
.
vm
.
name
attributes
[
"occi.compute.architecture"
]
=
(
attributes
[
"occi.compute.architecture"
]
=
(
COMPUTE_ARCHITECTURES
.
get
(
self
.
vm
.
arch
))
COMPUTE_ARCHITECTURES
.
get
(
self
.
vm
.
arch
))
attributes
[
"occi.compute.cores"
]
=
self
.
vm
.
num_cores
attributes
[
"occi.compute.cores"
]
=
self
.
vm
.
num_cores
...
@@ -77,38 +104,48 @@ class Compute(Resource):
...
@@ -77,38 +104,48 @@ class Compute(Resource):
self
.
vm
.
pw
)
self
.
vm
.
pw
)
attributes
[
"org.circlecloud.occi.credentials.command"
]
=
(
attributes
[
"org.circlecloud.occi.credentials.command"
]
=
(
self
.
vm
.
get_connect_command
())
self
.
vm
.
get_connect_command
())
attributes
[
"org.circlecloud.occi.leasetime.suspend"
]
=
(
unicode
(
self
.
vm
.
time_of_suspend
)[:
-
16
])
attributes
[
"org.circlecloud.occi.leasetime.remove"
]
=
(
unicode
(
self
.
vm
.
time_of_delete
)[:
-
16
])
return
attributes
return
attributes
def
set_links
(
self
):
links
=
[]
disks
=
self
.
vm
.
disks
.
all
()
storages
=
[]
for
disk
in
disks
:
storages
.
append
(
Storage
(
disk
))
for
storage
in
storages
:
links
.
append
(
StorageLink
(
self
,
storage
)
.
render_as_json
())
nics
=
[
NetworkInterface
(
self
,
Network
(
nic
.
vlan
))
for
nic
in
self
.
vm
.
interface_set
.
all
()]
for
networkinterface
in
nics
:
links
.
append
(
networkinterface
.
render_as_json
())
return
links
def
invoke_action
(
self
,
user
,
action
,
attributes
):
def
invoke_action
(
self
,
user
,
action
,
attributes
):
base
=
"http://schemas.ogf.org/occi/infrastructure/compute/action#"
if
action
.
endswith
(
"start"
):
if
action
==
(
base
+
"start"
):
self
.
start
(
user
)
self
.
start
(
user
)
elif
action
==
(
base
+
"stop"
):
elif
action
.
endswith
(
"stop"
):
self
.
stop
(
user
,
attributes
)
self
.
stop
(
user
,
attributes
)
elif
action
==
(
base
+
"restart"
):
elif
action
.
endswith
(
"restart"
):
self
.
restart
(
user
,
attributes
)
self
.
restart
(
user
,
attributes
)
elif
action
==
(
base
+
"suspend"
):
elif
action
.
endswith
(
"suspend"
):
self
.
suspend
(
user
,
attributes
)
self
.
suspend
(
user
,
attributes
)
elif
action
==
(
base
+
"save"
):
elif
action
.
endswith
(
"save"
):
self
.
save
(
user
,
attributes
)
self
.
save
(
user
,
attributes
)
elif
action
.
endswith
(
"renew"
):
self
.
renew
(
user
)
else
:
else
:
raise
OcciActionInvocationError
(
message
=
"Undefined action."
)
raise
OcciActionInvocationError
(
message
=
"Undefined action."
)
# to refresh Compute attribute
self
.
__init__
(
self
.
vm
)
self
.
__init__
(
self
.
vm
)
def
has_agent
(
self
):
def
renew
(
self
,
user
):
last_boot_time
=
self
.
vm
.
activity_log
.
filter
(
succeeded
=
True
,
activity_code__in
=
(
"vm.Instance.deploy"
,
"vm.Instance.reset"
,
"vm.Instance.reboot"
))
.
latest
(
"finished"
)
.
finished
try
:
try
:
InstanceActivity
.
objects
.
filter
(
self
.
vm
.
renew
(
user
=
user
,
force
=
True
)
activity_code
=
"vm.Instance.agent.starting"
,
except
HumanReadableException
as
e
:
started__gt
=
last_boot_time
,
instance
=
self
.
vm
raise
OcciActionInvocationError
(
message
=
e
.
get_user_text
())
)
.
latest
(
"started"
)
except
InstanceActivity
.
DoesNotExist
:
# no agent since last boot
return
False
return
True
def
start
(
self
,
user
):
def
start
(
self
,
user
):
""" Start action on a compute instance """
""" Start action on a compute instance """
...
@@ -125,13 +162,31 @@ class Compute(Resource):
...
@@ -125,13 +162,31 @@ class Compute(Resource):
if
"method"
not
in
attributes
:
if
"method"
not
in
attributes
:
raise
OcciActionInvocationError
(
message
=
"No method given."
)
raise
OcciActionInvocationError
(
message
=
"No method given."
)
if
attributes
[
"method"
]
in
(
"graceful"
,
"acpioff"
,):
if
attributes
[
"method"
]
in
(
"graceful"
,
"acpioff"
,):
if
not
self
.
has_agent
():
# NOTE: at kene nezni hogy minden except ag kell-e
raise
OcciActionInvocationError
(
timeout
=
self
.
vm
.
shutdown
.
remote_timeout
+
10
message
=
"User agent is required."
)
result
=
None
try
:
try
:
self
.
vm
.
shutdown
(
task
=
None
,
user
=
user
)
task
=
self
.
vm
.
shutdown
.
async
(
user
=
user
)
except
HumanReadableException
as
e
:
except
HumanReadableException
as
e
:
raise
OcciActionInvocationError
(
message
=
e
.
get_user_text
())
logger
.
exception
(
"Could not start operation"
)
result
=
e
except
Exception
as
e
:
logger
.
exception
(
"Could not start operation"
)
result
=
e
else
:
try
:
task
.
get
(
timeout
=
timeout
)
except
TimeoutError
:
logger
.
debug
(
"Result didn't arrive in
%
ss"
,
timeout
,
exc_info
=
True
)
except
HumanReadableException
as
e
:
logger
.
exception
(
e
)
result
=
e
except
Exception
as
e
:
logger
.
debug
(
"Operation failed."
,
exc_info
=
True
)
result
=
e
if
result
:
raise
OcciActionInvocationError
(
unicode
(
result
))
elif
attributes
[
"method"
]
in
(
"poweroff"
,):
elif
attributes
[
"method"
]
in
(
"poweroff"
,):
try
:
try
:
self
.
vm
.
shut_off
(
user
=
user
)
self
.
vm
.
shut_off
(
user
=
user
)
...
@@ -146,11 +201,8 @@ class Compute(Resource):
...
@@ -146,11 +201,8 @@ class Compute(Resource):
if
"method"
not
in
attributes
:
if
"method"
not
in
attributes
:
raise
OcciActionInvocationError
(
message
=
"No method given."
)
raise
OcciActionInvocationError
(
message
=
"No method given."
)
if
attributes
[
"method"
]
in
(
"graceful"
,
"warm"
,):
if
attributes
[
"method"
]
in
(
"graceful"
,
"warm"
,):
if
not
self
.
has_agent
():
raise
OcciActionInvocationError
(
message
=
"User agent is required."
)
try
:
try
:
self
.
vm
.
re
boo
t
(
user
=
user
)
self
.
vm
.
re
star
t
(
user
=
user
)
except
HumanReadableException
as
e
:
except
HumanReadableException
as
e
:
raise
OcciActionInvocationError
(
message
=
e
.
get_user_text
())
raise
OcciActionInvocationError
(
message
=
e
.
get_user_text
())
elif
attributes
[
"method"
]
in
(
"cold"
,):
elif
attributes
[
"method"
]
in
(
"cold"
,):
...
@@ -180,3 +232,160 @@ class Compute(Resource):
...
@@ -180,3 +232,160 @@ class Compute(Resource):
# TODO: save template
# TODO: save template
raise
OcciActionInvocationError
(
raise
OcciActionInvocationError
(
message
=
"Save action not implemented"
)
message
=
"Save action not implemented"
)
STORAGE_STATES_BY_IN_USE
=
{
"online"
:
"The disk is attached to an active compute instance."
,
"offline"
:
"The disk is not used by any compute instances at the moment."
,
"error"
:
"The disk is destroyed."
,
}
class
Storage
(
Resource
):
""" OCCI 1.2 - Infrastructure extension - Storage """
def
__init__
(
self
,
disk
):
super
(
Storage
,
self
)
.
__init__
(
"http://schemas.ogf.org/occi/infrastructure#storage"
,
str
(
disk
.
pk
))
self
.
disk
=
disk
self
.
actions
=
action_list_for_resource
(
STORAGE_ACTIONS
)
self
.
attributes
=
self
.
set_attributes
()
def
set_attributes
(
self
):
attributes
=
{}
attributes
[
"occi.storage.size"
]
=
float
(
self
.
disk
.
size
)
/
10
**
9
if
self
.
disk
.
destroyed
is
None
:
if
self
.
disk
.
is_in_use
:
state_key
=
"online"
else
:
state_key
=
"offline"
else
:
state_key
=
"error"
attributes
[
"occi.storage.state"
]
=
state_key
attributes
[
"occi.storage.state.message"
]
=
(
STORAGE_STATES_BY_IN_USE
[
state_key
])
return
attributes
def
invoke_action
(
self
,
user
,
action
,
attributes
):
message
=
(
"Action invokation on storage instances is not supported. "
"Please invoke actions on compute instances instead."
)
raise
OcciActionInvocationError
(
message
=
message
,
status
=
405
)
STORAGELINK_STATES_BY_STORAGE_STATE
=
{
"online"
:
"active"
,
"offline"
:
"inactive"
,
"error"
:
"error"
,
}
class
StorageLink
(
Link
):
""" OCCI 1.2 - Infrastructure extension - StorageLink """
def
__init__
(
self
,
compute
,
storage
):
super
(
StorageLink
,
self
)
.
__init__
(
{
"location"
:
"/compute/"
+
compute
.
id
,
"kind"
:
"http://schemas.ogf.org/occi/infrastructure#compute"
,
},
{
"location"
:
"/storage/"
+
storage
.
id
,
"kind"
:
"http://schemas.ogf.org/occi/infrastructure#storage"
,
},
"http://schemas.ogf.org/occi/infrastructure#storagelink"
,
"compute"
+
compute
.
id
+
"-"
+
"storage"
+
storage
.
id
)
self
.
compute
=
compute
self
.
storage
=
storage
self
.
attributes
=
self
.
set_attributes
()
def
set_attributes
(
self
):
attributes
=
{}
attributes
[
"occi.storagelink.deviceid"
]
=
self
.
storage
.
disk
.
pk
attributes
[
"occi.storagelink.mountpoint"
]
=
(
"/dev/
%
s
%
s"
%
(
self
.
storage
.
disk
.
device_type
,
self
.
storage
.
disk
.
dev_num
)
)
attributes
[
"occi.storagelink.state"
]
=
(
STORAGELINK_STATES_BY_STORAGE_STATE
[
self
.
storage
.
attributes
[
"occi.storage.state"
]])
attributes
[
"occi.storagelink.state.message"
]
=
(
self
.
storage
.
attributes
[
"occi.storage.state.message"
])
return
attributes
class
Network
(
Resource
):
""" OCCI 1.2 - Infrastructure extension - Network """
def
__init__
(
self
,
vlan
):
super
(
Network
,
self
)
.
__init__
(
"http://schemas.ogf.org/occi/infrastructure#network"
,
str
(
vlan
.
pk
),
)
self
.
vlan
=
vlan
self
.
actions
=
action_list_for_resource
(
NETWORK_ACTIONS
)
self
.
attributes
=
self
.
set_attributes
()
self
.
mixins
=
[
"http://schemas.ogf.org/occi/infrastructure/network#ipnetwork"
,
]
def
set_attributes
(
self
):
attributes
=
{}
attributes
[
"occi.network.vlan"
]
=
self
.
vlan
.
vid
attributes
[
"occi.network.state"
]
=
"active"
attributes
[
"occi.network.state.message"
]
=
(
"The network instance is active."
)
attributes
[
"occi.network.address"
]
=
unicode
(
self
.
vlan
.
network4
)
attributes
[
"occi.network.gateway"
]
=
unicode
(
self
.
vlan
.
network4
.
ip
)
attributes
[
"occi.network.allocation"
]
=
(
"static"
if
self
.
vlan
.
dhcp_pool
==
""
else
"dynamic"
)
return
attributes
def
invoke_action
(
self
,
user
,
action
,
attributes
):
message
=
(
"Action invokation on network instances is not supported. "
"Please invoke actions on compute instances instead."
)
raise
OcciActionInvocationError
(
message
=
message
,
status
=
405
)
class
NetworkInterface
(
Link
):
""" OCCI 1.2 - Infrastructure extension - NetworkInterace """
def
__init__
(
self
,
compute
,
network
):
super
(
NetworkInterface
,
self
)
.
__init__
(
{
"location"
:
"/compute/"
+
compute
.
id
,
"kind"
:
"http://schemas.ogf.org/occi/infrastructure#compute"
,
},
{
"location"
:
"/network/"
+
network
.
id
,
"kind"
:
"http://schemas.ogf.org/occi/infrastructure#network"
,
},
"http://schemas.ogf.org/occi/infrastructure#networkinterface"
,
"compute"
+
compute
.
id
+
"-"
+
"network"
+
network
.
id
)
self
.
compute
=
compute
self
.
network
=
network
self
.
interface
=
compute
.
vm
.
interface_set
.
get
(
vlan
=
network
.
vlan
)
self
.
mixins
=
[
(
"http://schemas.ogf.org/occi/infrastructure/networkinterface#"
+
"ipnetworkinterface"
),
]
self
.
attributes
=
self
.
set_attributes
()
def
set_attributes
(
self
):
attributes
=
{}
attributes
[
"occi.networkinterface.interface"
]
=
(
self
.
interface
.
vlan
.
name
)
attributes
[
"occi.networkinterface.mac"
]
=
unicode
(
self
.
interface
.
mac
)
attributes
[
"occi.networkinterface.state"
]
=
"active"
attributes
[
"occi.networkinterface.state.message"
]
=
(
"The networkinterface is active."
)
attributes
[
"occi.networkinterface.address"
]
=
(
unicode
(
self
.
interface
.
host
.
ipv4
))
attributes
[
"occi.networkinterface.gateway"
]
=
(
unicode
(
self
.
interface
.
vlan
.
network4
.
ip
))
attributes
[
"occi.networkinterface.allocation"
]
=
(
self
.
network
.
attributes
[
"occi.network.allocation"
])
return
attributes
circle/occi/occi_instances.py
View file @
04394fdf
# Copyright 2017 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
""" Required instances of the OCCI classes """
""" Required instances of the OCCI classes """
from
vm.models.instance
import
InstanceTemplate
from
vm.models.instance
import
InstanceTemplate
...
@@ -211,21 +229,46 @@ CREDENTIALS_ATTRIBUTES = [
...
@@ -211,21 +229,46 @@ CREDENTIALS_ATTRIBUTES = [
"connect to the compute instance."
),
"connect to the compute instance."
),
]
]
CREDENTIALS_MIXIN
=
Mixin
(
"http://circlecloud.org/occi/infrastructure#"
,
CREDENTIALS_MIXIN
=
Mixin
(
"http://circlecloud.org/occi/infrastructure/"
+
"compute#"
,
"credentials"
,
"credentials"
,
title
=
"Credentials Mixin"
,
title
=
"Credentials Mixin"
,
attributes
=
CREDENTIALS_ATTRIBUTES
,
attributes
=
CREDENTIALS_ATTRIBUTES
,
applies
=
"http://schemas.ogf.org/occi/"
+
applies
=
"http://schemas.ogf.org/occi/"
+
"infrastructure#compute"
)
"infrastructure#compute"
)
LEASETIME_ATTRIBUTES
=
[
Attribute
(
"org.circlecloud.occi.leasetime.suspend"
,
"String"
,
False
,
False
,
description
=
"The time remaining until the compute "
+
"instance is suspended."
),
Attribute
(
"org.circlecloud.occi.leasetime.remove"
,
"String"
,
False
,
False
,
description
=
"The time remaining until the compute "
+
"instance is deleted."
),
]
LEASETIME_ACTIONS
=
[
Action
(
"http://circlecloud.org/occi/infrastructure/compute/action#"
,
"renew"
,
title
=
"Renew the lease time of the compute instance."
),
]
LEASETIME_MIXIN
=
Mixin
(
"http://circlecloud.org/occi/infrastucture/compute#"
,
"leasetime"
,
title
=
"Compute Lease Time Mixin"
,
attributes
=
LEASETIME_ATTRIBUTES
,
actions
=
LEASETIME_ACTIONS
,
applies
=
"http://schemas.ogf.org/occi/infrastructure"
+
"#compute"
)
OS_TPL_MIXIN
=
Mixin
(
"http://schemas.ogf.org/occi/infrastructure#"
,
OS_TPL_MIXIN
=
Mixin
(
"http://schemas.ogf.org/occi/infrastructure#"
,
"os_tpl"
,
"os_tpl"
,
title
=
"OS Template"
)
title
=
"OS Template"
)
ACTION_ARRAYS
=
[
ACTION_ARRAYS
=
[
COMPUTE_ACTIONS
,
COMPUTE_ACTIONS
,
# NETWORK_ACTIONS,
NETWORK_ACTIONS
,
# STORAGE_ACTIONS,
STORAGE_ACTIONS
,
LEASETIME_ACTIONS
,
]
]
...
@@ -235,9 +278,10 @@ def ALL_KINDS():
...
@@ -235,9 +278,10 @@ def ALL_KINDS():
RESOURCE_KIND
,
RESOURCE_KIND
,
LINK_KIND
,
LINK_KIND
,
COMPUTE_KIND
,
COMPUTE_KIND
,
# NETWORK_KIND,
NETWORK_KIND
,
# STORAGE_KIND,
STORAGE_KIND
,
# NETWORKINTERFACE_KIND
NETWORKINTERFACE_KIND
,
STORAGELINK_KIND
,
]
]
...
@@ -255,10 +299,11 @@ def os_tpl_mixins(user):
...
@@ -255,10 +299,11 @@ def os_tpl_mixins(user):
def
ALL_MIXINS
(
user
):
def
ALL_MIXINS
(
user
):
mixins
=
[
mixins
=
[
#
IPNETWORK_MIXIN,
IPNETWORK_MIXIN
,
#
IPNETWORKINTERFACE_MIXIN,
IPNETWORKINTERFACE_MIXIN
,
CREDENTIALS_MIXIN
,
CREDENTIALS_MIXIN
,
OS_TPL_MIXIN
,
OS_TPL_MIXIN
,
LEASETIME_MIXIN
,
]
]
template_mixins
=
os_tpl_mixins
(
user
)
template_mixins
=
os_tpl_mixins
(
user
)
for
template
in
template_mixins
:
for
template
in
template_mixins
:
...
...
circle/occi/occi_utils.py
View file @
04394fdf
# Copyright 2017 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
"""" Utilities for the OCCI implementation of CIRCLE """
"""" Utilities for the OCCI implementation of CIRCLE """
from
django.http
import
HttpResponse
from
django.http
import
HttpResponse
...
@@ -7,6 +25,7 @@ import json
...
@@ -7,6 +25,7 @@ import json
class
OcciException
(
Exception
):
class
OcciException
(
Exception
):
""" The superclass for OCCI exceptions. It creates a response to be
""" The superclass for OCCI exceptions. It creates a response to be
returned when an error occures. """
returned when an error occures. """
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
message
=
kwargs
.
get
(
"message"
,
"An error occured."
)
message
=
kwargs
.
get
(
"message"
,
"An error occured."
)
status
=
kwargs
.
get
(
"status"
,
400
)
status
=
kwargs
.
get
(
"status"
,
400
)
...
@@ -17,6 +36,7 @@ class OcciException(Exception):
...
@@ -17,6 +36,7 @@ class OcciException(Exception):
class
OcciResourceInstanceNotExist
(
OcciException
):
class
OcciResourceInstanceNotExist
(
OcciException
):
""" An exception to be raised when a resource instance which has been
""" An exception to be raised when a resource instance which has been
asked for does not exist. """
asked for does not exist. """
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
if
"message"
not
in
kwargs
:
if
"message"
not
in
kwargs
:
kwargs
[
"message"
]
=
"The resource instance does not exist."
kwargs
[
"message"
]
=
"The resource instance does not exist."
...
@@ -26,6 +46,7 @@ class OcciResourceInstanceNotExist(OcciException):
...
@@ -26,6 +46,7 @@ class OcciResourceInstanceNotExist(OcciException):
class
OcciActionInvocationError
(
OcciException
):
class
OcciActionInvocationError
(
OcciException
):
""" An exception to be raised when an action could not be invoked on
""" An exception to be raised when an action could not be invoked on
an entity instance for some reason """
an entity instance for some reason """
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
if
"message"
not
in
kwargs
:
if
"message"
not
in
kwargs
:
kwargs
[
"message"
]
=
"Could not invoke action."
kwargs
[
"message"
]
=
"Could not invoke action."
...
@@ -35,6 +56,7 @@ class OcciActionInvocationError(OcciException):
...
@@ -35,6 +56,7 @@ class OcciActionInvocationError(OcciException):
class
OcciResourceCreationError
(
OcciException
):
class
OcciResourceCreationError
(
OcciException
):
""" An exception to be raised when a resource instance could not be
""" An exception to be raised when a resource instance could not be
created for a reason. """
created for a reason. """
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
if
"message"
not
in
kwargs
:
if
"message"
not
in
kwargs
:
kwargs
[
"message"
]
=
"Could not create resource instance."
kwargs
[
"message"
]
=
"Could not create resource instance."
...
@@ -44,6 +66,7 @@ class OcciResourceCreationError(OcciException):
...
@@ -44,6 +66,7 @@ class OcciResourceCreationError(OcciException):
class
OcciResourceDeletionError
(
OcciException
):
class
OcciResourceDeletionError
(
OcciException
):
""" An exception to be raised when a resource instance could not be
""" An exception to be raised when a resource instance could not be
deleted for some reason. """
deleted for some reason. """
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
if
"message"
not
in
kwargs
:
if
"message"
not
in
kwargs
:
kwargs
[
"message"
]
=
"Could not delete resource instance."
kwargs
[
"message"
]
=
"Could not delete resource instance."
...
@@ -53,6 +76,7 @@ class OcciResourceDeletionError(OcciException):
...
@@ -53,6 +76,7 @@ class OcciResourceDeletionError(OcciException):
class
OcciRequestNotValid
(
OcciException
):
class
OcciRequestNotValid
(
OcciException
):
""" An exception to be raised when the request sent by the client is
""" An exception to be raised when the request sent by the client is
not valid for a reason. (e.g, wrong content type, etc.) """
not valid for a reason. (e.g, wrong content type, etc.) """
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
if
"message"
not
in
kwargs
:
if
"message"
not
in
kwargs
:
kwargs
[
"message"
]
=
"The request is not valid."
kwargs
[
"message"
]
=
"The request is not valid."
...
...
circle/occi/urls.py
View file @
04394fdf
# Copyright 2017 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from
django.conf.urls
import
url
from
django.conf.urls
import
url
from
views
import
(
OcciLoginView
,
OcciLogoutView
,
OcciQueryInterfaceView
,
from
views
import
(
OcciLoginView
,
OcciLogoutView
,
OcciQueryInterfaceView
,
OcciComputeView
,
OcciComputeCollectionView
)
OcciComputeView
,
OcciComputeCollectionView
,
OcciStorageView
,
OcciStorageCollectionView
,
OcciNetworkView
,
OcciNetworkCollectionView
)
urlpatterns
=
[
urlpatterns
=
[
...
@@ -9,4 +29,8 @@ urlpatterns = [
...
@@ -9,4 +29,8 @@ urlpatterns = [
url
(
r'^-/$'
,
OcciQueryInterfaceView
.
as_view
()),
url
(
r'^-/$'
,
OcciQueryInterfaceView
.
as_view
()),
url
(
r'^compute/$'
,
OcciComputeCollectionView
.
as_view
()),
url
(
r'^compute/$'
,
OcciComputeCollectionView
.
as_view
()),
url
(
r'^compute/(?P<id>\d+)/$'
,
OcciComputeView
.
as_view
()),
url
(
r'^compute/(?P<id>\d+)/$'
,
OcciComputeView
.
as_view
()),
url
(
r'^storage/$'
,
OcciStorageCollectionView
.
as_view
()),
url
(
r'^storage/(?P<id>\d+)/$'
,
OcciStorageView
.
as_view
()),
url
(
r'^network/$'
,
OcciNetworkCollectionView
.
as_view
()),
url
(
r'^network/(?P<id>\d+)/$'
,
OcciNetworkView
.
as_view
()),
]
]
circle/occi/views.py
View file @
04394fdf
# Copyright 2017 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
""" The views of the OCCI implementation of CIRCLE.
""" The views of the OCCI implementation of CIRCLE.
These views handle the http requests of the API. """
These views handle the http requests of the API. """
...
@@ -10,8 +28,10 @@ from django.shortcuts import get_object_or_404
...
@@ -10,8 +28,10 @@ from django.shortcuts import get_object_or_404
from
django.views.decorators.csrf
import
ensure_csrf_cookie
from
django.views.decorators.csrf
import
ensure_csrf_cookie
from
django.utils.decorators
import
method_decorator
from
django.utils.decorators
import
method_decorator
from
vm.models.instance
import
Instance
,
InstanceTemplate
from
vm.models.instance
import
Instance
,
InstanceTemplate
from
storage.models
import
Disk
from
firewall.models
import
Vlan
from
forms
import
OcciAuthForm
from
forms
import
OcciAuthForm
from
occi_infrastructure
import
Compute
from
occi_infrastructure
import
Compute
,
Storage
,
Network
from
occi_utils
import
(
OcciResourceInstanceNotExist
,
from
occi_utils
import
(
OcciResourceInstanceNotExist
,
OcciActionInvocationError
,
OcciActionInvocationError
,
OcciRequestNotValid
,
OcciRequestNotValid
,
...
@@ -20,6 +40,10 @@ from occi_utils import (OcciResourceInstanceNotExist,
...
@@ -20,6 +40,10 @@ from occi_utils import (OcciResourceInstanceNotExist,
occi_response
,
occi_response
,
validate_request
)
validate_request
)
from
occi_instances
import
ALL_KINDS
,
ALL_MIXINS
,
ALL_ACTIONS
from
occi_instances
import
ALL_KINDS
,
ALL_MIXINS
,
ALL_ACTIONS
from
common.models
import
HumanReadableException
import
logging
log
=
logging
.
getLogger
(
__name__
)
class
OcciLoginView
(
View
):
class
OcciLoginView
(
View
):
...
@@ -38,6 +62,8 @@ class OcciLoginView(View):
...
@@ -38,6 +62,8 @@ class OcciLoginView(View):
""" Returns a response with a cookie to be used for the OCCI api
""" Returns a response with a cookie to be used for the OCCI api
requests. """
requests. """
data
=
json
.
loads
(
request
.
body
.
decode
(
"utf-8"
))
data
=
json
.
loads
(
request
.
body
.
decode
(
"utf-8"
))
log
.
error
(
data
)
print
(
data
)
form
=
OcciAuthForm
(
data
=
data
,
request
=
request
)
form
=
OcciAuthForm
(
data
=
data
,
request
=
request
)
if
form
.
is_valid
():
if
form
.
is_valid
():
result
=
{
"result"
:
"OK"
}
result
=
{
"result"
:
"OK"
}
...
@@ -51,6 +77,7 @@ class OcciLoginView(View):
...
@@ -51,6 +77,7 @@ class OcciLoginView(View):
class
OcciLogoutView
(
View
):
class
OcciLogoutView
(
View
):
""" Logout """
""" Logout """
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
logout
(
request
)
logout
(
request
)
result
=
{
"result"
:
"OK"
}
result
=
{
"result"
:
"OK"
}
...
@@ -84,7 +111,7 @@ class OcciQueryInterfaceView(View):
...
@@ -84,7 +111,7 @@ class OcciQueryInterfaceView(View):
def
put
(
self
,
request
,
*
args
,
**
kwargs
):
def
put
(
self
,
request
,
*
args
,
**
kwargs
):
return
occi_response
({
"error"
:
"Put method is not defined on the "
+
return
occi_response
({
"error"
:
"Put method is not defined on the "
+
"query interface."
},
status
=
400
)
"query interface."
},
status
=
400
)
class
OcciComputeCollectionView
(
View
):
class
OcciComputeCollectionView
(
View
):
...
@@ -94,7 +121,7 @@ class OcciComputeCollectionView(View):
...
@@ -94,7 +121,7 @@ class OcciComputeCollectionView(View):
validate_request
(
request
)
validate_request
(
request
)
except
OcciRequestNotValid
as
e
:
except
OcciRequestNotValid
as
e
:
return
e
.
response
return
e
.
response
vms
=
(
Instance
.
get_objects_with_level
(
"
us
er"
,
request
.
user
)
vms
=
(
Instance
.
get_objects_with_level
(
"
own
er"
,
request
.
user
)
.
filter
(
destroyed_at
=
None
))
.
filter
(
destroyed_at
=
None
))
json
=
{
"resources"
:
[]}
json
=
{
"resources"
:
[]}
for
vm
in
vms
:
for
vm
in
vms
:
...
@@ -114,10 +141,11 @@ class OcciComputeCollectionView(View):
...
@@ -114,10 +141,11 @@ class OcciComputeCollectionView(View):
class
OcciComputeView
(
View
):
class
OcciComputeView
(
View
):
""" View of a compute instance """
""" View of a compute instance """
def
get_vm_object
(
self
,
user
,
vmid
):
def
get_vm_object
(
self
,
user
,
vmid
):
try
:
try
:
vm
=
get_object_or_404
(
Instance
.
get_objects_with_level
(
"user"
,
vm
=
get_object_or_404
(
Instance
.
get_objects_with_level
(
user
)
.
filter
(
destroyed_at
=
None
),
pk
=
vmid
)
"owner"
,
user
)
.
filter
(
destroyed_at
=
None
),
pk
=
vmid
)
except
Http404
:
except
Http404
:
raise
OcciResourceInstanceNotExist
()
raise
OcciResourceInstanceNotExist
()
return
Compute
(
vm
)
return
Compute
(
vm
)
...
@@ -135,21 +163,42 @@ class OcciComputeView(View):
...
@@ -135,21 +163,42 @@ class OcciComputeView(View):
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
requestData
=
json
.
loads
(
request
.
body
.
decode
(
"utf-8"
))
requestData
=
json
.
loads
(
request
.
body
.
decode
(
"utf-8"
))
if
not
requestData
[
"action"
]:
if
"action"
in
requestData
:
return
occi_response
({
"error"
:
"Action invocation rendering "
+
try
:
"is not supplied."
},
compute
=
self
.
get_vm_object
(
request
.
user
,
kwargs
[
"id"
])
status
=
400
)
except
OcciResourceInstanceNotExist
as
e
:
try
:
return
e
.
response
compute
=
self
.
get_vm_object
(
request
.
user
,
kwargs
[
"id"
])
try
:
except
OcciResourceInstanceNotExist
as
e
:
compute
.
invoke_action
(
request
.
user
,
return
e
.
response
requestData
.
get
(
"action"
,
None
),
try
:
requestData
.
get
(
"attributes"
,
None
))
compute
.
invoke_action
(
request
.
user
,
except
OcciActionInvocationError
as
e
:
requestData
.
get
(
"action"
,
None
),
return
e
.
response
requestData
.
get
(
"attributes"
,
None
))
return
occi_response
(
compute
.
render_as_json
(),
status
=
200
)
except
OcciActionInvocationError
as
e
:
elif
"attributes"
in
requestData
:
return
e
.
response
attrs
=
requestData
[
"attributes"
]
return
occi_response
(
compute
.
render_as_json
(),
status
=
200
)
try
:
vm
=
get_object_or_404
(
Instance
.
get_objects_with_level
(
"owner"
,
request
.
user
)
.
filter
(
destroyed_at
=
None
),
pk
=
kwargs
[
"id"
])
except
Http404
:
return
OcciResourceInstanceNotExist
()
.
response
num_cores
=
attrs
.
get
(
"occi.compute.cores"
,
vm
.
num_cores
)
ram_size
=
(
attrs
.
get
(
"occi.compute.memory"
,
vm
.
ram_size
/
1024.0
)
*
1024
)
priority
=
attrs
.
get
(
"occi.compute.share"
,
vm
.
priority
)
try
:
vm
.
resources_change
(
user
=
request
.
user
,
num_cores
=
num_cores
,
ram_size
=
ram_size
,
max_ram_size
=
vm
.
max_ram_size
,
priority
=
priority
)
except
HumanReadableException
as
e
:
log
.
warning
(
e
.
get_user_text
())
return
occi_response
(
Compute
(
vm
)
.
render_as_json
(),
status
=
200
)
return
occi_response
({
"error"
:
"Bad request"
},
status
=
400
)
def
put
(
self
,
request
,
*
args
,
**
kwargs
):
def
put
(
self
,
request
,
*
args
,
**
kwargs
):
# checking if the requested resource exists
# checking if the requested resource exists
...
@@ -195,3 +244,135 @@ class OcciComputeView(View):
...
@@ -195,3 +244,135 @@ class OcciComputeView(View):
except
:
except
:
return
OcciResourceDeletionError
()
.
response
return
OcciResourceDeletionError
()
.
response
return
occi_response
({
"result"
:
"Compute instance deleted."
})
return
occi_response
({
"result"
:
"Compute instance deleted."
})
class
OcciStorageCollectionView
(
View
):
@method_decorator
(
ensure_csrf_cookie
)
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
try
:
validate_request
(
request
)
except
OcciRequestNotValid
as
e
:
return
e
.
response
vms
=
(
Instance
.
get_objects_with_level
(
"owner"
,
request
.
user
)
.
filter
(
destroyed_at
=
None
))
json
=
{
"resources"
:
[]}
for
vm
in
vms
:
disks
=
vm
.
disks
.
all
()
for
disk
in
disks
:
json
[
"resources"
]
.
append
(
Storage
(
disk
)
.
render_as_json
())
return
occi_response
(
json
)
def
put
(
self
,
request
,
*
args
,
**
kwargs
):
return
occi_response
({
"message"
:
"Not supported."
},
status
=
501
)
class
OcciStorageView
(
View
):
""" View of a storage instance """
def
get_disk_object
(
self
,
user
,
diskid
):
try
:
disk
=
get_object_or_404
(
Disk
,
pk
=
diskid
)
except
Http404
:
raise
OcciResourceInstanceNotExist
()
diskvms
=
disk
.
instance_set
.
all
()
uservms
=
Instance
.
get_objects_with_level
(
"user"
,
user
)
.
filter
(
destroyed_at
=
None
)
if
len
(
diskvms
&
uservms
)
>
0
:
return
Storage
(
disk
)
raise
OcciResourceInstanceNotExist
()
@method_decorator
(
ensure_csrf_cookie
)
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
try
:
validate_request
(
request
)
except
OcciRequestNotValid
as
e
:
return
e
.
response
try
:
disk
=
self
.
get_disk_object
(
request
.
user
,
kwargs
[
"id"
])
except
OcciResourceInstanceNotExist
as
e
:
return
e
.
response
return
occi_response
(
disk
.
render_as_json
(),
charset
=
"utf-8"
)
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
requestData
=
json
.
loads
(
request
.
body
.
decode
(
"utf-8"
))
if
"action"
not
in
requestData
:
return
occi_response
(
{
"error"
:
(
"Storage pratial update is not supported. "
+
"Action invocation rendering must be supplied."
),
},
status
=
400
)
try
:
storage
=
self
.
get_disk_object
(
request
.
user
,
kwargs
[
"id"
])
except
OcciResourceInstanceNotExist
as
e
:
return
e
.
response
try
:
storage
.
invoke_action
(
request
.
user
,
requestData
.
get
(
"action"
,
None
),
requestData
.
get
(
"attributes"
,
None
))
except
OcciActionInvocationError
as
e
:
return
e
.
response
return
occi_response
(
storage
.
render_as_json
(),
status
=
200
)
class
OcciNetworkCollectionView
(
View
):
@method_decorator
(
ensure_csrf_cookie
)
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
try
:
validate_request
(
request
)
except
OcciRequestNotValid
as
e
:
return
e
.
response
vlans
=
(
Vlan
.
get_objects_with_level
(
"owner"
,
request
.
user
))
json
=
{
"resources"
:
[]}
for
vlan
in
vlans
:
json
[
"resources"
]
.
append
(
Network
(
vlan
)
.
render_as_json
())
return
occi_response
(
json
)
class
OcciNetworkView
(
View
):
""" View of a compute instance """
def
get_vlan_object
(
self
,
user
,
vlanid
):
try
:
vlan
=
get_object_or_404
(
Vlan
.
get_objects_with_level
(
"user"
,
user
),
pk
=
vlanid
)
except
Http404
:
raise
OcciResourceInstanceNotExist
()
return
Network
(
vlan
)
@method_decorator
(
ensure_csrf_cookie
)
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
try
:
validate_request
(
request
)
except
OcciRequestNotValid
as
e
:
return
e
.
response
try
:
network
=
self
.
get_vlan_object
(
request
.
user
,
kwargs
[
"id"
])
except
OcciResourceInstanceNotExist
as
e
:
return
e
.
response
return
occi_response
(
network
.
render_as_json
(),
charset
=
"utf-8"
)
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
requestData
=
json
.
loads
(
request
.
body
.
decode
(
"utf-8"
))
if
"action"
not
in
requestData
:
return
occi_response
(
{
"error"
:
(
"Network partial update is not supported. "
+
"Action invocation rendering must be supplied."
),
},
status
=
400
)
try
:
network
=
self
.
get_vlan_object
(
request
.
user
,
kwargs
[
"id"
])
except
OcciResourceInstanceNotExist
as
e
:
return
e
.
response
try
:
network
.
invoke_action
(
request
.
user
,
requestData
.
get
(
"action"
,
None
),
requestData
.
get
(
"attributes"
,
None
))
except
OcciActionInvocationError
as
e
:
return
e
.
response
return
occi_response
(
network
.
render_as_json
(),
status
=
200
)
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