Commit f755d686 authored by Antoine Millet's avatar Antoine Millet

Implemented allocation job and handler

parent cc47bce9
......@@ -17,6 +17,8 @@
from sjrpc.core import RpcError
from cloudcontrol.common.datastructures.orderedset import OrderedSet
from cloudcontrol.common.allocation.vmspec import expand_vmspec
from cloudcontrol.server.conf import CCConf
from cloudcontrol.server.exceptions import (ReservedTagError, BadRoleError,
NotConnectedAccountError, CloneError)
......@@ -26,7 +28,7 @@ from cloudcontrol.server.repository import RepositoryOperationError
from cloudcontrol.server.handlers import listed, Reporter
from cloudcontrol.server.clients import Client, RegisteredCCHandler
from cloudcontrol.server.jobs import (ColdMigrationJob, HotMigrationJob,
CloneJob, KillClientJob)
CloneJob, KillClientJob, AllocationJob)
from cloudcontrol.common.tql.db.tag import StaticTag
MIGRATION_TYPES = {'cold': ColdMigrationJob,
......@@ -1012,7 +1014,7 @@ class CliHandler(RegisteredCCHandler):
return errs.get_dict()
#
# Election / Migration / Cloning:
# Election / Migration / Cloning / Allocation
#
@listed
......@@ -1102,6 +1104,25 @@ class CliHandler(RegisteredCCHandler):
'hv_dest': dest['id']})
return job.id
@listed
def allocate(self, vmspec, tql_target):
""" Allocate new VMs.
:param vmspec: a vmspec structure
:param tql_target: a TQL used as target restriction
"""
self.client.check('allocate')
# Check and expand vmspec input:
expanded_vmspec = expand_vmspec(vmspec)
job = self.client.spawn_job(AllocationJob, settings={'server': self.server,
'client': self.client,
'expanded_vmspec': expanded_vmspec,
'tql_target': tql_target})
return job.id
#
# Remote console:
#
......
......@@ -22,7 +22,8 @@ from cloudcontrol.server.jobs.hotmigration import HotMigrationJob
from cloudcontrol.server.jobs.clone import CloneJob
from cloudcontrol.server.jobs.killoldcli import KillOldCliJob
from cloudcontrol.server.jobs.killclient import KillClientJob
from cloudcontrol.server.jobs.allocation import AllocationJob
__all__ = ('ColdMigrationJob', 'HotMigrationJob', 'CloneJob', 'KillOldCliJob',
'KillClientJob')
\ No newline at end of file
'KillClientJob', 'AllocationJob')
\ No newline at end of file
# 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')
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment