1
0
mirror of https://github.com/OpenNebula/one.git synced 2024-12-27 03:21:29 +03:00

B #5233: Fix remote actions & IPs (#749)

This commit is contained in:
Sergio Betanzos 2021-02-03 12:40:07 +01:00 committed by GitHub
parent 3e742b4f87
commit b9f4066e4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 426 additions and 477 deletions

View File

@ -167,7 +167,7 @@ class OpenNebulaGuac
'security' => 'any',
'ignore-cert' => 'true',
'enable-drive' => 'true',
'enable-audio' => 'true',
#'enable-audio' => 'true',
'create-drive-path' => 'true'
}.merge!(settings)
}

View File

@ -805,7 +805,6 @@ define(function(require) {
"ipsStr": ipsStr,
"ipsDropdown": ipsDropdown,
"groupByIpsStr": groupByIpsStr,
"aliasStr": aliasStr,
"retrieveExternalIPs": retrieveExternalIPs,
"retrieveExternalNetworkAttrs": retrieveExternalNetworkAttrs,
"isNICGraphsSupported": isNICGraphsSupported,
@ -817,11 +816,6 @@ define(function(require) {
"isSPICESupported": isSPICESupported,
"isWFileSupported": isWFileSupported,
"hasConnection": hasConnection,
"buttonVnc": buttonVnc,
"buttonSpice": buttonSpice,
"buttonWFile": buttonWFile,
"dropdownRDP": dropdownRDP,
"buttonSSH": buttonSSH,
"getName": function(id){
return OpenNebulaAction.getName(id, RESOURCE);
}
@ -923,13 +917,18 @@ define(function(require) {
return nics;
}
// Return the IP or several IPs of a VM
function ipsStr(element, divider, groupStrFunction) {
var defaultValue = '--'
var divider = divider || "<br>";
// Return the IP or several IPs of a VM
function ipsStr(element, options) {
options = $.extend({
defaultValue: '--',
divider: '<br>',
groupStrFunction: groupByIpsStr,
forceGroup: false
}, options)
var nics = getNICs(element);
var ips = [];
var monitoring = element && element.MONITORING;
var ips = [];
if (monitoring) {
$.each(EXTERNAL_IP_ATTRS, function(_, IPAttr) {
@ -948,10 +947,8 @@ define(function(require) {
}
// infoextended: alias will be group by nic
if (Config.isExtendedVmInfo) {
return typeof groupStrFunction === "function"
? groupStrFunction(element, nics)
: groupByIpsStr(element, nics)
if (Config.isExtendedVmInfo || options.forceGroup) {
return options.groupStrFunction(element, nics)
}
return (ips.length === 0 && nics && nics.length > 0) ? (
@ -959,30 +956,30 @@ define(function(require) {
return $.map(NIC_ALIAS_IP_ATTRS, function(attribute) {
return nic[attribute]
})
}).join(divider)
}).join(options.divider)
) : (
defaultValue
options.defaultValue
)
};
// Return a dropdown with all the
function ipsDropdown(element, divider) {
var ipsStr = this.ipsStr(element,divider,groupByIpsDropdown);
var ips = ipsStr.split("<br>");
var ipsHtml = this.ipsStr(element, { divider, groupStrFunction: groupByIpsDropdown });
var ips = ipsHtml.split("<br>");
var html = "";
// If its generated by groupByIpsDropdown
if (~ipsStr.indexOf("li")){
if (~ipsHtml.indexOf("li")){
ips = [];
$.each($.parseHTML(ipsStr), function() {
$.each($.parseHTML(ipsHtml), function() {
ips.push($( this ).text());
});
ipsStr = "<ul style='list-style-type:none;'>" + ipsStr + "</ul>";
ipsHtml = "<ul style='list-style-type:none;'>" + ipsHtml + "</ul>";
}
// If it has less than "numIPs" IPs
var numIPs = 2;
if ((ips.length < numIPs)) return ipsStr;
if ((ips.length < numIPs)) return ipsHtml;
// Take the first x
var insideHtml = "";
@ -1020,7 +1017,7 @@ define(function(require) {
? $("<li/>").append($("<a/>").css("color", "gray").html(nic.NIC_ID + ": " + ip))
: $("<li/>").append("<li>").html("-") ;
if (String(nic.EXTERNAL_IP).toLowerCase() !== 'yes') {
if (nic.EXTERNAL_IP && String(nic.EXTERNAL_IP).toLowerCase() !== 'yes') {
var externalIp = "&#10;&#13;" + nic.NIC_ID + ": " + nic.EXTERNAL_IP
nicSection.append($("<li/>").append($("<a/>").css("color", "gray").html(externalIp)))
}
@ -1053,12 +1050,12 @@ define(function(require) {
function groupByIpsStr(element = {}, nics = []) {
var identation = "&nbsp;&nbsp;&nbsp;&nbsp;";
var res = nics.reduce(function(column, nic) {
return nics.reduce(function(column, nic) {
var ip = nic.IP || nic.IP6_ULA + "<br>" + identation + nic.IP6_GLOBAL
column.append($("<p/>").css("margin-bottom", 0).html(nic.NIC_ID + ": " + ip))
if (String(nic.EXTERNAL_IP).toLowerCase() !== 'yes') {
if (nic.EXTERNAL_IP && String(nic.EXTERNAL_IP).toLowerCase() !== 'yes') {
var externalIp = nic.NIC_ID + ": " + nic.EXTERNAL_IP
column.append($("<p/>").css("margin-bottom", 0).html(externalIp))
@ -1073,8 +1070,9 @@ define(function(require) {
var alias = templateAlias.find(function(alias) { return alias.NIC_ID === aliasId; });
if (alias) {
var alias_ip = identation + "> " + alias.IP ||
alias.IP6_ULA + "<br>" + identation + "> " + alias.IP6_GLOBAL;
var alias_ip = alias.IP
? identation + "> " + alias.IP
: alias.IP6_ULA + "<br>" + identation + "> " + alias.IP6_GLOBAL;
column.append($("<p/>").css({
"margin-bottom": 0,
@ -1088,62 +1086,37 @@ define(function(require) {
}, $("<div/>")).html();
};
// Return the Alias or several Aliases of a VM
function aliasStr(element, divider) {
var divider = divider || "<br>";
var nic_alias = element.TEMPLATE.NIC_ALIAS;
var ips = [];
function isVNCSupported(element = {}) {
var actionEnabled = Config.isTabActionEnabled('vms-tab', 'VM.vnc')
var vncSupported = graphicSupported(element, 'vnc')
if (nic_alias == undefined){
nic_alias = [];
}
if (!$.isArray(nic_alias)) {
nic_alias = [nic_alias];
}
if(ips.length==0) {
$.each(nic_alias, function(index, value) {
$.each(NIC_ALIAS_IP_ATTRS, function(j, attr){
if (value[attr]) {
ips.push(value[attr]);
}
});
});
}
if (ips.length > 0) {
return ips.join(divider);
} else {
return "--";
}
};
// returns true if the vnc button should be enabled
function isVNCSupported(element) {
return (Config.isTabActionEnabled("vms-tab", "VM.vnc") && graphicSupported(element, "vnc"))
? true : false;
return actionEnabled && vncSupported
}
// returns true if the vmrc button should be enabled
function isVMRCSupported(element) {
var action_enabled = Config.isTabActionEnabled("vms-tab", "VM.startvmrc");
var graphics = graphicSupported(element, "vmrc");
return (action_enabled && graphics)
? true : false;
function isVMRCSupported(element = {}) {
var actionEnabled = Config.isTabActionEnabled('vms-tab', 'VM.startvmrc')
var vmrcSupported = graphicSupported(element, 'vrmc')
var isVCenter =
element.USER_TEMPLATE &&
String(element.USER_TEMPLATE.HYPERVISOR).toLowerCase() === 'vcenter'
return actionEnabled && vmrcSupported && isVCenter
}
function isSPICESupported(element) {
return (Config.isTabActionEnabled("vms-tab", "VM.startspice") && graphicSupported(element, "spice"))
? true : false;
function isSPICESupported(element = {}) {
var actionEnabled = Config.isTabActionEnabled('vms-tab', 'VM.startspice')
var spiceSupported = graphicSupported(element, 'spice')
return actionEnabled && spiceSupported
}
function isWFileSupported(element) {
function isWFileSupported(element = {}) {
var history = retrieveLastHistoryRecord(element);
return (
Config.isTabActionEnabled("vms-tab", "VM.save_virt_viewer") && history &&
(graphicSupported(element, "vnc") || graphicSupported(element, "spice"))
)
var actionEnabled = Config.isTabActionEnabled("vms-tab", "VM.save_virt_viewer")
var vncSupported = graphicSupported(element, 'vnc')
var spiceSupported = graphicSupported(element, 'spice')
return (actionEnabled && history && (vncSupported || spiceSupported))
? {
hostname: history.HOSTNAME,
type: element.TEMPLATE.GRAPHICS.TYPE.toLowerCase(),
@ -1161,7 +1134,6 @@ define(function(require) {
var isEnabled = false;
if (
$.inArray(String(typeConnection).toLowerCase(), ['rdp', 'ssh']) > -1 &&
Config.isTabActionEnabled("vms-tab", "VM."+ String(typeConnection).toLowerCase()) &&
element && element.TEMPLATE && element.TEMPLATE.GRAPHICS && element.LCM_STATE
) {
var template = element.TEMPLATE;
@ -1203,73 +1175,11 @@ define(function(require) {
var state = parseInt(element.LCM_STATE);
rtn = graphics &&
graphics.TYPE &&
graphics.TYPE.toLowerCase() == type &&
$.inArray(state, VNC_STATES) != -1;
graphics.TYPE.toLowerCase() === type &&
$.inArray(state, VNC_STATES) !== -1;
}
return rtn;
}
function buttonVnc(id = "") {
return "<button class=\"vnc remote_vm\" data-id=\"" + id + "\">\
<i class=\"fas fa-desktop\"></i></button>";
}
function buttonSSH(id = "") {
return '<button class="ssh remote-vm" data-id="' + id + '">\
<i class="fas fa-terminal"></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-square-alt\"></i></button>";
}
function dropdownRDP(id = "", ip = "", vm = {}) {
return '<ul class="dropdown menu" id="rdp-buttons" data-dropdown-menu> \
<li>\
<button type="button" class="remote-vm"> \
<i class="fab fa-windows"></i> \
</button>\
<ul class="menu">\
<li>' + buttonRDP(id) + '</li> \
<li>' + buttonSaveRDP(ip, vm) + '</li> \
</ul>\
</li>\
</ul>';
}
function buttonRDP(id = "") {
var styleIcon = 'style="width: 2em;text-align: center;"';
return '<a class="rdp" data-id="' + id + '"> \
<i class="fas fa-desktop" ' + styleIcon + '></i><span>' + Locale.tr("HTML") + '</span></a>';
}
function buttonSaveRDP(ip = "", vm = {}) {
var username, password, styleIcon = 'style="width: 2em;text-align: center;"';
if (vm && vm.TEMPLATE && vm.TEMPLATE.CONTEXT) {
var context = vm.TEMPLATE.CONTEXT;
for (var prop in context) {
var propUpperCase = String(prop).toUpperCase();
(propUpperCase === "USERNAME") && (username = context[prop]);
(propUpperCase === "PASSWORD") && (password = context[prop]);
}
}
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>";
return button;
}
return VM;
});

View File

@ -27,11 +27,12 @@ define(function(require) {
var StateRolesButtons = require('./roles/state-roles-buttons');
var Sunstone = require('sunstone');
var DomDataTable = require('utils/dom-datatable');
var Vnc = require('utils/vnc');
var Spice = require('utils/spice');
var Notifier = require('utils/notifier');
var VMRemoteActions = require('utils/remote-actions');
var OpenNebulaVM = require("opennebula/vm");
var FireedgeValidator = require('utils/fireedge-validator');
var Websocket = require("utils/websocket");
var VMS_TAB_ID = require('tabs/vms-tab/tabId');
/*
@ -76,7 +77,6 @@ define(function(require) {
Panel.prototype.setState = _setState;
Panel.prototype.roleHTML = _roleHTML;
Panel.prototype.roleSetup = _roleSetup;
Panel.prototype.remoteButtonSetup = _remoteButtonSetup;
return Panel;
@ -229,23 +229,9 @@ define(function(require) {
: '<span class="has-tip" title="'+
Locale.tr("Waiting for the VM to be ready")+'"><i class="fas fa-clock"/></span>'
}
ips = OpenNebulaVM.ipsStr(data.VM);
ips = OpenNebulaVM.ipsStr(data.VM, { forceGroup: true });
if (OpenNebulaVM.isVNCSupported(data.VM)) {
actions += OpenNebulaVM.buttonVnc(id);
}
else if (OpenNebulaVM.isSPICESupported(data.VM)) {
actions += OpenNebulaVM.buttonSpice(id);
}
var wFile = OpenNebulaVM.isWFileSupported(data.VM);
actions += wFile ? OpenNebulaVM.buttonWFile(id, wFile) : "";
var rdp = OpenNebulaVM.isConnectionSupported(data.VM, 'rdp');
actions += rdp ? OpenNebulaVM.dropdownRDP(id, rdp.ID, data.VM) : "";
var ssh = OpenNebulaVM.isConnectionSupported(data.VM, 'ssh');
actions += ssh ? OpenNebulaVM.buttonSSH(id) : "";
actions = VMRemoteActions.renderActionsHtml(data.VM);
}
roleVms[index] = rowInfoRoleVm(ready, id, name, uname, gname, ips, actions);
@ -256,11 +242,14 @@ define(function(require) {
}
$.when.apply($, promises).then(function() {
if (that.serviceroleVMsDataTable) {
that.serviceroleVMsDataTable.updateView(null, roleVms, true);
}
that.remoteButtonSetup(context);
});
if (that.serviceroleVMsDataTable) {
that.serviceroleVMsDataTable.updateView(null, roleVms, true);
$("#rdp-buttons", context).foundation();
VMRemoteActions.bindActionsToContext(context)
}
Tips.setup(context);
});
return TemplateRoleInfo({
@ -331,62 +320,4 @@ define(function(require) {
);
}
}
function _remoteButtonSetup(context) {
$(".spice", context).off("click");
$(".spice", context).on("click", function() {
var data = $(this).data();
if (!Spice.lockStatus() && data.hasOwnProperty("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.hasOwnProperty("id") && data.hasOwnProperty("hostname") && data.hasOwnProperty("type") && data.hasOwnProperty("port"))
? Sunstone.runAction(
"VM.save_virt_viewer_action",
String(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 data = $(this).data();
if (!Vnc.lockStatus() && data.hasOwnProperty("id")) {
Vnc.lock();
Sunstone.runAction("VM.startvnc_action", String(data.id));
} else {
Notifier.notifyError(Locale.tr("VNC Connection in progress"));
}
return false;
});
$(".rdp", context).off("click");
$(".rdp", context).on("click", function() {
var data = $(this).data();
(data.hasOwnProperty("ip") && data.hasOwnProperty("name"))
? Sunstone.runAction("VM.save_rdp", data)
: Notifier.notifyError(Locale.tr("This VM needs a nic with rdp active"));
return false;
});
Tips.setup(context);
}
});

View File

@ -83,6 +83,8 @@ define(function(require) {
var state = parseInt(state);
var actionsAvailable = STATE_ACTIONS[state]
if (actionsAvailable === undefined) return;
$.each(ALL_ACTION_BUTTONS, function(_, action) {
const isDisabled = actionsAvailable.indexOf(action) !== -1

View File

@ -1023,58 +1023,8 @@ define(function(require) {
return (
"<div style=\"display: flex; gap: 5px;\">" +
"<i class=\"fas fa-fw fa-lg fa-globe\"></i>" +
"<div>" + OpenNebula.VM.ipsStr(data, ", ") + "</div>" +
"<div>" + OpenNebula.VM.ipsStr(data, { divider: ", " }) + "</div>" +
"</div>"
);
}
// @params
// data: and IMAGE object
// Example: data.ID
// @returns and object containing the following properties
// color: css class for this state.
// color + '-color' font color class
// color + '-bg' background class
// str: user friendly state string
function get_provision_image_state(data) {
var state = OpenNebula.Image.stateStr(data.STATE);
var state_color;
var state_str;
switch (state) {
case "READY":
case "USED":
state_color = "running";
state_str = Locale.tr("READY");
break;
case "DISABLED":
case "USED_PERS":
state_color = "off";
state_str = Locale.tr("OFF");
break;
case "LOCKED":
case "CLONE":
case "INIT":
state_color = "deploying";
state_str = Locale.tr("DEPLOYING") + " (1/3)";
break;
case "ERROR":
state_color = "error";
state_str = Locale.tr("ERROR");
break;
case "DELETE":
state_color = "error";
state_str = Locale.tr("DELETING");
break;
default:
state_color = "powering_off";
state_str = Locale.tr("UNKNOWN");
break;
}
return {
color: state_color,
str: state_str
};
}
});

View File

@ -22,19 +22,15 @@ define(function(require) {
var TabDataTable = require('utils/tab-datatable');
var VMsTableUtils = require('./utils/datatable-common');
var OpenNebulaVM = require('opennebula/vm');
var OpenNebulaAction = require("opennebula/action");
var SunstoneConfig = require('sunstone-config');
var Locale = require('utils/locale');
var StateActions = require('./utils/state-actions');
var Sunstone = require('sunstone');
var Vnc = require('utils/vnc');
var Spice = require('utils/spice');
var Notifier = require('utils/notifier');
var DashboardUtils = require('utils/dashboard');
var SearchDropdown = require('hbs!./datatable/search');
var TemplateUtils = require('utils/template-utils');
var FireedgeValidator = require('utils/fireedge-validator');
var Websocket = require("utils/websocket");
var VMRemoteActions = require('utils/remote-actions');
/*
CONSTANTS
@ -173,14 +169,11 @@ define(function(require) {
$("#rdp-buttons").foundation();
var create_socket = function(token){
if (Websocket.disconnected()){
FireedgeValidator.validateFireedgeToken(function(token) {
if (Websocket.disconnected()) {
Websocket.start(token);
}
}
FireedgeValidator.validateFireedgeToken(create_socket);
});
}
function _initialize(opts) {
@ -188,138 +181,7 @@ define(function(require) {
TabDataTable.prototype.initialize.call(this, opts);
//download virt-viewer file
$('#' + this.dataTableId).on("click", '.w-file', function(){
var data = $(this).data();
(data.hasOwnProperty("id") && data.hasOwnProperty("hostname") && data.hasOwnProperty("type") && data.hasOwnProperty("port"))
? Sunstone.runAction(
"VM.save_virt_viewer_action",
String(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", '.save-rdp', function() {
var data = $(this).data();
(data.hasOwnProperty("ip") && data.hasOwnProperty("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", ".rdp", function() {
var data = $(this).data();
(data.hasOwnProperty("id"))
? Sunstone.runAction("VM.startguac_action", String(data.id), { type: 'rdp' })
: Notifier.notifyError(Locale.tr("RDP - Invalid action"));
return false;
});
$('#' + this.dataTableId).on("click", ".ssh", function() {
var data = $(this).data();
(data.hasOwnProperty("id"))
? Sunstone.runAction("VM.startguac_action", String(data.id), { type: 'ssh' })
: Notifier.notifyError(Locale.tr("SSH - Invalid action"));
return false;
});
$('#' + this.dataTableId).on("click", ".guac-vnc", function() {
var data = $(this).data();
(data.hasOwnProperty("id"))
? Sunstone.runAction("VMstartguac_action", String(data.id), { type: 'vnc' })
: Notifier.notifyError(Locale.tr("VNC - Invalid action"));
return false;
});
$('#' + this.dataTableId).on("click", '.vnc', function() {
var that = this;
function promiseVmInfo(id, success) {
return $.ajax({
url: "vm/" + id,
type: "GET",
dataType: "json",
success: success
})
}
function callVNC() {
var data = $(that).data();
if (!Vnc.lockStatus() && data.hasOwnProperty("id")) {
Vnc.lock();
Sunstone.runAction("VM.startvnc_action", String(data.id));
} else {
Notifier.notifyError(Locale.tr("VNC Connection in progress"));
}
}
function callVMRC(){
var data = $(that).data();
(data.hasOwnProperty("id"))
? Sunstone.runAction("VM.startvmrc_action", String(data.id), { type: 'vnc' })
: Notifier.notifyError(Locale.tr("VNC - Invalid action"));
}
function callGuac(){
var data = $(that).data();
(data.hasOwnProperty("id"))
? Sunstone.runAction("VM.startguac_action", String(data.id), { type: 'vnc' })
: Notifier.notifyError(Locale.tr("VNC - Invalid action"));
}
var remote_connections = function(fireedgeToken){
if (fireedgeToken != ""){
var data = $(that).data();
// Get VM info
if (data.hasOwnProperty('id')){
promiseVmInfo(data['id'], function(data){
if (data && data.VM && data.VM.USER_TEMPLATE && data.VM.USER_TEMPLATE.HYPERVISOR == 'vcenter'){
callVMRC();
}
else{
callGuac();
}
});
}
}
else{
callVNC();
}
}
FireedgeValidator.validateFireedgeToken(remote_connections, callVNC);
return false;
});
$('#' + this.dataTableId).on("click", '.spice', function() {
var data = $(this).data();
if (!Spice.lockStatus() && data.hasOwnProperty("id")) {
Spice.lock();
Sunstone.runAction("VM.startspice_action", String(data.id));
} else {
Notifier.notifyError(Locale.tr("SPICE Connection in progress"))
}
return false;
});
VMRemoteActions.bindActionsToContext('#' + this.dataTableId)
$('#' + this.dataTableId).on("change", 'tbody input.check_item', function() {
if ($(this).is(":checked")){
@ -330,16 +192,12 @@ define(function(require) {
// Enable actions available to any of the selected VMs
var nodes = $('tr', that.dataTable); //visible nodes only
$.each($('input.check_item:checked', nodes), function(){
$.each($('input.check_item:checked', nodes), function() {
StateActions.enableStateActions($(this).attr("state"), $(this).attr("lcm_state"));
});
}
return true;
});
}
});

View File

@ -72,14 +72,14 @@ define(function(require) {
return false;
}
function _onShow(context) {
function _onShow() {
this.gClient.connect(this.element);
this.gClient.mouse(true);
this.gClient.keyboard(true);
return false;
}
function _onClose(context) {
function _onClose() {
this.gClient.disconnect();
this.gClient.mouse(false);
this.gClient.keyboard(false);

View File

@ -66,7 +66,6 @@ define(function(require) {
else if (isSPICESupported) {
$(".spice-sunstone-info").show();
$(".vnc-sunstone-info").hide();
}
else {
$(".spice-sunstone-info").hide();

View File

@ -79,13 +79,7 @@ define(function(require) {
var hostnameHTML = OpenNebula.VM.hostnameStrLink(this.element);
var vrouterHTML = "--";
var IP = OpenNebula.VM.ipsStr(this.element);
var alias = (
config.system_config &&
config.system_config.get_extended_vm_info &&
config.system_config.get_extended_vm_info === "true"
) ? null : OpenNebula.VM.aliasStr(this.element);
var IP = OpenNebula.VM.ipsStr(this.element, { forceGroup: true });
if (this.element.TEMPLATE.VROUTER_ID != undefined){
vrouterHTML = Navigation.link(
@ -159,7 +153,6 @@ define(function(require) {
"prettyStartTime": prettyStartTime,
"deployId": deployId,
"IP": IP,
"alias": alias,
"resched": resched,
"permissionsTableHTML": permissionsTableHTML,
"templateTableVcenterHTML": templateTableVcenterHTML,

View File

@ -69,14 +69,6 @@
<td></td>
</tr>
{{#if alias }}
<tr>
<td class="key_td">{{tr "Alias"}}</td>
<td class="value_td">{{{alias}}}</td>
<td></td>
</tr>
{{/if }}
<tr>
<td class="key_td">{{tr "Start time"}}</td>
<td class="value_td">{{prettyStartTime}}</td>

View File

@ -23,6 +23,7 @@ define(function(require) {
var LabelsUtils = require('utils/labels/utils');
var Status = require('utils/status');
var ScheduleActions = require("utils/schedule_action");
var VMRemoteActions = require('utils/remote-actions');
var RESOURCE = "VM";
var XML_ROOT = "VM";
@ -192,38 +193,7 @@ define(function(require) {
? OpenNebulaVM.shortLcmStateStr(element.LCM_STATE)
: OpenNebulaVM.stateStr(element.STATE);
var actions = "";
// VNC/SPICE icon
if (OpenNebulaVM.isVNCSupported(element)) {
actions += OpenNebulaVM.buttonVnc(element.ID);
}
else if (OpenNebulaVM.isSPICESupported(element)) {
actions += OpenNebulaVM.buttonSpice(element.ID);
}
// virt-viewer file icon
wFile = OpenNebulaVM.isWFileSupported(element);
wFile && (actions += OpenNebulaVM.buttonWFile(element.ID, wFile));
if(config &&
config["system_config"] &&
config["system_config"]["allow_vnc_federation"] &&
config["system_config"]["allow_vnc_federation"] === 'no' &&
config["id_own_federation"] &&
config["zone_id"] &&
config["id_own_federation"] !== config["zone_id"])
{
actions = '';
}
// RDP icons
var rdp = OpenNebulaVM.isConnectionSupported(element, 'rdp');
rdp && (actions += OpenNebulaVM.dropdownRDP(element.ID, rdp.IP, element));
// SSH icon
var ssh = OpenNebulaVM.isConnectionSupported(element, 'ssh');
ssh && (actions += OpenNebulaVM.buttonSSH(element.ID));
var actions = VMRemoteActions.renderActionsHtml(element);
var cpuMonitoring = 0, memoryMonitoring = 0;
if (element.MONITORING) {
@ -276,7 +246,7 @@ define(function(require) {
hostname,
OpenNebulaVM.ipsDropdown(element),
Humanize.prettyTimeDatatable(element.STIME),
actions && "<div style='display: flex; align-items: end; gap:5px'>"+actions+"</div>",
actions,
TemplateUtils.htmlEncode(TemplateUtils.templateToString(element)),
(LabelsUtils.labelsStr(element[TEMPLATE_ATTR])||''),
btoa(unescape(encodeURIComponent(JSON.stringify(search)))),

View File

@ -63,7 +63,6 @@ define(function(require) {
}
else setLoading(true);
var endpoint = Config.publicFireedgeEndpoint.split("//");
var fireedge_protocol = endpoint[0];
var fireedge_host = endpoint[1].split(":")[0];
@ -90,6 +89,9 @@ define(function(require) {
tunnel.onerror = function() {
disconnect();
Notifier.notifyError(that._clientErrorText)
setStatus("Guacamole tunnel ERROR");
setLoading(false);
};
guac.onstatechange = function(state) {

View File

@ -0,0 +1,342 @@
/* -------------------------------------------------------------------------- */
/* 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. */
/* -------------------------------------------------------------------------- */
define(function(require) {
var Locale = require('utils/locale'),
Sunstone = require('sunstone'),
Config = require("sunstone-config"),
OpenNebulaVM = require("opennebula/vm"),
Vnc = require('utils/vnc'),
Spice = require('utils/spice'),
FireedgeValidator = require('utils/fireedge-validator'),
Notifier = require('utils/notifier');
function _callSpice(data) {
if (!Spice.lockStatus() && data.hasOwnProperty('id')) {
Spice.lock();
Sunstone.runAction('VM.startspice_action', String(data.id));
} else {
Notifier.notifyError(Locale.tr('SPICE Connection in progress'));
}
}
function _callVNC(data) {
if (!Vnc.lockStatus() && data.hasOwnProperty('id')) {
Vnc.lock();
Sunstone.runAction('VM.startvnc_action', String(data.id));
} else {
Notifier.notifyError(Locale.tr('VNC Connection in progress'));
}
}
function _callSaveRDP(data) {
(data.hasOwnProperty('ip') && data.hasOwnProperty('name'))
? Sunstone.runAction('VM.save_rdp', data)
: Notifier.notifyError(Locale.tr('This VM needs a nic with rdp active'));
}
function _callSaveWFile(data) {
(
data.hasOwnProperty("id") &&
data.hasOwnProperty("hostname") &&
data.hasOwnProperty("type") &&
data.hasOwnProperty("port")
)
? Sunstone.runAction(
"VM.save_virt_viewer_action",
String(data.id),
{ hostname: data.hostname, type: data.type, port: data.port }
)
: Notifier.notifyError(Locale.tr("Data for virt-viewer file isn't correct"));
}
/**
* VMRC action
*/
function _callVMRC(data) {
(data.hasOwnProperty("id"))
? Sunstone.runAction("VM.startvmrc_action", String(data.id))
: Notifier.notifyError(Locale.tr("VNC - Invalid action"));
}
/**
* Guacamole actions
*/
function _callGuacVNC(data) {
(data.hasOwnProperty('id'))
? Sunstone.runAction('VM.startguac_action', String(data.id), { type: 'vnc' })
: Notifier.notifyError(Locale.tr('VNC - Invalid action'));
}
function _callGuacRDP(data) {
(data.hasOwnProperty('id'))
? Sunstone.runAction('VM.startguac_action', String(data.id), { type: 'rdp' })
: Notifier.notifyError(Locale.tr('RDP - Invalid action'));
}
function _callGuacSSH(data) {
(data.hasOwnProperty('id'))
? Sunstone.runAction('VM.startguac_action', String(data.id), { type: 'ssh' })
: Notifier.notifyError(Locale.tr('SSH - Invalid action'));
}
/**
* Render actions
*/
function buttonVnc(id = '') {
var icon = $('<i>', { class: 'fas fa-desktop' })
var button = $('<button>', {
title: 'vnc',
class: 'vnc remote-vm',
'data-id': id
})
return $('<div>').append(button.append(icon)).html()
}
function buttonVmrc(id = '') {
var icon = $('<i>', { class: 'fas fa-desktop' })
var button = $('<button>', {
title: 'vmrc',
class: 'vmrc remote-vm',
'data-id': id
})
return $('<div>').append(button.append(icon)).html()
}
function buttonSSH(id = '') {
var icon = $('<i>', { class: 'fas fa-terminal' })
var button = $('<button>', {
title: 'ssh',
class: 'ssh remote-vm',
'data-id': id
})
return $('<div>').append(button.append(icon)).html()
}
function buttonSpice(id = '') {
var icon = $('<i>', { class: 'fas fa-desktop' })
var button = $('<button>', {
title: 'spice',
class: 'spice remote-vm',
'data-id': id
})
return $('<div>').append(button.append(icon)).html()
}
function buttonWFile(id = '', data = {}) {
var icon = $('<i>', { class: 'fas fa-external-link-square-alt' })
var button = $('<button>', {
title: 'download virt-viewer file',
class: 'w-file remote-vm',
'data-id': id,
'data-type': data.type,
'data-port': data.port,
'data-hostname':data.hostname
})
return $('<div>').append(button.append(icon)).html()
}
function dropdownRDP(id = '', ip = '', vm = {}) {
var icon = $('<i>', { class: 'fab fa-windows' })
var dropdownButton = $('<button>', { title:'RDP menu', class: 'remote-vm' })
var dropdownMenu = $('<ul>', {
class: 'dropdown menu',
id: 'rdp-buttons',
'data-dropdown-menu': ''
})
var buttonsEnabled = []
Config.isTabActionEnabled("vms-tab", "VM.rdp") &&
buttonsEnabled.push($('<li>').append(buttonRDP(id)));
Config.isTabActionEnabled("vms-tab", "VM.save_rdp") &&
buttonsEnabled.push($('<li>').append(buttonSaveRDP(ip, vm)));
if (buttonsEnabled.length === 0) return '';
var menu = $('<ul>', { class: 'menu' }).append(buttonsEnabled)
return $('<div>').append(
dropdownMenu.append(
$('<li>').append([dropdownButton.append(icon), menu])
)
).html()
}
function buttonRDP(id = '') {
var icon = $('<i>', { class: 'fas fa-desktop' })
.css({ width: '2em', 'text-align': 'center' })
var text = $('<span>', { text: Locale.tr('HTML') })
var button = $('<a>', { class: 'rdp', 'data-id': id })
return $('<div>').append(button.append([icon, text])).html()
}
function buttonSaveRDP(ip = "", vm = {}) {
var icon = $('<i>', { class: 'fas fa-file' })
.css({ width: '2em', 'text-align': 'center' })
var text = $('<span>', { text: Locale.tr('RDP Client') })
var button = $('<a>', { class: 'save-rdp', 'data-name': vm.NAME, 'data-ip': ip })
var username, password;
if (vm.TEMPLATE && vm.TEMPLATE.CONTEXT) {
var context = vm.TEMPLATE.CONTEXT;
for (var prop in context) {
var propUpperCase = String(prop).toUpperCase();
(propUpperCase === "USERNAME") && (username = context[prop]);
(propUpperCase === "PASSWORD") && (password = context[prop]);
}
}
username && button.attr('data-username', username)
password && button.attr('data-password', password)
return $('<div>').append(button.append([icon, text])).html()
}
function _renderActionsHtml(vm) {
var actions = '';
if (OpenNebulaVM.isVNCSupported(vm)) {
actions += buttonVnc(vm.ID);
}
else if (OpenNebulaVM.isVMRCSupported(vm)) {
actions += buttonVmrc(vm.ID);
}
else if (OpenNebulaVM.isSPICESupported(vm)) {
actions += buttonSpice(vm.ID);
}
var wFile = OpenNebulaVM.isWFileSupported(vm);
actions += wFile ? buttonWFile(vm.ID, wFile) : '';
var rdp = OpenNebulaVM.isConnectionSupported(vm, 'rdp');
actions += rdp ? dropdownRDP(vm.ID, rdp.IP, vm) : '';
var ssh = OpenNebulaVM.isConnectionSupported(vm, 'ssh');
actions += ssh && Config.isTabActionEnabled("vms-tab", "VM.rdp") ? buttonSSH(vm.ID) : '';
if(config &&
config["system_config"] &&
config["system_config"]["allow_vnc_federation"] &&
config["system_config"]["allow_vnc_federation"] === 'no' &&
config["id_own_federation"] &&
config["zone_id"] &&
config["id_own_federation"] !== config["zone_id"])
{
actions = '';
}
return "<div style='display: flex; align-items: end; gap:5px'>"+actions+"</div>";
}
function _bindActionsToContext(context) {
$(context)
.off("click", '.w-file')
.on("click", '.w-file', function(evt) {
evt.preventDefault();
_callSaveWFile($(this).data());
evt.stopPropagation();
})
.off("click", '.save-rdp')
.on("click", '.save-rdp', function(evt) {
evt.preventDefault();
_callSaveRDP($(this).data());
evt.stopPropagation();
})
.off("click", '.rdp')
.on("click", ".rdp", function(evt) {
evt.preventDefault();
_callGuacRDP($(this).data());
evt.stopPropagation();
})
.off("click", '.ssh')
.on("click", ".ssh", function(evt) {
evt.preventDefault();
_callGuacSSH($(this).data());
evt.stopPropagation();
})
.off("click", '.spice')
.on("click", '.spice', function(evt) {
evt.preventDefault();
_callSpice($(this).data());
evt.stopPropagation();
})
.off("click", '.vnc')
.on("click", '.vnc', function(evt) {
evt.preventDefault();
var data = $(this).data();
FireedgeValidator.validateFireedgeToken(
function(fireedgeToken) {
fireedgeToken !== '' ? _callGuacVNC(data) : _callVNC(data)
},
function() {
_callVNC(data)
}
);
evt.stopPropagation();
})
.off("click", '.vmrc')
.on("click", '.vmrc', function(evt) {
evt.preventDefault();
var data = $(this).data();
FireedgeValidator.validateFireedgeToken(
function(fireedgeToken) {
fireedgeToken !== '' ? _callVMRC(data) : _callVNC(data)
},
function() { _callVNC(data) }
);
evt.stopPropagation();
});
}
return {
'callSpice': _callSpice,
'callVNC': _callVNC,
'callSaveRDP': _callSaveRDP,
'callSaveWFile': _callSaveWFile,
'callVMRC': _callVMRC,
'callGuacVNC': _callGuacVNC,
'callGuacSSH': _callGuacSSH,
'callGuacRDP': _callGuacRDP,
'callGuacVNC': _callGuacVNC,
'renderActionsHtml': _renderActionsHtml,
'bindActionsToContext': _bindActionsToContext
};
});