Compare commits
31 Commits
1536441e59
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 9436fe7c60 | |||
| b84ca3e4e4 | |||
| 79a944c0e3 | |||
| a1e314b00c | |||
| e169c19bd0 | |||
| d43842790a | |||
|
|
5d3bfbc491 | ||
| 72fe3d8335 | |||
| 3c461d4570 | |||
|
|
07678cacd4 | ||
| 625c246ba9 | |||
| 8aaf241075 | |||
| 68e726fae3 | |||
|
|
1dc3c4a557 | ||
|
|
cffcb3ea64 | ||
|
|
a8e21ef76c | ||
|
|
f868d991b1 | ||
|
|
a8e4ddb2e0 | ||
|
|
8ac143be27 | ||
|
|
f0399c9c9d | ||
| 6aee52c717 | |||
| 7e5d7d1d3c | |||
| a4e71a8992 | |||
|
|
0cde20881a | ||
|
|
31983b6803 | ||
|
|
1689989bd4 | ||
|
|
7d31e98713 | ||
|
|
50e9338059 | ||
|
|
6d0f7fb392 | ||
|
|
6d5d6e18f5 | ||
|
|
ca9dafcab4 |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
bin/check_status
|
||||
16
Makefile
Normal file
16
Makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
BINARY_NAME=check_status
|
||||
GO_PRG=check_status.go
|
||||
BIN_DIR=./bin
|
||||
GO=/usr/local/go/bin/go
|
||||
|
||||
all: build test
|
||||
|
||||
build:
|
||||
${GO} build -o ${BIN_DIR}/${BINARY_NAME} ${GO_PRG}
|
||||
|
||||
test:
|
||||
${GO} test -v ${GO_PRG}
|
||||
|
||||
clean:
|
||||
${GO} clean
|
||||
rm ${BIN_DIR}/${BINARY_NAME}
|
||||
73
README.md
73
README.md
@@ -1,7 +1,7 @@
|
||||
# RemoteSupport
|
||||
GLPI Plugin for direct VNC connection inside ticket
|
||||
GLPI Plugin for direct VNC connection from browser inside computer from server and update status of online computers, it checks computer with go program in glpi cron and with fusion inventory agent...
|
||||
|
||||
This Plugin add a simple button inside tickets:
|
||||
This Plugin add a simple button inside computer:
|
||||
|
||||

|
||||
|
||||
@@ -10,35 +10,60 @@ If user is correctly connected to one or more computer it will launch a VNC conn
|
||||
|
||||
- Prerequisites
|
||||
1) VNC Must be installed in the destination PC
|
||||
2) PC Name must me correct and resolved inside your DNS Server
|
||||
3) Add a script in your pc and add a node inside regedit
|
||||
2) Fusion inventory must be installed on server with GLPI
|
||||
3) Agent must be installed on remote PC
|
||||
4) Easy noVNC must be installed on server with GLPI
|
||||
|
||||
|
||||
1) write a script (you will find inside resources) like this (let's assume in c:\startVNC.bat)
|
||||
> SET S=%1
|
||||
>
|
||||
> SET S=%S:~7,-2%
|
||||
>
|
||||
> call "C:\Program Files\TightVNC\tvnviewer.exe" %S%
|
||||
>
|
||||
> quit 0
|
||||
clone it and build binnary with make, edit Makefile in remotesupport plugin and build with make
|
||||
|
||||
2) Open regedit and add
|
||||
Windows Registry Editor Version 5.00
|
||||
Create systemd unit file:
|
||||
```
|
||||
[HKEY_CLASSES_ROOT\vnc]
|
||||
@="URL:vnc Protocol"
|
||||
"URL Protocol"=""
|
||||
[Unit]
|
||||
Description=Easy NoVNC
|
||||
|
||||
[HKEY_CLASSES_ROOT\vnc\shell]
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/easy-novnc -a :8888 -H -P
|
||||
|
||||
[HKEY_CLASSES_ROOT\vnc\shell\open]
|
||||
|
||||
[HKEY_CLASSES_ROOT\vnc\shell\open\command]
|
||||
@="\"c:\\startVNC.bat\" \"%1\""
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
3) Download and install the plugin as usual
|
||||
|
||||
It will listen on 8888 port on local host.
|
||||
|
||||
|
||||
TODO: a lot of documentation
|
||||
Secure connection to server if you want, some ports are hardcoded in current status of plugin
|
||||
```
|
||||
<IfModule mod_ssl.c>
|
||||
<VirtualHost *:443>
|
||||
RewriteEngine On
|
||||
ProxyPreserveHost On
|
||||
ProxyRequests Off
|
||||
|
||||
# allow for upgrading to websockets
|
||||
RewriteEngine On
|
||||
RewriteCond %{HTTP:Upgrade} =websocket [NC]
|
||||
RewriteRule /(.*) ws://localhost:8888/$1 [P,L]
|
||||
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
|
||||
RewriteRule /glpi/(.*) http://localhost/glpi/$1 [P,L]
|
||||
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
|
||||
RewriteRule /(.*) http://localhost:8888/$1 [P,L]
|
||||
|
||||
ProxyPass "/" "http://localhost:8888/"
|
||||
ProxyPassReverse "/" "http://localhost:8888/"
|
||||
|
||||
ProxyPass "/glpi/" "http://localhost/glpi/"
|
||||
ProxyPassReverse "/glpi/" "http://localhost/glpi/"
|
||||
|
||||
ProxyPass "/vnc" "ws://localhost:8888/vnc"
|
||||
ProxyPassReverse "/vnc" "ws://localhost:8888/vnc
|
||||
|
||||
|
||||
ServerName server.name.lan
|
||||
|
||||
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
|
||||
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
|
||||
|
||||
</VirtualHost>
|
||||
</IfModule>
|
||||
```
|
||||
|
||||
4
bin/README.md
Normal file
4
bin/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# Go program for remotesupport plugin
|
||||
|
||||
- binnary program for checking states of hosts
|
||||
|
||||
137
check_status.go
Normal file
137
check_status.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"net/http"
|
||||
"time"
|
||||
"io/ioutil"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// a struct to hold the result from each request including an index
|
||||
// which will be used for sorting the results after they come in
|
||||
type result struct {
|
||||
id int
|
||||
status int
|
||||
err error
|
||||
}
|
||||
|
||||
type check struct {
|
||||
// defining struct variables
|
||||
Url string `json:"url"`
|
||||
Id int `json:"id"`
|
||||
Computers_id int `json:"computers_id"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
|
||||
func boundedParallelGet(Checks []check, concurrencyLimit int) []check {
|
||||
|
||||
// this buffered channel will block at the concurrency limit
|
||||
semaphoreChan := make(chan struct{}, concurrencyLimit)
|
||||
|
||||
// this channel will not block and collect the http request results
|
||||
resultsChan := make(chan *result)
|
||||
|
||||
// make sure we close these channels when we're done with them
|
||||
defer func() {
|
||||
close(semaphoreChan)
|
||||
close(resultsChan)
|
||||
}()
|
||||
|
||||
// keen an index and loop through every url we will send a request to
|
||||
for _,chck := range Checks {
|
||||
|
||||
// start a go routine with the index and url in a closure
|
||||
go func(chck check) {
|
||||
var status int
|
||||
|
||||
// this sends an empty struct into the semaphoreChan which
|
||||
// is basically saying add one to the limit, but when the
|
||||
// limit has been reached block until there is room
|
||||
semaphoreChan <- struct{}{}
|
||||
|
||||
// send the request and put the response in a result struct
|
||||
// along with the index so we can sort them later along with
|
||||
// any error that might have occoured
|
||||
//fmt.Println(chck.Url)
|
||||
client := http.Client{
|
||||
Timeout: 7 * time.Second,
|
||||
}
|
||||
|
||||
res, err := client.Get(chck.Url)
|
||||
status = 404
|
||||
if err == nil {
|
||||
status = res.StatusCode
|
||||
}
|
||||
|
||||
result := &result{chck.Id, status, err}
|
||||
// now we can send the result struct through the resultsChan
|
||||
resultsChan <- result
|
||||
|
||||
// once we're done it's we read from the semaphoreChan which
|
||||
// has the effect of removing one from the limit and allowing
|
||||
// another goroutine to start
|
||||
<-semaphoreChan
|
||||
}(chck)
|
||||
}
|
||||
|
||||
// make a slice to hold the results we're expecting
|
||||
var results []result
|
||||
|
||||
// start listening for any results over the resultsChan
|
||||
// once we get a result append it to the result slice
|
||||
for {
|
||||
result := <-resultsChan
|
||||
results = append(results, *result)
|
||||
|
||||
// if we've reached the expected amount of urls then stop
|
||||
if len(results) == len(Checks) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var ret []check
|
||||
for i := range results {
|
||||
ch := m[results[i].id]
|
||||
if results[i].status == 200 {
|
||||
ch.Status = "OK"
|
||||
ret = append(ret,*ch)
|
||||
}
|
||||
}
|
||||
// now we're done we return the results
|
||||
return ret
|
||||
}
|
||||
|
||||
var checks []check
|
||||
var m = make(map[int]*check)
|
||||
func init() {
|
||||
|
||||
bytes, _ := ioutil.ReadAll(os.Stdin)
|
||||
json.Unmarshal(bytes , &checks)
|
||||
for i := range checks {
|
||||
m[checks[i].Id] = &checks[i]
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
// str_debug := os.Getenv("debug")
|
||||
str_threads := os.Getenv("threads")
|
||||
|
||||
threads, _ := strconv.Atoi(str_threads)
|
||||
// debug, _ := strconv.ParseBool(str_debug)
|
||||
|
||||
//startTime := time.Now()
|
||||
results := boundedParallelGet(checks, threads)
|
||||
//seconds := time.Since(startTime).Seconds()
|
||||
//tmplate := "requests: %d/%d in %v"
|
||||
|
||||
// fmt.Printf(tmplate, len(results), len(checks), seconds)
|
||||
|
||||
val,_ := json.MarshalIndent(results, "", " ")
|
||||
fmt.Print(string(val))
|
||||
}
|
||||
|
||||
175
hook.php
175
hook.php
@@ -1,63 +1,136 @@
|
||||
<?php
|
||||
/*
|
||||
-------------------------------------------------------------------------
|
||||
Remote Spport (VNC)
|
||||
Copyright (C) 2021 by Alessandro Carloni
|
||||
https://github.com/Kaya84/RemoteSupport
|
||||
-------------------------------------------------------------------------
|
||||
Remote Spport (VNC)
|
||||
Copyright (C) 2021 by Alessandro Carloni
|
||||
https://github.com/Kaya84/RemoteSupport
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
LICENSE
|
||||
This file is part of Camera Input.
|
||||
Camera Input is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
Camera Input is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Camera Input. If not, see <http://www.gnu.org/licenses/>.
|
||||
--------------------------------------------------------------------------
|
||||
*/
|
||||
-------------------------------------------------------------------------
|
||||
LICENSE
|
||||
This file is part of Camera Input.
|
||||
Camera Input is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
Camera Input is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Camera Input. If not, see <http://www.gnu.org/licenses/>.
|
||||
--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
function plugin_remotesupport_install(){
|
||||
return true;
|
||||
function plugin_remotesupport_install()
|
||||
{
|
||||
global $DB;
|
||||
|
||||
$config = new Config();
|
||||
$config->setConfigurationValues('plugin:Remotesupport',
|
||||
['run_mode' => 'None',
|
||||
'threads' => 100,
|
||||
'show_in_tickets' => true,
|
||||
'show_in_computers' => true,
|
||||
'easy_novnc' => true,
|
||||
'fusion' => true]
|
||||
);
|
||||
|
||||
Toolbox::logInFile("remotesupport", "Installing plugin");
|
||||
$state_online = [
|
||||
'name' => 'Online',
|
||||
'entities_id' => 0,
|
||||
'is_recursive' => 0,
|
||||
'comment' => '',
|
||||
'states_id' => 0,
|
||||
'completename' => 'Online',
|
||||
'level' => 1,
|
||||
'ancestors_cache' => '[]',
|
||||
'sons_cache' => 'NULL',
|
||||
'is_visible_computer' => 1,
|
||||
'is_visible_monitor' => 0,
|
||||
'is_visible_networkequipment' => 0,
|
||||
'is_visible_peripheral' => 0,
|
||||
'is_visible_phone' => 0,
|
||||
'is_visible_printer' => 0,
|
||||
'is_visible_softwareversion' => 0,
|
||||
'is_visible_softwarelicense' => 0,
|
||||
'is_visible_line' => 0,
|
||||
'is_visible_certificate' => 0,
|
||||
'is_visible_rack' => 0,
|
||||
'is_visible_passivedcequipment' => 0,
|
||||
'is_visible_enclosure' => 0,
|
||||
'is_visible_pdu' => 0,
|
||||
'is_visible_cluster' => 0,
|
||||
'is_visible_contract' => 0,
|
||||
'is_visible_appliance' => 0];
|
||||
|
||||
$ret = $DB->insert(
|
||||
'glpi_states', $state_online
|
||||
);
|
||||
|
||||
$state_offline = $state_online;
|
||||
$state_offline["name"] = 'Offline';
|
||||
$state_offline["completename"] = 'Offline';
|
||||
|
||||
$ret = $DB->insert(
|
||||
'glpi_states', $state_offline
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function plugin_remotesupport_uninstall(){
|
||||
return true;
|
||||
function plugin_remotesupport_uninstall()
|
||||
{
|
||||
global $DB;
|
||||
|
||||
Toolbox::logInFile("remotsupport", "Uninstalling plugin");
|
||||
CronTask::Unregister('remotesupport');
|
||||
|
||||
$req = $DB->request('glpi_states', ['FIELDS' => ['glpi_states' => ['id', 'name']]], ['OR' => ['name' => 'Online', 'name' => 'Offline']]);
|
||||
|
||||
$ret = $req->next();
|
||||
$states_ids[$ret['name']] = $ret['id'];
|
||||
$ret = $req->next();
|
||||
$states_ids[$ret['name']] = $ret['id'];
|
||||
|
||||
$DB->query('UPDATE glpi_computers SET states_id=NULL WHERE id=' . $states_ids["Offline"]);
|
||||
$DB->query('UPDATE glpi_computers SET states_id=NULL WHERE id=' . $states_ids["Online"]);
|
||||
$DB->query('DELETE FROM glpi_states WHERE id=' . $states_ids["Offline"]);
|
||||
$DB->query('DELETE FROM glpi_states WHERE id=' . $states_ids["Online"]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function plugin_remotesupport_postinit() {
|
||||
global $CFG_GLPI, $DB;
|
||||
function plugin_remotesupport_postinit()
|
||||
{
|
||||
global $CFG_GLPI, $DB;
|
||||
$config = Config::getConfigurationValues('plugin:Remotesupport');
|
||||
|
||||
if(isset($_GET['id']) && $_GET['id'] != 0 && isset($_GET['_itemtype']) && $_GET['_itemtype'] == "Ticket"){
|
||||
$id = $_GET['id'];
|
||||
|
||||
//mysql> select * from glpi_tickets_users where tickets_id = 2 and type = 1;
|
||||
|
||||
$req = $DB->request(['FROM' => 'glpi_tickets_users', 'WHERE' => ['tickets_id' => $id, 'type' => 1]]);
|
||||
//NB: Estraggo unicamente il primo richiedente
|
||||
$row = $req->next();
|
||||
$requester = $row['users_id'];
|
||||
// select id, name, users_id from glpi_computers where users_id = 178;
|
||||
|
||||
if ($row['users_id'] != 0) {
|
||||
$req2 = $DB->request(['FROM' => 'glpi_computers', 'WHERE' => ['users_id' => $requester, 'is_deleted' => 0]]);
|
||||
$url = "";
|
||||
if (isset($_GET['id']) && $_GET['id'] != 0 && isset($_GET['_itemtype']) && $_GET['_itemtype'] == "Ticket" && $config["show_in_tickets"]) {
|
||||
$id = $_GET['id'];
|
||||
|
||||
while ($row2 = $req2->next()){
|
||||
//$url .= "<li class=\"document\" onclick=\"location.href='vnc://" . $row2['name'] ."'\"$
|
||||
$url .= "<li class=\"document\" onclick=\"location.href='vnc://" . $row2['name'] ."'\"><i class=\"fa fa-laptop-medical\"></i>" . $row2['name'] . "</li>";
|
||||
}
|
||||
//mysql> select * from glpi_tickets_users where tickets_id = 2 and type = 1;
|
||||
|
||||
if ($url != ""){
|
||||
echo "<div><ul class=\"timeline_choices\"><h2>Remote support : </h2>";
|
||||
echo $url;
|
||||
echo "</ul></div>";
|
||||
}
|
||||
}
|
||||
}
|
||||
$req = $DB->request(['FROM' => 'glpi_tickets_users', 'WHERE' => ['tickets_id' => $id, 'type' => 1]]);
|
||||
//NB: Estraggo unicamente il primo richiedente
|
||||
$row = $req->next();
|
||||
$requester = $row['users_id'];
|
||||
// select id, name, users_id from glpi_computers where users_id = 178;
|
||||
|
||||
if ($row['users_id'] != 0) {
|
||||
$req2 = $DB->request(['FROM' => 'glpi_computers', 'WHERE' => ['users_id' => $requester, 'is_deleted' => 0]]);
|
||||
$url = "";
|
||||
|
||||
while ($row2 = $req2->next()) {
|
||||
//$url .= "<li class=\"document\" onclick=\"location.href='vnc://" . $row2['name'] ."'\"$
|
||||
$url .= "<li class=\"document\" onclick=\"location.href='vnc://" . $row2['name'] . "'\"><i class=\"fa fa-laptop-medical\"></i>" . $row2['name'] . "</li>";
|
||||
}
|
||||
|
||||
if ($url != "") {
|
||||
echo "<div><ul class=\"timeline_choices\"><h2>Remote support : </h2>";
|
||||
echo $url;
|
||||
echo "</ul></div>";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
1
inc/.gitigonre
Normal file
1
inc/.gitigonre
Normal file
@@ -0,0 +1 @@
|
||||
bin/check_status
|
||||
112
inc/config.class.php
Normal file
112
inc/config.class.php
Normal file
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
/*
|
||||
* @version $Id$
|
||||
-------------------------------------------------------------------------
|
||||
GLPI - Gestionnaire Libre de Parc Informatique
|
||||
Copyright (C) 2003-2011 by the INDEPNET Development Team.
|
||||
http://indepnet.net/ http://glpi-project.org
|
||||
-------------------------------------------------------------------------
|
||||
LICENSE
|
||||
This file is part of GLPI.
|
||||
GLPI is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
GLPI is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GLPI. If not, see <http://www.gnu.org/licenses/>.
|
||||
--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
class PluginRemotesupportConfig extends CommonDBTM {
|
||||
|
||||
static protected $notable = true;
|
||||
|
||||
function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) {
|
||||
|
||||
if (!$withtemplate) {
|
||||
if ($item->getType() == 'Config') {
|
||||
return __('Remote Support plugin');
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
static function configUpdate($input) {
|
||||
$input['configuration'] = 1 - $input['configuration'];
|
||||
return $input;
|
||||
}
|
||||
|
||||
function showFormRemotesupport() {
|
||||
global $CFG_GLPI;
|
||||
|
||||
if (!Session::haveRight("config", UPDATE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$my_config = Config::getConfigurationValues('plugin:Remotesupport');
|
||||
|
||||
echo "<form name='form' action=\"".Toolbox::getItemTypeFormURL('Config')."\" method='post'>";
|
||||
echo "<div class='center' id='tabsbody'>";
|
||||
echo "<table class='tab_cadre_fixe'>";
|
||||
echo "<input type='hidden' name='config_class' value='".__CLASS__."'>";
|
||||
echo "<input type='hidden' name='config_context' value='plugin:Remotesupport'>";
|
||||
echo "<tr><th colspan='4'>" . __('Remote support setup') . "</th></tr>";
|
||||
echo "<tr>";
|
||||
echo "<td >" . __('Run Mode:') . "</td>";
|
||||
echo "<td>";
|
||||
Dropdown::showFromArray('run_mode', array('None' => __('None'),'Serial'=>__('Serial'),'Parallel' => __('Parallel')), array('value' => $my_config['run_mode']));
|
||||
echo "</td>";
|
||||
echo "<td >" . __('EasyNoVNC Installed:') . "</td>";
|
||||
echo "<td>";
|
||||
Dropdown::showYesNo("easy_novnc", $my_config['easy_novnc']);
|
||||
echo "</td></tr>";
|
||||
echo "<tr>";
|
||||
echo "<td >" . __('Show in Computers:') . "</td>";
|
||||
echo "<td>";
|
||||
Dropdown::showYesNo("show_in_computers", $my_config['show_in_computers']);
|
||||
echo "</td>";
|
||||
echo "<td >" . __('Show in Tickets:') . "</td>";
|
||||
echo "<td>";
|
||||
Dropdown::showYesNo("show_in_tickets", $my_config['show_in_tickets']);
|
||||
echo "</td>";
|
||||
echo "</tr>";
|
||||
|
||||
echo "<tr>";
|
||||
echo "<td >" . __('Threads:') . "</td>";
|
||||
echo "<td>";
|
||||
Dropdown::showNumber("threads",
|
||||
[
|
||||
'value' => 100,
|
||||
'min' => 1,
|
||||
'max' => 100
|
||||
]);
|
||||
echo "</td>";
|
||||
echo "<td >" . __('Fusion inventory:') . "</td>";
|
||||
echo "<td>";
|
||||
Dropdown::showYesNo("fusion", $my_config['fusion']);
|
||||
echo "</td>";
|
||||
|
||||
echo "</tr>";
|
||||
|
||||
echo "<tr class='tab_bg_2'>";
|
||||
echo "<td colspan='4' class='center'>";
|
||||
echo "<input type='submit' name='update' class='submit' value=\""._sx('button', 'Save')."\">";
|
||||
echo "</td></tr>";
|
||||
|
||||
echo "</table></div>";
|
||||
Html::closeForm();
|
||||
}
|
||||
|
||||
static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) {
|
||||
|
||||
if ($item->getType() == 'Config') {
|
||||
$config = new self();
|
||||
$config->showFormRemotesupport();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
88
inc/remote_status.php
Normal file
88
inc/remote_status.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
include "../../../inc/includes.php";
|
||||
|
||||
declare (ticks = 1);
|
||||
|
||||
global $DB, $agents;
|
||||
|
||||
$check_arr = [];
|
||||
$comps = [];
|
||||
|
||||
$rs_path = Plugin::getPhpDir('remotesupport');
|
||||
|
||||
$pfConfig = new PluginFusioninventoryConfig();
|
||||
$port = $pfConfig->getValue('agent_port');
|
||||
|
||||
$pfInventoryComputerComputer = new PluginFusioninventoryInventoryComputerComputer();
|
||||
foreach (getAllDataFromTable(PluginFusioninventoryAgent::getTable()) as $a) {
|
||||
|
||||
$check = [];
|
||||
$a_computerextend = $pfInventoryComputerComputer->hasAutomaticInventory($a["computers_id"]);
|
||||
|
||||
$check["url"] = "http://" . $a_computerextend["remote_addr"] . ":" . $port . "/status";
|
||||
$check["id"] = $a["id"];
|
||||
$check["computers_id"] = $a["computers_id"];
|
||||
$check["status"] = "unknown";
|
||||
|
||||
$check_arr[] = $check;
|
||||
$comps[$a["computers_id"]] = $check;
|
||||
//print_r($agent->getAgentStatusURLs());
|
||||
}
|
||||
|
||||
$descriptorspec = array(
|
||||
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
|
||||
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
|
||||
2 => array("file", "/tmp/error-output.txt", "a"), // stderr is a file to write to
|
||||
);
|
||||
|
||||
$cwd = '/tmp';
|
||||
$env = array('debug' => 'false', 'threads' => 100);
|
||||
|
||||
$process = proc_open($rs_path . '/bin/check_status', $descriptorspec, $pipes, $cwd, $env);
|
||||
|
||||
if (is_resource($process)) {
|
||||
// $pipes now looks like this:
|
||||
// 0 => writeable handle connected to child stdin
|
||||
// 1 => readable handle connected to child stdout
|
||||
// Any error output will be appended to /tmp/error-output.txt
|
||||
|
||||
fwrite($pipes[0], json_encode($check_arr));
|
||||
fclose($pipes[0]);
|
||||
|
||||
$checked = json_decode(stream_get_contents($pipes[1]));
|
||||
fclose($pipes[1]);
|
||||
|
||||
// It is important that you close any pipes before calling
|
||||
// proc_close in order to avoid a deadlock
|
||||
$return_value = proc_close($process);
|
||||
|
||||
echo "command returned $return_value\n";
|
||||
}
|
||||
|
||||
$req = $DB->request('glpi_states', ['FIELDS' => ['glpi_states' => ['id', 'name']]], ['OR' => ['name' => 'Online', 'name' => 'Offline']]);
|
||||
|
||||
$ret = $req->next();
|
||||
$states_ids[$ret['name']] = $ret['id'];
|
||||
$ret = $req->next();
|
||||
$states_ids[$ret['name']] = $ret['id'];
|
||||
print_r($states_ids);
|
||||
|
||||
$DB->update("glpi_computers", [
|
||||
'states_id' => $states_ids["Offline"] ] ,
|
||||
[ '1' => '1' ]
|
||||
);
|
||||
|
||||
$ids = [];
|
||||
foreach ($checked as $s) {
|
||||
echo $s->computers_id."\n";
|
||||
$ids[] = $s->computers_id;
|
||||
}
|
||||
|
||||
$DB->update("glpi_computers", [
|
||||
'states_id' => $states_ids["Online"] ],
|
||||
[ 'id' => $ids ]
|
||||
);
|
||||
|
||||
// print_r($a_computerextend);
|
||||
exit(0);
|
||||
@@ -1,54 +1,222 @@
|
||||
<?php
|
||||
|
||||
if (!defined('GLPI_ROOT')) {
|
||||
die("Sorry. You can't access directly to this file");
|
||||
die("Sorry. You can't access directly to this file");
|
||||
}
|
||||
|
||||
class PluginRemotesupportRemotesupport extends CommonDBTM
|
||||
{
|
||||
public static function showInfo($item)
|
||||
{
|
||||
|
||||
$config = Config::getConfigurationValues('plugin:Remotesupport');
|
||||
|
||||
class PluginRemotesupportRemotesupport extends CommonDBTM {
|
||||
if ($config["show_in_computers"] == false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static function showInfo($item) {
|
||||
$statusids = self::getStatusArray();
|
||||
|
||||
$fi_path = Plugin::getWebDir('fusioninventory');
|
||||
if ($config["fusion"] == true && $config["easy_novnc"] == true) {
|
||||
$pfInventoryComputerComputer = new PluginFusioninventoryInventoryComputerComputer();
|
||||
$a_computerextend = $pfInventoryComputerComputer->hasAutomaticInventory($item->getID());
|
||||
if (empty($a_computerextend)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Manage locks pictures
|
||||
PluginFusioninventoryLock::showLockIcon('Computer');
|
||||
$href = "https://" . $_SERVER['SERVER_NAME'] . "/vnc.html?path=vnc%2F" . $a_computerextend['remote_addr'] . "&autoconnect=true&resize=scale&reconnect=true&show_dot=true";
|
||||
$name = $a_computerextend['remote_addr'];
|
||||
} else {
|
||||
$href = "vnc://" . $item->fields["name"];
|
||||
$name = $item->fields["name"];
|
||||
}
|
||||
echo '<table class="tab_glpi" width="100%">';
|
||||
echo '<tr>';
|
||||
echo '<th>' . __('Remote Support') . '</th>';
|
||||
echo '</tr>';
|
||||
echo '<tr class="tab_bg_1">';
|
||||
echo '<td>';
|
||||
|
||||
$pfInventoryComputerComputer = new PluginFusioninventoryInventoryComputerComputer();
|
||||
$a_computerextend = $pfInventoryComputerComputer->hasAutomaticInventory($item->getID());
|
||||
if (empty($a_computerextend)) {
|
||||
return true;
|
||||
}
|
||||
$style = $statusids[$item->getID()] == "Offline" ? "style=\"background-color: red\"" : "";
|
||||
$url = "<a target=\"_blank\" href=\"" . $href . "\"><li class=\"document\" ". $style ."><i class=\"fa fa-laptop-medical\"></i>" . $name . "</li></a>";
|
||||
|
||||
echo '<table class="tab_glpi" width="100%">';
|
||||
echo '<tr>';
|
||||
echo '<th>'.__('Remote Support').'</th>';
|
||||
echo '</tr>';
|
||||
echo '<tr class="tab_bg_1">';
|
||||
echo '<td>';
|
||||
|
||||
$url .= "<a target=\"_blank\" href=\"https://" . $_SERVER['SERVER_ADDR']. "/vnc.html?path=vnc%2F". $a_computerextend['remote_addr'] ."&autoconnect=true&resize=scale&reconnect=true&show_dot=true\"><li class=\"document\"><i class=\"fa fa-laptop-medical\"></i>" . $a_computerextend['remote_addr'] . "</li></a>";
|
||||
|
||||
if ($url != ""){
|
||||
if ($url != "") {
|
||||
echo "<div><ul class=\"timeline_choices\"><h2>VNC connect : </h2>";
|
||||
echo $url;
|
||||
echo "</ul></div>";
|
||||
}
|
||||
echo '</td>';
|
||||
echo '</tr>';
|
||||
echo '</table>';
|
||||
}
|
||||
echo '</td>';
|
||||
echo '</tr>';
|
||||
echo '</table>';
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static function cronRemotesupport($task) {
|
||||
Toolbox::logInFile("remotsupport",'Starting search of agents');
|
||||
return true;
|
||||
}
|
||||
public static function getStatesIds()
|
||||
{
|
||||
global $DB;
|
||||
|
||||
static function cronInfo($name) {
|
||||
return [
|
||||
'description' => "Agent search remotesupport"];
|
||||
}
|
||||
$states_ids = [];
|
||||
|
||||
$req = $DB->request('glpi_states', ['FIELDS' => ['glpi_states' => ['id', 'name']]], ['OR' => ['name' => 'Online', 'name' => 'Offline']]);
|
||||
|
||||
$ret = $req->next();
|
||||
$states_ids[$ret['name']] = $ret['id'];
|
||||
$ret = $req->next();
|
||||
$states_ids[$ret['name']] = $ret['id'];
|
||||
|
||||
return $states_ids;
|
||||
}
|
||||
|
||||
public static function getContactArray()
|
||||
{
|
||||
global $DB;
|
||||
|
||||
$req = $DB->request('glpi_computers', ['FIELDS' => ['glpi_computers' => ['id', 'contact']]]);
|
||||
|
||||
$contactids = [];
|
||||
while ($ret = $req->next()) {
|
||||
$contactids[$ret["id"]] = $ret["contact"];
|
||||
}
|
||||
|
||||
return $contactids;
|
||||
}
|
||||
|
||||
public static function getStatusArray()
|
||||
{
|
||||
global $DB;
|
||||
|
||||
$st = self::getStatesIds();
|
||||
|
||||
$req = $DB->request('glpi_computers', ['FIELDS' => ['glpi_computers' => ['id', 'states_id']]]);
|
||||
|
||||
$statusids = [];
|
||||
while ($ret = $req->next()) {
|
||||
$statusids[$ret["id"]] = $ret["states_id"] == $st["Offline"] ? "Offline" : "Online";
|
||||
}
|
||||
|
||||
return $statusids;
|
||||
}
|
||||
|
||||
public static function cronRemotesupport($task)
|
||||
{
|
||||
global $DB;
|
||||
|
||||
$config = Config::getConfigurationValues('plugin:Remotesupport');
|
||||
|
||||
if ($config["fusion"] == false || $config["run_mode"] == "None") {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Toolbox::logInFile("remotesupport", "Starting search of agents\n");
|
||||
|
||||
if ($config["run_mode"] == "Parallel") {
|
||||
$pfConfig = new PluginFusioninventoryConfig();
|
||||
$port = $pfConfig->getValue('agent_port');
|
||||
$rs_path = Plugin::getPhpDir('remotesupport');
|
||||
|
||||
$check_arr = [];
|
||||
$comps = [];
|
||||
$pfInventoryComputerComputer = new PluginFusioninventoryInventoryComputerComputer();
|
||||
foreach (getAllDataFromTable(PluginFusioninventoryAgent::getTable()) as $a) {
|
||||
|
||||
$check = [];
|
||||
$a_computerextend = $pfInventoryComputerComputer->hasAutomaticInventory($a["computers_id"]);
|
||||
|
||||
$check["url"] = "http://" . $a_computerextend["remote_addr"] . ":" . $port . "/status";
|
||||
$check["id"] = $a["id"];
|
||||
$check["computers_id"] = $a["computers_id"];
|
||||
$check["status"] = "unknown";
|
||||
|
||||
$check_arr[] = $check;
|
||||
$comps[$a["computers_id"]] = $check;
|
||||
//print_r($agent->getAgentStatusURLs());
|
||||
}
|
||||
|
||||
$descriptorspec = array(
|
||||
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
|
||||
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
|
||||
2 => array("file", "/tmp/error-output.txt", "a"), // stderr is a file to write to
|
||||
);
|
||||
|
||||
$cwd = '/tmp';
|
||||
$env = array('debug' => 'false', 'threads' => $config["threads"]);
|
||||
|
||||
$process = proc_open($rs_path . '/bin/check_status', $descriptorspec, $pipes, $cwd, $env);
|
||||
|
||||
if (is_resource($process)) {
|
||||
// $pipes now looks like this:
|
||||
// 0 => writeable handle connected to child stdin
|
||||
// 1 => readable handle connected to child stdout
|
||||
// Any error output will be appended to /tmp/error-output.txt
|
||||
|
||||
fwrite($pipes[0], json_encode($check_arr));
|
||||
fclose($pipes[0]);
|
||||
|
||||
$checked = json_decode(stream_get_contents($pipes[1]));
|
||||
fclose($pipes[1]);
|
||||
|
||||
// It is important that you close any pipes before calling
|
||||
// proc_close in order to avoid a deadlock
|
||||
$return_value = proc_close($process);
|
||||
|
||||
Toolbox::logInFile("remotesupport", "command returned $return_value\n");
|
||||
}
|
||||
|
||||
} else {
|
||||
$agents = [];
|
||||
$data_set = [];
|
||||
$checked = [];
|
||||
|
||||
foreach (getAllDataFromTable(PluginFusioninventoryAgent::getTable()) as $a) {
|
||||
|
||||
$data_set[] = $a["id"];
|
||||
$agents[$a["id"]] = $a;
|
||||
}
|
||||
|
||||
foreach ($data_set as $id) {
|
||||
$agent = new PluginFusioninventoryAgent;
|
||||
$agent->getFromDB((int) $id);
|
||||
$st = $agent->getStatus();
|
||||
|
||||
if ($st["message"] != "noanswer") {
|
||||
$check = new stdClass();
|
||||
$check->computers_id = $agents[$id]["computers_id"];
|
||||
$checked[] = $check;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$stids = self::getStatesIds();
|
||||
|
||||
$DB->update("glpi_computers", [
|
||||
'states_id' => $stids["Offline"]],
|
||||
['1' => '1']
|
||||
);
|
||||
|
||||
$ids = [];
|
||||
$cids = self::getContactArray();
|
||||
|
||||
foreach ($checked as $s) {
|
||||
|
||||
$comp = new Computer();
|
||||
$comp->getFromDB($s->computers_id);
|
||||
Toolbox::logInFile("remotesupport", $s->computers_id . " " . $cids[$s->computers_id] . "\n");
|
||||
$ids[] = $s->computers_id;
|
||||
}
|
||||
|
||||
$DB->update("glpi_computers", [
|
||||
'states_id' => $stids["Online"]],
|
||||
['id' => $ids]
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static function cronInfo($name)
|
||||
{
|
||||
return [
|
||||
'description' => __('Agent search remotesupport')];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
</authors>
|
||||
<versions>
|
||||
<version>
|
||||
<num>0.0.1</num>
|
||||
<num>0.0.2</num>
|
||||
<compatibility>~9.5.0</compatibility>
|
||||
</version>
|
||||
</versions>
|
||||
|
||||
101
setup.php
101
setup.php
@@ -1,25 +1,25 @@
|
||||
<?php
|
||||
/*
|
||||
-------------------------------------------------------------------------
|
||||
Remote Spport (VNC)
|
||||
Copyright (C) 2021 by Alessandro Carloni
|
||||
https://github.com/Kaya84/RemoteSupport
|
||||
-------------------------------------------------------------------------
|
||||
Remote Spport (VNC)
|
||||
Copyright (C) 2021 by Alessandro Carloni
|
||||
https://github.com/Kaya84/RemoteSupport
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
LICENSE
|
||||
This file is part of Camera Input.
|
||||
Camera Input is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
Camera Input is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Camera Input. If not, see <http://www.gnu.org/licenses/>.
|
||||
--------------------------------------------------------------------------
|
||||
*/
|
||||
-------------------------------------------------------------------------
|
||||
LICENSE
|
||||
This file is part of Camera Input.
|
||||
Camera Input is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
Camera Input is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Camera Input. If not, see <http://www.gnu.org/licenses/>.
|
||||
--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
define('PLUGIN_REMOTESUPPORT_VERSION', '0.0.1');
|
||||
define('PLUGIN_REMOTESUPPORT_MIN_GLPI', '9.5.0');
|
||||
@@ -28,49 +28,40 @@ define("PLUGIN_REMOTESUPPORT_DIR", GLPI_ROOT . "/plugins/remotesupport");
|
||||
|
||||
function plugin_init_remotesupport()
|
||||
{
|
||||
global $PLUGIN_HOOKS;
|
||||
$PLUGIN_HOOKS['csrf_compliant']['remotesupport'] = true;
|
||||
global $PLUGIN_HOOKS;
|
||||
$PLUGIN_HOOKS['csrf_compliant']['remotesupport'] = true;
|
||||
|
||||
if (Plugin::isPluginActive('remotesupport')) {
|
||||
|
||||
// $PLUGIN_HOOKS['add_javascript']['remotesupport'][] = 'js/support.js';
|
||||
// include(PLUGIN_REMOTESUPPORT_DIR . "/inc/remotesupport.class.php");
|
||||
if (Plugin::isPluginActive('remotesupport')) {
|
||||
|
||||
$PLUGIN_HOOKS['autoinventory_information']['remotesupport'] = array(
|
||||
'Computer' => array('PluginRemotesupportRemotesupport', 'showInfo')
|
||||
);
|
||||
$PLUGIN_HOOKS['autoinventory_information']['remotesupport'] = array(
|
||||
'Computer' => array('PluginRemotesupportRemotesupport', 'showInfo'),
|
||||
);
|
||||
|
||||
CronTask::Register('PluginRemotesupportRemotesupport', 'remotesupport', DAY_TIMESTAMP, [
|
||||
'param' => 24,
|
||||
'mode' => CronTask::MODE_EXTERNAL
|
||||
]);
|
||||
Plugin::registerClass('PluginRemotesupportConfig', ['addtabon' => 'Config']);
|
||||
|
||||
// Add Config Page
|
||||
// Plugin::registerClass('PluginRemotesupportConfig', ['addtabon' => 'Config']);
|
||||
|
||||
// $PLUGIN_HOOKS["menu_toadd"]['remotesupport'] = ['tools' => 'PluginRemotesupportMenu'];
|
||||
// $PLUGIN_HOOKS['config_page']['remotesupport'] = 'front/index.php';
|
||||
$PLUGIN_HOOKS['menu']['remotesupport'] = true;
|
||||
$PLUGIN_HOOKS['post_init']['remotesupport'] = 'plugin_remotesupport_postinit';
|
||||
CronTask::Register('PluginRemotesupportRemotesupport', 'remotesupport', 300,
|
||||
['mode' => 2, 'allowmode' => 3, 'logs_lifetime' => 30,
|
||||
'comment' => 'Remotesupport crontab search agents']);
|
||||
|
||||
|
||||
}
|
||||
$PLUGIN_HOOKS['menu']['remotesupport'] = true;
|
||||
$PLUGIN_HOOKS['post_init']['remotesupport'] = 'plugin_remotesupport_postinit';
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function plugin_version_remotesupport()
|
||||
{
|
||||
return [
|
||||
'name' => __('Remote Support Input', 'remotesupport'),
|
||||
'version' => PLUGIN_REMOTESUPPORT_VERSION,
|
||||
'author' => 'Alessandro Carloni',
|
||||
'license' => 'GPLv2',
|
||||
'homepage' =>'https://github.com/Kaya84/',
|
||||
'requirements' => [
|
||||
'glpi' => [
|
||||
'min' => PLUGIN_REMOTESUPPORT_MIN_GLPI,
|
||||
'max' => PLUGIN_REMOTESUPPORT_MAX_GLPI
|
||||
]
|
||||
]
|
||||
];
|
||||
return [
|
||||
'name' => __('Remote Support Input', 'remotesupport'),
|
||||
'version' => PLUGIN_REMOTESUPPORT_VERSION,
|
||||
'author' => 'Alessandro Carloni',
|
||||
'license' => 'GPLv2',
|
||||
'homepage' => 'https://github.com/Kaya84/',
|
||||
'requirements' => [
|
||||
'glpi' => [
|
||||
'min' => PLUGIN_REMOTESUPPORT_MIN_GLPI,
|
||||
'max' => PLUGIN_REMOTESUPPORT_MAX_GLPI,
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user