Statistics
| Branch: | Tag: | Revision:

root / api / actions.py @ 1be508e9

History | View | Annotate | Download (7.5 kB)

1
#
2
# Copyright (c) 2010 Greek Research and Technology Network
3
#
4

    
5
from socket import getfqdn
6

    
7
from django.conf import settings
8
from django.http import HttpResponse
9
from django.template.loader import render_to_string
10
from django.utils import simplejson as json
11

    
12
from synnefo.api.faults import BadRequest, ResizeNotAllowed, ServiceUnavailable
13
from synnefo.api.util import random_password
14
from synnefo.util.rapi import GanetiRapiClient
15
from synnefo.util.vapclient import request_forwarding as request_vnc_forwarding
16
from synnefo.logic import backend
17
from synnefo.logic.utils import get_rsapi_state
18

    
19

    
20
server_actions = {}
21

    
22
rapi = GanetiRapiClient(*settings.GANETI_CLUSTER_INFO)
23

    
24

    
25
def server_action(name):
26
    '''Decorator for functions implementing server actions.
27
    
28
       `name` is the key in the dict passed by the client.
29
    '''
30
    
31
    def decorator(func):
32
        server_actions[name] = func
33
        return func
34
    return decorator
35

    
36
@server_action('console')
37
def get_console(request, vm, args):
38
    """Arrange for an OOB console of the specified type
39

40
    This method arranges for an OOB console of the specified type.
41
    Only "vnc" type consoles are supported for now.
42
    It uses a running instance of vncauthproxy to setup proper
43
    VNC forwarding with a random password, then returns the necessary
44
    VNC connection info to the caller.
45

46
    """
47
    # Normal Response Code: 200
48
    # Error Response Codes: computeFault (400, 500),
49
    #                       serviceUnavailable (503),
50
    #                       unauthorized (401),
51
    #                       badRequest (400),
52
    #                       badMediaType(415),
53
    #                       itemNotFound (404),
54
    #                       buildInProgress (409),
55
    #                       overLimit (413)
56
    try:
57
        console_type = args.get('type', '')
58
        if console_type != 'VNC':
59
            raise BadRequest(message="type can only be 'VNC'")
60
    except KeyError:
61
        raise BadRequest()
62

    
63
    # Use RAPI to get VNC console information for this instance
64
    if get_rsapi_state(vm) != 'ACTIVE':
65
        raise BadRequest(message="Server not in ACTIVE state")
66
    console_data = rapi.GetInstanceConsole(vm.backend_id)
67
    if console_data['kind'] != 'vnc':
68
        raise ServiceUnavailable()
69

    
70
    # Let vncauthproxy decide on the source port.
71
    # The alternative: static allocation, e.g.
72
    # sport = console_data['port'] - 1000]
73
    sport = 0
74
    daddr = console_data['host']
75
    dport = console_data['port']
76
    passwd = random_password()
77

    
78
    try:
79
        fwd = request_vnc_forwarding(sport, daddr, dport, passwd)
80
        if fwd['status'] != "OK":
81
            raise ServiceUnavailable("Could not allocate VNC console port")
82
        vnc = { 'host': getfqdn(), 'port': fwd['source_port'], 'password': passwd }
83
    except Exception:
84
        #raise ServiceUnavailable("Could not allocate VNC console port")
85
        raise
86

    
87
    # Format to be reviewed by [verigak], FIXME
88
    if request.serialization == 'xml':
89
        mimetype = 'application/xml'
90
        data = render_to_string('vnc.xml', {'vnc': vnc})
91
    else:
92
        mimetype = 'application/json'
93
        data = json.dumps(vnc)
94

    
95
    return HttpResponse(data, mimetype=mimetype, status=200)
96

    
97

    
98
@server_action('changePassword')
99
def change_password(request, vm, args):
100
    # Normal Response Code: 202
101
    # Error Response Codes: computeFault (400, 500),
102
    #                       serviceUnavailable (503),
103
    #                       unauthorized (401),
104
    #                       badRequest (400),
105
    #                       badMediaType(415),
106
    #                       itemNotFound (404),
107
    #                       buildInProgress (409),
108
    #                       overLimit (413)
109
    
110
    try:
111
        adminPass = args['adminPass']
112
    except KeyError:
113
        raise BadRequest()
114

    
115
    raise ServiceUnavailable()
116

    
117
@server_action('reboot')
118
def reboot(request, vm, args):
119
    # Normal Response Code: 202
120
    # Error Response Codes: computeFault (400, 500),
121
    #                       serviceUnavailable (503),
122
    #                       unauthorized (401),
123
    #                       badRequest (400),
124
    #                       badMediaType(415),
125
    #                       itemNotFound (404),
126
    #                       buildInProgress (409),
127
    #                       overLimit (413)
128
    
129
    reboot_type = args.get('type', '')
130
    if reboot_type not in ('SOFT', 'HARD'):
131
        raise BadRequest()
132
    
133
    backend.start_action(vm, 'REBOOT')
134
    rapi.RebootInstance(vm.backend_id, reboot_type.lower())
135
    return HttpResponse(status=202)
136

    
137
@server_action('start')
138
def start(request, vm, args):
139
    # Normal Response Code: 202
140
    # Error Response Codes: serviceUnavailable (503),
141
    #                       itemNotFound (404)
142

    
143
    backend.start_action(vm, 'START')
144
    rapi.StartupInstance(vm.backend_id)
145
    return HttpResponse(status=202)
146

    
147
@server_action('shutdown')
148
def shutdown(request, vm, args):
149
    # Normal Response Code: 202
150
    # Error Response Codes: serviceUnavailable (503),
151
    #                       itemNotFound (404)
152
    
153
    backend.start_action(vm, 'STOP')
154
    rapi.ShutdownInstance(vm.backend_id)
155
    return HttpResponse(status=202)
156

    
157
@server_action('rebuild')
158
def rebuild(request, vm, args):
159
    # Normal Response Code: 202
160
    # Error Response Codes: computeFault (400, 500),
161
    #                       serviceUnavailable (503),
162
    #                       unauthorized (401),
163
    #                       badRequest (400),
164
    #                       badMediaType(415),
165
    #                       itemNotFound (404),
166
    #                       buildInProgress (409),
167
    #                       serverCapacityUnavailable (503),
168
    #                       overLimit (413)
169

    
170
    raise ServiceUnavailable()
171

    
172
@server_action('resize')
173
def resize(request, vm, args):
174
    # Normal Response Code: 202
175
    # Error Response Codes: computeFault (400, 500),
176
    #                       serviceUnavailable (503),
177
    #                       unauthorized (401),
178
    #                       badRequest (400),
179
    #                       badMediaType(415),
180
    #                       itemNotFound (404),
181
    #                       buildInProgress (409),
182
    #                       serverCapacityUnavailable (503),
183
    #                       overLimit (413),
184
    #                       resizeNotAllowed (403)
185
    
186
    raise ResizeNotAllowed()
187

    
188
@server_action('confirmResize')
189
def confirm_resize(request, vm, args):
190
    # Normal Response Code: 204
191
    # Error Response Codes: computeFault (400, 500),
192
    #                       serviceUnavailable (503),
193
    #                       unauthorized (401),
194
    #                       badRequest (400),
195
    #                       badMediaType(415),
196
    #                       itemNotFound (404),
197
    #                       buildInProgress (409),
198
    #                       serverCapacityUnavailable (503),
199
    #                       overLimit (413),
200
    #                       resizeNotAllowed (403)
201
    
202
    raise ResizeNotAllowed()
203

    
204
@server_action('revertResize')
205
def revert_resize(request, vm, args):
206
    # Normal Response Code: 202
207
    # Error Response Codes: computeFault (400, 500),
208
    #                       serviceUnavailable (503),
209
    #                       unauthorized (401),
210
    #                       badRequest (400),
211
    #                       badMediaType(415),
212
    #                       itemNotFound (404),
213
    #                       buildInProgress (409),
214
    #                       serverCapacityUnavailable (503),
215
    #                       overLimit (413),
216
    #                       resizeNotAllowed (403)
217

    
218
    raise ResizeNotAllowed()