summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordevega <ma.devega@globunet.com>2019-05-17 13:21:04 +0200
committerdevega <ma.devega@globunet.com>2019-05-17 13:21:04 +0200
commit4a04b450f918e47fb0758cac47b3f0581d8db859 (patch)
treefb0b5aa897eb8e4f375fa7c10adf48229900ee2c
parent1dde16d74e66dd6699108bc17c03021e3ec96214 (diff)
parentd34b00c51df4dcc5aa88e76361b22ef7c1ff72a8 (diff)
Merge remote-tracking branch 'origin/webconsole3' into webconsole3
-rw-r--r--admin/Sources/Clients/ogagent/src/opengnsys/modules/server/OpenGnSys/__init__.py172
-rw-r--r--admin/WebConsole3/frontend/src/app/api/repository.service.ts54
-rw-r--r--admin/WebConsole3/frontend/src/app/api/software-component.service.ts2
-rw-r--r--admin/WebConsole3/frontend/src/app/api/software-type.service.ts36
-rw-r--r--admin/WebConsole3/frontend/src/app/core/header-inner/header-inner.component.html4
-rw-r--r--admin/WebConsole3/frontend/src/app/form-type/software-profile.form-type.ts12
-rw-r--r--admin/WebConsole3/frontend/src/app/model/command.ts3
-rw-r--r--admin/WebConsole3/frontend/src/app/model/software-profile.ts14
-rw-r--r--admin/WebConsole3/frontend/src/app/pages/command/create-image-command/create-image-command.component.ts4
-rw-r--r--admin/WebConsole3/frontend/src/app/pages/command/delete-cache-image-command/delete-cache-image-command.component.ts6
-rw-r--r--admin/WebConsole3/frontend/src/app/pages/command/format-command/format-command.component.ts13
-rw-r--r--admin/WebConsole3/frontend/src/app/pages/command/partition-format-command/partition-format-command.component.scss6
-rw-r--r--admin/WebConsole3/frontend/src/app/pages/command/partition-format-command/partition-format-command.component.ts3
-rw-r--r--admin/WebConsole3/frontend/src/app/pages/software-profile/software-profile.component.html84
-rw-r--r--admin/WebConsole3/frontend/src/app/pages/software-profile/software-profile.component.ts117
-rw-r--r--admin/WebConsole3/frontend/src/app/service/og-commands.service.ts15
-rw-r--r--admin/WebConsole3/frontend/src/app/service/og-common.service.ts16
-rw-r--r--admin/WebConsole3/frontend/src/environments/environment.ts6
-rw-r--r--installer/vagrant/Vagrantfile-webconsole3-vbox171
-rwxr-xr-xserver/bin/setserveraddr83
20 files changed, 574 insertions, 247 deletions
diff --git a/admin/Sources/Clients/ogagent/src/opengnsys/modules/server/OpenGnSys/__init__.py b/admin/Sources/Clients/ogagent/src/opengnsys/modules/server/OpenGnSys/__init__.py
index 2d233150..ab31fb39 100644
--- a/admin/Sources/Clients/ogagent/src/opengnsys/modules/server/OpenGnSys/__init__.py
+++ b/admin/Sources/Clients/ogagent/src/opengnsys/modules/server/OpenGnSys/__init__.py
@@ -39,6 +39,7 @@ import threading
import time
import urllib
import signal
+
from opengnsys import REST
from opengnsys import operations
from opengnsys.log import logger
@@ -46,6 +47,25 @@ 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):
@@ -92,7 +112,6 @@ class OpenGnSysWorker(ServerWorker):
interface = None # Bound interface for OpenGnsys
REST = None # REST object
loggedin = False # User session flag
- locked = {} # Locked partitions
browser = {} # Browser info
commands = [] # Running commands
random = None # Random string for secure connections
@@ -100,30 +119,24 @@ class OpenGnSysWorker(ServerWorker):
access_token = refresh_token = None # Server authorization tokens
grant_type = 'http://opengnsys.es/grants/og_client'
- def _check_secret(self, server):
- """
- Checks for received secret key and raise exception if it isn't valid.
- """
- try:
- if self.random != server.headers['Authorization']:
- raise Exception('Unauthorized operation')
- except Exception as e:
- logger.error(e)
- raise Exception(e)
-
def _launch_browser(self, url):
"""
Launchs the Browser with specified URL
:param url: URL to show
"""
logger.debug('Launching browser with URL: {}'.format(url))
- if hasattr(self.browser, 'process'):
- self.browser['process'].kill()
- os.kill(self.browser['process'].pid, signal.SIGINT)
+ # 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):
+ 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
@@ -136,20 +149,25 @@ class OpenGnSysWorker(ServerWorker):
if os_type == 'oglive':
menu_url = self.browser['url']
self._launch_browser('http://localhost/cgi-bin/httpd-log.sh')
- # Executing command
+ # Execute the code
(stat, out, err) = operations.exec_command(code)
- # Removing command from the list
+ # Remove command from the list
for c in self.commands:
if c.getName() == op_id:
self.commands.remove(c)
- # Removing the REST API prefix, if needed
+ # Remove the REST API prefix, if needed
if route.startswith(self.REST.endpoint):
route = route[len(self.REST.endpoint):]
- # Sending results
+ # 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')})
+ 'status': stat, 'output': out.encode('utf8').encode('base64'),
+ 'error': err.encode('utf8').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):
@@ -231,7 +249,7 @@ class OpenGnSysWorker(ServerWorker):
<html>
<head></head>
<body>
-<h1>Initializing...</h1>
+<h1 style="margin: 5em; font-size: xx-large;">OpenGnsys 3</h1>
</body>
</html>"""
f = open('/tmp/init.html', 'w')
@@ -312,7 +330,12 @@ class OpenGnSysWorker(ServerWorker):
def process_status(self, path, get_params, post_params, server):
"""
- Returns client status (OS type and login status).
+ 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.loggedin}
try:
@@ -320,32 +343,42 @@ class OpenGnSysWorker(ServerWorker):
except KeyError:
res['status'] = ''
# Check if OpenGnsys Client is busy
- if res['status'] == 'oglive' and self.locked:
+ 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')
- self._check_secret(server)
- # Rebooting thread.
+ # 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')
- self._check_secret(server)
- # Powering off thread.
+ # Powering off thread
def pwoff():
time.sleep(2)
operations.poweroff()
@@ -353,24 +386,30 @@ class OpenGnSysWorker(ServerWorker):
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')
- self._check_secret(server)
# Processing data
try:
script = urllib.unquote(post_params.get('script').decode('base64')).decode('utf8')
op_id = post_params.get('id')
- route = post_params.get('redirect_uri')
- # Checking if the thread id. exists
+ 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))
+ thr = threading.Thread(name=op_id, target=self._task_command, args=(route, script, op_id, send_config))
thr.start()
self.commands.append(thr)
else:
@@ -381,43 +420,43 @@ class OpenGnSysWorker(ServerWorker):
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')
- self._check_secret(server)
- # Sending log off message to OGAgent client.
+ # 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')
- self._check_secret(server)
- # Sending popup message to OGAgent client.
+ # 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:
- :return: object
+ :param server: authorization header
+ :return: JSON object
"""
serialno = '' # Serial number
storage = [] # Storage configuration
warnings = 0 # Number of warnings
logger.debug('Received getconfig operation')
- # self._check_secret(server)
# Processing data
for row in operations.get_configuration().split(';'):
cols = row.split(':')
@@ -443,65 +482,42 @@ class OpenGnSysWorker(ServerWorker):
logger.warn('Configuration parameter error: {}'.format(cols))
warnings += 1
else:
- # Logging warnings
+ # Log warnings
logger.warn('Configuration data error: {}'.format(cols))
warnings += 1
- # Returning configuration data and count of warnings
+ # Return configuration data and count of warnings
return {'serialno': serialno, 'storage': storage, 'warnings': warnings}
- def process_command(self, path, get_params, post_params, server):
- """
- Launches a thread to executing a command
- :param path: ignored
- :param get_params: ignored
- :param post_params: object with format:
- id: operation id.
- script: command code
- redirect_url: callback REST route
- :param server: headers data
- :rtype: object with launching status
- """
- logger.debug('Received command operation with params: {}'.format(post_params))
- self._check_secret(server)
- # Processing data
- try:
- script = post_params.get('script')
- op_id = post_params.get('id')
- route = post_params.get('redirect_url')
- # Checking 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))
- # Launching a new thread
- thr = threading.Thread(name=op_id, target=self.task_command, args=(script, route, op_id))
- thr.start()
- self.commands.append(thr)
- except Exception as e:
- logger.error('Got exception {}'.format(e))
- return {'error': e}
- return {'op': 'launched'}
-
+ @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:
- :return: object
+ :param server: authorization header
+ :return: JSON array: [["callback_url", "commands", trace_id], ...]
"""
data = []
logger.debug('Received execinfo operation')
- self._check_secret(server)
- # Returning the arguments of all running threads
+ # 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))
- self._check_secret(server)
+ # 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):
diff --git a/admin/WebConsole3/frontend/src/app/api/repository.service.ts b/admin/WebConsole3/frontend/src/app/api/repository.service.ts
index 1561f41a..55fd88a0 100644
--- a/admin/WebConsole3/frontend/src/app/api/repository.service.ts
+++ b/admin/WebConsole3/frontend/src/app/api/repository.service.ts
@@ -1,27 +1,27 @@
-import { Injectable } from '@angular/core';
-import { HttpClient} from '@angular/common/http';
-
-import { environment } from '../../environments/environment';
-import { Repository } from '../model/repository';
-import { RepositorySerializer } from '../serializer/repository.serializer';
-
-import {ResourceService} from 'globunet-angular/core/providers/api/resource.service';
-import {Observable} from 'rxjs';
-
-
-@Injectable({
- providedIn: 'root'
-})
-export class RepositoryService extends ResourceService<Repository> {
-
- constructor(http: HttpClient) {
- super(http, environment.API_URL, 'repositories', new RepositorySerializer());
- }
-
- getInfo(repository: Repository) {
- const url = 'https://' + repository.ip + '/' + environment.BASE_DIR + environment.API_BASE_URL;
- return this.httpClient.get(url, {headers: {
- Authorization: repository.password
- }});
- }
-}
+import { Injectable } from '@angular/core';
+import { HttpClient} from '@angular/common/http';
+
+import { environment } from '../../environments/environment';
+import { Repository } from '../model/repository';
+import { RepositorySerializer } from '../serializer/repository.serializer';
+
+import {ResourceService} from 'globunet-angular/core/providers/api/resource.service';
+import {Observable} from 'rxjs';
+
+
+@Injectable({
+ providedIn: 'root'
+})
+export class RepositoryService extends ResourceService<Repository> {
+
+ constructor(http: HttpClient) {
+ super(http, environment.API_URL, 'repositories', new RepositorySerializer());
+ }
+
+ getInfo(repository: Repository) {
+ const url = 'https://' + repository.ip + '/' + environment.BASE_DIR + environment.API_BASE_URL;
+ return this.httpClient.get(url, {headers: {
+ Authorization: repository.randomId
+ }});
+ }
+}
diff --git a/admin/WebConsole3/frontend/src/app/api/software-component.service.ts b/admin/WebConsole3/frontend/src/app/api/software-component.service.ts
index b154d41a..515f1cb4 100644
--- a/admin/WebConsole3/frontend/src/app/api/software-component.service.ts
+++ b/admin/WebConsole3/frontend/src/app/api/software-component.service.ts
@@ -14,7 +14,7 @@ import {ResourceService} from "globunet-angular/core/providers/api/resource.serv
export class SoftwareComponentService extends ResourceService<SoftwareComponent> {
constructor(http: HttpClient){
- super(http, environment.API_URL,"softwarecomponents", new SoftwareComponentSerializer());
+ super(http, environment.API_URL,"softwares", new SoftwareComponentSerializer());
}
}
diff --git a/admin/WebConsole3/frontend/src/app/api/software-type.service.ts b/admin/WebConsole3/frontend/src/app/api/software-type.service.ts
index ccc6eb8f..1c250b91 100644
--- a/admin/WebConsole3/frontend/src/app/api/software-type.service.ts
+++ b/admin/WebConsole3/frontend/src/app/api/software-type.service.ts
@@ -1,20 +1,36 @@
-import { Injectable } from '@angular/core';
-import { HttpClient} from '@angular/common/http';
+import {Injectable} from '@angular/core';
+import {HttpClient} from '@angular/common/http';
-import { environment } from '../../environments/environment';
-import { SoftwareType } from "../model/software-type";
-import { SoftwareTypeSerializer } from "../serializer/software-type.serializer";
+import {environment} from '../../environments/environment';
+import {SoftwareType} from '../model/software-type';
+import {SoftwareTypeSerializer} from '../serializer/software-type.serializer';
-import {ResourceService} from "globunet-angular/core/providers/api/resource.service";
+import {ResourceService} from 'globunet-angular/core/providers/api/resource.service';
+import {QueryOptions} from 'globunet-angular/core/providers/api/query-options';
+import {Observable} from 'rxjs';
+import {OgCommonService} from '../service/og-common.service';
@Injectable({
- providedIn: 'root'
+ providedIn: 'root'
})
export class SoftwareTypeService extends ResourceService<SoftwareType> {
- constructor(http: HttpClient){
- super(http, environment.API_URL,"softwaretypes", new SoftwareTypeSerializer());
- }
+ constructor(http: HttpClient, private ogCommonService: OgCommonService) {
+ super(http, environment.API_URL, 'softwaretypes', new SoftwareTypeSerializer());
+ }
+
+ list(queryOptions?: QueryOptions): Observable<SoftwareType[]> {
+ return new Observable<SoftwareType[]>((observer) => {
+ this.ogCommonService.loadEngineConfig().subscribe(
+ data => {
+ observer.next(data.constants.sofwaretypes);
+ },
+ error => {
+ observer.error(error);
+ }
+ );
+ });
+ }
}
diff --git a/admin/WebConsole3/frontend/src/app/core/header-inner/header-inner.component.html b/admin/WebConsole3/frontend/src/app/core/header-inner/header-inner.component.html
index 31b4286d..23cdb7e0 100644
--- a/admin/WebConsole3/frontend/src/app/core/header-inner/header-inner.component.html
+++ b/admin/WebConsole3/frontend/src/app/core/header-inner/header-inner.component.html
@@ -9,7 +9,7 @@
</mk-dropdown-toggle>
<mk-dropdown-menu>
<li class="header" *ngIf="executionTasks.length > 0">
- <span translate="you_have_x_exectution_taks" translate-values="{values: executionTasks.length}"></span>
+ <span translate="you_have_x_exectution_taks" [translateParams]="{values: executionTasks.length}"></span>
</li>
<li *ngIf="executionTasks.length > 0">
<!-- inner menu: contains the actual data -->
@@ -21,7 +21,7 @@
</a>
<a href="javascript:void(0)" (click)="relaunchExecutionTask(task)" class="btn btn-sm pull-right small-box-footer">
<i class="fa fa-refresh"></i>
- </a>A
+ </a>
</div>
<a href="javascript:void(0)" (click)="ogCommandsService.execute('REALTIME_LOG', {clientIp: task.client.ip})">
<i class="fa fa-warning text-yellow"></i> {{task.client.name}} ({{task.client.ip}})<br>{{task.commandType|translate}}
diff --git a/admin/WebConsole3/frontend/src/app/form-type/software-profile.form-type.ts b/admin/WebConsole3/frontend/src/app/form-type/software-profile.form-type.ts
new file mode 100644
index 00000000..baa16afe
--- /dev/null
+++ b/admin/WebConsole3/frontend/src/app/form-type/software-profile.form-type.ts
@@ -0,0 +1,12 @@
+import {GlobunetFormType} from './globunet.form-type';
+import {SoftwareProfile} from '../model/software-profile';
+
+
+export class SoftwareProfileFormType extends GlobunetFormType {
+ getForm() {
+ const formType = GlobunetFormType.getForm(new SoftwareProfile());
+ this.setFieldType(formType, 'description', 'textarea');
+ this.removeField(formType, 'softwares');
+ return formType;
+ }
+}
diff --git a/admin/WebConsole3/frontend/src/app/model/command.ts b/admin/WebConsole3/frontend/src/app/model/command.ts
index 2c5697aa..5fc44734 100644
--- a/admin/WebConsole3/frontend/src/app/model/command.ts
+++ b/admin/WebConsole3/frontend/src/app/model/command.ts
@@ -1,9 +1,10 @@
import { Resource } from 'globunet-angular/core/models/api/resource';
-export class Excecution {
+export class Execution {
script = '';
clients = '';
type = '';
+ sendConfig = false;
}
export class Command extends Resource {
diff --git a/admin/WebConsole3/frontend/src/app/model/software-profile.ts b/admin/WebConsole3/frontend/src/app/model/software-profile.ts
index 5b3ba732..6d411f20 100644
--- a/admin/WebConsole3/frontend/src/app/model/software-profile.ts
+++ b/admin/WebConsole3/frontend/src/app/model/software-profile.ts
@@ -1,6 +1,8 @@
-import { Resource } from 'globunet-angular/core/models/api/resource';
-
-export class SoftwareProfile extends Resource {
- description: string;
- comments: string;
-}
+import { Resource } from 'globunet-angular/core/models/api/resource';
+import {SoftwareComponent} from './software-component';
+
+export class SoftwareProfile extends Resource {
+ description = '';
+ comments = '';
+ public softwares: SoftwareComponent[] = [];
+}
diff --git a/admin/WebConsole3/frontend/src/app/pages/command/create-image-command/create-image-command.component.ts b/admin/WebConsole3/frontend/src/app/pages/command/create-image-command/create-image-command.component.ts
index 8f018e33..e97d20fa 100644
--- a/admin/WebConsole3/frontend/src/app/pages/command/create-image-command/create-image-command.component.ts
+++ b/admin/WebConsole3/frontend/src/app/pages/command/create-image-command/create-image-command.component.ts
@@ -10,7 +10,7 @@ import {User} from '../../../model/user';
import {OGCommandsService} from '../../../service/og-commands.service';
import {CommandService} from '../../../api/command.service';
import {Image} from '../../../model/image';
-import {Command, Excecution} from '../../../model/command';
+import {Command, Execution} from '../../../model/command';
import {Client, Partition} from '../../../model/client';
import {Repository} from '../../../model/repository';
import {RepositoryService} from '../../../api/repository.service';
@@ -26,7 +26,7 @@ export class CreateImageCommandComponent implements OnInit {
private readonly user: User;
private constants: any;
public repositories: Repository[];
- public execution = new Excecution();
+ public execution = new Execution();
public commands: Command[] = [];
public client: Client;
public images = [];
diff --git a/admin/WebConsole3/frontend/src/app/pages/command/delete-cache-image-command/delete-cache-image-command.component.ts b/admin/WebConsole3/frontend/src/app/pages/command/delete-cache-image-command/delete-cache-image-command.component.ts
index efc14d6d..fb238868 100644
--- a/admin/WebConsole3/frontend/src/app/pages/command/delete-cache-image-command/delete-cache-image-command.component.ts
+++ b/admin/WebConsole3/frontend/src/app/pages/command/delete-cache-image-command/delete-cache-image-command.component.ts
@@ -10,7 +10,7 @@ import {User} from '../../../model/user';
import {OGCommandsService} from '../../../service/og-commands.service';
import {CommandService} from '../../../api/command.service';
import {Image} from '../../../model/image';
-import {Command, Excecution} from '../../../model/command';
+import {Command, Execution} from '../../../model/command';
import {Client} from '../../../model/client';
import {Repository} from '../../../model/repository';
import {RepositoryService} from '../../../api/repository.service';
@@ -25,7 +25,7 @@ export class DeleteCacheImageCommandComponent implements OnInit {
private readonly user: User;
private constants: any;
public repositories: Repository[];
- public execution = new Excecution();
+ public execution = new Execution();
public commands: Command[] = [];
public client: Client;
public cacheImages = [];
@@ -102,9 +102,9 @@ export class DeleteCacheImageCommandComponent implements OnInit {
this.execution.script += '\n';
}
}
- this.execution.script += this.constants.commands.REFRESH_INFO + '\n';
this.execution.script = this.execution.script.replace(/\"/g, '\\"').replace(/\$/g, '\\\$');
this.execution.type = 'RUN_SCRIPT';
+ this.execution.sendConfig = true;
this.commandService.execute(this.execution).subscribe(
(response) => {
diff --git a/admin/WebConsole3/frontend/src/app/pages/command/format-command/format-command.component.ts b/admin/WebConsole3/frontend/src/app/pages/command/format-command/format-command.component.ts
index 62b733b8..05b3ebfe 100644
--- a/admin/WebConsole3/frontend/src/app/pages/command/format-command/format-command.component.ts
+++ b/admin/WebConsole3/frontend/src/app/pages/command/format-command/format-command.component.ts
@@ -11,6 +11,7 @@ import {OGCommandsService} from '../../../service/og-commands.service';
import {Client, Partition} from '../../../model/client';
import {CommandService} from '../../../api/command.service';
import {forkJoin} from 'rxjs';
+import {Execution} from '../../../model/command';
@Component({
selector: 'app-format-command',
@@ -18,7 +19,7 @@ import {forkJoin} from 'rxjs';
styleUrls: [ './format-command.component.scss' ]
})
export class FormatCommandComponent implements OnInit {
- execution = {clients: '', script: '', type: ''};
+ execution = new Execution();
command = {};
user: User;
clientGroups = {};
@@ -85,10 +86,7 @@ export class FormatCommandComponent implements OnInit {
const groups = Object.keys(this.clientGroups);
for (let g = 0; g < groups.length; g++) {
if (!executions[g]) {
- executions[g] = {
- clients: '',
- script: ''
- };
+ executions[g] = new Execution();
}
// Recorrer las particiones del primer cliente de la lista y ver si hay alguna seleccionada
const found = false;
@@ -101,7 +99,7 @@ export class FormatCommandComponent implements OnInit {
while (!found && index < client.partitions.length) {
const partition = client.partitions[index];
if (partition.selected === true) {
- if(executions[g].script === '') {
+ if (executions[g].script === '') {
executions[g].script = 'ogUnmountAll ' + partition.numDisk + '\n';
}
// Si la particion es cache
@@ -122,7 +120,8 @@ export class FormatCommandComponent implements OnInit {
const execution = {
type: 'RUN_SCRIPT',
script: executions[index].script,
- clients: executions[index].clients.substring(0, executions[index].clients.length - 1) // Quitar la ultima ","
+ clients: executions[index].clients.substring(0, executions[index].clients.length - 1), // Quitar la ultima ","
+ sendConfig: true
};
promises.push(this.commandService.execute(execution));
}
diff --git a/admin/WebConsole3/frontend/src/app/pages/command/partition-format-command/partition-format-command.component.scss b/admin/WebConsole3/frontend/src/app/pages/command/partition-format-command/partition-format-command.component.scss
index 97d2231d..ec120f1f 100644
--- a/admin/WebConsole3/frontend/src/app/pages/command/partition-format-command/partition-format-command.component.scss
+++ b/admin/WebConsole3/frontend/src/app/pages/command/partition-format-command/partition-format-command.component.scss
@@ -12,11 +12,13 @@
right: 0;
margin: 0;
background-color: black;
- width: 2px;
+ width: 4px;
height: 100%;
padding: 0 !important;
cursor: col-resize;
border: 1px solid transparent;
}
-
+ table.disk-partitions td:last-child span.resizer:last-child {
+ display: none;
+ }
}
diff --git a/admin/WebConsole3/frontend/src/app/pages/command/partition-format-command/partition-format-command.component.ts b/admin/WebConsole3/frontend/src/app/pages/command/partition-format-command/partition-format-command.component.ts
index 8c75fa2e..eb36930a 100644
--- a/admin/WebConsole3/frontend/src/app/pages/command/partition-format-command/partition-format-command.component.ts
+++ b/admin/WebConsole3/frontend/src/app/pages/command/partition-format-command/partition-format-command.component.ts
@@ -12,6 +12,7 @@ import {CommandService} from '../../../api/command.service';
import {DomSanitizer} from '@angular/platform-browser';
import {ChartOptions} from 'chart.js';
import {Client} from '../../../model/client';
+import {Execution} from '../../../model/command';
@Component({
selector: 'app-partition-format-command',
@@ -19,7 +20,7 @@ import {Client} from '../../../model/client';
styleUrls: [ './partition-format-command.component.scss' ]
})
export class PartitionFormatCommandComponent implements OnInit {
- execution = {clients: '', script: '', type: ''};
+ execution = new Execution();
command = {};
user: User;
constants: any;
diff --git a/admin/WebConsole3/frontend/src/app/pages/software-profile/software-profile.component.html b/admin/WebConsole3/frontend/src/app/pages/software-profile/software-profile.component.html
index 4cb0f6e5..0a9abe16 100644
--- a/admin/WebConsole3/frontend/src/app/pages/software-profile/software-profile.component.html
+++ b/admin/WebConsole3/frontend/src/app/pages/software-profile/software-profile.component.html
@@ -1 +1,83 @@
-<div>Html template for class SoftwareProfile</div> \ No newline at end of file
+<section class="content-header">
+ <h1 translate="software">
+ </h1>
+ <ol class="breadcrumb">
+ <li><a href="#/app/dashboard"><i class="fa fa-dashboard"></i> {{'dashboard'|translate}}</a></li>
+ <li><a href="#/app/software"><i class="fa fa-server"></i> {{'software'|translate}}</a></li>
+ <li class="active" translate="software_profile"></li>
+ </ol>
+</section>
+<section fixed-toolboxbar class="toolboxbar">
+ <div>
+ <div class="col-md-12">
+ <div class="box-tools pull-right">
+ <button class="btn btn-primary" translate="save" (click)="save(Form)"></button>
+ </div>
+ </div>
+ </div>
+</section>
+<section class="content">
+ <div class="row">
+ <div class="col-md-6">
+ <div class="box box-primary">
+ <div class="box-header with-border">
+ <h3 *ngIf="!softwareProfile.id" class="box-title" translate="new_software_profile"></h3>
+ <h3 *ngIf="softwareProfile.id" class="box-title" translate="software_profile"></h3>
+ </div>
+ <div class="box-body">
+ <form role="form" name="Form">
+ <app-form-input [cols]="1" [model]="softwareProfile" [formType]="formType"></app-form-input>
+ </form>
+ </div>
+ <div class="box-footer">
+ </div>
+ </div>
+ </div>
+ <div class="col-md-6">
+ <div class="box box-primary">
+ <div class="box-header with-border">
+ <h4 translate="software_profile_components"></h4>
+ <div class="input-group">
+ <input type="text" name="q" class="form-control" placeholder="Search..."
+ [(ngModel)]="searchText">
+ <span class="input-group-btn">
+ <button type="button" name="search" id="search-btn" class="btn btn-flat"><i
+ class="fa fa-search"></i>
+ </button>
+ </span>
+ </div>
+ </div>
+ <div class="box-body">
+ <table class="table table-hover">
+ <tbody>
+ <tr>
+ <th translate="select"></th>
+ <th translate="description"></th>
+ <th translate="type"></th>
+ </tr>
+ <tr *ngFor="let softwareComponent of softwareComponents; let index = index"
+ class="(index%2 == 0)?'odd':'even'">
+ <td>
+ <input icheck checkbox-class="icheckbox_square-blue" radio-class="iradio_square-blue"
+ type="checkbox" class="selection-checkbox"
+ [(ngModel)]="softwareComponent.$$selected"
+ (change)="ogCommonService.checkUnchekComponent(softwareProfile, softwareComponent)"/>
+ </td>
+ <td>
+ <span>
+ {{softwareComponent.description}}
+ </span>
+ </td>
+ <td>
+ <span>
+ {{softwareComponent.type ? softwareComponent.type.name : '-'}}
+ </span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ </div>
+</section>
diff --git a/admin/WebConsole3/frontend/src/app/pages/software-profile/software-profile.component.ts b/admin/WebConsole3/frontend/src/app/pages/software-profile/software-profile.component.ts
index bff05a1c..b34cfb77 100644
--- a/admin/WebConsole3/frontend/src/app/pages/software-profile/software-profile.component.ts
+++ b/admin/WebConsole3/frontend/src/app/pages/software-profile/software-profile.component.ts
@@ -1,17 +1,100 @@
-import { Component } from '@angular/core';
-
-import { SoftwareProfileService } from 'src/app/api/software-profile.service';
-import { SoftwareProfile } from 'src/app/model/software-profile';
-
-@Component({
- selector: 'software-profile',
- templateUrl: './software-profile.component.html',
- styleUrls: [ './software-profile.component.scss' ]
-})
-export class SoftwareProfileComponent {
- // this tells the tabs component which Pages
- // should be each tab's root Page
- constructor(public softwareProfileService: SoftwareProfileService) {
- }
-
-}
+import {Component, OnInit} from '@angular/core';
+
+import { SoftwareProfileService } from 'src/app/api/software-profile.service';
+import {ParamMap, ActivatedRoute, Router} from '@angular/router';
+import {SoftwareProfile} from '../../model/software-profile';
+import {ToasterService} from '../../service/toaster.service';
+import {SoftwareComponentService} from '../../api/software-component.service';
+import {SoftwareComponent} from '../../model/software-component';
+import {SoftwareProfileFormType} from '../../form-type/software-profile.form-type';
+import {OgCommonService} from '../../service/og-common.service';
+
+@Component({
+ selector: 'app-software-profile',
+ templateUrl: './software-profile.component.html',
+ styleUrls: [ './software-profile.component.scss' ]
+})
+export class SoftwareProfileComponent implements OnInit {
+ public softwareProfile: SoftwareProfile = new SoftwareProfile();
+ public softwareComponents: SoftwareComponent[];
+ formType: any;
+ // this tells the tabs component which Pages
+ // should be each tab's root Page
+ constructor(public ogCommonService: OgCommonService, public softwareProfileService: SoftwareProfileService,
+ public softwareComponentsService: SoftwareComponentService, private routerCtrl: Router,
+ private router: ActivatedRoute, private toaster: ToasterService) {
+ this.formType = new SoftwareProfileFormType().getForm();
+ }
+
+ ngOnInit(): void {
+ this.softwareComponentsService.list().subscribe(
+ components => {
+ this.softwareComponents = components;
+ this.router.paramMap.subscribe(
+ (params: ParamMap) => {
+ if(params.get('id')) {
+ this.softwareProfileService.read(Number(params.get('id'))).subscribe(
+ data => {
+ this.softwareProfile = data;
+ const self = this;
+ // Seleccionar los componentes adecuados
+ this.softwareComponents.forEach(function(component, index, array) {
+ if ( self.softwareProfile.softwares.find((value) => value.id === component.id)) {
+ // @ts-ignore
+ component.$$selected = true;
+ }
+ });
+ },
+ error => {
+ this.toaster.pop({type: 'error', body: 'error_loading_software_profile', title: 'error'});
+ }
+ );
+ } else {
+ this.softwareProfile = new SoftwareProfile();
+ }
+ }
+ );
+ },
+ error => {
+ this.toaster.pop({type: 'error', body: 'error_loading_software_components', title: 'error'});
+ }
+ );
+
+ }
+
+ save() {
+ this.softwareProfile.softwares = [];
+ const self = this;
+ this.softwareComponents.forEach(function(component, index, array) {
+ // @ts-ignore
+ if (component.$$selected === true) {
+ // @ts-ignore
+ self.softwareProfile.softwares.push(component.id);
+ }
+ });
+ // Actualizar o guardar
+ let request;
+ if(this.softwareProfile.id !== 0){
+ request = this.softwareProfileService.update(this.softwareProfile);
+ }
+ else{
+ request = this.softwareProfileService.create(this.softwareProfile);
+ }
+ request.subscribe(
+ (response) => {
+ this.toaster.pop({type: 'success', title: 'success', body: 'successfully_saved'});
+ this.routerCtrl.navigate(['/app/software']).then(
+ success => {
+ console.log(success);
+ },
+ error => {
+ console.log(error);
+ }
+ );
+ },
+ (error) => {
+ this.toaster.pop({type: 'error', title: 'error', body: error});
+ }
+ );
+ }
+}
diff --git a/admin/WebConsole3/frontend/src/app/service/og-commands.service.ts b/admin/WebConsole3/frontend/src/app/service/og-commands.service.ts
index 1ea33faa..6b54a896 100644
--- a/admin/WebConsole3/frontend/src/app/service/og-commands.service.ts
+++ b/admin/WebConsole3/frontend/src/app/service/og-commands.service.ts
@@ -39,9 +39,16 @@ export class OGCommandsService {
this.commandService.execute(this.execution).subscribe(
(response: any[]) => {
// Buscar en la respuesta si hay algún statuscode diferente de 200
- const errors = response.filter(function(value) {
- return (value.statusCode && value.statusCode !== '!200');
- } );
+ const errors = [];
+ const keys = Object.keys(response);
+ keys.forEach((index) => {
+ const elemKeys = Object.keys(response[index]);
+ elemKeys.forEach((elemKey) => {
+ if (elemKey === 'statusCode' && response[index][elemKey] !== 200) {
+ errors.push(response[index]);
+ }
+ });
+ });
let errorStr = '';
let toasterOpts = {type: 'success', title: 'success', body: this.translate.instant('successfully_executed')};
if (errors.length > 0) {
@@ -116,7 +123,7 @@ export class OGCommandsService {
// Crear como nombre para mostrar, el disco y partición del sistema
const obj = Object.assign({}, client.partitions[index]);
const str = 'disco: ' + obj.numDisk + ', part: ' + obj.numPartition + ', SO: ' + client.partitions[index].osName;
- clonablePartitions.push(obj.numDisk + ' ' + obj.numPartition)
+ clonablePartitions.push(obj.numDisk + ' ' + obj.numPartition);
options.scope.partitions.push(str);
}
}
diff --git a/admin/WebConsole3/frontend/src/app/service/og-common.service.ts b/admin/WebConsole3/frontend/src/app/service/og-common.service.ts
index b529199d..3de25304 100644
--- a/admin/WebConsole3/frontend/src/app/service/og-common.service.ts
+++ b/admin/WebConsole3/frontend/src/app/service/og-common.service.ts
@@ -198,15 +198,13 @@ export class OgCommonService {
}
saveSelection() {
- if (Object.keys(this.selectedClients).length > 0) {
- localStorage.setItem('selectedClients', JSON.stringify(this.selectedClients, function (key, value) {
- let result = value;
- if (key === 'parent' && typeof value === 'object') {
- result = value.id;
- }
- return result;
- }));
- }
+ localStorage.setItem('selectedClients', JSON.stringify(this.selectedClients, function (key, value) {
+ let result = value;
+ if (key === 'parent' && typeof value === 'object') {
+ result = value.id;
+ }
+ return result;
+ }));
}
getSelectionSize() {
diff --git a/admin/WebConsole3/frontend/src/environments/environment.ts b/admin/WebConsole3/frontend/src/environments/environment.ts
index 16b61e25..ef17e26d 100644
--- a/admin/WebConsole3/frontend/src/environments/environment.ts
+++ b/admin/WebConsole3/frontend/src/environments/environment.ts
@@ -1,7 +1,7 @@
// This file can be replaced during build by using the `fileReplacements` array.
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.
-const url = 'https://172.16.140.210/opengnsys3';
+const url = 'https://SERVERIP/opengnsys3';
export const environment = {
production: false,
BASE_URL: url,
@@ -9,8 +9,8 @@ export const environment = {
API_PUBLIC_URL: url + '/api',
API_BASE_URL: '/backend/web/app_dev.php/api',
OAUTH_DOMAIN: '/backend/web/app_dev.php/oauth/v2/token',
- OAUTH_CLIENT_ID: '1_23amzbdp4kskg80444oscko4w0w8wokocs88k0g8w88o4oggs4',
- OAUTH_CLIENT_SECRET: '46rttt2trwo4gocgoc4w80k4s8ok48sg8s84kk0cw48csks8o8',
+ OAUTH_CLIENT_ID: 'CLIENTID',
+ OAUTH_CLIENT_SECRET: 'CLIENTSECRET',
BASE_DIR: 'opengnsys3',
clientstatus: ['off', 'initializing', 'oglive', 'busy', 'linux', 'linux_session', 'macos', 'windows', 'windows_session'],
windowsboots: ['reboot', 'directo (kexec)'],
diff --git a/installer/vagrant/Vagrantfile-webconsole3-vbox b/installer/vagrant/Vagrantfile-webconsole3-vbox
new file mode 100644
index 00000000..6cf4f037
--- /dev/null
+++ b/installer/vagrant/Vagrantfile-webconsole3-vbox
@@ -0,0 +1,171 @@
+# Vagrantfile to prepare virtual environment using VirtualBox provider to develop new AngularJS-based web interface.
+
+VAGRANTFILE_API_VERSION = "2"
+ENV['VAGRANT_DEFAULT_PROVIDER'] = "virtualbox"
+LANGUAGE = "es_ES"
+ENV['LC_ALL'] = LANGUAGE + ".UTF-8"
+SERVERMEM = 2048
+SERVERCPUS = 2
+CLIENTMEM = 512
+NCLIENTS = 4
+REPODISK = "repo.vdi"
+REPOSIZE = 50
+MACPREFIX = "08:00:27:0e:65"
+NETPREFIX = "192.168.2"
+SERVERIP = "#{NETPREFIX}.10"
+LOCALWEBPORT = 8443
+
+
+# OpenGnsys Server provisioning script.
+SCRIPT = <<EOT
+# Set language.
+export LANG="#{LANGUAGE}.UTF-8"
+echo "LANG=\"$LANG\"" > /etc/default/locale
+echo "LANG=\"$LANG\"" >> /etc/environment
+echo "LANGUAGE=\"$LANG\"" >> /etc/environment
+echo "LC_ALL=\"$LANG\"" >> /etc/environment
+echo "LC_CTYPE=\"$LANG\"" >> /etc/environment
+locale-gen --lang #{LANGUAGE}
+sed -i "s/XKBLAYOUT=.*/XKBLAYOUT=\"${LANG%_*}\"/" /etc/default/keyboard
+dpkg-reconfigure -fnoninteractive console-setup
+# Exit if OpenGnsys is installed.
+[ -f /opt/opengnsys/doc/VERSION.json ] && echo "Cannot provision, OpenGnsys is alread
+y installed." && exit 1
+# Create repository disk using LVM, if necesary.
+if [ -z "$(blkid /dev/mapper/og-images | grep ext4)" ]; then
+ pvcreate /dev/sdb
+ vgcreate og /dev/sdb
+ vgchange -ay
+ lvcreate -ay -n images -l 100%VG og
+ mkfs -t ext4 /dev/mapper/og-images
+ mkdir -p /opt/opengnsys/images
+ echo "/dev/mapper/og-images /opt/opengnsys/images ext4 defaults 0 0" >> /etc/fstab
+ mount -a
+fi
+# Update repositories.
+add-apt-repository -y ppa:webupd8team/atom
+apt-get update
+# Install main dependencies.
+apt-get install -y xfce4 gnome-icon-theme-full tango-icon-theme linux-headers-$(uname -r) firefox atom virtualbox-guest-dkms virtualbox-guest-utils virtualbox-guest-x11
+echo "allowed_users=anybody" > /etc/X11/Xwrapper.config
+# Install OpenGnsys Server
+tar xpvzf /vagrant/opengnsys3.tar.gz -C /tmp
+/tmp/opengnsys/installer/opengnsys_installer.sh
+echo y | /opt/opengnsys/bin/setserveraddr eth1
+# Configure the virtual lab.
+read -e APIID APISECRET <<<$(/opt/opengnsys/www3/backend/app/console doctrine:query:sql "SELECT random_id, secret FROM og_core__clients WHERE id=1;" | awk -F\\" '$2~/^(random_id|secret)$/ {getline; printf("%s ", $2)}')
+rm -fr /opt/opengnsys/www3/backend/var/cache/*
+REQ=$(curl -sk 'https://localhost/opengnsys3/backend/web/app_dev.php/oauth/v2/token?client_id=1_'"$APIID"'&client_secret='"$APISECRET"'&grant_type=password&username=admin&password=admin')
+TOKEN="$(echo $REQ | jq -r .access_token)"
+REQ=$(curl -sk -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{"name":"Repositorio virtual", "ip":"#{SERVERIP}", "password":"'$(php -r 'echo md5(uniqid(rand(), true));')'", "configurationpath":"/", "adminpath":"/", "pxepath":"/", "port":0 }' https://localhost/opengnsys3/backend/web/app_dev.php/api/private/repositories)
+REPOID=$(echo $REQ | jq -r .id)
+REQ=$(curl -sk -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{"name":"Aula virtual", "description":"Despliegue virtual con Vagrant.", "networkSettings":{"mcastMode":"full-duplex", "mcastIp":"239.194.2.11", "mcastPort":9000, "mcastPort":9000, "mcastSpeed":100, "netmask":"#{NETPREFIX}.0", "router":"#{NETPREFIX}.1", "p2pMode":"peer", "p2pTime":60} }' https://localhost/opengnsys3/backend/web/app_dev.php/api/private/organizationalunits)
+OUID=$(echo $REQ | jq -r .id)
+for ((i=11; i<=10+#{NCLIENTS}; i++)); do
+ sed -i "/^}$/ i host pc${i} { hardware ethernet #{MACPREFIX}:${i}; fixed-address #{NETPREFIX}.${i}; }" /etc/dhcp/dhcpd.conf
+ [ $i == 11 ] && BOOTID=5 || BOOTID=6
+ REQ=$(curl -sk -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{"name":"pc'$i'", "ip":"#{NETPREFIX}.'$i'", "mac":"#{MACPREFIX}:'$i'", "serialno":"", "netiface":"eth0", "netdriver":"generic", "netboot":'"$BOOTID"', "organizationalUnit":'"$OUID"', "repository":'"$REPOID"'}' https://localhost/opengnsys3/backend/web/app_dev.php/api/private/clients)
+done
+systemctl restart isc-dhcp-server
+#/opt/opengnsys/bin/setclientmode ogLiveAdmin pc11 PERM
+#for ((i=12; i<=#{NCLIENTS+10}; i++)); do
+# /opt/opengnsys/bin/setclientmode ogLive pc$i PERM
+#done
+sed -i "s,\(url = 'https://\)[^/]*,\1localhost:#{LOCALWEBPORT}," /opt/opengnsys/www3/frontend/main.js
+sed -i "s,\(url = 'https://\)[^/]*,\1localhost:#{LOCALWEBPORT}," /opt/opengnsys/www3/frontend/main.js.map
+echo "Notes:"
+echo "- New OpenGnsys Server URL: https://localhost:#{LOCALWEBPORT}/opengnsys3/frontend/"
+EOT
+
+# Client 1 OS provisioning script.
+OGAGENTPKG = "ogagent_1.1.1_all.deb"
+MODELSCRIPT = <<EOT
+# Comment out next lines to install and configure OGAgent for Ubuntu.
+apt-get update -y
+apt-get install -y curl
+curl -ks https://#{SERVERIP}/opengnsys/descargas/#{OGAGENTPKG} -o /tmp/#{OGAGENTPKG}
+if [ -f /tmp/#{OGAGENTPKG} ]; then
+ apt-get install -y /tmp/#{OGAGENTPKG} || exit $?
+ sed -i "0,/remote=/ s,remote=.*,remote=https://#{SERVERIP}/opengnsys/rest/," /usr/share/OGAgent/cfg/ogagent.cfg
+ rm -f /tmp/#{OGAGENTPKG}
+else
+ echo "Warning: cannot install OGAgent package #{OGAGENTPKG}"
+fi
+# Remove network configuration added by Vagrant.
+sed -i "/eth1/ d" /etc/network/interfaces
+echo "Notes:"
+echo "- After now, use VirtualBox GUI to disable network interface 1 and restart this VM."
+# Leave VM halted.
+sleep 2
+poweroff &
+EOT
+
+Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
+
+ # OpenGnsys AngularJS VM definition.
+ config.vm.define "ogAngular", primary: true do |ag|
+ # Specific VirtualBox configuration.
+ ag.vm.provider "virtualbox" do |vb|
+ # VM name, memory and CPUs.
+ vb.name = "ogAngular"
+ vb.memory = SERVERMEM
+ vb.cpus = SERVERCPUS
+ # 2nd virtual disk path (current dir on Windows, VM dir on other OSes)
+ if Vagrant::Util::Platform.windows? then
+ second_disk = File.join(".", REPODISK)
+ else
+ line = `VBoxManage list systemproperties`.match("Default machine folder.*")[0]
+ vb_machine_folder = line.split(':')[1].strip()
+ second_disk = File.join(vb_machine_folder, vb.name, REPODISK)
+ end
+ # Create repo virtual disk, if needed.
+ unless File.exist?(second_disk)
+ vb.customize ['createhd', '--filename', second_disk, '--size', REPOSIZE * 1024]
+ end
+ # Attach repo virtual disk.
+ vb.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium', second_disk]
+ end
+ # VM base and host name.
+ ag.vm.box = "bento/ubuntu-18.04"
+ ag.vm.hostname = "ogAngular"
+ # Network settings.
+ ag.vm.network "forwarded_port", guest: 443, host: LOCALWEBPORT, host_ip: "127.0.0.1"
+ ag.vm.network "private_network", mac: "#{MACPREFIX}10".tr(":",""), ip: "#{SERVERIP}", virtualbox__intnet: true
+ # Launch provisioning script.
+ ag.vm.provision "shell", inline: SCRIPT
+ end
+
+ # Client 1 VM definition.
+ config.vm.define "pc11", autostart: false do |v1|
+ v1.vm.box = "bento/ubuntu-18.04"
+ v1.vm.hostname = "pc11"
+ v1.vm.network "private_network", mac: "#{MACPREFIX}11".tr(":",""), type: "dhcp", virtualbox__intnet: true
+ v1.vm.provider "virtualbox" do |vb|
+ vb.name = "pc11"
+ vb.memory = CLIENTMEM
+ vb.cpus = 1
+ vb.customize ['modifyvm', :id, '--boot1', 'net', '--boot2', 'disk']
+ end
+ v1.vm.synced_folder ".", "/vagrant", disabled: true
+ v1.vm.provision "shell", inline: MODELSCRIPT
+ end
+
+ # Clonable clients definition.
+ (2..NCLIENTS).each do |i|
+ config.vm.define "pc#{i+10}", autostart: false do |cl|
+ cl.vm.box = "clink15/pxe"
+ cl.ssh.insert_key = false
+ cl.vm.boot_timeout = 5
+ cl.vm.network "private_network", mac: "#{MACPREFIX}#{i+10}".tr(":",""), type: "dhcp", virtualbox__intnet: true
+ cl.vm.provider "virtualbox" do |vb|
+ vb.name = "pc#{i+10}"
+ vb.memory = CLIENTMEM
+ vb.cpus = 1
+ vb.customize ['modifyvm', :id, '--boot1', 'net', '--boot2', 'disk']
+ vb.customize ["modifyvm", :id, "--nic1", "none"]
+ end
+ end
+ end
+
+end
+
diff --git a/server/bin/setserveraddr b/server/bin/setserveraddr
index eb52d64d..a979595f 100755
--- a/server/bin/setserveraddr
+++ b/server/bin/setserveraddr
@@ -22,7 +22,7 @@
PROG="$(basename "$0")"
OPENGNSYS=/opt/opengnsys
PXEDIR=$OPENGNSYS/tftpboot/menu.lst
-DEFAULTFILE=/etc/default/opengnsys
+CONFIGFILE=$OPENGNSYS/etc/opengnsys.json
# Checking parameters.
if [ $# -ne 1 ]; then
@@ -56,8 +56,7 @@ done
if [ -n "$SERVERIP" ]; then
# Temporary files.
tmpfile=$(mktemp /tmp/og.XXXXX)
- MYCNF=$(mktemp /tmp/.my.cnf.XXXXX)
- trap "rm -f $tmpfile $MYCNF" 1 2 3 6 9 15
+ trap "rm -f $tmpfile" 1 2 3 6 9 15
# Checking whether the DHCP settings need to be changed.
CHANGE=0
@@ -85,73 +84,12 @@ if [ -n "$SERVERIP" ]; then
echo "DHCP configuration has not changed."
fi
- # Saving old IP address.
- source $OPENGNSYS/etc/ogAdmRepo.cfg
- OLDSERVERIP=$IPlocal
-
- # Checking if configuration files need to be modified.
- CHANGE=0
- for f in $OPENGNSYS/{etc/{ogAdmServer,ogAdmRepo,ogAdmAgent}.cfg,www/controlacceso.php,client/etc/ogAdmClient.cfg}; do
- # Error if configuration file cannot be found.
- if [ ! -f $f ]; then
- echo "$PROG: File $file does not exist." >&2
- exit 2
- fi
- # Updating configuration variables (if URLs does not contain "localhost").
- sed -e "s,ServidorAdm=.*,ServidorAdm=$SERVERIP," \
- -e "s,IPlocal=.*,IPlocal=$SERVERIP," \
- -e "s,UrlMenu=https?://\([^/]*\)/\(.*\),UrlMenu=https://$SERVERIP/\2," \
- -e '/localhost/!s,https\?://[^/]*/\(.*\),https://'$SERVERIP'/\1,' $f >$tmpfile
- file="${f/./-$SERVERDEV.}"
- # Copying updated file, if needed.
- if [ ! $f -ef $file ] || ! diff -q $tmpfile $file &>/dev/null; then
- cp $tmpfile $file
- ln -f $file $f
- CHANGE=1
- fi
- done
-
- # Processing when something has changed.
- if [ $CHANGE == 1 ]; then
- # Restart OpenGnsys services.
- /etc/init.d/opengnsys restart
- # If Repository is active, generating a new API token.
- source $DEFAULTFILE
- if [ "$RUN_OGADMREPO" == "yes" ]; then
- REPOKEY=$(php -r 'echo md5(uniqid(rand(), true));')
- sed -i -e "s/ApiToken=.*/ApiToken=$REPOKEY/" $OPENGNSYS/etc/ogAdmRepo.cfg
- fi
- # If OpenGnsys Server is active, updating the database.
- if [ "$RUN_OGADMSERVER" == "yes" ]; then
- source $OPENGNSYS/etc/ogAdmServer.cfg
- # Creating credentials file.
- cat << EOT > $MYCNF
-[client]
-user=$USUARIO
-password=$PASSWORD
-EOT
- # Updating OpenGnsys Server IP address.
- mysql --defaults-extra-file=$MYCNF -D "$CATALOG" -e \
- "UPDATE entornos
- SET ipserveradm='$SERVERIP'
- WHERE identorno=1"
- # If OpenGnsys Repository is active, updating IP address and API token.
- if [ "$RUN_OGADMREPO" == "yes" ]; then
- mysql --defaults-extra-file=$MYCNF -D "$CATALOG" -e \
- "UPDATE repositorios
- SET ip='$SERVERIP', apikey='$REPOKEY'
- WHERE ip='$OLDSERVERIP'"
- unset REPOKEY
- fi
- # Updating all menu URLs.
- mysql --defaults-extra-file=$MYCNF -D "$CATALOG" -e \
- "UPDATE menus
- SET htmlmenupub = REPLACE(htmlmenupub, '$OLDSERVERIP', '$SERVERIP'),
- htmlmenupri = REPLACE(htmlmenupri, '$OLDSERVERIP', '$SERVERIP');"
- # Updating all PXE files.
- find $PXEDIR -name "01-*" -exec sed -i -e "s/$OLDSERVERIP/$SERVERIP/g" {} \;
- fi
-
+ OLDSERVERIP=$(jq -r .server.ip $CONFIGFILE)
+ if [ "$SERVERIP" != "$OLDSERVERIP" ]; then
+ # Updating configuration file.
+ jq ".server.ip=\"$SERVERIP\"" $CONFIGFILE | sponge $CONFIGFILE
+ # Updating all PXE files.
+ find $PXEDIR -name "01-*" -exec sed -i -e "s/$OLDSERVERIP/$SERVERIP/g" {} \;
# Showing manual task to do after execution.
cat << EOT
Default server interface set to: $SERVERDEV ($SERVERIP)
@@ -161,7 +99,6 @@ Manual tasks:
- Check PXE files.
- Log-in as Web Console user:
- Check menu URLs.
-${REPOKEY:+" - Update repository API token"}
EOT
else
# Showing message if nothing changes.
@@ -173,6 +110,6 @@ else
exit 1
fi
-# Removing temporary files.
-rm -f $tmpfile $MYCNF
+# Removing temporary file.
+rm -f $tmpfile