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

Revert "F #5749: Creation ticket VMRC on FireEdge (#1848)"

This reverts commit 952cecb74d8091f1e479a73edd9adfadcf730f3e.
This commit is contained in:
Tino Vazquez 2022-03-23 11:15:50 +01:00
parent 1fe1e72c7e
commit dbbce59527
No known key found for this signature in database
GPG Key ID: 14201E424D02047E
9 changed files with 164 additions and 230 deletions

View File

@ -17,7 +17,7 @@
const { Validator } = require('jsonschema')
const { role, service, action } = require('server/routes/api/oneflow/schemas')
const {
oneFlowConnection,
oneFlowConection,
returnSchemaError,
} = require('server/routes/api/oneflow/utils')
const { defaults, httpCodes } = require('server/utils/constants')
@ -91,13 +91,13 @@ const serviceTemplate = (
if (params && params.id) {
config.path = '/service_template/{0}'
config.request = params.id
oneFlowConnection(
oneFlowConection(
config,
(data) => success(next, res, data),
(data) => error(next, res, data)
)
} else {
oneFlowConnection(
oneFlowConection(
config,
(data) => success(next, res, data),
(data) => error(next, res, data)
@ -130,7 +130,7 @@ const serviceTemplateDelete = (
password,
request: params.id,
}
oneFlowConnection(
oneFlowConection(
config,
(data) => success(next, res, data),
(data) => error(next, res, data)
@ -173,7 +173,7 @@ const serviceTemplateCreate = (
password,
post: template,
}
oneFlowConnection(
oneFlowConection(
config,
(data) => success(next, res, data),
(data) => error(next, res, data)
@ -224,7 +224,7 @@ const serviceTemplateUpdate = (
request: params.id,
post: template,
}
oneFlowConnection(
oneFlowConection(
config,
(data) => success(next, res, data),
(data) => error(next, res, data)
@ -275,7 +275,7 @@ const serviceTemplateAction = (
request: params.id,
post: template,
}
oneFlowConnection(
oneFlowConection(
config,
(data) => success(next, res, data),
(data) => error(next, res, data)

View File

@ -13,43 +13,32 @@
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
const btoa = require('btoa')
const https = require('https')
// eslint-disable-next-line node/no-deprecated-api
const { parse } = require('url')
const { request: axios } = require('axios')
const { defaults, httpCodes } = require('server/utils/constants')
const {
httpResponse,
executeCommand,
executeCommandAsync,
publish,
getSunstoneAuth,
} = require('server/utils/server')
const {
consoleParseToString,
consoleParseToJSON,
} = require('server/utils/opennebula')
const { createTokenServerAdmin } = require('server/routes/api/auth/utils')
const { Actions: ActionHost } = require('server/utils/constants/commands/host')
const { Actions: ActionVM } = require('server/utils/constants/commands/vm')
const {
resourceFromData,
resources,
params: commandParams,
} = require('server/routes/api/vcenter/command-flags')
const { getSunstoneConfig } = require('server/utils/yml')
const {
httpMethod,
defaultEmptyFunction,
defaultCommandVcenter,
defaultRegexpStartJSON,
defaultRegexpEndJSON,
defaultRegexpSplitLine,
} = defaults
const { POST } = httpMethod
const { ok, internalServerError, badRequest, accepted } = httpCodes
const { LIST, IMPORT } = resourceFromData
const appConfig = getSunstoneConfig()
@ -61,7 +50,6 @@ const regexExclude = [
/^\u001b\[.*?m\u001b\[.*?m# vCenter.*/i,
]
const regexHeader = /^IMID,.*/i
const regexGetVcenterId = /-(?<id>.*)_/s
const validObjects = Object.values(resources)
@ -385,194 +373,11 @@ const importVobject = (
httpReturn(accepted)
}
/**
* Axios request.
*
* @param {object} params - Axios params
* @param {Function} callback - Success Axios callback
* @param {Function} error - Error Axios callback
*/
const request = (
params = {},
callback = defaultEmptyFunction,
error = defaultEmptyFunction
) => {
const defaultsProperties = {
method: POST,
httpsAgent: new https.Agent({
rejectUnauthorized: false,
}),
validateStatus: (status) => status,
}
axios({
...defaultsProperties,
...params,
})
.then((response) => {
if (response && response.statusText) {
if (response.status >= 200 && response.status < 400) {
if (response.data) {
return response.data
}
}
throw Error(response.data)
} else if (response.data) {
throw Error(response.data)
}
})
.then((data) => {
callback(data)
})
.catch((e) => {
error(e)
})
}
/**
* Get system config.
*
* @param {object} res - http response
* @param {Function} next - express stepper
* @param {object} params - params of http request
* @param {object} userData - user of http request
* @param {function(string, string): Function} oneConnection - One Connection
*/
const getToken = (
res = {},
next = defaultEmptyFunction,
params = {},
userData = {},
oneConnection = defaultEmptyFunction
) => {
const { username, key, iv } = getSunstoneAuth()
const { id } = params
const responser = (code = badRequest, data = '') => {
res.locals.httpCode = httpResponse(code, data, '')
next()
}
if (!(username && key && iv) || !Number.isInteger(parseInt(id, 10))) {
responser()
return
}
const tokenWithServerAdmin = createTokenServerAdmin({
serverAdmin: username,
username,
key,
iv,
})
if (!tokenWithServerAdmin.token) {
responser()
return
}
const connect = oneConnection(
`${username}:${username}`,
tokenWithServerAdmin.token
)
connect(ActionVM.VM_INFO, [parseInt(id, 10), true], (err, vminfo) => {
if (
!(
vminfo &&
vminfo.VM &&
vminfo.VM.DEPLOY_ID &&
vminfo.VM.HISTORY_RECORDS &&
vminfo.VM.HISTORY_RECORDS.HISTORY
) ||
err
) {
responser(internalServerError)
}
const history = vminfo.VM.HISTORY_RECORDS.HISTORY
const arrayHistory = Array.isArray(history) ? history : [history]
const hostID = parseInt(
arrayHistory.reduce(
(max, record) => (record.SEQ > max.SEQ ? record : max),
arrayHistory[0]
).HID,
10
)
const vmid = vminfo.VM.DEPLOY_ID.match(regexGetVcenterId).groups.id
connect(ActionHost.HOST_INFO, [hostID, true], (err, hostinfo) => {
if (
!(
hostinfo &&
hostinfo.HOST &&
hostinfo.HOST.TEMPLATE &&
hostinfo.HOST.TEMPLATE.VCENTER_HOST &&
hostinfo.HOST.TEMPLATE.VCENTER_USER &&
hostinfo.HOST.TEMPLATE.VCENTER_PASSWORD
) ||
err
) {
responser(internalServerError)
return
}
const { VCENTER_HOST, VCENTER_USER, VCENTER_PASSWORD } =
hostinfo.HOST.TEMPLATE
const responseInternalServer = () => {
responser(internalServerError)
}
const genToken = (data) => {
request(
{
url: `https://${VCENTER_HOST}/api/vcenter/vm/vm-${vmid}/console/tickets`,
headers: {
'Content-Type': 'application/json',
'vmware-api-session-id': data,
},
data: JSON.stringify({ type: 'WEBMKS' }),
},
(success) => {
const { ticket } = success
const { protocol, hostname, port, path } = parse(ticket)
const httpProtocol = protocol === 'wss:' ? 'https' : 'http'
const esxUrl = `${httpProtocol}://${hostname}:${port}`
const token = path.replace('/ticket/', '')
global.vcenterToken = { [token]: esxUrl }
responser(ok, {
ticket: token,
})
},
responseInternalServer
)
}
request(
{
url: `https://${VCENTER_HOST}/api/session`,
headers: {
Authorization: `Basic ${btoa(
`${VCENTER_USER}:${VCENTER_PASSWORD}`
)}`,
},
},
genToken,
responseInternalServer
)
})
})
}
const functionRoutes = {
list,
listAll,
cleartags,
importHost,
importVobject,
getToken,
}
module.exports = functionRoutes

View File

@ -21,14 +21,12 @@ const {
listAll,
cleartags,
importHost,
getToken,
} = require('server/routes/api/vcenter/functions')
const { resources } = require('server/routes/api/vcenter/command-flags')
const { TEMPLATES, DATASTORES, NETWORKS, IMAGES } = resources
const {
VCENTER_TOKEN,
VCENTER_CLEAR_TAGS,
VCENTER_IMPORT_HOSTS,
VCENTER_IMPORT_DATASTORES,
@ -40,10 +38,6 @@ const {
} = Actions
module.exports = [
{
...Commands[VCENTER_TOKEN],
action: getToken,
},
{
...Commands[VCENTER_CLEAR_TAGS],
action: cleartags,

View File

@ -23,7 +23,6 @@ const basepath = '/vcenter'
const { POST, GET } = httpMethod
const { resource, postBody, query } = fromData
const VCENTER_TOKEN = 'vcenter.token'
const VCENTER_CLEAR_TAGS = 'vcenter.cleartags'
const VCENTER_IMPORT_HOSTS = 'vcenter.importhosts'
const VCENTER_IMPORT_DATASTORES = 'vcenter.importdatastores'
@ -33,7 +32,6 @@ const VCENTER_IMPORT_IMAGES = 'vcenter.importimages'
const VCENTER_LIST_ALL = 'vcenter.listall'
const VCENTER_LIST = 'vcenter.list'
const Actions = {
VCENTER_TOKEN,
VCENTER_CLEAR_TAGS,
VCENTER_IMPORT_HOSTS,
VCENTER_IMPORT_TEMPLATES,
@ -47,16 +45,6 @@ const Actions = {
module.exports = {
Actions,
Commands: {
[VCENTER_TOKEN]: {
path: `${basepath}/token/:id`,
httpMethod: GET,
auth: true,
params: {
id: {
from: resource,
},
},
},
[VCENTER_CLEAR_TAGS]: {
path: `${basepath}/cleartags/:id`,
httpMethod: POST,

View File

@ -17,6 +17,7 @@
// eslint-disable-next-line node/no-deprecated-api
const { parse } = require('url')
const { createProxyMiddleware } = require('http-proxy-middleware')
const { readFileSync } = require('fs-extra')
const { getFireedgeConfig } = require('server/utils/yml')
const { messageTerminal } = require('server/utils/general')
const {
@ -54,10 +55,14 @@ const vmrcProxy = createProxyMiddleware(endpointVmrc, {
if (parseURL && parseURL.pathname) {
const ticket = parseURL.pathname.split('/')[3]
writeInLogger(ticket, 'path to vmrc token: %s')
if (global && global.vcenterToken && global.vcenterToken[ticket]) {
return global.vcenterToken[ticket]
} else {
writeInLogger(ticket, 'Non-existent token: %s')
try {
const esxi = readFileSync(
`${global.paths.VMRC_TOKENS || ''}/${ticket}`
).toString()
return esxi
} catch (error) {
writeInLogger(ticket, 'Error to read vmrc token file: %s')
}
}
}

View File

@ -21,6 +21,7 @@ include OpenNebulaJSON
require 'sunstone_vnc'
require 'sunstone_guac'
require 'sunstone_vmrc'
require 'sunstone_vm_helper'
require 'OpenNebulaAddons'
require 'OpenNebulaJSON/JSONUtils'
@ -336,6 +337,33 @@ class SunstoneServer < CloudServer
return guac.proxy(resource, type_connection, client)
end
########################################################################
# VMRC
########################################################################
def startvmrc(id, vmrc, _client=nil)
resource = retrieve_resource("vm", id)
if OpenNebula.is_error?(resource)
return [404, resource.to_json]
end
vm_pool = VirtualMachinePool.new(@client, -1)
user_pool = UserPool.new(@client)
rc = user_pool.info
if OpenNebula.is_error?(rc)
puts rc.message
exit -1
end
rc = vm_pool.info
if OpenNebula.is_error?(rc)
puts rc.message
exit -1
end
client = _client.nil? ? @client : _client
return vmrc.proxy(resource, client)
end
########################################################################
# Accounting & Monitoring
########################################################################

View File

@ -0,0 +1,101 @@
# -------------------------------------------------------------------------- #
# 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. #
#--------------------------------------------------------------------------- #
#----------------------------------------------------------------------------#
# This class provides support for launching and stopping a vmrc proxy server #
#----------------------------------------------------------------------------#
require 'rubygems'
require 'json'
require 'opennebula'
require 'base64'
require 'openssl'
require 'vcenter_driver'
require 'fileutils'
require 'sunstone_remotes'
if !ONE_LOCATION
VMRC_TICKETS = '/var/lib/one/sunstone_vmrc_tokens/'
else
VMRC_TICKETS = ONE_LOCATION + '/var/sunstone_vmrc_tokens/'
end
FileUtils.mkdir_p VMRC_TICKETS
# Class for necessary VMRC ticket creation
class SunstoneVMRC < SunstoneRemoteConnections
attr_reader :proxy_port
def initialize(logger, options = {})
super
end
def proxy(vm_resource, client = nil)
# Check configurations and VM attributes
unless allowed_console_states.include?(vm_resource['LCM_STATE'])
error_message = "Wrong state (#{vm_resource['LCM_STATE']}) to
open a VMRC session"
return error(400, error_message)
end
unless vm_resource['USER_TEMPLATE/HYPERVISOR'] == 'vcenter'
return error(400, 'VMRC Connection is only for vcenter hipervisor')
end
unless vm_resource['MONITORING/VCENTER_ESX_HOST']
error_message = 'Could not determine the vCenter ESX host where
the VM is running. Wait till the VCENTER_ESX_HOST attribute is
retrieved once the host has been monitored'
return error(400, error_message)
end
vm_id = vm_resource['ID']
one_vm = VCenterDriver::VIHelper.one_item(
OpenNebula::VirtualMachine,
vm_id
)
vm_ref = one_vm['DEPLOY_ID']
host_id = one_vm['HISTORY_RECORDS/HISTORY[last()]/HID'].to_i
vi_client = VCenterDriver::VIClient.new_from_host(host_id, client)
vm = VCenterDriver::VirtualMachine.new(vi_client, vm_ref, vm_id)
parameters = vm.html_console_parameters
data = {
:host => parameters[:host],
:port => parameters[:port],
:ticket => parameters[:ticket]
}
file = File.open(
VMRC_TICKETS +
VCenterDriver::FileHelper.sanitize(data[:ticket]),
'w'
)
file.write('https://' + data[:host] + ':' + data[:port].to_s)
file.close
info = SunstoneVMHelper.get_remote_info(vm_resource)
encode_info = Base64.encode64(info.to_json)
[200, { :data => data, :info => encode_info }.to_json]
end
end

View File

@ -629,14 +629,14 @@ define(function(require) {
"vmrc" : function(params) {
var callback = params.success;
var callback_error = params.error;
var vm_id = params.data.id;
var id = params.data.id;
var resource = RESOURCE;
var request = OpenNebulaHelper.request(resource, null, params.data);
$.ajax({
url: Config.publicFireedgeEndpoint + "/fireedge/api/vcenter/token/" + vm_id,
type: "GET",
headers: {"Authorization": fireedge_token},
url: "vm/" + id + "/startvmrc",
type: "POST",
dataType: "json",
success: function(response) {
return callback ? callback(request, response) : null;
},

View File

@ -281,9 +281,13 @@ $vnc = SunstoneVNC.new($conf, logger)
#init Guacamole proxy
$guac = SunstoneGuac.new(logger)
#init VMRC proxy
$vmrc = SunstoneVMRC.new(logger)
configure do
set :run, false
set :vnc, $vnc
set :vmrc, $vmrc
set :erb, :trim => '-'
end
@ -1206,6 +1210,15 @@ post '/vm/:id/guac/:type' do
@SunstoneServer.startguac(vm_id, type_connection, $guac, user)
end
##############################################################################
# Start VMRC Session for a target VM
##############################################################################
post '/vm/:id/startvmrc' do
vm_id = params[:id]
serveradmin_client = $cloud_auth.client(nil, session[:active_zone_endpoint])
@SunstoneServer.startvmrc(vm_id, $vmrc, serveradmin_client)
end
##############################################################################
# Perform an action on a Resource
##############################################################################