Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
synnefo
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
itminedu
synnefo
Commits
ffafa697
Commit
ffafa697
authored
Sep 26, 2013
by
Giorgos Korfiatis
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
cyclades: Reassign resources
Add API calls to assign a VM, network, or floating IP to a new project.
parent
a4dc4bb0
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
215 additions
and
4 deletions
+215
-4
docs/compute-api-guide.rst
docs/compute-api-guide.rst
+79
-0
snf-cyclades-app/synnefo/api/floating_ips.py
snf-cyclades-app/synnefo/api/floating_ips.py
+40
-1
snf-cyclades-app/synnefo/api/networks.py
snf-cyclades-app/synnefo/api/networks.py
+34
-1
snf-cyclades-app/synnefo/api/servers.py
snf-cyclades-app/synnefo/api/servers.py
+10
-1
snf-cyclades-app/synnefo/logic/ips.py
snf-cyclades-app/synnefo/logic/ips.py
+10
-0
snf-cyclades-app/synnefo/logic/networks.py
snf-cyclades-app/synnefo/logic/networks.py
+10
-0
snf-cyclades-app/synnefo/logic/servers.py
snf-cyclades-app/synnefo/logic/servers.py
+9
-0
snf-cyclades-app/synnefo/quotas/__init__.py
snf-cyclades-app/synnefo/quotas/__init__.py
+23
-1
No files found.
docs/compute-api-guide.rst
View file @
ffafa697
...
...
@@ -1623,6 +1623,7 @@ Operations Cyclades OS/Compute
`Reboot <#reboot-server>`_ ✔ ✔
`Get Console <#get-server-console>`_ ✔ **✘**
`Set Firewall <#set-server-firewall-profile>`_ ✔ **✘**
`Reassign <#reassign-server>`_ ✔ **✘**
`Change Admin Password <#os-compute-specific>`_ **✘** ✔
`Rebuild <#os-compute-specific>`_ **✘** ✔
`Resize <#os-compute-specific>`_ **✘** ✔
...
...
@@ -1804,6 +1805,23 @@ Request body contents::
.. note:: Response body should be empty
Reassign Server
...............
This operation assigns the VM to a different project.
Request body contents::
reassign: { project: <project-id>}
*Example Action reassign: JSON**
.. code-block:: javascript
{"reassign": {"project": "9969f2fd-86d8-45d6-9106-5e251f7dd92f"}}
.. note:: Response body should be empty
OS/Compute Specific
...................
...
...
@@ -2756,6 +2774,7 @@ Description URI
`Delete <#delete-network>`_ ``/networks/<network-id>`` DELETE
`Connect <#connect-network-to-server>`_ ``/networks/<network-id>/action`` POST
`Disconnect <#disconnect-network-from-server>`_ ``/networks/<network-id>/action`` POST
`Reassign <#reassign-network>`_ ``/networks/<network-id>/action`` POST
=============================================== ================================= ======
...
...
@@ -3331,6 +3350,66 @@ Return Code Description
.. note:: In case of a 202 code, the request body should be empty
Reassign Network
................
Assign a network to a different project.
.. rubric:: Request
================================= ======
URI Method
================================= ======
``/networks/<network-id>/action`` POST
================================= ======
* **network-id** is the identifier of the network
|
============== =========================
Request Header Value
============== =========================
X-Auth-Token User authentication token
Content-Type Type or request body
Content-Length Length of request body
============== =========================
**Example Request Headers**::
X-Auth-Token: z31uRXUn1LZy45p1r7V==
Content-Type: application/json
Content-Length: 31
.. note:: Request parameters should be empty
Response body content (reassign)::
reassign {project: <project-id>}
*Example Action Reassign: JSON*
.. code-block:: javascript
{"reassign" : {"project" : "9969f2fd-86d8-45d6-9106-5e251f7dd92f"}}
.. rubric:: Response
=========================== =====================
Return Code Description
=========================== =====================
200 (OK) Request succeeded
400 (Bad Request) Malformed request
401 (Unauthorized) Missing or expired user token
403 (Forbidden) Not allowed to modify this network (e.g. public)
404 (Not Found) Network not found
500 (Internal Server Error) The request cannot be completed because of an
\ internal error
503 (Service Unavailable) The service is not currently available
=========================== =====================
.. note:: In case of a 200 code, the request body should be empty
Index of Attributes
-------------------
...
...
snf-cyclades-app/synnefo/api/floating_ips.py
View file @
ffafa697
...
...
@@ -62,7 +62,9 @@ ips_urlpatterns = patterns(
'synnefo.api.floating_ips'
,
(
r
'^(?:/|.json|.xml)?$'
,
'demux'
),
(
r
'^/detail(?:.json|.xml)?$'
,
'list_floating_ips'
,
{
'detail'
:
True
}),
(
r
'^/(\w+)(?:/|.json|.xml)?$'
,
'floating_ip_demux'
))
(
r
'^/(\w+)(?:/|.json|.xml)?$'
,
'floating_ip_demux'
),
(
r
'^/(\w+)/action(?:.json|.xml)?$'
,
'floating_ip_action_demux'
),
)
def
demux
(
request
):
...
...
@@ -87,6 +89,29 @@ def floating_ip_demux(request, floating_ip_id):
allowed_methods
=
[
'GET'
,
'DELETE'
])
@
api
.
api_method
(
http_method
=
'POST'
,
user_required
=
True
,
logger
=
log
,
serializations
=
[
"json"
])
def
floating_ip_action_demux
(
request
,
floating_ip_id
):
userid
=
request
.
user_uniq
req
=
utils
.
get_request_dict
(
request
)
log
.
debug
(
'floating_ip_action %s %s'
,
floating_ip_id
,
req
)
if
len
(
req
)
!=
1
:
raise
faults
.
BadRequest
(
'Malformed request.'
)
floating_ip
=
util
.
get_floating_ip_by_id
(
userid
,
floating_ip_id
,
for_update
=
True
)
action
=
req
.
keys
()[
0
]
try
:
f
=
FLOATING_IP_ACTIONS
[
action
]
except
KeyError
:
raise
faults
.
BadRequest
(
"Action %s not supported."
%
action
)
action_args
=
req
[
action
]
if
not
isinstance
(
action_args
,
dict
):
raise
faults
.
BadRequest
(
"Invalid argument."
)
return
f
(
request
,
floating_ip
,
action_args
)
def
ip_to_dict
(
floating_ip
):
machine_id
=
None
port_id
=
None
...
...
@@ -236,6 +261,20 @@ def list_floating_ip_pools(request):
return
HttpResponse
(
data
,
status
=
200
)
@
transaction
.
commit_on_success
def
reassign
(
request
,
floating_ip
,
args
):
project
=
args
.
get
(
"project"
)
if
project
is
None
:
raise
faults
.
BadRequest
(
"Missing 'project' attribute."
)
ips
.
reassign_floating_ip
(
floating_ip
,
project
)
return
HttpResponse
(
status
=
200
)
FLOATING_IP_ACTIONS
=
{
"reassign"
:
reassign
,
}
def
network_to_floating_ip_pool
(
network
):
"""Convert a 'Network' object to a floating IP pool dict."""
total
,
free
=
network
.
ip_count
()
...
...
snf-cyclades-app/synnefo/api/networks.py
View file @
ffafa697
...
...
@@ -40,6 +40,7 @@ from django.db.models import Q
from
django.template.loader
import
render_to_string
from
snf_django.lib
import
api
from
snf_django.lib.api
import
utils
from
synnefo.api
import
util
from
synnefo.db.models
import
Network
...
...
@@ -53,7 +54,9 @@ urlpatterns = patterns(
'synnefo.api.networks'
,
(
r
'^(?:/|.json|.xml)?$'
,
'demux'
),
(
r
'^/detail(?:.json|.xml)?$'
,
'list_networks'
,
{
'detail'
:
True
}),
(
r
'^/(\w+)(?:/|.json|.xml)?$'
,
'network_demux'
))
(
r
'^/(\w+)(?:/|.json|.xml)?$'
,
'network_demux'
),
(
r
'^/(\w+)/action(?:/|.json|.xml)?$'
,
'network_action_demux'
),
)
def
demux
(
request
):
...
...
@@ -81,6 +84,22 @@ def network_demux(request, network_id):
'DELETE'
])
@
api
.
api_method
(
http_method
=
'POST'
,
user_required
=
True
,
logger
=
log
)
def
network_action_demux
(
request
,
network_id
):
req
=
utils
.
get_request_dict
(
request
)
network
=
util
.
get_network
(
network_id
,
request
.
user_uniq
,
for_update
=
True
)
action
=
req
.
keys
()[
0
]
try
:
f
=
NETWORK_ACTIONS
[
action
]
except
KeyError
:
raise
faults
.
BadRequest
(
"Action %s not supported."
%
action
)
action_args
=
req
[
action
]
if
not
isinstance
(
action_args
,
dict
):
raise
faults
.
BadRequest
(
"Invalid argument."
)
return
f
(
request
,
network
,
action_args
)
@
api
.
api_method
(
http_method
=
'GET'
,
user_required
=
True
,
logger
=
log
)
def
list_networks
(
request
,
detail
=
True
):
log
.
debug
(
'list_networks detail=%s'
,
detail
)
...
...
@@ -196,6 +215,20 @@ def network_to_dict(network, detail=True):
return
d
@
transaction
.
commit_on_success
def
reassign_network
(
request
,
network
,
args
):
project
=
args
.
get
(
"project"
)
if
project
is
None
:
raise
faults
.
BadRequest
(
"Missing 'project' attribute."
)
networks
.
reassign
(
network
,
project
)
return
HttpResponse
(
status
=
200
)
NETWORK_ACTIONS
=
{
"reassign"
:
reassign_network
,
}
def
render_network
(
request
,
networkdict
,
status
=
200
):
if
request
.
serialization
==
'xml'
:
data
=
render_to_string
(
'network.xml'
,
{
'network'
:
networkdict
})
...
...
snf-cyclades-app/synnefo/api/servers.py
View file @
ffafa697
...
...
@@ -479,7 +479,7 @@ def delete_server(request, server_id):
# additional server actions
ARBITRARY_ACTIONS
=
[
'console'
,
'firewallProfile'
]
ARBITRARY_ACTIONS
=
[
'console'
,
'firewallProfile'
,
'reassign'
]
def
key_to_action
(
key
):
...
...
@@ -878,6 +878,15 @@ def revert_resize(request, vm, args):
raise
faults
.
NotImplemented
(
'Resize not supported.'
)
@
server_action
(
'reassign'
)
def
reassign
(
request
,
vm
,
args
):
project
=
args
.
get
(
"project"
)
if
project
is
None
:
raise
faults
.
BadRequest
(
"Missing 'project' attribute."
)
servers
.
reassign
(
vm
,
project
)
return
HttpResponse
(
status
=
200
)
@
network_action
(
'add'
)
@
transaction
.
commit_on_success
def
add
(
request
,
net
,
args
):
...
...
snf-cyclades-app/synnefo/logic/ips.py
View file @
ffafa697
...
...
@@ -230,3 +230,13 @@ def delete_floating_ip(floating_ip):
log
.
info
(
"Deleted floating IP '%s' of user '%s"
,
floating_ip
,
floating_ip
.
userid
)
floating_ip
.
delete
()
@
transaction
.
commit_on_success
def
reassign_floating_ip
(
floating_ip
,
project
):
action_fields
=
{
"to_project"
:
project
,
"from_project"
:
floating_ip
.
project
}
floating_ip
.
project
=
project
floating_ip
.
save
()
quotas
.
issue_and_accept_commission
(
floating_ip
,
action
=
"REASSIGN"
,
action_fields
=
action_fields
)
snf-cyclades-app/synnefo/logic/networks.py
View file @
ffafa697
...
...
@@ -174,3 +174,13 @@ def delete(network):
# If network does not exist in any backend, update the network state
backend_mod
.
update_network_state
(
network
)
return
network
@
network_command
(
"REASSIGN"
)
def
reassign
(
network
,
project
):
action_fields
=
{
"to_project"
:
project
,
"from_project"
:
network
.
project
}
network
.
project
=
project
network
.
save
()
quotas
.
issue_and_accept_commission
(
network
,
action
=
"REASSIGN"
,
action_fields
=
action_fields
)
return
network
snf-cyclades-app/synnefo/logic/servers.py
View file @
ffafa697
...
...
@@ -333,6 +333,15 @@ def _resize(vm, flavor):
return
backend
.
resize_instance
(
vm
,
vcpus
=
flavor
.
cpu
,
memory
=
flavor
.
ram
)
@
transaction
.
commit_on_success
def
reassign
(
vm
,
project
):
action_fields
=
{
"to_project"
:
project
,
"from_project"
:
vm
.
project
}
vm
.
project
=
project
vm
.
save
()
quotas
.
issue_and_accept_commission
(
vm
,
action
=
"REASSIGN"
,
action_fields
=
action_fields
)
@
server_command
(
"SET_FIREWALL_PROFILE"
)
def
set_firewall_profile
(
vm
,
profile
,
nic
):
log
.
info
(
"Setting VM %s, NIC %s, firewall %s"
,
vm
,
nic
,
profile
)
...
...
snf-cyclades-app/synnefo/quotas/__init__.py
View file @
ffafa697
...
...
@@ -131,7 +131,21 @@ def issue_commission(resource, action, name="", force=False, auto_accept=False,
source
=
resource
.
project
qh
=
Quotaholder
.
get
()
if
True
:
# placeholder
if
action
==
"REASSIGN"
:
try
:
from_project
=
action_fields
[
"from_project"
]
to_project
=
action_fields
[
"to_project"
]
except
KeyError
:
raise
Exception
(
"Missing project attribute."
)
projects
=
[
from_project
,
to_project
]
with
AstakosClientExceptionHandler
(
user
=
user
,
projects
=
projects
):
serial
=
qh
.
issue_resource_reassignment
(
user
,
from_project
,
to_project
,
provisions
,
name
=
name
,
force
=
force
,
auto_accept
=
auto_accept
)
else
:
with
AstakosClientExceptionHandler
(
user
=
user
,
projects
=
[
source
]):
serial
=
qh
.
issue_one_commission
(
user
,
source
,
provisions
,
name
=
name
,
...
...
@@ -352,6 +366,10 @@ def get_commission_info(resource, action, action_fields=None):
ram
=
beparams
.
get
(
"maxmem"
,
flavor
.
ram
)
return
{
"cyclades.total_cpu"
:
cpu
-
flavor
.
cpu
,
"cyclades.total_ram"
:
1048576
*
(
ram
-
flavor
.
ram
)}
elif
action
==
"REASSIGN"
:
if
resource
.
operstate
in
[
"STARTED"
,
"BUILD"
,
"ERROR"
]:
resources
.
update
(
online_resources
)
return
resources
else
:
#["CONNECT", "DISCONNECT", "SET_FIREWALL_PROFILE"]:
return
None
...
...
@@ -361,6 +379,8 @@ def get_commission_info(resource, action, action_fields=None):
return
resources
elif
action
==
"DESTROY"
:
return
reverse_quantities
(
resources
)
elif
action
==
"REASSIGN"
:
return
resources
elif
isinstance
(
resource
,
IPAddress
):
if
resource
.
floating_ip
:
resources
=
{
"cyclades.floating_ip"
:
1
}
...
...
@@ -368,6 +388,8 @@ def get_commission_info(resource, action, action_fields=None):
return
resources
elif
action
==
"DESTROY"
:
return
reverse_quantities
(
resources
)
elif
action
==
"REASSIGN"
:
return
resources
else
:
return
None
...
...
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