Files
xen-orchestra/app/node_modules/xo-services/index.coffee
2015-04-14 17:27:28 +02:00

265 lines
8.3 KiB
CoffeeScript

angular = require 'angular'
filter = require 'lodash.filter'
#=====================================================================
# TODO: split into multiple modules.
module.exports = angular.module 'xoWebApp.services', [
require 'angular-animate'
require 'angular-notify-toaster'
require 'xo-api'
]
.service 'notify', (toaster) ->
notifier = (level) ->
(options) ->
if angular.isString options
options = { message: options }
else
throw new Error 'missing message' unless options.message
toaster.pop(
level
options.title ? 'Xen-Orchestra'
options.message
)
{
warning: notifier 'warning'
error: notifier 'error'
info: notifier 'info'
# TODO: It is probably a bad design to have notification for
# successful operations.
# success: notifier 'success'
}
.service 'xo', ($timeout, xoApi, notify) ->
# FIXME: default mapper should be identity.
defaultArgsMapper = (id) -> if id? then {id} else {}
action = (name, method, options) ->
unless method
return ->
notify.info {
title: name
message: 'This feature has not been implemented yet.'
}
# TODO: A (broken) promise should be returned for
# consistency.
{argsMapper, notification} = options ? {}
argsMapper ?= defaultArgsMapper
(args...) ->
xoApi.call(
method
argsMapper args...
).catch (error) ->
unless notification is false
code = error?.code
message = if code is 2
'You don\'t have the permission.'
else
'The action failed for unknown reason.'
notify.warning {
title: name
message
}
console.error error
# Re-throws the error to make it available in the promise
# chain.
throw error
# The interface.
xo = {
acl:
add: action('Adding an ACL entry', 'acl.add', {
argsMapper: (subject, object) => {subject, object},
})
get: action('Getting ACLs', 'acl.get')
remove: action('Remove an ACL entry', 'acl.remove', {
argsMapper: (subject, object) => {subject, object},
})
pool:
disconnect: action 'Disconnect pool'
new_sr: action 'New SR' #temp fix before creating SR
patch: action 'Upload patch', 'pool.patch', argsMapper: (pool) -> {pool}
host:
attach: action 'Atach host'#, 'host.attach'
detach: action 'Detach host', 'host.detach'
restart: action 'Restart host', 'host.restart'
restartToolStack: action 'Restart tool stack', 'host.restart_agent'
start: action 'Start host', 'host.start'
enable: action 'Enable host', 'host.enable'
stop: action 'Stop host', 'host.stop'
disable: action 'Disable host', 'host.disable'
new_sr: action 'New SR' #temp fix before creating SR
# TODO: attach/set
log:
delete: action 'Delete Log', 'message.delete'
message:
delete: action 'Delete message'
pbd:
delete: action 'Delete PBD'
disconnect: action 'Disconnect PBD'
server:
add: action 'Add server', 'server.add', {
argsMapper: (params) -> angular.copy(params)
}
remove: action 'Remove server', 'server.remove', argsMapper: (id) -> {id}
getAll: action 'Getting server', 'server.getAll'
set: action 'Save server', 'server.set', {
argsMapper: (params) -> angular.copy(params)
}
connect: action 'Connect to a server', 'server.connect', notification: false, argsMapper: (id) -> {id}
disconnect: action 'Disconnect from a server', 'server.disconnect', argsMapper: (id) -> {id}
task:
cancel: action 'Cancel task', 'task.cancel', argsMapper: (id) -> {id}
destroy: action 'Destroy task', 'task.destroy', argsMapper: (id) -> {id}
user:
create: action 'Create user', 'user.create', {
argsMapper: (params) -> angular.copy(params)
}
delete: action 'Delete user', 'user.delete', argsMapper: (id) -> {id}
getAll: action 'Getting users', 'user.getAll'
set: action 'Save user', 'user.set', {
argsMapper: (params) -> angular.copy(params)
}
vm:
convert: action 'Convert VM', 'vm.convert', {
argsMapper: (id) -> {id}
}
clone: action 'Copy VM', 'vm.clone', {
argsMapper: (id, name, full_copy) -> {id, name, full_copy} #todo : sr ref to choose target SR
}
createSnapshot: action 'Create VM snapshot', 'vm.snapshot', {
argsMapper: (id, name) -> {id, name}
}
export: action 'Export VM', 'vm.export', {
argsMapper: (vm, compress = true) -> {vm, compress}
}
delete: action 'Delete VM', 'vm.delete', {
argsMapper: (id, delete_disks) -> { id, delete_disks }
}
ejectCd: action 'Eject disc', 'vm.ejectCd'
insertCd: action 'Insert disc', 'vm.insertCd', {
argsMapper: (id, cd_id, force = false) -> { id, cd_id, force }
}
import: action 'Import VM', 'vm.import', {
argsMapper: (host) -> { host }
}
migrate: action 'Migrate VM', 'vm.migrate', {
argsMapper: (id, host_id) -> { id, host_id }
}
migratePool: action 'Migrate VM to another pool', 'vm.migrate_pool', {
argsMapper: (params) -> angular.copy(params)
}
restart: action 'Restart VM', 'vm.restart', {
argsMapper: (id, force = false) -> { id, force }
}
start: action 'Start VM', 'vm.start'
stop: action 'Stop VM', 'vm.stop', {
argsMapper: (id, force = false) -> { id, force }
}
revert: action 'Revert snapshot', 'vm.revert'
suspend: action 'Suspend VM', 'vm.suspend'
resume: action 'Resume VM', 'vm.resume', {
argsMapper: (id, force = true) -> { id, force }
}
refreshStats: action 'Get Stats', 'vm.stats', {
argsMapper: (id) -> {id}
}
# TODO: create/set/pause
connectPci: action 'Connect PCI device', 'vm.attachPci', {
argsMapper: (vm, pciId) -> {vm, pciId}
}
disconnectPci: action 'Disconnect PCI device', 'vm.detachPci', {
argsMapper: (vm) -> {vm}
}
vdi:
delete: action 'Delete VDI', 'vdi.delete'
migrate: action 'Migrate VDI', 'vdi.migrate', {
argsMapper: (id, sr_id) -> { id, sr_id }
}
vif:
delete: action 'Delete VIF', 'vif.delete'
disconnect: action 'Disconnect VIF', 'vif.disconnect'
connect: action 'Connect VIF', 'vif.connect'
vbd:
delete: action 'Delete VBD', 'vbd.delete'
disconnect: action 'Disconnect VBD', 'vbd.disconnect'
connect: action 'Connect VBD', 'vbd.connect'
}
# TODO: should probably be merged in the main collection in xo-lib.
currentAcls = Object.create(null)
updateCurrentAcls = () ->
xoApi.call('acl.getCurrent').then((acls) ->
currentAcls = Object.create(null)
for acl in acls
object = xoApi.get(acl.object)
if object
currentAcls[object.id] = true
$timeout(updateCurrentAcls, 1e4)
return
)
updateCurrentAcls()
# Adds the dynamic properties.
Object.defineProperties(xo, {
byTypes: { get: ->
throw new Error('use xoApi.byTypes instead');
},
get: { get: ->
throw new Error('use xoApi.get() instead');
},
currentAcls: { get: -> currentAcls },
})
xo.canAccess = (id) ->
{id} = id if id.id
return (
# Administrators can access everything.
xoApi.user and (xoApi.user.permission is 'admin') or
# Check if the id is in the ACLs table.
(id of currentAcls) or
# Check if the id is in fact not a true id (maybe a ref or a
# UUID) and if we can resolve it to an id.
(id = xoApi.get(id)?.id) and (id of currentAcls)
)
# Returns the interface.
xo
.filter 'xoHideUnauthorized', (xo) ->
{canAccess} = xo
return (objects) -> filter objects, xo.canAccess
# A module exports its name.
.name