Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (13.1 kB)

1 e440e835 Christos Stavrakakis
# Copyright 2011, 2012, 2013 GRNET S.A. All rights reserved.
2 e440e835 Christos Stavrakakis
#
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 e440e835 Christos Stavrakakis
#
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 e440e835 Christos Stavrakakis
#
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 e440e835 Christos Stavrakakis
#
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 e440e835 Christos Stavrakakis
#
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 bd40abfa Christos Stavrakakis
from snf_django.lib.api import faults
44 fdc94944 Christos Stavrakakis
from synnefo.api.util import (random_password, get_vm, get_nic_from_index,
45 fdc94944 Christos Stavrakakis
                              get_network_free_address)
46 e440e835 Christos Stavrakakis
from synnefo.db.models import NetworkInterface
47 fdc94944 Christos Stavrakakis
from synnefo.db.pools import EmptyPool
48 03992c72 Christos Stavrakakis
from synnefo.logic import backend
49 20a51b1e Giorgos Verigakis
from synnefo.logic.utils import get_rsapi_state
50 d8e50a39 Giorgos Verigakis
51 bf5c82dc Christos Stavrakakis
from logging import getLogger
52 bf5c82dc Christos Stavrakakis
log = getLogger(__name__)
53 bf5c82dc Christos Stavrakakis
54 0971fa71 Markos Gogoulos
55 b016b476 Giorgos Verigakis
server_actions = {}
56 e2ee7808 Giorgos Verigakis
network_actions = {}
57 b016b476 Giorgos Verigakis
58 b016b476 Giorgos Verigakis
59 b016b476 Giorgos Verigakis
def server_action(name):
60 d8e50a39 Giorgos Verigakis
    '''Decorator for functions implementing server actions.
61 529178b1 Giorgos Verigakis
    `name` is the key in the dict passed by the client.
62 d8e50a39 Giorgos Verigakis
    '''
63 aa197ee4 Vangelis Koukis
64 b016b476 Giorgos Verigakis
    def decorator(func):
65 b016b476 Giorgos Verigakis
        server_actions[name] = func
66 b016b476 Giorgos Verigakis
        return func
67 b016b476 Giorgos Verigakis
    return decorator
68 b016b476 Giorgos Verigakis
69 4dba0480 Christos Stavrakakis
70 e2ee7808 Giorgos Verigakis
def network_action(name):
71 e2ee7808 Giorgos Verigakis
    '''Decorator for functions implementing network actions.
72 e2ee7808 Giorgos Verigakis
    `name` is the key in the dict passed by the client.
73 e2ee7808 Giorgos Verigakis
    '''
74 e2ee7808 Giorgos Verigakis
75 e2ee7808 Giorgos Verigakis
    def decorator(func):
76 e2ee7808 Giorgos Verigakis
        network_actions[name] = func
77 e2ee7808 Giorgos Verigakis
        return func
78 e2ee7808 Giorgos Verigakis
    return decorator
79 e2ee7808 Giorgos Verigakis
80 b016b476 Giorgos Verigakis
81 b016b476 Giorgos Verigakis
@server_action('changePassword')
82 20a51b1e Giorgos Verigakis
def change_password(request, vm, args):
83 b016b476 Giorgos Verigakis
    # Normal Response Code: 202
84 b016b476 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
85 b016b476 Giorgos Verigakis
    #                       serviceUnavailable (503),
86 b016b476 Giorgos Verigakis
    #                       unauthorized (401),
87 b016b476 Giorgos Verigakis
    #                       badRequest (400),
88 b016b476 Giorgos Verigakis
    #                       badMediaType(415),
89 b016b476 Giorgos Verigakis
    #                       itemNotFound (404),
90 b016b476 Giorgos Verigakis
    #                       buildInProgress (409),
91 b016b476 Giorgos Verigakis
    #                       overLimit (413)
92 aa197ee4 Vangelis Koukis
93 bd40abfa Christos Stavrakakis
    raise faults.NotImplemented('Changing password is not supported.')
94 b016b476 Giorgos Verigakis
95 bf5c82dc Christos Stavrakakis
96 b016b476 Giorgos Verigakis
@server_action('reboot')
97 20a51b1e Giorgos Verigakis
def reboot(request, vm, args):
98 b016b476 Giorgos Verigakis
    # Normal Response Code: 202
99 b016b476 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
100 b016b476 Giorgos Verigakis
    #                       serviceUnavailable (503),
101 b016b476 Giorgos Verigakis
    #                       unauthorized (401),
102 b016b476 Giorgos Verigakis
    #                       badRequest (400),
103 b016b476 Giorgos Verigakis
    #                       badMediaType(415),
104 b016b476 Giorgos Verigakis
    #                       itemNotFound (404),
105 b016b476 Giorgos Verigakis
    #                       buildInProgress (409),
106 b016b476 Giorgos Verigakis
    #                       overLimit (413)
107 aa197ee4 Vangelis Koukis
108 bf5c82dc Christos Stavrakakis
    log.info("Reboot VM %s", vm)
109 0971fa71 Markos Gogoulos
    reboot_type = args.get('type', '')
110 0971fa71 Markos Gogoulos
    if reboot_type not in ('SOFT', 'HARD'):
111 bd40abfa Christos Stavrakakis
        raise faults.BadRequest('Malformed Request.')
112 64938cb0 Giorgos Verigakis
    backend.reboot_instance(vm, reboot_type.lower())
113 b016b476 Giorgos Verigakis
    return HttpResponse(status=202)
114 b016b476 Giorgos Verigakis
115 bf5c82dc Christos Stavrakakis
116 b016b476 Giorgos Verigakis
@server_action('start')
117 20a51b1e Giorgos Verigakis
def start(request, vm, args):
118 b016b476 Giorgos Verigakis
    # Normal Response Code: 202
119 d8e50a39 Giorgos Verigakis
    # Error Response Codes: serviceUnavailable (503),
120 d8e50a39 Giorgos Verigakis
    #                       itemNotFound (404)
121 aa197ee4 Vangelis Koukis
122 bf5c82dc Christos Stavrakakis
    log.info("Start VM %s", vm)
123 529178b1 Giorgos Verigakis
    if args:
124 bd40abfa Christos Stavrakakis
        raise faults.BadRequest('Malformed Request.')
125 64938cb0 Giorgos Verigakis
    backend.startup_instance(vm)
126 b016b476 Giorgos Verigakis
    return HttpResponse(status=202)
127 b016b476 Giorgos Verigakis
128 bf5c82dc Christos Stavrakakis
129 b016b476 Giorgos Verigakis
@server_action('shutdown')
130 20a51b1e Giorgos Verigakis
def shutdown(request, vm, args):
131 b016b476 Giorgos Verigakis
    # Normal Response Code: 202
132 d8e50a39 Giorgos Verigakis
    # Error Response Codes: serviceUnavailable (503),
133 d8e50a39 Giorgos Verigakis
    #                       itemNotFound (404)
134 aa197ee4 Vangelis Koukis
135 bf5c82dc Christos Stavrakakis
    log.info("Shutdown VM %s", vm)
136 529178b1 Giorgos Verigakis
    if args:
137 bd40abfa Christos Stavrakakis
        raise faults.BadRequest('Malformed Request.')
138 64938cb0 Giorgos Verigakis
    backend.shutdown_instance(vm)
139 b016b476 Giorgos Verigakis
    return HttpResponse(status=202)
140 b016b476 Giorgos Verigakis
141 bf5c82dc Christos Stavrakakis
142 b016b476 Giorgos Verigakis
@server_action('rebuild')
143 20a51b1e Giorgos Verigakis
def rebuild(request, vm, args):
144 b016b476 Giorgos Verigakis
    # Normal Response Code: 202
145 b016b476 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
146 b016b476 Giorgos Verigakis
    #                       serviceUnavailable (503),
147 b016b476 Giorgos Verigakis
    #                       unauthorized (401),
148 b016b476 Giorgos Verigakis
    #                       badRequest (400),
149 b016b476 Giorgos Verigakis
    #                       badMediaType(415),
150 b016b476 Giorgos Verigakis
    #                       itemNotFound (404),
151 b016b476 Giorgos Verigakis
    #                       buildInProgress (409),
152 b016b476 Giorgos Verigakis
    #                       serverCapacityUnavailable (503),
153 b016b476 Giorgos Verigakis
    #                       overLimit (413)
154 b016b476 Giorgos Verigakis
155 bd40abfa Christos Stavrakakis
    raise faults.NotImplemented('Rebuild not supported.')
156 b016b476 Giorgos Verigakis
157 bf5c82dc Christos Stavrakakis
158 b016b476 Giorgos Verigakis
@server_action('resize')
159 20a51b1e Giorgos Verigakis
def resize(request, vm, args):
160 b016b476 Giorgos Verigakis
    # Normal Response Code: 202
161 b016b476 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
162 b016b476 Giorgos Verigakis
    #                       serviceUnavailable (503),
163 b016b476 Giorgos Verigakis
    #                       unauthorized (401),
164 b016b476 Giorgos Verigakis
    #                       badRequest (400),
165 b016b476 Giorgos Verigakis
    #                       badMediaType(415),
166 b016b476 Giorgos Verigakis
    #                       itemNotFound (404),
167 b016b476 Giorgos Verigakis
    #                       buildInProgress (409),
168 b016b476 Giorgos Verigakis
    #                       serverCapacityUnavailable (503),
169 b016b476 Giorgos Verigakis
    #                       overLimit (413),
170 b016b476 Giorgos Verigakis
    #                       resizeNotAllowed (403)
171 aa197ee4 Vangelis Koukis
172 bd40abfa Christos Stavrakakis
    raise faults.NotImplemented('Resize not supported.')
173 b016b476 Giorgos Verigakis
174 bf5c82dc Christos Stavrakakis
175 b016b476 Giorgos Verigakis
@server_action('confirmResize')
176 20a51b1e Giorgos Verigakis
def confirm_resize(request, vm, args):
177 b016b476 Giorgos Verigakis
    # Normal Response Code: 204
178 b016b476 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
179 b016b476 Giorgos Verigakis
    #                       serviceUnavailable (503),
180 b016b476 Giorgos Verigakis
    #                       unauthorized (401),
181 b016b476 Giorgos Verigakis
    #                       badRequest (400),
182 b016b476 Giorgos Verigakis
    #                       badMediaType(415),
183 b016b476 Giorgos Verigakis
    #                       itemNotFound (404),
184 b016b476 Giorgos Verigakis
    #                       buildInProgress (409),
185 b016b476 Giorgos Verigakis
    #                       serverCapacityUnavailable (503),
186 b016b476 Giorgos Verigakis
    #                       overLimit (413),
187 b016b476 Giorgos Verigakis
    #                       resizeNotAllowed (403)
188 aa197ee4 Vangelis Koukis
189 bd40abfa Christos Stavrakakis
    raise faults.NotImplemented('Resize not supported.')
190 b016b476 Giorgos Verigakis
191 bf5c82dc Christos Stavrakakis
192 b016b476 Giorgos Verigakis
@server_action('revertResize')
193 20a51b1e Giorgos Verigakis
def revert_resize(request, vm, args):
194 b016b476 Giorgos Verigakis
    # Normal Response Code: 202
195 b016b476 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
196 b016b476 Giorgos Verigakis
    #                       serviceUnavailable (503),
197 b016b476 Giorgos Verigakis
    #                       unauthorized (401),
198 b016b476 Giorgos Verigakis
    #                       badRequest (400),
199 b016b476 Giorgos Verigakis
    #                       badMediaType(415),
200 b016b476 Giorgos Verigakis
    #                       itemNotFound (404),
201 b016b476 Giorgos Verigakis
    #                       buildInProgress (409),
202 b016b476 Giorgos Verigakis
    #                       serverCapacityUnavailable (503),
203 b016b476 Giorgos Verigakis
    #                       overLimit (413),
204 b016b476 Giorgos Verigakis
    #                       resizeNotAllowed (403)
205 b016b476 Giorgos Verigakis
206 bd40abfa Christos Stavrakakis
    raise faults.NotImplemented('Resize not supported.')
207 529178b1 Giorgos Verigakis
208 4dba0480 Christos Stavrakakis
209 529178b1 Giorgos Verigakis
@server_action('console')
210 529178b1 Giorgos Verigakis
def get_console(request, vm, args):
211 529178b1 Giorgos Verigakis
    """Arrange for an OOB console of the specified type
212 529178b1 Giorgos Verigakis

213 529178b1 Giorgos Verigakis
    This method arranges for an OOB console of the specified type.
214 529178b1 Giorgos Verigakis
    Only consoles of type "vnc" are supported for now.
215 529178b1 Giorgos Verigakis

216 529178b1 Giorgos Verigakis
    It uses a running instance of vncauthproxy to setup proper
217 529178b1 Giorgos Verigakis
    VNC forwarding with a random password, then returns the necessary
218 529178b1 Giorgos Verigakis
    VNC connection info to the caller.
219 71099804 Vangelis Koukis

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