-
Notifications
You must be signed in to change notification settings - Fork 5
/
funcs.py
181 lines (121 loc) · 6.02 KB
/
funcs.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# NotebookCloud: EC2 Functions
# Uses the Python2.7 runtime and depends on /boto
# /main.py does import * all on this file
# Author: Carl Smith, Piousoft
# MailTo: [email protected]
import random, hashlib, time, os
from google.appengine.api import urlfetch
from google.appengine.ext.webapp import template
import boto
from boto.ec2.connection import EC2Connection
template_dir = os.path.join(os.path.dirname(__file__), 'templates/')
def valid_keys(access_key, secret_key):
'''Simply checks the given keys actually work.'''
try: EC2Connection(access_key, secret_key).get_all_instances()
except: return False
return True
def hash_password(password):
'''This function is derived from passwd in IPython.lib. It hashes a
password correctly for use with the IPython notebook server.'''
h = hashlib.new('sha1')
salt = ('%0' + str(12) + 'x') % random.getrandbits(48)
h.update(password + salt)
return ':'.join(('sha1', salt, h.hexdigest()))
def get_instance_list(access_key, secret_key):
'''This function returns the html for the instance info that is displayed
by the client in the Your Notebook Servers panel.'''
tab = ' '
html_output = ''
refresh = False
connection = EC2Connection(access_key, secret_key)
reservations = connection.get_all_instances()
instances = [inst for res in reservations for inst in res.instances]
for inst in instances:
ours = inst.__dict__['image_id'] == 'ami-affe51c6'
lives = inst.__dict__['state'] != 'terminated'
if ours and lives:
dns_name = inst.__dict__['public_dns_name']
state = inst.__dict__['state']
instance_type = inst.__dict__['instance_type']
instance_id = inst.__dict__['id']
date, time = inst.__dict__['launch_time'].split('T')
time=time[:-5]
transitional = False
if state in ('shutting-down', 'pending', 'stopping', 'running'):
transitional = True
# note: the variable `state` below will be changed to 'serving' if the
# IPython server is online. nbc has no running state, all running
# servers are classed as booting or serving
if state == 'running': state = 'booting'
html_string = (
'<div class=instance>Instance id: <b>{}</b>Type: <b>{}</b>'
'Started: <b>{}</b> ~ <b>{}</b><br>{}State: '
).format(instance_id + tab, instance_type + tab, time, date, tab)
if dns_name:
try: # check if the instance is actively serving
urlfetch.fetch(
'https://'+dns_name+':8888',
validate_certificate=False,
deadline=25
).content
except:
state = '<b>'+state+'</b>'
html_output += html_string + state + '</div>'
else:
html = template_dir + 'serving_buttons.html'
args = {'instance': instance_id}
serving_buttons = template.render(html, args)
html_output += (
html_string +
'<a id="serving" href="https://{}:8888">serving</a>{}</div>'
).format(dns_name, serving_buttons)
# now we know we're running, not booting
transitional = False
else:
if state == 'stopped':
state = '<b>stopped</b>'
html = template_dir + 'stopped_buttons.html'
args = {'instance': instance_id}
stopped_buttons = template.render(html, args)
html_output += html_string + state + stopped_buttons + '</div>'
else:
state = '<b>'+state+'</b>'
html_output += html_string + state + '</div>'
if transitional: refresh = True
if not html_output:
html_output = (
'<br>'+tab+'No instances (launched from NotebookCloud) '
'exist on your AWS account. <br><br>'
)
return refresh, html_output
def create_vm(access_key, secret_key, user_details, instance_class):
'''This function actually launches the new vms, one each time it's
called. It creates a connection to EC2 on that account. It passes the
password for the notebooks pre-hashed, as well as some random user
details. It returns the connection object and the reservation object.
'''
connection = EC2Connection(access_key, secret_key)
group_name = 'notebookcloud_group'
description = 'NotebookCloud: Default Security Group.'
try: group = connection.create_security_group(group_name, description)
except: pass
else: group.authorize('tcp', 8888,8888, '0.0.0.0/0')
reservation = connection.run_instances(
'ami-affe51c6',
instance_type=instance_class,
security_groups=['notebookcloud_group'],
user_data=user_details,
max_count=1
)
return connection, reservation
def control_vm(action, instance_list, access_key, secret_key):
'''Performs action on an existing instance or instances in instance_list.'''
connection = EC2Connection(access_key, secret_key)
if action == 'terminate':
connection.terminate_instances(instance_ids=instance_list)
elif action == 'stop':
connection.stop_instances(instance_ids=instance_list)
elif action == 'start':
connection.start_instances(instance_ids=instance_list)
elif action == 'reboot':
connection.reboot_instances(instance_ids=instance_list)