Skip to content

Commit 3e908f8

Browse files
authored
Merge branch '4.20' into honor-datadiskcontroller-attachvol
2 parents 5dec11f + 42f1e19 commit 3e908f8

File tree

10 files changed

+79
-28
lines changed

10 files changed

+79
-28
lines changed

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

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ Use VIR_DOMAIN_XML_SECURE (value = 1) prior to v1.0.0.
158158
final String target = command.getDestinationIp();
159159
xmlDesc = dm.getXMLDesc(xmlFlag);
160160
if (logger.isDebugEnabled()) {
161-
logger.debug(String.format("VM [%s] with XML configuration [%s] will be migrated to host [%s].", vmName, xmlDesc, target));
161+
logger.debug("VM {} with XML configuration {} will be migrated to host {}.", vmName, maskSensitiveInfoInXML(xmlDesc), target);
162162
}
163163

164164
// Limit the VNC password in case the length is greater than 8 characters
@@ -173,7 +173,7 @@ Use VIR_DOMAIN_XML_SECURE (value = 1) prior to v1.0.0.
173173
logger.debug(String.format("Editing mount path of ISO from %s to %s", oldIsoVolumePath, newIsoVolumePath));
174174
xmlDesc = replaceDiskSourceFile(xmlDesc, newIsoVolumePath, vmName);
175175
if (logger.isDebugEnabled()) {
176-
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));
176+
logger.debug("Replaced disk mount point {} with {} in Instance {} XML configuration. New XML configuration is {}.", oldIsoVolumePath, newIsoVolumePath, vmName, maskSensitiveInfoInXML(xmlDesc));
177177
}
178178
}
179179

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

205205
if (migrateStorage) {
206206
if (logger.isDebugEnabled()) {
207-
logger.debug(String.format("Changing VM [%s] volumes during migration to host: [%s].", vmName, target));
207+
logger.debug("Changing VM {} volumes during migration to host: {}.", vmName, target);
208208
}
209209
xmlDesc = replaceStorage(xmlDesc, mapMigrateStorage, migrateStorageManaged);
210210
if (logger.isDebugEnabled()) {
211-
logger.debug(String.format("Changed VM [%s] XML configuration of used storage. New XML configuration is [%s].", vmName, xmlDesc));
211+
logger.debug("Changed VM {} XML configuration of used storage. New XML configuration is {}.", vmName, maskSensitiveInfoInXML(xmlDesc));
212212
}
213213
migrateDiskLabels = getMigrateStorageDeviceLabels(disks, mapMigrateStorage);
214214
}
215215

216216
Map<String, DpdkTO> dpdkPortsMapping = command.getDpdkInterfaceMapping();
217217
if (MapUtils.isNotEmpty(dpdkPortsMapping)) {
218218
if (logger.isTraceEnabled()) {
219-
logger.trace(String.format("Changing VM [%s] DPDK interfaces during migration to host: [%s].", vmName, target));
219+
logger.trace("Changing VM {} DPDK interfaces during migration to host: {}.", vmName, target);
220220
}
221221
xmlDesc = replaceDpdkInterfaces(xmlDesc, dpdkPortsMapping);
222222
if (logger.isDebugEnabled()) {
223-
logger.debug(String.format("Changed VM [%s] XML configuration of DPDK interfaces. New XML configuration is [%s].", vmName, xmlDesc));
223+
logger.debug("Changed VM {} XML configuration of DPDK interfaces. New XML configuration is {}.", vmName, maskSensitiveInfoInXML(xmlDesc));
224224
}
225225
}
226226

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

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

@@ -575,9 +575,7 @@ String replaceIpForVNCInDescFileAndNormalizePassword(String xmlDesc, final Strin
575575
graphElem = graphElem.replaceAll("passwd='([^\\s]+)'", "passwd='" + vncPassword + "'");
576576
}
577577
xmlDesc = xmlDesc.replaceAll(GRAPHICS_ELEM_START + CONTENTS_WILDCARD + GRAPHICS_ELEM_END, graphElem);
578-
if (logger.isDebugEnabled()) {
579-
logger.debug(String.format("Replaced the VNC IP address [%s] with [%s] in VM [%s].", originalGraphElem, graphElem, vmName));
580-
}
578+
logger.debug("Replaced the VNC IP address {} with {} in VM {}.", maskSensitiveInfoInXML(originalGraphElem), maskSensitiveInfoInXML(graphElem), vmName);
581579
}
582580
}
583581
return xmlDesc;
@@ -910,4 +908,10 @@ private boolean findSourceNode(Document doc, Node diskNode, String vmName, Strin
910908
}
911909
return false;
912910
}
911+
912+
public static String maskSensitiveInfoInXML(String xmlDesc) {
913+
if (xmlDesc == null) return null;
914+
return xmlDesc.replaceAll("(graphics\\s+[^>]*type=['\"]vnc['\"][^>]*passwd=['\"])([^'\"]*)(['\"])",
915+
"$1*****$3");
916+
}
913917
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,9 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource
8080
}
8181

8282
libvirtComputingResource.createVifs(vmSpec, vm);
83-
84-
logger.debug("starting " + vmName + ": " + vm.toString());
83+
if (logger.isDebugEnabled()) {
84+
logger.debug("Starting {} : {}", vmName, LibvirtMigrateCommandWrapper.maskSensitiveInfoInXML(vm.toString()));
85+
}
8586
String vmInitialSpecification = vm.toString();
8687
String vmFinalSpecification = performXmlTransformHook(vmInitialSpecification, libvirtComputingResource);
8788
libvirtComputingResource.startVM(conn, vmName, vmFinalSpecification);

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

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ private Map<String, MigrateDiskInfo> createMapMigrateStorage(String sourceText,
589589
@Test
590590
public void testReplaceIpForVNCInDescFile() {
591591
final String targetIp = "192.168.22.21";
592-
final String result = libvirtMigrateCmdWrapper.replaceIpForVNCInDescFileAndNormalizePassword(fullfile, targetIp, null, "");
592+
final String result = libvirtMigrateCmdWrapper.replaceIpForVNCInDescFileAndNormalizePassword(fullfile, targetIp, "vncSecretPwd", "");
593593
assertEquals("transformation does not live up to expectation:\n" + result, targetfile, result);
594594
}
595595

@@ -1019,4 +1019,28 @@ public void replaceCdromIsoPathTest() throws ParserConfigurationException, IOExc
10191019

10201020
Assert.assertTrue(finalXml.contains(newIsoVolumePath));
10211021
}
1022+
1023+
@Test
1024+
public void testMaskVncPwdDomain() {
1025+
// Test case 1: Single quotes
1026+
String xml1 = "<graphics type='vnc' port='5900' passwd='secret123'/>";
1027+
String expected1 = "<graphics type='vnc' port='5900' passwd='*****'/>";
1028+
assertEquals(expected1, LibvirtMigrateCommandWrapper.maskSensitiveInfoInXML(xml1));
1029+
1030+
// Test case 2: Double quotes
1031+
String xml2 = "<graphics type=\"vnc\" port=\"5901\" passwd=\"mypassword\"/>";
1032+
String expected2 = "<graphics type=\"vnc\" port=\"5901\" passwd=\"*****\"/>";
1033+
assertEquals(expected2, LibvirtMigrateCommandWrapper.maskSensitiveInfoInXML(xml2));
1034+
1035+
// Test case 3: Non-VNC graphics (should remain unchanged)
1036+
String xml3 = "<graphics type='spice' port='5902' passwd='notvnc'/>";
1037+
assertEquals(xml3, LibvirtMigrateCommandWrapper.maskSensitiveInfoInXML(xml3));
1038+
1039+
// Test case 4: Multiple VNC entries in one string
1040+
String xml4 = "<graphics type='vnc' port='5900' passwd='a'/>\n" +
1041+
"<graphics type='vnc' port='5901' passwd='b'/>";
1042+
String expected4 = "<graphics type='vnc' port='5900' passwd='*****'/>\n" +
1043+
"<graphics type='vnc' port='5901' passwd='*****'/>";
1044+
assertEquals(expected4, LibvirtMigrateCommandWrapper.maskSensitiveInfoInXML(xml4));
1045+
}
10221046
}

ui/src/views/auth/ForgotPassword.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ export default {
162162
api('forgotPassword', {}, 'POST', loginParams)
163163
.finally(() => {
164164
this.$message.success(this.$t('message.forgot.password.success'))
165-
this.$router.push({ path: '/login' }).catch(() => {})
165+
this.$router.replace({ path: '/user/login' })
166166
})
167167
}).catch(error => {
168168
this.formRef.value.scrollToField(error.errorFields[0].name)

ui/src/views/compute/DeployVM.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2339,7 +2339,9 @@ export default {
23392339
this.owner.domainid = null
23402340
this.owner.projectid = OwnerOptions.selectedProject
23412341
}
2342-
this.resetData()
2342+
if (OwnerOptions.initialized) {
2343+
this.resetData()
2344+
}
23432345
},
23442346
fetchZones (zoneId, listZoneAllow) {
23452347
this.zones = []

ui/src/views/compute/wizard/OwnershipSelection.vue

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<a-form layout="vertical" >
2020
<a-form-item :label="$t('label.owner.type')">
2121
<a-select
22-
@change="changeDomain"
22+
@change="changeAccountTypeOrDomain"
2323
v-model:value="selectedAccountType"
2424
defaultValue="account"
2525
autoFocus
@@ -37,7 +37,7 @@
3737
</a-form-item>
3838
<a-form-item :label="$t('label.domain')" required>
3939
<a-select
40-
@change="changeDomain"
40+
@change="changeAccountTypeOrDomain"
4141
v-model:value="selectedDomain"
4242
showSearch
4343
optionFilterProp="label"
@@ -136,14 +136,16 @@ export default {
136136
components: { ResourceIcon },
137137
data () {
138138
return {
139+
initialized: false,
139140
domains: [],
140141
accounts: [],
141142
projects: [],
142143
selectedAccountType: this.$store.getters.project?.id ? 'Project' : 'Account',
143144
selectedDomain: null,
144145
selectedAccount: null,
145146
selectedProject: null,
146-
loading: false
147+
loading: false,
148+
requestToken: 0
147149
}
148150
},
149151
props: {
@@ -177,7 +179,7 @@ export default {
177179
const domainIds = this.domains?.map(domain => domain.id)
178180
const ownerDomainId = this.$store.getters.project?.domainid || this.$store.getters.userInfo.domainid
179181
this.selectedDomain = domainIds?.includes(ownerDomainId) ? ownerDomainId : this.domains?.[0]?.id
180-
this.changeDomain()
182+
this.fetchOwnerData()
181183
})
182184
.catch((error) => {
183185
this.$notifyError(error)
@@ -186,8 +188,13 @@ export default {
186188
this.loading = false
187189
})
188190
},
191+
incrementAndGetRequestToken () {
192+
this.requestToken += 1
193+
return this.requestToken
194+
},
189195
fetchAccounts () {
190196
this.loading = true
197+
const currentToken = this.incrementAndGetRequestToken()
191198
api('listAccounts', {
192199
response: 'json',
193200
domainId: this.selectedDomain,
@@ -196,6 +203,9 @@ export default {
196203
isrecursive: false
197204
})
198205
.then((response) => {
206+
if (currentToken !== this.requestToken) {
207+
return
208+
}
199209
this.accounts = response.listaccountsresponse.account || []
200210
if (this.override?.accounts && this.accounts) {
201211
this.accounts = this.accounts.filter(item => this.override.accounts.has(item.name))
@@ -214,10 +224,12 @@ export default {
214224
})
215225
.finally(() => {
216226
this.loading = false
227+
this.initialized = true
217228
})
218229
},
219230
fetchProjects () {
220231
this.loading = true
232+
const currentToken = this.incrementAndGetRequestToken()
221233
api('listProjects', {
222234
response: 'json',
223235
domainId: this.selectedDomain,
@@ -227,6 +239,9 @@ export default {
227239
isrecursive: false
228240
})
229241
.then((response) => {
242+
if (currentToken !== this.requestToken) {
243+
return
244+
}
230245
this.projects = response.listprojectsresponse.project
231246
if (this.override?.projects && this.projects) {
232247
this.projects = this.projects.filter(item => this.override.projects.has(item.id))
@@ -240,9 +255,14 @@ export default {
240255
})
241256
.finally(() => {
242257
this.loading = false
258+
this.initialized = true
243259
})
244260
},
245-
changeDomain () {
261+
changeAccountTypeOrDomain () {
262+
this.initialized = true
263+
this.fetchOwnerData()
264+
},
265+
fetchOwnerData () {
246266
if (this.selectedAccountType === 'Account') {
247267
this.fetchAccounts()
248268
} else {

ui/src/views/network/CreateIsolatedNetworkForm.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ export default {
507507
this.owner.domainid = null
508508
this.owner.projectid = OwnerOptions.selectedProject
509509
}
510-
if (isAdminOrDomainAdmin()) {
510+
if (OwnerOptions.initialized && isAdminOrDomainAdmin()) {
511511
this.updateVPCCheckAndFetchNetworkOfferingData()
512512
}
513513
},

ui/src/views/network/CreateL2NetworkForm.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ export default {
309309
this.owner.domainid = null
310310
this.owner.projectid = OwnerOptions.selectedProject
311311
}
312-
if (isAdminOrDomainAdmin()) {
312+
if (OwnerOptions.initialized && this.isAdminOrDomainAdmin()) {
313313
this.updateVPCCheckAndFetchNetworkOfferingData()
314314
}
315315
},

ui/src/views/storage/CreateSharedFS.vue

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -272,23 +272,21 @@ export default {
272272
},
273273
fetchOwnerOptions (OwnerOptions) {
274274
this.owner = {}
275-
console.log('fetching owner')
276275
if (OwnerOptions.selectedAccountType === 'Account') {
277276
if (!OwnerOptions.selectedAccount) {
278277
return
279278
}
280-
console.log('fetched account')
281279
this.owner.account = OwnerOptions.selectedAccount
282280
this.owner.domainid = OwnerOptions.selectedDomain
283281
} else if (OwnerOptions.selectedAccountType === 'Project') {
284282
if (!OwnerOptions.selectedProject) {
285283
return
286284
}
287-
console.log('fetched project')
288285
this.owner.projectid = OwnerOptions.selectedProject
289286
}
290-
console.log('fetched owner')
291-
this.fetchData()
287+
if (OwnerOptions.initialized) {
288+
this.fetchData()
289+
}
292290
},
293291
fetchData () {
294292
this.minCpu = store.getters.features.sharedfsvmmincpucount

ui/src/views/storage/CreateVolume.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,9 @@ export default {
272272
}
273273
this.owner.projectid = OwnerOptions.selectedProject
274274
}
275-
this.fetchData()
275+
if (OwnerOptions.initialized) {
276+
this.fetchData()
277+
}
276278
},
277279
fetchData () {
278280
if (this.createVolumeFromSnapshot) {

0 commit comments

Comments
 (0)