/** * 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; }
$app->response->setStatus($output['code']); $app->response->setBody(json_encode($output)); })->via('DELETE', 'GET', 'POST'); $app->run(); } // Define output for unprivileged requests $forbidden = array('code' => 401, 'status' => 'forbidden', 'message' => $GLOBALS['messages']['90032']); /*************************************************************************** * Authentication **************************************************************************/ $app->post('/api/auth/login', function () use($app, $db) { // Login $event = json_decode($app->request()->getBody()); $p = json_decode(json_encode($event), True); // Reading options from POST/PUT $cookie = genUuid(); $output = apiLogin($db, $p, $cookie); if ($output['code'] == 200) { // User is authenticated, need to set the cookie $app->setCookie('unetlab_session', $cookie, SESSION, '/api/', $_SERVER['SERVER_NAME'], False, False); } $app->response->setStatus($output['code']); $app->response->setBody(json_encode($output)); }); $app->get('/api/auth/logout', function () use($app, $db) { // Logout (DELETE request does not work with cookies) $cookie = $app->getCookie('unetlab_session'); $app->deleteCookie('unetlab_session'); $output = apiLogout($db, $cookie); $app->response->setStatus($output['code']); $app->response->setBody(json_encode($output));
/** * Method to get UUID. * * @return string UUID */ public function getUuid() { if ($this->type == 'docker') { return $this->lab_id . '-' . $this->tenant . '-' . $this->id; } else { if (isset($this->uuid)) { return $this->uuid; } else { // By default return a random UUID return genUuid(); } } }
/** * Function to get node template. * * @param Array $p Parameters * @return Array Node template (JSend data) */ function apiGetLabNodeTemplate($p) { // Check mandatory parameters if (!isset($p['type']) || !isset($p['template'])) { $output['code'] = 400; $output['status'] = 'fail'; $output['message'] = $GLOBALS['messages'][60033]; return $output; } // TODO must check lot of parameters $output['code'] = 200; $output['status'] = 'success'; $output['message'] = $GLOBALS['messages'][60032]; $output['data'] = array(); $output['data']['options'] = array(); // Name $output['data']['description'] = $GLOBALS['node_templates'][$p['template']]; // Type $output['data']['type'] = $p['type']; // Image $node_images = listNodeImages($p['type'], $p['template']); if (empty($node_images)) { $output['data']['options']['image'] = array('name' => $GLOBALS['messages'][70002], 'type' => 'list', 'value' => '', 'list' => array()); } else { $output['data']['options']['image'] = array('name' => $GLOBALS['messages'][70002], 'type' => 'list', 'value' => end($node_images), 'list' => $node_images); } // Node Name/Prefix $output['data']['options']['name'] = array('name' => $GLOBALS['messages'][70000], 'type' => 'input', 'value' => $p['name']); // Icon $output['data']['options']['icon'] = array('name' => $GLOBALS['messages'][70001], 'type' => 'list', 'value' => $p['icon'], 'list' => listNodeIcons()); // UUID if ($p['type'] == 'qemu') { $output['data']['options']['uuid'] = array('name' => $GLOBALS['messages'][70008], 'type' => 'input', 'value' => genUuid()); } // CPU if ($p['type'] == 'qemu') { $output['data']['options']['cpu'] = array('name' => $GLOBALS['messages'][70003], 'type' => 'input', 'value' => $p['cpu']); } // Idle PC if ($p['type'] == 'dynamips') { $output['data']['options']['idlepc'] = array('name' => $GLOBALS['messages'][70009], 'type' => 'input', 'value' => $p['idlepc']); } // NVRAM if ($p['type'] == 'dynamips') { $output['data']['options']['nvram'] = array('name' => $GLOBALS['messages'][70010], 'type' => 'input', 'value' => $p['nvram']); } // RAM $output['data']['options']['ram'] = array('name' => $GLOBALS['messages'][70011], 'type' => 'input', 'value' => $p['ram']); // Slots if ($p['type'] == 'dynamips') { foreach ($p as $key => $module) { if (preg_match('/^slot[0-9]+$/', $key)) { // Found a slot $slot_id = substr($key, 4); $output['data']['options']['slot' . $slot_id] = array('name' => $GLOBALS['messages'][70016] . ' ' . $slot_id, 'type' => 'list', 'value' => $p['slot' . $slot_id], 'list' => $p['modules']); } } } // Ethernet if ($p['type'] == 'qemu') { $output['data']['options']['ethernet'] = array('name' => $GLOBALS['messages'][70012], 'type' => 'input', 'value' => $p['ethernet']); } if ($p['type'] == 'iol') { $output['data']['options']['ethernet'] = array('name' => $GLOBALS['messages'][70018], 'type' => 'input', 'value' => $p['ethernet']); } // Serial if ($p['type'] == 'iol') { $output['data']['options']['serial'] = array('name' => $GLOBALS['messages'][70017], 'type' => 'input', 'value' => $p['serial']); } // Startup configs if (in_array($p['type'], array('dynamips', 'iol'))) { $output['data']['options']['config'] = array('name' => $GLOBALS['messages'][70013], 'type' => 'list', 'value' => 'Unconfigured', 'list' => array('Saved' => 'Saved', 'Unconfigured' => 'Unconfigured')); } // Delay $output['data']['options']['delay'] = array('name' => $GLOBALS['messages'][70014], 'type' => 'input', 'value' => 0); // Console if ($p['type'] == 'qemu') { $output['data']['options']['console'] = array('name' => $GLOBALS['messages'][70015], 'type' => 'list', 'value' => $p['console'], 'list' => array('telnet' => 'telnet', 'vnc' => 'vnc')); } // Dynamips options if ($p['type'] == 'dynamips') { $output['data']['dynamips'] = array(); if (isset($p['dynamips_options'])) { $output['data']['dynamips']['options'] = $p['dynamips_options']; } } // QEMU options if ($p['type'] == 'qemu') { $output['data']['qemu'] = array(); if (isset($p['qemu_arch'])) { $output['data']['qemu']['arch'] = $p['qemu_arch']; } if (isset($p['qemu_version'])) { $output['data']['qemu']['version'] = $p['qemu_version']; } if (isset($p['qemu_nic'])) { $output['data']['qemu']['nic'] = $p['qemu_nic']; } if (isset($p['qemu_options'])) { $output['data']['qemu']['options'] = $p['qemu_options']; } } return $output; }
/** * Method to set a new lab_id * * @return void */ public function setId() { $this->id = genUuid(); $this->save(); }
/** * Method to get UUID. * * @return string UUID */ public function getUuid() { if (isset($this->uuid)) { return $this->uuid; } else { // By default return a random UUID return genUuid(); } }