Skip to content

Commit 43ab44d

Browse files
committed
Merge release branch 4.7 to 4.8
* 4.7: CLOUDSTACK-9142 Migrate VM changes xmlDesc in a safe way
2 parents c2fc0c4 + c03e359 commit 43ab44d

File tree

3 files changed

+349
-13
lines changed

3 files changed

+349
-13
lines changed

plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@
4848
@ResourceWrapper(handles = MigrateCommand.class)
4949
public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCommand, Answer, LibvirtComputingResource> {
5050

51+
private static final String GRAPHICS_ELEM_END = "/graphics>";
52+
private static final String GRAPHICS_ELEM_START = "<graphics";
53+
private static final String CONTENTS_WILDCARD = "(?s).*";
5154
private static final Logger s_logger = Logger.getLogger(LibvirtMigrateCommandWrapper.class);
5255

5356
@Override
@@ -90,9 +93,11 @@ VIR_DOMAIN_XML_MIGRATABLE flag (value = 8)
9093
9194
Use VIR_DOMAIN_XML_SECURE (value = 1) prior to v1.0.0.
9295
*/
93-
int xmlFlag = conn.getLibVirVersion() >= 1000000 ? 8 : 1; // 1000000 equals v1.0.0
96+
final int xmlFlag = conn.getLibVirVersion() >= 1000000 ? 8 : 1; // 1000000 equals v1.0.0
9497

95-
xmlDesc = dm.getXMLDesc(xmlFlag).replace(libvirtComputingResource.getPrivateIp(), command.getDestinationIp());
98+
final String target = command.getDestinationIp();
99+
xmlDesc = dm.getXMLDesc(xmlFlag);
100+
xmlDesc = replaceIpForVNCInDescFile(xmlDesc, target);
96101

97102
dconn = libvirtUtilitiesHelper.retrieveQemuConnection("qemu+tcp://" + command.getDestinationIp() + "/system");
98103

@@ -190,4 +195,27 @@ Use VIR_DOMAIN_XML_SECURE (value = 1) prior to v1.0.0.
190195

191196
return new MigrateAnswer(command, result == null, result, null);
192197
}
193-
}
198+
199+
/**
200+
* This function assumes an qemu machine description containing a single graphics element like
201+
* <graphics type='vnc' port='5900' autoport='yes' listen='10.10.10.1'>
202+
* <listen type='address' address='10.10.10.1'/>
203+
* </graphics>
204+
* @param xmlDesc the qemu xml description
205+
* @param target the ip address to migrate to
206+
* @return the new xmlDesc
207+
*/
208+
String replaceIpForVNCInDescFile(String xmlDesc, final String target) {
209+
final int begin = xmlDesc.indexOf(GRAPHICS_ELEM_START);
210+
if (begin >= 0) {
211+
final int end = xmlDesc.lastIndexOf(GRAPHICS_ELEM_END) + GRAPHICS_ELEM_END.length();
212+
if (end > begin) {
213+
String graphElem = xmlDesc.substring(begin, end);
214+
graphElem = graphElem.replaceAll("listen='[a-zA-Z0-9\\.]*'", "listen='" + target + "'");
215+
graphElem = graphElem.replaceAll("address='[a-zA-Z0-9\\.]*'", "address='" + target + "'");
216+
xmlDesc = xmlDesc.replaceAll(GRAPHICS_ELEM_START + CONTENTS_WILDCARD + GRAPHICS_ELEM_END, graphElem);
217+
}
218+
}
219+
return xmlDesc;
220+
}
221+
}

plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -391,9 +391,9 @@ public void testGetNicStats() {
391391

392392
@Test
393393
public void diskUuidToSerialTest() {
394-
String uuid = "38400000-8cf0-11bd-b24e-10b96e4ef00d";
395-
String expected = "384000008cf011bdb24e";
396-
LibvirtComputingResource lcr = new LibvirtComputingResource();
394+
final String uuid = "38400000-8cf0-11bd-b24e-10b96e4ef00d";
395+
final String expected = "384000008cf011bdb24e";
396+
final LibvirtComputingResource lcr = new LibvirtComputingResource();
397397
Assert.assertEquals(expected, lcr.diskUuidToSerial(uuid));
398398
}
399399

@@ -711,7 +711,7 @@ public void testGetVmDiskStatsCommand() {
711711
@SuppressWarnings("unchecked")
712712
@Test
713713
public void testGetVmDiskStatsCommandException() {
714-
final Connect conn = Mockito.mock(Connect.class);
714+
Mockito.mock(Connect.class);
715715
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = Mockito.mock(LibvirtUtilitiesHelper.class);
716716

717717
final String vmName = "Test";
@@ -931,7 +931,7 @@ public void testRebootRouterCommandConnect() {
931931
public void testGetHostStatsCommand() {
932932
// A bit difficult to test due to the logger being passed and the parser itself relying on the connection.
933933
// Have to spend some more time afterwards in order to refactor the wrapper itself.
934-
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = Mockito.mock(LibvirtUtilitiesHelper.class);
934+
Mockito.mock(LibvirtUtilitiesHelper.class);
935935
final CPUStat cpuStat = Mockito.mock(CPUStat.class);
936936
final MemStat memStat = Mockito.mock(MemStat.class);
937937

@@ -1253,8 +1253,10 @@ public void testMigrateCommand() {
12531253
when(conn.domainLookupByName(vmName)).thenReturn(dm);
12541254

12551255
when(libvirtComputingResource.getPrivateIp()).thenReturn("127.0.0.1");
1256-
when(dm.getXMLDesc(8)).thenReturn("host_domain");
1257-
when(dm.getXMLDesc(1)).thenReturn("host_domain");
1256+
when(dm.getXMLDesc(8)).thenReturn("<domain type='kvm' id='3'>" + " <devices>" + " <graphics type='vnc' port='5900' autoport='yes' listen='10.10.10.1'>"
1257+
+ " <listen type='address' address='10.10.10.1'/>" + " </graphics>" + " </devices>" + "</domain>");
1258+
when(dm.getXMLDesc(1)).thenReturn("<domain type='kvm' id='3'>" + " <devices>" + " <graphics type='vnc' port='5900' autoport='yes' listen='10.10.10.1'>"
1259+
+ " <listen type='address' address='10.10.10.1'/>" + " </graphics>" + " </devices>" + "</domain>");
12581260
when(dm.isPersistent()).thenReturn(1);
12591261
doNothing().when(dm).undefine();
12601262

@@ -5010,13 +5012,13 @@ public void testUpdateHostPasswordCommandFail() {
50105012

50115013
@Test
50125014
public void testIsInterface () {
5013-
LibvirtComputingResource lvcr = new LibvirtComputingResource();
5015+
final LibvirtComputingResource lvcr = new LibvirtComputingResource();
50145016
assertFalse(lvcr.isInterface("bla"));
50155017
assertTrue(lvcr.isInterface("p99p00"));
5016-
for (String ifNamePattern : lvcr._ifNamePatterns) {
5018+
for (final String ifNamePattern : lvcr._ifNamePatterns) {
50175019
// excluding regexps as "\\\\d+" won't replace with String.replaceAll(String,String);
50185020
if (!ifNamePattern.contains("\\")) {
5019-
String ifName = ifNamePattern.replaceFirst("\\^", "") + "0";
5021+
final String ifName = ifNamePattern.replaceFirst("\\^", "") + "0";
50205022
assertTrue("The pattern '" + ifNamePattern + "' is expected to be valid for interface " + ifName,lvcr.isInterface(ifName));
50215023
}
50225024
}

0 commit comments

Comments
 (0)