views.py 19.9 KB
Newer Older
1
# Copyright 2011, 2012, 2013 GRNET S.A. All rights reserved.
2
#
3
4
5
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
6
#
7
8
9
#   1. Redistributions of source code must retain the above
#      copyright notice, this list of conditions and the following
#      disclaimer.
10
#
11
12
13
14
#   2. Redistributions in binary form must reproduce the above
#      copyright notice, this list of conditions and the following
#      disclaimer in the documentation and/or other materials
#      provided with the distribution.
15
#
16
17
18
19
20
21
22
23
24
25
26
27
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
30
31
32
# The views and conclusions contained in the software and
# documentation are those of the authors and should not be
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
33
#
34

35
import os
36

37
from django.conf import settings
38
from django.utils.translation import gettext_lazy as _
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
39
from django.template import loader
Dimitris Moraitis's avatar
Dimitris Moraitis committed
40
from django.http import HttpResponse
Dimitris Moraitis's avatar
Dimitris Moraitis committed
41
from django.utils.translation import get_language
Markos Gogoulos's avatar
Markos Gogoulos committed
42
from django.utils import simplejson as json
43
from synnefo_branding.utils import render_to_string
44
from django.core.urlresolvers import reverse
45
from django.template import RequestContext
Kostas Papadimitriou's avatar
Kostas Papadimitriou committed
46

Kostas Papadimitriou's avatar
Kostas Papadimitriou committed
47
from synnefo.util.version import get_component_version
48

49
from synnefo.ui import settings as uisettings
50

Kostas Papadimitriou's avatar
Kostas Papadimitriou committed
51
SYNNEFO_JS_LIB_VERSION = get_component_version('app')
Kostas Papadimitriou's avatar
Kostas Papadimitriou committed
52

53
54
# UI preferences settings
TIMEOUT = getattr(settings, "TIMEOUT", 10000)
55
UPDATE_INTERVAL = getattr(settings, "UI_UPDATE_INTERVAL", 5000)
56
CHANGES_SINCE_ALIGNMENT = getattr(settings, "UI_CHANGES_SINCE_ALIGNMENT", 0)
57
58
UPDATE_INTERVAL_INCREASE = getattr(settings, "UI_UPDATE_INTERVAL_INCREASE",
                                   500)
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
59
60
UPDATE_INTERVAL_INCREASE_AFTER_CALLS_COUNT = \
    getattr(settings, "UI_UPDATE_INTERVAL_INCREASE_AFTER_CALLS_COUNT", 3)
61
62
UPDATE_INTERVAL_FAST = getattr(settings, "UI_UPDATE_INTERVAL_FAST", 2500)
UPDATE_INTERVAL_MAX = getattr(settings, "UI_UPDATE_INTERVAL_MAX", 10000)
Kostas Papadimitriou's avatar
Kostas Papadimitriou committed
63

64
# predefined values settings
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
65
66
VM_IMAGE_COMMON_METADATA = \
    getattr(settings, "UI_VM_IMAGE_COMMON_METADATA", ["OS", "users"])
67
SUGGESTED_FLAVORS_DEFAULT = {}
Kostas Papadimitriou's avatar
Kostas Papadimitriou committed
68
69
70
71
72
73
SUGGESTED_FLAVORS = getattr(settings, "VM_CREATE_SUGGESTED_FLAVORS",
                            SUGGESTED_FLAVORS_DEFAULT)
SUGGESTED_ROLES_DEFAULT = ["Database server", "File server", "Mail server",
                           "Web server", "Proxy"]
SUGGESTED_ROLES = getattr(settings, "VM_CREATE_SUGGESTED_ROLES",
                          SUGGESTED_ROLES_DEFAULT)
Kostas Papadimitriou's avatar
Kostas Papadimitriou committed
74
IMAGE_ICONS = settings.IMAGE_ICONS
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
75
76
77
78
IMAGE_DELETED_TITLE = \
    getattr(settings, 'UI_IMAGE_DELETED_TITLE', '(deleted)')
IMAGE_DELETED_SIZE_TITLE = \
    getattr(settings, 'UI_IMAGE_DELETED_SIZE_TITLE', '(none)')
79

80
81
SUPPORT_SSH_OS_LIST = getattr(settings, "UI_SUPPORT_SSH_OS_LIST",)
OS_CREATED_USERS = getattr(settings, "UI_OS_DEFAULT_USER_MAP")
82
UNKNOWN_OS = getattr(settings, "UI_UNKNOWN_OS", "unknown")
83

84
AUTH_COOKIE_NAME = getattr(settings, "UI_AUTH_COOKIE_NAME", 'synnefo_user')
Kostas Papadimitriou's avatar
Kostas Papadimitriou committed
85

86
87
88
# never change window location. Helpful in development environments
AUTH_SKIP_REDIRECTS = getattr(settings, "UI_AUTH_SKIP_REDIRECTS", False)

89
90
91
# UI behaviour settings
DELAY_ON_BLUR = getattr(settings, "UI_DELAY_ON_BLUR", True)
UPDATE_HIDDEN_VIEWS = getattr(settings, "UI_UPDATE_HIDDEN_VIEWS", False)
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
92
93
HANDLE_WINDOW_EXCEPTIONS = \
    getattr(settings, "UI_HANDLE_WINDOW_EXCEPTIONS", True)
94
SKIP_TIMEOUTS = getattr(settings, "UI_SKIP_TIMEOUTS", 1)
Kostas Papadimitriou's avatar
Kostas Papadimitriou committed
95

96
97
# Additional settings
VM_NAME_TEMPLATE = getattr(settings, "VM_CREATE_NAME_TPL", "My {0} server")
98
NO_FQDN_MESSAGE = getattr(settings, "UI_NO_FQDN_MESSAGE", "No available FQDN")
99

100
MAX_SSH_KEYS_PER_USER = getattr(settings, "USERDATA_MAX_SSH_KEYS_PER_USER")
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
101
102
FLAVORS_DISK_TEMPLATES_INFO = \
    getattr(settings, "UI_FLAVORS_DISK_TEMPLATES_INFO", {})
103
SYSTEM_IMAGES_OWNERS = getattr(settings, "UI_SYSTEM_IMAGES_OWNERS", {})
104
CUSTOM_IMAGE_HELP_URL = getattr(settings, "UI_CUSTOM_IMAGE_HELP_URL", None)
Kostas Papadimitriou's avatar
Kostas Papadimitriou committed
105

106
# MEDIA PATHS
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
UI_MEDIA_URL = \
    getattr(settings, "UI_MEDIA_URL",
            "%ssnf-%s/" % (settings.MEDIA_URL, SYNNEFO_JS_LIB_VERSION))
UI_SYNNEFO_IMAGES_URL = \
    getattr(settings,
            "UI_SYNNEFO_IMAGES_URL", UI_MEDIA_URL + "images/")
UI_SYNNEFO_CSS_URL = \
    getattr(settings,
            "UI_SYNNEFO_CSS_URL", UI_MEDIA_URL + "css/")
UI_SYNNEFO_JS_URL = \
    getattr(settings,
            "UI_SYNNEFO_JS_URL", UI_MEDIA_URL + "js/")
UI_SYNNEFO_JS_LIB_URL = \
    getattr(settings,
            "UI_SYNNEFO_JS_LIB_URL", UI_SYNNEFO_JS_URL + "lib/")
UI_SYNNEFO_JS_WEB_URL = \
    getattr(settings, "UI_SYNNEFO_JS_WEB_URL", UI_SYNNEFO_JS_URL + "ui/web/")
124

Kostas Papadimitriou's avatar
Kostas Papadimitriou committed
125
126
# extensions
ENABLE_GLANCE = getattr(settings, 'UI_ENABLE_GLANCE', True)
127

Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
128
129
DIAGNOSTICS_UPDATE_INTERVAL = \
    getattr(settings, 'UI_DIAGNOSTICS_UPDATE_INTERVAL', 2000)
130

131
# network settings
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
132
133
134
135
136
DEFAULT_NETWORK_TYPES = {'MAC_FILTERED': 'mac-filtering',
                         'PHYSICAL_VLAN': 'physical-vlan'}
NETWORK_TYPES = \
    getattr(settings,
            'UI_NETWORK_AVAILABLE_NETWORK_TYPES', DEFAULT_NETWORK_TYPES)
137
DEFAULT_NETWORK_SUBNETS = ['10.0.0.0/24', '192.168.1.1/24']
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
138
139
140
141
142
143
144
145
146
NETWORK_SUBNETS = \
    getattr(settings,
            'UI_NETWORK_AVAILABLE_SUBNETS', DEFAULT_NETWORK_SUBNETS)
NETWORK_DUPLICATE_NICS = \
    getattr(settings,
            'UI_NETWORK_ALLOW_DUPLICATE_VM_NICS', False)
NETWORK_STRICT_DESTROY = \
    getattr(settings,
            'UI_NETWORK_STRICT_DESTROY', False)
147
148
149
PRIVATE_NETWORKS_NIC_HOTPLUG = \
    getattr(settings,
            'UI_PRIVATE_NETWORK_NIC_HOTPLUG', False)
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
150
151
152
NETWORK_ALLOW_MULTIPLE_DESTROY = \
    getattr(settings,
            'UI_NETWORK_ALLOW_MULTIPLE_DESTROY', False)
153
154
AUTOMATIC_NETWORK_RANGE_FORMAT = getattr(settings,
                                         'UI_AUTOMATIC_NETWORK_RANGE_FORMAT',
155
156
                                         "192.168.%d.0/24").replace("%d",
                                                                    "{0}")
157
GROUP_PUBLIC_NETWORKS = getattr(settings, 'UI_GROUP_PUBLIC_NETWORKS', True)
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
158
159
GROUPED_PUBLIC_NETWORK_NAME = \
    getattr(settings, 'UI_GROUPED_PUBLIC_NETWORK_NAME', 'Internet')
160

161

162
163
DEFAULT_FORCED_SERVER_NETWORKS = \
    getattr(settings, "CYCLADES_FORCED_SERVER_NETWORKS", [])
164
165
166
FORCED_SERVER_NETWORKS = getattr(settings, "UI_FORCED_SERVER_NETWORKS",
                                 DEFAULT_FORCED_SERVER_NETWORKS)

167

168
def template(name, request, context):
Dimitris Moraitis's avatar
Dimitris Moraitis committed
169
    template_path = os.path.join(os.path.dirname(__file__), "templates/")
170
171
    current_template = template_path + name + '.html'
    t = loader.get_template(current_template)
172
    media_context = {
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
173
174
175
176
177
178
179
180
        'UI_MEDIA_URL': UI_MEDIA_URL,
        'SYNNEFO_JS_URL': UI_SYNNEFO_JS_URL,
        'SYNNEFO_JS_LIB_URL': UI_SYNNEFO_JS_LIB_URL,
        'SYNNEFO_JS_WEB_URL': UI_SYNNEFO_JS_WEB_URL,
        'SYNNEFO_IMAGES_URL': UI_SYNNEFO_IMAGES_URL,
        'SYNNEFO_CSS_URL': UI_SYNNEFO_CSS_URL,
        'SYNNEFO_JS_LIB_VERSION': SYNNEFO_JS_LIB_VERSION,
        'DEBUG': settings.DEBUG
181
182
    }
    context.update(media_context)
183
    return HttpResponse(t.render(RequestContext(request, context)))
Dimitris Moraitis's avatar
Dimitris Moraitis committed
184

Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
185

Dimitris Moraitis's avatar
Dimitris Moraitis committed
186
def home(request):
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
187
188
189
190
191
192
    context = {
        'timeout': TIMEOUT,
        'project': '+nefo',
        'request': request,
        'current_lang': get_language() or 'en',
        'compute_api_url': json.dumps(uisettings.COMPUTE_URL),
193
        'network_api_url': json.dumps(uisettings.NETWORK_URL),
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
        'user_catalog_url': json.dumps(uisettings.USER_CATALOG_URL),
        'feedback_post_url': json.dumps(uisettings.FEEDBACK_URL),
        'accounts_api_url': json.dumps(uisettings.ACCOUNT_URL),
        'logout_redirect': json.dumps(uisettings.LOGOUT_REDIRECT),
        'login_redirect': json.dumps(uisettings.LOGIN_URL),
        'glance_api_url': json.dumps(uisettings.GLANCE_URL),
        'translate_uuids': json.dumps(True),
        # update interval settings
        'update_interval': UPDATE_INTERVAL,
        'update_interval_increase': UPDATE_INTERVAL_INCREASE,
        'update_interval_increase_after_calls':
        UPDATE_INTERVAL_INCREASE_AFTER_CALLS_COUNT,
        'update_interval_fast': UPDATE_INTERVAL_FAST,
        'update_interval_max': UPDATE_INTERVAL_MAX,
        'changes_since_alignment': CHANGES_SINCE_ALIGNMENT,
        'image_icons': IMAGE_ICONS,
        'auth_cookie_name': AUTH_COOKIE_NAME,
        'auth_skip_redirects': json.dumps(AUTH_SKIP_REDIRECTS),
        'suggested_flavors': json.dumps(SUGGESTED_FLAVORS),
        'suggested_roles': json.dumps(SUGGESTED_ROLES),
        'vm_image_common_metadata': json.dumps(VM_IMAGE_COMMON_METADATA),
        'synnefo_version': SYNNEFO_JS_LIB_VERSION,
        'delay_on_blur': json.dumps(DELAY_ON_BLUR),
        'update_hidden_views': json.dumps(UPDATE_HIDDEN_VIEWS),
        'handle_window_exceptions': json.dumps(HANDLE_WINDOW_EXCEPTIONS),
        'skip_timeouts': json.dumps(SKIP_TIMEOUTS),
        'vm_name_template': json.dumps(VM_NAME_TEMPLATE),
        'flavors_disk_templates_info': json.dumps(FLAVORS_DISK_TEMPLATES_INFO),
        'support_ssh_os_list': json.dumps(SUPPORT_SSH_OS_LIST),
        'unknown_os': json.dumps(UNKNOWN_OS),
        'os_created_users': json.dumps(OS_CREATED_USERS),
        'userdata_keys_limit': json.dumps(MAX_SSH_KEYS_PER_USER),
        'use_glance': json.dumps(ENABLE_GLANCE),
        'system_images_owners': json.dumps(SYSTEM_IMAGES_OWNERS),
        'custom_image_help_url': CUSTOM_IMAGE_HELP_URL,
        'image_deleted_title': json.dumps(IMAGE_DELETED_TITLE),
        'image_deleted_size_title': json.dumps(IMAGE_DELETED_SIZE_TITLE),
        'network_suggested_subnets': json.dumps(NETWORK_SUBNETS),
        'network_available_types': json.dumps(NETWORK_TYPES),
233
        'forced_server_networks': json.dumps(FORCED_SERVER_NETWORKS),
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
234
235
236
237
238
239
240
241
242
243
244
        'network_allow_duplicate_vm_nics': json.dumps(NETWORK_DUPLICATE_NICS),
        'network_strict_destroy': json.dumps(NETWORK_STRICT_DESTROY),
        'network_allow_multiple_destroy':
        json.dumps(NETWORK_ALLOW_MULTIPLE_DESTROY),
        'automatic_network_range_format':
        json.dumps(AUTOMATIC_NETWORK_RANGE_FORMAT),
        'grouped_public_network_name': json.dumps(GROUPED_PUBLIC_NETWORK_NAME),
        'group_public_networks': json.dumps(GROUP_PUBLIC_NETWORKS),
        'private_networks_nic_hotplug':
        json.dumps(PRIVATE_NETWORKS_NIC_HOTPLUG),
        'diagnostics_update_interval': json.dumps(DIAGNOSTICS_UPDATE_INTERVAL),
245
        'no_fqdn_message': json.dumps(NO_FQDN_MESSAGE)
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
246
    }
247
    return template('home', request, context)
Dimitris Moraitis's avatar
Dimitris Moraitis committed
248

Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
249

250
def machines_console(request):
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
251
252
253
254
255
256
257
    host, port, password = ('', '', '')
    host = request.GET.get('host', '')
    port = request.GET.get('port', '')
    password = request.GET.get('password', '')
    machine = request.GET.get('machine', '')
    host_ip = request.GET.get('host_ip', '')
    host_ip_v6 = request.GET.get('host_ip_v6', '')
Kostas Papadimitriou's avatar
Kostas Papadimitriou committed
258
    context = {'host': host, 'port': port, 'password': password,
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
259
260
               'machine': machine, 'host_ip': host_ip,
               'host_ip_v6': host_ip_v6}
261
    return template('machines_console', request, context)
Dimitris Moraitis's avatar
Dimitris Moraitis committed
262

Kostas Papadimitriou's avatar
Kostas Papadimitriou committed
263

264
def js_tests(request):
265
    return template('tests', request, {})
266

Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
267
268
269
270
271
272
273
274
275
276
277
278

CONNECT_LINUX_LINUX_MESSAGE = \
    _("""A direct connection to this machine can be established using the
<a target="_blank" href="http://en.wikipedia.org/wiki/Secure_Shell">
SSH Protocol</a>.
To do so open a terminal and type the following at the prompt to connect
to your machine:""")
CONNECT_LINUX_WINDOWS_MESSAGE = \
    _("""A direct connection to this machine can be established using
<a target="_blank"
href="http://en.wikipedia.org/wiki/Remote_Desktop_Services">
Remote Desktop Service</a>.
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
279
280
To do so, open the following file with an appropriate \
remote desktop client.""")
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
281
282
CONNECT_LINUX_WINDOWS_SUBMESSAGE = \
    _("""If you don't have a Remote Desktop client already installed,
283
we suggest the use of <a target="_blank"
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
284
285
286
287
href=
"http://sourceforge.net/projects/tsclient/files/latest/download?source=files">
tsclient</a>.<br /><span class="important">IMPORTANT: It may take up to 15
minutes for your Windows VM to become available
288
after its creation.</span>""")
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
289
290
291
CONNECT_WINDOWS_LINUX_MESSAGE = \
    _("""A direct connection to this machine can be established using the
<a target="_blank"
292
href="http://en.wikipedia.org/wiki/Secure_Shell">SSH Protocol</a>.
293
Open an ssh client such as PuTTY and type the following:""")
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
294
295
296
297
298
299
300
301
CONNECT_WINDOWS_LINUX_SUBMESSAGE = \
    _("""If you do not have an ssh client already installed,
<a target="_blank"
href="http://the.earth.li/~sgtatham/putty/latest/x86/putty.exe">
Download PuTTY</a>""")

CONNECT_WINDOWS_WINDOWS_MESSAGE = \
    _("""A direct connection to this machine can be
302
303
established using Remote Desktop. Click on the following link, and if asked
open it using "Remote Desktop Connection".
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
304
305
<br /><span class="important">
IMPORTANT: It may take up to 15 minutes for your Windows VM to become available
306
after its creation.</span>""")
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
307
308
CONNECT_WINDOWS_WINDOWS_SUBMESSAGE = \
    _("""Save this file to disk for future use.""")
309
310
311
312
313
314

# info/subinfo for all os combinations
#
# [0] info gets displayed on top of the message box
# [1] subinfo gets displayed on the bottom as extra info
# provided to the user when needed
315
CONNECT_PROMPT_MESSAGES = {
316
    'linux': {
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
317
318
319
        'linux': [CONNECT_LINUX_LINUX_MESSAGE, ""],
        'windows': [CONNECT_LINUX_WINDOWS_MESSAGE,
                    CONNECT_LINUX_WINDOWS_SUBMESSAGE],
320
321
322
        'ssh_message': "ssh %(user)s@%(hostname)s",
        'ssh_message_port': "ssh -p %(port)s %(user)s@%(hostname)s"

323
    },
324
    'windows': {
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
325
326
327
328
        'linux': [CONNECT_WINDOWS_LINUX_MESSAGE,
                  CONNECT_WINDOWS_LINUX_SUBMESSAGE],
        'windows': [CONNECT_WINDOWS_WINDOWS_MESSAGE,
                    CONNECT_WINDOWS_WINDOWS_SUBMESSAGE],
329
330
        'ssh_message': "%(user)s@%(hostname)s",
        'ssh_message_port': "%(user)s@%(hostname)s (port: %(port)s)"
331
332
333
    },
}

Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
334
335
APPEND_CONNECT_PROMPT_MESSAGES = \
    getattr(settings, 'UI_CONNECT_PROMPT_MESSAGES', {})
336
337
for k, v in APPEND_CONNECT_PROMPT_MESSAGES.iteritems():
    CONNECT_PROMPT_MESSAGES[k].update(v)
338

339
# retrieve domain prefix from settings
Kostas Papadimitriou's avatar
Kostas Papadimitriou committed
340
341
DOMAIN_PREFIX = getattr(settings, 'MACHINE_DOMAIN_PREFIX', getattr(settings,
                        'BACKEND_PREFIX_ID', ""))
342
343
344
345

# domain template string
DOMAIN_TPL = "%s%%s" % DOMAIN_PREFIX

Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
346

347
def machines_connect(request):
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
348
349
350
    ip_address = request.GET.get('ip_address', '')
    hostname = request.GET.get('hostname', '')
    operating_system = metadata_os = request.GET.get('os', '')
351
    server_id = request.GET.get('srv', 0)
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
352
    host_os = request.GET.get('host_os', 'Linux').lower()
353
    username = request.GET.get('username', None)
354
    domain = request.GET.get("domain", DOMAIN_TPL % int(server_id))
355
    ports = json.loads(request.GET.get('ports', '{}'))
356

357
    # guess host os
358
359
360
    if host_os != "windows":
        host_os = 'linux'

361
362
363
364
365
366
367
368
369
370
    # guess username
    if not username:
        username = "root"

        if metadata_os.lower() in ['ubuntu', 'kubuntu', 'fedora']:
            username = "user"

        if metadata_os.lower() == "windows":
            username = "Administrator"

371
372
373
    ssh_forward = ports.get("22", None)
    rdp_forward = ports.get("3389", None)

374
375
    # operating system provides ssh access
    ssh = False
376
377
    if operating_system != "windows":
        operating_system = "linux"
378
        ssh = True
379

380
    # rdp param is set, the user requested rdp file
381
382
    # check if we are on windows
    if operating_system == 'windows' and request.GET.get("rdp", False):
383
384
385
386
387
388
        port = '3389'
        if rdp_forward:
            hostname = rdp_forward.get('host', hostname)
            ip_address = rdp_forward.get('host', ip_address)
            port = str(rdp_forward.get('port', '3389'))

389
        extra_rdp_content = ''
390
391
        # UI sent domain info (from vm metadata) use this
        # otherwise use our default snf-<vm_id> domain
392
393
394
395
396
        EXTRA_RDP_CONTENT = getattr(settings, 'UI_EXTRA_RDP_CONTENT', '')
        if callable(EXTRA_RDP_CONTENT):
            extra_rdp_content = EXTRA_RDP_CONTENT(server_id, ip_address,
                                                  hostname, username)
        else:
397
398
399
400
401
402
            if EXTRA_RDP_CONTENT:
                extra_rdp_content = EXTRA_RDP_CONTENT % \
                    {
                        'server_id': server_id,
                        'ip_address': ip_address,
                        'hostname': hostname,
403
404
                        'user': username,
                        'port': port
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
405
                    }
406

407
        rdp_context = {
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
408
409
410
411
            'username': username,
            'domain': domain,
            'ip_address': ip_address,
            'hostname': hostname,
412
            'port': request.GET.get('port', port),
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
413
            'extra_content': extra_rdp_content
414
415
416
417
        }

        rdp_file_data = render_to_string("synnefo-windows.rdp", rdp_context)
        response = HttpResponse(rdp_file_data, mimetype='application/x-rdp')
418
419

        # proper filename, use server id and ip address
420
        filename = "%d-%s.rdp" % (int(server_id), hostname)
421
        response['Content-Disposition'] = 'attachment; filename=%s' % filename
422
    else:
423
424
425
426
427
428
429
430
431
432
433
        message_key = "ssh_message"
        ip_address = ip_address
        hostname = hostname
        port = ''
        if ssh_forward:
            message_key = 'ssh_message_port'
            hostname = ssh_forward.get('host', hostname)
            ip_address = ssh_forward.get('host', ip_address)
            port = str(ssh_forward.get('port', '22'))

        ssh_message = CONNECT_PROMPT_MESSAGES['linux'].get(message_key)
434
        if host_os == 'windows':
435
            ssh_message = CONNECT_PROMPT_MESSAGES['windows'].get(message_key)
436
437
438
439
        if callable(ssh_message):
            link_title = ssh_message(server_id, ip_address, hostname, username)
        else:
            link_title = ssh_message % {
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
440
441
442
                'server_id': server_id,
                'ip_address': ip_address,
                'hostname': hostname,
443
444
                'user': username,
                'port': port
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
445
            }
446
        if (operating_system != "windows"):
447
448
            link_url = None

449
450
        else:
            link_title = _("Remote desktop to %s") % ip_address
451
452
453
454
455
456
            if rdp_forward:
                hostname = rdp_forward.get('host', hostname)
                ip_address = rdp_forward.get('host', ip_address)
                port = str(rdp_forward.get('port', '3389'))
                link_title = _("Remote desktop to %s (port %s)") % (ip_address,
                                                                    port)
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
457
458
            link_url = \
                "%s?ip_address=%s&os=%s&rdp=1&srv=%d&username=%s&domain=%s" \
459
                "&hostname=%s&port=%s" % (
460
                    reverse("ui_machines_connect"), ip_address,
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
461
                    operating_system, int(server_id), username,
462
                    domain, hostname, port)
463

464
465
        # try to find a specific message
        try:
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
466
467
            connect_message = \
                CONNECT_PROMPT_MESSAGES[host_os][operating_system][0]
468
            subinfo = CONNECT_PROMPT_MESSAGES[host_os][operating_system][1]
469
        except KeyError:
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
470
471
472
            connect_message = \
                _("You are trying to connect from a %s "
                  "machine to a %s machine") % (host_os, operating_system)
473
            subinfo = ""
474

475
        response_object = {
Ilias Tsitsimpis's avatar
Ilias Tsitsimpis committed
476
477
478
479
480
481
482
483
484
485
            'ip': ip_address,
            'os': operating_system,
            'ssh': ssh,
            'info': unicode(connect_message),
            'subinfo': unicode(subinfo),
            'link': {'title': unicode(link_title), 'url': link_url}
        }
        response = \
            HttpResponse(json.dumps(response_object),
                         mimetype='application/json')  # no windows, no rdp
486

487
    return response