Loading cloudcontrol/server/clients/cli.py +36 −121 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ from cloudcontrol.common.datastructures.orderedset import OrderedSet from cloudcontrol.server.conf import CCConf from cloudcontrol.server.exceptions import (ReservedTagError, BadObjectError, BadRoleError, NotConnectedAccountError, CloneError) CloneError, RightError) from cloudcontrol.server.election import Elector from cloudcontrol.server.handlers import listed, Reporter Loading Loading @@ -66,9 +66,8 @@ class CliHandler(RegisteredCCHandler): :param query: the query to select objects to show """ self.check('list', query) self.logger.debug('Executed list function with query %s', query) objects = self.server.list(query) objects = self.client.list(query, method='list') order = OrderedSet(['id']) #if tags is not None: # order |= OrderedSet(tags) Loading @@ -79,7 +78,7 @@ class CliHandler(RegisteredCCHandler): """ errs = Reporter() # Search all hypervisors of selected vms: for vm in self.server.list(query, show=('r', 'h', 'p')): for vm in self.client.list(query, show=('r', 'h', 'p'), method=method): if vm['r'] != 'vm': errs.error(vm['id'], 'not a vm') else: Loading @@ -99,35 +98,30 @@ class CliHandler(RegisteredCCHandler): def start(self, query): """ Start a virtual machine. """ self.check('start', query) return self._vm_action(query, 'vm_start') @listed def stop(self, query): """ Stop a virtual machine. """ self.check('stop', query) return self._vm_action(query, 'vm_stop') @listed def destroy(self, query): """ Destroy (hard shutdown) a virtual machine. """ self.check('destroy', query) return self._vm_action(query, 'vm_destroy') @listed def pause(self, query): """ Pause a virtual machine. """ self.check('pause', query) return self._vm_action(query, 'vm_suspend') @listed def resume(self, query): """ Resume a virtual machine. """ self.check('resume', query) return self._vm_action(query, 'vm_resume') @listed Loading @@ -136,7 +130,6 @@ class CliHandler(RegisteredCCHandler): :param query: tql query """ self.check('disablevirtiocache', query) return self._vm_action(query, 'vm_disable_virtio_cache') @listed Loading @@ -160,9 +153,7 @@ class CliHandler(RegisteredCCHandler): success. """ self.check('undefine', query) objects = self.server.list(query, show=('r', 'p', 'h', 'disk*',)) objects = self.client.list(query, show=('r', 'p', 'h', 'disk*',), method='undefine') errs = Reporter() for obj in objects: if obj['r'] != 'vm': Loading Loading @@ -193,8 +184,7 @@ class CliHandler(RegisteredCCHandler): :return: a standard report output """ self.check('passwd', query) objects = self.server.list(query, show=('a',)) objects = self.client.list(query, show=('a',), method='passwd') errs = Reporter() with self.conf: for obj in objects: Loading @@ -216,7 +206,7 @@ class CliHandler(RegisteredCCHandler): :param password: the password of the new account (None = not set) """ self.check('addaccount') self.client.check('addaccount') if role in Client.roles: self.conf.create_account(login, role, password) Loading @@ -232,7 +222,7 @@ class CliHandler(RegisteredCCHandler): :param password: the password of the new account (default None) """ self.check('addaccount') self.client.check('addaccount') self.conf.copy_account(copy_login, login, password) @listed Loading @@ -244,12 +234,10 @@ class CliHandler(RegisteredCCHandler): :param tag_value: the value of the tag """ self.check('addtag', query) if tag_name in self.server.RESERVED_TAGS: raise ReservedTagError('Tag %r is read-only' % tag_name) objects = self.server.list(query, show=('a',)) objects = self.client.list(query, show=('a',), method='addtag') errs = Reporter() with self.conf: for obj in objects: Loading Loading @@ -282,12 +270,10 @@ class CliHandler(RegisteredCCHandler): :param tag_name: the name of the tag to remove """ self.check('deltag', query) if tag_name in self.server.RESERVED_TAGS: raise ReservedTagError('Tag %r is read-only' % tag_name) objects = self.server.list(query, show=('a',)) objects = self.client.list(query, show=('a',), method='deltag') errs = Reporter() with self.conf: for obj in objects: Loading @@ -312,8 +298,7 @@ class CliHandler(RegisteredCCHandler): :param query: the query to select objects """ self.check('tags', query) objects = self.server.list(query, show=('a',)) objects = self.client.list(query, show=('a',), method='tags') tags = [] for obj in objects: o = {'id': obj['id']} Loading @@ -331,8 +316,7 @@ class CliHandler(RegisteredCCHandler): :param query: the query to select objects """ self.check('delaccount', query) objects = self.server.list(query, show=('a',)) objects = self.client.list(query, show=('a',), method='delaccount') errs = Reporter() with self.server.conf: for obj in objects: Loading @@ -358,8 +342,7 @@ class CliHandler(RegisteredCCHandler): :param query: the query to select objects """ self.check('close', query) objects = self.server.list(query, show=('a',)) objects = self.client.list(query, show=('a',), method='close') errs = Reporter() with self.server.conf: for obj in objects: Loading Loading @@ -388,8 +371,7 @@ class CliHandler(RegisteredCCHandler): :param query: the query to select objects """ self.check('declose', query) objects = self.server.list(query, show=('a',)) objects = self.client.list(query, show=('a',), method='declose') errs = Reporter() with self.server.conf: for obj in objects: Loading @@ -414,8 +396,7 @@ class CliHandler(RegisteredCCHandler): :param query: the query to select objects """ self.check('kill', query) objects = self.server.list(query, show=set(('a',))) objects = self.client.list(query, show=set(('a',)), method='kill') errs = Reporter() with self.server.conf: for obj in objects: Loading @@ -432,80 +413,22 @@ class CliHandler(RegisteredCCHandler): return errs.get_dict() @listed def rights(self, query): """ Get the rights of selected accounts. :param query: the query to select objects def loadrights(self): """ Get the current ruleset. """ self.check('rights', query) objects = self.server.list(query, show=set(('a',))) rules = {} for obj in objects: if 'a' in obj: rules[obj['a']] = self.server.conf.show(obj['a'])['rights'] else: raise BadObjectError('All objects must have the "a" tag.') return rules @listed def addright(self, query, tql, method=None, allow=True, index=None): """ Add a right rule to the selected accounts. :param query: the query to select objects :param tql: the TQL of the right rule :param method: the method of the right rule :param allow: target = allow if True, else False :param index: the index of the rule in list (can be negative to index from the end, if the index is out of range, the rule is added to the end. """ self.check('addright', query) objects = self.server.list(query, show=set(('a',))) errs = Reporter() with self.server.conf: for obj in objects: if 'a' not in obj: errs.error(obj['id'], 'not an account') continue try: self.server.conf.add_right(obj['a'], tql, method, allow, index) except self.server.conf.UnknownAccount: errs.error(obj['id'], 'unknown account') else: errs.success(obj['id'], 'right rule added') return errs.get_dict() self.client.check('rights') return self.server.rights.export() @listed def delright(self, query, index): """ Remove a right rule from the selected objects. def saverights(self, ruleset): """ Set the current ruleset. :param query: the query to select objects :param index: the index of the right rule to remove :param ruleset: the ruleset to load. """ self.check('delright', query) objects = self.server.list(query, show=set(('a',))) errs = Reporter() with self.server.conf: for obj in objects: if 'a' not in obj: errs.error(obj['id'], 'not an account') continue try: self.server.conf.remove_right(obj['a'], index) except self.server.conf.UnknownAccount: errs.error(obj['id'], 'unknown account') except self.server.conf.OutOfRangeIndexError: errs.error(obj['id'], 'index out of range') else: errs.success(obj['id'], 'right rule deleted') return errs.get_dict() self.client.check('rights') self.server.rights.load(ruleset) @listed def execute(self, query, command): Loading @@ -519,8 +442,7 @@ class CliHandler(RegisteredCCHandler): success. """ self.check('execute', query) objects = self.server.list(query, show=('r',)) objects = self.client.list(query, show=('r',), method='execute') errs = Reporter() for obj in objects: if obj['r'] not in ('hv', 'host'): Loading Loading @@ -548,8 +470,7 @@ class CliHandler(RegisteredCCHandler): message an error message. """ self.check('execute', query) objects = self.server.list(query, show=set(('r',))) objects = self.client.list(query, show=set(('r',)), method='execute') errs = Reporter() for obj in objects: if obj['r'] not in ('hv', 'host'): Loading Loading @@ -577,8 +498,7 @@ class CliHandler(RegisteredCCHandler): :param query: the tql query used to select jobs to cancel """ self.check('cancel', query) objects = self.server.list(query, show=('r', 'p')) objects = self.client.list(query, show=('r', 'p'), method='cancel') errs = Reporter() for obj in objects: if obj['r'] != 'job': Loading @@ -604,8 +524,7 @@ class CliHandler(RegisteredCCHandler): .. note:: Purge only work for job with state done. """ self.check('purge', query) objects = self.server.list(query, show=('r', 'p', 'state')) objects = self.client.list(query, show=('r', 'p', 'state'), method='purge') errs = Reporter() for obj in objects: if obj['r'] != 'job': Loading @@ -631,8 +550,7 @@ class CliHandler(RegisteredCCHandler): :param query: the tql query used to select jobs """ self.check('attachment', query) objects = self.server.list(query, show=('r', 'p')) objects = self.server.list(query, show=('r', 'p'), method='attachment') errs = Reporter() for obj in objects: if obj['r'] != 'job': Loading Loading @@ -664,7 +582,7 @@ class CliHandler(RegisteredCCHandler): :param mtype: type of migration :param algo: algo used for distribution """ elector = Elector(self.server, query_vm, query_dest, self.client.login) elector = Elector(self.server, query_vm, query_dest, self.client) return elector.election(mtype, algo, **kwargs) @listed Loading @@ -688,6 +606,7 @@ class CliHandler(RegisteredCCHandler): # Construct the migration properties: migration_properties = { 'client': self.client, 'server': self.server, 'vm_name': vm['h'], 'hv_source': vm['p'], Loading @@ -710,7 +629,7 @@ class CliHandler(RegisteredCCHandler): :param name: the new name of the VM """ vm = self.server.list(tql_vm, show=('r', 'h', 'p')) vm = self.clone.list(tql_vm, show=('r', 'h', 'p'), method='clone') if len(vm) != 1: raise CloneError('VM Tql must select ONE vm') Loading @@ -719,7 +638,7 @@ class CliHandler(RegisteredCCHandler): else: vm = vm[0] dest = self.server.list(tql_dest, show=('r',)) dest = self.clone.list(tql_dest, show=('r',), method='clone') if len(dest) != 1: raise CloneError('Destination Tql must select ONE hypervisor') elif dest[0]['r'] != 'hv': Loading @@ -740,8 +659,7 @@ class CliHandler(RegisteredCCHandler): :param tql: tql matching only one object on which start the console :return: the label of the created tunnel """ self.check('console', tql) objects = self.server.list(tql, show=('r', 'p', 'h')) objects = self.server.list(tql, show=('r', 'p', 'h'), method='console') if len(objects) != 1: raise NotImplementedError('Console only support one tunnel at time for now') errs = Reporter() Loading @@ -762,8 +680,7 @@ class CliHandler(RegisteredCCHandler): :param tql: tql matching only one object on which start the rshell :return: the label of the created tunnel """ self.check('rshell', tql) objects = self.server.list(tql, show=('r', 'p')) objects = self.server.list(tql, show=('r', 'p'), method='rshell') if len(objects) != 1: raise NotImplementedError('Rshell only support one tunnel at time for now') errs = Reporter() Loading @@ -787,7 +704,6 @@ class CliHandler(RegisteredCCHandler): :param xpixel: unused :param ypixel: unused """ self.check('rshell') ttype, client, ctun, stun = self.client.get_tunnel(label) if ttype != 'rshell': raise ValueError('Label does not refers on a rshell') Loading @@ -797,7 +713,6 @@ class CliHandler(RegisteredCCHandler): def rshell_wait(self, label): """ Wait for a remote shell termination. """ self.check('rshell') ttype, client, ctun, stun = self.client.get_tunnel(label) if ttype != 'rshell': raise ValueError('Label does not refers on a rshell') Loading @@ -820,7 +735,7 @@ class CliHandler(RegisteredCCHandler): :param port: port on which establish the tunnel on destination :param destination: tunnel destination (from the remote client side) """ self.check('forward', 'id=%s' % login) self.client.check('forward', query='id=%s' % login) # Create the tunnel to the node: try: host_client = self.server.get_client(login) Loading @@ -844,7 +759,7 @@ class CliHandler(RegisteredCCHandler): :param func: function to execute on the client :param \*args, \*\*kwargs: arguments of the call """ self.check('forward_call') self.client.check('forward_call') client = self.server.get_client(login) return client.conn.call(func, *args, **kwargs) Loading cloudcontrol/server/election.py +5 −18 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ class Elector(object): ('not_source_hv', 'filter source hv'), ('is_connected', 'filter connected hv'), ('vm_htype_eq_hv', 'filter bad hv types'), ('has_rights', 'filter rights'), ('has_alloc', 'filter allocatable hv'), ('duplicate_name', 'filter vm duplicate names'), ('enough_disk', 'filter hv with not enough disk'),), Loading @@ -33,7 +32,6 @@ class Elector(object): ('not_source_hv', 'filter source hv'), ('is_connected', 'filter connected hv'), ('vm_htype_eq_hv', 'filter bad hv types'), ('has_rights', 'filter rights'), ('has_alloc', 'filter allocatable hv'), ('duplicate_name', 'filter vm duplicate names'), #('enough_ram', 'filter hv with not enough ram'), Loading @@ -44,7 +42,7 @@ class Elector(object): ALGO_BY_TYPES = {'cold': ('fair', ), 'hot': ('fair', )} def __init__(self, server, query_vm, query_dest, login): def __init__(self, server, query_vm, query_dest, client): # The server instance for this election: self._server = server Loading @@ -54,8 +52,8 @@ class Elector(object): # The TQL query to select destination hypervisor: self._query_dest = query_dest # The login of the initiator of the election: self._login = login # The client who requested the election: self._client = client def election(self, mtype, algo): """ Generate a new migration plan for this election. You must specify Loading Loading @@ -108,8 +106,8 @@ class Elector(object): hv_tags |= getattr(filterfunc, '__tags__', set()) # Get the selected vms and hvs: vms = self._server.list(self._query_vm, show=('*',)) hvs = self._server.list(self._query_dest, show=hv_tags) vms = self._client.list(self._query_vm, show=('*',), method='migrate') hvs = self._client.list(self._query_dest, show=hv_tags, method='migrate') candidates = [] errors = [] Loading @@ -118,9 +116,6 @@ class Elector(object): for vm in vms: if vm['r'] != 'vm': continue tql = 'id=%s' % vm['id'] if not self._server.check(self._login, 'coldmigrate', tql): continue vm_dest = copy(hvs) for func, desc in filterfuncs: vm_dest = func(vm, vm_dest) Loading Loading @@ -202,14 +197,6 @@ class Elector(object): returned.append(hv) return returned def _filter_has_rights(self, vm, hvs): returned = [] for hv in hvs: tql = 'id=%s' % hv['id'] if self._server.check(self._login, 'coldmigrate_dest', tql): returned.append(hv) return returned @tags('alloc') def _filter_has_alloc(self, vm, hvs): returned = [] Loading cloudcontrol/server/jobs/clone.py +10 −9 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ from sjrpc.core import AsyncWatcher from cloudcontrol.common.jobs import Job, JobCancelError from cloudcontrol.server.utils import AcquiresAllOrNone from cloudcontrol.server.exceptions import RightError class CloneJob(Job): Loading @@ -19,7 +20,7 @@ class CloneJob(Job): * author: login of the author cli """ def job(self, server, hv_source, vm_name, hv_dest, new_vm_name): def job(self, server, client, hv_source, vm_name, hv_dest, new_vm_name): self._func_cancel_xfer = None # Callback to a function used to cancel # a disk transfert vm_id = '%s.%s' % (hv_source, vm_name) Loading @@ -29,15 +30,15 @@ class CloneJob(Job): # Cancel the job if the user has not the right to clone the vm or to # select an hypervisor as destination: right_check = server.check tql = 'id=%s' % vm_id if not right_check(self.state.owner, 'clone', tql): raise JobCancelError('author have no rights to migrate this VM') try: client.check('clone', 'id=%s' % vm_id) except RightError: raise JobCancelError('author have no rights to clone this VM') tql = 'id=%s' % hv_dest if not right_check(self.state.owner, 'clone_dest', tql): raise JobCancelError('author have no right to migrate to this hv') try: client.check('clone', 'id=%s' % hv_dest) except RightError: raise JobCancelError('author have no right to clone to this hv') # Update the VM object: vm = server.db.get_by_id(vm_id) Loading cloudcontrol/server/jobs/coldmigration.py +8 −7 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ from sjrpc.core import AsyncWatcher from cloudcontrol.common.jobs import Job, JobCancelError from cloudcontrol.server.utils import AcquiresAllOrNone from cloudcontrol.server.exceptions import RightError class ColdMigrationJob(Job): Loading @@ -16,7 +17,7 @@ class ColdMigrationJob(Job): * author: login of the author cli """ def job(self, server, hv_source, vm_name, hv_dest): def job(self, server, client, hv_source, vm_name, hv_dest): self._func_cancel_xfer = None # Callback to a function used to cancel # a disk transfert vm_id = '%s.%s' % (hv_source, vm_name) Loading @@ -26,14 +27,14 @@ class ColdMigrationJob(Job): # Cancel the job if the user has not the right to migrate the vm or to # select an hypervisor as destination: right_check = server.check tql = 'id=%s' % vm_id if not right_check(self.state.owner, 'coldmigrate', tql): try: client.check('migrate', 'id=%s' % vm_id) except RightError: raise JobCancelError('author have no rights to migrate this VM') tql = 'id=%s' % hv_dest if not right_check(self.state.owner, 'coldmigrate_dest', tql): try: client.check('migrate', 'id=%s' % hv_dest) except RightError: raise JobCancelError('author have no right to migrate to this hv') # Update the VM object: Loading cloudcontrol/server/jobs/hotmigration.py +8 −7 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ from sjrpc.core import AsyncWatcher from cloudcontrol.common.jobs import Job, JobCancelError from cloudcontrol.server.utils import AcquiresAllOrNone from cloudcontrol.server.exceptions import RightError class HotMigrationJob(Job): Loading @@ -18,7 +19,7 @@ class HotMigrationJob(Job): * author: login of the author cli """ def job(self, server, hv_source, vm_name, hv_dest): def job(self, server, client, hv_source, vm_name, hv_dest): vm_id = '%s.%s' % (hv_source, vm_name) self.title = 'Hot migration %s --> %s' % (vm_id, hv_dest) Loading @@ -26,14 +27,14 @@ class HotMigrationJob(Job): # Cancel the job if the user has not the right to migrate the vm or to # select an hypervisor as destination: right_check = server.check tql = 'id=%s' % vm_id if not right_check(self.state.owner, 'hotmigrate', tql): try: client.check('migrate', 'id=%s' % vm_id) except RightError: raise JobCancelError('author have no rights to migrate this VM') tql = 'id=%s' % hv_dest if not right_check(self.state.owner, 'hotmigrate_dest', tql): try: client.check('migrate', 'id=%s' % hv_dest) except RightError: raise JobCancelError('author have no right to migrate to this hv') # Update the VM object: Loading Loading
cloudcontrol/server/clients/cli.py +36 −121 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ from cloudcontrol.common.datastructures.orderedset import OrderedSet from cloudcontrol.server.conf import CCConf from cloudcontrol.server.exceptions import (ReservedTagError, BadObjectError, BadRoleError, NotConnectedAccountError, CloneError) CloneError, RightError) from cloudcontrol.server.election import Elector from cloudcontrol.server.handlers import listed, Reporter Loading Loading @@ -66,9 +66,8 @@ class CliHandler(RegisteredCCHandler): :param query: the query to select objects to show """ self.check('list', query) self.logger.debug('Executed list function with query %s', query) objects = self.server.list(query) objects = self.client.list(query, method='list') order = OrderedSet(['id']) #if tags is not None: # order |= OrderedSet(tags) Loading @@ -79,7 +78,7 @@ class CliHandler(RegisteredCCHandler): """ errs = Reporter() # Search all hypervisors of selected vms: for vm in self.server.list(query, show=('r', 'h', 'p')): for vm in self.client.list(query, show=('r', 'h', 'p'), method=method): if vm['r'] != 'vm': errs.error(vm['id'], 'not a vm') else: Loading @@ -99,35 +98,30 @@ class CliHandler(RegisteredCCHandler): def start(self, query): """ Start a virtual machine. """ self.check('start', query) return self._vm_action(query, 'vm_start') @listed def stop(self, query): """ Stop a virtual machine. """ self.check('stop', query) return self._vm_action(query, 'vm_stop') @listed def destroy(self, query): """ Destroy (hard shutdown) a virtual machine. """ self.check('destroy', query) return self._vm_action(query, 'vm_destroy') @listed def pause(self, query): """ Pause a virtual machine. """ self.check('pause', query) return self._vm_action(query, 'vm_suspend') @listed def resume(self, query): """ Resume a virtual machine. """ self.check('resume', query) return self._vm_action(query, 'vm_resume') @listed Loading @@ -136,7 +130,6 @@ class CliHandler(RegisteredCCHandler): :param query: tql query """ self.check('disablevirtiocache', query) return self._vm_action(query, 'vm_disable_virtio_cache') @listed Loading @@ -160,9 +153,7 @@ class CliHandler(RegisteredCCHandler): success. """ self.check('undefine', query) objects = self.server.list(query, show=('r', 'p', 'h', 'disk*',)) objects = self.client.list(query, show=('r', 'p', 'h', 'disk*',), method='undefine') errs = Reporter() for obj in objects: if obj['r'] != 'vm': Loading Loading @@ -193,8 +184,7 @@ class CliHandler(RegisteredCCHandler): :return: a standard report output """ self.check('passwd', query) objects = self.server.list(query, show=('a',)) objects = self.client.list(query, show=('a',), method='passwd') errs = Reporter() with self.conf: for obj in objects: Loading @@ -216,7 +206,7 @@ class CliHandler(RegisteredCCHandler): :param password: the password of the new account (None = not set) """ self.check('addaccount') self.client.check('addaccount') if role in Client.roles: self.conf.create_account(login, role, password) Loading @@ -232,7 +222,7 @@ class CliHandler(RegisteredCCHandler): :param password: the password of the new account (default None) """ self.check('addaccount') self.client.check('addaccount') self.conf.copy_account(copy_login, login, password) @listed Loading @@ -244,12 +234,10 @@ class CliHandler(RegisteredCCHandler): :param tag_value: the value of the tag """ self.check('addtag', query) if tag_name in self.server.RESERVED_TAGS: raise ReservedTagError('Tag %r is read-only' % tag_name) objects = self.server.list(query, show=('a',)) objects = self.client.list(query, show=('a',), method='addtag') errs = Reporter() with self.conf: for obj in objects: Loading Loading @@ -282,12 +270,10 @@ class CliHandler(RegisteredCCHandler): :param tag_name: the name of the tag to remove """ self.check('deltag', query) if tag_name in self.server.RESERVED_TAGS: raise ReservedTagError('Tag %r is read-only' % tag_name) objects = self.server.list(query, show=('a',)) objects = self.client.list(query, show=('a',), method='deltag') errs = Reporter() with self.conf: for obj in objects: Loading @@ -312,8 +298,7 @@ class CliHandler(RegisteredCCHandler): :param query: the query to select objects """ self.check('tags', query) objects = self.server.list(query, show=('a',)) objects = self.client.list(query, show=('a',), method='tags') tags = [] for obj in objects: o = {'id': obj['id']} Loading @@ -331,8 +316,7 @@ class CliHandler(RegisteredCCHandler): :param query: the query to select objects """ self.check('delaccount', query) objects = self.server.list(query, show=('a',)) objects = self.client.list(query, show=('a',), method='delaccount') errs = Reporter() with self.server.conf: for obj in objects: Loading @@ -358,8 +342,7 @@ class CliHandler(RegisteredCCHandler): :param query: the query to select objects """ self.check('close', query) objects = self.server.list(query, show=('a',)) objects = self.client.list(query, show=('a',), method='close') errs = Reporter() with self.server.conf: for obj in objects: Loading Loading @@ -388,8 +371,7 @@ class CliHandler(RegisteredCCHandler): :param query: the query to select objects """ self.check('declose', query) objects = self.server.list(query, show=('a',)) objects = self.client.list(query, show=('a',), method='declose') errs = Reporter() with self.server.conf: for obj in objects: Loading @@ -414,8 +396,7 @@ class CliHandler(RegisteredCCHandler): :param query: the query to select objects """ self.check('kill', query) objects = self.server.list(query, show=set(('a',))) objects = self.client.list(query, show=set(('a',)), method='kill') errs = Reporter() with self.server.conf: for obj in objects: Loading @@ -432,80 +413,22 @@ class CliHandler(RegisteredCCHandler): return errs.get_dict() @listed def rights(self, query): """ Get the rights of selected accounts. :param query: the query to select objects def loadrights(self): """ Get the current ruleset. """ self.check('rights', query) objects = self.server.list(query, show=set(('a',))) rules = {} for obj in objects: if 'a' in obj: rules[obj['a']] = self.server.conf.show(obj['a'])['rights'] else: raise BadObjectError('All objects must have the "a" tag.') return rules @listed def addright(self, query, tql, method=None, allow=True, index=None): """ Add a right rule to the selected accounts. :param query: the query to select objects :param tql: the TQL of the right rule :param method: the method of the right rule :param allow: target = allow if True, else False :param index: the index of the rule in list (can be negative to index from the end, if the index is out of range, the rule is added to the end. """ self.check('addright', query) objects = self.server.list(query, show=set(('a',))) errs = Reporter() with self.server.conf: for obj in objects: if 'a' not in obj: errs.error(obj['id'], 'not an account') continue try: self.server.conf.add_right(obj['a'], tql, method, allow, index) except self.server.conf.UnknownAccount: errs.error(obj['id'], 'unknown account') else: errs.success(obj['id'], 'right rule added') return errs.get_dict() self.client.check('rights') return self.server.rights.export() @listed def delright(self, query, index): """ Remove a right rule from the selected objects. def saverights(self, ruleset): """ Set the current ruleset. :param query: the query to select objects :param index: the index of the right rule to remove :param ruleset: the ruleset to load. """ self.check('delright', query) objects = self.server.list(query, show=set(('a',))) errs = Reporter() with self.server.conf: for obj in objects: if 'a' not in obj: errs.error(obj['id'], 'not an account') continue try: self.server.conf.remove_right(obj['a'], index) except self.server.conf.UnknownAccount: errs.error(obj['id'], 'unknown account') except self.server.conf.OutOfRangeIndexError: errs.error(obj['id'], 'index out of range') else: errs.success(obj['id'], 'right rule deleted') return errs.get_dict() self.client.check('rights') self.server.rights.load(ruleset) @listed def execute(self, query, command): Loading @@ -519,8 +442,7 @@ class CliHandler(RegisteredCCHandler): success. """ self.check('execute', query) objects = self.server.list(query, show=('r',)) objects = self.client.list(query, show=('r',), method='execute') errs = Reporter() for obj in objects: if obj['r'] not in ('hv', 'host'): Loading Loading @@ -548,8 +470,7 @@ class CliHandler(RegisteredCCHandler): message an error message. """ self.check('execute', query) objects = self.server.list(query, show=set(('r',))) objects = self.client.list(query, show=set(('r',)), method='execute') errs = Reporter() for obj in objects: if obj['r'] not in ('hv', 'host'): Loading Loading @@ -577,8 +498,7 @@ class CliHandler(RegisteredCCHandler): :param query: the tql query used to select jobs to cancel """ self.check('cancel', query) objects = self.server.list(query, show=('r', 'p')) objects = self.client.list(query, show=('r', 'p'), method='cancel') errs = Reporter() for obj in objects: if obj['r'] != 'job': Loading @@ -604,8 +524,7 @@ class CliHandler(RegisteredCCHandler): .. note:: Purge only work for job with state done. """ self.check('purge', query) objects = self.server.list(query, show=('r', 'p', 'state')) objects = self.client.list(query, show=('r', 'p', 'state'), method='purge') errs = Reporter() for obj in objects: if obj['r'] != 'job': Loading @@ -631,8 +550,7 @@ class CliHandler(RegisteredCCHandler): :param query: the tql query used to select jobs """ self.check('attachment', query) objects = self.server.list(query, show=('r', 'p')) objects = self.server.list(query, show=('r', 'p'), method='attachment') errs = Reporter() for obj in objects: if obj['r'] != 'job': Loading Loading @@ -664,7 +582,7 @@ class CliHandler(RegisteredCCHandler): :param mtype: type of migration :param algo: algo used for distribution """ elector = Elector(self.server, query_vm, query_dest, self.client.login) elector = Elector(self.server, query_vm, query_dest, self.client) return elector.election(mtype, algo, **kwargs) @listed Loading @@ -688,6 +606,7 @@ class CliHandler(RegisteredCCHandler): # Construct the migration properties: migration_properties = { 'client': self.client, 'server': self.server, 'vm_name': vm['h'], 'hv_source': vm['p'], Loading @@ -710,7 +629,7 @@ class CliHandler(RegisteredCCHandler): :param name: the new name of the VM """ vm = self.server.list(tql_vm, show=('r', 'h', 'p')) vm = self.clone.list(tql_vm, show=('r', 'h', 'p'), method='clone') if len(vm) != 1: raise CloneError('VM Tql must select ONE vm') Loading @@ -719,7 +638,7 @@ class CliHandler(RegisteredCCHandler): else: vm = vm[0] dest = self.server.list(tql_dest, show=('r',)) dest = self.clone.list(tql_dest, show=('r',), method='clone') if len(dest) != 1: raise CloneError('Destination Tql must select ONE hypervisor') elif dest[0]['r'] != 'hv': Loading @@ -740,8 +659,7 @@ class CliHandler(RegisteredCCHandler): :param tql: tql matching only one object on which start the console :return: the label of the created tunnel """ self.check('console', tql) objects = self.server.list(tql, show=('r', 'p', 'h')) objects = self.server.list(tql, show=('r', 'p', 'h'), method='console') if len(objects) != 1: raise NotImplementedError('Console only support one tunnel at time for now') errs = Reporter() Loading @@ -762,8 +680,7 @@ class CliHandler(RegisteredCCHandler): :param tql: tql matching only one object on which start the rshell :return: the label of the created tunnel """ self.check('rshell', tql) objects = self.server.list(tql, show=('r', 'p')) objects = self.server.list(tql, show=('r', 'p'), method='rshell') if len(objects) != 1: raise NotImplementedError('Rshell only support one tunnel at time for now') errs = Reporter() Loading @@ -787,7 +704,6 @@ class CliHandler(RegisteredCCHandler): :param xpixel: unused :param ypixel: unused """ self.check('rshell') ttype, client, ctun, stun = self.client.get_tunnel(label) if ttype != 'rshell': raise ValueError('Label does not refers on a rshell') Loading @@ -797,7 +713,6 @@ class CliHandler(RegisteredCCHandler): def rshell_wait(self, label): """ Wait for a remote shell termination. """ self.check('rshell') ttype, client, ctun, stun = self.client.get_tunnel(label) if ttype != 'rshell': raise ValueError('Label does not refers on a rshell') Loading @@ -820,7 +735,7 @@ class CliHandler(RegisteredCCHandler): :param port: port on which establish the tunnel on destination :param destination: tunnel destination (from the remote client side) """ self.check('forward', 'id=%s' % login) self.client.check('forward', query='id=%s' % login) # Create the tunnel to the node: try: host_client = self.server.get_client(login) Loading @@ -844,7 +759,7 @@ class CliHandler(RegisteredCCHandler): :param func: function to execute on the client :param \*args, \*\*kwargs: arguments of the call """ self.check('forward_call') self.client.check('forward_call') client = self.server.get_client(login) return client.conn.call(func, *args, **kwargs) Loading
cloudcontrol/server/election.py +5 −18 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ class Elector(object): ('not_source_hv', 'filter source hv'), ('is_connected', 'filter connected hv'), ('vm_htype_eq_hv', 'filter bad hv types'), ('has_rights', 'filter rights'), ('has_alloc', 'filter allocatable hv'), ('duplicate_name', 'filter vm duplicate names'), ('enough_disk', 'filter hv with not enough disk'),), Loading @@ -33,7 +32,6 @@ class Elector(object): ('not_source_hv', 'filter source hv'), ('is_connected', 'filter connected hv'), ('vm_htype_eq_hv', 'filter bad hv types'), ('has_rights', 'filter rights'), ('has_alloc', 'filter allocatable hv'), ('duplicate_name', 'filter vm duplicate names'), #('enough_ram', 'filter hv with not enough ram'), Loading @@ -44,7 +42,7 @@ class Elector(object): ALGO_BY_TYPES = {'cold': ('fair', ), 'hot': ('fair', )} def __init__(self, server, query_vm, query_dest, login): def __init__(self, server, query_vm, query_dest, client): # The server instance for this election: self._server = server Loading @@ -54,8 +52,8 @@ class Elector(object): # The TQL query to select destination hypervisor: self._query_dest = query_dest # The login of the initiator of the election: self._login = login # The client who requested the election: self._client = client def election(self, mtype, algo): """ Generate a new migration plan for this election. You must specify Loading Loading @@ -108,8 +106,8 @@ class Elector(object): hv_tags |= getattr(filterfunc, '__tags__', set()) # Get the selected vms and hvs: vms = self._server.list(self._query_vm, show=('*',)) hvs = self._server.list(self._query_dest, show=hv_tags) vms = self._client.list(self._query_vm, show=('*',), method='migrate') hvs = self._client.list(self._query_dest, show=hv_tags, method='migrate') candidates = [] errors = [] Loading @@ -118,9 +116,6 @@ class Elector(object): for vm in vms: if vm['r'] != 'vm': continue tql = 'id=%s' % vm['id'] if not self._server.check(self._login, 'coldmigrate', tql): continue vm_dest = copy(hvs) for func, desc in filterfuncs: vm_dest = func(vm, vm_dest) Loading Loading @@ -202,14 +197,6 @@ class Elector(object): returned.append(hv) return returned def _filter_has_rights(self, vm, hvs): returned = [] for hv in hvs: tql = 'id=%s' % hv['id'] if self._server.check(self._login, 'coldmigrate_dest', tql): returned.append(hv) return returned @tags('alloc') def _filter_has_alloc(self, vm, hvs): returned = [] Loading
cloudcontrol/server/jobs/clone.py +10 −9 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ from sjrpc.core import AsyncWatcher from cloudcontrol.common.jobs import Job, JobCancelError from cloudcontrol.server.utils import AcquiresAllOrNone from cloudcontrol.server.exceptions import RightError class CloneJob(Job): Loading @@ -19,7 +20,7 @@ class CloneJob(Job): * author: login of the author cli """ def job(self, server, hv_source, vm_name, hv_dest, new_vm_name): def job(self, server, client, hv_source, vm_name, hv_dest, new_vm_name): self._func_cancel_xfer = None # Callback to a function used to cancel # a disk transfert vm_id = '%s.%s' % (hv_source, vm_name) Loading @@ -29,15 +30,15 @@ class CloneJob(Job): # Cancel the job if the user has not the right to clone the vm or to # select an hypervisor as destination: right_check = server.check tql = 'id=%s' % vm_id if not right_check(self.state.owner, 'clone', tql): raise JobCancelError('author have no rights to migrate this VM') try: client.check('clone', 'id=%s' % vm_id) except RightError: raise JobCancelError('author have no rights to clone this VM') tql = 'id=%s' % hv_dest if not right_check(self.state.owner, 'clone_dest', tql): raise JobCancelError('author have no right to migrate to this hv') try: client.check('clone', 'id=%s' % hv_dest) except RightError: raise JobCancelError('author have no right to clone to this hv') # Update the VM object: vm = server.db.get_by_id(vm_id) Loading
cloudcontrol/server/jobs/coldmigration.py +8 −7 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ from sjrpc.core import AsyncWatcher from cloudcontrol.common.jobs import Job, JobCancelError from cloudcontrol.server.utils import AcquiresAllOrNone from cloudcontrol.server.exceptions import RightError class ColdMigrationJob(Job): Loading @@ -16,7 +17,7 @@ class ColdMigrationJob(Job): * author: login of the author cli """ def job(self, server, hv_source, vm_name, hv_dest): def job(self, server, client, hv_source, vm_name, hv_dest): self._func_cancel_xfer = None # Callback to a function used to cancel # a disk transfert vm_id = '%s.%s' % (hv_source, vm_name) Loading @@ -26,14 +27,14 @@ class ColdMigrationJob(Job): # Cancel the job if the user has not the right to migrate the vm or to # select an hypervisor as destination: right_check = server.check tql = 'id=%s' % vm_id if not right_check(self.state.owner, 'coldmigrate', tql): try: client.check('migrate', 'id=%s' % vm_id) except RightError: raise JobCancelError('author have no rights to migrate this VM') tql = 'id=%s' % hv_dest if not right_check(self.state.owner, 'coldmigrate_dest', tql): try: client.check('migrate', 'id=%s' % hv_dest) except RightError: raise JobCancelError('author have no right to migrate to this hv') # Update the VM object: Loading
cloudcontrol/server/jobs/hotmigration.py +8 −7 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ from sjrpc.core import AsyncWatcher from cloudcontrol.common.jobs import Job, JobCancelError from cloudcontrol.server.utils import AcquiresAllOrNone from cloudcontrol.server.exceptions import RightError class HotMigrationJob(Job): Loading @@ -18,7 +19,7 @@ class HotMigrationJob(Job): * author: login of the author cli """ def job(self, server, hv_source, vm_name, hv_dest): def job(self, server, client, hv_source, vm_name, hv_dest): vm_id = '%s.%s' % (hv_source, vm_name) self.title = 'Hot migration %s --> %s' % (vm_id, hv_dest) Loading @@ -26,14 +27,14 @@ class HotMigrationJob(Job): # Cancel the job if the user has not the right to migrate the vm or to # select an hypervisor as destination: right_check = server.check tql = 'id=%s' % vm_id if not right_check(self.state.owner, 'hotmigrate', tql): try: client.check('migrate', 'id=%s' % vm_id) except RightError: raise JobCancelError('author have no rights to migrate this VM') tql = 'id=%s' % hv_dest if not right_check(self.state.owner, 'hotmigrate_dest', tql): try: client.check('migrate', 'id=%s' % hv_dest) except RightError: raise JobCancelError('author have no right to migrate to this hv') # Update the VM object: Loading