parent
8b05486945
commit
8971d218bb
@ -500,7 +500,6 @@ export async function set (params) {
|
||||
const vmId = VM._xapiId
|
||||
|
||||
const resourceSetId = extract(params, 'resourceSet')
|
||||
|
||||
if (resourceSetId !== undefined) {
|
||||
if (this.user.permission !== 'admin') {
|
||||
throw unauthorized()
|
||||
@ -509,6 +508,11 @@ export async function set (params) {
|
||||
await this.setVmResourceSet(vmId, resourceSetId)
|
||||
}
|
||||
|
||||
const share = extract(params, 'share')
|
||||
if (share) {
|
||||
await this.shareVmResourceSet(vmId)
|
||||
}
|
||||
|
||||
return xapi.editVm(vmId, params, async (limits, vm) => {
|
||||
const resourceSet = xapi.xo.getData(vm, 'resourceSet')
|
||||
|
||||
@ -580,6 +584,8 @@ set.params = {
|
||||
|
||||
// Move the vm In to/Out of Self Service
|
||||
resourceSet: { type: ['string', 'null'], optional: true },
|
||||
|
||||
share: { type: 'boolean', optional: true },
|
||||
}
|
||||
|
||||
set.resolve = {
|
||||
|
@ -391,10 +391,18 @@ export default class {
|
||||
await this._xo.removeAclsForObject(vmId)
|
||||
}
|
||||
if (resourceSetId != null) {
|
||||
await this.shareVmResourceSet(vmId)
|
||||
}
|
||||
}
|
||||
|
||||
async shareVmResourceSet (vmId) {
|
||||
const xapi = this._xo.getXapi(vmId)
|
||||
const resourceSetId = xapi.xo.getData(vmId, 'resourceSet')
|
||||
if (resourceSetId === undefined) {
|
||||
throw new Error('the vm is not in a resource set')
|
||||
}
|
||||
|
||||
const { subjects } = await this.getResourceSet(resourceSetId)
|
||||
await asyncMap(subjects, subject =>
|
||||
this._xo.addAcl(subject, vmId, 'admin')
|
||||
)
|
||||
}
|
||||
await asyncMap(subjects, subject => this._xo.addAcl(subject, vmId, 'admin'))
|
||||
}
|
||||
}
|
||||
|
@ -844,6 +844,7 @@ const messages = {
|
||||
// ----- VM advanced tab -----
|
||||
vmRemoveButton: 'Remove',
|
||||
vmConvertButton: 'Convert',
|
||||
vmShareButton: 'Share',
|
||||
xenSettingsLabel: 'Xen settings',
|
||||
guestOsLabel: 'Guest OS',
|
||||
miscLabel: 'Misc',
|
||||
@ -1252,6 +1253,9 @@ const messages = {
|
||||
deleteRemotesModalMessage:
|
||||
'Are you sure you want to delete {nRemotes, number} remote{nRemotes, plural, one {} other {s}}?',
|
||||
revertVmModalTitle: 'Revert your VM',
|
||||
shareVmInResourceSetModalTitle: 'Share your VM',
|
||||
shareVmInResourceSetModalMessage:
|
||||
'This VM will be shared with all the members of the self-service {self}. Are you sure?',
|
||||
deleteVifsModalTitle: 'Delete VIF{nVifs, plural, one {} other {s}}',
|
||||
deleteVifsModalMessage:
|
||||
'Are you sure you want to delete {nVifs, number} VIF{nVifs, plural, one {} other {s}}?',
|
||||
|
@ -24,6 +24,7 @@ import { forbiddenOperation, noHostsAvailable } from 'xo-common/api-errors'
|
||||
import _ from '../intl'
|
||||
import invoke from '../invoke'
|
||||
import logError from '../log-error'
|
||||
import renderXoItem from '../render-xo-item'
|
||||
import store from 'store'
|
||||
import { alert, chooseAction, confirm } from '../modal'
|
||||
import { error, info, success } from '../notification'
|
||||
@ -1171,6 +1172,14 @@ export const createVgpu = (vm, { gpuGroup, vgpuType }) =>
|
||||
|
||||
export const deleteVgpu = vgpu => _call('vm.deleteVgpu', resolveIds({ vgpu }))
|
||||
|
||||
export const shareVm = (vm, resourceSet) =>
|
||||
confirm({
|
||||
title: _('shareVmInResourceSetModalTitle'),
|
||||
body: _('shareVmInResourceSetModalMessage', {
|
||||
self: renderXoItem(resourceSet),
|
||||
}),
|
||||
}).then(() => editVm(vm, { share: true }), noop)
|
||||
|
||||
// DISK ---------------------------------------------------------------
|
||||
|
||||
export const createDisk = (name, size, sr, { vm, bootable, mode, position }) =>
|
||||
|
@ -356,6 +356,10 @@
|
||||
@extend .text-primary;
|
||||
@extend .fa-ship;
|
||||
}
|
||||
&-share {
|
||||
@extend .fa;
|
||||
@extend .fa-list-alt;
|
||||
}
|
||||
}
|
||||
|
||||
// Generic states
|
||||
|
@ -24,9 +24,9 @@ import {
|
||||
osFamily,
|
||||
} from 'utils'
|
||||
import {
|
||||
createVgpu,
|
||||
cloneVm,
|
||||
convertVmToTemplate,
|
||||
createVgpu,
|
||||
deleteVgpu,
|
||||
deleteVm,
|
||||
editVm,
|
||||
@ -34,6 +34,7 @@ import {
|
||||
recoveryStartVm,
|
||||
restartVm,
|
||||
resumeVm,
|
||||
shareVm,
|
||||
stopVm,
|
||||
subscribeResourceSets,
|
||||
suspendVm,
|
||||
@ -41,7 +42,12 @@ import {
|
||||
XEN_DEFAULT_CPU_WEIGHT,
|
||||
XEN_VIDEORAM_VALUES,
|
||||
} from 'xo'
|
||||
import { createGetObjectsOfType, createSelector, isAdmin } from 'selectors'
|
||||
import {
|
||||
createGetObjectsOfType,
|
||||
createSelector,
|
||||
getCheckPermissions,
|
||||
isAdmin,
|
||||
} from 'selectors'
|
||||
|
||||
const forceReboot = vm => restartVm(vm, true)
|
||||
const forceShutdown = vm => stopVm(vm, true)
|
||||
@ -122,6 +128,31 @@ 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 (
|
||||
<TabButton
|
||||
btnStyle='primary'
|
||||
handler={this._shareVm}
|
||||
icon='vm-share'
|
||||
labelId='vmShareButton'
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class NewVgpu extends Component {
|
||||
get value () {
|
||||
return this.state
|
||||
@ -284,16 +315,26 @@ 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,
|
||||
}
|
||||
})(({ container, gpuGroup, isAdmin, vgpus, vgpuTypes, vm }) => (
|
||||
})(
|
||||
({ canAdministrate, container, gpuGroup, isAdmin, vgpus, vgpuTypes, vm }) => (
|
||||
<Container>
|
||||
<Row>
|
||||
<Col className='text-xs-right'>
|
||||
{(isAdmin || canAdministrate) &&
|
||||
vm.resourceSet != null && <ShareVmButton vm={vm} />}
|
||||
{vm.power_state === 'Running' && (
|
||||
<span>
|
||||
<TabButton
|
||||
@ -578,7 +619,8 @@ export default connectStore(() => {
|
||||
<tr>
|
||||
<th>{_('osKernel')}</th>
|
||||
<td>
|
||||
{(vm.os_version && vm.os_version.uname) || _('unknownOsKernel')}
|
||||
{(vm.os_version && vm.os_version.uname) ||
|
||||
_('unknownOsKernel')}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@ -620,4 +662,5 @@ export default connectStore(() => {
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
))
|
||||
)
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user