[Kimchi-devel] [PATCH 2/3] Live migration backend: control/vms and model/vms changes
Daniel Henrique Barboza
dhbarboza82 at gmail.com
Tue Oct 27 17:23:39 UTC 2015
On 10/27/2015 03:11 PM, Paulo Ricardo Paz Vital wrote:
> On Tue, 2015-10-27 at 11:37 -0200, Daniel Henrique Barboza wrote:
>> On 10/27/2015 08:38 AM, Paulo Ricardo Paz Vital wrote:
>>> On Mon, 2015-10-26 at 16:08 -0200, dhbarboza82 at gmail.com wrote:
>>>> From: Daniel Henrique Barboza <dhbarboza82 at gmail.com>
>>>>
>>>> This patch adds the backend code to support live (and cold)
>>>> migration
>>>> in Kimchi.
>>>>
>>>> Signed-off-by: Daniel Henrique Barboza <dhbarboza82 at gmail.com>
>>>> ---
>>>> src/wok/plugins/kimchi/control/vms.py | 3 ++
>>>> src/wok/plugins/kimchi/model/vms.py | 68
>>>> ++++++++++++++++++++++++++++++++++-
>>>> 2 files changed, 70 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/src/wok/plugins/kimchi/control/vms.py
>>>> b/src/wok/plugins/kimchi/control/vms.py
>>>> index 58d4b67..5e24538 100644
>>>> --- a/src/wok/plugins/kimchi/control/vms.py
>>>> +++ b/src/wok/plugins/kimchi/control/vms.py
>>>> @@ -49,6 +49,9 @@ class VM(Resource):
>>>>
>>>> destructive=True)
>>>> self.connect = self.generate_action_handler('connect')
>>>> self.clone = self.generate_action_handler_task('clone')
>>>> + self.migrate =
>>>> self.generate_action_handler_task('migrate',
>>>> +
>>>> ['remote_host',
>>>> +
>>>> 'user'])
>>>> self.suspend = self.generate_action_handler('suspend')
>>>> self.resume = self.generate_action_handler('resume')
>>>>
>>>> diff --git a/src/wok/plugins/kimchi/model/vms.py
>>>> b/src/wok/plugins/kimchi/model/vms.py
>>>> index 60145d0..5d242e8 100644
>>>> --- a/src/wok/plugins/kimchi/model/vms.py
>>>> +++ b/src/wok/plugins/kimchi/model/vms.py
>>>> @@ -36,7 +36,7 @@ from wok.exception import NotFoundError,
>>>> OperationFailed
>>>> from wok.model.tasks import TaskModel
>>>> from wok.rollbackcontext import RollbackContext
>>>> from wok.utils import add_task, convert_data_size,
>>>> get_next_clone_name
>>>> -from wok.utils import import_class, run_setfacl_set_attr,
>>>> wok_log
>>>> +from wok.utils import import_class, run_setfacl_set_attr,
>>>> run_command, wok_log
>>>> from wok.xmlutils.utils import xpath_get_text, xml_item_update
>>>> from wok.xmlutils.utils import dictize
>>>>
>>>> @@ -1294,6 +1294,72 @@ class VMModel(object):
>>>> raise OperationFailed('KCHVM0040E', {'name': name,
>>>> 'err':
>>>> e.message})
>>>>
>>>> + def _check_if_host_not_localhost(self, remote_host):
>>>> + if remote_host in ['localhost', '127.0.0.1']:
>>>> + raise OperationFailed("KCHVM0055E", {'host':
>>>> remote_host})
>>> Only a curiosity: Is it OK accept the hostname or IP address of my
>>> 'localhost', or only these two cases are not a good case to
>>> migrate?
>> Libvirt will freak out if you try to do a 'migrateinception' :P
>>
>> This is why I've made this verification - to ensure that the user
>> doesn't pass the
>> IP/hostname of the same host Kimchi is running on by accident.
>>
>>
> So, if I'm running Kimchi in a machine called 'bla.br.ibm.com' and use
> this hostname to realize a migration, libvirt will freakout, right?!?!
>
> I suggest to check not only the name 'localhost' and IP '127.0.0.1',
> but also the IP address and real hostname of the machine.
hahahaha you're right
I'll fix it in v2
>
>>>
>>>
>>>> +
>>>> + def _check_if_password_less_login_enabled(self, remote_host,
>>>> user):
>>>> + username_host = "%s@%s" % (user, remote_host)
>>>> + ssh_cmd = ['ssh', '-oNumberOfPasswordPrompts=0',
>>>> + '-oStrictHostKeyChecking=no', username_host,
>>>> + 'echo', 'hello']
>>>> + stdout, stderr, returncode = run_command(ssh_cmd, 5,
>>>> silent=True)
>>>> + if returncode != 0:
>>>> + raise OperationFailed("KCHVM0056E",
>>>> + {'host': remote_host, 'user':
>>>> user})
>>>> +
>>>> + def _get_remote_libvirt_conn(self, remote_host,
>>>> + user='root', transport='ssh'):
>>>> + dest_uri = 'qemu+%s://%s@%s/system' % (transport, user,
>>>> remote_host)
>>>> + # TODO: verify why LibvirtConnection(dest_uri) does not
>>>> work
>>>> here
>>>> + return libvirt.open(dest_uri)
>>>> +
>>>> + def migration_pre_check(self, remote_host, user):
>>>> + self._check_if_host_not_localhost(remote_host)
>>>> + self._check_if_password_less_login_enabled(remote_host,
>>>> user)
>>>> +
>>>> + def migrate(self, name, remote_host, user='root'):
>>>> + name = name.decode('utf-8')
>>>> + remote_host = remote_host.decode('utf-8')
>>>> +
>>>> + self.migration_pre_check(remote_host, user)
>>>> + dest_conn = self._get_remote_libvirt_conn(remote_host)
>>>> +
>>>> + params = {'name': name,
>>>> + 'dest_conn': dest_conn}
>>>> + task_id = add_task('/vms/%s/migrate' % name,
>>>> self._migrate_task,
>>>> + self.objstore, params)
>>>> +
>>>> + return self.task.lookup(task_id)
>>>> +
>>>> + def _migrate_task(self, cb, params):
>>>> + name = params['name'].decode('utf-8')
>>>> + dest_conn = params['dest_conn']
>>>> +
>>>> + cb('starting a migration')
>>>> +
>>>> + dom = self.get_vm(name, self.conn)
>>>> + state = DOM_STATE_MAP[dom.info()[0]]
>>>> +
>>>> + flags = libvirt.VIR_MIGRATE_PEER2PEER
>>>> + if state == 'shutoff':
>>>> + flags |= (libvirt.VIR_MIGRATE_OFFLINE |
>>>> + libvirt.VIR_MIGRATE_PERSIST_DEST)
>>>> + elif state in ['running', 'paused']:
>>>> + flags |= libvirt.VIR_MIGRATE_LIVE |
>>>> libvirt.VIR_MIGRATE_TUNNELLED
>>>> + if dom.isPersistent():
>>>> + flags |= libvirt.VIR_MIGRATE_PERSIST_DEST
>>>> + else:
>>>> + raise OperationFailed("KCHVM0057E", {'name': name,
>>>> + 'state':
>>>> state})
>>>> + try:
>>>> + dom.migrate(dest_conn, flags)
>>>> + except libvirt.libvirtError as e:
>>>> + cb('Migrate failed', False)
>>>> + raise OperationFailed('KCHVM0058E', {'err':
>>>> e.message,
>>>> + 'name': name})
>>>> + cb('Migrate finished', True)
>>>> +
>>>>
>>>> class VMScreenshotModel(object):
>>>> def __init__(self, **kargs):
More information about the Kimchi-devel
mailing list