diff --git a/packages/xo-server/src/api/resource-set.js b/packages/xo-server/src/api/resource-set.js index 4943131cf..162e22de2 100644 --- a/packages/xo-server/src/api/resource-set.js +++ b/packages/xo-server/src/api/resource-set.js @@ -99,11 +99,14 @@ set.params = { // ------------------------------------------------------------------- export function get ({ id }) { + const { user } = this + if (!user) { + throw unauthorized() + } + return this.getResourceSet(id) } -get.permission = 'admin' - get.params = { id: { type: 'string', diff --git a/packages/xo-web/src/common/xo/index.js b/packages/xo-web/src/common/xo/index.js index 9939ca812..41a8122d6 100644 --- a/packages/xo-web/src/common/xo/index.js +++ b/packages/xo-web/src/common/xo/index.js @@ -1201,11 +1201,14 @@ export const createVgpu = (vm, { gpuGroup, vgpuType }) => export const deleteVgpu = vgpu => _call('vm.deleteVgpu', resolveIds({ vgpu })) -export const shareVm = (vm, resourceSet) => +export const shareVm = async (vm, resourceSet) => confirm({ title: _('shareVmInResourceSetModalTitle'), body: _('shareVmInResourceSetModalMessage', { - self: renderXoItem(resourceSet), + self: renderXoItem({ + ...(await getResourceSet(resourceSet)), + type: 'resourceSet', + }), }), }).then(() => editVm(vm, { share: true }), noop) @@ -1682,6 +1685,9 @@ export const deleteResourceSet = async id => { export const recomputeResourceSetsLimits = () => _call('resourceSet.recomputeAllLimits') +export const getResourceSet = id => + _call('resourceSet.get', { id: resolveId(id) }) + // Remote ------------------------------------------------------------ export const getRemote = remote => diff --git a/packages/xo-web/src/xo-app/vm/tab-advanced.js b/packages/xo-web/src/xo-app/vm/tab-advanced.js index ea7f97474..31e1a45ac 100644 --- a/packages/xo-web/src/xo-app/vm/tab-advanced.js +++ b/packages/xo-web/src/xo-app/vm/tab-advanced.js @@ -42,16 +42,16 @@ import { XEN_DEFAULT_CPU_WEIGHT, XEN_VIDEORAM_VALUES, } from 'xo' -import { - createGetObjectsOfType, - createSelector, - getCheckPermissions, - isAdmin, -} from 'selectors' +import { createGetObjectsOfType, createSelector, isAdmin } from 'selectors' + +// Button's height = react-select's height(36 px) + react-select's border-width(1 px) * 2 +// https://github.com/JedWatson/react-select/blob/916ab0e62fc7394be8e24f22251c399a68de8b1c/less/select.less#L21, L22 +const SHARE_BUTTON_STYLE = { height: '38px' } const forceReboot = vm => restartVm(vm, true) const forceShutdown = vm => stopVm(vm, true) const fullCopy = vm => cloneVm(vm, true) +const shareVmProxy = vm => shareVm(vm, vm.resourceSet) @connectStore(() => { const getAffinityHost = createGetObjectsOfType('host').find((_, { vm }) => ({ @@ -128,31 +128,6 @@ class ResourceSetItem extends Component { } } -@addSubscriptions({ - resourceSets: subscribeResourceSets, -}) -class ShareVmButton extends Component { - _shareVm = () => { - const { resourceSets, vm } = this.props - - return shareVm(vm, { - ...find(resourceSets, { id: vm.resourceSet }), - type: 'resourceSet', - }) - } - - render () { - return ( - - ) - } -} - class NewVgpu extends Component { get value () { return this.state @@ -315,332 +290,322 @@ export default connectStore(() => { createSelector(getVgpus, vgpus => map(vgpus, 'gpuGroup')) ) - const getCanAdministrate = createSelector( - getCheckPermissions, - (_, props) => props.vm.id, - (check, id) => check(id, 'administrate') - ) - return { - canAdministrate: getCanAdministrate, gpuGroup: getGpuGroup, isAdmin, vgpus: getVgpus, vgpuTypes: getVgpuTypes, } -})( - ({ canAdministrate, container, gpuGroup, isAdmin, vgpus, vgpuTypes, vm }) => ( - - - - {(isAdmin || canAdministrate) && - vm.resourceSet != null && } - {vm.power_state === 'Running' && ( - - - - - - )} - {vm.power_state === 'Halted' && ( - - - - - - )} - {vm.power_state === 'Suspended' && ( - - - - - )} - - - - - -

{_('xenSettingsLabel')}

- - +})(({ container, gpuGroup, isAdmin, vgpus, vgpuTypes, vm }) => ( + + + + {vm.power_state === 'Running' && ( + + + + + + )} + {vm.power_state === 'Halted' && ( + + + + + + )} + {vm.power_state === 'Suspended' && ( + + + + + )} + + + + + +

{_('xenSettingsLabel')}

+
+ + + + {vm.uuid} + + + + + + {vm.virtualizationMode === 'pv' && ( - - {vm.uuid} - - - + - {vm.virtualizationMode === 'pv' && ( - - - - - )} + )} + + + + + + + + + + + + + + + + + + + + + {vm.virtualizationMode === 'hvm' && ( - + + )} + {vm.virtualizationMode === 'hvm' && ( - - - - - + + )} + {vm.vga === 'std' && ( - + - - - - - {vm.virtualizationMode === 'hvm' && ( - - - - - )} - {vm.virtualizationMode === 'hvm' && ( - - - - - )} - {vm.vga === 'std' && ( - - - - - )} - -
{_('uuid')}
{_('virtualizationMode')} + {vm.virtualizationMode === 'pv' + ? _('paraVirtualizedMode') + : _('hardwareVirtualizedMode')} +
{_('uuid')}
{_('virtualizationMode')}{_('pvArgsLabel')} - {vm.virtualizationMode === 'pv' - ? _('paraVirtualizedMode') - : _('hardwareVirtualizedMode')} + editVm(vm, { PV_args: value })} + />
{_('pvArgsLabel')} - editVm(vm, { PV_args: value })} - /> -
{_('cpuWeightLabel')} + editVm(vm, { cpuWeight: value })} + nullable + > + {vm.cpuWeight == null + ? _('defaultCpuWeight', { value: XEN_DEFAULT_CPU_WEIGHT }) + : vm.cpuWeight} + +
{_('cpuCapLabel')} + editVm(vm, { cpuCap: value })} + nullable + > + {vm.cpuCap == null + ? _('defaultCpuCap', { value: XEN_DEFAULT_CPU_CAP }) + : vm.cpuCap} + +
{_('autoPowerOn')} + editVm(vm, { auto_poweron: value })} + /> +
{_('ha')} + editVm(vm, { high_availability: value })} + /> +
{_('vmAffinityHost')} + +
{_('cpuWeightLabel')}{_('vmVgpus')} - editVm(vm, { cpuWeight: value })} - nullable - > - {vm.cpuWeight == null - ? _('defaultCpuWeight', { value: XEN_DEFAULT_CPU_WEIGHT }) - : vm.cpuWeight} - +
{_('cpuCapLabel')} - editVm(vm, { cpuCap: value })} - nullable - > - {vm.cpuCap == null - ? _('defaultCpuCap', { value: XEN_DEFAULT_CPU_CAP }) - : vm.cpuCap} - -
{_('autoPowerOn')}{_('vmVga')} editVm(vm, { auto_poweron: value })} + value={vm.vga === 'std'} + onChange={value => + editVm(vm, { vga: value ? 'std' : 'cirrus' }) + } />
{_('ha')}{_('vmVideoram')} - editVm(vm, { high_availability: value })} - /> +
{_('vmAffinityHost')} - -
{_('vmVgpus')} - -
{_('vmVga')} - - editVm(vm, { vga: value ? 'std' : 'cirrus' }) - } - /> -
{_('vmVideoram')} - -
-
-

{_('vmLimitsLabel')}

- - - - - +
{_('vmCpuLimitsLabel')} + )} +
+
+

{_('vmLimitsLabel')}

+ + + + + - - - - - - - - - - -
{_('vmCpuLimitsLabel')} + editVm(vm, { cpus })} + /> + / + {vm.power_state === 'Running' ? ( + vm.CPUs.max + ) : ( editVm(vm, { cpus })} + value={vm.CPUs.max} + onChange={cpusStaticMax => editVm(vm, { cpusStaticMax })} /> - / - {vm.power_state === 'Running' ? ( - vm.CPUs.max - ) : ( - editVm(vm, { cpusStaticMax })} - /> - )} -
{_('vmCpuTopology')} - -
{_('vmMemoryLimitsLabel')} -

- Static: {formatSize(vm.memory.static[0])}/ - editVm(vm, { memoryStaticMax }) - } - /> -

-

- Dynamic:{' '} - editVm(vm, { memoryMin })} - />/ editVm(vm, { memoryMax })} - /> -

-
-
-

{_('guestOsLabel')}

- - - - - - - - - - - - - - - -
{_('xenToolsStatus')} - {_('xenToolsStatusValue', { - status: normalizeXenToolsStatus(vm.xenTools), - })} -
{_('osName')} - {isEmpty(vm.os_version) ? ( - _('unknownOsName') - ) : ( - -  {vm.os_version.name} - - )} -
{_('osKernel')} - {(vm.os_version && vm.os_version.uname) || - _('unknownOsKernel')} -
-
-

{_('miscLabel')}

- - - - - - - - - + + + + + + + + + + +
{_('originalTemplate')} - {vm.other.base_template_name - ? vm.other.base_template_name - : _('unknownOriginalTemplate')} -
{_('resourceSet')} - {isAdmin ? ( + )} +
{_('vmCpuTopology')} + +
{_('vmMemoryLimitsLabel')} +

+ Static: {formatSize(vm.memory.static[0])}/ + editVm(vm, { memoryStaticMax }) + } + /> +

+

+ Dynamic:{' '} + editVm(vm, { memoryMin })} + />/ editVm(vm, { memoryMax })} + /> +

+
+
+

{_('guestOsLabel')}

+ + + + + + + + + + + + + + + +
{_('xenToolsStatus')} + {_('xenToolsStatusValue', { + status: normalizeXenToolsStatus(vm.xenTools), + })} +
{_('osName')} + {isEmpty(vm.os_version) ? ( + _('unknownOsName') + ) : ( + +  {vm.os_version.name} + + )} +
{_('osKernel')} + {(vm.os_version && vm.os_version.uname) || _('unknownOsKernel')} +
+
+

{_('miscLabel')}

+ + + + + + + + + - - -
{_('originalTemplate')} + {vm.other.base_template_name + ? vm.other.base_template_name + : _('unknownOriginalTemplate')} +
{_('resourceSet')} + {isAdmin ? ( +
editVm(vm, { @@ -650,17 +615,39 @@ export default connectStore(() => { } value={vm.resourceSet} /> - ) : vm.resourceSet !== undefined ? ( - - ) : ( - _('resourceSetNone') - )} -
- -
-
- ) -) + {vm.resourceSet !== undefined && ( + + + + )} + + ) : vm.resourceSet !== undefined ? ( + + {' '} + + + ) : ( + _('resourceSetNone') + )} + + + + + + + +))