Пример #1
0
 /**
  * Method to add or replace the node metadata.
  * Editable attributes:
  * - config
  * - cpu
  * - delay
  * - ethernet
  * - icon
  * - idlepc
  * - image
  * - left
  * - name
  * - nvram
  * - ram
  * - serial
  * - slots
  * - top
  * If an attribute is set and is valid, then it will be used. If an
  * attribute is not set, then the original is maintained. If in attribute
  * is set and empty '', then the current one is deleted.
  *
  * @param   Array   $p                  Parameters
  * @return  int                         0 means ok
  */
 public function edit($p)
 {
     $modified = False;
     if (isset($p['config']) && $p['config'] === '') {
         // Config is empty, unset the current one
         unset($this->config);
         $modified = True;
     } else {
         if (isset($p['config']) && !checkNodeConfig($p['config'])) {
             // Config is invalid, ingored
             error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40003]);
         } else {
             if (isset($p['config'])) {
                 $this->config = $p['config'];
                 $modified = True;
             }
         }
     }
     if (isset($p['delay']) && $p['delay'] === '') {
         // Delay is empty, unset the current one
         unset($this->delay);
         $modified = True;
     } else {
         if (isset($p['delay']) && (int) $p['delay'] < 0) {
             // Delay is invalid, ignored
             error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40004]);
         } else {
             if (isset($p['delay'])) {
                 $this->delay = (int) $p['delay'];
             }
         }
     }
     if (isset($p['icon']) && $p['icon'] === '') {
         // Icon is empty, unset the current one
         unset($this->icon);
         $modified = True;
     } else {
         if (isset($p['icon']) && !checkNodeIcon($p['icon'])) {
             // Icon is invalid, ignored
             error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40005]);
         } else {
             if (isset($p['icon'])) {
                 $this->icon = $p['icon'];
             }
         }
     }
     if (isset($p['image']) && ($p['image'] === '' || !checkNodeImage($p['image'], $p['type'], $p['template']))) {
         // Image is not valid, ignored
         error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40006]);
     } else {
         if (isset($p['image'])) {
             $this->image = $p['image'];
             $modified = True;
         }
     }
     if (isset($p['left']) && $p['left'] === '') {
         // Left is empty, unset the current one
         unset($this->left);
         $modified = True;
     } else {
         if (isset($p['left']) && !checkPosition($p['left'])) {
             // Left is not valid, ignored
             error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40007]);
         } else {
             if (isset($p['left'])) {
                 $this->left = $p['left'];
                 $modified = True;
             }
         }
     }
     if (isset($p['name']) && $p['name'] === '') {
         // Name is empty, unset the current one
         unset($this->name);
         $modified = True;
     } else {
         if (isset($p['name']) && !checkNodeName($p['name'])) {
             // Name is not valid, ignored
             error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40008]);
         } else {
             if (isset($p['name'])) {
                 $this->name = $p['name'];
                 $modified = True;
             }
         }
     }
     if (isset($p['top']) && $p['top'] === '') {
         // Top is empty, unset the current one
         unset($this->top);
         $modified = True;
     } else {
         if (isset($p['top']) && !checkPosition($p['top'])) {
             // Top is not valid, ignored
             error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40010]);
         } else {
             if (isset($p['top'])) {
                 $this->top = $p['top'];
                 $modified = True;
             }
         }
     }
     // Specific parameters
     if ($this->type == 'iol') {
         if (isset($p['ethernet']) && $p['ethernet'] === '') {
             // Ethernet interfaces is empty, unset the current one
             unset($p['ethernet']);
             $modified = True;
         } else {
             if (isset($p['ethernet']) && (int) $p['ethernet'] < 0) {
                 // Ethernet interfaces is invalid, ignored
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40012]);
             } else {
                 if (isset($p['ethernet']) && $this->ethernet != (int) $p['ethernet']) {
                     // New Ethernet value
                     $this->ethernet = (int) $p['ethernet'];
                     $modified = True;
                 }
             }
         }
         if (isset($p['nvram']) && $p['nvram'] === '') {
             // NVRAM is empty, unset the current one
             unset($p['nvram']);
             $modified = True;
         } else {
             if (isset($p['nvram']) && (int) $p['nvram'] <= 0) {
                 // NVRAM is invalid, ignored
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40011]);
             } else {
                 if (isset($p['nvram'])) {
                     $this->nvram = (int) $p['nvram'];
                 }
             }
         }
         if (isset($p['ram']) && $p['ram'] === '') {
             // RAM is empty, unset the current one
             unset($p['ram']);
             $modified = True;
         } else {
             if (isset($p['ram']) && (int) $p['ram'] <= 0) {
                 // RAM is invalid, ignored
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40009]);
             } else {
                 if (isset($p['ram'])) {
                     $this->ram = (int) $p['ram'];
                 }
             }
         }
         if (isset($p['serial']) && $p['serial'] === '') {
             // Serial interfaces is empty, unset the current one
             unset($p['serial']);
             $modified = True;
         } else {
             if (isset($p['serial']) && (int) $p['serial'] < 0) {
                 // Serial interfaces is invalid, ignored
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40013]);
             } else {
                 if (isset($p['serial']) && $this->serial != (int) $p['serial']) {
                     // New Serial value
                     $this->serial = (int) $p['serial'];
                     $modified = True;
                 }
             }
         }
     }
     if ($this->type == 'dynamips') {
         if (isset($p['idlepc']) && $p['idlepc'] === '') {
             // Idle PC is empty, unset the current one
             unset($p['idlepc']);
             $modified = True;
         } else {
             if (isset($p['idlepc']) && !checkNodeIdlepc($p['idlepc'])) {
                 // Idle PC is invalid, ignored
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40014]);
             } else {
                 if (isset($p['idlepc'])) {
                     $this->idlepc = $p['idlepc'];
                 }
             }
         }
         if (isset($p['nvram']) && $p['nvram'] === '') {
             // NVRAM is empty, unset the current one
             unset($p['nvram']);
             $modified = True;
         } else {
             if (isset($p['nvram']) && (int) $p['nvram'] <= 0) {
                 // NVRAM is invalid, ignored
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40011]);
             } else {
                 if (isset($p['nvram'])) {
                     $this->nvram = (int) $p['nvram'];
                 }
             }
         }
         if (isset($p['ram']) && $p['ram'] === '') {
             // RAM is empty, unset the current one
             unset($p['ram']);
             $modified = True;
         } else {
             if (isset($p['ram']) && (int) $p['ram'] <= 0) {
                 // RAM is invalid, ignored
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40009]);
             } else {
                 if (isset($p['ram'])) {
                     $this->ram = (int) $p['ram'];
                 }
             }
         }
         // Loading slots
         foreach ($p as $key => $module) {
             if (preg_match('/^slot[0-9]+$/', $key)) {
                 // Found a slot
                 $slot_id = substr($key, 4);
                 if ($module == '') {
                     // Slot is empty, unset the current one
                     unset($this->slots[$slot_id]);
                     $modified = True;
                 } else {
                     if (!isset($this->slots[$slot_id]) || $this->slots[$slot_id] != $module) {
                         // Need to set the slot (previous was empty or different module)
                         $this->setSlot($slot_id, $module);
                         $modified = True;
                     }
                 }
             }
         }
     }
     if ($this->type == 'qemu') {
         // TODO check if == vnc or telnet (checkConsole)
         if (isset($p['console']) && $p['console'] === '') {
             // Console is empty, unset the current one
             unset($p['console']);
             $modified = True;
         } else {
             if (isset($p['console'])) {
                 $this->console = htmlentities($p['console']);
                 $modified = True;
             }
         }
         if (isset($p['cpu']) && $p['cpu'] === '') {
             // Configured CPUs is empty, unset the current one
             unset($p['cpu']);
             $modified = True;
         } else {
             if (isset($p['cpu']) && (int) $p['cpu'] <= 0) {
                 // Configured CPUs is invalid, ignored
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40011]);
             } else {
                 if (isset($p['cpu'])) {
                     $this->cpu = (int) $p['cpu'];
                 }
             }
         }
         if (isset($p['ram']) && $p['ram'] === '') {
             // RAM is empty, unset the current one
             unset($p['ram']);
             $modified = True;
         } else {
             if (isset($p['ram']) && (int) $p['ram'] <= 0) {
                 // RAM is invalid, ignored
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40009]);
             } else {
                 if (isset($p['ram'])) {
                     $this->ram = (int) $p['ram'];
                 }
             }
         }
         if (isset($p['ethernet']) && $p['ethernet'] === '') {
             // Ethernet interfaces is empty, unset the current one
             unset($p['ethernet']);
             $modified = True;
         } else {
             if (isset($p['ethernet']) && (int) $p['ethernet'] <= 0) {
                 // Ethernet interfaces is invalid, ignored
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40012]);
             } else {
                 if (isset($p['ethernet']) && $this->ethernet != (int) $p['ethernet']) {
                     // New Ethernet value
                     $this->ethernet = (int) $p['ethernet'];
                     $modified = True;
                 }
             }
         }
         if (isset($p['uuid']) && $p['uuid'] === '') {
             // UUID is empty, unset the current one
             unset($this->uuid);
             $modified = True;
         } else {
             if (isset($p['uuid']) && !checkUuid($p['uuid'])) {
                 // UUID is not valid, ignored
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40026]);
             } else {
                 if (isset($p['uuid'])) {
                     $this->uuid = $p['uuid'];
                     $modified = True;
                 }
             }
         }
     }
     if ($this->type == 'docker') {
         if (isset($p['ram']) && $p['ram'] === '') {
             // RAM is empty, unset the current one
             unset($p['ram']);
             $modified = True;
         } else {
             if (isset($p['ram']) && (int) $p['ram'] <= 0) {
                 // RAM is invalid, ignored
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40009]);
             } else {
                 if (isset($p['ram'])) {
                     $this->ram = (int) $p['ram'];
                 }
             }
         }
         if (isset($p['ethernet']) && $p['ethernet'] === '') {
             // Ethernet interfaces is empty, unset the current one
             unset($p['ethernet']);
             $modified = True;
         } else {
             if (isset($p['ethernet']) && (int) $p['ethernet'] <= 0) {
                 // Ethernet interfaces is invalid, ignored
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $GLOBALS['messages'][40012]);
             } else {
                 if (isset($p['ethernet']) && $this->ethernet != (int) $p['ethernet']) {
                     // New Ethernet value
                     $this->ethernet = (int) $p['ethernet'];
                     $modified = True;
                 }
             }
         }
     }
     if ($modified) {
         // At least an attribute is changed
         // Set interface name
         if (isset($p['ethernet'])) {
             $this->setEthernets();
         }
         if (isset($p['serial']) && $this->type == 'iol') {
             $this->setSerials();
         }
         return 0;
     } else {
         // No attribute has been changed
         error_log(date('M d H:i:s ') . 'ERROR: ' . $GLOBALS['messages'][40016]);
         return 40016;
     }
 }
Пример #2
0
 /**
  * Constructor which load an existent lab or create an empty one.
  *
  * @param	  string  $f                  the file of the lab with full path
  * @param	  int     $tenant             Tenant ID
  * @return	  void
  */
 public function __construct($f, $tenant)
 {
     $modified = False;
     if (!is_file($f)) {
         // File does not exist, create a new empty lab
         $this->filename = basename($f);
         $this->path = dirname($f);
         $this->tenant = (int) $tenant;
         if (!checkLabFilename($this->filename)) {
             // Invalid filename
             error_log('ERROR: ' . $f . ' ' . $GLOBALS['messages'][20001]);
             throw new Exception('20001');
         }
         if (!checkLabPath($this->path)) {
             // Invalid path
             error_log('ERROR: ' . $f . ' ' . $GLOBALS['messages'][20002]);
             throw new Exception('20002');
         }
         $this->name = substr(basename($f), 0, -4);
         $this->id = genUuid();
         $modified = True;
     } else {
         // Load the existent lab
         $this->filename = basename($f);
         $this->path = dirname($f);
         $this->tenant = (int) $tenant;
         if (!checkLabFilename($this->filename)) {
             // Invalid filename
             error_log('ERROR: ' . $f . ' ' . $GLOBALS['messages'][20001]);
             throw new Exception('20001');
         }
         if (!checkLabPath($this->path)) {
             // Invalid path
             error_log('ERROR: ' . $f . ' ' . $GLOBALS['messages'][20002]);
             throw new Exception('20002');
         }
         libxml_use_internal_errors(true);
         $xml = simplexml_load_file($f);
         if (!$xml) {
             // Invalid XML document
             error_log('ERROR: ' . $f . ' ' . $GLOBALS['messages'][20003]);
             throw new Exception('20003');
         }
         // Lab name
         $result = $xml->xpath('//lab/@name');
         if (empty($result)) {
             // Invalid UNetLab file (attribute is missing)
             error_log('ERROR: ' . $f . ' ' . $GLOBALS['messages'][20004]);
             throw new Exception('20004');
             return;
         } else {
             if (!checkLabName($result[0])) {
                 // Attribute not valid
                 error_log('ERROR: ' . $f . ' ' . $GLOBALS['messages'][20005]);
                 throw new Exception('20005');
                 return;
             } else {
                 $this->name = (string) $result[0];
             }
         }
         // Lab ID
         $result = $xml->xpath('//lab/@id');
         if (empty($result)) {
             // Lab ID not set, create a new one
             $this->id = genUuid();
             error_log('WARNING: ' . $f . ' ' . $GLOBALS['messages'][20011]);
             $modified = True;
         } else {
             if (!checkUuid($result[0])) {
                 // Attribute not valid
                 $this->id = genUuid();
                 error_log('WARNING: ' . $f . ' ' . $GLOBALS['messages'][20012]);
                 $modified = True;
             } else {
                 $this->id = (string) $result[0];
             }
         }
         // Lab description
         $result = (string) array_pop($xml->xpath('//lab/description'));
         if (strlen($result) !== 0) {
             $this->description = htmlspecialchars($result, ENT_DISALLOWED, 'UTF-8', TRUE);
         } else {
             if (strlen($result) !== 0) {
                 error_log('WARNING: ' . $f . ' ' . $GLOBALS['messages'][20006]);
             }
         }
         // Lab author
         $result = (string) array_pop($xml->xpath('//lab/@author'));
         if (strlen($result) !== 0) {
             $this->author = htmlspecialchars($result, ENT_DISALLOWED, 'UTF-8', TRUE);
         } else {
             if (strlen($result) !== 0) {
                 error_log('WARNING: ' . $f . ' ' . $GLOBALS['messages'][20007]);
             }
         }
         // Lab version
         $result = (string) array_pop($xml->xpath('//lab/@version'));
         if (strlen($result) !== 0 && (int) $result >= 0) {
             $this->version = $result;
         } else {
             if (strlen($result) !== 0) {
                 error_log('WARNING: ' . $f . ' ' . $GLOBALS['messages'][20008]);
             }
         }
         // Lab networks
         foreach ($xml->xpath('//lab/topology/networks/network') as $network) {
             $w = array();
             if (isset($network->attributes()->id)) {
                 $w['id'] = (string) $network->attributes()->id;
             }
             if (isset($network->attributes()->left)) {
                 $w['left'] = (string) $network->attributes()->left;
             }
             if (isset($network->attributes()->name)) {
                 $w['name'] = (string) $network->attributes()->name;
             }
             if (isset($network->attributes()->top)) {
                 $w['top'] = (string) $network->attributes()->top;
             }
             if (isset($network->attributes()->type)) {
                 $w['type'] = (string) $network->attributes()->type;
             }
             try {
                 $this->networks[$w['id']] = new Network($w, $w['id'], $this->tenant);
             } catch (Exception $e) {
                 // Invalid network
                 error_log('WARNING: ' . $f . ':net' . $w['id'] . ' ' . $GLOBALS['messages'][20009]);
                 error_log((string) $e);
                 continue;
             }
         }
         // Lab nodes (networks must be alredy loaded)
         foreach ($xml->xpath('//lab/topology/nodes/node') as $node_id => $node) {
             $n = array();
             if (isset($node->attributes()->config)) {
                 $n['config'] = (string) $node->attributes()->config;
             }
             if (isset($node->attributes()->console)) {
                 $n['console'] = (string) $node->attributes()->console;
             }
             if (isset($node->attributes()->cpu)) {
                 $n['cpu'] = (int) $node->attributes()->cpu;
             }
             if (isset($node->attributes()->delay)) {
                 $n['delay'] = (string) $node->attributes()->delay;
             }
             if (isset($node->attributes()->ethernet)) {
                 $n['ethernet'] = (int) $node->attributes()->ethernet;
             }
             if (isset($node->attributes()->icon)) {
                 $n['icon'] = (string) $node->attributes()->icon;
             }
             if (isset($node->attributes()->id)) {
                 $n['id'] = (int) $node->attributes()->id;
             }
             if (isset($node->attributes()->idlepc)) {
                 $n['idlepc'] = (string) $node->attributes()->idlepc;
             }
             if (isset($node->attributes()->image)) {
                 $n['image'] = (string) $node->attributes()->image;
             }
             if (isset($node->attributes()->left)) {
                 $n['left'] = (string) $node->attributes()->left;
             }
             if (isset($node->attributes()->name)) {
                 $n['name'] = (string) $node->attributes()->name;
             }
             if (isset($node->attributes()->nvram)) {
                 $n['nvram'] = (int) $node->attributes()->nvram;
             }
             if (isset($node->attributes()->ram)) {
                 $n['ram'] = (int) $node->attributes()->ram;
             }
             if (isset($node->attributes()->serial)) {
                 $n['serial'] = (int) $node->attributes()->serial;
             }
             if (isset($node->attributes()->template)) {
                 $n['template'] = (string) $node->attributes()->template;
             }
             if (isset($node->attributes()->top)) {
                 $n['top'] = (string) $node->attributes()->top;
             }
             if (isset($node->attributes()->type)) {
                 $n['type'] = (string) $node->attributes()->type;
             }
             if (isset($node->attributes()->uuid)) {
                 $n['uuid'] = (string) $node->attributes()->uuid;
             }
             try {
                 $this->nodes[$n['id']] = new Node($n, $n['id'], $this->tenant, $this->id);
             } catch (Exception $e) {
                 // Invalid node
                 error_log('WARNING: ' . $f . ':node' . $n['id'] . ' ' . $GLOBALS['messages'][20010]);
                 error_log((string) $e);
                 continue;
             }
             // Slot must be loaded before interfaces
             foreach ($node->slot as $slot) {
                 // Loading configured slots for this node
                 $s = array();
                 if (isset($slot->attributes()->id)) {
                     $s['id'] = (string) $slot->attributes()->id;
                 }
                 if (isset($slot->attributes()->module)) {
                     $s['module'] = (string) $slot->attributes()->module;
                 }
                 if ($this->nodes[$n['id']]->setSlot($s['id'], $s['module']) !== 0) {
                     error_log('WARNING: ' . $f . ':node' . $n['id'] . ':slot' . $s['id'] . ' ' . $GLOBALS['messages'][20013]);
                 }
             }
             foreach ($node->interface as $interface) {
                 // Loading configured interfaces for this node
                 $i = array();
                 if (isset($interface->attributes()->id)) {
                     $i['id'] = (string) $interface->attributes()->id;
                 }
                 if (isset($interface->attributes()->network_id)) {
                     $i['network_id'] = (string) $interface->attributes()->network_id;
                 }
                 if (isset($interface->attributes()->remote_id)) {
                     $i['remote_id'] = (string) $interface->attributes()->remote_id;
                 }
                 if (isset($interface->attributes()->remote_if)) {
                     $i['remote_if'] = (string) $interface->attributes()->remote_if;
                 }
                 if (isset($interface->attributes()->remote_host)) {
                     $i['remote_host'] = (string) $interface->attributes()->remote_host;
                 }
                 if (isset($interface->attributes()->type)) {
                     $i['type'] = (string) $interface->attributes()->type;
                 }
                 switch ($i['type']) {
                     default:
                         error_log('WARNING: ' . $f . ':node' . $n['id'] . ':inv' . $s['id'] . ' ' . $GLOBALS['messages'][20016]);
                         break;
                     case 'ethernet':
                         if ($this->nodes[$n['id']]->linkInterface($i) !== 0) {
                             error_log('WARNING: ' . $f . ':node' . $n['id'] . ':eth' . $i['id'] . ' ' . $GLOBALS['messages'][20014]);
                         }
                         break;
                     case 'serial':
                         // Serial
                         if ($this->nodes[$n['id']]->linkInterface($i) !== 0) {
                             error_log('WARNING: ' . $f . ':node' . $n['id'] . ':ser' . $i['id'] . ' ' . $GLOBALS['messages'][20015]);
                         }
                         break;
                 }
             }
         }
         // startup-config
         foreach ($xml->xpath('//lab/objects/configs/config') as $config) {
             $node_id = 0;
             $config_data = '';
             if (isset($config->attributes()->id)) {
                 $node_id = (string) $config->attributes()->id;
             }
             $result = (string) array_pop($config->xpath('.'));
             if (strlen($result) > 0) {
                 $config_data = base64_decode($result);
             }
             $rc = $this->nodes[$node_id]->setConfigData($config_data);
             if ($rc != 0) {
                 error_log('WARNING: ' . $f . ':cfg' . $node_id . ' ' . $GLOBALS['messages'][20037]);
                 continue;
             }
         }
         // Lab Pictures
         foreach ($xml->xpath('//lab/objects/pictures/picture') as $picture) {
             $p = array();
             if (isset($picture->attributes()->id)) {
                 $p['id'] = (string) $picture->attributes()->id;
             }
             if (isset($picture->attributes()->name)) {
                 $p['name'] = (string) $picture->attributes()->name;
             }
             if (isset($picture->attributes()->type)) {
                 $p['type'] = (string) $picture->attributes()->type;
             }
             $result = (string) array_pop($picture->xpath('./data'));
             if (strlen($result) > 0) {
                 $p['data'] = base64_decode($result);
             }
             $result = (string) array_pop($picture->xpath('./map'));
             if (strlen($result) > 0) {
                 $p['map'] = html_entity_decode($result);
             }
             try {
                 $this->pictures[$p['id']] = new Picture($p, $p['id']);
             } catch (Exception $e) {
                 // Invalid picture
                 error_log('WARNING: ' . $f . ':pic' . $p['id'] . ' ' . $GLOBALS['messages'][20020]);
                 error_log((string) $e);
                 continue;
             }
         }
         // Update attached network count
         $this->setNetworkCount();
     }
     if ($modified) {
         // Need to save
         $rc = $this->save();
         if ($rc != 0) {
             throw new Exception($rc);
             return $rc;
         }
     }
     return 0;
 }
Пример #3
0
 /**
  * Constructor which load an existent lab or create an empty one.
  *
  * @param	  string  $f                  the file of the lab with full path
  * @param	  int     $tenant             Tenant ID
  * @return	  void
  */
 public function __construct($f, $tenant)
 {
     $modified = False;
     if (!is_file($f)) {
         // File does not exist, create a new empty lab
         $this->filename = basename($f);
         $this->path = dirname($f);
         $this->tenant = (int) $tenant;
         if (!checkLabFilename($this->filename)) {
             // Invalid filename
             error_log(date('M d H:i:s ') . 'ERROR: ' . $f . ' ' . $GLOBALS['messages'][20001]);
             throw new Exception('20001');
         }
         if (!checkLabPath($this->path)) {
             // Invalid path
             error_log(date('M d H:i:s ') . 'ERROR: ' . $f . ' ' . $GLOBALS['messages'][20002]);
             throw new Exception('20002');
         }
         $this->name = substr(basename($f), 0, -4);
         $this->id = genUuid();
         $modified = True;
         $this->scripttimeout = 600;
     } else {
         // Load the existent lab
         $this->filename = basename($f);
         $this->path = dirname($f);
         $this->tenant = (int) $tenant;
         if (!checkLabFilename($this->filename)) {
             // Invalid filename
             error_log(date('M d H:i:s ') . 'ERROR: ' . $f . ' ' . $GLOBALS['messages'][20001]);
             throw new Exception('20001');
         }
         if (!checkLabPath($this->path)) {
             // Invalid path
             error_log(date('M d H:i:s ') . 'ERROR: ' . $f . ' ' . $GLOBALS['messages'][20002]);
             throw new Exception('20002');
         }
         libxml_use_internal_errors(true);
         $xml = simplexml_load_file($f);
         if (!$xml) {
             // Invalid XML document
             error_log(date('M d H:i:s ') . 'ERROR: ' . $f . ' ' . $GLOBALS['messages'][20003]);
             throw new Exception('20003');
         }
         // Lab name
         $patterns[0] = '/\\.unl$/';
         $replacements[0] = '';
         $this->name = preg_replace($patterns, $replacements, basename($f));
         // Lab ID
         $result = $xml->xpath('//lab/@id');
         if (empty($result)) {
             // Lab ID not set, create a new one
             $this->id = genUuid();
             error_log(date('M d H:i:s ') . 'WARNING: ' . $f . ' ' . $GLOBALS['messages'][20011]);
             $modified = True;
         } else {
             if (!checkUuid($result[0])) {
                 // Attribute not valid
                 $this->id = genUuid();
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $f . ' ' . $GLOBALS['messages'][20012]);
                 $modified = True;
             } else {
                 $this->id = (string) $result[0];
             }
         }
         // Lab description
         $result = (string) array_pop($xml->xpath('//lab/description'));
         if (strlen($result) !== 0) {
             $this->description = htmlspecialchars($result, ENT_DISALLOWED, 'UTF-8', TRUE);
         } else {
             if (strlen($result) !== 0) {
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $f . ' ' . $GLOBALS['messages'][20006]);
             }
         }
         // Lab body
         $result = (string) array_pop($xml->xpath('//lab/body'));
         if (strlen($result) !== 0) {
             $this->body = htmlspecialchars($result, ENT_DISALLOWED, 'UTF-8', TRUE);
         } else {
             if (strlen($result) !== 0) {
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $f . ' ' . $GLOBALS['messages'][20006]);
             }
         }
         // Lab author
         $result = (string) array_pop($xml->xpath('//lab/@author'));
         if (strlen($result) !== 0) {
             $this->author = htmlspecialchars($result, ENT_DISALLOWED, 'UTF-8', TRUE);
         } else {
             if (strlen($result) !== 0) {
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $f . ' ' . $GLOBALS['messages'][20007]);
             }
         }
         // Lab version
         $result = (string) array_pop($xml->xpath('//lab/@version'));
         if (strlen($result) !== 0 && (int) $result >= 0) {
             $this->version = $result;
         } else {
             if (strlen($result) !== 0) {
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $f . ' ' . $GLOBALS['messages'][20008]);
             }
         }
         // Lab networks
         foreach ($xml->xpath('//lab/topology/networks/network') as $network) {
             $w = array();
             if (isset($network->attributes()->id)) {
                 $w['id'] = (string) $network->attributes()->id;
             }
             if (isset($network->attributes()->left)) {
                 $w['left'] = (string) $network->attributes()->left;
             }
             if (isset($network->attributes()->name)) {
                 $w['name'] = (string) $network->attributes()->name;
             }
             if (isset($network->attributes()->top)) {
                 $w['top'] = (string) $network->attributes()->top;
             }
             if (isset($network->attributes()->type)) {
                 $w['type'] = (string) $network->attributes()->type;
             }
             try {
                 $this->networks[$w['id']] = new Network($w, $w['id'], $this->tenant);
             } catch (Exception $e) {
                 // Invalid network
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $f . ':net' . $w['id'] . ' ' . $GLOBALS['messages'][20009]);
                 error_log(date('M d H:i:s ') . (string) $e);
                 continue;
             }
         }
         // Lab nodes (networks must be alredy loaded)
         foreach ($xml->xpath('//lab/topology/nodes/node') as $node_id => $node) {
             $n = array();
             if (isset($node->attributes()->config)) {
                 $n['config'] = (string) $node->attributes()->config;
             }
             if (isset($node->attributes()->console)) {
                 $n['console'] = (string) $node->attributes()->console;
             }
             if (isset($node->attributes()->cpu)) {
                 $n['cpu'] = (int) $node->attributes()->cpu;
             }
             if (isset($node->attributes()->delay)) {
                 $n['delay'] = (string) $node->attributes()->delay;
             }
             if (isset($node->attributes()->ethernet)) {
                 $n['ethernet'] = (int) $node->attributes()->ethernet;
             }
             if (isset($node->attributes()->icon)) {
                 $n['icon'] = (string) $node->attributes()->icon;
             }
             if (isset($node->attributes()->id)) {
                 $n['id'] = (int) $node->attributes()->id;
             }
             if (isset($node->attributes()->idlepc)) {
                 $n['idlepc'] = (string) $node->attributes()->idlepc;
             }
             if (isset($node->attributes()->image)) {
                 $n['image'] = (string) $node->attributes()->image;
             }
             if (isset($node->attributes()->left)) {
                 $n['left'] = (string) $node->attributes()->left;
             }
             if (isset($node->attributes()->name)) {
                 $n['name'] = (string) $node->attributes()->name;
             }
             if (isset($node->attributes()->nvram)) {
                 $n['nvram'] = (int) $node->attributes()->nvram;
             }
             if (isset($node->attributes()->ram)) {
                 $n['ram'] = (int) $node->attributes()->ram;
             }
             if (isset($node->attributes()->serial)) {
                 $n['serial'] = (int) $node->attributes()->serial;
             }
             if (isset($node->attributes()->template)) {
                 $n['template'] = (string) $node->attributes()->template;
             }
             if (isset($node->attributes()->top)) {
                 $n['top'] = (string) $node->attributes()->top;
             }
             if (isset($node->attributes()->type)) {
                 $n['type'] = (string) $node->attributes()->type;
             }
             if (isset($node->attributes()->uuid)) {
                 $n['uuid'] = (string) $node->attributes()->uuid;
             }
             $n['config'] == 'Exported' ? $n['config'] = '1' : $n['config'];
             // Fix startup-config
             $n['config'] == 'None' ? $n['config'] = '0' : $n['config'];
             // Fix startup-config
             // If config is empty, force "None"
             $result = (string) array_pop($xml->xpath('//lab/objects/configs/config[@id="' . $n['id'] . '"]'));
             if (strlen($result) == 0) {
                 $n['config'] = 0;
                 $config_data = False;
             } else {
                 $config_data = base64_decode($result);
             }
             // F5 needs a first mac address
             if ($n['template'] == "bigip") {
                 if (isset($node->attributes()->firstmac)) {
                     $n['firstmac'] = (string) $node->attributes()->firstmac;
                 } else {
                     $n['firstmac'] = (string) '00:' . sprintf('%02x', $this->tenant) . ':' . sprintf('%02x', $this->id / 512) . ':' . sprintf('%02x', $this->id % 512) . ':00:10';
                 }
             }
             try {
                 $this->nodes[$n['id']] = new Node($n, $n['id'], $this->tenant, $this->id);
             } catch (Exception $e) {
                 // Invalid node
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $f . ':node' . $n['id'] . ' ' . $GLOBALS['messages'][20010]);
                 error_log(date('M d H:i:s ') . (string) $e);
                 continue;
             }
             // Slot must be loaded before interfaces
             foreach ($node->slot as $slot) {
                 // Loading configured slots for this node
                 $s = array();
                 if (isset($slot->attributes()->id)) {
                     $s['id'] = (string) $slot->attributes()->id;
                 }
                 if (isset($slot->attributes()->module)) {
                     $s['module'] = (string) $slot->attributes()->module;
                 }
                 if ($this->nodes[$n['id']]->setSlot($s['id'], $s['module']) !== 0) {
                     error_log(date('M d H:i:s ') . 'WARNING: ' . $f . ':node' . $n['id'] . ':slot' . $s['id'] . ' ' . $GLOBALS['messages'][20013]);
                 }
             }
             foreach ($node->interface as $interface) {
                 // Loading configured interfaces for this node
                 $i = array();
                 if (isset($interface->attributes()->id)) {
                     $i['id'] = (string) $interface->attributes()->id;
                 }
                 if (isset($interface->attributes()->network_id)) {
                     $i['network_id'] = (string) $interface->attributes()->network_id;
                 }
                 if (isset($interface->attributes()->remote_id)) {
                     $i['remote_id'] = (string) $interface->attributes()->remote_id;
                 }
                 if (isset($interface->attributes()->remote_if)) {
                     $i['remote_if'] = (string) $interface->attributes()->remote_if;
                 }
                 if (isset($interface->attributes()->remote_host)) {
                     $i['remote_host'] = (string) $interface->attributes()->remote_host;
                 }
                 if (isset($interface->attributes()->type)) {
                     $i['type'] = (string) $interface->attributes()->type;
                 }
                 switch ($i['type']) {
                     default:
                         error_log(date('M d H:i:s ') . 'WARNING: ' . $f . ':node' . $n['id'] . ':inv' . $s['id'] . ' ' . $GLOBALS['messages'][20016]);
                         break;
                     case 'ethernet':
                         if ($this->nodes[$n['id']]->linkInterface($i) !== 0) {
                             error_log(date('M d H:i:s ') . 'WARNING: ' . $f . ':node' . $n['id'] . ':eth' . $i['id'] . ' ' . $GLOBALS['messages'][20014]);
                         }
                         break;
                     case 'serial':
                         // Serial
                         if ($this->nodes[$n['id']]->linkInterface($i) !== 0) {
                             error_log(date('M d H:i:s ') . 'WARNING: ' . $f . ':node' . $n['id'] . ':ser' . $i['id'] . ' ' . $GLOBALS['messages'][20015]);
                         }
                         break;
                 }
             }
             // startup-config (read before)
             if ($config_data !== False) {
                 $rc = $this->nodes[$n['id']]->setConfigData($config_data);
                 if ($rc != 0) {
                     error_log(date('M d H:i:s ') . 'WARNING: ' . $f . ':cfg' . $node_id . ' ' . $GLOBALS['messages'][20037]);
                 }
             }
         }
         // lab script timeout
         $result = (string) array_pop($xml->xpath('//lab/@scripttimeout'));
         if (strlen($result) !== 0 && (int) $result >= 300) {
             $this->scripttimeout = $result;
         } else {
             if (strlen($result) !== 0) {
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $f . ' ' . $GLOBALS['messages'][20045]);
                 $this->scripttimeout = 300;
             }
         }
         // Lab Pictures
         foreach ($xml->xpath('//lab/objects/pictures/picture') as $picture) {
             $p = array();
             if (isset($picture->attributes()->id)) {
                 $p['id'] = (string) $picture->attributes()->id;
             }
             if (isset($picture->attributes()->name)) {
                 $p['name'] = (string) $picture->attributes()->name;
             }
             if (isset($picture->attributes()->type)) {
                 $p['type'] = (string) $picture->attributes()->type;
             }
             $result = (string) array_pop($picture->xpath('./data'));
             if (strlen($result) > 0) {
                 $p['data'] = base64_decode($result);
             }
             $result = (string) array_pop($picture->xpath('./map'));
             if (strlen($result) > 0) {
                 $p['map'] = html_entity_decode($result);
             }
             try {
                 $this->pictures[$p['id']] = new Picture($p, $p['id']);
             } catch (Exception $e) {
                 // Invalid picture
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $f . ':pic' . $p['id'] . ' ' . $GLOBALS['messages'][20020]);
                 error_log(date('M d H:i:s ') . (string) $e);
                 continue;
             }
         }
         // Text Objects
         foreach ($xml->xpath('//lab/objects/textobjects/textobject') as $textobject) {
             $p = array();
             if (isset($textobject->attributes()->id)) {
                 $p['id'] = (string) $textobject->attributes()->id;
             }
             if (isset($textobject->attributes()->name)) {
                 $p['name'] = (string) $textobject->attributes()->name;
             }
             if (isset($textobject->attributes()->type)) {
                 $p['type'] = (string) $textobject->attributes()->type;
             }
             $result = (string) array_pop($textobject->xpath('./data'));
             if (strlen($result) > 0) {
                 $p['data'] = $result;
             }
             try {
                 $this->textobjects[$p['id']] = new TextObject($p, $p['id']);
             } catch (Exception $e) {
                 // Invalid picture
                 error_log(date('M d H:i:s ') . 'WARNING: ' . $f . ':obj' . $p['id'] . ' ' . $GLOBALS['messages'][20041]);
                 error_log(date('M d H:i:s ') . (string) $e);
                 continue;
             }
         }
         // Update attached network count
         $this->setNetworkCount();
     }
     if ($modified) {
         // Need to save
         $rc = $this->save();
         if ($rc != 0) {
             throw new Exception($rc);
             return $rc;
         }
     }
     return 0;
 }