Revision ca4d59e3
b/snf-cyclades-app/synnefo/logic/backend.py | ||
---|---|---|
36 | 36 |
|
37 | 37 |
from synnefo.db.models import (Backend, VirtualMachine, Network, |
38 | 38 |
BackendNetwork, BACKEND_STATUSES, |
39 |
pooled_rapi_client, VirtualMachineDiagnostic) |
|
39 |
pooled_rapi_client, VirtualMachineDiagnostic, |
|
40 |
Flavor) |
|
40 | 41 |
from synnefo.logic import utils |
41 | 42 |
from synnefo import quotas |
42 | 43 |
from synnefo.api.util import release_resource |
... | ... | |
55 | 56 |
|
56 | 57 |
|
57 | 58 |
@transaction.commit_on_success |
58 |
def process_op_status(vm, etime, jobid, opcode, status, logmsg, nics=None): |
|
59 |
def process_op_status(vm, etime, jobid, opcode, status, logmsg, nics=None, |
|
60 |
beparams=None): |
|
59 | 61 |
"""Process a job progress notification from the backend |
60 | 62 |
|
61 | 63 |
Process an incoming message from the backend (currently Ganeti). |
... | ... | |
78 | 80 |
if status == 'success' and state_for_success is not None: |
79 | 81 |
vm.operstate = state_for_success |
80 | 82 |
|
81 |
# Update the NICs of the VM |
|
82 | 83 |
if status == "success" and nics is not None: |
84 |
# Update the NICs of the VM |
|
83 | 85 |
_process_net_status(vm, etime, nics) |
84 | 86 |
|
87 |
if beparams: |
|
88 |
assert(opcode == "OP_INSTANCE_SET_PARAMS"), "'beparams' should exist"\ |
|
89 |
" only for SET_PARAMS" |
|
90 |
# VM Resize |
|
91 |
if status == "success": |
|
92 |
# VM has been resized. Change the flavor |
|
93 |
_process_resize(vm, beparams) |
|
94 |
vm.operstate = "STOPPED" |
|
95 |
elif status in ("canceled", "error"): |
|
96 |
vm.operstate = "STOPPED" |
|
97 |
else: |
|
98 |
vm.operstate = "RESIZE" |
|
99 |
|
|
85 | 100 |
# Special case: if OP_INSTANCE_CREATE fails --> ERROR |
86 | 101 |
if opcode == 'OP_INSTANCE_CREATE' and status in ('canceled', 'error'): |
87 | 102 |
vm.operstate = 'ERROR' |
... | ... | |
111 | 126 |
vm.save() |
112 | 127 |
|
113 | 128 |
|
129 |
def _process_resize(vm, beparams): |
|
130 |
"""Change flavor of a VirtualMachine based on new beparams.""" |
|
131 |
old_flavor = vm.flavor |
|
132 |
vcpus = beparams.get("vcpus", None) or old_flavor.cpu |
|
133 |
minmem, maxmem = beparams.get("minmem"), beparams.get("maxmem") |
|
134 |
assert(minmem == maxmem), "Different minmem from maxmem" |
|
135 |
if vcpus is None and maxmem is None: |
|
136 |
return |
|
137 |
ram = maxmem or old_flavor.ram |
|
138 |
try: |
|
139 |
new_flavor = Flavor.objects.get(cpu=vcpus, ram=ram, |
|
140 |
disk=old_flavor.disk, |
|
141 |
disk_template=old_flavor.disk_template) |
|
142 |
except Flavor.DoesNotExist: |
|
143 |
raise Exception("Can not find flavor for VM") |
|
144 |
vm.flavor = new_flavor |
|
145 |
vm.save() |
|
146 |
|
|
147 |
|
|
114 | 148 |
@transaction.commit_on_success |
115 | 149 |
def process_net_status(vm, etime, nics): |
116 | 150 |
"""Wrap _process_net_status inside transaction.""" |
b/snf-cyclades-app/synnefo/logic/callbacks.py | ||
---|---|---|
171 | 171 |
return |
172 | 172 |
|
173 | 173 |
nics = msg.get("nics", None) |
174 |
beparams = msg.get("beparams", None) |
|
174 | 175 |
backend.process_op_status(vm, event_time, msg['jobId'], msg['operation'], |
175 |
msg['status'], msg['logmsg'], nics) |
|
176 |
msg['status'], msg['logmsg'], nics=nics, |
|
177 |
beparams=beparams) |
|
176 | 178 |
|
177 | 179 |
log.debug("Done processing ganeti-op-status msg for vm %s.", |
178 | 180 |
msg['instance']) |
b/snf-cyclades-app/synnefo/logic/tests.py | ||
---|---|---|
193 | 193 |
self.assertEqual(db_vm.operstate, vm.operstate) |
194 | 194 |
self.assertEqual(db_vm.backendtime, vm.backendtime) |
195 | 195 |
|
196 |
def test_resize_msg(self, client): |
|
197 |
vm = mfactory.VirtualMachineFactory() |
|
198 |
# Test empty beparams |
|
199 |
for status in ["success", "error"]: |
|
200 |
msg = self.create_msg(operation='OP_INSTANCE_SET_PARAMS', |
|
201 |
instance=vm.backend_vm_id, |
|
202 |
beparams={}, |
|
203 |
status=status) |
|
204 |
client.reset_mock() |
|
205 |
update_db(client, msg) |
|
206 |
self.assertTrue(client.basic_ack.called) |
|
207 |
db_vm = VirtualMachine.objects.get(id=vm.id) |
|
208 |
self.assertEqual(db_vm.operstate, vm.operstate) |
|
209 |
# Test intermediate states |
|
210 |
for status in ["queued", "waiting", "running"]: |
|
211 |
msg = self.create_msg(operation='OP_INSTANCE_SET_PARAMS', |
|
212 |
instance=vm.backend_vm_id, |
|
213 |
beparams={"vcpus": 4, "minmem": 2048, |
|
214 |
"maxmem": 2048}, |
|
215 |
status=status) |
|
216 |
client.reset_mock() |
|
217 |
update_db(client, msg) |
|
218 |
self.assertTrue(client.basic_ack.called) |
|
219 |
db_vm = VirtualMachine.objects.get(id=vm.id) |
|
220 |
self.assertEqual(db_vm.operstate, "RESIZE") |
|
221 |
# Test operstate after error |
|
222 |
msg = self.create_msg(operation='OP_INSTANCE_SET_PARAMS', |
|
223 |
instance=vm.backend_vm_id, |
|
224 |
beparams={"vcpus": 4}, |
|
225 |
status="error") |
|
226 |
client.reset_mock() |
|
227 |
update_db(client, msg) |
|
228 |
self.assertTrue(client.basic_ack.called) |
|
229 |
db_vm = VirtualMachine.objects.get(id=vm.id) |
|
230 |
self.assertEqual(db_vm.operstate, "STOPPED") |
|
231 |
# Test success |
|
232 |
f1 = mfactory.FlavorFactory(cpu=4, ram=1024, disk_template="drbd", |
|
233 |
disk=1024) |
|
234 |
vm.flavor = f1 |
|
235 |
vm.save() |
|
236 |
f2 = mfactory.FlavorFactory(cpu=8, ram=2048, disk_template="drbd", |
|
237 |
disk=1024) |
|
238 |
msg = self.create_msg(operation='OP_INSTANCE_SET_PARAMS', |
|
239 |
instance=vm.backend_vm_id, |
|
240 |
beparams={"vcpus": 8, "minmem": 2048, |
|
241 |
"maxmem": 2048}, |
|
242 |
status="success") |
|
243 |
client.reset_mock() |
|
244 |
update_db(client, msg) |
|
245 |
self.assertTrue(client.basic_ack.called) |
|
246 |
db_vm = VirtualMachine.objects.get(id=vm.id) |
|
247 |
self.assertEqual(db_vm.operstate, "STOPPED") |
|
248 |
self.assertEqual(db_vm.flavor, f2) |
|
249 |
msg = self.create_msg(operation='OP_INSTANCE_SET_PARAMS', |
|
250 |
instance=vm.backend_vm_id, |
|
251 |
beparams={"vcpus": 100, "minmem": 2048, |
|
252 |
"maxmem": 2048}, |
|
253 |
status="success") |
|
254 |
client.reset_mock() |
|
255 |
update_db(client, msg) |
|
256 |
self.assertTrue(client.basic_reject.called) |
|
257 |
|
|
196 | 258 |
|
197 | 259 |
@patch('synnefo.lib.amqp.AMQPClient') |
198 | 260 |
class UpdateNetTest(TestCase): |
Also available in: Unified diff