diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java index c1328aa99ae..6736c512dd6 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java @@ -48,6 +48,9 @@ import com.cloud.resource.ResourceWrapper; @ResourceWrapper(handles = MigrateCommand.class) public final class LibvirtMigrateCommandWrapper extends CommandWrapper { + private static final String GRAPHICS_ELEM_END = "/graphics>"; + private static final String GRAPHICS_ELEM_START = "= 1000000 ? 8 : 1; // 1000000 equals v1.0.0 + final int xmlFlag = conn.getLibVirVersion() >= 1000000 ? 8 : 1; // 1000000 equals v1.0.0 - xmlDesc = dm.getXMLDesc(xmlFlag).replace(libvirtComputingResource.getPrivateIp(), command.getDestinationIp()); + final String target = command.getDestinationIp(); + xmlDesc = dm.getXMLDesc(xmlFlag); + xmlDesc = replaceIpForVNCInDescFile(xmlDesc, target); dconn = libvirtUtilitiesHelper.retrieveQemuConnection("qemu+tcp://" + command.getDestinationIp() + "/system"); @@ -190,4 +195,27 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper + * + * + * @param xmlDesc the qemu xml description + * @param target the ip address to migrate to + * @return the new xmlDesc + */ + String replaceIpForVNCInDescFile(String xmlDesc, final String target) { + final int begin = xmlDesc.indexOf(GRAPHICS_ELEM_START); + if (begin >= 0) { + final int end = xmlDesc.lastIndexOf(GRAPHICS_ELEM_END) + GRAPHICS_ELEM_END.length(); + if (end > begin) { + String graphElem = xmlDesc.substring(begin, end); + graphElem = graphElem.replaceAll("listen='[a-zA-Z0-9\\.]*'", "listen='" + target + "'"); + graphElem = graphElem.replaceAll("address='[a-zA-Z0-9\\.]*'", "address='" + target + "'"); + xmlDesc = xmlDesc.replaceAll(GRAPHICS_ELEM_START + CONTENTS_WILDCARD + GRAPHICS_ELEM_END, graphElem); + } + } + return xmlDesc; + } +} diff --git a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java index 04a27f3d8c7..a10b477e411 100644 --- a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java +++ b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java @@ -391,9 +391,9 @@ public class LibvirtComputingResourceTest { @Test public void diskUuidToSerialTest() { - String uuid = "38400000-8cf0-11bd-b24e-10b96e4ef00d"; - String expected = "384000008cf011bdb24e"; - LibvirtComputingResource lcr = new LibvirtComputingResource(); + final String uuid = "38400000-8cf0-11bd-b24e-10b96e4ef00d"; + final String expected = "384000008cf011bdb24e"; + final LibvirtComputingResource lcr = new LibvirtComputingResource(); Assert.assertEquals(expected, lcr.diskUuidToSerial(uuid)); } @@ -711,7 +711,7 @@ public class LibvirtComputingResourceTest { @SuppressWarnings("unchecked") @Test public void testGetVmDiskStatsCommandException() { - final Connect conn = Mockito.mock(Connect.class); + Mockito.mock(Connect.class); final LibvirtUtilitiesHelper libvirtUtilitiesHelper = Mockito.mock(LibvirtUtilitiesHelper.class); final String vmName = "Test"; @@ -931,7 +931,7 @@ public class LibvirtComputingResourceTest { public void testGetHostStatsCommand() { // A bit difficult to test due to the logger being passed and the parser itself relying on the connection. // Have to spend some more time afterwards in order to refactor the wrapper itself. - final LibvirtUtilitiesHelper libvirtUtilitiesHelper = Mockito.mock(LibvirtUtilitiesHelper.class); + Mockito.mock(LibvirtUtilitiesHelper.class); final CPUStat cpuStat = Mockito.mock(CPUStat.class); final MemStat memStat = Mockito.mock(MemStat.class); @@ -1253,8 +1253,10 @@ public class LibvirtComputingResourceTest { when(conn.domainLookupByName(vmName)).thenReturn(dm); when(libvirtComputingResource.getPrivateIp()).thenReturn("127.0.0.1"); - when(dm.getXMLDesc(8)).thenReturn("host_domain"); - when(dm.getXMLDesc(1)).thenReturn("host_domain"); + when(dm.getXMLDesc(8)).thenReturn("" + " " + " " + + " " + " " + " " + ""); + when(dm.getXMLDesc(1)).thenReturn("" + " " + " " + + " " + " " + " " + ""); when(dm.isPersistent()).thenReturn(1); doNothing().when(dm).undefine(); @@ -5010,13 +5012,13 @@ public class LibvirtComputingResourceTest { @Test public void testIsInterface () { - LibvirtComputingResource lvcr = new LibvirtComputingResource(); + final LibvirtComputingResource lvcr = new LibvirtComputingResource(); assertFalse(lvcr.isInterface("bla")); assertTrue(lvcr.isInterface("p99p00")); - for (String ifNamePattern : lvcr._ifNamePatterns) { + for (final String ifNamePattern : lvcr._ifNamePatterns) { // excluding regexps as "\\\\d+" won't replace with String.replaceAll(String,String); if (!ifNamePattern.contains("\\")) { - String ifName = ifNamePattern.replaceFirst("\\^", "") + "0"; + final String ifName = ifNamePattern.replaceFirst("\\^", "") + "0"; assertTrue("The pattern '" + ifNamePattern + "' is expected to be valid for interface " + ifName,lvcr.isInterface(ifName)); } } diff --git a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapperTest.java b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapperTest.java new file mode 100644 index 00000000000..ed13cb25f0c --- /dev/null +++ b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapperTest.java @@ -0,0 +1,306 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// +package com.cloud.hypervisor.kvm.resource.wrapper; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class LibvirtMigrateCommandWrapperTest { + String fullfile = +"\n" + +" i-6-6-VM\n" + +" f197b32b-8da2-4a57-bb8a-d01bacc5cd33\n" + +" Other PV (64-bit)\n" + +" 262144\n" + +" 262144\n" + +" 1\n" + +" \n" + +" 100\n" + +" \n" + +" \n" + +" /machine\n" + +" \n" + +" \n" + +" \n" + +" Apache Software Foundation\n" + +" CloudStack KVM Hypervisor\n" + +" f197b32b-8da2-4a57-bb8a-d01bacc5cd33\n" + +" \n" + +" \n" + +" \n" + +" hvm\n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" destroy\n" + +" restart\n" + +" destroy\n" + +" \n" + +" /usr/libexec/qemu-kvm\n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" 4650a2f7fce548e2beaa\n" + +" \n" + +"
\n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +"
\n" + +" \n" + +" \n" + +" \n" + +"
\n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +"
\n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +"
\n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +"