Skip to content
Open
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
142 changes: 118 additions & 24 deletions ui/src/views/compute/wizard/ComputeSelection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -57,23 +57,40 @@
</a-col>
<a-col :md="colContraned" :lg="colContraned" v-if="isCustomized">
<a-form-item
:label="$t('label.memory.mb')"
:label="$t('label.memory')"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@saurabhkushwaha438 An out-of-range GiB value is rejected with "Invalid memory value, specify a value between 32 and 2147483647" and the message does not say the unit (MiB or GiB).
For example: 0.01 GiB is sent as 10 MiB and hits this error.

Image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

i think you can raise separate issue for that

:validate-status="errors.memory.status"
:help="errors.memory.message">
<a-row :gutter="12">
<a-col :md="10" :lg="10" v-show="isConstrained && maxMemory && !isNaN(maxMemory)">
<a-col :md="14" :lg="14" v-show="isConstrained && maxMemory && !isNaN(maxMemory)">
<a-slider
:min="minMemory"
:max="maxMemory"
v-model:value="memoryInputValue"
:min="minMemoryInUnit"
:max="maxMemoryInUnit"
:step="memoryStep"
v-model:value="memoryDisplayValue"
@change="($event) => updateComputeMemory($event)"
/>
</a-col>
<a-col :md="4" :lg="4">
<a-input-number
v-model:value="memoryInputValue"
@change="($event) => updateComputeMemory($event)"
/>
<a-col :md="isConstrained && maxMemory && !isNaN(maxMemory) ? 10 : 24" :lg="isConstrained && maxMemory && !isNaN(maxMemory) ? 10 : 24">
<a-input-group compact style="display: flex">
<a-tooltip :title="memoryTooltipText" placement="topLeft" style="flex: 1; display: flex">
<a-input-number
style="width: 100%; min-width: 60px"
:min="isConstrained ? minMemoryInUnit : 0"
:max="isConstrained ? maxMemoryInUnit : undefined"
:step="memoryStep"
:precision="memoryUnit === 'GiB' ? 2 : 0"
v-model:value="memoryDisplayValue"
@change="($event) => updateComputeMemory($event)"
/>
</a-tooltip>
<a-select
v-model:value="memoryUnit"
style="width: 75px"
@change="handleUnitChange">
<a-select-option value="GiB">GiB</a-select-option>
<a-select-option value="MiB">MiB</a-select-option>
</a-select>
</a-input-group>
</a-col>
</a-row>
</a-form-item>
Expand Down Expand Up @@ -165,6 +182,8 @@ export default {
cpuNumberInputValue: 0,
cpuSpeedInputValue: 0,
memoryInputValue: 0,
memoryDisplayValue: 0,
memoryUnit: 'GiB',
errors: {
cpu: {
status: '',
Expand Down Expand Up @@ -192,6 +211,37 @@ export default {
}

return 8
},
minMemoryInUnit () {
if (!this.minMemory) return 0
if (this.memoryUnit === 'GiB') {
return Math.ceil(this.minMemory / 256) * 0.25
}
return this.minMemory
},
maxMemoryInUnit () {
if (!this.maxMemory) return 0
if (this.memoryUnit === 'GiB') {
return Math.max(this.minMemoryInUnit, Math.floor(this.maxMemory / 256) * 0.25)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@saurabhkushwaha438 For custom offerings with a memory range like 2000-2300 MiB, the field is effectively restricted to 2.00 GiB when the unit is switched to GiB. The slider cannot be moved to any other value within the allowed range, preventing selection of valid memory sizes between 2000 MiB and 2300 MiB.

}
return this.maxMemory
},
memoryStep () {
if (this.memoryUnit === 'GiB') {
return 0.25
}
return 1
},
memoryTooltipText () {
if (!this.memoryInputValue) return ''
const exactGiB = this.memoryInputValue / 1024
if (this.memoryUnit === 'GiB') {
if (this.memoryDisplayValue === exactGiB) {
return `${this.memoryDisplayValue} GiB = ${this.memoryInputValue} MiB`
}
return `Exact: ${exactGiB} GiB (${this.memoryInputValue} MiB)`
}
return `${this.memoryInputValue} MiB = ${exactGiB} GiB`
}
},
watch: {
Expand All @@ -209,13 +259,24 @@ export default {
methods: {
fillValue () {
this.cpuNumberInputValue = this.initialCpuValue > 0 ? this.initialCpuValue : this.minCpu
this.memoryInputValue = this.initialMemoryValue > 0 ? this.initialMemoryValue : this.minMemory
const rawMemory = (this.preFillContent && this.preFillContent.memory)
? this.preFillContent.memory
: (this.initialMemoryValue > 0 ? this.initialMemoryValue : this.minMemory)

// MiB is the authoritative internal state
this.memoryInputValue = rawMemory

// Default to GiB if rawMemory is a multiple of 256 MiB (exact 0.25 GiB increment)
const isQuarterGiB = rawMemory >= 256 && (rawMemory % 256 === 0)
this.memoryUnit = isQuarterGiB ? 'GiB' : 'MiB'
this.memoryDisplayValue = isQuarterGiB ? (rawMemory / 1024) : rawMemory

this.cpuSpeedInputValue = this.cpuSpeed

if (!this.preFillContent) {
this.updateComputeCpuNumber(this.cpuNumberInputValue)
this.updateComputeCpuSpeed(this.cpuSpeedInputValue)
this.updateComputeMemory(this.memoryInputValue)
this.$emit('update-compute-memory', this.memoryInputDecorator, this.memoryInputValue)
return
}
if (this.preFillContent.cpunumber) {
Expand All @@ -224,12 +285,25 @@ export default {
if (this.preFillContent.cpuspeed) {
this.cpuSpeedInputValue = this.preFillContent.cpuspeed
}
if (this.preFillContent.memory) {
this.memoryInputValue = this.preFillContent.memory
}

this.updateComputeCpuNumber(this.preFillContent.cpunumber || this.cpuNumberInputValue)
this.updateComputeCpuSpeed(this.preFillContent.cpuspeed || this.cpuSpeedInputValue)
this.updateComputeMemory(this.preFillContent.memory || this.memoryInputValue)
// Emit exact prefilled MiB without any conversion on load
this.$emit('update-compute-memory', this.memoryInputDecorator, this.memoryInputValue)
},
handleUnitChange (newUnit) {
if (newUnit === 'MiB') {
this.memoryDisplayValue = this.memoryInputValue
} else {
this.memoryDisplayValue = Math.round(this.memoryInputValue / 256) * 0.25
}
if (this.isConstrained) {
if (this.memoryDisplayValue < this.minMemoryInUnit) {
this.memoryDisplayValue = this.minMemoryInUnit
} else if (this.memoryDisplayValue > this.maxMemoryInUnit) {
this.memoryDisplayValue = this.maxMemoryInUnit
}
}
},
updateComputeCpuNumber (value) {
if (!value) this.cpuNumberInputValue = 0
Expand All @@ -241,18 +315,37 @@ export default {
updateComputeCpuSpeed (value) {
this.$emit('update-compute-cpuspeed', this.cpuSpeedInputDecorator, value)
},
updateComputeMemory (value) {
if (!value) this.memoryInputValue = 0
if (!this.validateInput('memory', value)) {
updateComputeMemory (displayValue) {
if (displayValue === null || displayValue === undefined || displayValue === '') {
this.memoryDisplayValue = 0
this.memoryInputValue = 0
} else {
this.memoryDisplayValue = displayValue
}
if (!this.validateInput('memory', displayValue)) {
return
}
this.$emit('update-compute-memory', this.memoryInputDecorator, value)
let memoryInMiB
if (this.memoryUnit === 'GiB') {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@saurabhkushwaha438 The memory field and its hover text show different amounts of memory value at the minimum and maximum of a constrained offering.
With min memory 100 MiB, the GiB control shows 0.25 GiB. Hovering it shows "Exact: 0.09765625 GiB (100 MiB)", and deploy sends 100 MiB. 0.25 GiB is 256 MiB, so the VM is created with a smaller size than the field shows. The same happens at the maximum.

Image Image

if (this.isConstrained && displayValue === this.minMemoryInUnit) {
memoryInMiB = this.minMemory
} else if (this.isConstrained && displayValue === this.maxMemoryInUnit) {
memoryInMiB = this.maxMemory
} else {
memoryInMiB = Math.round(displayValue * 1024)
}
} else {
memoryInMiB = Math.round(displayValue)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@saurabhkushwaha438 Switching between MiB and GiB updates only the displayed memory value, while the deploy form continues to retain the previously entered MiB value.

On an unconstrained custom offering:

  • Enter 1100 MiB and then switch to GiB. The field displays 1.00 GiB, but when the instance is created, the deploy request still sends 1100 MiB (where 1.00 GiB = 1024 MiB).
  • Enter 100 MiB and then switch to GiB. The field displays 0 GiB, but instance creation still succeeds, and the deploy request sends 100 MiB, resulting in a VM being created with 100 MiB of memory.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

thanks for pointing out this "Enter 100 MiB and then switch to GiB. The field displays 0 GiB, but instance creation still succeeds, and the deploy request sends 100 MiB, resulting in a VM being created with 100 MiB of memory."

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

thanks for pointing out this "Enter 100 MiB and then switch to GiB. The field displays 0 GiB, but instance creation still succeeds, and the deploy request sends 100 MiB, resulting in a VM being created with 100 MiB of memory."

hey i am not able reproduce this problem , could you attach screenshot of it

}

this.memoryInputValue = memoryInMiB
this.$emit('update-compute-memory', this.memoryInputDecorator, memoryInMiB)
},
validateInput (input, value) {
this.errors[input].status = ''
this.errors[input].message = ''

if (value === null || value === undefined || value.length === 0) {
if (value === null || value === undefined || value.length === 0 || value === '' || value === 0) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@saurabhkushwaha438 Setting the CPU value to 0 does not clear the previously stored CPU count in the form. For example, after selecting a constrained offering, the form stores CPU = 2. When switching to an unconstrained custom offering, the CPU field displays 0 with the validation message "Please enter input". However, instance creation still proceeds successfully, and the VM is created with 2 CPUs, as the previously stored value is retained.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

well this is not related to this issue

this.errors[input].status = 'error'
this.errors[input].message = this.$t('message.error.required.input')
return false
Expand All @@ -271,8 +364,8 @@ export default {
max = this.maxCpu
break
case 'memory':
min = this.minMemory
max = this.maxMemory
min = this.minMemoryInUnit
max = this.maxMemoryInUnit
break
}

Expand All @@ -285,7 +378,8 @@ export default {
return true
},
checkValidRange (value, min, max) {
if (value < min || value > max) {
const epsilon = 0.001
if (value < (min - epsilon) || value > (max + epsilon)) {
return false
}

Expand Down