Skip to content
Merged
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
28 changes: 20 additions & 8 deletions server/src/main/java/com/cloud/server/StatsCollector.java
Original file line number Diff line number Diff line change
Expand Up @@ -1442,11 +1442,15 @@ protected void runInContext() {
logger.debug(String.format("VmStatsCollector is running to process VMs across %d UP hosts", hosts.size()));

List<UserVmJoinVO> listL2netVMs = userVmJoinDao.listGuestTypeVMs(Network.GuestType.L2);
ArrayList<String> listL2NicMacAddr = new ArrayList<String>();
Map<Long, List<String>> l2NicMacsByVmId = new HashMap<>();

for (UserVmJoinVO vm : listL2netVMs) {
if(!listL2NicMacAddr.contains(vm.getMacAddress())){
listL2NicMacAddr.add(vm.getMacAddress());
if (StringUtils.isBlank(vm.getMacAddress())) {
continue;
}
List<String> l2NicMacs = l2NicMacsByVmId.computeIfAbsent(vm.getId(), k -> new ArrayList<>());
if (!l2NicMacs.contains(vm.getMacAddress())) {
l2NicMacs.add(vm.getMacAddress());
}
}

Expand All @@ -1472,10 +1476,18 @@ protected void runInContext() {

Map<String, String> agentNicMap = statsForCurrentIteration.getNicAddrMap();
if (agentNicMap != null) {
for (String key : agentNicMap.keySet()) {
NicVO nicVO = _nicDao.findByMacAddress(key);
if (listL2NicMacAddr.contains(key)) {
nicVO.setIPv4Address(agentNicMap.get(key));
List<String> l2NicMacs = l2NicMacsByVmId.get(vmId);
if (CollectionUtils.isNotEmpty(l2NicMacs)) {
for (String macAddress : l2NicMacs) {
NicVO nicVO = _nicDao.findByMacAddress(macAddress);
if (nicVO == null) {
continue;
}
String guestIpAddress = agentNicMap.get(macAddress);
if (StringUtils.equals(nicVO.getIPv4Address(), guestIpAddress)) {
continue;
}
nicVO.setIPv4Address(guestIpAddress);
_nicDao.update(nicVO.getId(), nicVO);
}
}
Expand Down Expand Up @@ -2474,4 +2486,4 @@ public ConfigKey<?>[] getConfigKeys() {
public double getImageStoreCapacityThreshold() {
return CapacityManager.SecondaryStorageCapacityThreshold.value();
}
}
}
4 changes: 4 additions & 0 deletions server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -9757,6 +9757,10 @@ public UserVm updateVmNicLinkState(UpdateVmNicLinkStateCmd cmd){
throw new CloudRuntimeException(ex.getMessage());
}
}
if (!cmd.getLinkState() && network.getGuestType() == Network.GuestType.L2 && nic.getIPv4Address() != null) {
nic.setIPv4Address(null);
_nicDao.update(nicId, nic);
}
return _vmDao.findById(vmInstance.getId());
}

Expand Down
2 changes: 2 additions & 0 deletions ui/public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,7 @@
"label.compute": "Compute",
"label.compute.offerings": "Compute offerings",
"label.compute.offering.for.sharedfs.instance": "Compute offering for Instance",
"label.compute.resources": "Allocated resources",
"label.computeonly.offering": "Compute only disk offering",
"label.computeonly.offering.tooltip": "Option to specify root disk related information in the compute offering or to directly link a disk offering to the compute offering",
"label.conditions": "Conditions",
Expand Down Expand Up @@ -3423,6 +3424,7 @@
"message.kubernetes.cluster.start": "Please confirm that you want to start the cluster.",
"message.kubernetes.cluster.stop": "Please confirm that you want to stop the cluster.",
"message.kubernetes.cluster.upgrade": "Please select new Kubernetes version.",
"message.kubernetes.management.rule.delete.disabled": "Management rules created by Kubernetes cannot be deleted.",
"message.kubernetes.version.delete": "Please confirm that you want to delete this Kubernetes version.",
"message.l2.network.unsupported.for.nsx": "L2 networks aren't supported for NSX enabled zones",
"message.launch.zone": "Zone is ready to launch; please proceed to the next step.",
Expand Down
2 changes: 2 additions & 0 deletions ui/public/locales/ko_KR.json
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,7 @@
"label.compute": "\ucef4\ud4e8\ud2b8",
"label.compute.offerings": "\ucef4\ud4e8\ud2b8 \uc624\ud37c\ub9c1",
"label.compute.offering.for.sharedfs.instance": "\uac00\uc0c1\uba38\uc2e0\uc6a9 \ucef4\ud4e8\ud2b8 \uc624\ud37c\ub9c1",
"label.compute.resources": "\ud560\ub2f9 \uc790\uc6d0",
"label.computeonly.offering": "\ucef4\ud4e8\ud305 \uc804\uc6a9 \ub514\uc2a4\ud06c \uc81c\uacf5",
"label.computeonly.offering.tooltip": "\ucef4\ud4e8\ud305 \uc624\ud37c\ub9c1\uc5d0\uc11c \ub8e8\ud2b8 \ub514\uc2a4\ud06c \uad00\ub828 \uc815\ubcf4\ub97c \uc9c0\uc815\ud558\uac70\ub098 \ub514\uc2a4\ud06c \uc624\ud37c\ub9c1\uc744 \ucef4\ud4e8\ud305 \uc624\ud37c\ub9c1\uc5d0 \uc9c1\uc811 \uc5f0\uacb0\ud558\ub294 \uc635\uc158",
"label.conditions": "\uc870\uac74",
Expand Down Expand Up @@ -3423,6 +3424,7 @@
"message.kubernetes.cluster.start": "\ud074\ub7ec\uc2a4\ud130\ub97c \uc2dc\uc791\ud560 \uac83\uc778\uc9c0 \ud655\uc778\ud558\uc2ed\uc2dc\uc624.",
"message.kubernetes.cluster.stop": "\ud074\ub7ec\uc2a4\ud130\ub97c \uc911\uc9c0 \ud560 \uac83\uc778\uc9c0 \ud655\uc778\ud558\uc2ed\uc2dc\uc624.",
"message.kubernetes.cluster.upgrade": "\uc0c8 \ucfe0\ubc84\ub124\ud2f0\uc2a4 \ubc84\uc804\uc744 \uc120\ud0dd\ud558\uc2ed\uc2dc\uc624.",
"message.kubernetes.management.rule.delete.disabled": "Kubernetes\uc5d0\uc11c \uc0dd\uc131\ud55c \uad00\ub9ac \uaddc\uce59\uc740 \uc0ad\uc81c\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.",
"message.kubernetes.version.delete": "\uc774 \ucfe0\ubc84\ub124\ud2f0\uc2a4 \ubc84\uc804\uc744 \uc0ad\uc81c\ud560 \uac83\uc778\uc9c0 \ud655\uc778\ud558\uc2ed\uc2dc\uc624.",
"message.l2.network.unsupported.for.nsx": "L2 \ub124\ud2b8\uc6cc\ud06c\ub294 NSX \uc9c0\uc6d0 \uc601\uc5ed\uc5d0\uc11c \uc9c0\uc6d0\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.",
"message.launch.zone": "Zone\uc744 \uc2dc\uc791\ud560 \uc900\ube44\uac00 \ub418\uc5c8\uc2b5\ub2c8\ub2e4. \ub2e4\uc74c \uc21c\uc11c\uc5d0 \ub530\ub77c \uc9c4\ud589\ud574 \uc8fc\uc2ed\uc2dc\uc624.",
Expand Down
48 changes: 48 additions & 0 deletions ui/src/components/view/ListView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,24 @@
<a-tag v-if="text === 'Not Installed'" color="error">{{ this.$t('label.state.qemuagentversion.notinstalled') }}</a-tag>
<a-tag v-else-if="text" color="success">{{ text }}</a-tag>
</template>
<template v-if="column.key === 'resources'">
<div v-if="hasValue(record.cpunumber) || hasValue(record.memory)" class="resource-summary">
<span v-if="hasValue(record.cpunumber)" class="resource-item resource-item--cpu">
<a-tooltip>
<template #title>{{ $t('label.cpu') }}</template>
<font-awesome-icon :icon="['fa-solid', 'fa-microchip']" class="resource-icon" />
</a-tooltip>
{{ record.cpunumber }} CPU
</span>
<span v-if="hasValue(record.memory)" class="resource-item resource-item--memory">
<a-tooltip>
<template #title>{{ $t('label.memory') }}</template>
<font-awesome-icon :icon="['fa-solid', 'fa-memory']" class="resource-icon" />
</a-tooltip>
{{ record.memory }} MB
</span>
</div>
</template>
<template v-if="column.key === 'mirroringagentstatus'">
<status :text="text ? text : ''" displayText />
</template>
Expand Down Expand Up @@ -1324,6 +1342,9 @@ export default {
var duration = Date.parse(enddate) - Date.parse(startdate)
return (duration > 0 ? duration / 1000.0 : 0) + ''
},
hasValue (value) {
return value !== undefined && value !== null && value !== ''
},
getUsageTypes () {
if (this.$route.path.split('/')[1] === 'usage') {
api('listUsageTypes').then(json => {
Expand Down Expand Up @@ -1456,6 +1477,33 @@ export default {
padding: 10%;
}

.resource-summary {
display: inline-flex;
align-items: center;
gap: 10px;
line-height: 20px;
white-space: nowrap;
color: inherit;

.resource-item {
display: inline-flex;
align-items: center;
gap: 4px;
}

.resource-icon {
font-size: 13px;
}

.resource-item--cpu .resource-icon {
color: #5b6b84;
}

.resource-item--memory .resource-icon {
color: #68758a;
}
}

.quickview-context-menu {
position: fixed;
z-index: 2000;
Expand Down
4 changes: 2 additions & 2 deletions ui/src/config/section/compute.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export default {
return filters
},
columns: () => {
const fields = [{ field: 'displayname', customTitle: 'vm.displayname' }, 'state', 'qemuagentversion', 'ipaddress', 'templatetype']
const fields = [{ field: 'displayname', customTitle: 'vm.displayname' }, 'state', { field: 'resources', customTitle: 'compute.resources' }, 'qemuagentversion', 'ipaddress', 'templatetype']
const metricsFields = ['cpunumber', 'cputotal', 'cpuused', 'memorytotal',
{
memoryused: (record) => {
Expand All @@ -72,7 +72,7 @@ export default {
fields.push(...metricsFields)
}
if (store.getters.userInfo.roletype === 'Admin') {
fields.splice(3, 0, 'instancename')
fields.splice(1, 0, 'instancename')
fields.push('hostname')
fields.push('account')
} else if (store.getters.userInfo.roletype === 'DomainAdmin') {
Expand Down
11 changes: 10 additions & 1 deletion ui/src/views/AutogenView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -1310,11 +1310,20 @@ export default {
customRender[key] = columnKey[key]
}
}
const sorter = key === 'resources'
? (a, b) => {
const cpuCompare = Number(a.cpunumber || 0) - Number(b.cpunumber || 0)
if (cpuCompare !== 0) {
return cpuCompare
}
return Number(a.memory || 0) - Number(b.memory || 0)
}
: (a, b) => genericCompare(a[key] || '', b[key] || '')
this.columns.push({
key: key,
title: this.$t('label.' + String(title).toLowerCase()),
dataIndex: key,
sorter: (a, b) => genericCompare(a[key] || '', b[key] || '')
sorter: sorter
})
this.selectedColumns.push(key)
}
Expand Down
11 changes: 5 additions & 6 deletions ui/src/views/compute/DeployVnfAppliance.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2297,13 +2297,14 @@ export default {
successMethod: result => {
const vm = result.jobresult.virtualmachine
const name = vm.displayname || vm.name || vm.id
const passwordEnabled = this.template?.passwordenabled === true
const username = vm.vnfdetails?.username || null
const password = vm.vnfdetails?.password || null
const effectivePassword = vm.password || password
const password = passwordEnabled ? vm.vnfdetails?.password || null : null
const effectivePassword = passwordEnabled ? (vm.password || password) : null
const sshUsername = vm.vnfdetails?.ssh_user || null
const sshPassword = vm.vnfdetails?.ssh_password || null
const sshPassword = passwordEnabled ? vm.vnfdetails?.ssh_password || null : null
const webUsername = vm.vnfdetails?.web_user || null
const webPassword = vm.vnfdetails?.web_password || null
const webPassword = passwordEnabled ? vm.vnfdetails?.web_password || null : null
const credentials = []
if (username) {
credentials.push(this.$t('label.username') + ' : ' + username)
Expand All @@ -2325,8 +2326,6 @@ export default {
}
if (credentials.length > 0) {
credentials.push(this.$t('message.vnf.credentials.change'))
} else {
credentials.push(this.$t('message.vnf.no.credentials'))
}
this.$notification.success({
message: `${this.$t('message.vnf.credentials.default')} ` + name,
Expand Down
18 changes: 16 additions & 2 deletions ui/src/views/compute/KubernetesServiceTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,16 @@
</a-table>
</a-tab-pane>
<a-tab-pane :tab="$t('label.firewall')" key="firewall" v-if="publicIpAddress">
<FirewallRules :resource="publicIpAddress" :loading="networkLoading" />
<FirewallRules
:resource="publicIpAddress"
:loading="networkLoading"
:protected-management-ports="kubernetesManagementPorts" />
</a-tab-pane>
<a-tab-pane :tab="$t('label.portforwarding')" key="portforwarding" v-if="publicIpAddress">
<PortForwarding :resource="publicIpAddress" :loading="networkLoading" />
<PortForwarding
:resource="publicIpAddress"
:loading="networkLoading"
:protected-management-ports="kubernetesManagementPorts" />
</a-tab-pane>
<a-tab-pane :tab="$t('label.loadbalancing')" key="loadbalancing" v-if="publicIpAddress">
<LoadBalancing :resource="publicIpAddress" :loading="networkLoading" />
Expand Down Expand Up @@ -283,6 +289,14 @@ export default {
this.setCurrentTab()
}
},
computed: {
kubernetesManagementPorts () {
const sshPorts = this.virtualmachines
.map((vm, index) => Number(vm.port || vm.sshport || vm.sshPort || this.cksSshStartingPort + index))
.filter(port => Number.isInteger(port))
return [...new Set([6443, ...sshPorts])]
}
},
mounted () {
if (this.$store.getters.apis.scaleKubernetesCluster?.params?.filter(x => x.name === 'nodeids').length > 0 && this.resource.clustertype === 'CloudManaged') {
this.vmColumns.push({
Expand Down
54 changes: 45 additions & 9 deletions ui/src/views/compute/ScaleVM.vue
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ export default {
this.total = 0
this.offerings = []
this.offeringsMap = []
this.fixedOfferingKvm = false
api('listServiceOfferings', {
virtualmachineid: this.resource.id,
keyword: options.keyword,
Expand All @@ -149,22 +150,57 @@ export default {
response: 'json'
}).then(response => {
this.total = response.listserviceofferingsresponse.count
if (this.total === 0) {
return
}
this.offerings = response.listserviceofferingsresponse.serviceoffering || []
if (this.resource.state === 'Running' && this.resource.hypervisor === 'KVM') {
this.offerings = this.offerings.filter(offering => offering.id === this.resource.serviceofferingid)
this.currentOffer = this.offerings[0]
if (this.currentOffer === undefined) {
this.fixedOfferingKvm = true
}
return this.applyRunningKvmOfferingFilter()
}
this.offerings.map(i => { this.offeringsMap[i.id] = i })
if (this.total === 0) {
return
}
this.setOfferingsMap()
}).finally(() => {
this.loading = false
})
},
applyRunningKvmOfferingFilter () {
const currentOffer = this.offerings.find(offering => offering.id === this.resource.serviceofferingid)
if (currentOffer) {
this.offerings = [currentOffer]
this.total = this.offerings.length
this.setOfferingsMap()
return Promise.resolve()
}

return this.fetchCurrentServiceOffering().then(offering => {
if (offering?.iscustomized) {
this.offerings = [offering]
this.total = this.offerings.length
} else {
this.offerings = []
this.total = 0
this.fixedOfferingKvm = true
}
this.setOfferingsMap()
}).catch(error => {
this.offerings = []
this.total = 0
this.fixedOfferingKvm = true
this.$notifyError(error)
})
},
fetchCurrentServiceOffering () {
return api('listServiceOfferings', {
id: this.resource.serviceofferingid,
details: 'min',
response: 'json'
}).then(response => {
return response.listserviceofferingsresponse.serviceoffering?.[0]
})
},
setOfferingsMap () {
this.offeringsMap = []
this.offerings.map(i => { this.offeringsMap[i.id] = i })
},
getMinCpu () {
// We can only scale up while a VM is running
if (this.resource.state === 'Running') {
Expand Down
4 changes: 4 additions & 0 deletions ui/src/views/compute/wizard/ComputeOfferingSelection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,10 @@ export default {
selectInitialRow () {
const selectedId = this.value || this.preFillContent?.computeofferingid
const selectedRow = this.tableSource.find(row => row.key === selectedId && !row.disabled)
if (selectedId && !selectedRow) {
this.selectedRowKeys = [selectedId]
return
}
const fallbackRow = this.tableSource.find(row => !row.disabled)
const row = selectedRow || fallbackRow
if (!row) {
Expand Down
Loading
Loading