Newer
Older
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
# This file is part of CloudControl.
#
# CloudControl is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# CloudControl is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with CloudControl. If not, see <http://www.gnu.org/licenses/>.
import threading
from cloudcontrol.common.jobs import Job
from cloudcontrol.server.allocator import Allocator, AllocationError
class DeployError(Exception):
""" Exception raised when an error occurs while deploying a
virtual machine on an hypervisor.
"""
class AllocationJob(Job):
""" Allocate a set of VM on hypervisors.
"""
# Global allocation lock. Must be locked before to do allocation for a
# single virtual machine:
allocation_lock = threading.Lock()
def job(self, server, client, expanded_vmspec, tql_target=None):
allocator = Allocator(self.logger.getChild('allocator'), server, client)
results_by_vm = {}
total = len(expanded_vmspec)
errors = 0
for i, vmspec in enumerate(expanded_vmspec):
self.title = 'Virtual machines allocation (%d/%d, %d errors)' % (i + 1, total, errors)
with AllocationJob.allocation_lock:
self.checkpoint()
try:
target_hv_name = allocator.allocate(vmspec, tql_target)[0]
except AllocationError, err:
self.logger.warn('VM %s: allocation error: %s. Skipping...' % (vmspec['title'], err))
results_by_vm[vmspec['title']] = 'allocation error, %s' % err
errors += 1
except Exception, err:
self.logger.exception('VM %s: unknow error while allocation: %s. Skipping...' % (vmspec['title'], err))
results_by_vm[vmspec['title']] = 'unknown error (see logs)'
errors += 1
else:
# Keep the VM target in a tag for future migrations
if 'tags' not in vmspec:
vmspec['tags'] = {}
vmspec['tags'].setdefault('target', vmspec['target'])
try:
vm_uuid = self._deploy(vmspec, server.get_client(target_hv_name))
except Exception as err:
results_by_vm[vmspec['title']] = 'Error: %s' % err
errors += 1
else:
self.logger.info('VM %s: spawned on %s' % (vmspec['title'], target_hv_name))
results_by_vm[vmspec['title']] = 'spawned %s on %s' % (vm_uuid, target_hv_name)
# Write a summary of the Allocation job in the results attachment:
results = self.attachment('results')
for vm_name, result in results_by_vm.iteritems():
results.write('%s: %s\n' % (vm_name, result))
def _deploy(self, vmspec, target_hv):
# Delete keys which are not recognized by subsequent components:
for key in ('target', 'flags', 'riskgroup'):
try:
del vmspec[key]
except KeyError:
pass
return target_hv.define(vmspec, format='vmspec')