Statistics
| Branch: | Tag: | Revision:

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

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

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

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

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