Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / api / actions.py @ 1ed2557d

History | View | Annotate | Download (12.6 kB)

1 adee02b8 Giorgos Verigakis
# Copyright 2011 GRNET S.A. All rights reserved.
2 adee02b8 Giorgos Verigakis
# 
3 adee02b8 Giorgos Verigakis
# Redistribution and use in source and binary forms, with or
4 adee02b8 Giorgos Verigakis
# without modification, are permitted provided that the following
5 adee02b8 Giorgos Verigakis
# conditions are met:
6 adee02b8 Giorgos Verigakis
# 
7 adee02b8 Giorgos Verigakis
#   1. Redistributions of source code must retain the above
8 adee02b8 Giorgos Verigakis
#      copyright notice, this list of conditions and the following
9 adee02b8 Giorgos Verigakis
#      disclaimer.
10 adee02b8 Giorgos Verigakis
# 
11 adee02b8 Giorgos Verigakis
#   2. Redistributions in binary form must reproduce the above
12 adee02b8 Giorgos Verigakis
#      copyright notice, this list of conditions and the following
13 adee02b8 Giorgos Verigakis
#      disclaimer in the documentation and/or other materials
14 adee02b8 Giorgos Verigakis
#      provided with the distribution.
15 adee02b8 Giorgos Verigakis
# 
16 adee02b8 Giorgos Verigakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 adee02b8 Giorgos Verigakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 adee02b8 Giorgos Verigakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 adee02b8 Giorgos Verigakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 adee02b8 Giorgos Verigakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 adee02b8 Giorgos Verigakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 adee02b8 Giorgos Verigakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 adee02b8 Giorgos Verigakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 adee02b8 Giorgos Verigakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 adee02b8 Giorgos Verigakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 adee02b8 Giorgos Verigakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 adee02b8 Giorgos Verigakis
# POSSIBILITY OF SUCH DAMAGE.
28 adee02b8 Giorgos Verigakis
# 
29 adee02b8 Giorgos Verigakis
# The views and conclusions contained in the software and
30 adee02b8 Giorgos Verigakis
# documentation are those of the authors and should not be
31 adee02b8 Giorgos Verigakis
# interpreted as representing official policies, either expressed
32 adee02b8 Giorgos Verigakis
# or implied, of GRNET S.A.
33 b016b476 Giorgos Verigakis
34 aea3e7c6 Vangelis Koukis
from socket import getfqdn
35 1f092444 Faidon Liambotis
from vncauthproxy.client import request_forwarding as request_vnc_forwarding
36 aea3e7c6 Vangelis Koukis
37 77f0fa63 Christos Stavrakakis
from django.db import transaction
38 b016b476 Giorgos Verigakis
from django.conf import settings
39 b016b476 Giorgos Verigakis
from django.http import HttpResponse
40 09471611 Vangelis Koukis
from django.template.loader import render_to_string
41 09471611 Vangelis Koukis
from django.utils import simplejson as json
42 b016b476 Giorgos Verigakis
43 0196d9a3 Christos Stavrakakis
from synnefo.api.faults import (BadRequest, ServiceUnavailable,
44 0196d9a3 Christos Stavrakakis
                                ItemNotFound, BuildInProgress)
45 fdc94944 Christos Stavrakakis
from synnefo.api.util import (random_password, get_vm, get_nic_from_index,
46 fdc94944 Christos Stavrakakis
                              get_network_free_address)
47 77f0fa63 Christos Stavrakakis
from synnefo.db.models import NetworkInterface, Network
48 fdc94944 Christos Stavrakakis
from synnefo.db.pools import EmptyPool
49 03992c72 Christos Stavrakakis
from synnefo.logic import backend
50 20a51b1e Giorgos Verigakis
from synnefo.logic.utils import get_rsapi_state
51 d8e50a39 Giorgos Verigakis
52 0971fa71 Markos Gogoulos
53 b016b476 Giorgos Verigakis
server_actions = {}
54 e2ee7808 Giorgos Verigakis
network_actions = {}
55 b016b476 Giorgos Verigakis
56 b016b476 Giorgos Verigakis
57 b016b476 Giorgos Verigakis
def server_action(name):
58 d8e50a39 Giorgos Verigakis
    '''Decorator for functions implementing server actions.
59 529178b1 Giorgos Verigakis
    `name` is the key in the dict passed by the client.
60 d8e50a39 Giorgos Verigakis
    '''
61 aa197ee4 Vangelis Koukis
62 b016b476 Giorgos Verigakis
    def decorator(func):
63 b016b476 Giorgos Verigakis
        server_actions[name] = func
64 b016b476 Giorgos Verigakis
        return func
65 b016b476 Giorgos Verigakis
    return decorator
66 b016b476 Giorgos Verigakis
67 4dba0480 Christos Stavrakakis
68 e2ee7808 Giorgos Verigakis
def network_action(name):
69 e2ee7808 Giorgos Verigakis
    '''Decorator for functions implementing network actions.
70 e2ee7808 Giorgos Verigakis
    `name` is the key in the dict passed by the client.
71 e2ee7808 Giorgos Verigakis
    '''
72 e2ee7808 Giorgos Verigakis
73 e2ee7808 Giorgos Verigakis
    def decorator(func):
74 e2ee7808 Giorgos Verigakis
        network_actions[name] = func
75 e2ee7808 Giorgos Verigakis
        return func
76 e2ee7808 Giorgos Verigakis
    return decorator
77 e2ee7808 Giorgos Verigakis
78 b016b476 Giorgos Verigakis
79 b016b476 Giorgos Verigakis
@server_action('changePassword')
80 20a51b1e Giorgos Verigakis
def change_password(request, vm, args):
81 b016b476 Giorgos Verigakis
    # Normal Response Code: 202
82 b016b476 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
83 b016b476 Giorgos Verigakis
    #                       serviceUnavailable (503),
84 b016b476 Giorgos Verigakis
    #                       unauthorized (401),
85 b016b476 Giorgos Verigakis
    #                       badRequest (400),
86 b016b476 Giorgos Verigakis
    #                       badMediaType(415),
87 b016b476 Giorgos Verigakis
    #                       itemNotFound (404),
88 b016b476 Giorgos Verigakis
    #                       buildInProgress (409),
89 b016b476 Giorgos Verigakis
    #                       overLimit (413)
90 aa197ee4 Vangelis Koukis
91 529178b1 Giorgos Verigakis
    raise ServiceUnavailable('Changing password is not supported.')
92 b016b476 Giorgos Verigakis
93 b016b476 Giorgos Verigakis
@server_action('reboot')
94 20a51b1e Giorgos Verigakis
def reboot(request, vm, args):
95 b016b476 Giorgos Verigakis
    # Normal Response Code: 202
96 b016b476 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
97 b016b476 Giorgos Verigakis
    #                       serviceUnavailable (503),
98 b016b476 Giorgos Verigakis
    #                       unauthorized (401),
99 b016b476 Giorgos Verigakis
    #                       badRequest (400),
100 b016b476 Giorgos Verigakis
    #                       badMediaType(415),
101 b016b476 Giorgos Verigakis
    #                       itemNotFound (404),
102 b016b476 Giorgos Verigakis
    #                       buildInProgress (409),
103 b016b476 Giorgos Verigakis
    #                       overLimit (413)
104 aa197ee4 Vangelis Koukis
105 0971fa71 Markos Gogoulos
    reboot_type = args.get('type', '')
106 0971fa71 Markos Gogoulos
    if reboot_type not in ('SOFT', 'HARD'):
107 529178b1 Giorgos Verigakis
        raise BadRequest('Malformed Request.')
108 64938cb0 Giorgos Verigakis
    backend.reboot_instance(vm, reboot_type.lower())
109 b016b476 Giorgos Verigakis
    return HttpResponse(status=202)
110 b016b476 Giorgos Verigakis
111 b016b476 Giorgos Verigakis
@server_action('start')
112 20a51b1e Giorgos Verigakis
def start(request, vm, args):
113 b016b476 Giorgos Verigakis
    # Normal Response Code: 202
114 d8e50a39 Giorgos Verigakis
    # Error Response Codes: serviceUnavailable (503),
115 d8e50a39 Giorgos Verigakis
    #                       itemNotFound (404)
116 aa197ee4 Vangelis Koukis
117 529178b1 Giorgos Verigakis
    if args:
118 529178b1 Giorgos Verigakis
        raise BadRequest('Malformed Request.')
119 64938cb0 Giorgos Verigakis
    backend.startup_instance(vm)
120 b016b476 Giorgos Verigakis
    return HttpResponse(status=202)
121 b016b476 Giorgos Verigakis
122 b016b476 Giorgos Verigakis
@server_action('shutdown')
123 20a51b1e Giorgos Verigakis
def shutdown(request, vm, args):
124 b016b476 Giorgos Verigakis
    # Normal Response Code: 202
125 d8e50a39 Giorgos Verigakis
    # Error Response Codes: serviceUnavailable (503),
126 d8e50a39 Giorgos Verigakis
    #                       itemNotFound (404)
127 aa197ee4 Vangelis Koukis
128 529178b1 Giorgos Verigakis
    if args:
129 529178b1 Giorgos Verigakis
        raise BadRequest('Malformed Request.')
130 64938cb0 Giorgos Verigakis
    backend.shutdown_instance(vm)
131 b016b476 Giorgos Verigakis
    return HttpResponse(status=202)
132 b016b476 Giorgos Verigakis
133 b016b476 Giorgos Verigakis
@server_action('rebuild')
134 20a51b1e Giorgos Verigakis
def rebuild(request, vm, args):
135 b016b476 Giorgos Verigakis
    # Normal Response Code: 202
136 b016b476 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
137 b016b476 Giorgos Verigakis
    #                       serviceUnavailable (503),
138 b016b476 Giorgos Verigakis
    #                       unauthorized (401),
139 b016b476 Giorgos Verigakis
    #                       badRequest (400),
140 b016b476 Giorgos Verigakis
    #                       badMediaType(415),
141 b016b476 Giorgos Verigakis
    #                       itemNotFound (404),
142 b016b476 Giorgos Verigakis
    #                       buildInProgress (409),
143 b016b476 Giorgos Verigakis
    #                       serverCapacityUnavailable (503),
144 b016b476 Giorgos Verigakis
    #                       overLimit (413)
145 b016b476 Giorgos Verigakis
146 529178b1 Giorgos Verigakis
    raise ServiceUnavailable('Rebuild not supported.')
147 b016b476 Giorgos Verigakis
148 b016b476 Giorgos Verigakis
@server_action('resize')
149 20a51b1e Giorgos Verigakis
def resize(request, vm, args):
150 b016b476 Giorgos Verigakis
    # Normal Response Code: 202
151 b016b476 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
152 b016b476 Giorgos Verigakis
    #                       serviceUnavailable (503),
153 b016b476 Giorgos Verigakis
    #                       unauthorized (401),
154 b016b476 Giorgos Verigakis
    #                       badRequest (400),
155 b016b476 Giorgos Verigakis
    #                       badMediaType(415),
156 b016b476 Giorgos Verigakis
    #                       itemNotFound (404),
157 b016b476 Giorgos Verigakis
    #                       buildInProgress (409),
158 b016b476 Giorgos Verigakis
    #                       serverCapacityUnavailable (503),
159 b016b476 Giorgos Verigakis
    #                       overLimit (413),
160 b016b476 Giorgos Verigakis
    #                       resizeNotAllowed (403)
161 aa197ee4 Vangelis Koukis
162 529178b1 Giorgos Verigakis
    raise ServiceUnavailable('Resize not supported.')
163 b016b476 Giorgos Verigakis
164 b016b476 Giorgos Verigakis
@server_action('confirmResize')
165 20a51b1e Giorgos Verigakis
def confirm_resize(request, vm, args):
166 b016b476 Giorgos Verigakis
    # Normal Response Code: 204
167 b016b476 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
168 b016b476 Giorgos Verigakis
    #                       serviceUnavailable (503),
169 b016b476 Giorgos Verigakis
    #                       unauthorized (401),
170 b016b476 Giorgos Verigakis
    #                       badRequest (400),
171 b016b476 Giorgos Verigakis
    #                       badMediaType(415),
172 b016b476 Giorgos Verigakis
    #                       itemNotFound (404),
173 b016b476 Giorgos Verigakis
    #                       buildInProgress (409),
174 b016b476 Giorgos Verigakis
    #                       serverCapacityUnavailable (503),
175 b016b476 Giorgos Verigakis
    #                       overLimit (413),
176 b016b476 Giorgos Verigakis
    #                       resizeNotAllowed (403)
177 aa197ee4 Vangelis Koukis
178 529178b1 Giorgos Verigakis
    raise ServiceUnavailable('Resize not supported.')
179 b016b476 Giorgos Verigakis
180 b016b476 Giorgos Verigakis
@server_action('revertResize')
181 20a51b1e Giorgos Verigakis
def revert_resize(request, vm, args):
182 b016b476 Giorgos Verigakis
    # Normal Response Code: 202
183 b016b476 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
184 b016b476 Giorgos Verigakis
    #                       serviceUnavailable (503),
185 b016b476 Giorgos Verigakis
    #                       unauthorized (401),
186 b016b476 Giorgos Verigakis
    #                       badRequest (400),
187 b016b476 Giorgos Verigakis
    #                       badMediaType(415),
188 b016b476 Giorgos Verigakis
    #                       itemNotFound (404),
189 b016b476 Giorgos Verigakis
    #                       buildInProgress (409),
190 b016b476 Giorgos Verigakis
    #                       serverCapacityUnavailable (503),
191 b016b476 Giorgos Verigakis
    #                       overLimit (413),
192 b016b476 Giorgos Verigakis
    #                       resizeNotAllowed (403)
193 b016b476 Giorgos Verigakis
194 529178b1 Giorgos Verigakis
    raise ServiceUnavailable('Resize not supported.')
195 529178b1 Giorgos Verigakis
196 4dba0480 Christos Stavrakakis
197 529178b1 Giorgos Verigakis
@server_action('console')
198 529178b1 Giorgos Verigakis
def get_console(request, vm, args):
199 529178b1 Giorgos Verigakis
    """Arrange for an OOB console of the specified type
200 529178b1 Giorgos Verigakis

201 529178b1 Giorgos Verigakis
    This method arranges for an OOB console of the specified type.
202 529178b1 Giorgos Verigakis
    Only consoles of type "vnc" are supported for now.
203 529178b1 Giorgos Verigakis

204 529178b1 Giorgos Verigakis
    It uses a running instance of vncauthproxy to setup proper
205 529178b1 Giorgos Verigakis
    VNC forwarding with a random password, then returns the necessary
206 529178b1 Giorgos Verigakis
    VNC connection info to the caller.
207 71099804 Vangelis Koukis

208 529178b1 Giorgos Verigakis
    """
209 529178b1 Giorgos Verigakis
    # Normal Response Code: 200
210 529178b1 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
211 529178b1 Giorgos Verigakis
    #                       serviceUnavailable (503),
212 529178b1 Giorgos Verigakis
    #                       unauthorized (401),
213 529178b1 Giorgos Verigakis
    #                       badRequest (400),
214 529178b1 Giorgos Verigakis
    #                       badMediaType(415),
215 529178b1 Giorgos Verigakis
    #                       itemNotFound (404),
216 529178b1 Giorgos Verigakis
    #                       buildInProgress (409),
217 529178b1 Giorgos Verigakis
    #                       overLimit (413)
218 aa197ee4 Vangelis Koukis
219 529178b1 Giorgos Verigakis
    console_type = args.get('type', '')
220 529178b1 Giorgos Verigakis
    if console_type != 'vnc':
221 529178b1 Giorgos Verigakis
        raise BadRequest('Type can only be "vnc".')
222 529178b1 Giorgos Verigakis
223 529178b1 Giorgos Verigakis
    # Use RAPI to get VNC console information for this instance
224 529178b1 Giorgos Verigakis
    if get_rsapi_state(vm) != 'ACTIVE':
225 529178b1 Giorgos Verigakis
        raise BadRequest('Server not in ACTIVE state.')
226 aa197ee4 Vangelis Koukis
227 529178b1 Giorgos Verigakis
    if settings.TEST:
228 529178b1 Giorgos Verigakis
        console_data = {'kind': 'vnc', 'host': 'ganeti_node', 'port': 1000}
229 529178b1 Giorgos Verigakis
    else:
230 64938cb0 Giorgos Verigakis
        console_data = backend.get_instance_console(vm)
231 aa197ee4 Vangelis Koukis
232 529178b1 Giorgos Verigakis
    if console_data['kind'] != 'vnc':
233 71099804 Vangelis Koukis
        message = 'got console of kind %s, not "vnc"' % console_data['kind']
234 b36f78fa Giorgos Verigakis
        raise ServiceUnavailable(message)
235 aa197ee4 Vangelis Koukis
236 529178b1 Giorgos Verigakis
    # Let vncauthproxy decide on the source port.
237 529178b1 Giorgos Verigakis
    # The alternative: static allocation, e.g.
238 529178b1 Giorgos Verigakis
    # sport = console_data['port'] - 1000
239 529178b1 Giorgos Verigakis
    sport = 0
240 529178b1 Giorgos Verigakis
    daddr = console_data['host']
241 529178b1 Giorgos Verigakis
    dport = console_data['port']
242 529178b1 Giorgos Verigakis
    password = random_password()
243 aa197ee4 Vangelis Koukis
244 71099804 Vangelis Koukis
    if settings.TEST:
245 71099804 Vangelis Koukis
        fwd = {'source_port': 1234, 'status': 'OK'}
246 71099804 Vangelis Koukis
    else:
247 71099804 Vangelis Koukis
        fwd = request_vnc_forwarding(sport, daddr, dport, password)
248 529178b1 Giorgos Verigakis
249 529178b1 Giorgos Verigakis
    if fwd['status'] != "OK":
250 71099804 Vangelis Koukis
        raise ServiceUnavailable('vncauthproxy returned error status')
251 aa197ee4 Vangelis Koukis
252 bb54871d Stratos Psomadakis
    # Verify that the VNC server settings haven't changed
253 bb54871d Stratos Psomadakis
    if not settings.TEST:
254 bb54871d Stratos Psomadakis
        if console_data != backend.get_instance_console(vm):
255 bb54871d Stratos Psomadakis
            raise ServiceUnavailable('VNC Server settings changed.')
256 bb54871d Stratos Psomadakis
257 529178b1 Giorgos Verigakis
    console = {
258 529178b1 Giorgos Verigakis
        'type': 'vnc',
259 529178b1 Giorgos Verigakis
        'host': getfqdn(),
260 529178b1 Giorgos Verigakis
        'port': fwd['source_port'],
261 529178b1 Giorgos Verigakis
        'password': password}
262 aa197ee4 Vangelis Koukis
263 529178b1 Giorgos Verigakis
    if request.serialization == 'xml':
264 529178b1 Giorgos Verigakis
        mimetype = 'application/xml'
265 529178b1 Giorgos Verigakis
        data = render_to_string('console.xml', {'console': console})
266 529178b1 Giorgos Verigakis
    else:
267 529178b1 Giorgos Verigakis
        mimetype = 'application/json'
268 529178b1 Giorgos Verigakis
        data = json.dumps({'console': console})
269 aa197ee4 Vangelis Koukis
270 529178b1 Giorgos Verigakis
    return HttpResponse(data, mimetype=mimetype, status=200)
271 e2ee7808 Giorgos Verigakis
272 4dba0480 Christos Stavrakakis
273 91826390 Giorgos Verigakis
@server_action('firewallProfile')
274 4dba0480 Christos Stavrakakis
@transaction.commit_on_success
275 91826390 Giorgos Verigakis
def set_firewall_profile(request, vm, args):
276 26563957 Giorgos Verigakis
    # Normal Response Code: 200
277 26563957 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
278 26563957 Giorgos Verigakis
    #                       serviceUnavailable (503),
279 26563957 Giorgos Verigakis
    #                       unauthorized (401),
280 26563957 Giorgos Verigakis
    #                       badRequest (400),
281 26563957 Giorgos Verigakis
    #                       badMediaType(415),
282 26563957 Giorgos Verigakis
    #                       itemNotFound (404),
283 26563957 Giorgos Verigakis
    #                       buildInProgress (409),
284 26563957 Giorgos Verigakis
    #                       overLimit (413)
285 4dba0480 Christos Stavrakakis
286 91826390 Giorgos Verigakis
    profile = args.get('profile', '')
287 26563957 Giorgos Verigakis
    if profile not in [x[0] for x in NetworkInterface.FIREWALL_PROFILES]:
288 91826390 Giorgos Verigakis
        raise BadRequest("Unsupported firewall profile")
289 91826390 Giorgos Verigakis
    backend.set_firewall_profile(vm, profile)
290 91826390 Giorgos Verigakis
    return HttpResponse(status=202)
291 91826390 Giorgos Verigakis
292 e2ee7808 Giorgos Verigakis
293 e2ee7808 Giorgos Verigakis
@network_action('add')
294 77f0fa63 Christos Stavrakakis
@transaction.commit_on_success
295 e2ee7808 Giorgos Verigakis
def add(request, net, args):
296 13b954b0 Giorgos Verigakis
    # Normal Response Code: 202
297 13b954b0 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
298 13b954b0 Giorgos Verigakis
    #                       serviceUnavailable (503),
299 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
300 13b954b0 Giorgos Verigakis
    #                       badRequest (400),
301 13b954b0 Giorgos Verigakis
    #                       badMediaType(415),
302 13b954b0 Giorgos Verigakis
    #                       itemNotFound (404),
303 13b954b0 Giorgos Verigakis
    #                       overLimit (413)
304 aa197ee4 Vangelis Koukis
305 dca6520b Giorgos Verigakis
    server_id = args.get('serverRef', None)
306 e2ee7808 Giorgos Verigakis
    if not server_id:
307 e2ee7808 Giorgos Verigakis
        raise BadRequest('Malformed Request.')
308 4b3b8688 Giorgos Verigakis
    vm = get_vm(server_id, request.user_uniq)
309 77f0fa63 Christos Stavrakakis
310 1ed2557d Christos Stavrakakis
    net = Network.objects.get(id=net.id)
311 8d03316d Dimitris Aragiorgis
312 8d03316d Dimitris Aragiorgis
    if net.state != 'ACTIVE':
313 8d03316d Dimitris Aragiorgis
        raise ServiceUnavailable('Network not active yet')
314 8d03316d Dimitris Aragiorgis
315 77f0fa63 Christos Stavrakakis
    # Get a free IP from the address pool.
316 77f0fa63 Christos Stavrakakis
    try:
317 fdc94944 Christos Stavrakakis
        address = get_network_free_address(net)
318 fdc94944 Christos Stavrakakis
    except EmptyPool:
319 77f0fa63 Christos Stavrakakis
        raise ServiceUnavailable('Network is full')
320 77f0fa63 Christos Stavrakakis
321 77f0fa63 Christos Stavrakakis
    backend.connect_to_network(vm, net, address)
322 e2ee7808 Giorgos Verigakis
    return HttpResponse(status=202)
323 e2ee7808 Giorgos Verigakis
324 77f0fa63 Christos Stavrakakis
325 e2ee7808 Giorgos Verigakis
@network_action('remove')
326 4dba0480 Christos Stavrakakis
@transaction.commit_on_success
327 e2ee7808 Giorgos Verigakis
def remove(request, net, args):
328 13b954b0 Giorgos Verigakis
    # Normal Response Code: 202
329 13b954b0 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
330 13b954b0 Giorgos Verigakis
    #                       serviceUnavailable (503),
331 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
332 13b954b0 Giorgos Verigakis
    #                       badRequest (400),
333 13b954b0 Giorgos Verigakis
    #                       badMediaType(415),
334 13b954b0 Giorgos Verigakis
    #                       itemNotFound (404),
335 13b954b0 Giorgos Verigakis
    #                       overLimit (413)
336 aa197ee4 Vangelis Koukis
337 4dba0480 Christos Stavrakakis
    try:  # attachment string: nic-<vm-id>-<nic-index>
338 08b079e2 Stavros Sachtouris
        server_id = args.get('attachment', None).split('-')[1]
339 08b079e2 Stavros Sachtouris
        nic_index = args.get('attachment', None).split('-')[2]
340 99a74636 Christos Stavrakakis
    except AttributeError:
341 99a74636 Christos Stavrakakis
        raise BadRequest("Malformed Request")
342 08b079e2 Stavros Sachtouris
    except IndexError:
343 08b079e2 Stavros Sachtouris
        raise BadRequest('Malformed Network Interface Id')
344 08b079e2 Stavros Sachtouris
345 08b079e2 Stavros Sachtouris
    if not server_id or not nic_index:
346 e2ee7808 Giorgos Verigakis
        raise BadRequest('Malformed Request.')
347 4b3b8688 Giorgos Verigakis
    vm = get_vm(server_id, request.user_uniq)
348 08b079e2 Stavros Sachtouris
    nic = get_nic_from_index(vm, nic_index)
349 0196d9a3 Christos Stavrakakis
350 0196d9a3 Christos Stavrakakis
    if nic.dirty:
351 0196d9a3 Christos Stavrakakis
        raise BuildInProgress('Machine is busy.')
352 0196d9a3 Christos Stavrakakis
    else:
353 0196d9a3 Christos Stavrakakis
        vm.nics.all().update(dirty=True)
354 0196d9a3 Christos Stavrakakis
355 0196d9a3 Christos Stavrakakis
    backend.disconnect_from_network(vm, nic)
356 e2ee7808 Giorgos Verigakis
    return HttpResponse(status=202)