1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-22 18:50:08 +03:00

F #5625: add download marketapp (#1812)

(cherry picked from commit 3fd624edcbeb7f0ab3c0cec4400296b6055197e1)
This commit is contained in:
Jorge Miguel Lobo Escalona 2022-02-28 19:13:48 +01:00 committed by Tino Vazquez
parent d682eeec41
commit fa338f8004
No known key found for this signature in database
GPG Key ID: 14201E424D02047E
33 changed files with 403 additions and 338 deletions

View File

@ -16,12 +16,15 @@
/* eslint-disable jsdoc/require-jsdoc */
import { useMemo } from 'react'
import { useHistory } from 'react-router-dom'
import { AddSquare, CloudDownload } from 'iconoir-react'
import { AddSquare, CloudDownload, DownloadCircledOutline } from 'iconoir-react'
import { useViews } from 'client/features/Auth'
import { useGeneralApi } from 'client/features/General'
import { Translate } from 'client/components/HOC'
import { useExportAppMutation } from 'client/features/OneApi/marketplaceApp'
import {
useExportAppMutation,
useDownloadAppMutation,
} from 'client/features/OneApi/marketplaceApp'
import { ExportForm } from 'client/components/Forms/MarketplaceApp'
import { createActions } from 'client/components/Tables/Enhanced/Utils'
@ -51,6 +54,7 @@ const Actions = () => {
const { view, getResourceView } = useViews()
const { enqueueSuccess } = useGeneralApi()
const [exportApp] = useExportAppMutation()
const [downloadApp] = useDownloadAppMutation()
const marketplaceAppActions = useMemo(
() =>
@ -86,6 +90,18 @@ const Actions = () => {
},
],
},
{
accessor: MARKETPLACE_APP_ACTIONS.DOWNLOAD,
tooltip: T.DownloadApp,
selected: { min: 1 },
icon: DownloadCircledOutline,
action: async (apps) => {
const urls = await Promise.all(
apps.map(({ id }) => downloadApp(id).unwrap())
)
urls.forEach((url) => window.open(url, '_blank'))
},
},
],
}),
[view]

View File

@ -53,4 +53,5 @@ export const MARKETPLACE_APP_ACTIONS = {
CREATE_DIALOG: 'create_dialog',
RENAME: ACTIONS.RENAME,
EXPORT: 'export',
DOWNLOAD: 'download',
}

View File

@ -670,6 +670,7 @@ module.exports = {
automatically added when the App is exported`,
ImportIntoDatastore: 'Import into Datastore',
DownloadAppToOpenNebula: 'Download App to OpenNebula',
DownloadApp: 'Download App',
ExportAppNameConcept:
'Name that the resource will get for description purposes',
ExportTemplateNameConcept: `

View File

@ -24,6 +24,7 @@ import {
ONE_RESOURCES,
ONE_RESOURCES_POOL,
} from 'client/features/OneApi'
import { requestConfig } from 'client/utils'
import { FilterFlag, Permission, MarketplaceApp } from 'client/constants'
const { APP } = ONE_RESOURCES
@ -305,6 +306,31 @@ const marketAppApi = oneApi.injectEndpoints({
},
invalidatesTags: [APP_POOL],
}),
downloadApp: builder.mutation({
/**
* Download a MarketPlaceApp.
*
* @param {string} id - Marketplace app id
* @param {object} configBaseQueryApi - ConfigBaseQueryApi
* @param {function():object} configBaseQueryApi.getState - Get current state
* @returns {object} Marketplace URL download
* @throws Fails when response isn't code 200
*/
queryFn: (id, { getState }) => {
try {
const state = getState()
const token = state.auth.jwt
const name = ExtraActions.MARKETAPP_DOWNLOAD
const command = { name, ...ExtraCommands[name] }
const { url, params } = requestConfig({ id, token }, command)
return { data: `/fireedge${url}?token=${params.token}` }
} catch (error) {
return { error }
}
},
}),
exportApp: builder.mutation({
/**
* Exports the marketplace app to the OpenNebula cloud.
@ -354,6 +380,7 @@ export const {
useUnlockAppMutation,
useImportAppMutation,
useExportAppMutation,
useDownloadAppMutation,
} = marketAppApi
export default marketAppApi

View File

@ -1,17 +0,0 @@
/* ------------------------------------------------------------------------- *
* Copyright 2002-2021, OpenNebula Project, OpenNebula Systems *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain *
* a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
module.exports = 'tfa'

View File

@ -43,19 +43,19 @@ const twoFactorAuthIssuer = appConfig.TWO_FACTOR_AUTH_ISSUER || default2FAIssuer
/**
* Get information for opennebula authenticated user.
*
* @param {Function} connect - xmlrpc function
* @param {Function} oneConnect - xmlrpc function
* @param {Function} next - express stepper
* @param {Function} callback - run if have user information
*/
const getUserInfoAuthenticated = (
connect = defaultEmptyFunction,
oneConnect = defaultEmptyFunction,
next = defaultEmptyFunction,
callback = defaultEmptyFunction
) => {
connect(
Actions.USER_INFO,
getDefaultParamsOfOpennebulaCommand(Actions.USER_INFO, GET),
(err, value) => {
oneConnect({
action: Actions.USER_INFO,
parameters: getDefaultParamsOfOpennebulaCommand(Actions.USER_INFO, GET),
callback: (err, value) => {
responseOpennebula(
() => undefined,
err,
@ -69,8 +69,8 @@ const getUserInfoAuthenticated = (
},
next
)
}
)
},
})
}
/**
@ -105,9 +105,9 @@ const setup = (
const sunstone = user.USER.TEMPLATE.SUNSTONE
const secret = sunstone[default2FAOpennebulaTmpVar]
if (check2Fa(secret, token)) {
oneConnect(
Actions.USER_UPDATE,
[
oneConnect({
action: Actions.USER_UPDATE,
parameters: [
parseInt(user.USER.ID, 10),
generateNewResourceTemplate(
user.USER.TEMPLATE.SUNSTONE || {},
@ -116,7 +116,7 @@ const setup = (
),
1,
],
(error, value) => {
callback: (error, value) => {
responseOpennebula(
() => undefined,
error,
@ -129,8 +129,8 @@ const setup = (
},
next
)
}
)
},
})
} else {
res.locals.httpCode = httpResponse(unauthorized)
next()
@ -171,9 +171,9 @@ const qr = (
const oneConnect = oneConnection()
getUserInfoAuthenticated(oneConnect, next, (user) => {
if (user && user.USER && user.USER.ID && user.USER.TEMPLATE) {
oneConnect(
Actions.USER_UPDATE,
[
oneConnect({
action: Actions.USER_UPDATE,
parameters: [
parseInt(user.USER.ID, 10),
generateNewResourceTemplate(
user.USER.TEMPLATE.SUNSTONE || {},
@ -182,7 +182,7 @@ const qr = (
),
1,
],
(error, value) => {
callback: (error, value) => {
responseOpennebula(
() => undefined,
error,
@ -199,8 +199,8 @@ const qr = (
},
next
)
}
)
},
})
} else {
next()
}
@ -237,9 +237,9 @@ const del = (
user.USER.TEMPLATE &&
user.USER.TEMPLATE.SUNSTONE
) {
oneConnect(
Actions.USER_UPDATE,
[
oneConnect({
action: Actions.USER_UPDATE,
parameters: [
parseInt(user.USER.ID, 10),
generateNewResourceTemplate(user.USER.TEMPLATE.SUNSTONE || {}, {}, [
default2FAOpennebulaTmpVar,
@ -247,7 +247,7 @@ const del = (
]),
1,
],
(err, value) => {
callback: (err, value) => {
responseOpennebula(
() => undefined,
err,
@ -260,8 +260,8 @@ const del = (
},
next
)
}
)
},
})
}
})
}

View File

@ -18,10 +18,9 @@ const {
httpMethod,
from: fromData,
} = require('server/utils/constants/defaults')
const TFA = require('server/routes/api/2fa/basepath')
const { POST, DELETE, GET } = httpMethod
const basepath = `/${TFA}`
const basepath = '/tfa'
const TFA_SETUP = 'tfa.setup'
const TFA_QR = 'tfa.qr'
const TFA_DELETE = 'tfa.delete'

View File

@ -1,17 +0,0 @@
/* ------------------------------------------------------------------------- *
* Copyright 2002-2021, OpenNebula Project, OpenNebula Systems *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain *
* a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
module.exports = 'auth'

View File

@ -111,20 +111,19 @@ const auth = (
next()
}
oneConnect(
Actions.USER_INFO,
getDefaultParamsOfOpennebulaCommand(Actions.USER_INFO, GET),
(err, value) => {
oneConnect({
action: Actions.USER_INFO,
parameters: getDefaultParamsOfOpennebulaCommand(Actions.USER_INFO, GET),
callback: (err, value) => {
loginUser(err, value, success, error)
},
false
)
fillHookResource: false,
})
} else {
next()
}
}
const authApi = {
module.exports = {
auth,
}
module.exports = authApi

View File

@ -19,11 +19,9 @@ const {
from: fromData,
} = require('server/utils/constants/defaults')
const AUTH = require('server/routes/api/auth/basepath')
const { POST } = httpMethod
const { postBody } = fromData
const basepath = `/${AUTH}`
const basepath = '/auth'
const AUTHENTICATION = 'authentication'
const Actions = {

View File

@ -357,10 +357,13 @@ const getCreatedTokenOpennebula = (username = '') => {
const setZones = () => {
if (global && !global.zones) {
const oneConnect = connectOpennebula()
oneConnect(
ActionZones.ZONEPOOL_INFO,
getDefaultParamsOfOpennebulaCommand(ActionZones.ZONEPOOL_INFO, GET),
(err, value) => {
oneConnect({
action: ActionZones.ZONEPOOL_INFO,
parameters: getDefaultParamsOfOpennebulaCommand(
ActionZones.ZONEPOOL_INFO,
GET
),
callback: (err, value) => {
// res, err, value, response, next
responseOpennebula(
() => undefined,
@ -394,8 +397,8 @@ const setZones = () => {
next
)
},
false
)
fillHookResource: false,
})
}
}
@ -516,10 +519,13 @@ const getServerAdminAndWrapUser = (userData = {}) => {
`${serverAdminData.username}:${serverAdminData.username}`,
tokenWithServerAdmin.token
)
oneConnect(
ActionUsers.USER_INFO,
getDefaultParamsOfOpennebulaCommand(ActionUsers.USER_INFO, GET),
(err, value) => {
oneConnect({
action: ActionUsers.USER_INFO,
parameters: getDefaultParamsOfOpennebulaCommand(
ActionUsers.USER_INFO,
GET
),
callback: (err, value) => {
responseOpennebula(
updaterResponse,
err,
@ -529,8 +535,8 @@ const getServerAdminAndWrapUser = (userData = {}) => {
next
)
},
false
)
fillHookResource: false,
})
}
}
}

View File

@ -1,17 +0,0 @@
/* ------------------------------------------------------------------------- *
* Copyright 2002-2021, OpenNebula Project, OpenNebula Systems *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain *
* a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
module.exports = 'files'

View File

@ -57,10 +57,10 @@ const checkUserAdmin = (
typeof success === 'function' &&
typeof error === 'function'
) {
oneConnection(
ActionUser.USER_INFO,
[parseInt(id, 10)],
(err, value) => {
oneConnection({
action: ActionUser.USER_INFO,
parameters: [parseInt(id, 10)],
callback: (err, value) => {
if (
!err &&
value &&
@ -83,8 +83,8 @@ const checkUserAdmin = (
error(err)
}
},
false
)
fillHookResource: false,
})
} else {
error()
}
@ -255,14 +255,12 @@ const getDefaultFilesforApps = (
* @param {Function} next - express stepper
* @param {string} params - data response http
* @param {object} userData - user of http request
* @param {Function} oneConnection - one connection XMLRPC
*/
const list = (
res = {},
next = defaultEmptyFunction,
params = {},
userData = {},
oneConnection = defaultEmptyFunction
userData = {}
) => {
const { user, password, id } = userData
const { app } = params

View File

@ -18,10 +18,9 @@ const {
from: fromData,
httpMethod,
} = require('server/utils/constants/defaults')
const FILES = require('server/routes/api/files/basepath')
const { GET, POST, PUT, DELETE } = httpMethod
const basepath = `/${FILES}`
const basepath = '/files'
const { query } = fromData
const FILE_SHOW = 'file.show'

View File

@ -17,10 +17,13 @@
const multer = require('multer')
const { messageTerminal } = require('server/utils/general')
const { getRequestParameters, getRequestFiles } = require('server/utils/server')
const { defaultConfigErrorMessage } = require('server/utils/constants/defaults')
const {
defaultConfigErrorMessage,
defaultTmpPath,
} = require('server/utils/constants/defaults')
const { writeInLogger } = require('server/utils/logger')
const upload = multer({ dest: '/tmp' })
const upload = multer({ dest: defaultTmpPath })
const routes = [
'2fa',

View File

@ -14,9 +14,13 @@
* limitations under the License. *
* ------------------------------------------------------------------------- */
const btoa = require('btoa')
const { exec } = require('child_process')
const { sprintf } = require('sprintf-js')
const { request: axios } = require('axios')
const { messageTerminal } = require('server/utils/general')
const { defaults, httpCodes } = require('server/utils/constants')
const { validateAuth } = require('server/utils/jwt')
const {
Actions: ActionsMarketApp,
} = require('server/utils/constants/commands/marketapp')
@ -25,9 +29,11 @@ const {
} = require('server/utils/constants/commands/market')
const { httpResponse, executeCommand } = require('server/utils/server')
const { getSunstoneConfig } = require('server/utils/yml')
const { writeInLogger } = require('server/utils/logger')
const { defaultEmptyFunction, defaultCommandMarketApp, dockerUrl } = defaults
const { ok, internalServerError, badRequest, notFound } = httpCodes
const { ok, internalServerError, badRequest, notFound, unauthorized } =
httpCodes
const httpBadRequest = httpResponse(badRequest, '', '')
const httpNotFoundRequest = httpResponse(notFound, '', '')
@ -109,7 +115,83 @@ const exportApp = (
}
/**
* Import the marketplace VM or VM TEMPLATE to the OpenNebula cloud.
* Exports the marketplace app to the OpenNebula cloud.
*
* @param {object} res - http response
* @param {Function} next - express stepper
* @param {object} params - params of http request
* @param {number} params.id - app id
* @param {object} userData - user of http request
* @param {Function} oneConnection - function of xmlrpc
*/
const downloadApp = (
res = {},
next = defaultEmptyFunction,
params = {},
userData = {},
oneConnection = defaultEmptyFunction
) => {
const { id, token } = params
if (!(Number.isInteger(parseInt(id, 10)) && token)) {
responseHttp(res, next, httpNotFoundRequest)
return
}
const userDataFromJWT =
validateAuth({
headers: { authorization: token },
}) || {}
const { aud, jti } = userDataFromJWT
if (!(aud && jti)) {
responseHttp(res, next, httpResponse(unauthorized, '', ''))
return
}
const oneConnect = oneConnection(aud, jti)
const callbackNotfound = () => responseHttp(res, next, httpNotFoundRequest)
const market = ({ MARKETPLACE_ID, SOURCE }) => {
Number.isInteger(parseInt(MARKETPLACE_ID, 10)) &&
getMarket({
oneConnect,
id: MARKETPLACE_ID,
success: (MARKET) => {
const drvMessage = `<DS_DRIVER_ACTION_DATA>${MARKET}</DS_DRIVER_ACTION_DATA>`
const drvMessageBase64 = btoa(drvMessage)
const downloadCmd = `DRV_ACTION=${drvMessageBase64}; ${global.paths.DOWNLOADER} ${SOURCE} -`
const filename = `one-marketplaceapp-${id}`
res.setHeader('Content-Type', 'application/octet-stream')
res.setHeader('Cache-Control', 'no-transform')
res.setHeader(
'Content-Disposition',
`attachment; filename=${filename}`
)
const execChild = exec(
downloadCmd,
{ maxBuffer: 1024 ** 3 },
(error) => {
error &&
writeInLogger(error) &&
messageTerminal({
color: 'red',
message: 'error download marketapp: %s',
error,
})
}
)
execChild.stdout.pipe(res)
},
error: callbackNotfound,
parseXML: false,
})
}
getMarketApp({ oneConnect, id, success: market, error: callbackNotfound })
}
/**
* Import the marketplace VM or VM TEPLATE to the OpenNebula cloud.
*
* @param {object} res - http response
* @param {Function} next - express stepper
@ -178,58 +260,65 @@ const getTagsDocker = (
/**
* Get market APP information.
*
* @param {Function} oneConnection - ONE connection
* @param {number} id - ID market app
* @param {Function} success - callback when have data
* @param {Function} error - error callback
* @param {object} config - config
* @param {Function} config.oneConnect - ONE connection
* @param {number} config.id - ID market app
* @param {Function} config.success - callback when have data
* @param {Function} config.error - error callback
* @returns {undefined} one connect
*/
const getMarketApp = (
oneConnection = defaultEmptyFunction,
const getMarketApp = ({
oneConnect = defaultEmptyFunction,
id,
success = defaultEmptyFunction,
error = defaultEmptyFunction
) => {
oneConnection(
ActionsMarketApp.MARKETAPP_INFO,
[parseInt(id, 10)],
(err = undefined, marketApp = {}) => {
error = defaultEmptyFunction,
}) =>
oneConnect({
action: ActionsMarketApp.MARKETAPP_INFO,
parameters: [parseInt(id, 10)],
callback: (err = undefined, marketApp = {}) => {
if (err || !(marketApp && marketApp.MARKETPLACEAPP)) {
error()
return
}
success(marketApp && marketApp.MARKETPLACEAPP)
}
)
}
},
})
/**
* Get market information.
*
* @param {Function} oneConnection - ONE connection
* @param {number} id - ID market
* @param {Function} success - callback when have data
* @param {Function} error - error callback
* @param {object} config - config
* @param {Function} config.oneConnect - ONE connection
* @param {number} config.id - ID market
* @param {Function} config.success - callback when have data
* @param {Function} config.error - error callback
* @param {boolean} config.parseXML - parse XML data
* @returns {undefined} one connect
*/
const getMarket = (
oneConnection = defaultEmptyFunction,
const getMarket = ({
oneConnect = defaultEmptyFunction,
id,
success = defaultEmptyFunction,
error = defaultEmptyFunction
) => {
oneConnection(
ActionsMarket.MARKET_INFO,
[parseInt(id, 10)],
(err = undefined, market = {}) => {
if (err || !(market && market.MARKETPLACE)) {
error = defaultEmptyFunction,
parseXML = true,
}) =>
oneConnect({
action: ActionsMarket.MARKET_INFO,
parameters: [parseInt(id, 10)],
callback: (err = undefined, market = {}) => {
if (err || (parseXML && !(market && market.MARKETPLACE))) {
error()
return
}
success(market && market.MARKETPLACE)
}
)
}
success(parseXML ? market && market.MARKETPLACE : market)
},
fillHookResource: false,
parseXML,
})
/**
* Get Docker Hub Tags.
@ -254,16 +343,16 @@ const getDockerTags = (
const { id, page } = params
const { user, password } = userData
if (id && user && password) {
const connect = oneConnection(user, password)
const oneConnect = oneConnection(user, password)
const callbackNotfound = () => responseHttp(res, next, httpNotFoundRequest)
const callbackBadRequest = () => responseHttp(res, next, httpBadRequest)
const market = ({ MARKETPLACE_ID, NAME: MARKETAPP_NAME }) => {
Number.isInteger(parseInt(MARKETPLACE_ID)) &&
getMarket(
connect,
MARKETPLACE_ID,
({ MARKET_MAD }) => {
Number.isInteger(parseInt(MARKETPLACE_ID, 10)) &&
getMarket({
oneConnect,
id: MARKETPLACE_ID,
success: ({ MARKET_MAD }) => {
if (MARKET_MAD !== 'dockerhub') {
return callbackBadRequest()
}
@ -278,10 +367,10 @@ const getDockerTags = (
callbackNotfound
)
},
callbackNotfound
)
error: callbackNotfound,
})
}
getMarketApp(connect, id, market, callbackNotfound)
getMarketApp({ oneConnect, id, success: market, error: callbackNotfound })
} else {
responseHttp(res, next, httpNotFoundRequest)
}
@ -289,6 +378,7 @@ const getDockerTags = (
const functionRoutes = {
exportApp,
downloadApp,
importMarket,
getDockerTags,
}

View File

@ -17,11 +17,17 @@
const { Actions, Commands } = require('server/routes/api/marketapp/routes')
const {
exportApp,
downloadApp,
importMarket,
getDockerTags,
} = require('server/routes/api/marketapp/functions')
const { MARKETAPP_EXPORT, MARKETAPP_IMPORT, MARKETAPP_DOCKERTAGS } = Actions
const {
MARKETAPP_EXPORT,
MARKETAPP_DOWNLOAD,
MARKETAPP_VMIMPORT,
MARKETAPP_DOCKERTAGS,
} = Actions
module.exports = [
{
@ -29,7 +35,11 @@ module.exports = [
action: exportApp,
},
{
...Commands[MARKETAPP_IMPORT],
...Commands[MARKETAPP_DOWNLOAD],
action: downloadApp,
},
{
...Commands[MARKETAPP_VMIMPORT],
action: importMarket,
},
{

View File

@ -15,22 +15,23 @@
* ------------------------------------------------------------------------- */
const {
httpMethod,
from: fromData,
httpMethod,
} = require('../../../utils/constants/defaults')
const { POST, GET } = httpMethod
const { query, resource, postBody } = fromData
const basepath = '/marketapp'
const MARKETAPP_EXPORT = 'marketapp.export'
const MARKETAPP_IMPORT = 'marketapp.import'
const MARKETAPP_DOWNLOAD = 'marketapp.download'
const MARKETAPP_VMIMPORT = 'marketapp.vmimport'
const MARKETAPP_DOCKERTAGS = 'marketapp.dockertags'
const Actions = {
MARKETAPP_EXPORT,
MARKETAPP_IMPORT,
MARKETAPP_DOWNLOAD,
MARKETAPP_VMIMPORT,
MARKETAPP_DOCKERTAGS,
}
@ -68,8 +69,21 @@ module.exports = {
},
},
},
[MARKETAPP_IMPORT]: {
path: `${basepath}/import/:resource/:id`,
[MARKETAPP_DOWNLOAD]: {
path: `${basepath}/download/:id`,
httpMethod: GET,
auth: false,
params: {
id: {
from: resource,
},
token: {
from: query,
},
},
},
[MARKETAPP_VMIMPORT]: {
path: `${basepath}/vmimport/:vmId`,
httpMethod: POST,
auth: true,
params: {

View File

@ -454,10 +454,10 @@ const serviceAddSchedAction = (
params.id,
(node = {}, nodesLength, index) => {
const oneConnect = oneConnection(user, password)
oneConnect(
ActionVM.VM_SCHED_ADD,
[node.deploy_id, schedTemplate],
(err, value) => {
oneConnect({
action: ActionVM.VM_SCHED_ADD,
parameters: [node.deploy_id, schedTemplate],
callback: (err, value) => {
if (!err && !isNaN(value)) {
nodesUpdated.push(node.deploy_id)
}
@ -465,8 +465,8 @@ const serviceAddSchedAction = (
success(next, res, nodesUpdated)
}
},
false
)
fillHookResource: false,
})
},
(data = '') => error(next, res, data)
)
@ -518,10 +518,10 @@ const serviceUpdateSchedAction = (
id,
(node = {}, nodesLength, index) => {
const oneConnect = oneConnection(user, password)
oneConnect(
ActionVM.VM_SCHED_UPDATE,
[node.deploy_id, parseInt(idSched, 10), schedTemplate],
(err, value) => {
oneConnect({
action: ActionVM.VM_SCHED_UPDATE,
parameters: [node.deploy_id, parseInt(idSched, 10), schedTemplate],
callback: (err, value) => {
if (!err && !isNaN(value)) {
nodesUpdated.push(node.deploy_id)
}
@ -529,8 +529,8 @@ const serviceUpdateSchedAction = (
success(next, res, nodesUpdated)
}
},
false
)
fillHookResource: false,
})
},
(data = '') => error(next, res, data)
)
@ -579,10 +579,10 @@ const serviceDeleteSchedAction = (
id,
(node = {}, nodesLength, index) => {
const oneConnect = oneConnection(user, password)
oneConnect(
ActionVM.VM_SCHED_DELETE,
[node.deploy_id, parseInt(idSched, 10)],
(err, value) => {
oneConnect({
action: ActionVM.VM_SCHED_DELETE,
parameters: [node.deploy_id, parseInt(idSched, 10)],
callback: (err, value) => {
if (!err && !isNaN(value)) {
nodesUpdated.push(node.deploy_id)
}
@ -590,8 +590,8 @@ const serviceDeleteSchedAction = (
success(next, res, nodesUpdated)
}
},
false
)
fillHookResource: false,
})
},
(data = '') => error(next, res, data)
)

View File

@ -710,12 +710,16 @@ const deleteProvision = (
)
findFolder && removeFile(findFolder)
} else {
const connect = oneConnection(user, password)
connect(
Actions.DOCUMENT_UPDATE,
[parseInt(params.id, 10), sprintf(defaultErrorTemplate, lastLine), 1],
defaultEmptyFunction
)
const oneConnect = oneConnection(user, password)
oneConnect({
action: Actions.DOCUMENT_UPDATE,
parameters: [
parseInt(params.id, 10),
sprintf(defaultErrorTemplate, lastLine),
1,
],
callback: defaultEmptyFunction,
})
}
}
@ -803,14 +807,12 @@ const hostCommand = (
* @param {string} userData.user - username
* @param {string} userData.password - user password
* @param {number} userData.id - user id
* @param {Function} oneConnection - function of xmlrpc
*/
const createProvision = (
res = {},
next = defaultEmptyFunction,
params = {},
userData = {},
oneConnection = defaultEmptyFunction
userData = {}
) => {
const basePath = `${global.paths.CPI}/provision`
const relFile = `${basePath}/${relName}`

View File

@ -32,21 +32,21 @@ const httpInternalError = httpResponse(internalServerError, '', '')
/**
* Get information of opennebula group.
*
* @param {Function} connect - xmlrpc function
* @param {Function} oneConnect - xmlrpc function
* @param {string} idGroup - id of group
* @param {Function} callback - run function when have group information
*/
const getInfoGroup = (
connect = defaultEmptyFunction,
oneConnect = defaultEmptyFunction,
idGroup,
callback = defaultEmptyFunction
) => {
connect(
ActionsGroup.GROUP_INFO,
[parseInt(idGroup, 10), false],
oneConnect({
action: ActionsGroup.GROUP_INFO,
parameters: [parseInt(idGroup, 10), false],
callback,
false
)
fillHookResource: false,
})
}
/**
@ -88,14 +88,14 @@ const getViews = (
global.paths.SUNSTONE_VIEWS &&
global.paths.SUNSTONE_PATH
) {
const connect = oneConnection(user, password)
connect(
ActionsUser.USER_INFO,
[-1, false],
(err = {}, dataUser = {}) => {
const oneConnect = oneConnection(user, password)
oneConnect({
action: ActionsUser.USER_INFO,
parameters: [-1, false],
callback: (err = {}, dataUser = {}) => {
if (dataUser && dataUser.USER && dataUser.USER.GID) {
getInfoGroup(
connect,
oneConnect,
dataUser.USER.GID,
(err = {}, vmgroupData = {}) => {
if (vmgroupData && vmgroupData.GROUP && vmgroupData.GROUP.NAME) {
@ -143,8 +143,8 @@ const getViews = (
responseHttp(res, next, httpInternalError)
}
},
false
)
fillHookResource: false,
})
} else {
responseHttp(res, next, httpInternalError)
}

View File

@ -1,17 +0,0 @@
/* ------------------------------------------------------------------------- *
* Copyright 2002-2021, OpenNebula Project, OpenNebula Systems *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain *
* a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
module.exports = 'system'

View File

@ -76,14 +76,17 @@ const getConfig = (
return
}
const connect = oneConnection(
const oneConnect = oneConnection(
`${username}:${username}`,
tokenWithServerAdmin.token
)
connect(
ActionSystem.SYSTEM_CONFIG,
getDefaultParamsOfOpennebulaCommand(ActionSystem.SYSTEM_CONFIG, GET),
(err, value) => {
oneConnect({
action: ActionSystem.SYSTEM_CONFIG,
parameters: getDefaultParamsOfOpennebulaCommand(
ActionSystem.SYSTEM_CONFIG,
GET
),
callback: (err, value) => {
if (err) {
res.locals.httpCode = httpResponse(internalServerError, '', '')
@ -100,8 +103,8 @@ const getConfig = (
)
res.locals.httpCode = httpResponse(ok, filterData)
next()
}
)
},
})
}
module.exports = {

View File

@ -15,9 +15,8 @@
* ------------------------------------------------------------------------- */
const { httpMethod } = require('server/utils/constants/defaults')
const SYSTEM = require('server/routes/api/system/basepath')
const basepath = `/${SYSTEM}`
const basepath = '/system'
const { GET } = httpMethod
const SYSTEM_CONFIG = 'system.config'

View File

@ -239,7 +239,6 @@ const importHost = (res = {}, next = defaultEmptyFunction, params = {}) => {
* @param {Function} next - express stepper
* @param {object} params - params of http request
* @param {object} userData - user Data
* @param {Function} oneConnection - xmlrpc function
* @param {'template'|'images'|'datastores'|'networks'} type - type resource
*/
const importVobject = (
@ -247,7 +246,6 @@ const importVobject = (
next = defaultEmptyFunction,
params = {},
userData = {},
oneConnection = defaultEmptyFunction,
type
) => {
const httpReturn = (httpCode) => {

View File

@ -1,17 +0,0 @@
/* ------------------------------------------------------------------------- *
* Copyright 2002-2021, OpenNebula Project, OpenNebula Systems *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain *
* a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
module.exports = 'vm'

View File

@ -18,9 +18,8 @@ const {
httpMethod,
from: fromData,
} = require('server/utils/constants/defaults')
const VM = require('server/routes/api/vm/basepath')
const basepath = `/${VM}`
const basepath = '/vm'
const { POST } = httpMethod
const { resource, postBody } = fromData

View File

@ -1,17 +0,0 @@
/* ------------------------------------------------------------------------- *
* Copyright 2002-2021, OpenNebula Project, OpenNebula Systems *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain *
* a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
module.exports = 'zendesk'

View File

@ -18,10 +18,9 @@ const {
httpMethod,
from: fromData,
} = require('server/utils/constants/defaults')
const ZENDESK = require('server/routes/api/zendesk/basepath')
const { POST, GET, PUT } = httpMethod
const basepath = `/${ZENDESK}`
const basepath = '/zendesk'
const { resource, postBody } = fromData
const ZENDESK_LOGIN = 'zendesk.login'

View File

@ -48,6 +48,7 @@ const defaults = {
* @returns {undefined} undefined data
*/
defaultEmptyFunction: () => undefined,
defaultTmpPath: '/tmp',
defaultErrorTemplate: 'ERROR_FIREEDGE="%1$s"',
defaultSessionExpiration: 180,
defaultSessionLimitExpiration: 30,
@ -91,6 +92,7 @@ const defaults = {
query: 'QUERY',
postBody: 'POST_BODY',
},
defaultDownloader: 'remotes/datastore/downloader.sh',
defaultOpennebulaZones: [
{
id: '0',

View File

@ -50,10 +50,14 @@ onmessage = function (ev = {}) {
if (globalState && user && password && rpc && command) {
pass = false
global.paths = globalState
const connect = opennebulaConnect(user, password, rpc)
connect(command, paramsCommand, (err, value) => {
pass = true
returnDataWorker({ err, value })
const oneConnect = opennebulaConnect(user, password, rpc)
oneConnect({
action: command,
parameters: paramsCommand,
callback: (err, value) => {
pass = true
returnDataWorker({ err, value })
},
})
}
}

View File

@ -17,7 +17,7 @@
// eslint-disable-next-line node/no-deprecated-api
const { parse } = require('url')
const rpc = require('xmlrpc')
const parser = require('fast-xml-parser')
const { parse: xmlParse } = require('fast-xml-parser')
const { Map } = require('immutable')
const { sprintf } = require('sprintf-js')
const { global } = require('window-or-global')
@ -63,7 +63,7 @@ const stringWrappedBrakets = /^\[.*\]$/g
const brakets = /(^\[)|(\]$)/g
/**
* Parse xml to JSON.
* Parse XML to JSON.
*
* @param {string} xml - xml data in string
* @param {Function} callback - callback data
@ -71,7 +71,7 @@ const brakets = /(^\[)|(\]$)/g
const xml2json = (xml = '', callback = defaultEmptyFunction) => {
let rtn = []
try {
const jsonObj = parser.parse(xml, defaultConfigParseXML)
const jsonObj = xmlParse(xml, defaultConfigParseXML)
rtn = [null, jsonObj]
} catch (error) {
rtn = [error]
@ -135,12 +135,13 @@ const opennebulaConnect = (username = '', password = '', zoneURL = '') => {
xmlClient = rpc.createClient(zoneURL)
}
if (xmlClient && xmlClient.methodCall) {
rtn = (
rtn = ({
action = '',
parameters = [],
callback = () => undefined,
fillHookResource = true
) => {
callback = defaultEmptyFunction,
fillHookResource = true,
parseXML = true,
}) => {
if (action && parameters && Array.isArray(parameters) && callback) {
// user config
const appConfig = getFireedgeConfig()
@ -150,40 +151,41 @@ const opennebulaConnect = (username = '', password = '', zoneURL = '') => {
`${namespace}.${action}`,
xmlParameters,
(err, value) => {
if (err && err.body) {
xml2json(err.body, (error, result) => {
if (error) {
callback(error, undefined) // error parse xml
const success = (data) => {
fillHookResource &&
fillResourceforHookConnection(username, action, parameters)
callback(undefined, data)
}
return
}
if (
result &&
result.methodResponse &&
result.methodResponse.fault &&
result.methodResponse.fault.value &&
result.methodResponse.fault.value.struct &&
result.methodResponse.fault.value.struct.member &&
Array.isArray(
result.methodResponse.fault.value.struct.member
)
) {
const errorData =
result.methodResponse.fault.value.struct.member.find(
(element) => element.value && element.value.string
)
if (errorData) {
// success
fillHookResource &&
fillResourceforHookConnection(
username,
action,
parameters
if (err && err.body) {
parseXML
? xml2json(err.body, (error, result) => {
if (error) {
callback(error, undefined) // error parse xml
return
}
if (
result &&
result.methodResponse &&
result.methodResponse.fault &&
result.methodResponse.fault.value &&
result.methodResponse.fault.value.struct &&
result.methodResponse.fault.value.struct.member &&
Array.isArray(
result.methodResponse.fault.value.struct.member
)
callback(undefined, errorData.value.string)
}
}
})
) {
const errorData =
result.methodResponse.fault.value.struct.member.find(
(element) => element.value && element.value.string
)
if (errorData) {
success(errorData.value.string)
}
}
})
: success(err.body)
return
} else if (value && value[0] && value[1]) {
@ -194,26 +196,20 @@ const opennebulaConnect = (username = '', password = '', zoneURL = '') => {
messageCall = value
}
if (typeof messageCall === 'string' && messageCall.length > 0) {
xml2json(messageCall, (error, result) => {
if (error) {
callback(error, undefined) // error parse xml
parseXML
? xml2json(messageCall, (error, result) => {
if (error) {
callback(error, undefined) // error parse xml
return
}
// success
fillHookResource &&
fillResourceforHookConnection(
username,
action,
parameters
)
callback(
undefined,
error === null && !String(result)
? JSON.stringify(messageCall)
: result
)
})
return
}
success(
error === null && !String(result)
? JSON.stringify(messageCall)
: result
)
})
: success(messageCall)
return
}

View File

@ -67,6 +67,7 @@ const {
defaultSunstoneConfig,
defaultProvisionPath,
defaultProvisionConfig,
defaultDownloader,
defaultEmptyFunction,
} = defaults
const { internalServerError } = httpCodes
@ -522,6 +523,9 @@ const genPathResources = () => {
if (!global.paths.FIREEDGE_LOG) {
global.paths.FIREEDGE_LOG = `${LOG_LOCATION}/${defaultLogFilename}`
}
if (!global.paths.DOWNLOADER) {
global.paths.DOWNLOADER = `${VAR_LOCATION}/${defaultDownloader}`
}
if (!global.paths.SUNSTONE_AUTH_PATH) {
global.paths.SUNSTONE_AUTH_PATH = `${VAR_LOCATION}/.one/${defaultSunstoneAuth}`
}