refs #311 removes a lot of innecesaries directories and files
parent
a6d884ec6f
commit
e595d248c7
File diff suppressed because it is too large
Load Diff
|
@ -1,15 +0,0 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
|
||||
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
|
||||
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
|
||||
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true],
|
||||
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
|
||||
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
|
||||
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
|
||||
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
|
||||
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
|
||||
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
||||
App\OgBootBundle\OgBootBundle::class => ['all' => true],
|
||||
];
|
|
@ -1,19 +0,0 @@
|
|||
framework:
|
||||
cache:
|
||||
# Unique name of your app: used to compute stable namespaces for cache keys.
|
||||
#prefix_seed: your_vendor_name/app_name
|
||||
|
||||
# The "app" cache stores to the filesystem by default.
|
||||
# The data in this cache should persist between deploys.
|
||||
# Other options include:
|
||||
|
||||
# Redis
|
||||
#app: cache.adapter.redis
|
||||
#default_redis_provider: redis://localhost
|
||||
|
||||
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
|
||||
#app: cache.adapter.apcu
|
||||
|
||||
# Namespaced pools use the above "app" backend by default
|
||||
#pools:
|
||||
#my.dedicated.cache: null
|
|
@ -1,5 +0,0 @@
|
|||
when@dev:
|
||||
debug:
|
||||
# Forwards VarDumper Data clones to a centralized server allowing to inspect dumps on CLI or in your browser.
|
||||
# See the "server:dump" command to start a new server.
|
||||
dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%"
|
|
@ -1,43 +0,0 @@
|
|||
doctrine:
|
||||
dbal:
|
||||
url: '%env(resolve:DATABASE_URL)%'
|
||||
|
||||
# IMPORTANT: You MUST configure your server version,
|
||||
# either here or in the DATABASE_URL env var (see .env file)
|
||||
#server_version: '15'
|
||||
orm:
|
||||
auto_generate_proxy_classes: true
|
||||
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
|
||||
auto_mapping: true
|
||||
mappings:
|
||||
App:
|
||||
is_bundle: false
|
||||
dir: '%kernel.project_dir%/src/Entity'
|
||||
prefix: 'App\Entity'
|
||||
alias: App
|
||||
|
||||
when@test:
|
||||
doctrine:
|
||||
dbal:
|
||||
# "TEST_TOKEN" is typically set by ParaTest
|
||||
dbname_suffix: '_test%env(default::TEST_TOKEN)%'
|
||||
|
||||
when@prod:
|
||||
doctrine:
|
||||
orm:
|
||||
auto_generate_proxy_classes: false
|
||||
proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies'
|
||||
query_cache_driver:
|
||||
type: pool
|
||||
pool: doctrine.system_cache_pool
|
||||
result_cache_driver:
|
||||
type: pool
|
||||
pool: doctrine.result_cache_pool
|
||||
|
||||
framework:
|
||||
cache:
|
||||
pools:
|
||||
doctrine.result_cache_pool:
|
||||
adapter: cache.app
|
||||
doctrine.system_cache_pool:
|
||||
adapter: cache.system
|
|
@ -1,6 +0,0 @@
|
|||
doctrine_migrations:
|
||||
migrations_paths:
|
||||
# namespace is arbitrary but should be different from App\Migrations
|
||||
# as migrations classes should NOT be autoloaded
|
||||
'DoctrineMigrations': '%kernel.project_dir%/migrations'
|
||||
enable_profiler: false
|
|
@ -1,24 +0,0 @@
|
|||
# see https://symfony.com/doc/current/reference/configuration/framework.html
|
||||
framework:
|
||||
secret: '%env(APP_SECRET)%'
|
||||
#csrf_protection: true
|
||||
http_method_override: false
|
||||
|
||||
# Enables session support. Note that the session will ONLY be started if you read or write from it.
|
||||
# Remove or comment this section to explicitly disable session support.
|
||||
session:
|
||||
handler_id: null
|
||||
cookie_secure: auto
|
||||
cookie_samesite: lax
|
||||
storage_factory_id: session.storage.factory.native
|
||||
|
||||
#esi: true
|
||||
#fragments: true
|
||||
php_errors:
|
||||
log: true
|
||||
|
||||
when@test:
|
||||
framework:
|
||||
test: true
|
||||
session:
|
||||
storage_factory_id: session.storage.factory.mock_file
|
|
@ -1,3 +0,0 @@
|
|||
framework:
|
||||
mailer:
|
||||
dsn: '%env(MAILER_DSN)%'
|
|
@ -1,24 +0,0 @@
|
|||
framework:
|
||||
messenger:
|
||||
failure_transport: failed
|
||||
|
||||
transports:
|
||||
# https://symfony.com/doc/current/messenger.html#transport-configuration
|
||||
async:
|
||||
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
|
||||
options:
|
||||
use_notify: true
|
||||
check_delayed_interval: 60000
|
||||
retry_strategy:
|
||||
max_retries: 3
|
||||
multiplier: 2
|
||||
failed: 'doctrine://default?queue_name=failed'
|
||||
# sync: 'sync://'
|
||||
|
||||
routing:
|
||||
Symfony\Component\Mailer\Messenger\SendEmailMessage: async
|
||||
Symfony\Component\Notifier\Message\ChatMessage: async
|
||||
Symfony\Component\Notifier\Message\SmsMessage: async
|
||||
|
||||
# Route your messages to the transports
|
||||
# 'App\Message\YourMessage': async
|
|
@ -1,61 +0,0 @@
|
|||
monolog:
|
||||
channels:
|
||||
- deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists
|
||||
|
||||
when@dev:
|
||||
monolog:
|
||||
handlers:
|
||||
main:
|
||||
type: stream
|
||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||
level: debug
|
||||
channels: ["!event"]
|
||||
# uncomment to get logging in your browser
|
||||
# you may have to allow bigger header sizes in your Web server configuration
|
||||
#firephp:
|
||||
# type: firephp
|
||||
# level: info
|
||||
#chromephp:
|
||||
# type: chromephp
|
||||
# level: info
|
||||
console:
|
||||
type: console
|
||||
process_psr_3_messages: false
|
||||
channels: ["!event", "!doctrine", "!console"]
|
||||
|
||||
when@test:
|
||||
monolog:
|
||||
handlers:
|
||||
main:
|
||||
type: fingers_crossed
|
||||
action_level: error
|
||||
handler: nested
|
||||
excluded_http_codes: [404, 405]
|
||||
channels: ["!event"]
|
||||
nested:
|
||||
type: stream
|
||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||
level: debug
|
||||
|
||||
when@prod:
|
||||
monolog:
|
||||
handlers:
|
||||
main:
|
||||
type: fingers_crossed
|
||||
action_level: error
|
||||
handler: nested
|
||||
excluded_http_codes: [404, 405]
|
||||
buffer_size: 50 # How many messages should be saved? Prevent memory leaks
|
||||
nested:
|
||||
type: stream
|
||||
path: php://stderr
|
||||
level: debug
|
||||
formatter: monolog.formatter.json
|
||||
console:
|
||||
type: console
|
||||
process_psr_3_messages: false
|
||||
channels: ["!event", "!doctrine"]
|
||||
deprecation:
|
||||
type: stream
|
||||
channels: [deprecation]
|
||||
path: php://stderr
|
|
@ -1,12 +0,0 @@
|
|||
framework:
|
||||
notifier:
|
||||
chatter_transports:
|
||||
texter_transports:
|
||||
channel_policy:
|
||||
# use chat/slack, chat/telegram, sms/twilio or sms/nexmo
|
||||
urgent: ['email']
|
||||
high: ['email']
|
||||
medium: ['email']
|
||||
low: ['email']
|
||||
admin_recipients:
|
||||
- { email: admin@example.com }
|
|
@ -1,12 +0,0 @@
|
|||
framework:
|
||||
router:
|
||||
utf8: true
|
||||
|
||||
# Configure how to generate URLs in non-HTTP contexts, such as CLI commands.
|
||||
# See https://symfony.com/doc/current/routing.html#generating-urls-in-commands
|
||||
#default_uri: http://localhost
|
||||
|
||||
when@prod:
|
||||
framework:
|
||||
router:
|
||||
strict_requirements: null
|
|
@ -1,40 +0,0 @@
|
|||
security:
|
||||
enable_authenticator_manager: true
|
||||
# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
|
||||
password_hashers:
|
||||
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
|
||||
# https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
|
||||
providers:
|
||||
users_in_memory: { memory: null }
|
||||
firewalls:
|
||||
dev:
|
||||
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
||||
security: false
|
||||
main:
|
||||
lazy: true
|
||||
provider: users_in_memory
|
||||
|
||||
# activate different ways to authenticate
|
||||
# https://symfony.com/doc/current/security.html#the-firewall
|
||||
|
||||
# https://symfony.com/doc/current/security/impersonating_user.html
|
||||
# switch_user: true
|
||||
|
||||
# Easy way to control access for large sections of your site
|
||||
# Note: Only the *first* access control that matches will be used
|
||||
access_control:
|
||||
# - { path: ^/admin, roles: ROLE_ADMIN }
|
||||
# - { path: ^/profile, roles: ROLE_USER }
|
||||
|
||||
when@test:
|
||||
security:
|
||||
password_hashers:
|
||||
# By default, password hashers are resource intensive and take time. This is
|
||||
# important to generate secure password hashes. In tests however, secure hashes
|
||||
# are not important, waste resources and increase test times. The following
|
||||
# reduces the work factor to the lowest possible values.
|
||||
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
|
||||
algorithm: auto
|
||||
cost: 4 # Lowest possible value for bcrypt
|
||||
time_cost: 3 # Lowest possible value for argon
|
||||
memory_cost: 10 # Lowest possible value for argon
|
|
@ -1,13 +0,0 @@
|
|||
framework:
|
||||
default_locale: en
|
||||
translator:
|
||||
default_path: '%kernel.project_dir%/translations'
|
||||
fallbacks:
|
||||
- en
|
||||
# providers:
|
||||
# crowdin:
|
||||
# dsn: '%env(CROWDIN_DSN)%'
|
||||
# loco:
|
||||
# dsn: '%env(LOCO_DSN)%'
|
||||
# lokalise:
|
||||
# dsn: '%env(LOKALISE_DSN)%'
|
|
@ -1,6 +0,0 @@
|
|||
twig:
|
||||
default_path: '%kernel.project_dir%/templates'
|
||||
|
||||
when@test:
|
||||
twig:
|
||||
strict_variables: true
|
|
@ -1,13 +0,0 @@
|
|||
framework:
|
||||
validation:
|
||||
email_validation_mode: html5
|
||||
|
||||
# Enables validator auto-mapping support.
|
||||
# For instance, basic validation constraints will be inferred from Doctrine's metadata.
|
||||
#auto_mapping:
|
||||
# App\Entity\: []
|
||||
|
||||
when@test:
|
||||
framework:
|
||||
validation:
|
||||
not_compromised_password: false
|
|
@ -1,15 +0,0 @@
|
|||
when@dev:
|
||||
web_profiler:
|
||||
toolbar: true
|
||||
intercept_redirects: false
|
||||
|
||||
framework:
|
||||
profiler: { only_exceptions: false }
|
||||
|
||||
when@test:
|
||||
web_profiler:
|
||||
toolbar: false
|
||||
intercept_redirects: false
|
||||
|
||||
framework:
|
||||
profiler: { collect: false }
|
|
@ -1,5 +0,0 @@
|
|||
<?php
|
||||
|
||||
if (file_exists(dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php')) {
|
||||
require dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php';
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
#index:
|
||||
# path: /
|
||||
# controller: App\Controller\DefaultController::index
|
|
@ -1,7 +0,0 @@
|
|||
controllers:
|
||||
resource: ../../src/OgBootBundle/Controller/
|
||||
type: annotation
|
||||
|
||||
kernel:
|
||||
resource: ../../src/Kernel.php
|
||||
type: annotation
|
|
@ -1,4 +0,0 @@
|
|||
when@dev:
|
||||
_errors:
|
||||
resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
|
||||
prefix: /_error
|
|
@ -1,8 +0,0 @@
|
|||
when@dev:
|
||||
web_profiler_wdt:
|
||||
resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml'
|
||||
prefix: /_wdt
|
||||
|
||||
web_profiler_profiler:
|
||||
resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml'
|
||||
prefix: /_profiler
|
|
@ -1,27 +0,0 @@
|
|||
# This file is the entry point to configure your own services.
|
||||
# Files in the packages/ subdirectory configure your dependencies.
|
||||
|
||||
# Put parameters here that don't need to change on each machine where the app is deployed
|
||||
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
|
||||
parameters:
|
||||
|
||||
services:
|
||||
# default configuration for services in *this* file
|
||||
_defaults:
|
||||
autowire: true # Automatically injects dependencies in your services.
|
||||
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
|
||||
|
||||
# makes classes in src/ available to be used as services
|
||||
# this creates a service per class whose id is the fully-qualified class name
|
||||
App\:
|
||||
resource: '../src/'
|
||||
exclude:
|
||||
- '../src/DependencyInjection/'
|
||||
- '../src/Entity/'
|
||||
- '../src/Kernel.php'
|
||||
|
||||
# add more service definitions when explicit configuration is needed
|
||||
# please note that last definitions always *replace* previous ones
|
||||
App\OgBootBundle\Controller\:
|
||||
resource: '../src/OgBootBundle/Controller'
|
||||
tags: ['controller.service_arguments']
|
|
@ -1,121 +0,0 @@
|
|||
## API de DHCP
|
||||
|
||||
La API de DHCP proporciona una interfaz para interactuar con el servidor DHCP de Kea. Esta API permite realizar operaciones como obtener la configuración actual del servidor DHCP, actualizar la configuración y obtener información sobre las reservas de direcciones IP.
|
||||
|
||||
Los endpoints están agrupados en el recurso al que hace referencia. Actualmente se gestionan dos recursos:
|
||||
|
||||
- `/dhcp/subnets/`: CRUD de subredes de Kea DHCP. Las subredes serán donde se organizarán los hosts y hacen referencia a las subredes montadas por el aula.
|
||||
- `/dhcp/subnets/hosts/`: CRUD de hosts en la configuración de Kea DHCP. Los hosts hacen referencia a los ordenadores dados de alta en las aulas. Esta sección en Kea DHCP se encarga de asignar, dada la MAC del dispositivo, la IP y el boot-file-name del ordenador.
|
||||
|
||||
El presente documento detalla los endpoints del API con sus respectivos parámetros de entrada así como los cambios que aplican sobre la configuración de Kea DHCP.
|
||||
|
||||
|
||||
|
||||
### Recurso `/dhcp/subnets`
|
||||
|
||||
#### Obtener configuración de las subredes
|
||||
|
||||
Devuelve las subredes dadas de alta en la configuración de Kea DHCP.
|
||||
|
||||
|
||||
**Método HTTP:** GET
|
||||
|
||||
**URL:** `/dhcp/subnets`
|
||||
|
||||
|
||||
#### Añadir subred
|
||||
|
||||
Añade un nueva subred a la configuración de Kea DHCP.
|
||||
|
||||
**Método HTTP:** POST
|
||||
|
||||
**URL:** `/dhcp/subnets`
|
||||
|
||||
**Parámetros de entrada:**
|
||||
|
||||
- `name`: Nombre de la subred.
|
||||
- `subnet`: DirecciónIP de la subred.
|
||||
- `boot-file-name`: Archivo de arranque de la subred.
|
||||
- `nextServer`: Dirección IP del next-server.
|
||||
|
||||
#### Borrar subred DHCP
|
||||
|
||||
Borrar una subred de la configuración de Kea DHCP.
|
||||
|
||||
**Método HTTP:** DELETE
|
||||
|
||||
**URL:** `/dhcp/subnets/{id_subnet}`
|
||||
|
||||
|
||||
#### Modificar Host DHCP
|
||||
|
||||
Modificar la subred en la configuración de Kea DHCP.
|
||||
|
||||
**Método HTTP:** PUT
|
||||
|
||||
**URL:** `/dhcp/subnets/{id_subnet}`
|
||||
|
||||
**Parámetros de entrada:**
|
||||
|
||||
- `name`: Nombre de la subred.
|
||||
- `subnet`: DirecciónIP de la subred.
|
||||
- `boot-file-name`: Archivo de arranque de la subred.
|
||||
- `nextServer`: Dirección IP del next-server.
|
||||
|
||||
|
||||
### Recurso `/dhcp/subnets/hosts`
|
||||
|
||||
#### Obtener configuración de los hosts
|
||||
|
||||
Devuelve la configuración de los hosts que se encuentran bajo una subred en la configuración de Kea DHCP.
|
||||
|
||||
|
||||
**Método HTTP:** GET
|
||||
|
||||
**URL:** `/dhcp/subnets/{id_subnet}/hosts`
|
||||
|
||||
|
||||
#### Añadir Host DHCP
|
||||
|
||||
Añade un nuevo host a la subnet especificada.
|
||||
|
||||
**Método HTTP:** POST
|
||||
|
||||
**URL:** `/dhcp/subnets/{id_subnet}/hosts`
|
||||
|
||||
**Parámetros de entrada:**
|
||||
|
||||
- `host`: Nombre del host.
|
||||
- `macAddress`: Dirección MAC del host.
|
||||
- `address`: Dirección IP del host.
|
||||
- `nextServer`: Dirección IP del next-server.
|
||||
|
||||
#### Borrar Host DHCP
|
||||
|
||||
Borrar un host de la subnet especificada.
|
||||
|
||||
**Método HTTP:** DELETE
|
||||
|
||||
**URL:** `/dhcp/subnets/{id_subnet}/hosts`
|
||||
|
||||
**Parámetros de entrada:**
|
||||
|
||||
- `host`: Nombre del host.
|
||||
|
||||
#### Modificar Host DHCP
|
||||
|
||||
Modificar la configuración de un host en la subnet especificada.
|
||||
|
||||
**Método HTTP:** PUT
|
||||
|
||||
**URL:** `/dhcp/subnets/{id_subnet}/hosts`
|
||||
|
||||
**Parámetros de entrada:**
|
||||
|
||||
- `host`: Nombre del host.
|
||||
- `oldMacAddress`: Dirección MAC antigua del host.
|
||||
- `oldAddress`: Dirección IP antigua del host.
|
||||
- `macAddress`: Nueva dirección MAC del host.
|
||||
- `address`: Nueva dirección IP del host.
|
||||
- `nextServer`: Nueva dirección IP del servidor siguiente.
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
OpenGnsys Services for Clients README
|
||||
=======================================
|
||||
|
||||
|
||||
Este directorio contiene el código fuente de los servicios OpenGnsys específicos para clientes.
|
||||
|
||||
- ogAdmClient servicio para cliente ogLive que atiende peticiones de OpenGnsys Server
|
||||
- ogagent OGAgent: agente modular para sistemas operativos con API REST
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
# makefile
|
||||
|
||||
# Nombre del proyecto
|
||||
PROYECTO := ogAdmClient
|
||||
|
||||
# Directorios y librerias
|
||||
DIRS :=
|
||||
LIBS := -static
|
||||
|
||||
# Opciones de compilacion
|
||||
OPCS := -m32 -O0 -g -Wall # Depuracion
|
||||
#OPCS := -m32 -O3 -Wall # Optimizacion
|
||||
|
||||
# Ficheros objetos
|
||||
OBJS := sources/ogAdmClient.o
|
||||
|
||||
all: $(PROYECTO)
|
||||
|
||||
$(PROYECTO): $(OBJS)
|
||||
gcc $(OPCS) $(DIRS) $(LIBS) $(OBJS) -o $(PROYECTO)
|
||||
# strip $(PROYECTO) # Optimizacion
|
||||
|
||||
clean:
|
||||
rm -f $(PROYECTO) $(OBJS)
|
||||
|
||||
sources/%.o: sources/%.c
|
||||
gcc $(OPCS) -I ../../Includes -c -o"$@" "$<"
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
ServidorAdm=SERVERIP
|
||||
PUERTO=2008
|
||||
PATHINTERFACE=/opt/opengnsys/interfaceAdm
|
||||
UrlMenu=OPENGNSYSURL/varios/menubrowser.php
|
||||
UrlMsg=http://localhost/cgi-bin/httpd-log.sh
|
File diff suppressed because it is too large
Load Diff
|
@ -1,183 +0,0 @@
|
|||
// ********************************************************************************************************
|
||||
// Cliernte: ogAdmClient
|
||||
// Autor: José Manuel Alonso (E.T.S.I.I.) Universidad de Sevilla
|
||||
// Fecha Creación: Marzo-2010
|
||||
// Fecha Última modificación: Marzo-2010
|
||||
// Nombre del fichero: ogAdmClient.h
|
||||
// Descripción :Este fichero implementa el cliente general del sistema
|
||||
// ********************************************************************************************************
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <signal.h>
|
||||
#include "ogAdmLib.h"
|
||||
// ________________________________________________________________________________________________________
|
||||
// Variables globales
|
||||
// ________________________________________________________________________________________________________
|
||||
char *idordenador; // Identificador del ordenador
|
||||
char *nombreordenador; // Nombre del ordenador
|
||||
char *cache; // Tamaño de la caché
|
||||
char *idproautoexec; // Identificador del procedimiento de autoexec
|
||||
char *idcentro; // Identificador de la Unidad Organizativa
|
||||
char *idaula; // Identificador del aula
|
||||
char IPlocal[LONIP]; // Ip local
|
||||
|
||||
char servidoradm[LONPRM]; // Dirección IP del servidor de administración
|
||||
char puerto[LONPRM]; // Puerto de comunicación
|
||||
char pathinterface[LONPRM]; // Path donde está la interface entre la administración y el módulo de clonación
|
||||
|
||||
char interface[LONFUN]; // Nombre del módulo,función o script de la interface con el módulo de administración
|
||||
char parametros[LONSTD]; // Parámetros para la llamada
|
||||
int herror;
|
||||
|
||||
BOOLEAN CMDPTES; // Para bucle de comandos pendientes
|
||||
|
||||
|
||||
char urlmenu[MAXLONURL]; // Url de la pagina de menu para el browser
|
||||
char urlmsg[MAXLONURL]; // Url de la página de mensajed para el browser
|
||||
|
||||
|
||||
typedef struct{ // Estructura usada para referenciar las funciones que procesan las tramas
|
||||
char nf[LONFUN]; // Nombre de la función
|
||||
BOOLEAN (*fptr)(TRAMA*); // Puntero a la función que procesa la trama
|
||||
}MSGFUN;
|
||||
MSGFUN tbfuncionesClient[MAXIMAS_FUNCIONES];
|
||||
// ________________________________________________________________________________________________________
|
||||
// Tabla de errores de la ejecución de los scripts
|
||||
// ________________________________________________________________________________________________________
|
||||
char* tbErroresScripts[]={"Se han generado errores desconocidos. No se puede continuar la ejecución de este módulo",\
|
||||
"001-Formato de ejecución incorrecto.",\
|
||||
"002-Fichero o dispositivo no encontrado",\
|
||||
"003-Error en partición de disco",\
|
||||
"004-Partición o fichero bloqueado",\
|
||||
"005-Error al crear o restaurar una imagen",\
|
||||
"006-Sin sistema operativo",\
|
||||
"007-Programa o función BOOLEAN no ejecutable",\
|
||||
"008-Error en la creación del archivo de eco para consola remota",\
|
||||
"009-Error en la lectura del archivo temporal de intercambio",\
|
||||
"010-Error al ejecutar la llamada a la interface de administración",\
|
||||
"011-La información retornada por la interface de administración excede de la longitud permitida",\
|
||||
"012-Error en el envío de fichero por la red",\
|
||||
"013-Error en la creación del proceso hijo",\
|
||||
"014-Error de escritura en destino",\
|
||||
"015-Sin Cache en el Cliente",\
|
||||
"016-No hay espacio en la cache para almacenar fichero-imagen",\
|
||||
"017-Error al Reducir el Sistema Archivos",\
|
||||
"018-Error al Expandir el Sistema Archivos",\
|
||||
"019-Valor fuera de rango o no válido.",\
|
||||
"020-Sistema de archivos desconocido o no se puede montar",\
|
||||
"021-Error en partición de caché local",\
|
||||
"022-El disco indicado no contiene una particion GPT",\
|
||||
"023-Error no definido",\
|
||||
"024-Error no definido",\
|
||||
"025-Error no definido",\
|
||||
"026-Error no definido",\
|
||||
"027-Error no definido",\
|
||||
"028-Error no definido",\
|
||||
"029-Error no definido",\
|
||||
"030-Error al restaurar imagen - Imagen mas grande que particion",\
|
||||
"031-Error al realizar el comando updateCache",\
|
||||
"032-Error al formatear",\
|
||||
"033-Archivo de imagen corrupto o de otra versión de partclone",\
|
||||
"034-Error no definido",\
|
||||
"035-Error no definido",\
|
||||
"036-Error no definido",\
|
||||
"037-Error no definido",\
|
||||
"038-Error no definido",\
|
||||
"039-Error no definido",\
|
||||
"040-Error imprevisto no definido",\
|
||||
"041-Error no definido",\
|
||||
"042-Error no definido",\
|
||||
"043-Error no definido",\
|
||||
"044-Error no definido",\
|
||||
"045-Error no definido",\
|
||||
"046-Error no definido",\
|
||||
"047-Error no definido",\
|
||||
"048-Error no definido",\
|
||||
"049-Error no definido",\
|
||||
"050-Error en la generación de sintaxis de transferenica unicast",\
|
||||
"051-Error en envio UNICAST de una particion",\
|
||||
"052-Error en envio UNICAST de un fichero",\
|
||||
"053-Error en la recepcion UNICAST de una particion",\
|
||||
"054-Error en la recepcion UNICAST de un fichero",\
|
||||
"055-Error en la generacion de sintaxis de transferenica Multicast",\
|
||||
"056-Error en envio MULTICAST de un fichero",\
|
||||
"057-Error en la recepcion MULTICAST de un fichero",\
|
||||
"058-Error en envio MULTICAST de una particion",\
|
||||
"059-Error en la recepcion MULTICAST de una particion",\
|
||||
"060-Error en la conexion de una sesion UNICAST|MULTICAST con el MASTER",\
|
||||
"061-Error no definido",\
|
||||
"062-Error no definido",\
|
||||
"063-Error no definido",\
|
||||
"064-Error no definido",\
|
||||
"065-Error no definido",\
|
||||
"066-Error no definido",\
|
||||
"067-Error no definido",\
|
||||
"068-Error no definido",\
|
||||
"069-Error no definido",\
|
||||
"070-Error al montar una imagen sincronizada.",\
|
||||
"071-Imagen no sincronizable (es monolitica).",\
|
||||
"072-Error al desmontar la imagen.",\
|
||||
"073-No se detectan diferencias entre la imagen basica y la particion.",\
|
||||
"074-Error al sincronizar, puede afectar la creacion/restauracion de la imagen.",\
|
||||
"Error desconocido "
|
||||
};
|
||||
#define MAXERRORSCRIPT 74 // Error máximo cometido
|
||||
// ________________________________________________________________________________________________________
|
||||
// Prototipo de funciones
|
||||
// ________________________________________________________________________________________________________
|
||||
BOOLEAN autoexecCliente(TRAMA*);
|
||||
BOOLEAN RESPUESTA_AutoexecCliente(TRAMA*);
|
||||
void procesaComandos(TRAMA*);
|
||||
|
||||
BOOLEAN tomaConfiguracion(char*);
|
||||
BOOLEAN tomaIPlocal(void);
|
||||
void scriptLog(const char *,int );
|
||||
|
||||
BOOLEAN gestionaTrama(TRAMA *);
|
||||
BOOLEAN inclusionCliente();
|
||||
char* LeeConfiguracion();
|
||||
BOOLEAN RESPUESTA_InclusionCliente(TRAMA *);
|
||||
|
||||
BOOLEAN comandosPendientes(TRAMA*);
|
||||
BOOLEAN NoComandosPtes(TRAMA *);
|
||||
|
||||
BOOLEAN respuestaEjecucionComando(TRAMA *,int,char*);
|
||||
BOOLEAN Sondeo(TRAMA *);
|
||||
BOOLEAN Actualizar(TRAMA *);
|
||||
int Purgar(TRAMA* );
|
||||
|
||||
BOOLEAN ConsolaRemota(TRAMA*);
|
||||
|
||||
BOOLEAN Arrancar(TRAMA *);
|
||||
BOOLEAN Apagar(TRAMA *);
|
||||
BOOLEAN Reiniciar(TRAMA *);
|
||||
BOOLEAN IniciarSesion(TRAMA *);
|
||||
BOOLEAN CrearImagen(TRAMA *);
|
||||
BOOLEAN CrearImagenBasica(TRAMA *);
|
||||
BOOLEAN CrearSoftIncremental(TRAMA*);
|
||||
|
||||
BOOLEAN InventarioHardware(TRAMA *);
|
||||
BOOLEAN InventariandoSoftware(TRAMA *,BOOLEAN,char*);
|
||||
BOOLEAN EjecutarScript(TRAMA *);
|
||||
BOOLEAN ejecutaArchivo(char*,TRAMA*);
|
||||
|
||||
BOOLEAN cuestionCache(char*);
|
||||
int cargaPaginaWeb(char *);
|
||||
void muestraMenu(void);
|
||||
void muestraMensaje(int idx,char*);
|
||||
|
||||
BOOLEAN enviaMensajeServidor(SOCKET *,TRAMA *,char);
|
||||
|
||||
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
|
@ -1,182 +0,0 @@
|
|||
Format: 1.0
|
||||
Source: ogagent-oglive
|
||||
Binary: ogagent-oglive
|
||||
Architecture: all
|
||||
Version: 3.0.0-20190520
|
||||
Checksums-Md5:
|
||||
7252ce182f6ea1d1c6d569046770cbad 33624 ogagent-oglive_3.0.0-20190520_all.deb
|
||||
Checksums-Sha1:
|
||||
5c1a1984bc7598e33a4271d11954352a77adda50 33624 ogagent-oglive_3.0.0-20190520_all.deb
|
||||
Checksums-Sha256:
|
||||
94624c2751b6178a9476ee57a5f59c98f516cf5795f849383418a4182644dd0d 33624 ogagent-oglive_3.0.0-20190520_all.deb
|
||||
Build-Origin: Ubuntu
|
||||
Build-Architecture: amd64
|
||||
Build-Date: Thu, 14 Dec 2023 08:28:43 +0100
|
||||
Build-Tainted-By:
|
||||
merged-usr-via-aliased-dirs
|
||||
usr-local-has-configs
|
||||
usr-local-has-libraries
|
||||
usr-local-has-programs
|
||||
Installed-Build-Depends:
|
||||
autoconf (= 2.71-2),
|
||||
automake (= 1:1.16.5-1.3),
|
||||
autopoint (= 0.21-4ubuntu4),
|
||||
autotools-dev (= 20220109.1),
|
||||
base-files (= 12ubuntu4.4),
|
||||
base-passwd (= 3.5.52build1),
|
||||
bash (= 5.1-6ubuntu1),
|
||||
binutils (= 2.38-4ubuntu2.4),
|
||||
binutils-common (= 2.38-4ubuntu2.4),
|
||||
binutils-x86-64-linux-gnu (= 2.38-4ubuntu2.4),
|
||||
bsdextrautils (= 2.37.2-4ubuntu3),
|
||||
bsdutils (= 1:2.37.2-4ubuntu3),
|
||||
build-essential (= 12.9ubuntu3),
|
||||
bzip2 (= 1.0.8-5build1),
|
||||
coreutils (= 8.32-4.1ubuntu1),
|
||||
cpp (= 4:11.2.0-1ubuntu1),
|
||||
cpp-11 (= 11.4.0-1ubuntu1~22.04),
|
||||
dash (= 0.5.11+git20210903+057cd650a4ed-3build1),
|
||||
debconf (= 1.5.79ubuntu1),
|
||||
debhelper (= 13.6ubuntu1),
|
||||
debianutils (= 5.5-1ubuntu2),
|
||||
debugedit (= 1:5.0-4build1),
|
||||
dh-autoreconf (= 20),
|
||||
dh-strip-nondeterminism (= 1.13.0-1),
|
||||
diffutils (= 1:3.8-0ubuntu2),
|
||||
dpkg (= 1.21.1ubuntu2.2),
|
||||
dpkg-dev (= 1.21.1ubuntu2.2),
|
||||
dwz (= 0.14-1build2),
|
||||
file (= 1:5.41-3ubuntu0.1),
|
||||
findutils (= 4.8.0-1ubuntu3),
|
||||
g++ (= 4:11.2.0-1ubuntu1),
|
||||
g++-11 (= 11.4.0-1ubuntu1~22.04),
|
||||
gawk (= 1:5.1.0-1ubuntu0.1),
|
||||
gcc (= 4:11.2.0-1ubuntu1),
|
||||
gcc-11 (= 11.4.0-1ubuntu1~22.04),
|
||||
gcc-11-base (= 11.4.0-1ubuntu1~22.04),
|
||||
gcc-12-base (= 12.3.0-1ubuntu1~22.04),
|
||||
gettext (= 0.21-4ubuntu4),
|
||||
gettext-base (= 0.21-4ubuntu4),
|
||||
grep (= 3.7-1build1),
|
||||
groff-base (= 1.22.4-8build1),
|
||||
gzip (= 1.10-4ubuntu4.1),
|
||||
hostname (= 3.23ubuntu2),
|
||||
init-system-helpers (= 1.62),
|
||||
install-info (= 6.8-4build1),
|
||||
intltool-debian (= 0.35.0+20060710.5),
|
||||
libacl1 (= 2.3.1-1),
|
||||
libarchive-zip-perl (= 1.68-1),
|
||||
libasan6 (= 11.4.0-1ubuntu1~22.04),
|
||||
libatomic1 (= 12.3.0-1ubuntu1~22.04),
|
||||
libattr1 (= 1:2.5.1-1build1),
|
||||
libaudit-common (= 1:3.0.7-1build1),
|
||||
libaudit1 (= 1:3.0.7-1build1),
|
||||
libbinutils (= 2.38-4ubuntu2.4),
|
||||
libblkid1 (= 2.37.2-4ubuntu3),
|
||||
libbz2-1.0 (= 1.0.8-5build1),
|
||||
libc-bin (= 2.35-0ubuntu3.5),
|
||||
libc-dev-bin (= 2.35-0ubuntu3.5),
|
||||
libc6 (= 2.35-0ubuntu3.5),
|
||||
libc6-dev (= 2.35-0ubuntu3.5),
|
||||
libcap-ng0 (= 0.7.9-2.2build3),
|
||||
libcap2 (= 1:2.44-1ubuntu0.22.04.1),
|
||||
libcc1-0 (= 12.3.0-1ubuntu1~22.04),
|
||||
libcom-err2 (= 1.46.5-2ubuntu1.1),
|
||||
libcrypt-dev (= 1:4.4.27-1),
|
||||
libcrypt1 (= 1:4.4.27-1),
|
||||
libctf-nobfd0 (= 2.38-4ubuntu2.4),
|
||||
libctf0 (= 2.38-4ubuntu2.4),
|
||||
libdb5.3 (= 5.3.28+dfsg1-0.8ubuntu3),
|
||||
libdebconfclient0 (= 0.261ubuntu1),
|
||||
libdebhelper-perl (= 13.6ubuntu1),
|
||||
libdpkg-perl (= 1.21.1ubuntu2.2),
|
||||
libdw1 (= 0.186-1build1),
|
||||
libelf1 (= 0.186-1build1),
|
||||
libfile-stripnondeterminism-perl (= 1.13.0-1),
|
||||
libgcc-11-dev (= 11.4.0-1ubuntu1~22.04),
|
||||
libgcc-s1 (= 12.3.0-1ubuntu1~22.04),
|
||||
libgcrypt20 (= 1.9.4-3ubuntu3),
|
||||
libgdbm-compat4 (= 1.23-1),
|
||||
libgdbm6 (= 1.23-1),
|
||||
libgmp10 (= 2:6.2.1+dfsg-3ubuntu1),
|
||||
libgomp1 (= 12.3.0-1ubuntu1~22.04),
|
||||
libgpg-error0 (= 1.43-3),
|
||||
libgssapi-krb5-2 (= 1.19.2-2ubuntu0.3),
|
||||
libicu70 (= 70.1-2),
|
||||
libisl23 (= 0.24-2build1),
|
||||
libitm1 (= 12.3.0-1ubuntu1~22.04),
|
||||
libk5crypto3 (= 1.19.2-2ubuntu0.3),
|
||||
libkeyutils1 (= 1.6.1-2ubuntu3),
|
||||
libkrb5-3 (= 1.19.2-2ubuntu0.3),
|
||||
libkrb5support0 (= 1.19.2-2ubuntu0.3),
|
||||
liblsan0 (= 12.3.0-1ubuntu1~22.04),
|
||||
liblz4-1 (= 1.9.3-2build2),
|
||||
liblzma5 (= 5.2.5-2ubuntu1),
|
||||
libmagic-mgc (= 1:5.41-3ubuntu0.1),
|
||||
libmagic1 (= 1:5.41-3ubuntu0.1),
|
||||
libmount1 (= 2.37.2-4ubuntu3),
|
||||
libmpc3 (= 1.2.1-2build1),
|
||||
libmpfr6 (= 4.1.0-3build3),
|
||||
libnsl-dev (= 1.3.0-2build2),
|
||||
libnsl2 (= 1.3.0-2build2),
|
||||
libpam-modules (= 1.4.0-11ubuntu2.3),
|
||||
libpam-modules-bin (= 1.4.0-11ubuntu2.3),
|
||||
libpam-runtime (= 1.4.0-11ubuntu2.3),
|
||||
libpam0g (= 1.4.0-11ubuntu2.3),
|
||||
libpcre2-8-0 (= 10.40-1+ubuntu22.04.1+deb.sury.org+1),
|
||||
libpcre3 (= 2:8.45-1+ubuntu22.04.1+deb.sury.org+1),
|
||||
libperl5.34 (= 5.34.0-3ubuntu1.3),
|
||||
libpipeline1 (= 1.5.5-1),
|
||||
libquadmath0 (= 12.3.0-1ubuntu1~22.04),
|
||||
libreadline8 (= 8.1.2-1),
|
||||
libseccomp2 (= 2.5.3-2ubuntu2),
|
||||
libselinux1 (= 3.3-1build2),
|
||||
libsigsegv2 (= 2.13-1ubuntu3),
|
||||
libsmartcols1 (= 2.37.2-4ubuntu3),
|
||||
libssl3 (= 3.0.2-0ubuntu1.12),
|
||||
libstdc++-11-dev (= 11.4.0-1ubuntu1~22.04),
|
||||
libstdc++6 (= 12.3.0-1ubuntu1~22.04),
|
||||
libsub-override-perl (= 0.09-2),
|
||||
libsystemd0 (= 249.11-0ubuntu3.11),
|
||||
libtinfo6 (= 6.3-2ubuntu0.1),
|
||||
libtirpc-common (= 1.3.2-2ubuntu0.1),
|
||||
libtirpc-dev (= 1.3.2-2ubuntu0.1),
|
||||
libtirpc3 (= 1.3.2-2ubuntu0.1),
|
||||
libtool (= 2.4.6-15build2),
|
||||
libtsan0 (= 11.4.0-1ubuntu1~22.04),
|
||||
libubsan1 (= 12.3.0-1ubuntu1~22.04),
|
||||
libuchardet0 (= 0.0.7-1build2),
|
||||
libudev1 (= 249.11-0ubuntu3.11),
|
||||
libunistring2 (= 1.0-1),
|
||||
libuuid1 (= 2.37.2-4ubuntu3),
|
||||
libxml2 (= 2.9.14+dfsg-0.1+ubuntu22.04.1+deb.sury.org+1),
|
||||
libzstd1 (= 1.4.8+dfsg-3build1),
|
||||
linux-libc-dev (= 5.15.0-91.101),
|
||||
login (= 1:4.8.1-2ubuntu2.1),
|
||||
lsb-base (= 11.1.0ubuntu4),
|
||||
lto-disabled-list (= 24),
|
||||
m4 (= 1.4.18-5ubuntu2),
|
||||
make (= 4.3-4.1build1),
|
||||
man-db (= 2.10.2-1),
|
||||
mawk (= 1.3.4.20200120-3),
|
||||
ncurses-base (= 6.3-2ubuntu0.1),
|
||||
ncurses-bin (= 6.3-2ubuntu0.1),
|
||||
patch (= 2.7.6-7build2),
|
||||
perl (= 5.34.0-3ubuntu1.3),
|
||||
perl-base (= 5.34.0-3ubuntu1.3),
|
||||
perl-modules-5.34 (= 5.34.0-3ubuntu1.3),
|
||||
po-debconf (= 1.0.21+nmu1),
|
||||
readline-common (= 8.1.2-1),
|
||||
rpcsvc-proto (= 1.4.2-0ubuntu6),
|
||||
sed (= 4.8-1ubuntu2),
|
||||
sensible-utils (= 0.0.17),
|
||||
sysvinit-utils (= 3.01-1ubuntu1),
|
||||
tar (= 1.34+dfsg-1ubuntu0.1.22.04.2),
|
||||
util-linux (= 2.37.2-4ubuntu3),
|
||||
xz-utils (= 5.2.5-2ubuntu1),
|
||||
zlib1g (= 1:1.2.11.dfsg-2ubuntu9.2)
|
||||
Environment:
|
||||
DEB_BUILD_OPTIONS="parallel=8"
|
||||
DEB_BUILD_PROFILES="noudeb"
|
||||
LANG="C"
|
||||
SOURCE_DATE_EPOCH="1529319600"
|
|
@ -1,26 +0,0 @@
|
|||
Format: 1.8
|
||||
Date: Mon, 18 Jun 2018 13:00:00 +0200
|
||||
Source: ogagent-oglive
|
||||
Binary: ogagent-oglive
|
||||
Built-For-Profiles: noudeb
|
||||
Architecture: all
|
||||
Version: 3.0.0-20190520
|
||||
Distribution: unstable
|
||||
Urgency: medium
|
||||
Maintainer: Ramón M. Gómez <ramongomez@us.es>
|
||||
Changed-By: Ramón M. Gómez <ramongomez@us.es>
|
||||
Description:
|
||||
ogagent-oglive - OpenGnsys Agent for ogLive client
|
||||
Changes:
|
||||
ogagent-oglive (3.0.0-20190520) unstable; urgency=medium
|
||||
.
|
||||
* OGAgent for ogLive compatible with OpenGnsys 3 web API
|
||||
Checksums-Sha1:
|
||||
5c1a1984bc7598e33a4271d11954352a77adda50 33624 ogagent-oglive_3.0.0-20190520_all.deb
|
||||
ec6e0da3760059612e014f25297cb73e887697cd 5954 ogagent-oglive_3.0.0-20190520_amd64.buildinfo
|
||||
Checksums-Sha256:
|
||||
94624c2751b6178a9476ee57a5f59c98f516cf5795f849383418a4182644dd0d 33624 ogagent-oglive_3.0.0-20190520_all.deb
|
||||
7f2a8b5e25860c53c72b1a438010be022b3bf1c0a05f3562b570f9e940bfd450 5954 ogagent-oglive_3.0.0-20190520_amd64.buildinfo
|
||||
Files:
|
||||
7252ce182f6ea1d1c6d569046770cbad 33624 admin optional ogagent-oglive_3.0.0-20190520_all.deb
|
||||
9f2806400070d5df4bb4c54a010dde70 5954 admin optional ogagent-oglive_3.0.0-20190520_amd64.buildinfo
|
|
@ -1 +0,0 @@
|
|||
./readme.txt
|
|
@ -1,2 +0,0 @@
|
|||
ogagent-oglive_3.0.0-20190520_all.deb admin optional
|
||||
ogagent-oglive_3.0.0-20190520_amd64.buildinfo admin optional
|
|
@ -1,14 +0,0 @@
|
|||
dh_prep
|
||||
dh_installdirs
|
||||
dh_installchangelogs
|
||||
dh_installdocs
|
||||
dh_installdebconf
|
||||
dh_installinit
|
||||
dh_compress
|
||||
dh_link
|
||||
dh_fixperms
|
||||
dh_installdeb
|
||||
dh_shlibdeps
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
|
@ -1,11 +0,0 @@
|
|||
Package: ogagent-oglive
|
||||
Version: 3.0.0-20190520
|
||||
Architecture: all
|
||||
Maintainer: Ramón M. Gómez <ramongomez@us.es>
|
||||
Installed-Size: 235
|
||||
Depends: python-requests (>= 0.8.2), python-six (>= 1.1), python-prctl (>= 1.1.1), python (>= 2.7), libxss1
|
||||
Section: admin
|
||||
Priority: optional
|
||||
Homepage: https://opengnsys.es
|
||||
Description: OpenGnsys Agent for ogLive client
|
||||
This package provides the required components to allow this machine to work on an environment managed by OpenGnsys.
|
|
@ -1,44 +0,0 @@
|
|||
a645b097e936b35a0f9d667320b97c7a usr/bin/ogagent
|
||||
f1af20ebcb0f9ca24050f5440b280971 usr/share/OGAgent/cfg/ogagent.cfg
|
||||
1a151168042f9f91b0ac9de8d81b1cc9 usr/share/OGAgent/cfg/ogclient.cfg
|
||||
e9b55cf5a2893cb205ece2914ad2cec6 usr/share/OGAgent/opengnsys/RESTApi.py
|
||||
b2145636e0e9f3733a07dc3c864ffba6 usr/share/OGAgent/opengnsys/__init__.py
|
||||
a53a553fabe11b358872eaa6f15e51c7 usr/share/OGAgent/opengnsys/certs.py
|
||||
b6b6d13dffe43f62019489701bd3dceb usr/share/OGAgent/opengnsys/config.py
|
||||
5ddd04ea082b0030b56dbac442817ba2 usr/share/OGAgent/opengnsys/httpserver.py
|
||||
a7ceb4791ea9a1e5074f37c27aaef65b usr/share/OGAgent/opengnsys/ipc.py
|
||||
08005cd7b24449275157d9c560f729c0 usr/share/OGAgent/opengnsys/linux/OGAgentService.py
|
||||
3ef55d64ebda86651c3d882c5c649389 usr/share/OGAgent/opengnsys/linux/__init__.py
|
||||
e5c7da55543002f86d591d243383563a usr/share/OGAgent/opengnsys/linux/daemon.py
|
||||
86e7674bddc118fc1ceb9cd1de7d5912 usr/share/OGAgent/opengnsys/linux/log.py
|
||||
18c89c3f7a9d457f99c1e1bb9e3297dd usr/share/OGAgent/opengnsys/linux/operations.py
|
||||
f287da160c9d182e8a11d86bce27fd69 usr/share/OGAgent/opengnsys/linux/renamer/__init__.py
|
||||
dee0a162a35e6bf8b18e39c4b8c4922c usr/share/OGAgent/opengnsys/linux/renamer/debian.py
|
||||
39cc52a365eac6caec10dbad16d3dceb usr/share/OGAgent/opengnsys/linux/renamer/opensuse.py
|
||||
b97470f7d68208d837659fcd6b910c9f usr/share/OGAgent/opengnsys/linux/renamer/redhat.py
|
||||
f2255a73b7801f9596a9929358d75629 usr/share/OGAgent/opengnsys/loader.py
|
||||
8d648c5a0cbb79e69c3d0eeee8247226 usr/share/OGAgent/opengnsys/log.py
|
||||
cc21354530aecfd1376d0a9efcedc0f5 usr/share/OGAgent/opengnsys/macos/__init__.py
|
||||
5ed4af5272fe5f5e4bd1f5ad591edd3a usr/share/OGAgent/opengnsys/macos/operations.py
|
||||
d41d8cd98f00b204e9800998ecf8427e usr/share/OGAgent/opengnsys/modules/__init__.py
|
||||
5be7cd44bb941107cbe67345982cce22 usr/share/OGAgent/opengnsys/modules/client/OpenGnSys/__init__.py
|
||||
d41d8cd98f00b204e9800998ecf8427e usr/share/OGAgent/opengnsys/modules/client/__init__.py
|
||||
a7903db8bd76249a4e0ee72147542ecd usr/share/OGAgent/opengnsys/modules/server/OpenGnSys/__init__.py
|
||||
d41d8cd98f00b204e9800998ecf8427e usr/share/OGAgent/opengnsys/modules/server/__init__.py
|
||||
3ef55d64ebda86651c3d882c5c649389 usr/share/OGAgent/opengnsys/oglive/__init__.py
|
||||
e5c7da55543002f86d591d243383563a usr/share/OGAgent/opengnsys/oglive/daemon.py
|
||||
a316e2cd56e19eb453215d441f9589aa usr/share/OGAgent/opengnsys/oglive/operations.py
|
||||
7b20385f798d849dd546eb1c25149d76 usr/share/OGAgent/opengnsys/operations.py
|
||||
e5c055043531b106f345f63ffbfb3b44 usr/share/OGAgent/opengnsys/scriptThread.py
|
||||
296542d5654398781ec99c1ec2c0db7f usr/share/OGAgent/opengnsys/service.py
|
||||
68b513e35d67d3e783947ec35b60cfa7 usr/share/OGAgent/opengnsys/utils.py
|
||||
99858b8c43e60816ce3d50888f6bdf21 usr/share/OGAgent/opengnsys/windows/OGAgentService.py
|
||||
5c4822b3e4cef2d5ec2225ad8adcfeed usr/share/OGAgent/opengnsys/windows/__init__.py
|
||||
737d49175b1b4045adfd3bd8a66b66b7 usr/share/OGAgent/opengnsys/windows/log.py
|
||||
f6e9945941b22caf066617abc25b47e2 usr/share/OGAgent/opengnsys/windows/operations.py
|
||||
4eeead8170a612cedd5ac16f043695f8 usr/share/OGAgent/opengnsys/workers/__init__.py
|
||||
7e0279e56a6730c74c4b525916a06f57 usr/share/OGAgent/opengnsys/workers/client_worker.py
|
||||
6e6ff6fc0e398882d8696ae00cf48bb9 usr/share/OGAgent/opengnsys/workers/server_worker.py
|
||||
c25929437b6c40d24ff965ca588dd089 usr/share/doc/ogagent-oglive/changelog.Debian.gz
|
||||
172f344346f66d22a8bf1888b1811c06 usr/share/doc/ogagent-oglive/copyright
|
||||
a7d8603a8cfc9a45e52129a5e5e8664b usr/share/doc/ogagent-oglive/readme.txt
|
|
@ -1,21 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
. /usr/share/debconf/confmodule
|
||||
|
||||
set -e
|
||||
case "$1" in
|
||||
configure)
|
||||
chmod 600 /usr/share/OGAgent/cfg/ogagent.cfg
|
||||
;;
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
|
||||
exit 0
|
|
@ -1,10 +0,0 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
. /usr/share/debconf/confmodule
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$1" = "purge" ] ; then
|
||||
rm -rf /usr/share/OGAgent || true > /dev/null 2>&1
|
||||
fi
|
||||
|
|
@ -1 +0,0 @@
|
|||
/usr/share/OGAgent/cfg/ogagent.cfg
|
|
@ -1 +0,0 @@
|
|||
/usr/share/OGAgent/cfg/ogclient.cfg
|
|
@ -1,6 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
FOLDER=/usr/share/OGAgent
|
||||
|
||||
cd $FOLDER
|
||||
python -m opengnsys.linux.OGAgentService $@
|
|
@ -1,27 +0,0 @@
|
|||
[opengnsys]
|
||||
# Listen address & port of REST
|
||||
address=0.0.0.0
|
||||
port=8000
|
||||
|
||||
# This is a comma separated list of paths where to look for modules to load
|
||||
path=test_modules/server
|
||||
|
||||
# Remote OpenGnsys Service (please change IP address)
|
||||
remote=https://192.168.2.10/opengnsys/rest/v3
|
||||
# Alternate OpenGnsys Service (comment out to enable this option)
|
||||
#altremote=https://10.0.2.2/opengnsys/rest
|
||||
|
||||
# Security tokens (please change)
|
||||
client=xxxxx
|
||||
secret=yyyyy
|
||||
|
||||
# Log Level, if ommited, will be set to INFO
|
||||
log=DEBUG
|
||||
|
||||
# Module specific
|
||||
# The sections must match the module name
|
||||
# This section will be passes on activation to module
|
||||
#[Sample1]
|
||||
#value1=Mariete
|
||||
#value2=Yo
|
||||
#remote=https://172.27.0.1:9999/rest
|
|
@ -1,11 +0,0 @@
|
|||
[opengnsys]
|
||||
# Log Level, if ommited, will be set to INFO
|
||||
log=DEBUG
|
||||
|
||||
# Module specific
|
||||
# The sections must match the module name
|
||||
# This section will be passes on activation to module
|
||||
#[Sample1]
|
||||
#value1=Mariete
|
||||
#value2=Yo
|
||||
#remote=https://172.27.0.1:9999/rest
|
|
@ -1,196 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 201 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
|
||||
# pylint: disable-msg=E1101,W0703
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import requests
|
||||
import logging
|
||||
import json
|
||||
import warnings
|
||||
|
||||
from .log import logger
|
||||
|
||||
from .utils import exceptionToMessage
|
||||
|
||||
VERIFY_CERT = False # Do not check server certificate
|
||||
TIMEOUT = 5 # Connection timout, in seconds
|
||||
|
||||
|
||||
class RESTError(Exception):
|
||||
ERRCODE = 0
|
||||
|
||||
|
||||
class ConnectionError(RESTError):
|
||||
ERRCODE = -1
|
||||
|
||||
|
||||
# Disable warnings log messages
|
||||
try:
|
||||
import urllib3 # @UnusedImport
|
||||
except Exception:
|
||||
from requests.packages import urllib3 # @Reimport
|
||||
|
||||
try:
|
||||
urllib3.disable_warnings() # @UndefinedVariable
|
||||
warnings.simplefilter("ignore")
|
||||
except Exception:
|
||||
pass # In fact, isn't too important, but wil log warns to logging file
|
||||
|
||||
|
||||
class REST(object):
|
||||
"""
|
||||
Simple interface to remote REST apis.
|
||||
The constructor expects the "base url" as parameter, that is, the url that will be common on all REST requests
|
||||
Remember that this is a helper for "easy of use". You can provide your owns using requests lib for example.
|
||||
Examples:
|
||||
v = REST('https://example.com/rest/v1/') (Can omit trailing / if desired)
|
||||
v.sendMessage('hello?param1=1¶m2=2')
|
||||
This will generate a GET message to https://example.com/rest/v1/hello?param1=1¶m2=2, and return the
|
||||
deserialized JSON result or an exception
|
||||
v.sendMessage('hello?param1=1¶m2=2', {'name': 'mario' })
|
||||
This will generate a POST message to https://example.com/rest/v1/hello?param1=1¶m2=2, with json encoded
|
||||
body {'name': 'mario' }, and also returns
|
||||
the deserialized JSON result or raises an exception in case of error
|
||||
"""
|
||||
access_token = None
|
||||
refresh_token = None
|
||||
|
||||
def __init__(self, url):
|
||||
"""
|
||||
Initializes the REST helper
|
||||
url is the full url of the REST API Base, as for example "https://example.com/rest/v1".
|
||||
@param url The url of the REST API Base. The trailing '/' can be included or omitted, as desired.
|
||||
"""
|
||||
self.endpoint = url
|
||||
|
||||
if self.endpoint[-1] != '/':
|
||||
self.endpoint += '/'
|
||||
|
||||
# Some OSs ships very old python requests lib implementations, workaround them...
|
||||
try:
|
||||
self.newerRequestLib = requests.__version__.split('.')[0] >= '1'
|
||||
except Exception:
|
||||
self.newerRequestLib = False # I no version, guess this must be an old requests
|
||||
|
||||
# Disable logging requests messages except for errors, ...
|
||||
logging.getLogger("requests").setLevel(logging.CRITICAL)
|
||||
# Tries to disable all warnings
|
||||
try:
|
||||
warnings.simplefilter("ignore") # Disables all warnings
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _getUrl(self, method):
|
||||
"""
|
||||
Internal method
|
||||
Composes the URL based on "method"
|
||||
@param method: Method to append to base url for composition
|
||||
"""
|
||||
url = self.endpoint + method
|
||||
|
||||
return url
|
||||
|
||||
def _request(self, url, data=None, patch=False):
|
||||
"""
|
||||
Launches the request
|
||||
@param url: The url to obtain
|
||||
@param data: if None, the request will be sent as a GET request. If != None, the request will be sent as a POST,
|
||||
with data serialized as JSON in the body.
|
||||
"""
|
||||
try:
|
||||
# Prepare the header content
|
||||
headers = {'content-type': 'application/json'}
|
||||
if self.access_token is not None:
|
||||
headers['Authorization'] = 'Bearer ' + self.access_token
|
||||
|
||||
if data is None:
|
||||
logger.debug('REST - Requesting using GET (no data provided) {}'.format(url))
|
||||
# Old requests version does not support verify, but it do not checks ssl certificate by default
|
||||
if self.newerRequestLib:
|
||||
r = requests.get(url, verify=VERIFY_CERT, timeout=TIMEOUT)
|
||||
else:
|
||||
r = requests.get(url)
|
||||
else: # POST / PATCH
|
||||
if patch is False:
|
||||
logger.debug('REST - Requesting using POST {}, data: {}'.format(url, data))
|
||||
if self.newerRequestLib:
|
||||
r = requests.post(url, data=data, headers=headers,
|
||||
verify=VERIFY_CERT, timeout=TIMEOUT)
|
||||
else:
|
||||
r = requests.post(url, data=data, headers=headers)
|
||||
else:
|
||||
logger.debug('REST - Requesting using PATCH {}, data: {}'.format(url, data))
|
||||
if self.newerRequestLib:
|
||||
r = requests.patch(url, data=data, headers=headers,
|
||||
verify=VERIFY_CERT, timeout=TIMEOUT)
|
||||
else:
|
||||
r = requests.patch(url, data=data, headers=headers)
|
||||
|
||||
# la respuesta puede venir sin contenido, para ello miramos el codigo devuelto
|
||||
if r.status_code == 204:
|
||||
r = json.loads('{"response": "OK"}')
|
||||
else:
|
||||
r = json.loads(r.content) # Using instead of r.json() to make compatible with old requests lib versions
|
||||
logger.debug("REST - response - " + json.dumps(r))
|
||||
except requests.exceptions.RequestException as e:
|
||||
raise ConnectionError(e)
|
||||
except Exception as e:
|
||||
raise ConnectionError(exceptionToMessage(e))
|
||||
|
||||
return r
|
||||
|
||||
def sendMessage(self, msg, data=None, processData=True, patch=False):
|
||||
"""
|
||||
Sends a message to remote REST server
|
||||
@param data: if None or omitted, message will be a GET, else it will send a POST
|
||||
@param processData: if True, data will be serialized to json before sending, else, data will be sent as "raw"
|
||||
"""
|
||||
logger.debug('Invoking post message {} with data {}'.format(msg, data))
|
||||
|
||||
if processData and data is not None:
|
||||
data = json.dumps(data)
|
||||
|
||||
url = self._getUrl(msg)
|
||||
logger.debug('Requesting {}'.format(url))
|
||||
|
||||
return self._request(url, data, patch)
|
||||
|
||||
def set_authorization_headers(self, access_token = None, refresh_token = None):
|
||||
"""
|
||||
Set access token and refresh token for use in REST Api with authorization headers
|
||||
@param access_token: if None, no authorization headers will be sent in each request, else, and authorization header will be sent
|
||||
@param refresh_token: if not None, when access_token expires, it will be used to obtain new access token
|
||||
"""
|
||||
self.access_token = access_token
|
||||
self.refresh_token = refresh_token
|
|
@ -1,60 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# On centos, old six release does not includes byte2int, nor six.PY2
|
||||
import six
|
||||
|
||||
import modules
|
||||
from RESTApi import REST, RESTError
|
||||
|
||||
try:
|
||||
with open('VERSION', 'r') as v:
|
||||
VERSION = v.read()
|
||||
except IOError:
|
||||
VERSION = '1.1.0'
|
||||
|
||||
__title__ = 'OpenGnsys Agent'
|
||||
__version__ = VERSION
|
||||
__build__ = 0x010750
|
||||
__author__ = 'Adolfo Gómez'
|
||||
__license__ = "BSD 3-clause"
|
||||
__copyright__ = "Copyright VirtualCable S.L.U."
|
||||
|
||||
if not hasattr(six, 'byte2int'):
|
||||
if six.PY3:
|
||||
import operator
|
||||
six.byte2int = operator.itemgetter(0)
|
||||
else:
|
||||
def _byte2int(bs):
|
||||
return ord(bs[0])
|
||||
six.byte2int = _byte2int
|
|
@ -1,101 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
|
||||
from tempfile import gettempdir
|
||||
from os.path import exists, join
|
||||
|
||||
CERTFILE = 'OGAgent.pem'
|
||||
|
||||
|
||||
def createSelfSignedCert(force=False):
|
||||
|
||||
certFile = join(gettempdir(), CERTFILE)
|
||||
|
||||
if exists(certFile) and not force:
|
||||
return certFile
|
||||
|
||||
certData = '''-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCb50K3mIznNklz
|
||||
yVAD7xSQOSJQ6+NPXj7U9/4zLZ+TvmbQ7RqUUsxbfxHbeRnoYTWV2nKk4+tHqmvz
|
||||
ujLSS/loFhTSMqtrLn7rowSYJoQhKOUkAiQlWkqCfItWgL5pJopDpNHFul9Rn3ds
|
||||
PMWQTiGeUNR4Y3RnBhr1Q1BsqAzf4m6zFUmgLPPmVLdF4uJ3Tuz8TSy2gWLs5aSr
|
||||
5do4WamwUfYjRSVMJECmwjUM4rQ8SQgg0sHBeBuDUGNBvBQFac1G7qUcMReeu8Zr
|
||||
DUtMsXma/l4rA8NB5CRmTrQbTBF4l+jb2BDFebDqDUK1Oqs9X35yOQfDOAFYHiix
|
||||
PX0IsXOZAgMBAAECggEBAJi3000RrIUZUp6Ph0gzPMuCjDEEwWiQA7CPNX1gpb8O
|
||||
dp0WhkDhUroWIaICYPSXtOwUTtVjRqivMoxPy1Thg3EIoGC/rdeSdlXRHMEGicwJ
|
||||
yVyalFnatr5Xzg5wkxVh4XMd0zeDt7e3JD7s0QLo5lm1CEzd77qz6lhzFic5/1KX
|
||||
bzdULtTlq60dazg2hEbcS4OmM1UMCtRVDAsOIUIZPL0M9j1C1d1iEdYnh2xshKeG
|
||||
/GOfo95xsgdMlGjtv3hUT5ryKVoEsu+36rGb4VfhPfUvvoVbRx5QZpW+QvxaYh5E
|
||||
Fi0JEROozFwG31Y++8El7J3yQko8cFBa1lYYUwwpNAECgYEAykT+GiM2YxJ4uVF1
|
||||
OoKiE9BD53i0IG5j87lGPnWqzEwYBwnqjEKDTou+uzMGz3MDV56UEFNho7wUWh28
|
||||
LpEkjJB9QgbsugjxIBr4JoL/rYk036e/6+U8I95lvYWrzb+rBMIkRDYI7kbQD/mQ
|
||||
piYUpuCkTymNAu2RisK6bBzJslkCgYEAxVE23OQvkCeOV8hJNPZGpJ1mDS+TiOow
|
||||
oOScMZmZpail181eYbAfMsCr7ri812lSj98NvA2GNVLpddil6LtS1cQ5p36lFBtV
|
||||
xQUMZiFz4qVbEak+izL+vPaev/mXXsOcibAIQ+qI/0txFpNhJjpaaSy6vRCBYFmc
|
||||
8pgSoBnBI0ECgYAUKCn2atnpp5aWSTLYgNosBU4vDA1PShD14dnJMaqyr0aZtPhF
|
||||
v/8b3btFJoGgPMLxgWEZ+2U4ju6sSFhPf7FXvLJu2QfQRkHZRDbEh7t5DLpTK4Fp
|
||||
va9vl6Ml7uM/HsGpOLuqfIQJUs87OFCc7iCSvMJDDU37I7ekT2GKkpfbCQKBgBrE
|
||||
0NeY0WcSJrp7/oqD2sOcYurpCG/rrZs2SIZmGzUhMxaa0vIXzbO59dlWELB8pmnE
|
||||
Tf20K//x9qA5OxDe0PcVPukdQlH+/1zSOYNliG44FqnHtyd1TJ/gKVtMBiAiE4uO
|
||||
aSClod5Yosf4SJbCFd/s5Iyfv52NqsAyp1w3Aj/BAoGAVCnEiGUfyHlIR+UH4zZW
|
||||
GXJMeqdZLfcEIszMxLePkml4gUQhoq9oIs/Kw+L1DDxUwzkXN4BNTlFbOSu9gzK1
|
||||
dhuIUGfS6RPL88U+ivC3A0y2jT43oUMqe3hiRt360UQ1GXzp2dMnR9odSRB1wHoO
|
||||
IOjEBZ8341/c9ZHc5PCGAG8=
|
||||
-----END PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIID7zCCAtegAwIBAgIJAIrEIthCfxUCMA0GCSqGSIb3DQEBCwUAMIGNMQswCQYD
|
||||
VQQGEwJFUzEPMA0GA1UECAwGTWFkcmlkMREwDwYDVQQHDAhBbGNvcmNvbjEMMAoG
|
||||
A1UECgwDVURTMQ4wDAYDVQQLDAVBY3RvcjESMBAGA1UEAwwJVURTIEFjdG9yMSgw
|
||||
JgYJKoZIhvcNAQkBFhlzdXBwb3J0QHVkc2VudGVycHJpc2UuY29tMB4XDTE0MTAy
|
||||
NjIzNDEyNFoXDTI0MTAyMzIzNDEyNFowgY0xCzAJBgNVBAYTAkVTMQ8wDQYDVQQI
|
||||
DAZNYWRyaWQxETAPBgNVBAcMCEFsY29yY29uMQwwCgYDVQQKDANVRFMxDjAMBgNV
|
||||
BAsMBUFjdG9yMRIwEAYDVQQDDAlVRFMgQWN0b3IxKDAmBgkqhkiG9w0BCQEWGXN1
|
||||
cHBvcnRAdWRzZW50ZXJwcmlzZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
|
||||
ggEKAoIBAQCb50K3mIznNklzyVAD7xSQOSJQ6+NPXj7U9/4zLZ+TvmbQ7RqUUsxb
|
||||
fxHbeRnoYTWV2nKk4+tHqmvzujLSS/loFhTSMqtrLn7rowSYJoQhKOUkAiQlWkqC
|
||||
fItWgL5pJopDpNHFul9Rn3dsPMWQTiGeUNR4Y3RnBhr1Q1BsqAzf4m6zFUmgLPPm
|
||||
VLdF4uJ3Tuz8TSy2gWLs5aSr5do4WamwUfYjRSVMJECmwjUM4rQ8SQgg0sHBeBuD
|
||||
UGNBvBQFac1G7qUcMReeu8ZrDUtMsXma/l4rA8NB5CRmTrQbTBF4l+jb2BDFebDq
|
||||
DUK1Oqs9X35yOQfDOAFYHiixPX0IsXOZAgMBAAGjUDBOMB0GA1UdDgQWBBRShS90
|
||||
5lJTNvYPIEqP3GxWwG5iiDAfBgNVHSMEGDAWgBRShS905lJTNvYPIEqP3GxWwG5i
|
||||
iDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAU0Sp4gXhQmRVzq+7+
|
||||
vRFUkQuPj4Ga/d9r5Wrbg3hck3+5pwe9/7APoq0P/M0DBhQpiJKjrD6ydUevC+Y/
|
||||
43ZOJPhMlNw0o6TdQxOkX6FDwQanLLs7sfvJvqtVzYn3nuRFKT3dvl7Zg44QMw2M
|
||||
ay42q59fAcpB4LaDx/i7gOYSS5eca3lYW7j7YSr/+ozXK2KlgUkuCUHN95lOq+dF
|
||||
trmV9mjzM4CNPZqKSE7kpHRywgrXGPCO000NvEGSYf82AtgRSFKiU8NWLQSEPdcB
|
||||
k//2dsQZw2cRZ8DrC2B6Tb3M+3+CA6wVyqfqZh1SZva3LfGvq/C+u+ItguzPqNpI
|
||||
xtvM
|
||||
-----END CERTIFICATE-----'''
|
||||
with open(certFile, "wt") as f:
|
||||
f.write(certData)
|
||||
|
||||
return certFile
|
|
@ -1,58 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
# pylint: disable=unused-wildcard-import, wildcard-import
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from ConfigParser import SafeConfigParser
|
||||
|
||||
config = None
|
||||
|
||||
def readConfig(client=False):
|
||||
'''
|
||||
Reads configuration file
|
||||
If client is False, will read ogagent.cfg as configuration
|
||||
If client is True, will read ogclient.cfg as configuration
|
||||
|
||||
This is this way so we can protect ogagent.cfg against reading for non admin users on all platforms.
|
||||
'''
|
||||
cfg = SafeConfigParser()
|
||||
if client is True:
|
||||
fname = 'ogclient.cfg'
|
||||
else:
|
||||
fname = 'ogagent.cfg'
|
||||
|
||||
if len(cfg.read('cfg/{}'.format(fname))) == 0:
|
||||
# No configuration found
|
||||
return None
|
||||
|
||||
return cfg
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2015 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
# pylint: disable=unused-wildcard-import,wildcard-import
|
||||
from __future__ import unicode_literals, print_function
|
||||
|
||||
# Pydev can't parse "six.moves.xxxx" because it is loaded lazy
|
||||
import six
|
||||
from six.moves.socketserver import ThreadingMixIn # @UnresolvedImport
|
||||
from six.moves.BaseHTTPServer import BaseHTTPRequestHandler # @UnresolvedImport
|
||||
from six.moves.BaseHTTPServer import HTTPServer # @UnresolvedImport
|
||||
from six.moves.urllib.parse import unquote # @UnresolvedImport
|
||||
|
||||
import json
|
||||
import threading
|
||||
import ssl
|
||||
|
||||
from .utils import exceptionToMessage
|
||||
from .certs import createSelfSignedCert
|
||||
from .log import logger
|
||||
|
||||
class HTTPServerHandler(BaseHTTPRequestHandler):
|
||||
service = None
|
||||
protocol_version = 'HTTP/1.0'
|
||||
server_version = 'OpenGnsys Agent Server'
|
||||
sys_version = ''
|
||||
|
||||
def sendJsonError(self, code, message):
|
||||
self.send_response(code)
|
||||
self.send_header('Content-type', 'application/json')
|
||||
self.end_headers()
|
||||
self.wfile.write(json.dumps({'error': message}))
|
||||
return
|
||||
|
||||
def sendJsonResponse(self, data):
|
||||
self.send_response(200)
|
||||
data = json.dumps(data)
|
||||
self.send_header('Content-type', 'application/json')
|
||||
self.send_header('Content-Length', len(data))
|
||||
self.end_headers()
|
||||
# Send the html message
|
||||
self.wfile.write(data)
|
||||
|
||||
|
||||
# parseURL
|
||||
def parseUrl(self):
|
||||
# Very simple path & params splitter
|
||||
path = self.path.split('?')[0][1:].split('/')
|
||||
|
||||
try:
|
||||
params = dict((v[0], unquote(v[1])) for v in (v.split('=') for v in self.path.split('?')[1].split('&')))
|
||||
except Exception:
|
||||
params = {}
|
||||
|
||||
for v in self.service.modules:
|
||||
if v.name == path[0]: # Case Sensitive!!!!
|
||||
return (v, path[1:], params)
|
||||
|
||||
return (None, path, params)
|
||||
|
||||
def notifyMessage(self, module, path, getParams, postParams):
|
||||
'''
|
||||
Locates witch module will process the message based on path (first folder on url path)
|
||||
'''
|
||||
try:
|
||||
data = module.processServerMessage(path, getParams, postParams, self)
|
||||
self.sendJsonResponse(data)
|
||||
except Exception as e:
|
||||
logger.exception()
|
||||
self.sendJsonError(500, exceptionToMessage(e))
|
||||
|
||||
def do_GET(self):
|
||||
module, path, params = self.parseUrl()
|
||||
|
||||
self.notifyMessage(module, path, params, None)
|
||||
|
||||
def do_POST(self):
|
||||
module, path, getParams = self.parseUrl()
|
||||
|
||||
# Tries to get JSON content (UTF-8 encoded)
|
||||
try:
|
||||
length = int(self.headers.getheader('content-length'))
|
||||
content = self.rfile.read(length).decode('utf-8')
|
||||
logger.debug('length: {}, content >>{}<<'.format(length, content))
|
||||
postParams = json.loads(content)
|
||||
except Exception as e:
|
||||
self.sendJsonError(500, exceptionToMessage(e))
|
||||
|
||||
self.notifyMessage(module, path, getParams, postParams)
|
||||
|
||||
|
||||
def log_error(self, fmt, *args):
|
||||
logger.error('HTTP ' + fmt % args)
|
||||
|
||||
def log_message(self, fmt, *args):
|
||||
logger.info('HTTP ' + fmt % args)
|
||||
|
||||
|
||||
class HTTPThreadingServer(ThreadingMixIn, HTTPServer):
|
||||
pass
|
||||
|
||||
class HTTPServerThread(threading.Thread):
|
||||
def __init__(self, address, service):
|
||||
super(self.__class__, self).__init__()
|
||||
|
||||
HTTPServerHandler.service = service # Keep tracking of service so we can intercact with it
|
||||
|
||||
self.certFile = createSelfSignedCert()
|
||||
self.server = HTTPThreadingServer(address, HTTPServerHandler)
|
||||
self.server.socket = ssl.wrap_socket(self.server.socket, certfile=self.certFile, server_side=True)
|
||||
|
||||
logger.debug('Initialized HTTPS Server thread on {}'.format(address))
|
||||
|
||||
def getServerUrl(self):
|
||||
return 'https://{}:{}/'.format(self.server.server_address[0], self.server.server_address[1])
|
||||
|
||||
def stop(self):
|
||||
self.server.shutdown()
|
||||
|
||||
def run(self):
|
||||
self.server.serve_forever()
|
||||
|
||||
|
|
@ -1,423 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import socket
|
||||
import threading
|
||||
import six
|
||||
import traceback
|
||||
import json
|
||||
|
||||
from opengnsys.utils import toUnicode
|
||||
from opengnsys.log import logger
|
||||
|
||||
# The IPC Server will wait for connections from clients
|
||||
# Clients will open socket, and wait for data from server
|
||||
# The messages sent (from server) will be the following (subject to future changes):
|
||||
# Message_id Data Action
|
||||
# ------------ -------- --------------------------
|
||||
# MSG_LOGOFF None Logout user from session
|
||||
# MSG_MESSAGE message,level Display a message with level (INFO, WARN, ERROR, FATAL) # TODO: Include level, right now only has message
|
||||
# MSG_POPUP title,message Display a popup box with a title
|
||||
# MSG_SCRIPT python script Execute an specific python script INSIDE CLIENT environment (this messages is not sent right now)
|
||||
# The messages received (sent from client) will be the following:
|
||||
# Message_id Data Action
|
||||
# ------------ -------- --------------------------
|
||||
# REQ_LOGOUT Logout user from session
|
||||
# REQ_INFORMATION None Request information from ipc server (maybe configuration parameters in a near future)
|
||||
# REQ_LOGIN python script Execute an specific python script INSIDE CLIENT environment (this messages is not sent right now)
|
||||
#
|
||||
# All messages are in the form:
|
||||
# BYTE
|
||||
# 0 1-2 3 4 ...
|
||||
# MSG_ID DATA_LENGTH (little endian) Data (can be 0 length)
|
||||
# With a previos "MAGIC" header in fron of each message
|
||||
|
||||
# Client messages
|
||||
MSG_LOGOFF = 0xA1 # Request log off from an user
|
||||
MSG_MESSAGE = 0xB2
|
||||
MSG_POPUP = 0xB3
|
||||
MSG_SCRIPT = 0xC3
|
||||
|
||||
# Request messages
|
||||
REQ_MESSAGE = 0xD4
|
||||
REQ_POPUP = 0xD5
|
||||
REQ_LOGIN = 0xE5
|
||||
REQ_LOGOUT = 0xF6
|
||||
|
||||
# Reverse msgs dict for debugging
|
||||
REV_DICT = {
|
||||
MSG_LOGOFF: 'MSG_LOGOFF',
|
||||
MSG_MESSAGE: 'MSG_MESSAGE',
|
||||
MSG_POPUP: 'MSG_POPUP',
|
||||
MSG_SCRIPT: 'MSG_SCRIPT',
|
||||
REQ_LOGIN: 'REQ_LOGIN',
|
||||
REQ_LOGOUT: 'REQ_LOGOUT',
|
||||
REQ_MESSAGE: 'REQ_MESSAGE'
|
||||
}
|
||||
|
||||
MAGIC = b'\x4F\x47\x41\x00' # OGA in hexa with a padded 0 to the right
|
||||
|
||||
|
||||
# States for client processor
|
||||
ST_SECOND_BYTE = 0x01
|
||||
ST_RECEIVING = 0x02
|
||||
ST_PROCESS_MESSAGE = 0x02
|
||||
|
||||
|
||||
class ClientProcessor(threading.Thread):
|
||||
def __init__(self, parent, clientSocket):
|
||||
super(self.__class__, self).__init__()
|
||||
self.parent = parent
|
||||
self.clientSocket = clientSocket
|
||||
self.running = False
|
||||
self.messages = six.moves.queue.Queue(32) # @UndefinedVariable
|
||||
|
||||
def stop(self):
|
||||
logger.debug('Stoping client processor')
|
||||
self.running = False
|
||||
|
||||
def processRequest(self, msg, data):
|
||||
logger.debug('Got Client message {}={}'.format(msg, REV_DICT.get(msg)))
|
||||
if self.parent.clientMessageProcessor is not None:
|
||||
self.parent.clientMessageProcessor(msg, data)
|
||||
|
||||
def run(self):
|
||||
self.running = True
|
||||
self.clientSocket.setblocking(0)
|
||||
|
||||
state = None
|
||||
recv_msg = None
|
||||
recv_data = None
|
||||
while self.running:
|
||||
try:
|
||||
counter = 1024
|
||||
while counter > 0: # So we process at least the incoming queue every XX bytes readed
|
||||
counter -= 1
|
||||
b = self.clientSocket.recv(1)
|
||||
if b == b'':
|
||||
# Client disconnected
|
||||
self.running = False
|
||||
break
|
||||
buf = six.byte2int(b) # Empty buffer, this is set as non-blocking
|
||||
if state is None:
|
||||
if buf in (REQ_MESSAGE, REQ_LOGIN, REQ_LOGOUT):
|
||||
logger.debug('State set to {}'.format(buf))
|
||||
state = buf
|
||||
recv_msg = buf
|
||||
continue # Get next byte
|
||||
else:
|
||||
logger.debug('Got unexpected data {}'.format(buf))
|
||||
elif state in (REQ_MESSAGE, REQ_LOGIN, REQ_LOGOUT):
|
||||
logger.debug('First length byte is {}'.format(buf))
|
||||
msg_len = buf
|
||||
state = ST_SECOND_BYTE
|
||||
continue
|
||||
elif state == ST_SECOND_BYTE:
|
||||
msg_len += buf << 8
|
||||
logger.debug('Second length byte is {}, len is {}'.format(buf, msg_len))
|
||||
if msg_len == 0:
|
||||
self.processRequest(recv_msg, None)
|
||||
state = None
|
||||
break
|
||||
state = ST_RECEIVING
|
||||
recv_data = b''
|
||||
continue
|
||||
elif state == ST_RECEIVING:
|
||||
recv_data += six.int2byte(buf)
|
||||
msg_len -= 1
|
||||
if msg_len == 0:
|
||||
self.processRequest(recv_msg, recv_data)
|
||||
recv_data = None
|
||||
state = None
|
||||
break
|
||||
else:
|
||||
logger.debug('Got invalid message from request: {}, state: {}'.format(buf, state))
|
||||
except socket.error as e:
|
||||
# If no data is present, no problem at all, pass to check messages
|
||||
pass
|
||||
except Exception as e:
|
||||
tb = traceback.format_exc()
|
||||
logger.error('Error: {}, trace: {}'.format(e, tb))
|
||||
|
||||
if self.running is False:
|
||||
break
|
||||
|
||||
try:
|
||||
msg = self.messages.get(block=True, timeout=1)
|
||||
except six.moves.queue.Empty: # No message got in time @UndefinedVariable
|
||||
continue
|
||||
|
||||
logger.debug('Got message {}={}'.format(msg, REV_DICT.get(msg[0])))
|
||||
|
||||
try:
|
||||
m = msg[1] if msg[1] is not None else b''
|
||||
l = len(m)
|
||||
data = MAGIC + six.int2byte(msg[0]) + six.int2byte(l & 0xFF) + six.int2byte(l >> 8) + m
|
||||
try:
|
||||
self.clientSocket.sendall(data)
|
||||
except socket.error as e:
|
||||
# Send data error
|
||||
logger.debug('Socket connection is no more available: {}'.format(e.args))
|
||||
self.running = False
|
||||
except Exception as e:
|
||||
logger.error('Invalid message in queue: {}'.format(e))
|
||||
|
||||
logger.debug('Client processor stopped')
|
||||
try:
|
||||
self.clientSocket.close()
|
||||
except Exception:
|
||||
pass # If can't close, nothing happens, just end thread
|
||||
|
||||
|
||||
class ServerIPC(threading.Thread):
|
||||
|
||||
def __init__(self, listenPort, clientMessageProcessor=None):
|
||||
super(self.__class__, self).__init__()
|
||||
self.port = listenPort
|
||||
self.running = False
|
||||
self.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self.threads = []
|
||||
self.clientMessageProcessor = clientMessageProcessor
|
||||
|
||||
def stop(self):
|
||||
logger.debug('Stopping Server IPC')
|
||||
self.running = False
|
||||
for t in self.threads:
|
||||
t.stop()
|
||||
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect(('localhost', self.port))
|
||||
self.serverSocket.close()
|
||||
|
||||
for t in self.threads:
|
||||
t.join()
|
||||
|
||||
def sendMessage(self, msgId, msgData):
|
||||
'''
|
||||
Notify message to all listening threads
|
||||
'''
|
||||
logger.debug('Sending message {}({}),{} to all clients'.format(msgId, REV_DICT.get(msgId), msgData))
|
||||
|
||||
# Convert to bytes so length is correctly calculated
|
||||
if isinstance(msgData, six.text_type):
|
||||
msgData = msgData.encode('utf8')
|
||||
|
||||
for t in self.threads:
|
||||
if t.isAlive():
|
||||
logger.debug('Sending to {}'.format(t))
|
||||
t.messages.put((msgId, msgData))
|
||||
|
||||
def sendLoggofMessage(self):
|
||||
self.sendMessage(MSG_LOGOFF, '')
|
||||
|
||||
def sendMessageMessage(self, message):
|
||||
self.sendMessage(MSG_MESSAGE, message)
|
||||
|
||||
def sendPopupMessage(self, title, message):
|
||||
self.sendMessage(MSG_POPUP, {'title':title, 'message':message})
|
||||
|
||||
def sendScriptMessage(self, script):
|
||||
self.sendMessage(MSG_SCRIPT, script)
|
||||
|
||||
def cleanupFinishedThreads(self):
|
||||
'''
|
||||
Cleans up current threads list
|
||||
'''
|
||||
aliveThreads = []
|
||||
for t in self.threads:
|
||||
if t.isAlive():
|
||||
logger.debug('Thread {} is alive'.format(t))
|
||||
aliveThreads.append(t)
|
||||
self.threads[:] = aliveThreads
|
||||
|
||||
def run(self):
|
||||
self.running = True
|
||||
|
||||
self.serverSocket.bind(('localhost', self.port))
|
||||
self.serverSocket.setblocking(1)
|
||||
self.serverSocket.listen(4)
|
||||
|
||||
while True:
|
||||
try:
|
||||
(clientSocket, address) = self.serverSocket.accept()
|
||||
# Stop processing if thread is mean to stop
|
||||
if self.running is False:
|
||||
break
|
||||
logger.debug('Got connection from {}'.format(address))
|
||||
|
||||
self.cleanupFinishedThreads() # House keeping
|
||||
|
||||
logger.debug('Starting new thread, current: {}'.format(self.threads))
|
||||
t = ClientProcessor(self, clientSocket)
|
||||
self.threads.append(t)
|
||||
t.start()
|
||||
except Exception as e:
|
||||
logger.error('Got an exception on Server ipc thread: {}'.format(e))
|
||||
|
||||
|
||||
class ClientIPC(threading.Thread):
|
||||
def __init__(self, listenPort):
|
||||
super(ClientIPC, self).__init__()
|
||||
self.port = listenPort
|
||||
self.running = False
|
||||
self.clientSocket = None
|
||||
self.messages = six.moves.queue.Queue(32) # @UndefinedVariable
|
||||
|
||||
self.connect()
|
||||
|
||||
def stop(self):
|
||||
self.running = False
|
||||
|
||||
def getMessage(self):
|
||||
while self.running:
|
||||
try:
|
||||
return self.messages.get(timeout=1)
|
||||
except six.moves.queue.Empty: # @UndefinedVariable
|
||||
continue
|
||||
|
||||
return None
|
||||
|
||||
def sendRequestMessage(self, msg, data=None):
|
||||
logger.debug('Sending request for msg: {}({}), {}'.format(msg, REV_DICT.get(msg), data))
|
||||
if data is None:
|
||||
data = b''
|
||||
|
||||
if isinstance(data, six.text_type): # Convert to bytes if necessary
|
||||
data = data.encode('utf-8')
|
||||
|
||||
l = len(data)
|
||||
msg = six.int2byte(msg) + six.int2byte(l & 0xFF) + six.int2byte(l >> 8) + data
|
||||
self.clientSocket.sendall(msg)
|
||||
|
||||
def sendLogin(self, username, language):
|
||||
self.sendRequestMessage(REQ_LOGIN, username+','+language)
|
||||
|
||||
def sendLogout(self, username):
|
||||
self.sendRequestMessage(REQ_LOGOUT, username)
|
||||
|
||||
def sendMessage(self, module, message, data=None):
|
||||
'''
|
||||
Sends a message "message" with data (data will be encoded as json, so ensure that it is serializable)
|
||||
@param module: Module that will receive this message
|
||||
@param message: Message to send. This message is "customized", and understand by modules
|
||||
@param data: Data to be send as message companion
|
||||
'''
|
||||
msg = '\0'.join((module, message, json.dumps(data)))
|
||||
self.sendRequestMessage(REQ_MESSAGE, msg)
|
||||
|
||||
def messageReceived(self):
|
||||
'''
|
||||
Override this method to automatically get notified on new message
|
||||
received. Message is at self.messages queue
|
||||
'''
|
||||
pass
|
||||
|
||||
def receiveBytes(self, number):
|
||||
msg = b''
|
||||
while self.running and len(msg) < number:
|
||||
try:
|
||||
buf = self.clientSocket.recv(number - len(msg))
|
||||
if buf == b'':
|
||||
logger.debug('Buf {}, msg {}({})'.format(buf, msg, REV_DICT.get(msg)))
|
||||
self.running = False
|
||||
break
|
||||
msg += buf
|
||||
except socket.timeout:
|
||||
pass
|
||||
|
||||
if self.running is False:
|
||||
logger.debug('Not running, returning None')
|
||||
return None
|
||||
return msg
|
||||
|
||||
def connect(self):
|
||||
self.clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.clientSocket.connect(('localhost', self.port))
|
||||
self.clientSocket.settimeout(2) # Static, custom socket timeout of 2 seconds for local connection (no network)
|
||||
|
||||
def run(self):
|
||||
self.running = True
|
||||
|
||||
while self.running:
|
||||
try:
|
||||
msg = b''
|
||||
# We look for magic message header
|
||||
while self.running: # Wait for MAGIC
|
||||
try:
|
||||
buf = self.clientSocket.recv(len(MAGIC) - len(msg))
|
||||
if buf == b'':
|
||||
self.running = False
|
||||
break
|
||||
msg += buf
|
||||
if len(msg) != len(MAGIC):
|
||||
continue # Do not have message
|
||||
if msg != MAGIC: # Skip first byte an continue searchong
|
||||
msg = msg[1:]
|
||||
continue
|
||||
break
|
||||
except socket.timeout: # Timeout is here so we can get stop thread
|
||||
continue
|
||||
|
||||
if self.running is False:
|
||||
break
|
||||
|
||||
# Now we get message basic data (msg + datalen)
|
||||
msg = bytearray(self.receiveBytes(3))
|
||||
|
||||
# We have the magic header, here comes the message itself
|
||||
if msg is None:
|
||||
continue
|
||||
|
||||
msgId = msg[0]
|
||||
dataLen = msg[1] + (msg[2] << 8)
|
||||
if msgId not in (MSG_LOGOFF, MSG_MESSAGE, MSG_SCRIPT):
|
||||
raise Exception('Invalid message id: {}'.format(msgId))
|
||||
|
||||
data = self.receiveBytes(dataLen)
|
||||
if data is None:
|
||||
continue
|
||||
|
||||
self.messages.put((msgId, data))
|
||||
self.messageReceived()
|
||||
|
||||
except socket.error as e:
|
||||
logger.error('Communication with server got an error: {}'.format(toUnicode(e.strerror)))
|
||||
self.running = False
|
||||
return
|
||||
except Exception as e:
|
||||
tb = traceback.format_exc()
|
||||
logger.error('Error: {}, trace: {}'.format(e, tb))
|
||||
|
||||
try:
|
||||
self.clientSocket.close()
|
||||
except Exception:
|
||||
pass # If can't close, nothing happens, just end thread
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from opengnsys.service import CommonService
|
||||
from opengnsys.service import IPC_PORT
|
||||
from opengnsys import ipc
|
||||
|
||||
from opengnsys.log import logger
|
||||
|
||||
from opengnsys.linux.daemon import Daemon
|
||||
|
||||
import sys
|
||||
import signal
|
||||
import json
|
||||
|
||||
try:
|
||||
from prctl import set_proctitle # @UnresolvedImport
|
||||
except Exception: # Platform may not include prctl, so in case it's not available, we let the "name" as is
|
||||
def set_proctitle(_):
|
||||
pass
|
||||
|
||||
|
||||
class OGAgentSvc(Daemon, CommonService):
|
||||
def __init__(self, args=None):
|
||||
Daemon.__init__(self, '/var/run/opengnsys-agent.pid')
|
||||
CommonService.__init__(self)
|
||||
|
||||
def run(self):
|
||||
logger.debug('** Running Daemon **')
|
||||
set_proctitle('OGAgent')
|
||||
|
||||
self.initialize()
|
||||
|
||||
# Call modules initialization
|
||||
# They are called in sequence, no threading is done at this point, so ensure modules onActivate always returns
|
||||
|
||||
|
||||
# *********************
|
||||
# * Main Service loop *
|
||||
# *********************
|
||||
# Counter used to check ip changes only once every 10 seconds, for
|
||||
# example
|
||||
try:
|
||||
while self.isAlive:
|
||||
# In milliseconds, will break
|
||||
self.doWait(1000)
|
||||
except (KeyboardInterrupt, SystemExit) as e:
|
||||
logger.error('Requested exit of main loop')
|
||||
except Exception as e:
|
||||
logger.exception()
|
||||
logger.error('Caught exception on main loop: {}'.format(e))
|
||||
|
||||
self.terminate()
|
||||
|
||||
self.notifyStop()
|
||||
|
||||
def signal_handler(self, signal, frame):
|
||||
self.isAlive = False
|
||||
sys.stderr.write("signal handler: {}".format(signal))
|
||||
|
||||
|
||||
def usage():
|
||||
sys.stderr.write("usage: {} start|stop|restart|fg|login 'username'|logout 'username'|message 'module' 'message' 'json'\n".format(sys.argv[0]))
|
||||
sys.exit(2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
logger.setLevel('INFO')
|
||||
|
||||
if len(sys.argv) == 5 and sys.argv[1] == 'message':
|
||||
logger.debug('Running client opengnsys')
|
||||
client = None
|
||||
try:
|
||||
client = ipc.ClientIPC(IPC_PORT)
|
||||
client.sendMessage(sys.argv[2], sys.argv[3], json.loads(sys.argv[4]))
|
||||
sys.exit(0)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
|
||||
if len(sys.argv) == 3 and sys.argv[1] in ('login', 'logout'):
|
||||
logger.debug('Running client opengnsys')
|
||||
client = None
|
||||
try:
|
||||
client = ipc.ClientIPC(IPC_PORT)
|
||||
if 'login' == sys.argv[1]:
|
||||
client.sendLogin(sys.argv[2])
|
||||
sys.exit(0)
|
||||
elif 'logout' == sys.argv[1]:
|
||||
client.sendLogout(sys.argv[2])
|
||||
sys.exit(0)
|
||||
else:
|
||||
usage()
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
elif len(sys.argv) != 2:
|
||||
usage()
|
||||
|
||||
logger.debug('Executing actor')
|
||||
daemon = OGAgentSvc()
|
||||
|
||||
signal.signal(signal.SIGTERM, daemon.signal_handler)
|
||||
signal.signal(signal.SIGINT, daemon.signal_handler)
|
||||
|
||||
if len(sys.argv) == 2:
|
||||
if 'start' == sys.argv[1]:
|
||||
daemon.start()
|
||||
elif 'stop' == sys.argv[1]:
|
||||
daemon.stop()
|
||||
elif 'restart' == sys.argv[1]:
|
||||
daemon.restart()
|
||||
elif 'fg' == sys.argv[1]:
|
||||
daemon.run()
|
||||
else:
|
||||
usage()
|
||||
sys.exit(0)
|
||||
else:
|
||||
usage()
|
|
@ -1,32 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
|
@ -1,182 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
@author: : http://www.jejik.com/authors/sander_marechal/
|
||||
@see: : http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/
|
||||
'''
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import atexit
|
||||
from opengnsys.log import logger
|
||||
|
||||
from signal import SIGTERM
|
||||
|
||||
|
||||
class Daemon:
|
||||
"""
|
||||
A generic daemon class.
|
||||
|
||||
Usage: subclass the Daemon class and override the run() method
|
||||
"""
|
||||
def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
|
||||
self.stdin = stdin
|
||||
self.stdout = stdout
|
||||
self.stderr = stderr
|
||||
self.pidfile = pidfile
|
||||
|
||||
def daemonize(self):
|
||||
"""
|
||||
do the UNIX double-fork magic, see Stevens' "Advanced
|
||||
Programming in the UNIX Environment" for details (ISBN 0201563177)
|
||||
http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
|
||||
"""
|
||||
try:
|
||||
pid = os.fork()
|
||||
if pid > 0:
|
||||
# exit first parent
|
||||
sys.exit(0)
|
||||
except OSError as e:
|
||||
logger.error("fork #1 error: {}".format(e))
|
||||
sys.stderr.write("fork #1 failed: {}\n".format(e))
|
||||
sys.exit(1)
|
||||
|
||||
# decouple from parent environment
|
||||
os.chdir("/")
|
||||
os.setsid()
|
||||
os.umask(0)
|
||||
|
||||
# do second fork
|
||||
try:
|
||||
pid = os.fork()
|
||||
if pid > 0:
|
||||
# exit from second parent
|
||||
sys.exit(0)
|
||||
except OSError as e:
|
||||
logger.error("fork #2 error: {}".format(e))
|
||||
sys.stderr.write("fork #2 failed: {}\n".format(e))
|
||||
sys.exit(1)
|
||||
|
||||
# redirect standard file descriptors
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
si = open(self.stdin, 'r')
|
||||
so = open(self.stdout, 'a+')
|
||||
se = open(self.stderr, 'a+', 0)
|
||||
os.dup2(si.fileno(), sys.stdin.fileno())
|
||||
os.dup2(so.fileno(), sys.stdout.fileno())
|
||||
os.dup2(se.fileno(), sys.stderr.fileno())
|
||||
|
||||
# write pidfile
|
||||
atexit.register(self.delpid)
|
||||
pid = str(os.getpid())
|
||||
with open(self.pidfile, 'w+') as f:
|
||||
f.write("{}\n".format(pid))
|
||||
|
||||
def delpid(self):
|
||||
try:
|
||||
os.remove(self.pidfile)
|
||||
except Exception:
|
||||
# Not found/not permissions or whatever...
|
||||
pass
|
||||
|
||||
def start(self):
|
||||
"""
|
||||
Start the daemon
|
||||
"""
|
||||
logger.debug('Starting daemon')
|
||||
# Check for a pidfile to see if the daemon already runs
|
||||
try:
|
||||
pf = open(self.pidfile, 'r')
|
||||
pid = int(pf.read().strip())
|
||||
pf.close()
|
||||
except IOError:
|
||||
pid = None
|
||||
|
||||
if pid:
|
||||
message = "pidfile {} already exist. Daemon already running?\n".format(pid)
|
||||
logger.error(message)
|
||||
sys.stderr.write(message)
|
||||
sys.exit(1)
|
||||
|
||||
# Start the daemon
|
||||
self.daemonize()
|
||||
try:
|
||||
self.run()
|
||||
except Exception as e:
|
||||
logger.error('Exception running process: {}'.format(e))
|
||||
|
||||
if os.path.exists(self.pidfile):
|
||||
os.remove(self.pidfile)
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
Stop the daemon
|
||||
"""
|
||||
# Get the pid from the pidfile
|
||||
try:
|
||||
pf = open(self.pidfile, 'r')
|
||||
pid = int(pf.read().strip())
|
||||
pf.close()
|
||||
except IOError:
|
||||
pid = None
|
||||
|
||||
if pid is None:
|
||||
message = "pidfile {} does not exist. Daemon not running?\n".format(self.pidfile)
|
||||
logger.info(message)
|
||||
# sys.stderr.write(message)
|
||||
return # not an error in a restart
|
||||
|
||||
# Try killing the daemon process
|
||||
try:
|
||||
for i in range(10):
|
||||
os.kill(pid, SIGTERM)
|
||||
time.sleep(1)
|
||||
except OSError as err:
|
||||
if err.errno == 3: # No such process
|
||||
if os.path.exists(self.pidfile):
|
||||
os.remove(self.pidfile)
|
||||
else:
|
||||
sys.stderr.write(err)
|
||||
sys.exit(1)
|
||||
|
||||
def restart(self):
|
||||
"""
|
||||
Restart the daemon
|
||||
"""
|
||||
self.stop()
|
||||
self.start()
|
||||
|
||||
# Overridables
|
||||
def run(self):
|
||||
"""
|
||||
You should override this method when you subclass Daemon. It will be called after the process has been
|
||||
daemonized by start() or restart().
|
||||
"""
|
|
@ -1,80 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
import six
|
||||
|
||||
# Valid logging levels, from UDS Broker (uds.core.utils.log)
|
||||
OTHER, DEBUG, INFO, WARN, ERROR, FATAL = (10000 * (x + 1) for x in six.moves.xrange(6)) # @UndefinedVariable
|
||||
|
||||
|
||||
class LocalLogger(object):
|
||||
def __init__(self):
|
||||
# tempdir is different for "user application" and "service"
|
||||
# service wil get c:\windows\temp, while user will get c:\users\XXX\temp
|
||||
# Try to open logger at /var/log path
|
||||
# If it fails (access denied normally), will try to open one at user's home folder, and if
|
||||
# agaim it fails, open it at the tmpPath
|
||||
|
||||
for logDir in ('/var/log', os.path.expanduser('~'), tempfile.gettempdir()):
|
||||
try:
|
||||
fname = os.path.join(logDir, 'opengnsys.log')
|
||||
logging.basicConfig(
|
||||
filename=fname,
|
||||
filemode='a',
|
||||
format='%(levelname)s %(asctime)s %(message)s',
|
||||
level=logging.DEBUG
|
||||
)
|
||||
self.logger = logging.getLogger('opengnsys')
|
||||
os.chmod(fname, 0o0600)
|
||||
return
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Logger can't be set
|
||||
self.logger = None
|
||||
|
||||
def log(self, level, message):
|
||||
# Debug messages are logged to a file
|
||||
# our loglevels are 10000 (other), 20000 (debug), ....
|
||||
# logging levels are 10 (debug), 20 (info)
|
||||
# OTHER = logging.NOTSET
|
||||
self.logger.log(int(level / 1000) - 10, message)
|
||||
|
||||
def isWindows(self):
|
||||
return False
|
||||
|
||||
def isLinux(self):
|
||||
return True
|
|
@ -1,286 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import socket
|
||||
import platform
|
||||
import fcntl
|
||||
import os
|
||||
import locale
|
||||
import ctypes # @UnusedImport
|
||||
import ctypes.util
|
||||
import subprocess
|
||||
import struct
|
||||
import array
|
||||
import six
|
||||
from opengnsys import utils
|
||||
from .renamer import rename
|
||||
|
||||
|
||||
def _getMacAddr(ifname):
|
||||
'''
|
||||
Returns the mac address of an interface
|
||||
Mac is returned as unicode utf-8 encoded
|
||||
'''
|
||||
if isinstance(ifname, list):
|
||||
return dict([(name, _getMacAddr(name)) for name in ifname])
|
||||
if isinstance(ifname, six.text_type):
|
||||
ifname = ifname.encode('utf-8') # If unicode, convert to bytes (or str in python 2.7)
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
info = bytearray(fcntl.ioctl(s.fileno(), 0x8927, struct.pack(str('256s'), ifname[:15])))
|
||||
return six.text_type(''.join(['%02x:' % char for char in info[18:24]])[:-1])
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def _getIpAddr(ifname):
|
||||
'''
|
||||
Returns the ip address of an interface
|
||||
Ip is returned as unicode utf-8 encoded
|
||||
'''
|
||||
if isinstance(ifname, list):
|
||||
return dict([(name, _getIpAddr(name)) for name in ifname])
|
||||
if isinstance(ifname, six.text_type):
|
||||
ifname = ifname.encode('utf-8') # If unicode, convert to bytes (or str in python 2.7)
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
return six.text_type(socket.inet_ntoa(fcntl.ioctl(
|
||||
s.fileno(),
|
||||
0x8915, # SIOCGIFADDR
|
||||
struct.pack(str('256s'), ifname[:15])
|
||||
)[20:24]))
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def _getInterfaces():
|
||||
'''
|
||||
Returns a list of interfaces names coded in utf-8
|
||||
'''
|
||||
max_possible = 128 # arbitrary. raise if needed.
|
||||
space = max_possible * 16
|
||||
if platform.architecture()[0] == '32bit':
|
||||
offset, length = 32, 32
|
||||
elif platform.architecture()[0] == '64bit':
|
||||
offset, length = 16, 40
|
||||
else:
|
||||
raise OSError('Unknown arquitecture {0}'.format(platform.architecture()[0]))
|
||||
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
names = array.array(str('B'), b'\0' * space)
|
||||
outbytes = struct.unpack(str('iL'), fcntl.ioctl(
|
||||
s.fileno(),
|
||||
0x8912, # SIOCGIFCONF
|
||||
struct.pack(str('iL'), space, names.buffer_info()[0])
|
||||
))[0]
|
||||
namestr = names.tostring()
|
||||
# return namestr, outbytes
|
||||
return [namestr[i:i + offset].split(b'\0', 1)[0].decode('utf-8') for i in range(0, outbytes, length)]
|
||||
|
||||
|
||||
def _getIpAndMac(ifname):
|
||||
ip, mac = _getIpAddr(ifname), _getMacAddr(ifname)
|
||||
return (ip, mac)
|
||||
|
||||
|
||||
def getComputerName():
|
||||
'''
|
||||
Returns computer name, with no domain
|
||||
'''
|
||||
return socket.gethostname().split('.')[0]
|
||||
|
||||
|
||||
def getNetworkInfo():
|
||||
'''
|
||||
Obtains a list of network interfaces
|
||||
@return: A "generator" of elements, that are dict-as-object, with this elements:
|
||||
name: Name of the interface
|
||||
mac: mac of the interface
|
||||
ip: ip of the interface
|
||||
'''
|
||||
for ifname in _getInterfaces():
|
||||
ip, mac = _getIpAndMac(ifname)
|
||||
if mac != '00:00:00:00:00:00': # Skips local interfaces
|
||||
yield utils.Bunch(name=ifname, mac=mac, ip=ip)
|
||||
|
||||
|
||||
def getDomainName():
|
||||
return ''
|
||||
|
||||
|
||||
def getLinuxVersion():
|
||||
lv = platform.linux_distribution()
|
||||
return lv[0] + ', ' + lv[1]
|
||||
|
||||
|
||||
def reboot(flags=0):
|
||||
'''
|
||||
Simple reboot using os command
|
||||
'''
|
||||
# Workaround for dummy thread
|
||||
if six.PY3 is False:
|
||||
import threading
|
||||
threading._DummyThread._Thread__stop = lambda x: 42
|
||||
|
||||
subprocess.call(['/sbin/reboot'])
|
||||
|
||||
|
||||
def poweroff(flags=0):
|
||||
'''
|
||||
Simple poweroff using os command
|
||||
'''
|
||||
# Workaround for dummy thread
|
||||
if six.PY3 is False:
|
||||
import threading
|
||||
threading._DummyThread._Thread__stop = lambda x: 42
|
||||
|
||||
subprocess.call(['/sbin/poweroff'])
|
||||
|
||||
|
||||
def logoff():
|
||||
'''
|
||||
Kills all curent user processes, which must send a logogof
|
||||
caveat: If the user has other sessions, will also disconnect from them
|
||||
'''
|
||||
# Workaround for dummy thread
|
||||
if six.PY3 is False:
|
||||
import threading
|
||||
threading._DummyThread._Thread__stop = lambda x: 42
|
||||
|
||||
subprocess.call(['/usr/bin/pkill', '-u', os.environ['USER']])
|
||||
|
||||
|
||||
def renameComputer(newName):
|
||||
rename(newName)
|
||||
|
||||
|
||||
def joinDomain(domain, ou, account, password, executeInOneStep=False):
|
||||
pass
|
||||
|
||||
|
||||
def changeUserPassword(user, oldPassword, newPassword):
|
||||
'''
|
||||
Simple password change for user using command line
|
||||
'''
|
||||
os.system('echo "{1}\n{1}" | /usr/bin/passwd {0} 2> /dev/null'.format(user, newPassword))
|
||||
|
||||
|
||||
class XScreenSaverInfo(ctypes.Structure):
|
||||
_fields_ = [('window', ctypes.c_long),
|
||||
('state', ctypes.c_int),
|
||||
('kind', ctypes.c_int),
|
||||
('til_or_since', ctypes.c_ulong),
|
||||
('idle', ctypes.c_ulong),
|
||||
('eventMask', ctypes.c_ulong)]
|
||||
|
||||
# Initialize xlib & xss
|
||||
try:
|
||||
xlibPath = ctypes.util.find_library('X11')
|
||||
xssPath = ctypes.util.find_library('Xss')
|
||||
xlib = ctypes.cdll.LoadLibrary(xlibPath)
|
||||
xss = ctypes.cdll.LoadLibrary(xssPath)
|
||||
|
||||
# Fix result type to XScreenSaverInfo Structure
|
||||
xss.XScreenSaverQueryExtension.restype = ctypes.c_int
|
||||
xss.XScreenSaverAllocInfo.restype = ctypes.POINTER(XScreenSaverInfo) # Result in a XScreenSaverInfo structure
|
||||
except Exception: # Libraries not accesible, not found or whatever..
|
||||
xlib = xss = None
|
||||
|
||||
|
||||
def initIdleDuration(atLeastSeconds):
|
||||
'''
|
||||
On linux we set the screensaver to at least required seconds, or we never will get "idle"
|
||||
'''
|
||||
# Workaround for dummy thread
|
||||
if six.PY3 is False:
|
||||
import threading
|
||||
threading._DummyThread._Thread__stop = lambda x: 42
|
||||
|
||||
subprocess.call(['/usr/bin/xset', 's', '{}'.format(atLeastSeconds + 30)])
|
||||
# And now reset it
|
||||
subprocess.call(['/usr/bin/xset', 's', 'reset'])
|
||||
|
||||
|
||||
def getIdleDuration():
|
||||
'''
|
||||
Returns idle duration, in seconds
|
||||
'''
|
||||
if xlib is None or xss is None:
|
||||
return 0 # Libraries not available
|
||||
|
||||
# production code might want to not hardcode the offset 16...
|
||||
display = xlib.XOpenDisplay(None)
|
||||
|
||||
event_base = ctypes.c_int()
|
||||
error_base = ctypes.c_int()
|
||||
|
||||
available = xss.XScreenSaverQueryExtension(display, ctypes.byref(event_base), ctypes.byref(error_base))
|
||||
if available != 1:
|
||||
return 0 # No screen saver is available, no way of getting idle
|
||||
|
||||
info = xss.XScreenSaverAllocInfo()
|
||||
xss.XScreenSaverQueryInfo(display, xlib.XDefaultRootWindow(display), info)
|
||||
|
||||
if info.contents.state != 0:
|
||||
return 3600 * 100 * 1000 # If screen saver is active, return a high enough value
|
||||
|
||||
return info.contents.idle / 1000.0
|
||||
|
||||
|
||||
def getCurrentUser():
|
||||
'''
|
||||
Returns current logged in user
|
||||
'''
|
||||
return os.environ['USER']
|
||||
|
||||
|
||||
def getSessionLanguage():
|
||||
'''
|
||||
Returns the user's session language
|
||||
'''
|
||||
return locale.getdefaultlocale()[0]
|
||||
|
||||
|
||||
def showPopup(title, message):
|
||||
'''
|
||||
Displays a message box on user's session (during 1 min).
|
||||
'''
|
||||
return subprocess.call('zenity --info --timeout 60 --title "{}" --text "{}"'.format(title, message), shell=True)
|
||||
|
||||
|
||||
def get_etc_path():
|
||||
"""
|
||||
:return:
|
||||
Returns etc directory path.
|
||||
"""
|
||||
return os.sep + 'etc'
|
|
@ -1,61 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import platform
|
||||
import os
|
||||
import sys
|
||||
import pkgutil
|
||||
|
||||
from opengnsys.log import logger
|
||||
|
||||
renamers = {}
|
||||
|
||||
|
||||
# Renamers now are for IPv4 only addresses
|
||||
def rename(newName):
|
||||
distribution = platform.linux_distribution()[0].lower().strip()
|
||||
if distribution in renamers:
|
||||
return renamers[distribution](newName)
|
||||
|
||||
# Try Debian renamer, simplest one
|
||||
logger.info('Renamer for platform "{0}" not found, tryin debian renamer'.format(distribution))
|
||||
return renamers['debian'](newName)
|
||||
|
||||
|
||||
# Do load of packages
|
||||
def _init():
|
||||
pkgpath = os.path.dirname(sys.modules[__name__].__file__)
|
||||
for _, name, _ in pkgutil.iter_modules([pkgpath]):
|
||||
__import__(__name__ + '.' + name, globals(), locals())
|
||||
|
||||
_init()
|
|
@ -1,68 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from opengnsys.linux.renamer import renamers
|
||||
from opengnsys.log import logger
|
||||
|
||||
import os
|
||||
|
||||
|
||||
def rename(newName):
|
||||
'''
|
||||
Debian renamer
|
||||
Expects new host name on newName
|
||||
Host does not needs to be rebooted after renaming
|
||||
'''
|
||||
logger.debug('using Debian renamer')
|
||||
|
||||
with open('/etc/hostname', 'w') as hostname:
|
||||
hostname.write(newName)
|
||||
|
||||
# Force system new name
|
||||
os.system('/bin/hostname %s' % newName)
|
||||
|
||||
# add name to "hosts"
|
||||
with open('/etc/hosts', 'r') as hosts:
|
||||
lines = hosts.readlines()
|
||||
with open('/etc/hosts', 'w') as hosts:
|
||||
hosts.write("127.0.1.1\t%s\n" % newName)
|
||||
for l in lines:
|
||||
if l[:9] == '127.0.1.1': # Skips existing 127.0.1.1. if it already exists
|
||||
continue
|
||||
hosts.write(l)
|
||||
|
||||
return True
|
||||
|
||||
# All names in lower case
|
||||
renamers['debian'] = rename
|
||||
renamers['ubuntu'] = rename
|
|
@ -1,66 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from opengnsys.linux.renamer import renamers
|
||||
from opengnsys.log import logger
|
||||
|
||||
import os
|
||||
|
||||
|
||||
def rename(newName):
|
||||
'''
|
||||
RH, Centos, Fedora Renamer
|
||||
Expects new host name on newName
|
||||
Host does not needs to be rebooted after renaming
|
||||
'''
|
||||
logger.debug('using SUSE renamer')
|
||||
|
||||
with open('/etc/hostname', 'w') as hostname:
|
||||
hostname.write(newName)
|
||||
|
||||
# Force system new name
|
||||
os.system('/bin/hostname %s' % newName)
|
||||
|
||||
# add name to "hosts"
|
||||
with open('/etc/hosts', 'r') as hosts:
|
||||
lines = hosts.readlines()
|
||||
with open('/etc/hosts', 'w') as hosts:
|
||||
hosts.write("127.0.1.1\t{}\n".format(newName))
|
||||
for l in lines:
|
||||
if l[:9] != '127.0.1.1': # Skips existing 127.0.1.1. if it already exists
|
||||
hosts.write(l)
|
||||
|
||||
return True
|
||||
|
||||
# All names in lower case
|
||||
renamers['opensuse'] = rename
|
||||
renamers['suse'] = rename
|
|
@ -1,74 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from opengnsys.linux.renamer import renamers
|
||||
from opengnsys.log import logger
|
||||
|
||||
import os
|
||||
|
||||
|
||||
def rename(newName):
|
||||
'''
|
||||
RH, Centos, Fedora Renamer
|
||||
Expects new host name on newName
|
||||
Host does not needs to be rebooted after renaming
|
||||
'''
|
||||
logger.debug('using RH renamer')
|
||||
|
||||
with open('/etc/hostname', 'w') as hostname:
|
||||
hostname.write(newName)
|
||||
|
||||
# Force system new name
|
||||
os.system('/bin/hostname %s' % newName)
|
||||
|
||||
# add name to "hosts"
|
||||
with open('/etc/hosts', 'r') as hosts:
|
||||
lines = hosts.readlines()
|
||||
with open('/etc/hosts', 'w') as hosts:
|
||||
hosts.write("127.0.1.1\t{}\n".format(newName))
|
||||
for l in lines:
|
||||
if l[:9] != '127.0.1.1': # Skips existing 127.0.1.1. if it already exists
|
||||
hosts.write(l)
|
||||
|
||||
with open('/etc/sysconfig/network', 'r') as net:
|
||||
lines = net.readlines()
|
||||
with open('/etc/sysconfig/network', 'w') as net:
|
||||
net.write('HOSTNAME={}\n'.format(newName))
|
||||
for l in lines:
|
||||
if l[:8] != 'HOSTNAME':
|
||||
net.write(l)
|
||||
|
||||
return True
|
||||
|
||||
# All names in lower case
|
||||
renamers['centos linux'] = rename
|
||||
renamers['fedora'] = rename
|
|
@ -1,111 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
# pylint: disable=unused-wildcard-import,wildcard-import
|
||||
|
||||
# This is a simple module loader, so we can add "external opengnsys" modules as addons
|
||||
# Modules under "opengsnsys/modules" are always autoloaded
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import pkgutil
|
||||
import os.path
|
||||
|
||||
from opengnsys.workers import ServerWorker
|
||||
from opengnsys.workers import ClientWorker
|
||||
from .log import logger
|
||||
|
||||
|
||||
def loadModules(controller, client=False):
|
||||
'''
|
||||
Load own provided modules plus the modules that are in the configuration path.
|
||||
The loading order is not defined (they are loaded as found, because modules MUST be "standalone" modules
|
||||
@param service: The service that:
|
||||
* Holds the configuration
|
||||
* Will be used to initialize modules.
|
||||
'''
|
||||
|
||||
ogModules = []
|
||||
|
||||
if client is False:
|
||||
from opengnsys.modules.server import OpenGnSys # @UnusedImport
|
||||
from .modules import server # @UnusedImport, just used to ensure opengnsys modules are initialized
|
||||
modPath = 'opengnsys.modules.server'
|
||||
modType = ServerWorker
|
||||
else:
|
||||
from opengnsys.modules.client import OpenGnSys # @UnusedImport @Reimport
|
||||
from .modules import client # @UnusedImport, just used to ensure opengnsys modules are initialized
|
||||
modPath = 'opengnsys.modules.client'
|
||||
modType = ClientWorker
|
||||
|
||||
def addCls(cls):
|
||||
logger.debug('Found module class {}'.format(cls))
|
||||
try:
|
||||
if cls.name is None:
|
||||
# Error, cls has no name
|
||||
# Log the issue and
|
||||
logger.error('Class {} has no name attribute'.format(cls))
|
||||
return
|
||||
ogModules.append(cls(controller))
|
||||
except Exception as e:
|
||||
logger.error('Error loading module {}'.format(e))
|
||||
|
||||
def recursiveAdd(p):
|
||||
subcls = p.__subclasses__()
|
||||
|
||||
if len(subcls) == 0:
|
||||
addCls(p)
|
||||
else:
|
||||
for c in subcls:
|
||||
recursiveAdd(c)
|
||||
|
||||
def doLoad(paths):
|
||||
for (module_loader, name, ispkg) in pkgutil.iter_modules(paths, modPath + '.'):
|
||||
if ispkg:
|
||||
logger.debug('Found module package {}'.format(name))
|
||||
module_loader.find_module(name).load_module(name)
|
||||
|
||||
|
||||
if controller.config.has_option('opengnsys', 'path') is True:
|
||||
paths = tuple(os.path.abspath(v) for v in controller.config.get('opengnsys', 'path').split(','))
|
||||
else:
|
||||
paths = ()
|
||||
|
||||
# paths += (os.path.dirname(sys.modules[modPath].__file__),)
|
||||
|
||||
logger.debug('Loading modules from {}'.format(paths))
|
||||
|
||||
# Load modules
|
||||
doLoad(paths)
|
||||
|
||||
# Add to list of available modules
|
||||
recursiveAdd(modType)
|
||||
|
||||
return ogModules
|
|
@ -1,103 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import traceback
|
||||
import sys
|
||||
import six
|
||||
|
||||
if sys.platform == 'win32':
|
||||
from opengnsys.windows.log import LocalLogger # @UnusedImport
|
||||
else:
|
||||
from opengnsys.linux.log import LocalLogger # @Reimport
|
||||
|
||||
# Valid logging levels, from UDS Broker (uds.core.utils.log)
|
||||
OTHER, DEBUG, INFO, WARN, ERROR, FATAL = (10000 * (x + 1) for x in six.moves.xrange(6)) # @UndefinedVariable
|
||||
|
||||
_levelName = {
|
||||
'OTHER': OTHER,
|
||||
'DEBUG': DEBUG,
|
||||
'INFO': INFO,
|
||||
'WARN': WARN,
|
||||
'ERROR': ERROR,
|
||||
'FATAL': FATAL
|
||||
}
|
||||
|
||||
class Logger(object):
|
||||
def __init__(self):
|
||||
self.logLevel = INFO
|
||||
self.logger = LocalLogger()
|
||||
|
||||
def setLevel(self, level):
|
||||
'''
|
||||
Sets log level filter (minimum level required for a log message to be processed)
|
||||
:param level: Any message with a level below this will be filtered out
|
||||
'''
|
||||
if isinstance(level, six.string_types):
|
||||
level = _levelName.get(level, INFO)
|
||||
|
||||
self.logLevel = level # Ensures level is an integer or fails
|
||||
|
||||
def log(self, level, message):
|
||||
if level < self.logLevel: # Skip not wanted messages
|
||||
return
|
||||
|
||||
self.logger.log(level, message)
|
||||
|
||||
def debug(self, message):
|
||||
self.log(DEBUG, message)
|
||||
|
||||
def warn(self, message):
|
||||
self.log(WARN, message)
|
||||
|
||||
def info(self, message):
|
||||
self.log(INFO, message)
|
||||
|
||||
def error(self, message):
|
||||
self.log(ERROR, message)
|
||||
|
||||
def fatal(self, message):
|
||||
self.log(FATAL, message)
|
||||
|
||||
def exception(self):
|
||||
try:
|
||||
tb = traceback.format_exc()
|
||||
except Exception:
|
||||
tb = '(could not get traceback!)'
|
||||
|
||||
self.log(DEBUG, tb)
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
|
||||
|
||||
logger = Logger()
|
|
@ -1,32 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Ramón M. Gómez, ramongomez at us dot es
|
||||
'''
|
||||
from __future__ import unicode_literals
|
|
@ -1,263 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import socket
|
||||
import platform
|
||||
import fcntl
|
||||
import os
|
||||
import locale
|
||||
import ctypes # @UnusedImport
|
||||
import ctypes.util
|
||||
import subprocess
|
||||
import struct
|
||||
import array
|
||||
import six
|
||||
from opengnsys import utils
|
||||
import netifaces
|
||||
|
||||
|
||||
def _getMacAddr(ifname):
|
||||
'''
|
||||
Returns the mac address of an interface
|
||||
Mac is returned as unicode utf-8 encoded
|
||||
'''
|
||||
if isinstance(ifname, list):
|
||||
return dict([(name, _getMacAddr(name)) for name in ifname])
|
||||
if isinstance(ifname, six.text_type):
|
||||
ifname = ifname.encode('utf-8') # If unicode, convert to bytes (or str in python 2.7)
|
||||
try:
|
||||
return netifaces.ifaddresses(ifname)[18][0]['addr']
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def _getIpAddr(ifname):
|
||||
'''
|
||||
Returns the IP address of an interface
|
||||
IP is returned as unicode utf-8 encoded
|
||||
'''
|
||||
if isinstance(ifname, list):
|
||||
return dict([(name, _getIpAddr(name)) for name in ifname])
|
||||
if isinstance(ifname, six.text_type):
|
||||
ifname = ifname.encode('utf-8') # If unicode, convert to bytes (or str in python 2.7)
|
||||
try:
|
||||
return netifaces.ifaddresses(ifname)[2][0]['addr']
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def _getInterfaces():
|
||||
'''
|
||||
Returns a list of interfaces names
|
||||
'''
|
||||
return netifaces.interfaces()
|
||||
|
||||
|
||||
def _getIpAndMac(ifname):
|
||||
ip, mac = _getIpAddr(ifname), _getMacAddr(ifname)
|
||||
return (ip, mac)
|
||||
|
||||
|
||||
def getComputerName():
|
||||
'''
|
||||
Returns computer name, with no domain
|
||||
'''
|
||||
return socket.gethostname().split('.')[0]
|
||||
|
||||
|
||||
def getNetworkInfo():
|
||||
'''
|
||||
Obtains a list of network interfaces
|
||||
@return: A "generator" of elements, that are dict-as-object, with this elements:
|
||||
name: Name of the interface
|
||||
mac: mac of the interface
|
||||
ip: ip of the interface
|
||||
'''
|
||||
for ifname in _getInterfaces():
|
||||
ip, mac = _getIpAndMac(ifname)
|
||||
if mac != None and ip != None: # Skips local interfaces
|
||||
yield utils.Bunch(name=ifname, mac=mac, ip=ip)
|
||||
|
||||
|
||||
def getDomainName():
|
||||
return ''
|
||||
|
||||
|
||||
def getMacosVersion():
|
||||
return 'macOS {}'.format(platform.mac_ver()[0])
|
||||
|
||||
|
||||
def reboot(flags=0):
|
||||
'''
|
||||
Simple reboot command
|
||||
'''
|
||||
# Workaround for dummy thread
|
||||
if six.PY3 is False:
|
||||
import threading
|
||||
threading._DummyThread._Thread__stop = lambda x: 42
|
||||
|
||||
# Exec reboot command
|
||||
subprocess.call('/sbin/shutdown -r now', shell=True)
|
||||
|
||||
|
||||
def poweroff(flags=0):
|
||||
'''
|
||||
Simple poweroff command
|
||||
'''
|
||||
# Workaround for dummy thread
|
||||
if six.PY3 is False:
|
||||
import threading
|
||||
threading._DummyThread._Thread__stop = lambda x: 42
|
||||
|
||||
# Exec shutdown command
|
||||
subprocess.call('/sbin/shutdown -h now', shell=True)
|
||||
|
||||
|
||||
def logoff():
|
||||
'''
|
||||
Simple logout using AppleScript
|
||||
'''
|
||||
# Workaround for dummy thread
|
||||
if six.PY3 is False:
|
||||
import threading
|
||||
threading._DummyThread._Thread__stop = lambda x: 42
|
||||
|
||||
# Exec logout using AppleSctipt
|
||||
subprocess.call('/usr/bin/osascript -e \'tell app "System Events" to «event aevtrlgo»\'', shell=True)
|
||||
|
||||
|
||||
def renameComputer(newName):
|
||||
rename(newName)
|
||||
|
||||
|
||||
def joinDomain(domain, ou, account, password, executeInOneStep=False):
|
||||
pass
|
||||
|
||||
|
||||
def changeUserPassword(user, oldPassword, newPassword):
|
||||
'''
|
||||
Simple password change for user using command line
|
||||
'''
|
||||
os.system('echo "{1}\n{1}" | /usr/bin/passwd {0} 2> /dev/null'.format(user, newPassword))
|
||||
|
||||
|
||||
class XScreenSaverInfo(ctypes.Structure):
|
||||
_fields_ = [('window', ctypes.c_long),
|
||||
('state', ctypes.c_int),
|
||||
('kind', ctypes.c_int),
|
||||
('til_or_since', ctypes.c_ulong),
|
||||
('idle', ctypes.c_ulong),
|
||||
('eventMask', ctypes.c_ulong)]
|
||||
|
||||
# Initialize xlib & xss
|
||||
try:
|
||||
xlibPath = ctypes.util.find_library('X11')
|
||||
xssPath = ctypes.util.find_library('Xss')
|
||||
xlib = ctypes.cdll.LoadLibrary(xlibPath)
|
||||
xss = ctypes.cdll.LoadLibrary(xssPath)
|
||||
|
||||
# Fix result type to XScreenSaverInfo Structure
|
||||
xss.XScreenSaverQueryExtension.restype = ctypes.c_int
|
||||
xss.XScreenSaverAllocInfo.restype = ctypes.POINTER(XScreenSaverInfo) # Result in a XScreenSaverInfo structure
|
||||
except Exception: # Libraries not accesible, not found or whatever..
|
||||
xlib = xss = None
|
||||
|
||||
|
||||
def initIdleDuration(atLeastSeconds):
|
||||
'''
|
||||
On linux we set the screensaver to at least required seconds, or we never will get "idle"
|
||||
'''
|
||||
# Workaround for dummy thread
|
||||
if six.PY3 is False:
|
||||
import threading
|
||||
threading._DummyThread._Thread__stop = lambda x: 42
|
||||
|
||||
subprocess.call(['/usr/bin/xset', 's', '{}'.format(atLeastSeconds + 30)])
|
||||
# And now reset it
|
||||
subprocess.call(['/usr/bin/xset', 's', 'reset'])
|
||||
|
||||
|
||||
def getIdleDuration():
|
||||
'''
|
||||
Returns idle duration, in seconds
|
||||
'''
|
||||
if xlib is None or xss is None:
|
||||
return 0 # Libraries not available
|
||||
|
||||
# production code might want to not hardcode the offset 16...
|
||||
display = xlib.XOpenDisplay(None)
|
||||
|
||||
event_base = ctypes.c_int()
|
||||
error_base = ctypes.c_int()
|
||||
|
||||
available = xss.XScreenSaverQueryExtension(display, ctypes.byref(event_base), ctypes.byref(error_base))
|
||||
if available != 1:
|
||||
return 0 # No screen saver is available, no way of getting idle
|
||||
|
||||
info = xss.XScreenSaverAllocInfo()
|
||||
xss.XScreenSaverQueryInfo(display, xlib.XDefaultRootWindow(display), info)
|
||||
|
||||
if info.contents.state != 0:
|
||||
return 3600 * 100 * 1000 # If screen saver is active, return a high enough value
|
||||
|
||||
return info.contents.idle / 1000.0
|
||||
|
||||
|
||||
def getCurrentUser():
|
||||
'''
|
||||
Returns current logged in user
|
||||
'''
|
||||
return os.environ['USER']
|
||||
|
||||
|
||||
def getSessionLanguage():
|
||||
'''
|
||||
Returns the user's session language
|
||||
'''
|
||||
return locale.getdefaultlocale()[0]
|
||||
|
||||
|
||||
def showPopup(title, message):
|
||||
'''
|
||||
Displays a message box on user's session (during 1 min).
|
||||
'''
|
||||
# Show a dialog using AppleSctipt
|
||||
return subprocess.call('/usr/bin/osascript -e \'display notification "{}" with title "{}"\''.format(message, title), shell=True)
|
||||
|
||||
|
||||
def get_etc_path():
|
||||
"""
|
||||
:return:
|
||||
Returns etc directory path.
|
||||
"""
|
||||
return os.sep + 'etc'
|
|
@ -1,63 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
@author: Ramón M. Gómez, ramongomez at us dot es
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from opengnsys.workers import ClientWorker
|
||||
|
||||
from opengnsys import operations
|
||||
from opengnsys.log import logger
|
||||
from opengnsys.scriptThread import ScriptExecutorThread
|
||||
|
||||
class OpenGnSysWorker(ClientWorker):
|
||||
name = 'opengnsys'
|
||||
|
||||
def onActivation(self):
|
||||
logger.debug('Activate invoked')
|
||||
|
||||
def onDeactivation(self):
|
||||
logger.debug('Deactivate invoked')
|
||||
|
||||
# Processes script execution
|
||||
def process_script(self, jsonParams):
|
||||
logger.debug('Processed message: script({})'.format(jsonParams))
|
||||
thr = ScriptExecutorThread(jsonParams['code'])
|
||||
thr.start()
|
||||
#self.sendServerMessage('script', {'op', 'launched'})
|
||||
|
||||
def process_logoff(self, jsonParams):
|
||||
logger.debug('Processed message: logoff({})'.format(jsonParams))
|
||||
operations.logoff()
|
||||
|
||||
def process_popup(self, jsonParams):
|
||||
logger.debug('Processed message: popup({})'.format(jsonParams))
|
||||
ret = operations.showPopup(jsonParams['title'], jsonParams['message'])
|
||||
#self.sendServerMessage('popup', {'op', ret})
|
||||
|
|
@ -1,558 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
@author: Ramón M. Gómez, ramongomez at us dot es
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import os
|
||||
import random
|
||||
import shutil
|
||||
import string
|
||||
import subprocess
|
||||
import threading
|
||||
import time
|
||||
import urllib
|
||||
import signal
|
||||
|
||||
from opengnsys import REST
|
||||
from opengnsys import operations
|
||||
from opengnsys.log import logger
|
||||
from opengnsys.workers import ServerWorker
|
||||
from six.moves.urllib import parse
|
||||
|
||||
|
||||
# Check authorization header decorator
|
||||
def check_secret(fnc):
|
||||
"""
|
||||
Decorator to check for received secret key and raise exception if it isn't valid.
|
||||
"""
|
||||
def wrapper(*args, **kwargs):
|
||||
try:
|
||||
this, path, get_params, post_params, server = args # @UnusedVariable
|
||||
if this.random == server.headers['Authorization']:
|
||||
fnc(*args, **kwargs)
|
||||
else:
|
||||
raise Exception('Unauthorized operation')
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
raise Exception(e)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
# Error handler decorator.
|
||||
def catch_background_error(fnc):
|
||||
def wrapper(*args, **kwargs):
|
||||
this = args[0]
|
||||
try:
|
||||
fnc(*args, **kwargs)
|
||||
except Exception as e:
|
||||
this.REST.sendMessage('error?id={}'.format(kwargs.get('requestId', 'error')), {'error': '{}'.format(e)})
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def check_locked_partition(sync=False):
|
||||
"""
|
||||
Decorator to check if a partition is locked
|
||||
"""
|
||||
|
||||
def outer(fnc):
|
||||
def wrapper(*args, **kwargs):
|
||||
part_id = 'None'
|
||||
try:
|
||||
this, path, get_params, post_params, server = args # @UnusedVariable
|
||||
part_id = post_params['disk'] + post_params['part']
|
||||
if this.locked.get(part_id, False):
|
||||
this.locked[part_id] = True
|
||||
fnc(*args, **kwargs)
|
||||
else:
|
||||
return 'partition locked'
|
||||
except Exception as e:
|
||||
this.locked[part_id] = False
|
||||
return 'error {}'.format(e)
|
||||
finally:
|
||||
if sync is True:
|
||||
this.locked[part_id] = False
|
||||
logger.debug('Lock status: {} {}'.format(fnc, this.locked))
|
||||
|
||||
return wrapper
|
||||
|
||||
return outer
|
||||
|
||||
|
||||
class OpenGnSysWorker(ServerWorker):
|
||||
name = 'opengnsys'
|
||||
interface = None # Bound interface for OpenGnsys
|
||||
REST = None # REST object
|
||||
logged_in = False # User session flag
|
||||
browser = {} # Browser info
|
||||
commands = [] # Running commands
|
||||
random = None # Random string for secure connections
|
||||
length = 32 # Random string length
|
||||
access_token = refresh_token = None # Server authorization tokens
|
||||
grant_type = 'http://opengnsys.es/grants/og_client'
|
||||
|
||||
def _launch_browser(self, url):
|
||||
"""
|
||||
Launchs the Browser with specified URL
|
||||
:param url: URL to show
|
||||
"""
|
||||
logger.debug('Launching browser with URL: {}'.format(url))
|
||||
# Trying to kill an old browser
|
||||
try:
|
||||
os.kill(self.browser['process'].pid, signal.SIGKILL)
|
||||
except OSError:
|
||||
logger.warn('Cannot kill the old browser process')
|
||||
except KeyError:
|
||||
# There is no previous browser
|
||||
pass
|
||||
self.browser['url'] = url
|
||||
self.browser['process'] = subprocess.Popen(['browser', '-qws', url])
|
||||
|
||||
def _task_command(self, route, code, op_id, send_config=False):
|
||||
"""
|
||||
Task to execute a command and return results to a server URI
|
||||
:param route: server callback REST route to return results
|
||||
:param code: code to execute
|
||||
:param op_id: operation id.
|
||||
"""
|
||||
menu_url = ''
|
||||
# Show execution tacking log, if OGAgent runs on ogLive
|
||||
os_type = operations.os_type.lower()
|
||||
if os_type == 'oglive':
|
||||
menu_url = self.browser['url']
|
||||
self._launch_browser('http://localhost/cgi-bin/httpd-log.sh')
|
||||
# Execute the code
|
||||
(stat, out, err) = operations.exec_command(code)
|
||||
# Remove command from the list
|
||||
for c in self.commands:
|
||||
if c.getName() == op_id:
|
||||
self.commands.remove(c)
|
||||
# Remove the REST API prefix, if needed
|
||||
if route.startswith(self.REST.endpoint):
|
||||
route = route[len(self.REST.endpoint):]
|
||||
# Send back exit status and outputs (base64-encoded)
|
||||
self.REST.sendMessage(route, {'mac': self.interface.mac, 'ip': self.interface.ip, 'trace': op_id,
|
||||
'status': stat, 'output': out.encode('base64'), 'error': err.encode('base64')})
|
||||
# Show latest menu, if OGAgent runs on ogLive
|
||||
if os_type == 'oglive':
|
||||
# Send configuration data, if needed
|
||||
if send_config:
|
||||
self.REST.sendMessage('clients/configs', {'mac': self.interface.mac, 'ip': self.interface.ip,
|
||||
'config': operations.get_configuration()})
|
||||
self._launch_browser(menu_url)
|
||||
|
||||
def onActivation(self):
|
||||
"""
|
||||
Sends OGAgent activation notification to OpenGnsys server
|
||||
"""
|
||||
t = 0
|
||||
# Generate random secret to send on activation
|
||||
self.random = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(self.length))
|
||||
# Ensure cfg has required configuration variables or an exception will be thrown
|
||||
url = self.service.config.get('opengnsys', 'remote')
|
||||
server_client = self.service.config.get('opengnsys', 'client')
|
||||
server_secret = self.service.config.get('opengnsys', 'secret')
|
||||
if operations.os_type == 'ogLive' and 'oglive' in os.environ:
|
||||
# Replacing server IP if its running on ogLive client
|
||||
logger.debug('Activating on ogLive client, new server is {}'.format(os.environ['oglive']))
|
||||
url = parse.urlsplit(url)._replace(netloc=os.environ['oglive']).geturl()
|
||||
if not url.endswith(os.path.sep):
|
||||
url += os.path.sep
|
||||
self.REST = REST(url)
|
||||
# Get network interfaces until they are active or timeout (5 minutes)
|
||||
for t in range(0, 300):
|
||||
try:
|
||||
self.interface = list(operations.getNetworkInfo())[0] # Get first network interface
|
||||
except Exception as e:
|
||||
# Wait 1 sec. and retry
|
||||
time.sleep(1)
|
||||
finally:
|
||||
# Exit loop if interface is active
|
||||
if self.interface:
|
||||
if t > 0:
|
||||
logger.debug("Fetch connection data after {} tries".format(t))
|
||||
break
|
||||
# Raise error after timeout
|
||||
if not self.interface:
|
||||
raise e
|
||||
# Compose login route
|
||||
login_route = 'oauth/v2/token?client_id=' + server_client + '&client_secret=' + server_secret + \
|
||||
'&grant_type=' + self.grant_type + '&ip=' + self.interface.ip + '&mac=' + self.interface.mac + \
|
||||
'&token=' + self.random
|
||||
# Send initialization login message
|
||||
response = None
|
||||
# Loop to send initialization message
|
||||
for t in range(0, 100):
|
||||
try:
|
||||
try:
|
||||
# New web compatibility.
|
||||
self.REST = REST(self.service.config.get('opengnsys', 'remote'))
|
||||
response = self.REST.sendMessage(login_route)
|
||||
break
|
||||
except:
|
||||
# Trying to initialize on alternative server, if defined
|
||||
# (used in "exam mode" from the University of Seville)
|
||||
self.REST = REST(self.service.config.get('opengnsys', 'altremote'))
|
||||
response = self.REST.sendMessage(login_route)
|
||||
break
|
||||
except:
|
||||
time.sleep(3)
|
||||
# Raise error after timeout or authentication failure
|
||||
if 0 < t < 100:
|
||||
logger.debug('Successful connection after {} tries'.format(t))
|
||||
elif t == 100:
|
||||
raise Exception('Initialization error: Cannot connect to remote server')
|
||||
if response['access_token'] is None:
|
||||
raise Exception('Initialization error: Cannot obtain access token')
|
||||
# Read access tokens
|
||||
self.access_token = response['access_token']
|
||||
self.refresh_token = response['refresh_token']
|
||||
# Once authenticated with the server, change the API URL for private request
|
||||
self.REST = REST(url + 'api/private')
|
||||
# Set authorization tokens in the REST object, so in each request this token will be used
|
||||
self.REST.set_authorization_headers(self.access_token, self.refresh_token)
|
||||
# Completing OGAgent initialization process
|
||||
os_type = operations.os_type.lower()
|
||||
if os_type == 'oglive':
|
||||
# Create HTML file (TEMPORARY)
|
||||
message = """
|
||||
<html>
|
||||
<head></head>
|
||||
<style>
|
||||
#barra { width: 20px; height: 10px; position: relative; background: darkslategrey; }
|
||||
</style>
|
||||
<body>
|
||||
<h1 style="margin: 5em 0 0 5em; font-size: 250%; color: darkslategrey;">
|
||||
<span id="opengnsys"><span style="font-weight: lighter;">Open</span>Gnsys 3</div>
|
||||
<div id="barra"></span>
|
||||
</h1>
|
||||
<script>
|
||||
var elem = document.getElementById("barra");
|
||||
var max = document.getElementById("opengnsys").offsetWidth;
|
||||
var pos = 0;
|
||||
var inc = true;
|
||||
var id = setInterval(frame, 5);
|
||||
function frame() {
|
||||
if (inc) {
|
||||
if (pos == max - 20) { inc = false; } else { pos++; }
|
||||
} else {
|
||||
if (pos == 0) { inc = true; } else { pos--; }
|
||||
}
|
||||
elem.style.left = pos + 'px';
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>"""
|
||||
f = open('/tmp/init.html', 'w')
|
||||
f.write(message)
|
||||
f.close()
|
||||
# Launching Browser
|
||||
self._launch_browser('/tmp/init.html')
|
||||
self.REST.sendMessage('clients/statuses', {'mac': self.interface.mac, 'ip': self.interface.ip,
|
||||
'status': 'initializing'})
|
||||
# Send configuration message
|
||||
self.REST.sendMessage('clients/configs', {'mac': self.interface.mac, 'ip': self.interface.ip,
|
||||
'config': operations.get_configuration()})
|
||||
# Launching new Browser with client's menu
|
||||
# menu_url = self.REST.sendMessage('menus?mac' + self.interface.mac + '&ip=' + self.interface.ip)
|
||||
menu_url = '/opt/opengnsys/log/' + self.interface.ip + '.info.html' # TEMPORARY menu
|
||||
self._launch_browser(menu_url)
|
||||
else:
|
||||
# Delete marking files
|
||||
for f in ['ogboot.me', 'ogboot.firstboot', 'ogboot.secondboot']:
|
||||
try:
|
||||
os.remove(os.sep + f)
|
||||
except OSError:
|
||||
pass
|
||||
# Copy file "HostsFile.FirstOctetOfIPAddress" to "HostsFile", if it exists
|
||||
# (used in "exam mode" from the University of Seville)
|
||||
hosts_file = os.path.join(operations.get_etc_path(), 'hosts')
|
||||
new_file = hosts_file + '.' + self.interface.ip.split('.')[0]
|
||||
if os.path.isfile(new_file):
|
||||
shutil.copy2(new_file, hosts_file)
|
||||
# Return status message
|
||||
self.REST.sendMessage('clients/statuses', {'mac': self.interface.mac, 'ip': self.interface.ip,
|
||||
'status': os_type})
|
||||
|
||||
def onDeactivation(self):
|
||||
"""
|
||||
Sends OGAgent stopping notification to OpenGnsys server
|
||||
"""
|
||||
logger.debug('onDeactivation')
|
||||
self.REST.sendMessage('clients/statuses', {'mac': self.interface.mac, 'ip': self.interface.ip,
|
||||
'ostype': operations.os_type, 'osversion': operations.os_version,
|
||||
'status': 'off'})
|
||||
|
||||
def processClientMessage(self, message, data):
|
||||
logger.debug('Got OpenGnsys message from client: {}, data {}'.format(message, data))
|
||||
|
||||
def onLogin(self, data):
|
||||
"""
|
||||
Sends session login notification to OpenGnsys server
|
||||
"""
|
||||
user, sep, language = data.partition(',')
|
||||
logger.debug('Received login for {} with language {}'.format(user, language))
|
||||
self.logged_in = True
|
||||
self.REST.sendMessage('ogagent/loggedin', {'ip': self.interface.ip, 'user': user, 'language': language,
|
||||
'ostype': operations.os_type, 'osversion': operations.os_version})
|
||||
|
||||
def onLogout(self, user):
|
||||
"""
|
||||
Sends session logout notification to OpenGnsys server
|
||||
"""
|
||||
logger.debug('Received logout for {}'.format(user))
|
||||
self.logged_in = False
|
||||
self.REST.sendMessage('ogagent/loggedout', {'ip': self.interface.ip, 'user': user})
|
||||
|
||||
def process_ogclient(self, path, get_params, post_params, server):
|
||||
"""
|
||||
This method can be overridden to provide your own message processor, or better you can
|
||||
implement a method that is called exactly as "process_" + path[0] (module name has been removed from path
|
||||
array) and this default processMessage will invoke it
|
||||
* Example:
|
||||
Imagine this invocation url (no matter if GET or POST): http://example.com:9999/Sample/mazinger/Z
|
||||
The HTTP Server will remove "Sample" from path, parse arguments and invoke this method as this:
|
||||
module.processMessage(["mazinger","Z"], get_params, post_params)
|
||||
|
||||
This method will process "mazinger", and look for a "self" method that is called "process_mazinger",
|
||||
and invoke it this way:
|
||||
return self.process_mazinger(["Z"], get_params, post_params)
|
||||
|
||||
In the case path is empty (that is, the path is composed only by the module name, like in
|
||||
"http://example.com/Sample", the "process" method will be invoked directly
|
||||
|
||||
The methods must return data that can be serialized to json (i.e. Objects are not serializable to json,
|
||||
basic type are)
|
||||
"""
|
||||
if not path:
|
||||
return "ok"
|
||||
try:
|
||||
operation = getattr(self, 'ogclient_' + path[0])
|
||||
except Exception:
|
||||
raise Exception('Message processor for "{}" not found'.format(path[0]))
|
||||
return operation(path[1:], get_params, post_params)
|
||||
|
||||
def process_status(self, path, get_params, post_params, server):
|
||||
"""
|
||||
Returns client status (OS type or execution status) and login status
|
||||
:param path:
|
||||
:param get_params:
|
||||
:param post_params:
|
||||
:param server:
|
||||
:return: JSON object {"status": "status_code", "loggedin": boolean}
|
||||
"""
|
||||
res = {'loggedin': self.logged_in}
|
||||
try:
|
||||
res['status'] = operations.os_type.lower()
|
||||
except KeyError:
|
||||
res['status'] = ''
|
||||
# Check if OpenGnsys Client is busy
|
||||
if res['status'] == 'oglive' and len(self.commands) > 0:
|
||||
res['status'] = 'busy'
|
||||
return res
|
||||
|
||||
@check_secret
|
||||
def process_reboot(self, path, get_params, post_params, server):
|
||||
"""
|
||||
Launches a system reboot operation
|
||||
:param path:
|
||||
:param get_params:
|
||||
:param post_params:
|
||||
:param server: authorization header
|
||||
:return: JSON object {"op": "launched"}
|
||||
"""
|
||||
logger.debug('Received reboot operation')
|
||||
|
||||
# Rebooting thread
|
||||
def rebt():
|
||||
operations.reboot()
|
||||
|
||||
threading.Thread(target=rebt).start()
|
||||
return {'op': 'launched'}
|
||||
|
||||
@check_secret
|
||||
def process_poweroff(self, path, get_params, post_params, server):
|
||||
"""
|
||||
Launches a system power off operation
|
||||
:param path:
|
||||
:param get_params:
|
||||
:param post_params:
|
||||
:param server: authorization header
|
||||
:return: JSON object {"op": "launched"}
|
||||
"""
|
||||
logger.debug('Received poweroff operation')
|
||||
|
||||
# Powering off thread
|
||||
def pwoff():
|
||||
time.sleep(2)
|
||||
operations.poweroff()
|
||||
|
||||
threading.Thread(target=pwoff).start()
|
||||
return {'op': 'launched'}
|
||||
|
||||
@check_secret
|
||||
def process_script(self, path, get_params, post_params, server):
|
||||
"""
|
||||
Processes an script execution (script should be encoded in base64)
|
||||
:param path:
|
||||
:param get_params:
|
||||
:param post_params: JSON object {"redirect_uri, "uri", "script": "commands", "id": trace_id}
|
||||
:param server: authorization header
|
||||
:return: JSON object {"op": "launched"} or {"error": "message"}
|
||||
"""
|
||||
logger.debug('Processing script request')
|
||||
# Processing data
|
||||
try:
|
||||
script = urllib.unquote(post_params.get('script').decode('base64')).decode('utf8')
|
||||
op_id = post_params.get('id')
|
||||
route = post_params.get('redirectUri')
|
||||
send_config = (post_params.get('sendConfig', 'false') == 'true')
|
||||
# Check if the thread id. exists
|
||||
for c in self.commands:
|
||||
if c.getName() == str(op_id):
|
||||
raise Exception('Task id. already exists: {}'.format(op_id))
|
||||
if post_params.get('client', 'false') == 'false':
|
||||
# Launching a new thread
|
||||
thr = threading.Thread(name=op_id, target=self._task_command, args=(route, script, op_id, send_config))
|
||||
thr.start()
|
||||
self.commands.append(thr)
|
||||
else:
|
||||
# Executing as normal user
|
||||
self.sendClientMessage('script', {'code': script})
|
||||
except Exception as e:
|
||||
logger.error('Got exception {}'.format(e))
|
||||
return {'error': e}
|
||||
return {'op': 'launched'}
|
||||
|
||||
@check_secret
|
||||
def process_logoff(self, path, get_params, post_params, server):
|
||||
"""
|
||||
Closes user session
|
||||
"""
|
||||
logger.debug('Received logoff operation')
|
||||
# Send log off message to OGAgent client
|
||||
self.sendClientMessage('logoff', {})
|
||||
return {'op': 'sent to client'}
|
||||
|
||||
@check_secret
|
||||
def process_popup(self, path, get_params, post_params, server):
|
||||
"""
|
||||
Shows a message popup on the user's session
|
||||
"""
|
||||
logger.debug('Received message operation')
|
||||
# Send popup message to OGAgent client
|
||||
self.sendClientMessage('popup', post_params)
|
||||
return {'op': 'launched'}
|
||||
|
||||
def process_client_popup(self, params):
|
||||
self.REST.sendMessage('popup_done', params)
|
||||
|
||||
@check_secret
|
||||
def process_config(self, path, get_params, post_params, server):
|
||||
"""
|
||||
Returns client configuration
|
||||
:param path:
|
||||
:param get_params:
|
||||
:param post_params:
|
||||
:param server: authorization header
|
||||
:return: JSON object
|
||||
"""
|
||||
serialno = '' # Serial number
|
||||
storage = [] # Storage configuration
|
||||
warnings = 0 # Number of warnings
|
||||
logger.debug('Received getconfig operation')
|
||||
# Processing data
|
||||
for row in operations.get_configuration().split(';'):
|
||||
cols = row.split(':')
|
||||
if len(cols) == 1:
|
||||
if cols[0] != '':
|
||||
# Serial number
|
||||
serialno = cols[0]
|
||||
else:
|
||||
# Skip blank rows
|
||||
pass
|
||||
elif len(cols) == 7:
|
||||
disk, npart, tpart, fs, opsys, size, usage = cols
|
||||
try:
|
||||
if int(npart) == 0:
|
||||
# Disk information
|
||||
storage.append({'disk': int(disk), 'parttable': int(tpart), 'size': int(size)})
|
||||
else:
|
||||
# Partition information
|
||||
storage.append({'disk': int(disk), 'partition': int(npart), 'parttype': tpart,
|
||||
'filesystem': fs, 'operatingsystem': opsys, 'size': int(size),
|
||||
'usage': int(usage)})
|
||||
except ValueError:
|
||||
logger.warn('Configuration parameter error: {}'.format(cols))
|
||||
warnings += 1
|
||||
else:
|
||||
# Log warnings
|
||||
logger.warn('Configuration data error: {}'.format(cols))
|
||||
warnings += 1
|
||||
# Return configuration data and count of warnings
|
||||
return {'serialno': serialno, 'storage': storage, 'warnings': warnings}
|
||||
|
||||
@check_secret
|
||||
def process_execinfo(self, path, get_params, post_params, server):
|
||||
"""
|
||||
Returns running commands information
|
||||
:param path:
|
||||
:param get_params:
|
||||
:param post_params:
|
||||
:param server: authorization header
|
||||
:return: JSON array: [["callback_url", "commands", trace_id], ...]
|
||||
"""
|
||||
data = []
|
||||
logger.debug('Received execinfo operation')
|
||||
# Return the arguments of all running threads
|
||||
for c in self.commands:
|
||||
if c.is_alive():
|
||||
data.append(c.__dict__['_Thread__args'])
|
||||
return data
|
||||
|
||||
@check_secret
|
||||
def process_stopcmd(self, path, get_params, post_params, server):
|
||||
"""
|
||||
Stops a running process identified by its trace id.
|
||||
:param path:
|
||||
:param get_params:
|
||||
:param post_params: JSON object {"trace": trace_id}
|
||||
:param server: authorization header
|
||||
:return: JSON object: {"stopped": trace_id}
|
||||
"""
|
||||
logger.debug('Received stopcmd operation with params {}:'.format(post_params))
|
||||
# Find operation id. and stop the thread
|
||||
op_id = post_params.get('trace')
|
||||
for c in self.commands:
|
||||
if c.is_alive() and c.getName() == str(op_id):
|
||||
c._Thread__stop()
|
||||
return {"stopped": op_id}
|
||||
return {}
|
|
@ -1,32 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
|
@ -1,182 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
@author: : http://www.jejik.com/authors/sander_marechal/
|
||||
@see: : http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/
|
||||
'''
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import atexit
|
||||
from opengnsys.log import logger
|
||||
|
||||
from signal import SIGTERM
|
||||
|
||||
|
||||
class Daemon:
|
||||
"""
|
||||
A generic daemon class.
|
||||
|
||||
Usage: subclass the Daemon class and override the run() method
|
||||
"""
|
||||
def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
|
||||
self.stdin = stdin
|
||||
self.stdout = stdout
|
||||
self.stderr = stderr
|
||||
self.pidfile = pidfile
|
||||
|
||||
def daemonize(self):
|
||||
"""
|
||||
do the UNIX double-fork magic, see Stevens' "Advanced
|
||||
Programming in the UNIX Environment" for details (ISBN 0201563177)
|
||||
http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
|
||||
"""
|
||||
try:
|
||||
pid = os.fork()
|
||||
if pid > 0:
|
||||
# exit first parent
|
||||
sys.exit(0)
|
||||
except OSError as e:
|
||||
logger.error("fork #1 error: {}".format(e))
|
||||
sys.stderr.write("fork #1 failed: {}\n".format(e))
|
||||
sys.exit(1)
|
||||
|
||||
# decouple from parent environment
|
||||
os.chdir("/")
|
||||
os.setsid()
|
||||
os.umask(0)
|
||||
|
||||
# do second fork
|
||||
try:
|
||||
pid = os.fork()
|
||||
if pid > 0:
|
||||
# exit from second parent
|
||||
sys.exit(0)
|
||||
except OSError as e:
|
||||
logger.error("fork #2 error: {}".format(e))
|
||||
sys.stderr.write("fork #2 failed: {}\n".format(e))
|
||||
sys.exit(1)
|
||||
|
||||
# redirect standard file descriptors
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
si = open(self.stdin, 'r')
|
||||
so = open(self.stdout, 'a+')
|
||||
se = open(self.stderr, 'a+', 0)
|
||||
os.dup2(si.fileno(), sys.stdin.fileno())
|
||||
os.dup2(so.fileno(), sys.stdout.fileno())
|
||||
os.dup2(se.fileno(), sys.stderr.fileno())
|
||||
|
||||
# write pidfile
|
||||
atexit.register(self.delpid)
|
||||
pid = str(os.getpid())
|
||||
with open(self.pidfile, 'w+') as f:
|
||||
f.write("{}\n".format(pid))
|
||||
|
||||
def delpid(self):
|
||||
try:
|
||||
os.remove(self.pidfile)
|
||||
except Exception:
|
||||
# Not found/not permissions or whatever...
|
||||
pass
|
||||
|
||||
def start(self):
|
||||
"""
|
||||
Start the daemon
|
||||
"""
|
||||
logger.debug('Starting daemon')
|
||||
# Check for a pidfile to see if the daemon already runs
|
||||
try:
|
||||
pf = open(self.pidfile, 'r')
|
||||
pid = int(pf.read().strip())
|
||||
pf.close()
|
||||
except IOError:
|
||||
pid = None
|
||||
|
||||
if pid:
|
||||
message = "pidfile {} already exist. Daemon already running?\n".format(pid)
|
||||
logger.error(message)
|
||||
sys.stderr.write(message)
|
||||
sys.exit(1)
|
||||
|
||||
# Start the daemon
|
||||
self.daemonize()
|
||||
try:
|
||||
self.run()
|
||||
except Exception as e:
|
||||
logger.error('Exception running process: {}'.format(e))
|
||||
|
||||
if os.path.exists(self.pidfile):
|
||||
os.remove(self.pidfile)
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
Stop the daemon
|
||||
"""
|
||||
# Get the pid from the pidfile
|
||||
try:
|
||||
pf = open(self.pidfile, 'r')
|
||||
pid = int(pf.read().strip())
|
||||
pf.close()
|
||||
except IOError:
|
||||
pid = None
|
||||
|
||||
if pid is None:
|
||||
message = "pidfile {} does not exist. Daemon not running?\n".format(self.pidfile)
|
||||
logger.info(message)
|
||||
# sys.stderr.write(message)
|
||||
return # not an error in a restart
|
||||
|
||||
# Try killing the daemon process
|
||||
try:
|
||||
for i in range(10):
|
||||
os.kill(pid, SIGTERM)
|
||||
time.sleep(1)
|
||||
except OSError as err:
|
||||
if err.errno == 3: # No such process
|
||||
if os.path.exists(self.pidfile):
|
||||
os.remove(self.pidfile)
|
||||
else:
|
||||
sys.stderr.write(err)
|
||||
sys.exit(1)
|
||||
|
||||
def restart(self):
|
||||
"""
|
||||
Restart the daemon
|
||||
"""
|
||||
self.stop()
|
||||
self.start()
|
||||
|
||||
# Overridables
|
||||
def run(self):
|
||||
"""
|
||||
You should override this method when you subclass Daemon. It will be called after the process has been
|
||||
daemonized by start() or restart().
|
||||
"""
|
|
@ -1,258 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""
|
||||
@author: Ramón M. Gómez, ramongomez at us dot es
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import socket
|
||||
import platform
|
||||
import os
|
||||
import fcntl
|
||||
import subprocess
|
||||
import struct
|
||||
import array
|
||||
import six
|
||||
import chardet
|
||||
from opengnsys import utils
|
||||
from opengnsys.log import logger
|
||||
|
||||
|
||||
def _getMacAddr(ifname):
|
||||
"""
|
||||
Returns the mac address of an interface
|
||||
Mac is returned as unicode utf-8 encoded
|
||||
"""
|
||||
if isinstance(ifname, list):
|
||||
return dict([(name, _getMacAddr(name)) for name in ifname])
|
||||
if isinstance(ifname, six.text_type):
|
||||
ifname = ifname.encode('utf-8') # If unicode, convert to bytes (or str in python 2.7)
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
info = bytearray(fcntl.ioctl(s.fileno(), 0x8927, struct.pack(str('256s'), ifname[:15])))
|
||||
return six.text_type(''.join(['%02x:' % char for char in info[18:24]])[:-1])
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def _getIpAddr(ifname):
|
||||
"""
|
||||
Returns the ip address of an interface
|
||||
Ip is returned as unicode utf-8 encoded
|
||||
"""
|
||||
if isinstance(ifname, list):
|
||||
return dict([(name, _getIpAddr(name)) for name in ifname])
|
||||
if isinstance(ifname, six.text_type):
|
||||
ifname = ifname.encode('utf-8') # If unicode, convert to bytes (or str in python 2.7)
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
return six.text_type(socket.inet_ntoa(fcntl.ioctl(
|
||||
s.fileno(),
|
||||
0x8915, # SIOCGIFADDR
|
||||
struct.pack(str('256s'), ifname[:15])
|
||||
)[20:24]))
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def _getInterfaces():
|
||||
"""
|
||||
Returns a list of interfaces names coded in utf-8
|
||||
"""
|
||||
max_possible = 128 # arbitrary. raise if needed.
|
||||
space = max_possible * 16
|
||||
if platform.architecture()[0] == '32bit':
|
||||
offset, length = 32, 32
|
||||
elif platform.architecture()[0] == '64bit':
|
||||
offset, length = 16, 40
|
||||
else:
|
||||
raise OSError('Unknown arquitecture {0}'.format(platform.architecture()[0]))
|
||||
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
names = array.array(str('B'), b'\0' * space)
|
||||
outbytes = struct.unpack(str('iL'), fcntl.ioctl(
|
||||
s.fileno(),
|
||||
0x8912, # SIOCGIFCONF
|
||||
struct.pack(str('iL'), space, names.buffer_info()[0])
|
||||
))[0]
|
||||
namestr = names.tostring()
|
||||
# return namestr, outbytes
|
||||
return [namestr[i:i + offset].split(b'\0', 1)[0].decode('utf-8') for i in range(0, outbytes, length)]
|
||||
|
||||
|
||||
def _getIpAndMac(ifname):
|
||||
ip, mac = _getIpAddr(ifname), _getMacAddr(ifname)
|
||||
return ip, mac
|
||||
|
||||
|
||||
def _exec_ogcommand(ogcmd):
|
||||
"""
|
||||
Loads OpenGnsys environment variables, executes the command and returns the result
|
||||
"""
|
||||
ret = subprocess.check_output(ogcmd, shell=True)
|
||||
return ret
|
||||
|
||||
|
||||
def getComputerName():
|
||||
"""
|
||||
Returns computer name, with no domain
|
||||
"""
|
||||
return socket.gethostname().split('.')[0]
|
||||
|
||||
|
||||
def getNetworkInfo():
|
||||
"""
|
||||
Obtains a list of network interfaces
|
||||
:return: A "generator" of elements, that are dict-as-object, with this elements:
|
||||
name: Name of the interface
|
||||
mac: mac of the interface
|
||||
ip: ip of the interface
|
||||
"""
|
||||
for ifname in _getInterfaces():
|
||||
ip, mac = _getIpAndMac(ifname)
|
||||
if mac != '00:00:00:00:00:00': # Skips local interfaces
|
||||
yield utils.Bunch(name=ifname, mac=mac, ip=ip)
|
||||
|
||||
|
||||
def getDomainName():
|
||||
return ''
|
||||
|
||||
|
||||
def get_oglive_version():
|
||||
"""
|
||||
Returns ogLive Kernel version and architecture
|
||||
:return: kernel version
|
||||
"""
|
||||
kv = platform.os.uname()
|
||||
return kv[2] + ', ' + kv[4]
|
||||
|
||||
|
||||
def reboot():
|
||||
"""
|
||||
Simple reboot using OpenGnsys script
|
||||
"""
|
||||
# Workaround for dummy thread
|
||||
if six.PY3 is False:
|
||||
import threading
|
||||
threading._DummyThread._Thread__stop = lambda x: 42
|
||||
|
||||
_exec_ogcommand('/opt/opengnsys/scripts/reboot')
|
||||
|
||||
|
||||
def poweroff():
|
||||
"""
|
||||
Simple power off using OpenGnsys script
|
||||
"""
|
||||
# Workaround for dummy thread
|
||||
if six.PY3 is False:
|
||||
import threading
|
||||
threading._DummyThread._Thread__stop = lambda x: 42
|
||||
|
||||
_exec_ogcommand('/opt/opengnsys/scripts/poweroff')
|
||||
|
||||
|
||||
def get_etc_path():
|
||||
"""
|
||||
Returns etc directory path.
|
||||
"""
|
||||
return os.sep + 'etc'
|
||||
|
||||
|
||||
def get_configuration():
|
||||
"""
|
||||
Returns client's configuration
|
||||
Warning: this operation may take some time
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
_exec_ogcommand('/opt/opengnsys/interfaceAdm/getConfiguration')
|
||||
# Returns content of configuration file
|
||||
cfgdata = open('/tmp/getconfig', 'r').read().strip()
|
||||
except IOError:
|
||||
cfgdata = ''
|
||||
return cfgdata
|
||||
|
||||
|
||||
def exec_command(cmd):
|
||||
"""
|
||||
Executing a shell command
|
||||
:param cmd:
|
||||
:return: object with components:
|
||||
output: standard output
|
||||
error: error output
|
||||
exit: exit code
|
||||
"""
|
||||
proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
(out, err) = proc.communicate()
|
||||
try:
|
||||
if out is not None:
|
||||
encoding = chardet.detect(out)["encoding"]
|
||||
if encoding is not None:
|
||||
out = out.decode(encoding).encode("utf8")
|
||||
if err is not None:
|
||||
encoding = chardet.detect(err)["encoding"]
|
||||
if encoding is not None:
|
||||
err = err.decode(encoding).encode("utf8")
|
||||
except Exception as e:
|
||||
logger.debug("ERROR EXEC COMMAND: {}".format(str(e)))
|
||||
|
||||
stat = proc.returncode
|
||||
return stat, out, err
|
||||
|
||||
|
||||
def get_hardware():
|
||||
"""
|
||||
Returns client's hardware list
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
filepath = _exec_ogcommand('/opt/opengnsys/scripts/listHardwareInfo').strip()
|
||||
# Returns content of configuration file, skipping the header line and newline characters
|
||||
with open(filepath, 'r') as f:
|
||||
harddata = map(str.strip, f.readlines()[1:])
|
||||
except IOError:
|
||||
harddata = ''
|
||||
return harddata
|
||||
|
||||
|
||||
def get_software(disk, part):
|
||||
"""
|
||||
Returns software list installed on an operating system
|
||||
:param disk:
|
||||
:param part:
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
filepath = _exec_ogcommand('/opt/opengnsys/scripts/listSoftwareInfo {} {}'.format(disk, part)).strip()
|
||||
# Returns content of configuration file, skipping the header line and newline characters
|
||||
with open(filepath, 'r') as f:
|
||||
softdata = map(str.strip, f.readlines())
|
||||
except IOError:
|
||||
softdata = ''
|
||||
return softdata
|
|
@ -1,57 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""
|
||||
@author: Ramón M. Gómez, ramongomez at us dot es
|
||||
"""
|
||||
# pylint: disable=unused-wildcard-import,wildcard-import
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Importing platform operations and getting operating system data.
|
||||
if sys.platform == 'win32':
|
||||
from .windows.operations import * # @UnusedWildImport
|
||||
os_type = 'Windows'
|
||||
os_version = getWindowsVersion()
|
||||
else:
|
||||
if sys.platform == 'darwin':
|
||||
from .macos.operations import * # @UnusedWildImport
|
||||
os_type = 'MacOS'
|
||||
os_version = getMacosVersion().replace(',', '')
|
||||
else:
|
||||
if os.path.exists('/scripts/oginit'):
|
||||
from .oglive.operations import * # @UnusedWildImport
|
||||
os_type = 'ogLive'
|
||||
os_version = get_oglive_version().replace(',', '')
|
||||
else:
|
||||
from .linux.operations import * # @UnusedWildImport
|
||||
os_type = 'Linux'
|
||||
os_version = getLinuxVersion().replace(',', '')
|
|
@ -1,51 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 201 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
|
||||
# pylint: disable-msg=E1101,W0703
|
||||
|
||||
from opengnsys.log import logger
|
||||
|
||||
import threading
|
||||
import six
|
||||
|
||||
|
||||
class ScriptExecutorThread(threading.Thread):
|
||||
def __init__(self, script):
|
||||
super(ScriptExecutorThread, self).__init__()
|
||||
self.script = script
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
logger.debug('Executing script: {}'.format(self.script))
|
||||
six.exec_(self.script, globals(), None)
|
||||
except Exception as e:
|
||||
logger.error('Error executing script: {}'.format(e))
|
|
@ -1,249 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from .log import logger
|
||||
from .config import readConfig
|
||||
from .utils import exceptionToMessage
|
||||
|
||||
from . import ipc
|
||||
from . import httpserver
|
||||
from .loader import loadModules
|
||||
|
||||
import socket
|
||||
import time
|
||||
import json
|
||||
import six
|
||||
|
||||
IPC_PORT = 10398
|
||||
|
||||
|
||||
class CommonService(object):
|
||||
isAlive = True
|
||||
ipc = None
|
||||
httpServer = None
|
||||
modules = None
|
||||
|
||||
def __init__(self):
|
||||
logger.info('----------------------------------------')
|
||||
logger.info('Initializing OpenGnsys Agent')
|
||||
|
||||
# Read configuration file before proceding & ensures minimal config is there
|
||||
|
||||
self.config = readConfig()
|
||||
|
||||
# Get opengnsys section as dict
|
||||
cfg = dict(self.config.items('opengnsys'))
|
||||
|
||||
# Set up log level
|
||||
logger.setLevel(cfg.get('log', 'INFO'))
|
||||
|
||||
|
||||
logger.debug('Loaded configuration from opengnsys.cfg:')
|
||||
for section in self.config.sections():
|
||||
logger.debug('Section {} = {}'.format(section, self.config.items(section)))
|
||||
|
||||
|
||||
if logger.logger.isWindows():
|
||||
# Logs will also go to windows event log for services
|
||||
logger.logger.serviceLogger = True
|
||||
|
||||
self.address = (cfg.get('address', '0.0.0.0'), int(cfg.get('port', '10997')))
|
||||
self.ipcport = int(cfg.get('ipc_port', IPC_PORT))
|
||||
|
||||
self.timeout = int(cfg.get('timeout', '20'))
|
||||
|
||||
logger.debug('Socket timeout: {}'.format(self.timeout))
|
||||
socket.setdefaulttimeout(self.timeout)
|
||||
|
||||
# Now load modules
|
||||
self.modules = loadModules(self)
|
||||
logger.debug('Modules: {}'.format(list(v.name for v in self.modules)))
|
||||
|
||||
def stop(self):
|
||||
'''
|
||||
Requests service termination
|
||||
'''
|
||||
self.isAlive = False
|
||||
|
||||
# ********************************
|
||||
# * Internal messages processors *
|
||||
# ********************************
|
||||
def notifyLogin(self, username):
|
||||
for v in self.modules:
|
||||
try:
|
||||
logger.debug('Notifying login of user {} to module {}'.format(username, v.name))
|
||||
v.onLogin(username)
|
||||
except Exception as e:
|
||||
logger.error('Got exception {} processing login message on {}'.format(e, v.name))
|
||||
|
||||
def notifyLogout(self, username):
|
||||
for v in self.modules:
|
||||
try:
|
||||
logger.debug('Notifying logout of user {} to module {}'.format(username, v.name))
|
||||
v.onLogout(username)
|
||||
except Exception as e:
|
||||
logger.error('Got exception {} processing logout message on {}'.format(e, v.name))
|
||||
|
||||
def notifyMessage(self, data):
|
||||
module, message, data = data.split('\0')
|
||||
for v in self.modules:
|
||||
if v.name == module: # Case Sensitive!!!!
|
||||
try:
|
||||
logger.debug('Notifying message {} to module {} with json data {}'.format(message, v.name, data))
|
||||
v.processClientMessage(message, json.loads(data))
|
||||
return
|
||||
except Exception as e:
|
||||
logger.error('Got exception {} processing generic message on {}'.format(e, v.name))
|
||||
|
||||
logger.error('Module {} not found, messsage {} not sent'.format(module, message))
|
||||
|
||||
|
||||
def clientMessageProcessor(self, msg, data):
|
||||
'''
|
||||
Callback, invoked from IPC, on its own thread (not the main thread).
|
||||
This thread will "block" communication with agent untill finished, but this should be no problem
|
||||
'''
|
||||
logger.debug('Got message {}'.format(msg))
|
||||
|
||||
if msg == ipc.REQ_LOGIN:
|
||||
self.notifyLogin(data)
|
||||
elif msg == ipc.REQ_LOGOUT:
|
||||
self.notifyLogout(data)
|
||||
elif msg == ipc.REQ_MESSAGE:
|
||||
self.notifyMessage(data)
|
||||
|
||||
def initialize(self):
|
||||
# ******************************************
|
||||
# * Initialize listeners, modules, etc...
|
||||
# ******************************************
|
||||
|
||||
if six.PY3 is False:
|
||||
import threading
|
||||
threading._DummyThread._Thread__stop = lambda x: 42
|
||||
|
||||
logger.debug('Starting IPC listener at {}'.format(IPC_PORT))
|
||||
self.ipc = ipc.ServerIPC(self.ipcport, clientMessageProcessor=self.clientMessageProcessor)
|
||||
self.ipc.start()
|
||||
|
||||
# And http threaded server
|
||||
self.httpServer = httpserver.HTTPServerThread(self.address, self)
|
||||
self.httpServer.start()
|
||||
|
||||
# And lastly invoke modules activation
|
||||
validMods = []
|
||||
for mod in self.modules:
|
||||
try:
|
||||
logger.debug('Activating module {}'.format(mod.name))
|
||||
mod.activate()
|
||||
validMods.append(mod)
|
||||
except Exception as e:
|
||||
logger.exception()
|
||||
logger.error("Activation of {} failed: {}".format(mod.name, exceptionToMessage(e)))
|
||||
|
||||
self.modules[:] = validMods # copy instead of assignment
|
||||
|
||||
logger.debug('Modules after activation: {}'.format(list(v.name for v in self.modules)))
|
||||
|
||||
def terminate(self):
|
||||
# First invoke deactivate on modules
|
||||
for mod in reversed(self.modules):
|
||||
try:
|
||||
logger.debug('Deactivating module {}'.format(mod.name))
|
||||
mod.deactivate()
|
||||
except Exception as e:
|
||||
logger.exception()
|
||||
logger.error("Deactivation of {} failed: {}".format(mod.name, exceptionToMessage(e)))
|
||||
|
||||
# Remove IPC threads
|
||||
if self.ipc is not None:
|
||||
try:
|
||||
self.ipc.stop()
|
||||
except Exception:
|
||||
logger.error('Couln\'t stop ipc server')
|
||||
|
||||
if self.httpServer is not None:
|
||||
try:
|
||||
self.httpServer.stop()
|
||||
except Exception:
|
||||
logger.error('Couln\'t stop RESTApi server')
|
||||
|
||||
self.notifyStop()
|
||||
|
||||
# ****************************************
|
||||
# Methods that CAN BE overridden by agents
|
||||
# ****************************************
|
||||
def doWait(self, miliseconds):
|
||||
'''
|
||||
Invoked to wait a bit
|
||||
CAN be OVERRIDDEN
|
||||
'''
|
||||
time.sleep(float(miliseconds) / 1000)
|
||||
|
||||
def notifyStop(self):
|
||||
'''
|
||||
Overridden to log stop
|
||||
'''
|
||||
logger.info('Service is being stopped')
|
||||
|
||||
# ***************************************************
|
||||
# * Helpers, convenient methods to facilitate comms *
|
||||
# ***************************************************
|
||||
def sendClientMessage(self, toModule, message, data):
|
||||
'''
|
||||
Sends a message to the clients using IPC
|
||||
The data is converted to json, so ensure that it is serializable.
|
||||
All IPC is asynchronous, so if you expect a response, this will be sent by client using another message
|
||||
|
||||
@param toModule: Module that will receive this message
|
||||
@param message: Message to send
|
||||
@param data: data to send
|
||||
'''
|
||||
self.ipc.sendMessageMessage('\0'.join((toModule, message, json.dumps(data))))
|
||||
|
||||
def sendScriptMessage(self, script):
|
||||
'''
|
||||
Sends an script to be executed by client
|
||||
'''
|
||||
self.ipc.sendScriptMessage(script)
|
||||
|
||||
def sendLogoffMessage(self):
|
||||
'''
|
||||
Sends a logoff message to client
|
||||
'''
|
||||
self.ipc.sendLoggofMessage()
|
||||
|
||||
def sendPopupMessage(self, title, message):
|
||||
'''
|
||||
Sends a poup box to be displayed by client
|
||||
'''
|
||||
self.ipc.sendPopupMessage(title, message)
|
|
@ -1,72 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import sys
|
||||
import six
|
||||
|
||||
if sys.platform == 'win32':
|
||||
_fromEncoding = 'windows-1250'
|
||||
else:
|
||||
_fromEncoding = 'utf-8'
|
||||
|
||||
|
||||
def toUnicode(msg):
|
||||
try:
|
||||
if not isinstance(msg, six.text_type):
|
||||
if isinstance(msg, six.binary_type):
|
||||
return msg.decode(_fromEncoding, 'ignore')
|
||||
return six.text_type(msg)
|
||||
else:
|
||||
return msg
|
||||
except Exception:
|
||||
try:
|
||||
return six.text_type(msg)
|
||||
except Exception:
|
||||
return ''
|
||||
|
||||
|
||||
def exceptionToMessage(e):
|
||||
msg = ''
|
||||
for arg in e.args:
|
||||
if isinstance(arg, Exception):
|
||||
msg = msg + exceptionToMessage(arg)
|
||||
else:
|
||||
msg = msg + toUnicode(arg) + '. '
|
||||
return msg
|
||||
|
||||
|
||||
class Bunch(dict):
|
||||
def __init__(self, **kw):
|
||||
dict.__init__(self, kw)
|
||||
self.__dict__ = self
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
# pylint: disable=unused-wildcard-import, wildcard-import
|
||||
|
||||
import win32serviceutil # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32service # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32security # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32net # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32event # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32com.client # @UnresolvedImport, @UnusedImport, pylint: disable=import-error
|
||||
import pythoncom # @UnresolvedImport, pylint: disable=import-error
|
||||
import servicemanager # @UnresolvedImport, pylint: disable=import-error
|
||||
import os
|
||||
|
||||
from opengnsys import operations
|
||||
from opengnsys.service import CommonService
|
||||
|
||||
from opengnsys.log import logger
|
||||
|
||||
class OGAgentSvc(win32serviceutil.ServiceFramework, CommonService):
|
||||
'''
|
||||
This class represents a Windows Service for managing Agent interactions
|
||||
with OpenGnsys Server
|
||||
'''
|
||||
_svc_name_ = "OGAgent"
|
||||
_svc_display_name_ = "OpenGnsys Agent Service"
|
||||
_svc_description_ = "OpenGnsys Agent for Operating Systems"
|
||||
# 'System Event Notification' is the SENS service
|
||||
_svc_deps_ = ['EventLog']
|
||||
|
||||
def __init__(self, args):
|
||||
win32serviceutil.ServiceFramework.__init__(self, args)
|
||||
CommonService.__init__(self)
|
||||
self.hWaitStop = win32event.CreateEvent(None, 1, 0, None)
|
||||
self._user = None
|
||||
|
||||
def SvcStop(self):
|
||||
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
|
||||
self.isAlive = False
|
||||
win32event.SetEvent(self.hWaitStop)
|
||||
|
||||
SvcShutdown = SvcStop
|
||||
|
||||
def notifyStop(self):
|
||||
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
|
||||
servicemanager.PYS_SERVICE_STOPPED,
|
||||
(self._svc_name_, ''))
|
||||
|
||||
def doWait(self, miliseconds):
|
||||
win32event.WaitForSingleObject(self.hWaitStop, miliseconds)
|
||||
|
||||
def SvcDoRun(self):
|
||||
'''
|
||||
Main service loop
|
||||
'''
|
||||
try:
|
||||
logger.debug('running SvcDoRun')
|
||||
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
|
||||
servicemanager.PYS_SERVICE_STARTED,
|
||||
(self._svc_name_, ''))
|
||||
|
||||
# call the CoInitialize to allow the registration to run in an other
|
||||
# thread
|
||||
logger.debug('Initializing com...')
|
||||
pythoncom.CoInitialize()
|
||||
|
||||
# Initialize remaining service data
|
||||
self.initialize()
|
||||
except Exception: # Any init exception wil be caught, service must be then restarted
|
||||
logger.exception()
|
||||
logger.debug('Exiting service with failure status')
|
||||
os._exit(-1) # pylint: disable=protected-access
|
||||
|
||||
# *********************
|
||||
# * Main Service loop *
|
||||
# *********************
|
||||
try:
|
||||
while self.isAlive:
|
||||
# Pumps & processes any waiting messages
|
||||
pythoncom.PumpWaitingMessages()
|
||||
win32event.WaitForSingleObject(self.hWaitStop, 1000)
|
||||
except Exception as e:
|
||||
logger.error('Caught exception on main loop: {}'.format(e))
|
||||
|
||||
logger.debug('Exited main loop, deregistering SENS')
|
||||
|
||||
self.terminate() # Ends IPC servers
|
||||
|
||||
self.notifyStop()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
win32serviceutil.HandleCommandLine(OGAgentSvc)
|
|
@ -1,39 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Change to application directory.
|
||||
os.chdir(os.path.dirname(sys.argv[0]))
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import servicemanager # @UnresolvedImport, pylint: disable=import-error
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
# Valid logging levels, from UDS Broker (uds.core.utils.log)
|
||||
OTHER, DEBUG, INFO, WARN, ERROR, FATAL = (10000 * (x + 1) for x in range(6))
|
||||
|
||||
|
||||
class LocalLogger(object):
|
||||
def __init__(self):
|
||||
# tempdir is different for "user application" and "service"
|
||||
# service wil get c:\windows\temp, while user will get c:\users\XXX\temp
|
||||
logging.basicConfig(
|
||||
filename=os.path.join(tempfile.gettempdir(), 'opengnsys.log'),
|
||||
filemode='a',
|
||||
format='%(levelname)s %(asctime)s %(message)s',
|
||||
level=logging.DEBUG
|
||||
)
|
||||
self.logger = logging.getLogger('opengnsys')
|
||||
self.serviceLogger = False
|
||||
|
||||
def log(self, level, message):
|
||||
# Debug messages are logged to a file
|
||||
# our loglevels are 10000 (other), 20000 (debug), ....
|
||||
# logging levels are 10 (debug), 20 (info)
|
||||
# OTHER = logging.NOTSET
|
||||
self.logger.log(level / 1000 - 10, message)
|
||||
|
||||
if level < INFO or self.serviceLogger is False: # Only information and above will be on event log
|
||||
return
|
||||
|
||||
if level < WARN: # Info
|
||||
servicemanager.LogInfoMsg(message)
|
||||
elif level < ERROR: # WARN
|
||||
servicemanager.LogWarningMsg(message)
|
||||
else: # Error & Fatal
|
||||
servicemanager.LogErrorMsg(message)
|
||||
|
||||
def isWindows(self):
|
||||
return True
|
||||
|
||||
def isLinux(self):
|
||||
return False
|
|
@ -1,269 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import os
|
||||
import locale
|
||||
import subprocess
|
||||
import ctypes
|
||||
from ctypes.wintypes import DWORD, LPCWSTR
|
||||
import win32com.client # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32net # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32security # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32api # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32con # @UnresolvedImport, pylint: disable=import-error
|
||||
|
||||
from opengnsys import utils
|
||||
from opengnsys.log import logger
|
||||
|
||||
|
||||
def getErrorMessage(res=0):
|
||||
msg = win32api.FormatMessage(res)
|
||||
return msg.decode('windows-1250', 'ignore')
|
||||
|
||||
|
||||
def getComputerName():
|
||||
return win32api.GetComputerNameEx(win32con.ComputerNamePhysicalDnsHostname)
|
||||
|
||||
|
||||
def getNetworkInfo():
|
||||
'''
|
||||
Obtains a list of network interfaces
|
||||
@return: A "generator" of elements, that are dict-as-object, with this elements:
|
||||
name: Name of the interface
|
||||
mac: mac of the interface
|
||||
ip: ip of the interface
|
||||
'''
|
||||
obj = win32com.client.Dispatch("WbemScripting.SWbemLocator")
|
||||
wmobj = obj.ConnectServer("localhost", "root\cimv2")
|
||||
adapters = wmobj.ExecQuery("Select * from Win32_NetworkAdapterConfiguration where IpEnabled=True")
|
||||
try:
|
||||
for obj in adapters:
|
||||
if obj.DefaultIPGateway is None: # Skip adapters without default router
|
||||
continue
|
||||
for ip in obj.IPAddress:
|
||||
if ':' in ip: # Is IPV6, skip this
|
||||
continue
|
||||
if ip is None or ip == '' or ip.startswith('169.254') or ip.startswith('0.'): # If single link ip, or no ip
|
||||
continue
|
||||
logger.debug('Net config found: {}=({}, {})'.format(obj.Caption, obj.MACAddress, ip))
|
||||
yield utils.Bunch(name=obj.Caption, mac=obj.MACAddress, ip=ip)
|
||||
except Exception:
|
||||
return
|
||||
|
||||
|
||||
def getDomainName():
|
||||
'''
|
||||
Will return the domain name if we belong a domain, else None
|
||||
(if part of a network group, will also return None)
|
||||
'''
|
||||
# Status:
|
||||
# 0 = Unknown
|
||||
# 1 = Unjoined
|
||||
# 2 = Workgroup
|
||||
# 3 = Domain
|
||||
domain, status = win32net.NetGetJoinInformation()
|
||||
if status != 3:
|
||||
domain = None
|
||||
|
||||
return domain
|
||||
|
||||
|
||||
def getWindowsVersion():
|
||||
'''
|
||||
Returns Windows version.
|
||||
'''
|
||||
import _winreg
|
||||
reg = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion')
|
||||
try:
|
||||
data = '{} {}'.format(_winreg.QueryValueEx(reg, 'ProductName')[0], _winreg.QueryValueEx(reg, 'ReleaseId')[0])
|
||||
except Exception:
|
||||
data = '{} {}'.format(_winreg.QueryValueEx(reg, 'ProductName')[0], _winreg.QueryValueEx(reg, 'CurrentBuildNumber')[0])
|
||||
reg.Close()
|
||||
return data
|
||||
|
||||
|
||||
EWX_LOGOFF = 0x00000000
|
||||
EWX_SHUTDOWN = 0x00000001
|
||||
EWX_REBOOT = 0x00000002
|
||||
EWX_FORCE = 0x00000004
|
||||
EWX_POWEROFF = 0x00000008
|
||||
EWX_FORCEIFHUNG = 0x00000010
|
||||
|
||||
|
||||
def reboot(flags=EWX_FORCEIFHUNG | EWX_REBOOT):
|
||||
hproc = win32api.GetCurrentProcess()
|
||||
htok = win32security.OpenProcessToken(hproc, win32security.TOKEN_ADJUST_PRIVILEGES | win32security.TOKEN_QUERY)
|
||||
privs = ((win32security.LookupPrivilegeValue(None, win32security.SE_SHUTDOWN_NAME), win32security.SE_PRIVILEGE_ENABLED),)
|
||||
win32security.AdjustTokenPrivileges(htok, 0, privs)
|
||||
win32api.ExitWindowsEx(flags, 0)
|
||||
|
||||
def poweroff(flags=0):
|
||||
'''
|
||||
Simple poweroff command.
|
||||
'''
|
||||
reboot(flags=EWX_FORCEIFHUNG | EWX_SHUTDOWN)
|
||||
|
||||
def logoff():
|
||||
win32api.ExitWindowsEx(EWX_LOGOFF)
|
||||
|
||||
|
||||
def renameComputer(newName):
|
||||
# Needs admin privileges to work
|
||||
if ctypes.windll.kernel32.SetComputerNameExW(DWORD(win32con.ComputerNamePhysicalDnsHostname), LPCWSTR(newName)) == 0: # @UndefinedVariable
|
||||
# win32api.FormatMessage -> returns error string
|
||||
# win32api.GetLastError -> returns error code
|
||||
# (just put this comment here to remember to log this when logger is available)
|
||||
error = getErrorMessage()
|
||||
computerName = win32api.GetComputerNameEx(win32con.ComputerNamePhysicalDnsHostname)
|
||||
raise Exception('Error renaming computer from {} to {}: {}'.format(computerName, newName, error))
|
||||
|
||||
|
||||
NETSETUP_JOIN_DOMAIN = 0x00000001
|
||||
NETSETUP_ACCT_CREATE = 0x00000002
|
||||
NETSETUP_ACCT_DELETE = 0x00000004
|
||||
NETSETUP_WIN9X_UPGRADE = 0x00000010
|
||||
NETSETUP_DOMAIN_JOIN_IF_JOINED = 0x00000020
|
||||
NETSETUP_JOIN_UNSECURE = 0x00000040
|
||||
NETSETUP_MACHINE_PWD_PASSED = 0x00000080
|
||||
NETSETUP_JOIN_WITH_NEW_NAME = 0x00000400
|
||||
NETSETUP_DEFER_SPN_SET = 0x1000000
|
||||
|
||||
|
||||
def joinDomain(domain, ou, account, password, executeInOneStep=False):
|
||||
'''
|
||||
Joins machine to a windows domain
|
||||
:param domain: Domain to join to
|
||||
:param ou: Ou that will hold machine
|
||||
:param account: Account used to join domain
|
||||
:param password: Password of account used to join domain
|
||||
:param executeInOneStep: If true, means that this machine has been renamed and wants to add NETSETUP_JOIN_WITH_NEW_NAME to request so we can do rename/join in one step.
|
||||
'''
|
||||
# If account do not have domain, include it
|
||||
if '@' not in account and '\\' not in account:
|
||||
if '.' in domain:
|
||||
account = account + '@' + domain
|
||||
else:
|
||||
account = domain + '\\' + account
|
||||
|
||||
# Do log
|
||||
flags = NETSETUP_ACCT_CREATE | NETSETUP_DOMAIN_JOIN_IF_JOINED | NETSETUP_JOIN_DOMAIN
|
||||
|
||||
if executeInOneStep:
|
||||
flags |= NETSETUP_JOIN_WITH_NEW_NAME
|
||||
|
||||
flags = DWORD(flags)
|
||||
|
||||
domain = LPCWSTR(domain)
|
||||
|
||||
# Must be in format "ou=.., ..., dc=...,"
|
||||
ou = LPCWSTR(ou) if ou is not None and ou != '' else None
|
||||
account = LPCWSTR(account)
|
||||
password = LPCWSTR(password)
|
||||
|
||||
res = ctypes.windll.netapi32.NetJoinDomain(None, domain, ou, account, password, flags)
|
||||
# Machine found in another ou, use it and warn this on log
|
||||
if res == 2224:
|
||||
flags = DWORD(NETSETUP_DOMAIN_JOIN_IF_JOINED | NETSETUP_JOIN_DOMAIN)
|
||||
res = ctypes.windll.netapi32.NetJoinDomain(None, domain, None, account, password, flags)
|
||||
if res != 0:
|
||||
# Log the error
|
||||
error = getErrorMessage(res)
|
||||
if res == 1355:
|
||||
error = "DC Is not reachable"
|
||||
print('{} {}'.format(res, error))
|
||||
raise Exception('Error joining domain {}, with credentials {}/*****{}: {}, {}'.format(domain.value, account.value, ', under OU {}'.format(ou.value) if ou.value is not None else '', res, error))
|
||||
|
||||
|
||||
def changeUserPassword(user, oldPassword, newPassword):
|
||||
computerName = LPCWSTR(getComputerName())
|
||||
user = LPCWSTR(user)
|
||||
oldPassword = LPCWSTR(oldPassword)
|
||||
newPassword = LPCWSTR(newPassword)
|
||||
|
||||
res = ctypes.windll.netapi32.NetUserChangePassword(computerName, user, oldPassword, newPassword)
|
||||
|
||||
if res != 0:
|
||||
# Log the error, and raise exception to parent
|
||||
error = getErrorMessage()
|
||||
raise Exception('Error changing password for user {}: {}'.format(user.value, error))
|
||||
|
||||
|
||||
class LASTINPUTINFO(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('cbSize', ctypes.c_uint),
|
||||
('dwTime', ctypes.c_uint),
|
||||
]
|
||||
|
||||
|
||||
def initIdleDuration(atLeastSeconds):
|
||||
'''
|
||||
In windows, there is no need to set screensaver
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
def getIdleDuration():
|
||||
lastInputInfo = LASTINPUTINFO()
|
||||
lastInputInfo.cbSize = ctypes.sizeof(lastInputInfo)
|
||||
ctypes.windll.user32.GetLastInputInfo(ctypes.byref(lastInputInfo))
|
||||
millis = ctypes.windll.kernel32.GetTickCount() - lastInputInfo.dwTime # @UndefinedVariable
|
||||
return millis / 1000.0
|
||||
|
||||
|
||||
def getCurrentUser():
|
||||
'''
|
||||
Returns current logged in username
|
||||
'''
|
||||
return os.environ['USERNAME']
|
||||
|
||||
|
||||
def getSessionLanguage():
|
||||
'''
|
||||
Returns the user's session language
|
||||
'''
|
||||
return locale.getdefaultlocale()[0]
|
||||
|
||||
|
||||
def showPopup(title, message):
|
||||
'''
|
||||
Displays a message box on user's session (during 1 min).
|
||||
'''
|
||||
return subprocess.call('mshta "javascript:var sh=new ActiveXObject(\'WScript.Shell\'); sh.Popup( \'{}\', 60, \'{}\', 64); close()"'.format(message.encode('unicode_escape'), title.encode('unicode_escape')), shell=True)
|
||||
|
||||
|
||||
def get_etc_path():
|
||||
"""
|
||||
:return:
|
||||
Returns etc directory path.
|
||||
"""
|
||||
return os.path.join('C:', os.sep, 'Windows', 'System32', 'drivers', 'etc')
|
|
@ -1,2 +0,0 @@
|
|||
from .server_worker import ServerWorker
|
||||
from .client_worker import ClientWorker
|
|
@ -1,114 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
# pylint: disable=unused-wildcard-import,wildcard-import
|
||||
from __future__ import unicode_literals
|
||||
|
||||
class ClientWorker(object):
|
||||
'''
|
||||
A ServerWorker is a server module that "works" for service
|
||||
Most method are invoked inside their own thread, except onActivation & onDeactivation.
|
||||
This two methods are invoked inside main service thread, take that into account when creating them
|
||||
|
||||
* You must provide a module name (override name on your class), so we can identify the module by a "valid" name.
|
||||
A valid name is like a valid python variable (do not use spaces, etc...)
|
||||
* The name of the module is used as REST message destination id:
|
||||
https://sampleserver:8888/[name]/....
|
||||
Remember that module names and REST path are case sensitive!!!
|
||||
|
||||
'''
|
||||
name = None
|
||||
service = None
|
||||
|
||||
def __init__(self, service):
|
||||
self.service = service
|
||||
|
||||
def activate(self):
|
||||
'''
|
||||
Convenient method to wrap onActivation, so we can include easyly custom common logic for activation in a future
|
||||
'''
|
||||
self.onActivation()
|
||||
|
||||
def deactivate(self):
|
||||
'''
|
||||
Convenient method to wrap onActivation, so we can include easyly custom common logic for deactivation in a future
|
||||
'''
|
||||
self.onDeactivation()
|
||||
|
||||
def processMessage(self, message, params):
|
||||
'''
|
||||
This method can be overriden to provide your own message proccessor, or better you can
|
||||
implement a method that is called "process_" + message and this default processMessage will invoke it
|
||||
* Example:
|
||||
We got a message from OGAgent "Mazinger", with json params
|
||||
module.processMessage("mazinger", jsonParams)
|
||||
|
||||
This method will process "mazinguer", and look for a "self" method that is called "process_mazinger", and invoke it this way:
|
||||
return self.process_mazinger(jsonParams)
|
||||
|
||||
The methods must return data that can be serialized to json (i.e. Ojects are not serializable to json, basic type are)
|
||||
'''
|
||||
try:
|
||||
operation = getattr(self, 'process_' + message)
|
||||
except Exception:
|
||||
raise Exception('Message processor for "{}" not found'.format(message))
|
||||
|
||||
return operation(params)
|
||||
|
||||
def onActivation(self):
|
||||
'''
|
||||
Invoked by Service for activation.
|
||||
This MUST be overridden by modules!
|
||||
This method is invoked inside main thread, so if it "hangs", complete service will hang
|
||||
This should be no problem, but be advised about this
|
||||
'''
|
||||
pass
|
||||
|
||||
def onDeactivation(self):
|
||||
'''
|
||||
Invoked by Service before unloading service
|
||||
This MUST be overridden by modules!
|
||||
This method is invoked inside main thread, so if it "hangs", complete service will hang
|
||||
This should be no problem, but be advised about this
|
||||
'''
|
||||
pass
|
||||
|
||||
# *************************************
|
||||
# * Helper, convenient helper methods *
|
||||
# *************************************
|
||||
def sendServerMessage(self, message, data):
|
||||
'''
|
||||
Sends a message to connected ipc clients
|
||||
By convenience, it uses the "current" moduel name as destination module name also.
|
||||
If you need to send a message to a different module, you can use self.service.sendClientMessage(module, message, data) instead
|
||||
og this helmer
|
||||
'''
|
||||
self.service.ipc.sendMessage(self.name, message, data)
|
||||
|
|
@ -1,186 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
# pylint: disable=unused-wildcard-import,wildcard-import
|
||||
from __future__ import unicode_literals
|
||||
|
||||
class ServerWorker(object):
|
||||
'''
|
||||
A ServerWorker is a server module that "works" for service
|
||||
Most method are invoked inside their own thread, except onActivation & onDeactivation.
|
||||
This two methods are invoked inside main service thread, take that into account when creating them
|
||||
|
||||
* You must provide a module name (override name on your class), so we can identify the module by a "valid" name.
|
||||
A valid name is like a valid python variable (do not use spaces, etc...)
|
||||
* The name of the module is used as REST message destination id:
|
||||
https://sampleserver:8888/[name]/....
|
||||
Remember that module names and REST path are case sensitive!!!
|
||||
|
||||
'''
|
||||
name = None
|
||||
service = None
|
||||
locked = False
|
||||
|
||||
def __init__(self, service):
|
||||
self.service = service
|
||||
|
||||
def activate(self):
|
||||
'''
|
||||
Convenient method to wrap onActivation, so we can include easyly custom common logic for activation in a future
|
||||
'''
|
||||
self.onActivation()
|
||||
|
||||
def deactivate(self):
|
||||
'''
|
||||
Convenient method to wrap onActivation, so we can include easyly custom common logic for deactivation in a future
|
||||
'''
|
||||
self.onDeactivation()
|
||||
|
||||
def process(self, getParams, postParams, server):
|
||||
'''
|
||||
This method is invoked on a message received with an empty path (that means a message with only the module name, like in "http://example.com/Sample"
|
||||
Override it if you expect messages with that pattern
|
||||
|
||||
Overriden method must return data that can be serialized to json (i.e. Ojects are not serializable to json, basic type are)
|
||||
'''
|
||||
raise NotImplementedError('Generic message processor is not supported')
|
||||
|
||||
def processServerMessage(self, path, getParams, postParams, server):
|
||||
'''
|
||||
This method can be overriden to provide your own message proccessor, or better you can
|
||||
implement a method that is called exactly as "process_" + path[0] (module name has been removed from path array) and this default processMessage will invoke it
|
||||
* Example:
|
||||
Imagine this invocation url (no matter if GET or POST): http://example.com:9999/Sample/mazinger/Z
|
||||
The HTTP Server will remove "Sample" from path, parse arguments and invoke this method as this:
|
||||
module.processMessage(["mazinger","Z"], getParams, postParams)
|
||||
|
||||
This method will process "mazinguer", and look for a "self" method that is called "process_mazinger", and invoke it this way:
|
||||
return self.process_mazinger(["Z"], getParams, postParams)
|
||||
|
||||
In the case path is empty (that is, the path is composed only by the module name, like in "http://example.com/Sample", the "process" method
|
||||
will be invoked directly
|
||||
|
||||
The methods must return data that can be serialized to json (i.e. Ojects are not serializable to json, basic type are)
|
||||
'''
|
||||
if self.locked is True:
|
||||
raise Exception('system is busy')
|
||||
|
||||
if len(path) == 0:
|
||||
return self.process(getParams, postParams, server)
|
||||
try:
|
||||
operation = getattr(self, 'process_' + path[0])
|
||||
except Exception:
|
||||
raise Exception('Message processor for "{}" not found'.format(path[0]))
|
||||
|
||||
return operation(path[1:], getParams, postParams, server)
|
||||
|
||||
|
||||
def processClientMessage(self, message, data):
|
||||
'''
|
||||
Invoked by Service when a client message is received (A message from user space Agent)
|
||||
|
||||
This method can be overriden to provide your own message proccessor, or better you can
|
||||
implement a method that is called exactly "process_client_" + message (module name has been removed from path) and this default processMessage will invoke it
|
||||
* Example:
|
||||
We got a message from OGAgent "Mazinger", with json params
|
||||
module.processClientMessage("mazinger", jsonParams)
|
||||
|
||||
This method will process "mazinguer", and look for a "self" method that is called "process_client_mazinger", and invoke it this way:
|
||||
self.process_client_mazinger(jsonParams)
|
||||
|
||||
The methods returns nothing (client communications are done asynchronously)
|
||||
'''
|
||||
try:
|
||||
operation = getattr(self, 'process_client_' + message)
|
||||
except Exception:
|
||||
raise Exception('Message processor for "{}" not found'.format(message))
|
||||
|
||||
operation(data)
|
||||
|
||||
# raise NotImplementedError('Got a client message but no proccessor is implemented')
|
||||
|
||||
|
||||
def onActivation(self):
|
||||
'''
|
||||
Invoked by Service for activation.
|
||||
This MUST be overridden by modules!
|
||||
This method is invoked inside main thread, so if it "hangs", complete service will hang
|
||||
This should be no problem, but be advised about this
|
||||
'''
|
||||
pass
|
||||
|
||||
def onDeactivation(self):
|
||||
'''
|
||||
Invoked by Service before unloading service
|
||||
This MUST be overridden by modules!
|
||||
This method is invoked inside main thread, so if it "hangs", complete service will hang
|
||||
This should be no problem, but be advised about this
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
def onLogin(self, user):
|
||||
'''
|
||||
Invoked by Service when an user login is detected
|
||||
This CAN be overridden by modules
|
||||
This method is invoked whenever the client (user space agent) notifies the server (Service) that a user has logged in.
|
||||
This method is run on its own thread
|
||||
'''
|
||||
pass
|
||||
|
||||
def onLogout(self, user):
|
||||
'''
|
||||
Invoked by Service when an user login is detected
|
||||
This CAN be overridden by modules
|
||||
This method is invoked whenever the client (user space agent) notifies the server (Service) that a user has logged in.
|
||||
This method is run on its own thread
|
||||
'''
|
||||
pass
|
||||
|
||||
# *************************************
|
||||
# * Helper, convenient helper methods *
|
||||
# *************************************
|
||||
def sendClientMessage(self, message, data):
|
||||
'''
|
||||
Sends a message to connected ipc clients
|
||||
By convenience, it uses the "current" moduel name as destination module name also.
|
||||
If you need to send a message to a different module, you can use self.service.sendClientMessage(module, message, data) instead
|
||||
og this helmer
|
||||
'''
|
||||
self.service.sendClientMessage(self.name, message, data)
|
||||
|
||||
def sendScriptMessage(self, script):
|
||||
self.service.sendScriptMessage(script)
|
||||
|
||||
def sendLogoffMessage(self):
|
||||
self.service.sendLogoffMessage()
|
||||
|
||||
def sendPopupMessage(self):
|
||||
self.service.sendPopupMessage()
|
Binary file not shown.
|
@ -1,26 +0,0 @@
|
|||
Format-Specification: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?op=file&rev=135
|
||||
Name: ogagent
|
||||
Maintainer: Ramón M. Gómez
|
||||
Source: https://opengnsys.es
|
||||
|
||||
Copyright: 2014 Virtual Cable S.L.U.
|
||||
License: BSD-3-clause
|
||||
|
||||
License: GPL-2+
|
||||
This program 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.
|
||||
.
|
||||
This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
.
|
||||
On Debian systems, the full text of the GNU General Public
|
||||
License version 2 can be found in the file
|
||||
`/usr/share/common-licenses/GPL-2'.
|
|
@ -1,3 +0,0 @@
|
|||
OGAgent is the agent intended for OpengGnsys interaction.
|
||||
|
||||
Please, visit https://opengnsys.es for more information
|
|
@ -1,203 +0,0 @@
|
|||
// ********************************************************************************************************
|
||||
// Nombre del fichero: Database.cpp
|
||||
// Autor: José Manuel Alonso (E.T.S.I.I.) Universidad de Sevilla
|
||||
// Fecha Creación: Marzo-2010
|
||||
// Fecha Última modificación: Marzo-2010
|
||||
// Descripción:
|
||||
// Fichero de implementación de la clase Database para funciones de manipulación
|
||||
// de bases de datos sobre un Servidor Mysql
|
||||
// ********************************************************************************************************
|
||||
#include "Database.h"
|
||||
// __________________________________________________________________________
|
||||
void ErrorHandler(Herror hr, char* ErrStr)
|
||||
{
|
||||
sprintf(ErrStr,"Error:\n");
|
||||
sprintf(ErrStr,"%sCode = %d\n",ErrStr ,hr.nError);
|
||||
sprintf(ErrStr,"%sDescription = %s",ErrStr, (char*) hr.dError);
|
||||
}
|
||||
// __________________________________________________________________________
|
||||
Database::Database()
|
||||
{
|
||||
m_Cnn=NULL;
|
||||
sprintf(m_ErrStr,"NULL POINTER");
|
||||
}
|
||||
// __________________________________________________________________________
|
||||
void Database::GetErrorErrStr(char* ErrStr)
|
||||
{
|
||||
sprintf(ErrStr,"%s",m_ErrStr);
|
||||
}
|
||||
// __________________________________________________________________________
|
||||
void Table::GetErrorErrStr(char* ErrStr)
|
||||
{
|
||||
sprintf(ErrStr,"%s",m_ErrStr);
|
||||
}
|
||||
// __________________________________________________________________________
|
||||
bool Database::Open(char* UserName, char* Pwd,char* server,char*Bd)
|
||||
{
|
||||
Herror hr;
|
||||
m_Cnn=mysql_init(NULL);
|
||||
if(m_Cnn==NULL){
|
||||
hr.nError=0;
|
||||
strcpy(hr.dError,"Error en la Creación del objeto MYSQL");
|
||||
ErrorHandler(hr,m_ErrStr);
|
||||
return(false); // Fallo de inicializaci<63>
|
||||
}
|
||||
|
||||
if(!mysql_real_connect(m_Cnn, server,UserName,Pwd,Bd, MYSQL_PORT,NULL,0)){
|
||||
mysql_error(m_Cnn);
|
||||
hr.nError=mysql_errno(m_Cnn);
|
||||
strcpy(hr.dError,mysql_error(m_Cnn));
|
||||
ErrorHandler(hr,m_ErrStr);
|
||||
return(false); // Fallo de conexi<78>
|
||||
}
|
||||
hr.nError=0;
|
||||
strcpy(hr.dError,"Success");
|
||||
ErrorHandler(hr,m_ErrStr);
|
||||
return (true);
|
||||
}
|
||||
// __________________________________________________________________________
|
||||
bool Database::Close()
|
||||
{
|
||||
mysql_close(m_Cnn);
|
||||
return(true);
|
||||
}
|
||||
// __________________________________________________________________________
|
||||
bool Database::Execute(char* CmdStr)
|
||||
{
|
||||
Herror hr;
|
||||
if (mysql_query(m_Cnn,CmdStr)){ // Ejecuta la consulta
|
||||
mysql_error(m_Cnn);
|
||||
hr.nError=mysql_errno(m_Cnn);
|
||||
strcpy(hr.dError,mysql_error(m_Cnn));
|
||||
ErrorHandler(hr,m_ErrStr);
|
||||
mysql_close(m_Cnn);
|
||||
return(false); // Fallo de conexión
|
||||
}
|
||||
hr.nError=0;
|
||||
strcpy(hr.dError,"Success");
|
||||
ErrorHandler(hr,m_ErrStr);
|
||||
return (true);
|
||||
}
|
||||
// __________________________________________________________________________
|
||||
bool Database::Execute(char* CmdStr, Table& Tbl)
|
||||
{
|
||||
Herror hr;
|
||||
if (mysql_query(m_Cnn,CmdStr)) { // Ejecuta la consulta
|
||||
mysql_error(m_Cnn);
|
||||
hr.nError=mysql_errno(m_Cnn);
|
||||
strcpy(hr.dError,mysql_error(m_Cnn));
|
||||
ErrorHandler(hr,m_ErrStr);
|
||||
mysql_close(m_Cnn);
|
||||
return(false); // Fallo de conexi<78>
|
||||
}
|
||||
|
||||
hr.nError=0;
|
||||
strcpy(hr.dError,"Success");
|
||||
ErrorHandler(hr,m_ErrStr);
|
||||
|
||||
Tbl.m_Rec = mysql_store_result(m_Cnn) ; // Toma el recordset
|
||||
if(Tbl.m_Rec){
|
||||
Tbl.row=mysql_fetch_row(Tbl.m_Rec);
|
||||
Tbl.fields = mysql_fetch_fields(Tbl.m_Rec);
|
||||
Tbl.num_fields = mysql_num_fields(Tbl.m_Rec);
|
||||
Tbl.numreg=mysql_num_rows(Tbl.m_Rec);
|
||||
Tbl.eof=Tbl.numreg==0; // Consulta vacia
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
// __________________________________________________________________________
|
||||
void Database::liberaResult (Table& Tbl) {
|
||||
//Free resources after mysql_store_result
|
||||
mysql_free_result(Tbl.m_Rec);
|
||||
}
|
||||
// __________________________________________________________________________
|
||||
Table::Table()
|
||||
{
|
||||
m_Rec=NULL;
|
||||
}
|
||||
// __________________________________________________________________________
|
||||
bool Table::ISEOF()
|
||||
{
|
||||
return(eof);
|
||||
}
|
||||
// __________________________________________________________________________
|
||||
bool Table::Get(const char* FieldName, char *FieldValue)
|
||||
{
|
||||
char * aux;
|
||||
aux=tomadato(FieldName);
|
||||
if(aux)
|
||||
strcpy(FieldValue,aux);
|
||||
else
|
||||
strcpy(FieldValue,"");
|
||||
return(true);
|
||||
}
|
||||
// __________________________________________________________________________
|
||||
bool Table::Get(const char* FieldName,int &FieldValue)
|
||||
{
|
||||
char *aux;
|
||||
aux=tomadato(FieldName);
|
||||
if(aux)
|
||||
FieldValue=atoi(aux);
|
||||
else
|
||||
FieldValue=0;
|
||||
return(true);
|
||||
}
|
||||
// __________________________________________________________________________
|
||||
bool Table::Get(const char* FieldName,char &FieldValue)
|
||||
{
|
||||
char *aux;
|
||||
aux=tomadato(FieldName);
|
||||
FieldValue=aux[0];
|
||||
return(true);
|
||||
}
|
||||
// __________________________________________________________________________
|
||||
char* Table::tomadato(const char* FieldName)
|
||||
{
|
||||
Herror hr;
|
||||
unsigned int i;
|
||||
|
||||
for(i = 0; i < num_fields; i++){
|
||||
if(strcmp((char*)fields[i].name,FieldName)==0){
|
||||
sprintf(m_ErrStr,"Success");
|
||||
return((char*)row[i]);
|
||||
}
|
||||
}
|
||||
hr.nError=-1;
|
||||
strcpy(hr.dError,"El nombre del campo no existe");
|
||||
ErrorHandler(hr,m_ErrStr);
|
||||
return(NULL); // No existe el nombre del campo en la tabla
|
||||
}
|
||||
// __________________________________________________________________________
|
||||
|
||||
bool Table::MoveNext()
|
||||
{
|
||||
eof=false;
|
||||
row=mysql_fetch_row(m_Rec);
|
||||
if(row==NULL){
|
||||
if(!mysql_eof(m_Rec))
|
||||
return(false); // Fallo de lectura
|
||||
else
|
||||
eof=true; // Fin de fichero
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
// __________________________________________________________________________
|
||||
bool Table::MoveFirst()
|
||||
{
|
||||
my_ulonglong auxnumreg;
|
||||
|
||||
auxnumreg=0;
|
||||
mysql_data_seek(m_Rec,auxnumreg);
|
||||
return (MoveNext());
|
||||
}
|
||||
// __________________________________________________________________________
|
||||
bool Table::MoveLast()
|
||||
{
|
||||
my_ulonglong auxnumreg;
|
||||
auxnumreg=numreg;
|
||||
auxnumreg--;
|
||||
if(auxnumreg<0) auxnumreg=0; // Principio de fichero
|
||||
mysql_data_seek(m_Rec,auxnumreg);
|
||||
return (MoveNext());
|
||||
return (true);
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
// ******************************************************************************************************
|
||||
// Aplicación HIDRA
|
||||
// Copyright 2004 Jos<6F>Manuel Alonso. Todos los derechos reservados.
|
||||
// Fichero: Database.h
|
||||
// Descripción:
|
||||
// Fichero de cabecera de la clase Database para implementar funciones de manipulaci<63>
|
||||
// de bases de datos sobre un Servidor Mysql
|
||||
// ******************************************************************************************************
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include </usr/include/mysql/mysql.h>
|
||||
// __________________________________________________________________________
|
||||
class Database;
|
||||
class Table;
|
||||
// __________________________________________________________________________
|
||||
class Database
|
||||
{
|
||||
public:
|
||||
MYSQL *m_Cnn;
|
||||
char m_ErrStr[500];
|
||||
Database();
|
||||
bool Open(char* UserName, char* Pwd,char* server,char*Database);
|
||||
bool OpenTbl(int Mode, char* CmdStr, Table& Tbl);
|
||||
bool Close(void);
|
||||
bool Execute(char* CmdStr);
|
||||
bool Execute(char* CmdStr, Table& Tbl);
|
||||
void liberaResult(Table& Tbl);
|
||||
void GetErrorErrStr(char* ErrStr);
|
||||
};
|
||||
// __________________________________________________________________________
|
||||
class Table{
|
||||
char* tomadato(const char* FieldName);
|
||||
public:
|
||||
bool eof,bof;
|
||||
MYSQL_RES * m_Rec ;
|
||||
MYSQL_FIELD *fields;
|
||||
unsigned int num_fields;
|
||||
MYSQL_ROW row ;
|
||||
MYSQL_ROW_OFFSET ptr;
|
||||
my_ulonglong numreg;
|
||||
char m_ErrStr[500];
|
||||
Table();
|
||||
void GetErrorErrStr(char* ErrStr);
|
||||
bool ISEOF();
|
||||
bool MoveNext();
|
||||
bool MovePrevious();
|
||||
bool MoveFirst();
|
||||
bool MoveLast();
|
||||
|
||||
bool Get(const char* FieldName, char* FieldValue);
|
||||
bool Get(const char* FieldName,int &FieldValue);
|
||||
bool Get(const char* FieldName,char &FieldValue);
|
||||
};
|
||||
// __________________________________________________________________________
|
||||
class Herror
|
||||
{
|
||||
public:
|
||||
int nError; // C<>igo del error
|
||||
char dError[500]; // Descripción del error
|
||||
};
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -1,319 +0,0 @@
|
|||
// **************************************************************************************************************************************************
|
||||
// Libreria: ogAdmLib
|
||||
// Autor: José Manuel Alonso (E.T.S.I.I.) Universidad de Sevilla
|
||||
// Fecha Creación: Marzo-2010
|
||||
// Fecha Última modificación: Marzo-2010
|
||||
// Nombre del fichero: ogAdmLib.h
|
||||
// Descripción: Este fichero implementa el archivo de cabecera de la libreria ogAdmLib
|
||||
// **************************************************************************************************************************************************
|
||||
// ________________________________________________________________________________________________________
|
||||
// Valores definidos
|
||||
// ________________________________________________________________________________________________________
|
||||
#define LONSTD 1024 // Longitud de memoria estandar
|
||||
#define LONINT 16 // Longitud de memoria estandar para un número entero
|
||||
#define LONFIL 1024 // Longitud de memoria estandar para nombres de archivo completos (incluido path)
|
||||
#define LONIP 16 // Longitud de memoria estandar para cadenas que contiene una dirección IP
|
||||
#define LONMAC 16 // Longitud de memoria estandar para cadenas que contiene una dirección MAC
|
||||
#define LONSQL 8192 // Longitud de memoria estandar para una sentencia SQL
|
||||
#define LONPRM 4098 // Longitud estandar de los parámetros del fichero de configuración del servicio
|
||||
#define LONSCP 4098 // Longitud estandar de los parámetros de las tramas
|
||||
#define LONFUN 512 // Longitud estandar de los nombres de las funciones que procesan las tramas
|
||||
#define LONSUC 4098 // Longitud de los mensajes de sucesos
|
||||
#define LONBLK 8192 // Longitud de los paquetes de tramas leidos cada vez
|
||||
#define MAXPRM 20 // Máximo número de parámeros del fichero de configuración del servicio
|
||||
#define MAXPAR 128 // Maximo numero de particiones manejadas por el sistema, ahora con GPT es 128
|
||||
#define MAXLONURL 1024 // Longitud máxima de una dirección url con parámetros
|
||||
|
||||
#define LONHEXPRM 5 // Longitud del campo que contiene el tamaño de la cadena de parámetros
|
||||
#define LONGITUD_CABECERATRAMA 16 // Longitud de la cabecera de las tramas
|
||||
#define LONGITUD_PARAMETROS 8192 // Longitud estandar de la información de la trama (parámetros)
|
||||
#define MAXCMD_PARAMETROS 200 // Máximo número de parámetros de una trama
|
||||
|
||||
#define MAXIMOS_CLIENTES 4000 // Máximo número de conexiones con ordenadores clientes
|
||||
#define MAXIMAS_FUNCIONES LONSTD // Máximo número de funciones que procesan los mensajes entre servicio y clientes
|
||||
#define MAXIMAS_LINEAS 3000 // Longitud máxima de lineas en un archivo de comandos
|
||||
|
||||
#define AUTOINCORPORACION_OFF 0x0000 // Los ordenadores no se pueden dar de alta automáticamente
|
||||
#define AUTOINCORPORACION_ONA 0x0001 // Los ordenadores se pueden dar de alta automáticamente si existe el aula
|
||||
#define AUTOINCORPORACION_ONX 0x0002 // Los ordenadores se pueden dar de alta automáticamentee y si no existe el aula la crea
|
||||
|
||||
#define DEBUG_BAJO 1 // Nivel de debug bajo
|
||||
#define DEBUG_MEDIO 2 // Nivel de debug medio
|
||||
#define DEBUG_ALTO 3 // Nivel de debug alto
|
||||
#define DEBUG_MAXIMO 4 // Nivel de debug máximo
|
||||
|
||||
#define CLIENTE_OCUPADO "BSY" // Cliente ocupado
|
||||
#define CLIENTE_APAGADO "OFF" // Cliente apagado
|
||||
#define CLIENTE_INICIANDO "INI" // Cliente iniciando
|
||||
|
||||
#define CLIENTE_OPENGNSYS "OPG" // Cliente Opengnsys
|
||||
|
||||
#define CLIENTE_WIN "WIN" // Cliente Windows genérico
|
||||
#define CLIENTE_WNT "WNT" // Windows NT
|
||||
#define CLIENTE_W2K "W2K" // Windows 2000
|
||||
#define CLIENTE_WS2 "WS2" // Windows Server 2003
|
||||
#define CLIENTE_WXP "WXP" // Cliente Windows XP
|
||||
#define CLIENTE_W95 "W95" // Windows 95
|
||||
#define CLIENTE_W98 "W98" // Windows 98
|
||||
#define CLIENTE_WML "WML" // Windows Milenium
|
||||
#define CLIENTE_MS2 "MS2" // MsDos
|
||||
#define CLIENTE_WVI "WVI" // Cliente Windows Vista
|
||||
#define CLIENTE_WI7 "WI7" // Cliente Windows 7
|
||||
|
||||
#define CLIENTE_LNX "LNX" // Cliente Linux
|
||||
|
||||
#define ACCION_SINRESULTADO 0 // Sin resultado
|
||||
#define ACCION_EXITOSA 1 // Finalizada con éxito
|
||||
#define ACCION_FALLIDA 2 // Finalizada con errores
|
||||
|
||||
#define ACCION_INICIADA 1 // Acción activa
|
||||
#define ACCION_DETENIDA 2 // Acción momentanemente parada
|
||||
#define ACCION_FINALIZADA 3 // Accion finalizada
|
||||
|
||||
#define EJECUCION_COMANDO 1
|
||||
#define EJECUCION_PROCEDIMIENTO 2
|
||||
#define EJECUCION_TAREA 3
|
||||
#define EJECUCION_RESERVA 4
|
||||
|
||||
#define AMBITO_CENTROS 0x01
|
||||
#define AMBITO_GRUPOSAULAS 0x02
|
||||
#define AMBITO_AULAS 0x04
|
||||
#define AMBITO_GRUPOSORDENADORES 0x08
|
||||
#define AMBITO_ORDENADORES 0x10
|
||||
|
||||
// Código de los tipos de mensajes
|
||||
#define MSG_COMANDO '1' // Mensaje del tipo comando
|
||||
#define MSG_NOTIFICACION '2' // Respuesta a la ejecución un comando
|
||||
#define MSG_PETICION '3' // Petición de cualquier actuación
|
||||
#define MSG_RESPUESTA '4' // Respuesta a una petición
|
||||
#define MSG_INFORMACION '5' // Envío de cualquier información sin espera de confirmación o respuesta
|
||||
|
||||
#define ANNOREF 2009 // Año de referencia base
|
||||
|
||||
#define LONGITUD_SCRIPTSALIDA 131072 // Longitud máxima de la información devuelta por una función de interface
|
||||
#define MAXARGS 16 // Número máximo de argumentos enviados a un scripts
|
||||
#define MAXCNX 5 // Máximos intentos de conexión al servidor de Administración
|
||||
|
||||
#define PUERTO_WAKEUP 9 // Puerto wake up
|
||||
|
||||
#define MAXHARDWARE 128 // Máximos elementos hardware a detectar
|
||||
#define MAXSOFTWARE 8096 // Máximos elementos software a detectar
|
||||
// ________________________________________________________________________________________________________
|
||||
// Tipos definidos
|
||||
// ________________________________________________________________________________________________________
|
||||
typedef unsigned long DWORD;
|
||||
typedef unsigned short WORD;
|
||||
typedef int BOOLEAN;
|
||||
typedef char BYTE;
|
||||
typedef int SOCKET;
|
||||
typedef void* LPVOID;
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define SOCKET_ERROR (-1)
|
||||
#define INVALID_SOCKET (SOCKET)(~0)
|
||||
|
||||
#define LEER 0
|
||||
#define ESCRIBIR 1
|
||||
|
||||
#define CHARNULL '\0'
|
||||
|
||||
// ________________________________________________________________________________________________________
|
||||
// Variables globales
|
||||
// ________________________________________________________________________________________________________
|
||||
char szPathFileCfg[LONSTD],szPathFileLog[LONSTD];
|
||||
int ndebug; // Nivel de debuger
|
||||
|
||||
typedef struct{ // Estructura de las tramas
|
||||
char arroba; // Caracter arroba siempre
|
||||
char identificador[14]; // Identificador de la trama, siempre JMMLCAMDJ_MCDJ
|
||||
char tipo; // Tipo de mensaje
|
||||
long lonprm; // Longitud en hexadecimal de los parámetros
|
||||
char *parametros; // Parámetros de la trama
|
||||
}TRAMA;
|
||||
// ________________________________________________________________________________________________________
|
||||
// Tabla de errores
|
||||
// ________________________________________________________________________________________________________
|
||||
const char* tbErrores[]={"Se han generado errores. No se puede continuar la ejecución de este módulo",\
|
||||
"001-El nombre del fichero de configuración del programa está vacío",\
|
||||
"002-No existe fichero de configuración del programa",\
|
||||
"003-No hay memoria suficiente para el buffer",\
|
||||
"004-Error en el fichero de configuración del programa. No se ha definido el parámetro SERVIDORADM",\
|
||||
"005-Error en el fichero de configuración del programa. No se ha definido el parámetro PUERTO",\
|
||||
"006-Error en el fichero de configuración del programa. No se ha definido el parámetro USUARIO",\
|
||||
"007-Error en el fichero de configuración del programa. No se ha definido el parámetro PASSWORD",\
|
||||
"008-Error en el fichero de configuración del programa. No se ha definido el parámetro DATASOURCE",\
|
||||
"009-Error en el fichero de configuración del programa. No se ha definido el parámetro CATALOG",\
|
||||
"010-Error en los parámetros de ejecución del programa. Debe especificar el fichero de configuración",\
|
||||
"011-Error en los parámetros de ejecución del programa. Debe especificar el fichero de log",\
|
||||
"012-Error de sintaxis en los parámetros de ejecución del programa: Debe especificar -f nombre_del_fichero_de_configuración_del_programa -l nombre_del_fichero_de_log_del_programa -d nivel de debug",\
|
||||
"013-Error al crear socket ***socket() fallo",\
|
||||
"014-Error al enlazar socket al interface ***bind() fallo",\
|
||||
"015-Error al acceptar conexión de clientes ***accept() fallo",\
|
||||
"016-Error al crear hebra de cliente en módulo main()",\
|
||||
"017-Error al recibir trama ***recv() fallo",\
|
||||
"018-No se reconoce el mensaje enviado",\
|
||||
"019-Trama recibida NO válida",\
|
||||
"020-No se puede establecer conexión con la base de datos",\
|
||||
"021-No se han podido recuperar los datos de la consulta o bien insertar, modificar o eliminar datos",\
|
||||
"022-El cliente no se ha sido dado de alta en la base de datos del sistema. Se rechaza su petición de inclusión",\
|
||||
"023-Ha habido algún problema en la incorporación automática del cliente",\
|
||||
"024-Ha habido algún problema en la actualización de la configuración del cliente",\
|
||||
"025-La tabla de clientes está llena, no pueden registrarse más clientes en el sistema",\
|
||||
"026-Error al enviar trama ***send() fallo",\
|
||||
"027-No se encuentra Repositorio del cliente",\
|
||||
"028-Ha ocurrido algún error al tomar las particiones",\
|
||||
"029-Ha ocurrido algún problema en el proceso de inclusión del cliente. Se rechaza su petición",\
|
||||
"030-Ha ocurrido algún problema en el proceso de respuesta al comando",\
|
||||
"031-No se ha encontrado la acción a notificar es posible que se haya eliminado el registro",\
|
||||
"032-Ha ocurrido algún problema en el envío del comando",\
|
||||
"033-Error en el fichero de configuración del programa. No se ha definido el parámetro PATHSCRIPTS",\
|
||||
"034-Error en el fichero de configuración del programa. No se ha definido el parámetro URLMENU",\
|
||||
"035-Error en el fichero de configuración del programa. No se ha definido el parámetro URLMSG",\
|
||||
"036-No se ha podido recuperar la configuración de las particiones del disco",\
|
||||
"037-Ha ocurrido algún problema en el proceso de inclusión del cliente",\
|
||||
"038-No se ha podido establecer conexión con el Servidor de Administración",\
|
||||
"039-Ha ocurrido algún problema al procesar la trama recibida",\
|
||||
"040-Se han recibido parámetros con valores no válidos",\
|
||||
"041-Ha ocurrido algún problema en el proceso de inclusión del cliente",\
|
||||
"042-Ha ocurrido algún problema al enviar una petición de comandos o tareas pendientes al Servidor de Administración",\
|
||||
"043-Ha ocurrido algún problema al enviar una petición de comandos interactivos al Servidor de Administración",\
|
||||
"044-Ha ocurrido algún problema al enviar una respuesta de comandos al servidor",\
|
||||
"045-Ha ocurrido algún problema al recibir una petición de comandos o tareas pendientes desde el Servidor de Administración",\
|
||||
"046-Ha ocurrido algún problema al recibir un comando interactivo desde el Servidor de Administración",\
|
||||
"047-El cliente no está registrado en la tabla de sockest del sistema",\
|
||||
"048-Error al configurar opción BROADCAST para socket: setsockopt(SO_BROADCAST)",\
|
||||
"049-Error al enviar trama magic packet",\
|
||||
"050-Ha ocurrido algún problema al enviar un fichero por la red",\
|
||||
"051-Error en el fichero de configuración del programa. No se ha definido el parámetro PATHLOGFIL",\
|
||||
"052-No se puede crear archivo temporal para ejecución de Comandos",\
|
||||
"053-Ha ocurrido algún problema al procesar el Inventario Hardware del cliente",\
|
||||
"054-Existe un tipo de hardware que no está registrado",\
|
||||
"055-Ha ocurrido algún problema al actualizar el hardware del cliente",\
|
||||
"056-Error en el fichero de configuración del programa. No se ha definido el parámetro PATHINTERFACE",\
|
||||
"057-Ha ocurrido algún problema al enviar un archivo por la red",\
|
||||
"058-Ha ocurrido algún problema al recibir un archivo por la red",\
|
||||
"059-Error al crear la hebra DHCP o BOOTP",\
|
||||
"060-Error al crear la hebra TFTP",\
|
||||
"061-Error al crear socket para servicio DHCP",\
|
||||
"062-Error al enlazar socket con interface para servicio DHCP",\
|
||||
"063-No hay puertos libres para la hebra del servicio",\
|
||||
"064-Error al crear estructura de control para protocolo DHCP",\
|
||||
"065-Error al recibir mensaje DHCP. Se para el servicio",\
|
||||
"066-Error al crear la hebra cliente DHCP",\
|
||||
"067-Error al crear socket para servicio BOOTP",\
|
||||
"068-Error al enlazar socket con interface para servicio BOOTP",\
|
||||
"069-Error al crear estructura de control para protocolo BOOTP",\
|
||||
"070-Error al recibir mensaje BOOTP. Se para el servicio",\
|
||||
"071-Error al crear la hebra cliente BOOTP",\
|
||||
"072-Error al crear socket para servicio TFTP",\
|
||||
"073-Error al enlazar socket con interface para servicio TFTP",\
|
||||
"074-Error al crear estructura de control para protocolo TFTP",\
|
||||
"075-Error al recibir mensaje TFTP. Se para el servicio",\
|
||||
"076-Error al crear la hebra cliente TFTP",\
|
||||
"077-No se encontró opción DHCP",\
|
||||
"078-ERROR TFTP",\
|
||||
"079-Error al recibir mensaje TFTP en hebra cliente",\
|
||||
"080-Error al recibir mensaje DHCP",\
|
||||
"081-Error al crear socket de usuario para hebra",\
|
||||
"082-Ha ocurrido algún problema al procesar el Inventario software del cliente",\
|
||||
"083-Ha ocurrido algún problema al actualizar el software del cliente",\
|
||||
"084-Ha ocurrido algún problema al reiniciar la sesión del cliente",\
|
||||
"085-No se ha podido recuperar la dirección IP del cliente",\
|
||||
"086-Error al ejecutar el comando",\
|
||||
"087-Error al leer o escribir el contenido del archivo de eco de consola remota",\
|
||||
"088-Ha habido algún problerma al procesar la caché",\
|
||||
"089-Error en el fichero de configuración del programa. No se ha definido el parámetro URLMENU",\
|
||||
"090-Error en el fichero de configuración del programa. No se ha definido el parámetro URLMSG",\
|
||||
"091-Ha habido algún problema al enviar un mensaje de tipo petición al Servidor",\
|
||||
"092-Error en el fichero de configuración del programa. No se ha definido el parámetro IPLOCAL",\
|
||||
"093-No se puede cargar la librería Windows para trabajar con sockets",\
|
||||
"094-Ha habido algún problerma al procesar la actualización después de crear una imagen",\
|
||||
"095-Ha habido algún problerma al procesar la actualización después de restaurar una imagen",\
|
||||
"096-Ha habido algún problerma al procesar la actualización después de crear un software incremental",\
|
||||
"097-Este fichero de log está obsoleto, este proceso usa ahora syslog para gestionar los mensajes de log",\
|
||||
};
|
||||
// ________________________________________________________________________________________________________
|
||||
// Tabla de mensajes
|
||||
// ________________________________________________________________________________________________________
|
||||
const char* tbMensajes[]={"",\
|
||||
"001-Inicio de sesion",\
|
||||
"002-Petición de inclusión de cliente",\
|
||||
"003-Abriendo sesión en el servidor de Administración",\
|
||||
"004-Cliente iniciado",\
|
||||
"005-Ejecución de archivo Autoexec",\
|
||||
"006-Procesa comandos pendientes",\
|
||||
"007-Acciones pendientes procesadas",\
|
||||
"008-Ejecución del script",\
|
||||
"009-Parámetro del script",\
|
||||
"010-Ha ocurrido algún error en la creación del proceso hijo",\
|
||||
"011-Aviso: La información de salida del script excede de la longitud permitida. Puede haberse truncado",\
|
||||
"012-Información devuelta por el script",\
|
||||
"013-Estatus de finalización del script",\
|
||||
"014-Configuración de particiones",\
|
||||
"015-Enviando petición de inclusión en el sistema al Servidor de Administración",\
|
||||
"016-Recibiendo respuesta de inclusión desde el Servidor de Administración",\
|
||||
"017-Enviando petición de comandos o tareas pendientes al Servidor de Administración",\
|
||||
"018-Recibiendo respuesta de comandos o tareas pendientes desde el Servidor de Administración",\
|
||||
"019-Disponibilidad de comandos activada",\
|
||||
"020-Disponibilidad de comandos desactivada",\
|
||||
"021-Ejecución de comando",\
|
||||
"022-Sin eco",\
|
||||
"023-Procesando caché",\
|
||||
"024-Repositorio iniciado",\
|
||||
|
||||
};
|
||||
// ________________________________________________________________________________________________________
|
||||
// Prototipo de funciones
|
||||
// ________________________________________________________________________________________________________
|
||||
struct tm * tomaHora();
|
||||
void registraLog(const char *,const char *,int );
|
||||
void errorLog(const char *,int ,int);
|
||||
#define og_log(err, swe) errorLog(__FUNCTION__, err, swe)
|
||||
void errorInfo(const char *,char *);
|
||||
#define og_info(err) errorInfo(__FUNCTION__, err)
|
||||
void infoLog(int);
|
||||
void infoDebug(char*);
|
||||
BOOLEAN validacionParametros(int,char**,int);
|
||||
char* reservaMemoria(int);
|
||||
char* ampliaMemoria(char*,int);
|
||||
void liberaMemoria(void*);
|
||||
BOOLEAN initParametros(TRAMA*,int);
|
||||
int splitCadena(char **,char *, char);
|
||||
void sustituir(char *,char ,char );
|
||||
char* StrToUpper(char *);
|
||||
char* StrToLower(char *);
|
||||
void INTROaFINCAD(TRAMA*);
|
||||
void FINCADaINTRO(TRAMA*);
|
||||
int cuentaIPES(char*);
|
||||
char *tomaParametro(const char*,TRAMA*);
|
||||
char *copiaParametro(const char*,TRAMA *);
|
||||
BOOLEAN contieneIP(char *,char *);
|
||||
char* rTrim(char *);
|
||||
SOCKET TCPConnect(char *,char *);
|
||||
SOCKET abreConexion(void);
|
||||
BOOLEAN enviaMensaje(SOCKET *,TRAMA *,char);
|
||||
TRAMA* recibeMensaje(SOCKET *);
|
||||
BOOLEAN mandaTrama(SOCKET*,TRAMA*);
|
||||
BOOLEAN sendData(SOCKET *, char* ,int );
|
||||
BOOLEAN enviaTrama(SOCKET *,TRAMA *);
|
||||
TRAMA* recibeTrama(SOCKET*);
|
||||
BOOLEAN recData(SOCKET *,char*,int,int*);
|
||||
BOOLEAN sendFlag(SOCKET *, char* ,int );
|
||||
BOOLEAN recibeFlag(SOCKET*,TRAMA*);
|
||||
char* URLEncode(char *);
|
||||
char* URLDecode(char *);
|
||||
char* leeArchivo(char*);
|
||||
int lonArchivo(char *);
|
||||
BOOLEAN escribeArchivo(char *,char*);
|
||||
BOOLEAN sendArchivo(SOCKET *,char *);
|
||||
BOOLEAN recArchivo(SOCKET *,char *);
|
||||
SOCKET TCPConnect(char *,char*);
|
||||
|
||||
#include <stddef.h> /* for offsetof. */
|
||||
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
||||
(type *)( (char *)__mptr - offsetof(type,member) );})
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
# makefile
|
||||
|
||||
# Nombre del proyecto
|
||||
PROYECTO := ogAdmAgent
|
||||
|
||||
# Directorio de instalación
|
||||
INSTALL_DIR := /opt/opengnsys
|
||||
|
||||
# Opciones de compilacion
|
||||
CFLAGS := $(shell mysql_config --cflags)
|
||||
CFLAGS += -g -Wall -I../../Includes
|
||||
CPPFLAGS := $(CFLAGS)
|
||||
|
||||
# Opciones de linkado
|
||||
LDFLAGS := -Wl,--no-as-needed $(shell mysql_config --libs) -lpthread
|
||||
|
||||
# Ficheros objetos
|
||||
OBJS := ../../Includes/Database.o sources/ogAdmAgent.o
|
||||
|
||||
|
||||
all: $(PROYECTO)
|
||||
|
||||
$(PROYECTO): $(OBJS)
|
||||
g++ $(LDFLAGS) $(OBJS) -o $(PROYECTO)
|
||||
|
||||
install: $(PROYECTO)
|
||||
cp $(PROYECTO) $(INSTALL_DIR)/sbin
|
||||
cp $(PROYECTO).cfg $(INSTALL_DIR)/etc
|
||||
|
||||
clean:
|
||||
rm -f $(PROYECTO) $(OBJS)
|
||||
|
||||
uninstall: clean
|
||||
rm -f /usr/local/sbin/$(PROYECTO) /usr/local/etc/$(PROYECTO).cfg
|
||||
|
||||
sources/%.o: sources/%.cpp
|
||||
g++ $(CPPFLAGS) -c -o"$@" "$<"
|
||||
|
||||
sources/%.o: sources/%.c
|
||||
gcc $(CFLAGS) -c -o"$@" "$<"
|
||||
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
ServidorAdm=SERVERIP
|
||||
PUERTO=2008
|
||||
USUARIO=DBUSER
|
||||
PASSWORD=DBPASSWORD
|
||||
datasource=localhost
|
||||
CATALOG=DATABASE
|
||||
|
|
@ -1,914 +0,0 @@
|
|||
// ********************************************************************************************************
|
||||
// Servicio: ogAdmAgent
|
||||
// Autor: José Manuel Alonso (E.T.S.I.I.) Universidad de Sevilla
|
||||
// Fecha Creación: Marzo-2010
|
||||
// Fecha Última modificación: Marzo-2010
|
||||
// Nombre del fichero: ogAdmAgent.cpp
|
||||
// Descripción: Este fichero implementa el servicio agente del sistema. Revisa a intervalos
|
||||
// regulares la base de datos para comprobar si existen acciones programadas.
|
||||
// ********************************************************************************************************
|
||||
#include "ogAdmAgent.h"
|
||||
#include "ogAdmLib.c"
|
||||
//________________________________________________________________________________________________________
|
||||
// Función: tomaConfiguracion
|
||||
//
|
||||
// Descripción:
|
||||
// Lee el fichero de configuración del servicio
|
||||
// Parámetros:
|
||||
// filecfg : Ruta completa al fichero de configuración
|
||||
// Devuelve:
|
||||
// TRUE: Si el proceso es correcto
|
||||
// FALSE: En caso de ocurrir algún error
|
||||
//________________________________________________________________________________________________________
|
||||
BOOLEAN tomaConfiguracion(char* filecfg)
|
||||
{
|
||||
char modulo[] = "tomaConfiguracion()";
|
||||
|
||||
if (filecfg == NULL || strlen(filecfg) == 0) {
|
||||
errorLog(modulo, 1, FALSE); // Fichero de configuración del servicio vacío
|
||||
return (FALSE);
|
||||
}
|
||||
FILE *fcfg;
|
||||
long lSize;
|
||||
char * buffer, *lineas[MAXPRM], *dualparametro[2];
|
||||
int i, numlin, resul;
|
||||
|
||||
fcfg = fopen(filecfg, "rt");
|
||||
if (fcfg == NULL) {
|
||||
errorLog(modulo, 2, FALSE); // No existe fichero de configuración del servicio
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
fseek(fcfg, 0, SEEK_END);
|
||||
lSize = ftell(fcfg); // Obtiene tamaño del fichero.
|
||||
rewind(fcfg);
|
||||
buffer = (char*) reservaMemoria(lSize + 1); // Toma memoria para el buffer de lectura.
|
||||
if (buffer == NULL) { // No hay memoria suficiente para el buffer
|
||||
errorLog(modulo, 3, FALSE);
|
||||
return (FALSE);
|
||||
}
|
||||
fread(buffer, 1, lSize, fcfg); // Lee contenido del fichero
|
||||
buffer[lSize] = (char) NULL;
|
||||
fclose(fcfg);
|
||||
|
||||
servidoradm[0] = (char) NULL; //inicializar variables globales
|
||||
puerto[0] = (char) NULL;
|
||||
usuario[0] = (char) NULL;
|
||||
pasguor[0] = (char) NULL;
|
||||
datasource[0] = (char) NULL;
|
||||
catalog[0] = (char) NULL;
|
||||
|
||||
numlin = splitCadena(lineas, buffer, '\n');
|
||||
for (i = 0; i < numlin; i++) {
|
||||
splitCadena(dualparametro, lineas[i], '=');
|
||||
resul = strcmp(StrToUpper(dualparametro[0]), "SERVIDORADM");
|
||||
if (resul == 0)
|
||||
strcpy(servidoradm, dualparametro[1]);
|
||||
resul = strcmp(StrToUpper(dualparametro[0]), "PUERTO");
|
||||
if (resul == 0)
|
||||
strcpy(puerto, dualparametro[1]);
|
||||
resul = strcmp(StrToUpper(dualparametro[0]), "USUARIO");
|
||||
if (resul == 0)
|
||||
strcpy(usuario, dualparametro[1]);
|
||||
resul = strcmp(StrToUpper(dualparametro[0]), "PASSWORD");
|
||||
if (resul == 0)
|
||||
strcpy(pasguor, dualparametro[1]);
|
||||
resul = strcmp(StrToUpper(dualparametro[0]), "DATASOURCE");
|
||||
if (resul == 0)
|
||||
strcpy(datasource, dualparametro[1]);
|
||||
resul = strcmp(StrToUpper(dualparametro[0]), "CATALOG");
|
||||
if (resul == 0)
|
||||
strcpy(catalog, dualparametro[1]);
|
||||
}
|
||||
if (servidoradm[0] == (char) NULL) {
|
||||
errorLog(modulo, 4, FALSE); // Falta parámetro SERVIDORADM
|
||||
return (FALSE);
|
||||
}
|
||||
if (puerto[0] == (char) NULL) {
|
||||
errorLog(modulo, 5, FALSE); // Falta parámetro PUERTO
|
||||
return (FALSE);
|
||||
}
|
||||
if (usuario[0] == (char) NULL) {
|
||||
errorLog(modulo, 6, FALSE); // Falta parámetro USUARIO
|
||||
return (FALSE);
|
||||
}
|
||||
if (pasguor[0] == (char) NULL) {
|
||||
errorLog(modulo, 7, FALSE); // Falta parámetro PASSWORD
|
||||
return (FALSE);
|
||||
}
|
||||
if (datasource[0] == (char) NULL) {
|
||||
errorLog(modulo, 8, FALSE); // Falta parámetro DATASOURCE
|
||||
return (FALSE);
|
||||
}
|
||||
if (catalog[0] == (char) NULL) {
|
||||
errorLog(modulo, 9, FALSE); // Falta parámetro CATALOG
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
// ________________________________________________________________________________________________________
|
||||
//
|
||||
// Función: diadelaSemana
|
||||
//
|
||||
// Descripción:
|
||||
// Calcula el número del día de la semana que corresponde a una fecha
|
||||
// Parámetros:
|
||||
// - dia: Un día
|
||||
// - mes: Un mes
|
||||
// - anno: Un año
|
||||
// Devuelve:
|
||||
// El número del día de la semana: 1=Lunes, 2=martes ... 6=sábado 7=domingo
|
||||
// ________________________________________________________________________________________________________
|
||||
|
||||
int diadelaSemana(WORD dia,WORD mes,WORD anno)
|
||||
{
|
||||
int i,cont,dias_anuales;
|
||||
int desplazamiento_dias=6;
|
||||
int orddiasem;
|
||||
|
||||
cont =0;
|
||||
for (i=1900;i<anno;i++){
|
||||
if (bisiesto(i)) dias_anuales=366; else dias_anuales=365;
|
||||
cont+=dias_anuales;
|
||||
}
|
||||
for (i=1;i<mes;i++){
|
||||
if (i!=2)
|
||||
cont+=dias_meses[i];
|
||||
else{
|
||||
if (bisiesto(anno))
|
||||
cont+=29;
|
||||
else
|
||||
cont+=28;
|
||||
}
|
||||
}
|
||||
cont+=dia+desplazamiento_dias;
|
||||
orddiasem=(cont%7);
|
||||
if(orddiasem==0) orddiasem=7;
|
||||
return(orddiasem);
|
||||
}
|
||||
// ________________________________________________________________________________________________________
|
||||
//
|
||||
// Función: bisiesto
|
||||
//
|
||||
// Descripción:
|
||||
// Calcula si un año es bisiesto o no lo es
|
||||
// Parámetros:
|
||||
// - anno: Un año
|
||||
// Devuelve:
|
||||
// TRUE si el año es bisiesto
|
||||
// FALSE si no es bisiesto
|
||||
// ________________________________________________________________________________________________________
|
||||
|
||||
BOOLEAN bisiesto(WORD anno){
|
||||
return(anno%4==0);
|
||||
}
|
||||
// ________________________________________________________________________________________________________
|
||||
//
|
||||
// Función: semanadelMes
|
||||
//
|
||||
// Descripción:
|
||||
// Calcula el número de semana perteneciente a un día del mes
|
||||
// Parámetros:
|
||||
// - ordiasem_1: Orden semanal (1,2...) del primer dia del mes que se pasa como parámetro
|
||||
// - diames: El mes concreto
|
||||
// Devuelve:
|
||||
// El número del día de la semana: 1=Lunes, 2=martes ... 6=sábado 7=domingo , de ese mes
|
||||
// ________________________________________________________________________________________________________
|
||||
|
||||
int semanadelMes(int ordiasem_1,int diames)
|
||||
{
|
||||
int nwdia,resto,cociente;
|
||||
|
||||
nwdia=diames+ordiasem_1-1;
|
||||
cociente=nwdia/7;
|
||||
resto=nwdia%7;
|
||||
if(resto>0) cociente++;
|
||||
return(cociente);
|
||||
}
|
||||
// ________________________________________________________________________________________________________
|
||||
//
|
||||
// Función: buscaAccion
|
||||
//
|
||||
// Descripción:
|
||||
// Busca en la base de datos, acciones programadas
|
||||
// Parámetros:
|
||||
// - db: Objeto base de datos (operativo)
|
||||
// - dia : Día actual del mes
|
||||
// - mes : mes en curso
|
||||
// - anno : Año en curso
|
||||
// - hora : Hora actual
|
||||
// - minutos : Minutos actuales
|
||||
// - diasemana : Dia de la semana 1=lunes,2=martes ... ( 0 Domingo)
|
||||
// Devuelve:
|
||||
// TRUE: Si el proceso es correcto
|
||||
// FALSE: En caso de ocurrir algún error
|
||||
// ________________________________________________________________________________________________________
|
||||
|
||||
BOOLEAN buscaAccion(Database db,WORD dia,WORD mes,WORD anno,WORD hora,WORD minutos,WORD diasemana)
|
||||
{
|
||||
char msglog[LONSTD], sqlstr[LONSQL];
|
||||
Table tbl;
|
||||
BYTE swampm,bitsemana;
|
||||
int ordsem,ordulsem,ordiasem_1,maxdias;
|
||||
int sesionprog;
|
||||
char modulo[] = "buscaAccion()";
|
||||
|
||||
/* Año de comienzo */
|
||||
anno=anno-ANNOREF; //
|
||||
/* Preparación hora */
|
||||
if(hora>11){
|
||||
hora-=12;
|
||||
swampm=1; // Es P.M.
|
||||
}
|
||||
else
|
||||
swampm=0; // Es am
|
||||
/* Preparación semana */
|
||||
if(diasemana==0) diasemana=7; // El domingo
|
||||
|
||||
// Cuestión semanas
|
||||
ordiasem_1=diadelaSemana(1,mes,anno+2009);
|
||||
ordsem=semanadelMes(ordiasem_1,dia); // Calcula el número de la semana
|
||||
if (mes!=2) // Toma el último día de ese mes
|
||||
maxdias=dias_meses[mes];
|
||||
else{
|
||||
if (bisiesto(anno+ANNOREF))
|
||||
maxdias=29;
|
||||
else
|
||||
maxdias=28;
|
||||
}
|
||||
ordulsem=semanadelMes(ordiasem_1,maxdias); // Calcula el número de la última semana
|
||||
bitsemana=HEX_semanas[ordsem];
|
||||
if(ordsem==ordulsem) // Si es la última semana del mes
|
||||
bitsemana|=HEX_semanas[6];
|
||||
|
||||
sprintf(sqlstr,"SELECT DISTINCT idprogramacion,tipoaccion,identificador,sesion,idcentro,"\
|
||||
"tareas.descripcion as descritarea"\
|
||||
" FROM programaciones"\
|
||||
" LEFT OUTER JOIN tareas ON tareas.idtarea=programaciones.identificador"\
|
||||
" WHERE suspendida=0 "\
|
||||
" AND (annos & %d <> 0) "\
|
||||
" AND (meses & %d<>0) "\
|
||||
" AND ((diario & %d<>0) OR (dias & %d<>0) OR (semanas & %d<>0))"\
|
||||
" AND (horas & %d<>0) AND ampm=%d AND minutos=%d",\
|
||||
HEX_annos[anno],\
|
||||
HEX_meses[mes],\
|
||||
HEX_dias[dia],\
|
||||
HEX_diasemana[diasemana],\
|
||||
bitsemana,\
|
||||
HEX_horas[hora],\
|
||||
swampm,minutos);
|
||||
|
||||
if (!db.Execute(sqlstr, tbl)) { // Error al leer
|
||||
errorLog(modulo, 21, FALSE);
|
||||
db.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
if(tbl.ISEOF()){
|
||||
return(TRUE); // No hay acciones programadas
|
||||
}
|
||||
|
||||
while(!tbl.ISEOF()){
|
||||
if(!tbl.Get("idprogramacion",idprogramacion)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
if(!tbl.Get("tipoaccion",tipoaccion)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
if(!tbl.Get("identificador",idtipoaccion)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
if(!tbl.Get("sesion",sesionprog)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
if(!tbl.Get("idcentro",idcentro)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if(tipoaccion==EJECUCION_COMANDO){ // Es una programación de un comando
|
||||
return(ejecutarComando(db,idprogramacion,sesionprog));
|
||||
}
|
||||
else{
|
||||
|
||||
if(tipoaccion==EJECUCION_TAREA){
|
||||
if(!tbl.Get("descritarea",descriaccion)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
return(ejecutarTarea(db,idprogramacion,idtipoaccion));
|
||||
}
|
||||
else{
|
||||
if(tipoaccion==EJECUCION_RESERVA){
|
||||
EjecutarReserva(idtipoaccion,db); // Es una programación de un trabajo
|
||||
}
|
||||
}
|
||||
}
|
||||
tbl.MoveNext();
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
// ________________________________________________________________________________________________________
|
||||
//
|
||||
// Función: ejecutarComando
|
||||
//
|
||||
// Descripción:
|
||||
// Ejecuta un comando programado
|
||||
// Parámetros:
|
||||
// - db: Objeto base de datos (operativo)
|
||||
// - idcomando: Identificador del comando
|
||||
// - sesion: Sesión correspondiente al comando cuando se grabó en la tabla acciones
|
||||
// Devuelve:
|
||||
// TRUE: Si el proceso es correcto
|
||||
// FALSE: En caso de ocurrir algún error
|
||||
// ________________________________________________________________________________________________________
|
||||
|
||||
BOOLEAN ejecutarComando(Database db,int idprogramacion,int sesion )
|
||||
{
|
||||
struct tm* st;
|
||||
char msglog[LONSTD], sqlstr[LONSQL];
|
||||
char fechahorareg[24];
|
||||
char modulo[] = "ejecutarComando()";
|
||||
|
||||
st = tomaHora();
|
||||
sprintf(fechahorareg,"%d/%d/%d %d:%d:%d", st->tm_year + 1900, st->tm_mon + 1,
|
||||
st->tm_mday, st->tm_hour, st->tm_min, st->tm_sec);
|
||||
|
||||
sprintf(sqlstr,"UPDATE acciones SET estado=%d,idprogramacion=%d,fechahorareg='%s'"\
|
||||
" WHERE sesion=%d", ACCION_INICIADA,idprogramacion,fechahorareg,sesion);
|
||||
|
||||
if (!db.Execute(sqlstr)) { // Error al recuperar los datos
|
||||
errorLog(modulo, 21, FALSE);
|
||||
db.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
return(enviaPeticion(idprogramacion));
|
||||
}
|
||||
// ________________________________________________________________________________________________________
|
||||
//
|
||||
// Función: ejecutarProcedimiento
|
||||
//
|
||||
// Descripción:
|
||||
// Ejecuta un procedimiento programado
|
||||
// Parámetros:
|
||||
// - db: Objeto base de datos (operativo)
|
||||
// - idprocedimiento: Identificador del procedimiento
|
||||
// - ambito: Ámbito de aplicación
|
||||
// - idambito: Identificador del ámbito
|
||||
// - restrambito: cadena con los identificadores de los ordenadores a los que se aplica la acción
|
||||
// Devuelve:
|
||||
// TRUE: Si el proceso es correcto
|
||||
// FALSE: En caso de ocurrir algún error
|
||||
// ________________________________________________________________________________________________________
|
||||
|
||||
BOOLEAN ejecutarProcedimiento(Database db,int idprocedimiento,int ambito,int idambito,char* restrambito)
|
||||
{
|
||||
char msglog[LONSTD], sqlstr[LONSQL],*parametros;
|
||||
Table tbl;
|
||||
int procedimientoid,idcomando,lonprm;
|
||||
char modulo[] = "ejecutarProcedimiento()";
|
||||
|
||||
sprintf(sqlstr,"SELECT idcomando,procedimientoid,parametros,length(parametros) as lonprm"\
|
||||
" FROM procedimientos_acciones"\
|
||||
" WHERE idprocedimiento=%d ORDER BY orden",idprocedimiento);
|
||||
|
||||
if (!db.Execute(sqlstr, tbl)) { // Error al leer
|
||||
errorLog(modulo, 21, FALSE);
|
||||
db.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if(tbl.ISEOF()){
|
||||
return(TRUE); // No exustde tarea
|
||||
}
|
||||
while(!tbl.ISEOF()){
|
||||
if(!tbl.Get("procedimientoid",procedimientoid)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
if(procedimientoid>0){ // Procedimiento recursivo
|
||||
if(!ejecutarProcedimiento(db,procedimientoid,ambito,idambito,restrambito)){
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(!tbl.Get("lonprm",lonprm)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
parametros = reservaMemoria(lonprm+1); // Reserva para almacenar los parametros del procedimiento
|
||||
if (parametros == NULL) {
|
||||
errorLog(modulo, 3, FALSE);
|
||||
return (FALSE);
|
||||
}
|
||||
if(!tbl.Get("parametros",parametros)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
liberaMemoria(parametros);
|
||||
return (FALSE);
|
||||
}
|
||||
if(!tbl.Get("idcomando",idcomando)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if(!insertaComando(db,idcomando,parametros,idprocedimiento,ambito,idambito,restrambito)) {
|
||||
|
||||
liberaMemoria(parametros);
|
||||
return(false);
|
||||
}
|
||||
liberaMemoria(parametros);
|
||||
}
|
||||
tbl.MoveNext();
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
// ________________________________________________________________________________________________________
|
||||
//
|
||||
// Función: ejecutarTarea
|
||||
//
|
||||
// Descripción:
|
||||
// Ejecuta una tarea programada
|
||||
// Parámetros:
|
||||
// - db: Objeto base de datos (operativo)
|
||||
// - idtarea: Identificador de la tarea
|
||||
// - idprogramacion: Identificador de la programación
|
||||
// Devuelve:
|
||||
// TRUE: Si el proceso es correcto
|
||||
// FALSE: En caso de ocurrir algún error
|
||||
// ________________________________________________________________________________________________________
|
||||
|
||||
BOOLEAN ejecutarTarea(Database db, int idprogramacion, int idtarea)
|
||||
{
|
||||
char msglog[LONSTD], sqlstr[LONSQL];
|
||||
Table tbl;
|
||||
int tareaid,ambito,idambito,idprocedimiento,lonrestrambito;
|
||||
char* restrambito;
|
||||
char modulo[] = "ejecutarTarea()";
|
||||
|
||||
sprintf(sqlstr,"SELECT tareas_acciones.orden,tareas_acciones.idprocedimiento,tareas_acciones.tareaid,"\
|
||||
" tareas.ambito,tareas.idambito,tareas.restrambito,length(tareas.restrambito) as lonrestrambito"\
|
||||
" FROM tareas"\
|
||||
" INNER JOIN tareas_acciones ON tareas_acciones.idtarea=tareas.idtarea"\
|
||||
" WHERE tareas_acciones.idtarea=%d ORDER BY tareas_acciones.orden",idtarea);
|
||||
|
||||
if (!db.Execute(sqlstr, tbl)) { // Error al leer
|
||||
errorLog(modulo, 21, FALSE);
|
||||
db.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if(tbl.ISEOF()){
|
||||
return(TRUE); // No existe tarea
|
||||
}
|
||||
|
||||
while(!tbl.ISEOF()){
|
||||
if(!tbl.Get("tareaid",tareaid)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
if(tareaid>0){ // Tarea recursiva
|
||||
if(!ejecutarTarea(db,idprogramacion,tareaid)){
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(!tbl.Get("ambito",ambito)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
if(!tbl.Get("idambito",idambito)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
if(!tbl.Get("lonrestrambito",lonrestrambito)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
restrambito = reservaMemoria(lonrestrambito+1);
|
||||
if (restrambito == NULL) {
|
||||
errorLog(modulo, 3, FALSE);
|
||||
return (FALSE);
|
||||
}
|
||||
if(!tbl.Get("restrambito",restrambito)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
liberaMemoria(restrambito);
|
||||
return (FALSE);
|
||||
}
|
||||
liberaMemoria(restrambito);
|
||||
RecopilaIpesMacs(db,ambito,idambito,restrambito); // Recopila Ipes del ámbito
|
||||
if(!tbl.Get("idprocedimiento",idprocedimiento)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
sesion=time(NULL);
|
||||
|
||||
if(!ejecutarProcedimiento(db,idprocedimiento,ambito,idambito,restrambito))
|
||||
return(FALSE);
|
||||
}
|
||||
tbl.MoveNext();
|
||||
}
|
||||
return(enviaPeticion(idprogramacion));
|
||||
}
|
||||
// ________________________________________________________________________________________________________
|
||||
//
|
||||
// Función: ejecutarTarea
|
||||
//
|
||||
// Descripción:
|
||||
// Registra un procedimiento para un ambito concreto
|
||||
// Parámetros:
|
||||
// - db: Objeto base de datos (operativo)
|
||||
// - idcomando: Identificador del comando
|
||||
// - idprocedimiento: Identificador del procedimiento
|
||||
// - ambito: Ámbito de aplicación
|
||||
// - idambito: Identificador del ámbito
|
||||
// - restrambito: cadena con los identificadores de los ordenadores a los que se aplica la acción
|
||||
// Devuelve:
|
||||
// TRUE: Si el proceso es correcto
|
||||
// FALSE: En caso de ocurrir algún error
|
||||
//________________________________________________________________________________________________________
|
||||
BOOLEAN insertaComando(Database db,int idcomando,char*parametros,int idprocedimiento,int ambito,int idambito,char*restrambito)
|
||||
{
|
||||
char msglog[LONSTD], sqlstr[LONSQL];
|
||||
struct tm* st;
|
||||
char *auxID[MAXIMOS_CLIENTES],*auxIP[MAXIMOS_CLIENTES];
|
||||
char fechahorareg[24];
|
||||
int i;
|
||||
char modulo[] = "insertaComando()";
|
||||
|
||||
if(concli==0) return(TRUE); // No hay ordenadores en el ámbito
|
||||
|
||||
st = tomaHora();
|
||||
sprintf(fechahorareg,"%d/%d/%d %d:%d:%d", st->tm_year + 1900, st->tm_mon + 1, st->tm_mday, st->tm_hour, st->tm_min, st->tm_sec);
|
||||
|
||||
splitCadena(auxID,cadenaid,',');
|
||||
splitCadena(auxIP,cadenaip,';');
|
||||
|
||||
for (i=0;i<concli;i++){
|
||||
sprintf(sqlstr,"INSERT INTO acciones (idordenador,tipoaccion,idtipoaccion,descriaccion,ip,"\
|
||||
"sesion,idcomando,parametros,fechahorareg,estado,resultado,ambito,idambito,"\
|
||||
"restrambito,idprocedimiento,idcentro,idprogramacion)"\
|
||||
" VALUES (%s,%d,%d,'%s','%s',%d,%d,'%s','%s',%d,%d,%d,%d,'%s',%d,%d,%d)",\
|
||||
auxID[i],tipoaccion,idtipoaccion,descriaccion,auxIP[i],sesion,idcomando,parametros,fechahorareg,\
|
||||
ACCION_INICIADA,ACCION_SINRESULTADO,ambito,idambito,restrambito,idprocedimiento,idcentro,idprogramacion);
|
||||
if (!db.Execute(sqlstr)) { // Error al recuperar los datos
|
||||
errorLog(modulo, 21, FALSE);
|
||||
db.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
// _____________________________________________________________________________________________________________
|
||||
// Función: EjecutarReserva
|
||||
//
|
||||
// Descripción:
|
||||
// Registra una acción (Tarea) y la envía para su ejecución
|
||||
// Parámetros:
|
||||
// - idreserva : Identificador de la reserva
|
||||
// - db: una conexion ADO operativa
|
||||
// - parametros: Parámetros de la acción
|
||||
// _____________________________________________________________________________________________________________
|
||||
BOOLEAN EjecutarReserva(int idreserva,Database db )
|
||||
{
|
||||
|
||||
|
||||
return(true);
|
||||
}
|
||||
// _____________________________________________________________________________________________________________
|
||||
// Función: enviaPeticion
|
||||
//
|
||||
// Descripción:
|
||||
// Hace una petición al servidor para que actualice los ordenadores implicados en la programación
|
||||
// Parámetros:
|
||||
// - idprogramacion: Identificador de la programación
|
||||
// _____________________________________________________________________________________________________________
|
||||
BOOLEAN enviaPeticion(int idprogramacion)
|
||||
{
|
||||
int lon;
|
||||
TRAMA *ptrTrama;
|
||||
SOCKET socket_c;
|
||||
char modulo[] = "enviaPeticion()";
|
||||
|
||||
/* Envio de comandos a clientes */
|
||||
ptrTrama=(TRAMA *)reservaMemoria(sizeof(TRAMA));
|
||||
if (ptrTrama == NULL) { // No hay memoria suficiente para el bufer de las tramas
|
||||
errorLog(modulo, 3, FALSE);
|
||||
return(FALSE);
|
||||
}
|
||||
initParametros(ptrTrama,0);
|
||||
lon=sprintf(ptrTrama->parametros,"nfn=envioProgramacion\r"); // Nombre de la función a ejecutar en el servidor
|
||||
lon+=sprintf(ptrTrama->parametros+lon,"idp=%d\r",idprogramacion); // Configuración de los Sistemas Operativos del cliente
|
||||
|
||||
if(!enviaMensaje(&socket_c,ptrTrama,MSG_PETICION)){
|
||||
errorLog(modulo,91,FALSE);
|
||||
liberaMemoria(ptrTrama);
|
||||
return(FALSE);
|
||||
}
|
||||
liberaMemoria(ptrTrama);
|
||||
return(TRUE);
|
||||
}
|
||||
// _____________________________________________________________________________________________________________
|
||||
//
|
||||
// Función: RecopilaIpesMacs
|
||||
//
|
||||
// Descripción :
|
||||
// Recopila las IPes, las Macs y los identificadores de ordenadores de un ámbito determinado
|
||||
//
|
||||
// Especificaciones:
|
||||
// Esta Función recibe tres parámatros:
|
||||
// db : Un objeto Base de datos totalmente operativo
|
||||
// ambito: Tipo de ámbito
|
||||
// idambito: Identificador del ámbito
|
||||
// Devuelve:
|
||||
// Todas los identificadores de ordenadores , las ipes y las macs de los ordenadores que componen el ámbito
|
||||
// Para ellos habrá que tener declarada tres variables globales :
|
||||
// cadenaid,cadenaip y cadenamac
|
||||
// _____________________________________________________________________________________________________________
|
||||
|
||||
BOOLEAN RecopilaIpesMacs(Database db,int ambito,int idambito,char *restrambito)
|
||||
{
|
||||
char sqlstr[LONSQL];
|
||||
|
||||
concli=0;
|
||||
/* Reserva memoria al meno para caracter nulo */
|
||||
cadenaid=(char*) reservaMemoria(1);
|
||||
cadenaip=(char*) reservaMemoria(1);
|
||||
cadenamac=(char*) reservaMemoria(1);
|
||||
|
||||
switch(ambito){
|
||||
case AMBITO_CENTROS :
|
||||
sprintf(sqlstr,"SELECT ip,mac,idordenador FROM ordenadores INNER JOIN aulas WHERE ordenadores.idaula=aulas.idaula AND idcentro=%d ORDER BY ordenadores.idaula, ordenadores.ip;",idambito);
|
||||
RecorreOrdenadores(db,sqlstr);
|
||||
break;
|
||||
case AMBITO_GRUPOSAULAS :
|
||||
sprintf(sqlstr,"SELECT idgrupo FROM grupos WHERE idgrupo=%d AND tipo=%d",idambito,AMBITO_GRUPOSAULAS);
|
||||
RecorreGruposAulas(db,sqlstr);
|
||||
break;
|
||||
case AMBITO_AULAS :
|
||||
sprintf(sqlstr,"SELECT ip,mac,idordenador FROM ordenadores WHERE idaula=%d ORDER BY ip;",idambito);
|
||||
RecorreOrdenadores(db,sqlstr);
|
||||
break;
|
||||
case AMBITO_GRUPOSORDENADORES :
|
||||
sprintf(sqlstr,"SELECT idgrupo FROM gruposordenadores WHERE idgrupo=%d",idambito);
|
||||
RecorreGruposOrdenadores(db,sqlstr);
|
||||
break;
|
||||
case AMBITO_ORDENADORES :
|
||||
sprintf(sqlstr,"SELECT ip,mac,idordenador FROM ordenadores WHERE idordenador=%d",idambito);
|
||||
RecorreOrdenadores(db,sqlstr);
|
||||
break;
|
||||
default: // Se trata de un conjunto aleatorio de ordenadores
|
||||
sprintf(sqlstr,"SELECT ip,mac,idordenador FROM ordenadores WHERE idordenador IN (%s)",restrambito);
|
||||
RecorreOrdenadores(db,sqlstr);
|
||||
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
//________________________________________________________________________________________________________
|
||||
|
||||
BOOLEAN RecorreCentro(Database db, char* sqlstr)
|
||||
{
|
||||
char msglog[LONSTD];
|
||||
Table tbl;
|
||||
int idcentro;
|
||||
char modulo[] = "RecorreCentro()";
|
||||
|
||||
if (!db.Execute(sqlstr, tbl)) { // Error al leer
|
||||
errorLog(modulo, 21, FALSE);
|
||||
db.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
if(!tbl.ISEOF()){
|
||||
if(!tbl.Get("idcentro",idcentro)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
sprintf(sqlstr,"SELECT idgrupo FROM grupos WHERE idcentro=%d AND grupoid=0 AND tipo=%d",idcentro,AMBITO_GRUPOSAULAS);
|
||||
RecorreGruposAulas(db,sqlstr);
|
||||
sprintf(sqlstr,"SELECT idaula FROM aulas WHERE idcentro=%d AND grupoid=0",idcentro);
|
||||
RecorreAulas(db,sqlstr);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
//________________________________________________________________________________________________________
|
||||
|
||||
BOOLEAN RecorreGruposAulas(Database db, char* sqlstr)
|
||||
{
|
||||
char msglog[LONSTD];
|
||||
Table tbl;
|
||||
int idgrupo;
|
||||
char modulo[] = "RecorreGruposAulas()";
|
||||
|
||||
if (!db.Execute(sqlstr, tbl)) { // Error al leer
|
||||
errorLog(modulo, 21, FALSE);
|
||||
db.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
while(!tbl.ISEOF()){
|
||||
if(!tbl.Get("idgrupo",idgrupo)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
sprintf(sqlstr,"SELECT idgrupo FROM grupos WHERE grupoid=%d AND tipo=%d",idgrupo,AMBITO_GRUPOSAULAS);
|
||||
RecorreGruposAulas(db,sqlstr);
|
||||
sprintf(sqlstr,"SELECT idaula FROM aulas WHERE grupoid=%d",idgrupo);
|
||||
RecorreAulas(db,sqlstr);
|
||||
tbl.MoveNext();
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
//________________________________________________________________________________________________________
|
||||
|
||||
BOOLEAN RecorreAulas(Database db, char* sqlstr)
|
||||
{
|
||||
char msglog[LONSTD];
|
||||
Table tbl;
|
||||
int idaula;
|
||||
char modulo[] = "RecorreAulas()";
|
||||
|
||||
if (!db.Execute(sqlstr, tbl)) { // Error al leer
|
||||
errorLog(modulo, 21, FALSE);
|
||||
db.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
while(!tbl.ISEOF()){
|
||||
if(!tbl.Get("idaula",idaula)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
sprintf(sqlstr,"SELECT idgrupo FROM gruposordenadores WHERE idaula=%d AND grupoid=0",idaula);
|
||||
RecorreGruposOrdenadores(db,sqlstr);
|
||||
sprintf(sqlstr,"SELECT ip,mac,idordenador FROM ordenadores WHERE idaula=%d AND grupoid=0",idaula);
|
||||
RecorreOrdenadores(db,sqlstr);
|
||||
tbl.MoveNext();
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
//________________________________________________________________________________________________________
|
||||
|
||||
BOOLEAN RecorreGruposOrdenadores(Database db, char* sqlstr)
|
||||
{
|
||||
char msglog[LONSTD];
|
||||
Table tbl;
|
||||
int idgrupo;
|
||||
char modulo[] = "RecorreGruposOrdenadores()";
|
||||
|
||||
if (!db.Execute(sqlstr, tbl)) { // Error al leer
|
||||
errorLog(modulo, 21, FALSE);
|
||||
db.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
while(!tbl.ISEOF()){
|
||||
if(!tbl.Get("idgrupo",idgrupo)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
sprintf(sqlstr,"SELECT idgrupo FROM gruposordenadores WHERE grupoid=%d",idgrupo);
|
||||
RecorreGruposOrdenadores(db,sqlstr);
|
||||
sprintf(sqlstr,"SELECT ip,mac,idordenador FROM ordenadores WHERE grupoid=%d",idgrupo);
|
||||
RecorreOrdenadores(db,sqlstr);
|
||||
tbl.MoveNext();
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
//________________________________________________________________________________________________________
|
||||
|
||||
BOOLEAN RecorreOrdenadores(Database db, char* sqlstr)
|
||||
{
|
||||
char msglog[LONSTD];
|
||||
Table tbl;
|
||||
int idordenador,o,p,m,lon;
|
||||
char ido[16],ip[LONIP],mac[LONMAC];
|
||||
char modulo[] = "RecorreOrdenadores()";
|
||||
|
||||
if (!db.Execute(sqlstr, tbl)) { // Error al leer
|
||||
errorLog(modulo, 21, FALSE);
|
||||
db.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
o=p=m=0;
|
||||
while(!tbl.ISEOF()){
|
||||
if(!tbl.Get("idordenador",idordenador)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
if(!tbl.Get("ip",ip)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
if(!tbl.Get("mac",mac)){
|
||||
tbl.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
return (FALSE);
|
||||
}
|
||||
sprintf(ido,"%d",idordenador);
|
||||
lon=strlen(ido);
|
||||
if(lon>16) lon=16;
|
||||
cadenaid=(char*) ampliaMemoria(cadenaid,o+lon+1);
|
||||
memcpy(&cadenaid[o],ido,lon);
|
||||
o+=lon;
|
||||
cadenaid[o++]=',';
|
||||
|
||||
lon=strlen(ip);
|
||||
if(lon>16) lon=LONIP;
|
||||
cadenaip=(char*) ampliaMemoria(cadenaip,p+lon+1);
|
||||
memcpy(&cadenaip[p],ip,lon);
|
||||
p+=lon;
|
||||
cadenaip[p++]=';';
|
||||
|
||||
lon=strlen(mac);
|
||||
if(lon>16) lon=LONMAC;
|
||||
cadenamac=(char*) ampliaMemoria(cadenamac,m+lon+1);
|
||||
memcpy(&cadenamac[m],mac,lon);
|
||||
m+=lon;
|
||||
cadenamac[m++]=';';
|
||||
|
||||
concli++;
|
||||
tbl.MoveNext();
|
||||
}
|
||||
if(o>0) o--;
|
||||
if(p>0) p--;
|
||||
if(m>0) m--;
|
||||
cadenaid[o]='\0';
|
||||
cadenaip[p]='\0';
|
||||
cadenamac[m]='\0';
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
// ********************************************************************************************************
|
||||
// PROGRAMA PRINCIPAL (SERVICIO)
|
||||
// ********************************************************************************************************
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int pseg;
|
||||
char msglog[LONSTD];
|
||||
struct tm* st;
|
||||
Database db;
|
||||
char modulo[] = "main()";
|
||||
|
||||
/* Validación de parámetros de ejecución y lectura del fichero de configuración del servicio */
|
||||
|
||||
if (!validacionParametros(argc, argv, 5)) // Valida parámetros de ejecución
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
if (!tomaConfiguracion(szPathFileCfg)) { // Toma parametros de configuracion
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Bucle principal del servicio */
|
||||
|
||||
while (TRUE){
|
||||
st = tomaHora();
|
||||
pseg=65-st->tm_sec; // Calcula segundos de inactividad de la hebra
|
||||
sleep(pseg);
|
||||
|
||||
// Toma la hora
|
||||
st = tomaHora();
|
||||
|
||||
if (!db.Open(usuario, pasguor, datasource, catalog)) { // Error de conexion
|
||||
errorLog(modulo, 20, FALSE);
|
||||
db.GetErrorErrStr(msglog);
|
||||
errorInfo(modulo, msglog);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
buscaAccion(db,st->tm_mday,st->tm_mon+1,st->tm_year+1900,st->tm_hour,st->tm_min,st->tm_wday );
|
||||
db.Close(); // Cierra conexión
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
// ********************************************************************************************************
|
||||
// Servicio: ogAdmAgent
|
||||
// Autor: José Manuel Alonso (E.T.S.I.I.) Universidad de Sevilla
|
||||
// Fecha Creación: Marzo-2010
|
||||
// Fecha Última modificación: Marzo-2010
|
||||
// Nombre del fichero: ogAdmAgent.h
|
||||
// Descripción: Este fichero implementa el servicio agente del sistema. Revisa a intervalos
|
||||
// regulares la base de datos para comprobar si existen acciones programadas.
|
||||
// ********************************************************************************************************
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include </usr/include/mysql/mysql.h>
|
||||
#include "Database.h"
|
||||
#include "ogAdmLib.h"
|
||||
|
||||
// ________________________________________________________________________________________________________
|
||||
//
|
||||
// Valores hexadecimales para consultas
|
||||
// ________________________________________________________________________________________________________
|
||||
|
||||
WORD HEX_annos[]={0,0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};
|
||||
WORD HEX_meses[]={0,0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,0x0100,0x0200,0x0400,0x0800};
|
||||
int HEX_dias[]={0,0x00000001,0x00000002,0x00000004,0x00000008,0x00000010,0x00000020,0x00000040,0x00000080,0x00000100,0x00000200,
|
||||
0x00000400,0x00000800,0x00001000,0x00002000,0x00004000,0x00008000,0x00010000,0x00020000,0x00040000,0x00080000,
|
||||
0x00100000,0x00200000,0x00400000,0x00800000,0x01000000,0x02000000,0x04000000,0x08000000,0x10000000,0x20000000,0x40000000};
|
||||
WORD HEX_horas[]={0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,0x0100,0x0200,0x0400,0x0800 };
|
||||
BYTE HEX_diasemana[]={0,0x01,0x02,0x04,0x08,0x10,0x20,0x40};
|
||||
BYTE HEX_semanas[]={0,0x01,0x02,0x04,0x08,0x10,0x20};
|
||||
WORD dias_meses[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
|
||||
|
||||
// ________________________________________________________________________________________________________
|
||||
//
|
||||
// Variables globales
|
||||
// ________________________________________________________________________________________________________
|
||||
|
||||
char servidoradm[LONPRM]; // Dirección IP del servidor de administración
|
||||
char puerto[LONPRM]; // Puerto de comunicación
|
||||
char usuario[LONPRM]; // Usuario de acceso a la base de datos
|
||||
char pasguor[LONPRM]; // Password del usuario
|
||||
char datasource[LONPRM]; // Dirección IP del gestor de base de datos
|
||||
char catalog[LONPRM]; // Nombre de la base de datos
|
||||
|
||||
int idprogramacion;
|
||||
int tipoaccion,idtipoaccion;
|
||||
char descriaccion[250];
|
||||
char *cadenaid;
|
||||
char *cadenaip;
|
||||
char *cadenamac;
|
||||
int concli;
|
||||
int sesion;
|
||||
int idcentro;
|
||||
|
||||
// ________________________________________________________________________________________________________
|
||||
// Prototipo de funciones
|
||||
// ________________________________________________________________________________________________________
|
||||
BOOLEAN tomaConfiguracion(char*);
|
||||
int diadelaSemana(WORD,WORD,WORD);
|
||||
BOOLEAN bisiesto(WORD);
|
||||
BOOLEAN buscaAccion(Database,WORD,WORD,WORD,WORD,WORD,WORD);
|
||||
BOOLEAN ejecutarComando(Database,int,int );
|
||||
BOOLEAN ejecutarProcedimiento(Database,int,int,int,char*);
|
||||
BOOLEAN ejecutarTarea(Database,int, int);
|
||||
BOOLEAN insertaComando(Database,int,char*,int,int,int,char*);
|
||||
BOOLEAN EjecutarReserva(int,Database);
|
||||
BOOLEAN enviaPeticion(int);
|
||||
BOOLEAN RecopilaIpesMacs(Database,int,int,char *);
|
||||
BOOLEAN RecorreCentro(Database, char*);
|
||||
BOOLEAN RecorreGruposAulas(Database, char*);
|
||||
BOOLEAN RecorreAulas(Database, char*);
|
||||
BOOLEAN RecorreGruposOrdenadores(Database, char*);
|
||||
BOOLEAN RecorreOrdenadores(Database, char*);
|
||||
|
Binary file not shown.
|
@ -1,285 +0,0 @@
|
|||
#!/bin/bash
|
||||
PARM=`cat`
|
||||
#PARM=$@
|
||||
|
||||
|
||||
#TODO: ticket 379
|
||||
#buscar parametro de identificador de operacion.
|
||||
#usar parametro de identificacion para anexarlo al nombre de log
|
||||
#Comprobar si la variable está seteas.
|
||||
#Si no lo está setearla.
|
||||
#Si esta seteada (en progreso) salir.
|
||||
|
||||
|
||||
TIME=$SECONDS
|
||||
|
||||
BASEDIR=/opt/opengnsys
|
||||
PATH=$PATH:$BASEDIR/bin
|
||||
REPONAME=ogAdmRepo
|
||||
REPODIR="$BASEDIR/images/"
|
||||
|
||||
# Para las sincronizadas
|
||||
# BACKUP: Define si se realiza copia de seguridad al crear una imagen (true|false).
|
||||
# IMGFS: Sistema de ficheros al crear las sincronizadas tipo archivo (EXT4|BTRFS).
|
||||
[ -z $OGENGINECONFIGURATE ] && source $BASEDIR/client/etc/engine.cfg
|
||||
# FS segun la configuracion y la version del kernel. ext4 para < 3.7, para >= BTRFS
|
||||
KERNEL=$(file -bkr /opt/opengnsys/tftpboot/ogclient/ogvmlinuz |awk '/Linux/ {for(i=1;i<=NF;i++) if($i~/version/) {v=$(i+1);printf("%d",v);sub(/[0-9]*\./,"",v);printf(".%02d",v)}}')
|
||||
[ $KERNEL \< 3.07 ] && IMGFS="EXT4" || IMGFS=${IMGFS:-"BTRFS"}
|
||||
|
||||
# Añade registro de incidencias.
|
||||
function echolog () {
|
||||
logger --tag $0 --priority local0.info "$*"
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
function mountImage () {
|
||||
#@param 1 image_file
|
||||
#@param 2 mount_dir
|
||||
#@param 3 openciones mount
|
||||
[ "$3" != "" ] && OPTMOUNT=" -o $3 "
|
||||
# Si está montado nada que hacer
|
||||
df |grep "$2$" 2>&1 >/dev/null && return 0
|
||||
# FS de la imagen segun el contenido del archivo .img
|
||||
if file "$1" |grep -i -e " ext4 filesystem " 2>&1 > /dev/null ; then
|
||||
echolog "mount $OPTMOUNT -t ext4 $1 $2"
|
||||
mount $OPTMOUNT -t ext4 $1 $2
|
||||
else
|
||||
echolog "mount $OPTMOUNT -o compress=lzo $1 $2"
|
||||
mount $OPTMOUNT -o compress=lzo "$1" "$2"
|
||||
fi
|
||||
# Si esta montado da error 32, lo damos como bueno
|
||||
RETVAL=$?
|
||||
[ $RETVAL -eq 32 ] && RETVAL=0
|
||||
return $RETVAL
|
||||
}
|
||||
|
||||
|
||||
PARM1=$(echo $PARM | cut -f1 -d" ")
|
||||
PARM2=$(echo $PARM | cut -f2 -d" ")
|
||||
PARM3=$(echo $PARM | cut -f3 -d" ")
|
||||
PARM4=$(echo $PARM | cut -f4 -d" ")
|
||||
|
||||
# Determinamos el tipo de sistema de fichero de las imagenes segun el kernel que tenga
|
||||
|
||||
|
||||
case "$PARM1" in
|
||||
START_MULTICAST)
|
||||
#1 START_MULTICAST
|
||||
#2 fichero a enviar
|
||||
#3 opciones de multicast
|
||||
FILE="$PARM2"
|
||||
MCASTOPT="$PARM3"
|
||||
echolog "Ejecutar $(which sendFileMcast) $FILE $MCASTOPT"
|
||||
sendFileMcast $FILE $MCASTOPT |logger --tag $0 --priority local0.info
|
||||
case $? in
|
||||
1) echolog "Parametros insuficientes"
|
||||
exit 1 ;;
|
||||
2) echolog "Fichero no accesible"
|
||||
exit 2 ;;
|
||||
3) echolog "Sesion multicast no valida"
|
||||
exit 3 ;;
|
||||
esac
|
||||
;;
|
||||
CREATE_IMAGE)
|
||||
# Creamos/Redimensionamos el fichero de imagen y lo montamos para que se pueda escribir sobre el
|
||||
#1 CREATE_IMAGE
|
||||
#2 nombre imagen
|
||||
#3 tipo de imagen [ img | diff ]
|
||||
#4 tamaño imagen
|
||||
LOOPDEVICE=$(losetup -f)
|
||||
DIRMOUNT="$REPODIR/mount/$PARM2"
|
||||
if [ "$PARM3" == "img" ] ; then
|
||||
IMGEXT="img"
|
||||
else
|
||||
IMGEXT="img.diff"
|
||||
DIRMOUNT="$DIRMOUNT.diff"
|
||||
fi
|
||||
IMGFILE="$REPODIR/$PARM2.$IMGEXT"
|
||||
IMGDIR="$(dirname $IMGFILE)"
|
||||
[ -d $IMGDIR ] || mkdir -p $IMGDIR
|
||||
mkdir -p "$DIRMOUNT"
|
||||
|
||||
LOCKFILE="$IMGFILE.lock"
|
||||
|
||||
SIZEREQUIRED="$PARM4"
|
||||
|
||||
# Si existe la imagen hacemos copia de seguridad y la redimesionamos
|
||||
if [ -f "$IMGFILE" ]; then
|
||||
echolog "La imagen $IMGFILE ya existe."
|
||||
# TODO modificar ogGetImageSize
|
||||
IMGSIZE=$(ls -l --block-size=1024 $IMGFILE| cut -f5 -d" ")
|
||||
|
||||
if [ "$BACKUP" == "true" -o "$BACKUP" == "TRUE" -o $IMGSIZE -lt $SIZEREQUIRED ]; then
|
||||
# Si la imagen esta montada la desmonto
|
||||
if [ -r "$DIRMOUNT/ogimg.info" ]; then
|
||||
echolog "umount $DIRMOUNT"
|
||||
umount "$DIRMOUNT"
|
||||
[ $? -ne 0 ] && echolog "Error: No podemos desmontar la imagen para hacer copia de seguridad o redimensionar" && exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Copia de seguridad de la imagen
|
||||
if [ "$BACKUP" == "true" -o "$BACKUP" == "TRUE" ]; then
|
||||
echolog "Copia de seguridad de la imagen anterior"
|
||||
echolog "cp $IMGFILE $IMGFILE.ant"
|
||||
cp "$IMGFILE" "$IMGFILE.ant"
|
||||
echolog mv -f "$IMGFILE.torrent" "$IMGFILE.torrent.ant" 2>/dev/null
|
||||
mv -f "$IMGFILE.torrent" "$IMGFILE.torrent.ant" 2>/dev/null
|
||||
fi
|
||||
|
||||
# Redimensionamos la imagen al tamaño necesario
|
||||
if [ $IMGSIZE -lt $SIZEREQUIRED ];then
|
||||
echolog "Redimensionamos la imagen $IMGFILE al tamaño necesario: $SIZEREQUIRED"
|
||||
echolog "truncate --size=\">$SIZEREQUIRED\"k $IMGFILE"
|
||||
truncate --size=">$SIZEREQUIRED"k $IMGFILE 2>&1 |logger --tag $0 --priority local0.info
|
||||
# FS de la imagen segun el contenido del archivo .img
|
||||
if file "$IMGFILE" |grep -i -e " ext4 filesystem " 2>&1 > /dev/null ; then
|
||||
losetup $LOOPDEVICE "$IMGFILE"
|
||||
echolog "resize2fs -f $LOOPDEVICE"
|
||||
resize2fs -f $LOOPDEVICE |logger --tag $0 --priority local0.info
|
||||
else
|
||||
mount -o compress=lzo "$IMGFILE" "$DIRMOUNT"
|
||||
echolog "btrfs filesystem resize max $DIRMOUNT"
|
||||
btrfs filesystem resize max "$DIRMOUNT" 2>&1 |logger --tag $0 --priority local0.info
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# Si no existe la imagen creamos el fichero.
|
||||
else
|
||||
echolog "Creamos la imagen $IMGFILE al tamaño necesario: $SIZEREQUIRED"
|
||||
touch "$IMGFILE"
|
||||
echolog "truncate --size=\">$SIZEREQUIRED\"k $IMGFILE"
|
||||
truncate --size=">$SIZEREQUIRED"k $IMGFILE 2>&1 |logger --tag $0 --priority local0.info
|
||||
#Formateamos imagen
|
||||
echo losetup $LOOPDEVICE "$IMGFILE"
|
||||
losetup $LOOPDEVICE "$IMGFILE"
|
||||
if [ $IMGFS == "EXT4" ] ; then
|
||||
echolog " mkfs.ext4 -i 4096 -b 4096 -L ${PARM2##*\/} $LOOPDEVICE"
|
||||
mkfs.ext4 -i 4096 -b 4096 -L ${PARM2##*\/} $LOOPDEVICE
|
||||
else
|
||||
echolog mkfs.btrfs -L ${PARM2##*\/} $LOOPDEVICE
|
||||
mkfs.btrfs -L ${PARM2##*\/} $LOOPDEVICE #&> $OGLOGCOMMAND
|
||||
fi
|
||||
fi
|
||||
# Montamos la imagen.
|
||||
mountImage "$IMGFILE" "$DIRMOUNT"
|
||||
if [ $? -ne 0 ]; then
|
||||
rmdir "$DIRMOUNT"
|
||||
echolog "Error al crear/redimensionar la imagen"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#touch "$DIRMOUNT/ogimg.info"
|
||||
echo "mounted"> "$LOCKFILE"
|
||||
TIME2=$[SECONDS-TIME]
|
||||
echolog "Fin creación/redimension de la imagen: $[TIME2/60]m $[TIME2%60]s"
|
||||
# Si existe dispositivo loop lo borramos.
|
||||
[ $LOOPDEVICE ] && losetup -a| grep $LOOPDEVICE &> /dev/null && losetup -d $LOOPDEVICE
|
||||
# TODO: comprobar que no se quede el losetup bloqueado.
|
||||
|
||||
;;
|
||||
MOUNT_IMAGE)
|
||||
# Montamos el fichero imagen para que se pueda
|
||||
#1 MOUNT_IMAGE
|
||||
#2 nombre imagen
|
||||
#3 tipo de imagen [ img | diff ]
|
||||
DIRMOUNT="$REPODIR""mount/$PARM2"
|
||||
if [ "$PARM3" == "img" ] ; then
|
||||
IMGEXT="img"
|
||||
else
|
||||
IMGEXT="img.diff"
|
||||
DIRMOUNT="$DIRMOUNT.diff"
|
||||
fi
|
||||
IMGFILE="$REPODIR/$PARM2.$IMGEXT"
|
||||
echolog "Montamos la imagen $IMGFILE "
|
||||
mkdir -p "$DIRMOUNT"
|
||||
mountImage "$IMGFILE" "$DIRMOUNT" ro || (echolog "Error al montar la imagen"; exit 1)
|
||||
;;
|
||||
UMOUNT_IMAGE)
|
||||
# Desmontamos el fichero imagen.
|
||||
# Si el directorio esta ocupado no se desmontará
|
||||
#1 UMOUNT_IMAGE
|
||||
#2 nombre imagen
|
||||
#3 tipo de imagen [ img | diff ]
|
||||
IMGTYPE="$PARM3"
|
||||
DIRMOUNT="$REPODIR/mount/$PARM2"
|
||||
if [ "$IMGTYPE" == "img" ]; then
|
||||
IMGEXT="img"
|
||||
else
|
||||
DIRMOUNT="$DIRMOUNT.$IMGTYPE"
|
||||
IMGEXT="img.diff"
|
||||
fi
|
||||
LOCKFILE="$REPODIR/$PARM2.$IMGEXT.lock"
|
||||
echolog "Desmontamos la imagen $PARM2 $PARM3 "
|
||||
umount $DIRMOUNT
|
||||
rmdir $DIRMOUNT
|
||||
[ -f $LOCKFILE ] && sed -i s/mounted//g $LOCKFILE
|
||||
|
||||
;;
|
||||
REDUCE_IMAGE)
|
||||
# Reduce el archivo de la imagen a tamaño datos + 500M
|
||||
#1 REDUCE_IMAGE
|
||||
#2 Nombre Imagen
|
||||
#3 Tipo de imagen [ img |diff ]
|
||||
DIRMOUNT="${REPODIR}mount/${PARM2}"
|
||||
if [ "$PARM3" == "img" ] ; then
|
||||
IMGEXT="img"
|
||||
else
|
||||
IMGEXT="img.diff"
|
||||
DIRMOUNT="$DIRMOUNT.diff"
|
||||
fi
|
||||
IMGFILE="$REPODIR$PARM2.$IMGEXT"
|
||||
LOCKFILE="$IMGFILE.lock"
|
||||
[ ! -f $IMGFILE ] && echolog "Imagen $IMGFILE no existe" && exit 1
|
||||
|
||||
# Para imagenes EXT4 reduzco, para BTRFS solo desmonto.
|
||||
if file $IMGFILE |grep -i -e " ext4 filesystem " 2>&1 > /dev/null ; then
|
||||
|
||||
[ -d $DIRMOUNT ] || mkdir $DIRMOUNT
|
||||
mountImage "$IMGFILE" "$DIRMOUNT" || (echolog "Error al montar la imagen $IMGFILE"; exit 1)
|
||||
|
||||
|
||||
# Si el espacio libre menor que 200Mb desmontamos la imagen y nos salimos
|
||||
AVAILABLE=$(df -k|grep $DIRMOUNT|awk '{print $4}')
|
||||
if [ $AVAILABLE -lt 200000 ]; then
|
||||
echolog "reducir imagen REPO $PARM2 $IMGEXT. tamaño minimo, nada que hacer"
|
||||
umount $DIRMOUNT || (echolog "Error al desmontar la imagen $IMGFILE"; exit 1)
|
||||
else
|
||||
|
||||
# Calculamos la diferencia entre el tamaño interno y externo
|
||||
EXTSIZE=$(ls -l --block-size=1024 $IMGFILE | cut -f5 -d" ")
|
||||
INTSIZE=$(df -k|grep "$DIRMOUNT"|awk '{print $2}')
|
||||
let EDGESIZE=$EXTSIZE-$INTSIZE
|
||||
|
||||
echolog "reducir imagen REPO $PARM2 $IMGEXT, tamaño final: $ENDSIZE"
|
||||
umount $DIRMOUNT
|
||||
LOOPDEVICE=$(losetup -f)
|
||||
losetup $LOOPDEVICE "$IMGFILE"
|
||||
|
||||
# Redimensiono sistema de ficheros
|
||||
echolog "resize2fs -fpM $LOOPDEVICE "
|
||||
resize2fs -fpM $LOOPDEVICE # 2>&1 |logger --tag $0 --priority local0.info
|
||||
mountImage "$IMGFILE" "$DIRMOUNT"
|
||||
# Calculamos el tamaño final del archivo
|
||||
INTSIZE=$(df -k|grep "$DIRMOUNT"|awk '{print $2}')
|
||||
let EXTSIZE=$INTSIZE+$EDGESIZE
|
||||
umount $DIRMOUNT || (echolog "Error al desmontar la imagen $IMGFILE"; exit 1)
|
||||
# Si existe dispositivo loop lo borramos.
|
||||
[ $LOOPDEVICE ] && losetup -a| grep $LOOPDEVICE &> /dev/null && losetup -d $LOOPDEVICE
|
||||
# Corto el archivo al tamaño del sistema de ficheros
|
||||
echo "truncate --size=\"$EXTSIZE\"k $IMGFILE"
|
||||
echolog "truncate --size=\"$EXTSIZE\"k $IMGFILE"
|
||||
truncate --size="$EXTSIZE"k $IMGFILE
|
||||
fi
|
||||
else
|
||||
umount $DIRMOUNT || (echolog "Error al desmontar la imagen $IMGFILE"; exit 1)
|
||||
fi
|
||||
rmdir $DIRMOUNT
|
||||
echo "reduced" >$LOCKFILE
|
||||
|
||||
;;
|
||||
default)
|
||||
echolog "Solicitud con parametros \"$PARM\" no realizada, no registrada o con errores"
|
||||
;;
|
||||
esac
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue