Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ Use VIR_DOMAIN_XML_SECURE (value = 1) prior to v1.0.0.
final String target = command.getDestinationIp();
xmlDesc = dm.getXMLDesc(xmlFlag);
if (logger.isDebugEnabled()) {
logger.debug(String.format("VM [%s] with XML configuration [%s] will be migrated to host [%s].", vmName, xmlDesc, target));
logger.debug("VM {} with XML configuration {} will be migrated to host {}.", vmName, maskSensitiveInfoInXML(xmlDesc), target);
}
Comment on lines 160 to 162
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (logger.isDebugEnabled()) {
logger.debug(String.format("VM [%s] with XML configuration [%s] will be migrated to host [%s].", vmName, xmlDesc, target));
logger.debug("VM {} with XML configuration {} will be migrated to host {}.", vmName, maskSensitiveInfoInXML(xmlDesc), target);
}
logger.debug("VM {} with XML configuration {} will be migrated to host {}.", vmName, () -> maskSensitiveInfoInXML(xmlDesc), target);

just a suggestion, (may apply below as well)


// Limit the VNC password in case the length is greater than 8 characters
Expand All @@ -173,7 +173,7 @@ Use VIR_DOMAIN_XML_SECURE (value = 1) prior to v1.0.0.
logger.debug(String.format("Editing mount path of ISO from %s to %s", oldIsoVolumePath, newIsoVolumePath));
xmlDesc = replaceDiskSourceFile(xmlDesc, newIsoVolumePath, vmName);
if (logger.isDebugEnabled()) {
logger.debug(String.format("Replaced disk mount point [%s] with [%s] in Instance [%s] XML configuration. New XML configuration is [%s].", oldIsoVolumePath, newIsoVolumePath, vmName, xmlDesc));
logger.debug("Replaced disk mount point {} with {} in Instance {} XML configuration. New XML configuration is {}.", oldIsoVolumePath, newIsoVolumePath, vmName, maskSensitiveInfoInXML(xmlDesc));
}
}

Expand Down Expand Up @@ -204,23 +204,23 @@ Use VIR_DOMAIN_XML_SECURE (value = 1) prior to v1.0.0.

if (migrateStorage) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Changing VM [%s] volumes during migration to host: [%s].", vmName, target));
logger.debug("Changing VM {} volumes during migration to host: {}.", vmName, target);
}
xmlDesc = replaceStorage(xmlDesc, mapMigrateStorage, migrateStorageManaged);
if (logger.isDebugEnabled()) {
logger.debug(String.format("Changed VM [%s] XML configuration of used storage. New XML configuration is [%s].", vmName, xmlDesc));
logger.debug("Changed VM {} XML configuration of used storage. New XML configuration is {}.", vmName, maskSensitiveInfoInXML(xmlDesc));
}
migrateDiskLabels = getMigrateStorageDeviceLabels(disks, mapMigrateStorage);
}

Map<String, DpdkTO> dpdkPortsMapping = command.getDpdkInterfaceMapping();
if (MapUtils.isNotEmpty(dpdkPortsMapping)) {
if (logger.isTraceEnabled()) {
logger.trace(String.format("Changing VM [%s] DPDK interfaces during migration to host: [%s].", vmName, target));
logger.trace("Changing VM {} DPDK interfaces during migration to host: {}.", vmName, target);
}
xmlDesc = replaceDpdkInterfaces(xmlDesc, dpdkPortsMapping);
if (logger.isDebugEnabled()) {
logger.debug(String.format("Changed VM [%s] XML configuration of DPDK interfaces. New XML configuration is [%s].", vmName, xmlDesc));
logger.debug("Changed VM {} XML configuration of DPDK interfaces. New XML configuration is {}.", vmName, maskSensitiveInfoInXML(xmlDesc));
}
}

Expand All @@ -233,7 +233,7 @@ Use VIR_DOMAIN_XML_SECURE (value = 1) prior to v1.0.0.
}

//run migration in thread so we can monitor it
logger.info(String.format("Starting live migration of instance [%s] to destination host [%s] having the final XML configuration: [%s].", vmName, dconn.getURI(), xmlDesc));
logger.info("Starting live migration of instance {} to destination host {} having the final XML configuration: {}.", vmName, dconn.getURI(), maskSensitiveInfoInXML(xmlDesc));
final ExecutorService executor = Executors.newFixedThreadPool(1);
boolean migrateNonSharedInc = command.isMigrateNonSharedInc() && !migrateStorageManaged;

Expand Down Expand Up @@ -910,4 +910,11 @@ private boolean findSourceNode(Document doc, Node diskNode, String vmName, Strin
}
return false;
}

public static String maskSensitiveInfoInXML(String xmlDesc) {
if (xmlDesc == null) return null;
// Mask VNC password in XML for logging
return xmlDesc.replaceAll("(graphics\\s+[^>]*type=['\"]vnc['\"][^>]*passwd=['\"])([^'\"]*)(['\"])",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can also just remove it, btw

Copy link
Collaborator Author

@sudo87 sudo87 Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wont it confuse admin whether vnc section is not part of the xml or not?

"$1*****$3");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,9 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource
}

libvirtComputingResource.createVifs(vmSpec, vm);

logger.debug("starting " + vmName + ": " + vm.toString());
if (logger.isDebugEnabled()) {
logger.debug("Starting {} : {}", vmName, LibvirtMigrateCommandWrapper.maskSensitiveInfoInXML(vm.toString()));
}
String vmInitialSpecification = vm.toString();
String vmFinalSpecification = performXmlTransformHook(vmInitialSpecification, libvirtComputingResource);
libvirtComputingResource.startVM(conn, vmName, vmFinalSpecification);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ private Map<String, MigrateDiskInfo> createMapMigrateStorage(String sourceText,
@Test
public void testReplaceIpForVNCInDescFile() {
final String targetIp = "192.168.22.21";
final String result = libvirtMigrateCmdWrapper.replaceIpForVNCInDescFileAndNormalizePassword(fullfile, targetIp, null, "");
final String result = libvirtMigrateCmdWrapper.replaceIpForVNCInDescFileAndNormalizePassword(fullfile, targetIp, "vncSecretPwd", "");
assertEquals("transformation does not live up to expectation:\n" + result, targetfile, result);
}

Expand Down Expand Up @@ -1019,4 +1019,28 @@ public void replaceCdromIsoPathTest() throws ParserConfigurationException, IOExc

Assert.assertTrue(finalXml.contains(newIsoVolumePath));
}

@Test
public void testMaskVncPwdDomain() {
// Test case 1: Single quotes
String xml1 = "<graphics type='vnc' port='5900' passwd='secret123'/>";
String expected1 = "<graphics type='vnc' port='5900' passwd='*****'/>";
assertEquals(expected1, LibvirtMigrateCommandWrapper.maskSensitiveInfoInXML(xml1));

// Test case 2: Double quotes
String xml2 = "<graphics type=\"vnc\" port=\"5901\" passwd=\"mypassword\"/>";
String expected2 = "<graphics type=\"vnc\" port=\"5901\" passwd=\"*****\"/>";
assertEquals(expected2, LibvirtMigrateCommandWrapper.maskSensitiveInfoInXML(xml2));

// Test case 3: Non-VNC graphics (should remain unchanged)
String xml3 = "<graphics type='spice' port='5902' passwd='notvnc'/>";
assertEquals(xml3, LibvirtMigrateCommandWrapper.maskSensitiveInfoInXML(xml3));

// Test case 4: Multiple VNC entries in one string
String xml4 = "<graphics type='vnc' port='5900' passwd='a'/>\n" +
"<graphics type='vnc' port='5901' passwd='b'/>";
String expected4 = "<graphics type='vnc' port='5900' passwd='*****'/>\n" +
"<graphics type='vnc' port='5901' passwd='*****'/>";
assertEquals(expected4, LibvirtMigrateCommandWrapper.maskSensitiveInfoInXML(xml4));
}
}