1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-10 01:17:40 +03:00

F #1262: Support for virt-viewer links (#4626)

This commit is contained in:
Sergio Betanzos 2020-04-29 15:29:34 +02:00 committed by GitHub
parent 59426dd8fd
commit 90ccd68a36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 280 additions and 128 deletions

View File

@ -508,8 +508,7 @@ define(function(require) {
var resource = RESOURCE;
var method = startstop;
var action = OpenNebulaHelper.action(method);
var request = OpenNebulaHelper.request(resource, method, id);
var request = OpenNebulaHelper.request(resource, method, params.data);
$.ajax({
url: "vm/" + id + "/startvnc",
type: "POST",
@ -677,8 +676,12 @@ define(function(require) {
"isNICAttachSupported": isNICAttachSupported,
"isVNCSupported": isVNCSupported,
"isRDPSupported": isRDPSupported,
"buttonRDP": buttonRDP,
"isSPICESupported": isSPICESupported,
"isWFileSupported": isWFileSupported,
"buttonVnc": buttonVnc,
"buttonSpice": buttonSpice,
"buttonWFile": buttonWFile,
"buttonRDP": buttonRDP,
"getName": function(id){
return OpenNebulaAction.getName(id, RESOURCE);
}
@ -899,6 +902,18 @@ define(function(require) {
return rtn;
}
function isWFileSupported(element) {
// spice/vnc is assumed to be supported
var history = retrieveLastHistoryRecord(element);
return (history)
? {
hostname: history.HOSTNAME,
type: element.TEMPLATE.GRAPHICS.TYPE.toLowerCase(),
port: element.TEMPLATE.GRAPHICS.PORT || "5901"
}
: false;
}
// returns true if the RDP button should be enabled
function isRDPSupported(element) {
var hasRdp = false;
@ -932,6 +947,22 @@ define(function(require) {
return activated;
}
function buttonVnc(id = "") {
return '<button class="vnc remote_vm" data-id="' + id + '">\
<i class="fas fa-desktop"></i></button>';
}
function buttonSpice(id = "") {
return '<button class="spice remote_vm" data-id="' + id + '">\
<i class="fas fa-desktop"></i></button>';
}
function buttonWFile(id = "", data = {}) {
return '<button class="w_file remote_vm" data-id="' + id + '"\
data-type="' + data.type + '" data-port="' + data.port + '" data-hostname="' + data.hostname + '">\
<i class="fas fa-external-link-alt"></i></button>';
}
function buttonRDP(ip = "", vm = {}) {
var username, password;
@ -943,7 +974,7 @@ define(function(require) {
(propUpperCase === "PASSWORD") && (password = context[prop]);
}
}
var button = '<button class="rdp" data-name="' + vm.NAME + '" data-ip="' + ip + '"';
var button = '<button class="rdp remote_vm" data-name="' + vm.NAME + '" data-ip="' + ip + '"';
username && (button += ' data-username="' + username + '"');
password && (button += ' data-password="' + password + '"');
button += '><i class="fab fa-windows"></i></button>';

View File

@ -231,8 +231,8 @@ define(function(require) {
var name = vm_info ? vm_info.VM.NAME : "";
var uname = vm_info ? vm_info.VM.UNAME : "";
var gname = vm_info ? vm_info.VM.GNAME : "";
var ips = "";
var actions = "";
var ips = "", actions = "";
if (that.cache && that.cache.data && Array.isArray(that.cache.data)) {
$.each(that.cache.data, function(_, data){
if (data.VM && data.VM.ID === id) {
@ -243,14 +243,25 @@ define(function(require) {
}
ips = OpenNebulaVM.ipsStr(data.VM);
var wFile = false, rdp = false;
if (OpenNebulaVM.isVNCSupported(data.VM)) {
actions += '<button class="vnc" data-id="' + id + '"><i class="fas fa-desktop"></i></button>';
actions += OpenNebulaVM.buttonVnc(id);
wFile = OpenNebulaVM.isWFileSupported(data.VM);
}
else if (OpenNebulaVM.isSPICESupported(data.VM)) {
actions += OpenNebulaVM.buttonSpice(id);
wFile = OpenNebulaVM.isWFileSupported(data.VM);
}
if (wFile) {
actions += OpenNebulaVM.buttonWFile(id, wFile);
}
rdp = OpenNebulaVM.isRDPSupported(data.VM);
if (rdp) {
actions += OpenNebulaVM.buttonRDP(rdp.IP, data.VM)
actions += OpenNebulaVM.buttonRDP(rdp.IP, data.VM);
}
}
})
@ -288,26 +299,9 @@ define(function(require) {
}
function _roleSetup(context, role_index) {
var that = this;
if(this.servicePanel) {
var role = this.element.TEMPLATE.BODY.roles[role_index];
$(".spice", context).off("click");
$(".spice", context).on("click", function() {
var vmId = $(this).attr('vm_id');
if (!Spice.lockStatus()) {
Spice.lock();
Sunstone.runAction("VM.startspice_action", vmId);
} else {that.cache = OpenNebulaAction.cache("VM");
Notifier.notifyError(Locale.tr("SPICE Connection in progress"));
}
return false;
});
this.serviceroleVMsDataTable = new DomDataTable(
'datatable_vms_'+this.panelId+'_'+role.name,
{
@ -333,13 +327,42 @@ define(function(require) {
$('div#role_vms_actions', context)
);
$(".spice", context).off("click");
$(".spice", context).on("click", function() {
var data = $(this).data();
if (!Spice.lockStatus() && data.id) {
Spice.lock();
Sunstone.runAction("VM.startspice_action", String(data.id));
} else {
Notifier.notifyError(Locale.tr("SPICE Connection in progress"));
}
return false;
});
$(".w_file", context).off("click");
$(".w_file", context).on("click", function() {
var data = $(this).data();
(data.id && data.hostname && data.type && data.port)
? Sunstone.runAction(
"VM.save_virt_viewer_action",
data.id,
{ hostname: data.hostname, type: data.type, port: data.port }
)
: Notifier.notifyError(Locale.tr("Data for virt-viewer file isn't correct"));
return false;
});
$(".vnc", context).off("click");
$(".vnc", context).on("click", function() {
var vmId = $(this).data("id");
var data = $(this).data();
if (!Vnc.lockStatus()) {
if (!Vnc.lockStatus() && data.id) {
Vnc.lock();
Sunstone.runAction("VM.startvnc_action", String(vmId));
Sunstone.runAction("VM.startvnc_action", String(data.id));
} else {
Notifier.notifyError(Locale.tr("VNC Connection in progress"));
}
@ -350,10 +373,12 @@ define(function(require) {
$(".rdp", context).off("click");
$(".rdp", context).on("click", function() {
var data = $(this).data();
if (data.ip && data.name) {
Sunstone.runAction("VM.save_rdp", data);
}
return false;
(data.ip && data.name)
? Sunstone.runAction("VM.save_rdp", data)
: Notifier.notifyError(Locale.tr("This VM needs a nic with rdp active"));
return false;
});
}

View File

@ -23,7 +23,7 @@ define(function(require) {
var CommonActions = require('utils/common-actions');
var Vnc = require('utils/vnc');
var Spice = require('utils/spice');
var Rdp = require('utils/rdp');
var Files = require('utils/files');
var TAB_ID = require('./tabId');
var CREATE_DIALOG_ID = require('./form-panels/create/formPanelId');
@ -179,9 +179,9 @@ define(function(require) {
if (args && args.ip && args.name) {
var credentials = {};
args.username && (credentials["USERNAME"] = args.username);
args.password && (credentials["PASSWORD"] = args.password);
Rdp.downloadFile(args.ip, args.name, credentials);
args.username && (credentials["username"] = args.username);
args.password && (credentials["password"] = args.password);
Files.downloadRdpFile(args.ip, args.name, credentials);
}
else if (vm && vm.NAME && vm.TEMPLATE && vm.TEMPLATE.NIC) {
var name = vm.NAME;
@ -208,14 +208,44 @@ define(function(require) {
}
}
nic && Rdp.downloadFile(ip, name, credentials);
nic && Files.downloadRdpFile(ip, name, credentials);
} else {
Notifier.notifyError(Locale.tr("RDP file error"));
Notifier.notifyError(Locale.tr("Data for rdp file isn't correct"));
return false;
}
}
},
"VM.save_virt_viewer" : {
type: "custom",
call: function() {
var vm = Sunstone.getElementRightInfo(TAB_ID) || {};
var wDataFile = OpenNebulaVM.isWFileSupported(vm);
if (vm && vm.ID && wDataFile) {
Sunstone.runAction("VM.save_virt_viewer_action", vm.ID, wDataFile);
} else {
Notifier.notifyError(Locale.tr("Data for virt-viewer file isn't correct"));
return false;
}
}
},
"VM.save_virt_viewer_action" : {
type: "single",
call: OpenNebulaVM.vnc,
callback: function(_, response) {
_.request && $.each(_.request.data, function(_, vm) {
var hostname = vm.extra_param.hostname;
var type = vm.extra_param.type;
var port = vm.extra_param.port;
(hostname && type && port)
? Files.downloadWFile(response, hostname, type, port)
: Notifier.notifyError(Locale.tr("Data for virt-viewer file isn't correct"));
});
},
error: function(req, resp) {
Notifier.onError(req, resp);
},
},
"VM.startvnc" : {
type: "custom",
call: function() {

View File

@ -206,6 +206,12 @@ define(function(require) {
layout: "vmsremote_buttons",
custom_classes: "only-sunstone-info spice-sunstone-info"
},
"VM.save_virt_viewer" : {
type: "action",
text: Locale.tr("VIRT-VIEWER FILE"),
layout: "vmsremote_buttons",
custom_classes: "only-sunstone-info vv-sunstone-info"
},
"VM.save_rdp" : {
type: "action",
text: Locale.tr("RDP"),

View File

@ -32,7 +32,6 @@ define(function(require) {
var Notifier = require('utils/notifier');
var DashboardUtils = require('utils/dashboard');
var SearchDropdown = require('hbs!./datatable/search');
var Rdp = require('utils/rdp');
var TemplateUtils = require('utils/template-utils');
/*
@ -173,22 +172,38 @@ define(function(require) {
TabDataTable.prototype.initialize.call(this, opts);
//download file RDP
$('#' + this.dataTableId).on("click", '.rdp', function(e){
e.stopPropagation();
//download virt-viewer file
$('#' + this.dataTableId).on("click", '.w_file', function(){
var data = $(this).data();
if (data.ip && data.name) {
Sunstone.runAction("VM.save_rdp", data);
}
(data.id && data.hostname && data.type && data.port)
? Sunstone.runAction(
"VM.save_virt_viewer_action",
data.id,
{ hostname: data.hostname, type: data.type, port: data.port }
)
: Notifier.notifyError(Locale.tr("Data for virt-viewer file isn't correct"));
return false;
});
//download RDP file
$('#' + this.dataTableId).on("click", '.rdp', function() {
var data = $(this).data();
(data.ip && data.name)
? Sunstone.runAction("VM.save_rdp", data)
: Notifier.notifyError(Locale.tr("This VM needs a nic with rdp active"));
return false;
});
$('#' + this.dataTableId).on("click", '.vnc', function() {
var vmId = $(this).attr('vm_id');
var data = $(this).data();
if (!Vnc.lockStatus()) {
Vnc.lock();
Sunstone.runAction("VM.startvnc_action", vmId);
Sunstone.runAction("VM.startvnc_action", data.id);
} else {
Notifier.notifyError(Locale.tr("VNC Connection in progress"));
}
@ -197,11 +212,11 @@ define(function(require) {
});
$('#' + this.dataTableId).on("click", '.spice', function() {
var vmId = $(this).attr('vm_id');
var data = $(this).data();
if (!Spice.lockStatus()) {
if (!Spice.lockStatus() && data.id) {
Spice.lock();
Sunstone.runAction("VM.startspice_action", vmId);
Sunstone.runAction("VM.startspice_action", data.id);
} else {
Notifier.notifyError(Locale.tr("SPICE Connection in progress"))
}

View File

@ -41,25 +41,31 @@ define(function(require) {
StateActions.disableAllStateActions();
StateActions.enableStateActions(element.STATE, element.LCM_STATE);
// Enable / disable vnc button
var isWFileSupported = false;
if (OpenNebulaVM.isVNCSupported(element)) {
$(".vnc-sunstone-info").show();
} else {
$(".spice-sunstone-info").hide();
isWFileSupported = OpenNebulaVM.isWFileSupported(element);
}
else if (OpenNebulaVM.isSPICESupported(element)) {
$(".spice-sunstone-info").show();
$(".vnc-sunstone-info").hide();
isWFileSupported = OpenNebulaVM.isWFileSupported(element);
}
else {
$(".spice-sunstone-info").hide();
$(".vnc-sunstone-info").hide();
}
(isWFileSupported)
? $(".vv-sunstone-info").show()
: $(".vv-sunstone-info").hide();
// Enable / disable rdp button
if (OpenNebulaVM.isRDPSupported(element)) {
$(".rdp-sunstone-info").show();
} else {
$(".rdp-sunstone-info").hide();
}
(OpenNebulaVM.isRDPSupported(element))
? $(".rdp-sunstone-info").show()
: $(".rdp-sunstone-info").hide();
if (OpenNebulaVM.isSPICESupported(element)) {
$(".spice-sunstone-info").show();
} else {
$(".spice-sunstone-info").hide();
}
if(config &&
config["system_config"] &&
config["system_config"]["allow_vnc_federation"] &&

View File

@ -148,23 +148,24 @@ define(function(require) {
function _elementArray(element_json) {
var element = element_json[XML_ROOT];
var state;
var state = (element.STATE == OpenNebulaVM.STATES.ACTIVE)
? OpenNebulaVM.shortLcmStateStr(element.LCM_STATE)
: OpenNebulaVM.stateStr(element.STATE);
if (element.STATE == OpenNebulaVM.STATES.ACTIVE) {
state = OpenNebulaVM.shortLcmStateStr(element.LCM_STATE);
} else {
state = OpenNebulaVM.stateStr(element.STATE);
}
var actions = "", wFile = false;
var actions = "";
// VNC/SPICE icon
if (OpenNebulaVM.isVNCSupported(element)) {
actions += '<button class="vnc" vm_id="' + element.ID + '">\
<i class="fas fa-desktop"></i></button>';
} else if (OpenNebulaVM.isSPICESupported(element)) {
actions += '<button class="spice" vm_id="' + element.ID + '">\
<i class="fas fa-desktop" style="-webkit-text-stroke: 0.7px;"></i></button>';
actions += OpenNebulaVM.buttonVnc(element.ID);
wFile = OpenNebulaVM.isWFileSupported(element);
}
else if (OpenNebulaVM.isSPICESupported(element)) {
actions += OpenNebulaVM.buttonSpice(element.ID);
wFile = OpenNebulaVM.isWFileSupported(element);
}
// virt-viewer file icon
wFile && (actions += OpenNebulaVM.buttonWFile(element.ID, wFile));
if(config &&
config["system_config"] &&
@ -179,12 +180,9 @@ define(function(require) {
// RDP icon
var rdp = OpenNebulaVM.isRDPSupported(element);
if (rdp) {
actions += OpenNebulaVM.buttonRDP(rdp.IP, element);
}
rdp && (actions += OpenNebulaVM.buttonRDP(rdp.IP, element));
var cpuMonitoring = 0;
var memoryMonitoring = 0;
var cpuMonitoring = 0, memoryMonitoring = 0;
if (element.MONITORING) {
if (element.MONITORING.CPU) {
cpuMonitoring = element.MONITORING.CPU;
@ -197,15 +195,10 @@ define(function(require) {
var hostname = OpenNebulaVM.hostnameStr(element);
var type;
if (element && element.TEMPLATE && element.TEMPLATE.VROUTER_ID && element.TEMPLATE.VROUTER_ID != undefined){
type = "VR";
} else if (element && element.USER_TEMPLATE && element.USER_TEMPLATE.SERVICE_ID && element.USER_TEMPLATE.SERVICE_ID != undefined){
type = "FLOW";
} else {
type = "VM";
}
var type = (element && element.TEMPLATE && element.TEMPLATE.VROUTER_ID && element.TEMPLATE.VROUTER_ID != undefined)
? "VR"
: (element && element.USER_TEMPLATE && element.USER_TEMPLATE.SERVICE_ID && element.USER_TEMPLATE.SERVICE_ID != undefined)
? "FLOW" : "VM";
var search = {
NAME: element.NAME,
@ -219,11 +212,9 @@ define(function(require) {
STIME_BEFORE: element.STIME
};
if (OpenNebulaVM.isFailureState(element.LCM_STATE)){
value_state = "FAILED";
} else {
value_state = OpenNebulaVM.stateStr(element.STATE);
}
var value_state = (OpenNebulaVM.isFailureState(element.LCM_STATE))
? "FAILED" : OpenNebulaVM.stateStr(element.STATE);
var color_html = Status.state_lock_to_color("VM", value_state, element_json[RESOURCE.toUpperCase()]["LOCK"]);
return [

View File

@ -14,18 +14,52 @@
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
define(function() {
define(function(require) {
var Config = require('sunstone-config');
return {
"fileText": _fileText,
"downloadFile": _downloadFile
"downloadWFile": _downloadWFile,
"downloadRdpFile": _downloadRdpFile,
};
function _downloadFile(ip, name, credentials) {
var file = _fileText(ip, credentials.USERNAME, credentials.PASSWORD);
function _downloadRdpFile(ip, name = "vm_name", credentials = {}) {
var file = _rdpFile(ip, credentials.username, credentials.password);
_download(name, ".rdp", file);
}
function _downloadWFile(response, vm_host, graphics_type, graphics_port) {
var protocol = window.location.protocol;
var proxy_host = window.location.hostname;
var proxy_port = Config.vncProxyPort;
var token = response["token"];
var password = response["password"];
var vm_name = response["vm_name"];
if ($.inArray(graphics_type, ['spice', 'vnc']) < 0) {
Notifier.notifyError(Locale.tr("Type grapichs supported: vnc, spice"));
return;
}
if (!graphics_type || !graphics_port) {
Notifier.notifyError(Locale.tr("Must specify type and port in graphics options"));
return;
}
if (!proxy_host || !proxy_port) {
Notifier.notifyError(Locale.tr("Must specify proxy host and port in config"));
return;
}
var proxy = protocol + "//" + proxy_host + ":" + proxy_port + "?token=" + token;
var file = _wFile(graphics_type, vm_name, vm_host, graphics_port, proxy, password);
_download(vm_name, ".vv", file);
}
function _download(name, extension, text) {
var link = $("<a/>", {
href: 'data:text/plain;charset=utf-8,' + encodeURIComponent(file),
download: name + ".rdp",
href: 'data:text/plain;charset=utf-8,' + encodeURIComponent(text),
download: String(name).concat(extension),
}).css({
display: 'none',
}).appendTo("body");
@ -37,8 +71,26 @@ define(function() {
link.remove();
}
function _fileText(ip, username, password) {
let file = ""
function _wFile(type, title, host, port, proxy, password) {
let file = "";
file += "[virt-viewer]\n";
if (type) { file += "type=" + type + "\n"; }
if (title) { file += "title=" + title + "\n"; }
if (host) { file += "host=" + host + "\n"; }
if (port) { file += "port=" + port + "\n"; }
if (proxy) { file += "proxy=" + proxy + "\n"; }
if (password) { file += "password=" + password + "\n"; }
file += "fullscreen=0\n";
file += "toggle-fullscreen=shift+f11\n";
file += "release-cursor=shift+f12\n";
file += "secure-attention=ctrl+alt+end\n";
return file;
}
function _rdpFile(ip, username, password) {
let file = "";
file += "screen mode id:i:2\n";
file += "desktopwidth:i:1280\n";

View File

@ -126,30 +126,26 @@ button.search-dropdown {
border-style: none !important;
}
button.vnc,
button.spice,
button.rdp {
button.remote_vm {
margin: 0 5px;
font-size: 1.4em;
}
font-size: 1.5em;
button.vnc i,
button.spice i,
button.rdp i {
color: $anchor-color;
}
&.spice i {
-webkit-text-stroke: 0.7px;
}
button.vnc:hover i,
button.spice:hover i,
button.rdp:hover i {
color: $anchor-color-hover;
}
i {
color: $anchor-color;
}
button.vnc:focus:active,
button.vnc:focus:active i,
button.spice:focus:active,
button.spice:focus:active i,
button.rdp:focus:active,
button.rdp:focus:active i {
outline: 0;
&:hover i {
color: $anchor-color-hover;
}
&:focus,
&:active,
&:focus i,
&:active i {
outline: 0;
}
}