Commit 8455cf70 authored by Anael Beutot's avatar Anael Beutot
Browse files

hypervisor.kvm: fix domain XML update while running

When we update a VM configuration while it is running, for example a change in
the network interfaces, we recreate a domain from the running XML which is fine
but this is not valid anymore when the VM is stopped.
So in the latter case, we keep an attribute on the VM indicating if we need to
recreate the VM instance from the XML when it stops.
parent 80f2bcb4
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -96,6 +96,8 @@ class VirtualMachine(object):
        self.from_stream = None  # buffer
        self.stream_handling = 0  # libvirt stream event mask

        self.redefine_on_stop = False  # for XML update (see KVM class)

    @property
    def state(self):
        return self._state
+29 −7
Original line number Diff line number Diff line
@@ -120,19 +120,22 @@ class KVM(object):
                return
            # update Storage pools in case VM has volumes that were created
            self.storage.update()
            # if vm is redefined while running we need to refresh its devices
            # when stopped
            redefine_on_stop = False
            if dom.name() in self.domains:
                # sometimes libvirt send us the same event multiple times
                # this can be the result of a change in the domain configuration
                # we first remove the old domain
                vm = self.domains.pop(dom.name())
                self.handler.tag_db.remove_sub_object(vm.name)
                if vm.state not in ('stopped', 'crashed'):
                    # if the vm was updated while it was "on", then the
                    # modifications will not be reflected since we construct the
                    # object/tags from running XML
                    redefine_on_stop = True
                logger.debug('Domain %s recreated', dom.name())
            vm = VirtualMachine(dom, self)
            logger.info('Created domain %s', vm.name)
            self.domains[vm.name] = vm
            self.handler.tag_db.add_sub_object(vm.name, vm.tags.itervalues(),
                                               'vm')
            self.update_domain_count()
            self.vm_register(dom, redefine_on_stop)
        elif event == 'Removed':
            vm_name = dom.name()
            self.vm_unregister(vm_name)
@@ -155,9 +158,28 @@ class KVM(object):
                else:
                    logger.info('Domain change state from %s to %s', vm.state,
                                 state)
                    if event == 'Stopped' and vm.redefine_on_stop:
                        # if the vm was changed while it was running, then we
                        # need to recreate it now as stated above
                        self.vm_unregister(vm.name)
                        self.vm_register(dom)
                    else:
                        vm.state = state
                    self.update_domain_count()

    def vm_register(self, dom, redefine_on_stop=False):
        """Register a VM to the hypervisor object.

        :param dom: libvirt domain instance
        :param redefine_on_stop: if we need to reread the domain XML on stop
        """
        vm = VirtualMachine(dom, self)
        logger.info('Created domain %s', vm.name)
        vm.redefine_on_stop = redefine_on_stop
        self.domains[vm.name] = vm
        self.handler.tag_db.add_sub_object(vm.name, vm.tags.itervalues(), 'vm')
        self.update_domain_count()

    def vm_unregister(self, name):
        """Unregister a VM from the cc-server and remove it from the index."""
        try: