Revision 4cf8adf8
b/README.develop | ||
---|---|---|
169 | 169 |
$ ./bin/python manage.py loaddata db/fixtures/flavors.json |
170 | 170 |
$ ./bin/python manage.py loaddata db/fixtures/images.json |
171 | 171 |
|
172 |
The following fictures can be loaded optionally depending on
|
|
172 |
The following fixtures can be loaded optionally depending on
|
|
173 | 173 |
testing requirements: |
174 | 174 |
|
175 | 175 |
$ ./bin/python manage.py loaddata db/fixtures/vms.json |
176 |
$ ./bin/python manage.py loaddata db/fixtures/initial_data.json |
|
177 | 176 |
$ ./bin/python manage.py loaddata db/fixtures/disks.json |
178 | 177 |
|
179 | 178 |
7. Set the BACKEND_PREFIX_ID variable to some unique prefix, e.g. your commit |
180 | 179 |
username |
181 | 180 |
|
182 | 181 |
8. Start the system |
183 |
$ ./bin/python db/db_controller.py #DB synch daemon |
|
184 |
$ ./bin/python manage.py runserver #Django |
|
182 |
$ ./bin/python db/db_controller.py # DB synch daemon
|
|
183 |
$ ./bin/python manage.py runserver # Django
|
|
185 | 184 |
|
186 | 185 |
9. (Hopefully) Done |
187 | 186 |
|
b/api/actions.py | ||
---|---|---|
38 | 38 |
"""Arrange for an OOB console of the specified type |
39 | 39 |
|
40 | 40 |
This method arranges for an OOB console of the specified type. |
41 |
Only "vnc" type consoles are supported for now. |
|
41 |
Only consoles of type "vnc" are supported for now. |
|
42 |
|
|
42 | 43 |
It uses a running instance of vncauthproxy to setup proper |
43 | 44 |
VNC forwarding with a random password, then returns the necessary |
44 | 45 |
VNC connection info to the caller. |
45 | 46 |
|
47 |
JSON Request: { |
|
48 |
"console": { |
|
49 |
"type": "vnc" |
|
50 |
} |
|
51 |
} |
|
52 |
|
|
53 |
JSON Reply: { |
|
54 |
"vnc": { |
|
55 |
"host": "fqdn_here", |
|
56 |
"port": a_port_here, |
|
57 |
"password": "a_password_here" |
|
58 |
} |
|
59 |
} |
|
60 |
|
|
46 | 61 |
""" |
47 | 62 |
# Normal Response Code: 200 |
48 | 63 |
# Error Response Codes: computeFault (400, 500), |
... | ... | |
55 | 70 |
# overLimit (413) |
56 | 71 |
try: |
57 | 72 |
console_type = args.get('type', '') |
58 |
if console_type != 'VNC':
|
|
59 |
raise BadRequest(message="type can only be 'VNC'")
|
|
73 |
if console_type != 'vnc':
|
|
74 |
raise BadRequest(message="type can only be 'vnc'")
|
|
60 | 75 |
except KeyError: |
61 | 76 |
raise BadRequest() |
62 | 77 |
|
63 | 78 |
# Use RAPI to get VNC console information for this instance |
64 | 79 |
if get_rsapi_state(vm) != 'ACTIVE': |
65 | 80 |
raise BadRequest(message="Server not in ACTIVE state") |
66 |
console_data = rapi.GetInstanceConsole(vm.backend_id) |
|
81 |
if settings.TEST: |
|
82 |
console_data = { 'kind': 'vnc', 'host': 'ganeti_node', 'port': 1000 } |
|
83 |
else: |
|
84 |
console_data = rapi.GetInstanceConsole(vm.backend_id) |
|
67 | 85 |
if console_data['kind'] != 'vnc': |
68 | 86 |
raise ServiceUnavailable() |
69 | 87 |
|
70 | 88 |
# Let vncauthproxy decide on the source port. |
71 | 89 |
# The alternative: static allocation, e.g. |
72 |
# sport = console_data['port'] - 1000]
|
|
90 |
# sport = console_data['port'] - 1000 |
|
73 | 91 |
sport = 0 |
74 | 92 |
daddr = console_data['host'] |
75 | 93 |
dport = console_data['port'] |
76 | 94 |
passwd = random_password() |
77 | 95 |
|
78 | 96 |
try: |
79 |
fwd = request_vnc_forwarding(sport, daddr, dport, passwd) |
|
97 |
if settings.TEST: |
|
98 |
fwd = { 'source_port': 1234, 'status': 'OK' } |
|
99 |
else: |
|
100 |
fwd = request_vnc_forwarding(sport, daddr, dport, passwd) |
|
80 | 101 |
if fwd['status'] != "OK": |
81 |
raise ServiceUnavailable("Could not allocate VNC console port")
|
|
102 |
raise ServiceUnavailable() |
|
82 | 103 |
vnc = { 'host': getfqdn(), 'port': fwd['source_port'], 'password': passwd } |
83 | 104 |
except Exception: |
84 |
#raise ServiceUnavailable("Could not allocate VNC console port") |
|
85 |
raise |
|
105 |
raise ServiceUnavailable("Could not allocate VNC console port") |
|
86 | 106 |
|
87 | 107 |
# Format to be reviewed by [verigak], FIXME |
88 | 108 |
if request.serialization == 'xml': |
... | ... | |
90 | 110 |
data = render_to_string('vnc.xml', {'vnc': vnc}) |
91 | 111 |
else: |
92 | 112 |
mimetype = 'application/json' |
93 |
data = json.dumps(vnc)
|
|
113 |
data = json.dumps({'vnc': vnc})
|
|
94 | 114 |
|
95 | 115 |
return HttpResponse(data, mimetype=mimetype, status=200) |
96 | 116 |
|
b/api/servers.py | ||
---|---|---|
178 | 178 |
# so that it gets a vm.id and vm.backend_id is valid. |
179 | 179 |
vm.save() |
180 | 180 |
|
181 |
if request.META.get('SERVER_NAME', None) == 'testserver': |
|
182 |
backend_name = 'test-server' |
|
183 |
dry_run = True |
|
184 |
else: |
|
185 |
backend_name = vm.backend_id |
|
186 |
dry_run = False |
|
187 |
|
|
188 | 181 |
try: |
189 | 182 |
jobId = rapi.CreateInstance( |
190 | 183 |
mode='create', |
191 |
name=backend_name,
|
|
184 |
name=vm.backend_id,
|
|
192 | 185 |
disk_template='plain', |
193 | 186 |
disks=[{"size": 2000}], #FIXME: Always ask for a 2GB disk for now |
194 | 187 |
nics=[{}], |
... | ... | |
196 | 189 |
ip_check=False, |
197 | 190 |
name_check=False, |
198 | 191 |
pnode=rapi.GetNodes()[0], #TODO: verify if this is necessary |
199 |
dry_run=dry_run,
|
|
192 |
dry_run=settings.TEST,
|
|
200 | 193 |
beparams=dict(auto_balance=True, vcpus=flavor.cpu, memory=flavor.ram)) |
201 | 194 |
except GanetiApiError: |
202 | 195 |
vm.delete() |
b/api/tests.py | ||
---|---|---|
694 | 694 |
data = json.dumps({'metadata': {'Key1': 'A Value'}}) |
695 | 695 |
response = self.client.post(path, data, content_type='application/json') |
696 | 696 |
self.assertItemNotFound(response) |
697 |
|
|
698 |
|
|
699 |
class ServerVNCConsole(BaseTestCase): |
|
700 |
SERVERS = 1 |
|
701 |
|
|
702 |
def test_not_active_server(self): |
|
703 |
"""Test console req for server not in ACTIVE state returns badRequest""" |
|
704 |
server_id = choice(VirtualMachine.objects.all()).id |
|
705 |
path = '/api/v1.1/servers/%d/action' % server_id |
|
706 |
data = json.dumps({'console': {'type': 'vnc'}}) |
|
707 |
response = self.client.post(path, data, content_type='application/json') |
|
708 |
self.assertBadRequest(response) |
|
709 |
|
|
710 |
def test_active_server(self): |
|
711 |
"""Test console req for ACTIVE server""" |
|
712 |
server_id = choice(VirtualMachine.objects.all()).id |
|
713 |
# FIXME: Start the server properly, instead of tampering with the DB |
|
714 |
vm = choice(VirtualMachine.objects.all()) |
|
715 |
vm.operstate = 'STARTED' |
|
716 |
vm.save() |
|
717 |
server_id = vm.id |
|
718 |
|
|
719 |
path = '/api/v1.1/servers/%d/action' % server_id |
|
720 |
data = json.dumps({'console': {'type': 'vnc'}}) |
|
721 |
response = self.client.post(path, data, content_type='application/json') |
|
722 |
self.assertEqual(response.status_code, 200) |
|
723 |
reply = json.loads(response.content) |
|
724 |
self.assertEqual(reply.keys(), ['vnc']) |
|
725 |
self.assertEqual(set(reply['vnc'].keys()), set(['host', 'port', 'password'])) |
|
726 |
|
b/api/util.py | ||
---|---|---|
132 | 132 |
else: |
133 | 133 |
response['Content-Type'] = 'application/json' |
134 | 134 |
|
135 |
if request.META.get('SERVER_NAME') == 'testserver':
|
|
135 |
if settings.TEST:
|
|
136 | 136 |
response['Date'] = format_date_time(time()) |
137 | 137 |
|
138 | 138 |
def render_metadata(request, metadata, use_values=False, status=200): |
... | ... | |
151 | 151 |
return HttpResponse(data, status=status) |
152 | 152 |
|
153 | 153 |
def render_fault(request, fault): |
154 |
if settings.DEBUG or request.META.get('SERVER_NAME') == 'testserver':
|
|
154 |
if settings.DEBUG or settings.TEST:
|
|
155 | 155 |
fault.details = format_exc(fault) |
156 | 156 |
|
157 | 157 |
if request.serialization == 'xml': |
b/settings.py.dist | ||
---|---|---|
8 | 8 |
DEBUG = True |
9 | 9 |
TEMPLATE_DEBUG = DEBUG |
10 | 10 |
|
11 |
# A quick-n-dirty way to know if we're running unit tests |
|
12 |
import sys |
|
13 |
if len(sys.argv) >= 2: |
|
14 |
TEST = ('manage.py', 'test') == (os.path.basename(sys.argv[0]), sys.argv[1]) |
|
15 |
else: |
|
16 |
TEST = False |
|
17 |
|
|
11 | 18 |
ADMINS = ( |
12 | 19 |
# ('Your Name', 'your_email@domain.com'), |
13 | 20 |
) |
b/tools/cloud | ||
---|---|---|
82 | 82 |
buf = resp.read() or '{}' |
83 | 83 |
reply = json.loads(buf) |
84 | 84 |
|
85 |
# If the response status is not the expected one, |
|
86 |
# assume an error has occured and treat the body |
|
87 |
# as a cloudfault. |
|
85 | 88 |
if resp.status != expected_status: |
86 | 89 |
if len(reply) == 1: |
87 | 90 |
key = reply.keys()[0] |
... | ... | |
241 | 244 |
|
242 | 245 |
def execute(self, server_id): |
243 | 246 |
path = '/api/%s/servers/%d/action' % (self.api, int(server_id)) |
244 |
body = json.dumps({'console':{'type':'VNC'}})
|
|
245 |
reply = self.http_post(path, body)
|
|
246 |
print_dict(reply) |
|
247 |
body = json.dumps({'console':{'type':'vnc'}})
|
|
248 |
reply = self.http_cmd('POST', path, body, 200)
|
|
249 |
print_dict(reply['vnc'])
|
|
247 | 250 |
|
248 | 251 |
|
249 | 252 |
@command_name('lsaddr') |
Also available in: Unified diff