/** * Function to start a node. * * @param Node $n Node * @param Int $id Node ID * @param Int $t Tenant ID * @param Array $nets Array of networks * @return int 0 means ok */ function start($n, $id, $t, $nets) { if ($n->getStatus() !== 0) { // Node is in running or building state return 0; } $rc = prepareNode($n, $id, $t, $nets); if ($rc !== 0) { // Failed to prepare the node return $rc; } list($bin, $flags) = $n->getCommand(); if ($bin == False || $flags == False) { // Invalid CMD line error_log('ERROR: ' . $GLOBALS['messages'][80046]); return 80046; } if (!chdir($n->getRunningPath())) { // Failed to change directory error_log('ERROR: ' . $GLOBALS['messages'][80047]); return 80047; } // Starting the node switch ($n->getNType()) { default: // Invalid node_type error_log('ERROR: ' . $GLOBALS['messages'][80038]); return 80028; case 'iol': $cmd = '/opt/unetlab/wrappers/iol_wrapper -T ' . $t . ' -D ' . $id . ' -t "' . $n->getName() . '" -F /opt/unetlab/addons/iol/bin/' . $n->getImage() . ' -d ' . $n->getDelay() . ' -e ' . $n->getEthernetCount() . ' -s ' . $n->getSerialCount(); // Adding Serial links foreach ($n->getSerials() as $interface_id => $interface) { if ($interface->getRemoteId() > 0) { $cmd .= ' -l ' . $interface_id . ':localhost:' . $interface->getRemoteId() . ':' . $interface->getRemoteIf(); } } $cmd .= ' -- ' . $flags . ' > ' . $n->getRunningPath() . '/wrapper.txt 2>&1 &'; break; case 'docker': $cmd = 'docker start -ai ' . $n->getUuid(); break; case 'dynamips': $cmd = '/opt/unetlab/wrappers/dynamips_wrapper -T ' . $t . ' -D ' . $id . ' -t "' . $n->getName() . '" -F /opt/unetlab/addons/dynamips/' . $n->getImage() . ' -d ' . $n->getDelay(); $cmd .= ' -- ' . $flags . ' > ' . $n->getRunningPath() . '/wrapper.txt 2>&1 &'; break; case 'qemu': $cmd = '/opt/unetlab/wrappers/qemu_wrapper -T ' . $t . ' -D ' . $id . ' -t "' . $n->getName() . '" -F ' . $bin . ' -d ' . $n->getDelay(); if ($n->getConsole() == 'vnc') { // Disable telnet (wrapper) console $cmd .= ' -x'; } $cmd .= ' -- ' . $flags . ' > ' . $n->getRunningPath() . '/wrapper.txt 2>&1 &'; break; } error_log('INFO: CWD is ' . getcwd()); error_log('INFO: starting ' . $cmd); exec($cmd, $o, $rc); if ($rc == 0 && $n->getNType() == 'qemu' && is_file($n->getRunningPath() . '/startup-config') && !is_file(is_file($n->getRunningPath() . '/.configured'))) { // Start configuration process touch($n->getRunningPath() . '/.lock'); $cmd = 'nohup /opt/unetlab/scripts/config_vios.py -a put -p ' . $n->getPort() . ' -f ' . $n->getRunningPath() . '/startup-config -t ' . ($n->getDelay() + 300) . ' &'; exec($cmd, $o, $rc); error_log('INFO: importing ' . $cmd); } if ($rc == 0 && $n->getNType() == 'docker') { // Need to configure each interface foreach ($n->getEthernets() as $interface_id => $interface) { // TODO must check each step against errors // ip link add docker3_4_5 type veth peer name vnet3_4_5 $cmd = 'ip link add docker' . $t . '_' . $id . '_' . $interface_id . ' type veth peer name vnet' . $t . '_' . $id . '_' . $interface_id; error_log('INFO: starting ' . $cmd); exec($cmd, $o, $rc); // ip link set dev vnet3_4_5 up $cmd = 'ip link set dev vnet' . $t . '_' . $id . '_' . $interface_id . ' up'; error_log('INFO: starting ' . $cmd); exec($cmd, $o, $rc); // brctl addif vnet0_1 vnet3_4_5 $cmd = 'brctl addif vnet' . $t . '_' . $interface->getNetworkId() . ' vnet' . $t . '_' . $id . '_' . $interface_id; error_log('INFO: starting ' . $cmd); exec($cmd, $o, $rc); // PID=$(docker inspect --format '{{ .State.Pid }}' docker3_4) # Must be greater than 0 $cmd = 'docker inspect --format "{{ .State.Pid }}" ' . $n->getUuid(); error_log('INFO: starting ' . $cmd); exec($cmd, $o, $rc); // ip link set netns ${PID} docker3_4_5 name eth0 address 22:ce:e0:99:04:05 up $cmd = 'ip link set netns ' . $o[0] . ' docker' . $t . '_' . $id . '_' . $interface_id . ' name eth0 address ' . '50:' . sprintf('%02x', $t) . ':' . sprintf('%02x', $id / 512) . ':' . sprintf('%02x', $id % 512) . ':00:' . sprintf('%02x', $interface_id) . ' up'; error_log('INFO: starting ' . $cmd); exec($cmd, $o, $rc); // /opt/unetlab/wrappers/nsenter -t ${PID} -n ip addr add 1.1.1.1/24 dev eth0 // /opt/unetlab/wrappers/nsenter -t ${PID} -n ip route add default via 1.1.1.254 } } return 0; }
/** * Function to start a node. * * @param Node $n Node * @param Int $id Node ID * @param Int $t Tenant ID * @param Array $nets Array of networks * @param int $scripttimeout Config Script Timeout * @return int 0 means ok */ function start($n, $id, $t, $nets, $scripttimeout) { if ($n->getStatus() !== 0) { // Node is in running or building state return 0; } $rc = prepareNode($n, $id, $t, $nets); if ($rc !== 0) { // Failed to prepare the node return $rc; } list($bin, $flags) = $n->getCommand(); if ($bin == False || $flags == False) { // Invalid CMD line error_log(date('M d H:i:s ') . 'ERROR: ' . $GLOBALS['messages'][80046]); return 80046; } if (!chdir($n->getRunningPath())) { // Failed to change directory error_log(date('M d H:i:s ') . 'ERROR: ' . $GLOBALS['messages'][80047]); return 80047; } // Starting the node switch ($n->getNType()) { default: // Invalid node_type error_log(date('M d H:i:s ') . 'ERROR: ' . $GLOBALS['messages'][80038]); return 80028; case 'iol': $cmd = '/opt/unetlab/wrappers/iol_wrapper -T ' . $t . ' -D ' . $id . ' -t "' . $n->getName() . '" -F /opt/unetlab/addons/iol/bin/' . $n->getImage() . ' -d ' . $n->getDelay() . ' -e ' . $n->getEthernetCount() . ' -s ' . $n->getSerialCount(); // Adding Serial links foreach ($n->getSerials() as $interface_id => $interface) { if ($interface->getRemoteId() > 0) { $cmd .= ' -l ' . $interface_id . ':localhost:' . $interface->getRemoteId() . ':' . $interface->getRemoteIf(); } } break; case 'docker': $cmd = 'docker -H=tcp://127.0.0.1:4243 start ' . $n->getUuid(); break; case 'vpcs': $cmd = '/opt/vpcsu/bin/vpcs -m ' . $id . ' -N ' . $n->getName(); break; case 'dynamips': $cmd = '/opt/unetlab/wrappers/dynamips_wrapper -T ' . $t . ' -D ' . $id . ' -t "' . $n->getName() . '" -F /opt/unetlab/addons/dynamips/' . $n->getImage() . ' -d ' . $n->getDelay(); break; case 'qemu': $cmd = '/opt/unetlab/wrappers/qemu_wrapper -T ' . $t . ' -D ' . $id . ' -t "' . $n->getName() . '" -F ' . $bin . ' -d ' . $n->getDelay(); if ($n->getConsole() == 'vnc') { // Disable telnet (wrapper) console $cmd .= ' -x'; } break; } // Special Case for xrv - csr1000v - vIOS - vIOSL - Docker if (($n->getTemplate() == 'xrv' || $n->getTemplate() == 'csr1000v' || $n->getTemplate() == 'asav' || $n->getTemplate() == 'titanium') && is_file($n->getRunningPath() . '/config.iso') && !is_file($n->getRunningPath() . '/.configured') && $n->getConfig() != 0) { $flags .= ' -cdrom config.iso'; } if (($n->getTemplate() == 'vios' || $n->getTemplate() == 'viosl2') && is_file($n->getRunningPath() . '/minidisk') && !is_file($n->getRunningPath() . '/.configured') && $n->getConfig() != 0) { $flags .= ' -drive file=minidisk,if=virtio,bus=0,unit=1,cache=none'; } if (($n->getTemplate() == 'vmx' || $n->getTemplate() == 'vsrx') && is_file($n->getRunningPath() . '/config.iso') && !is_file($n->getRunningPath() . '/.configured') && $n->getConfig() != 0) { $flags .= ' -drive file=config.iso,if=virtio,media=cdrom,index=2'; } if ($n->getTemplate() == 'vsrxng' && is_file($n->getRunningPath() . '/config.iso') && !is_file($n->getRunningPath() . '/.configured') && $n->getConfig() != 0) { $flags .= ' -drive file=config.iso,if=ide,media=cdrom,index=2'; } if ($n->getTemplate() == 'pfsense' && is_file($n->getRunningPath() . '/config.iso') && !is_file($n->getRunningPath() . '/.configured') && $n->getConfig() != 0) { $flags .= ' -cdrom config.iso'; } if ($n->getNType() != 'docker' && $n->getNType() != 'vpcs') { $cmd .= ' -- ' . $flags . ' > ' . $n->getRunningPath() . '/wrapper.txt 2>&1 &'; } if ($n->getNType() == 'vpcs') { $cmd .= $flags . ' > ' . $n->getRunningPath() . '/wrapper.txt 2>&1 &'; } error_log(date('M d H:i:s ') . 'INFO: CWD is ' . getcwd()); error_log(date('M d H:i:s ') . 'INFO: starting ' . $cmd); exec($cmd, $o, $rc); if ($rc == 0 && $n->getNType() == 'qemu' && is_file($n->getRunningPath() . '/startup-config') && !is_file($n->getRunningPath() . '/.configured') && $n->getConfig() != 0) { // Start configuration process or check if bootstrap is done touch($n->getRunningPath() . '/.lock'); $cmd = 'nohup /opt/unetlab/scripts/config_' . $n->getTemplate() . '.py -a put -p ' . $n->getPort() . ' -f ' . $n->getRunningPath() . '/startup-config -t ' . ($n->getDelay() + $scripttimeout) . ' > /dev/null 2>&1 &'; exec($cmd, $o, $rc); error_log(date('M d H:i:s ') . 'INFO: importing ' . $cmd); } if ($rc == 0 && $n->getNType() == 'docker') { // Need to configure each interface foreach ($n->getEthernets() as $interface_id => $interface) { // TODO must check each step against errors // ip link add docker3_4_5 type veth peer name vnet3_4_5 $cmd = 'ip link add docker' . $t . '_' . $id . '_' . $interface_id . ' type veth peer name vnet' . $t . '_' . $id . '_' . $interface_id; error_log(date('M d H:i:s ') . 'INFO: starting ' . $cmd); exec($cmd, $o, $rc); // ip link set dev vnet3_4_5 up $cmd = 'ip link set dev vnet' . $t . '_' . $id . '_' . $interface_id . ' up'; error_log(date('M d H:i:s ') . 'INFO: starting ' . $cmd); exec($cmd, $o, $rc); // brctl addif vnet0_1 vnet3_4_5 $cmd = 'brctl addif vnet' . $t . '_' . $interface->getNetworkId() . ' vnet' . $t . '_' . $id . '_' . $interface_id; error_log(date('M d H:i:s ') . 'INFO: starting ' . $cmd); exec($cmd, $o, $rc); // PID=$(docker inspect --format '{{ .State.Pid }}' docker3_4) # Must be greater than 0 $cmd = 'docker -H=tcp://127.0.0.1:4243 inspect --format "{{ .State.Pid }}" ' . $n->getUuid(); error_log(date('M d H:i:s ') . 'INFO: starting ' . $cmd); exec($cmd, $o, $rc); // ip link set netns ${PID} docker3_4_5 name eth0 address 22:ce:e0:99:04:05 up $cmd = 'ip link set netns ' . $o[1] . ' docker' . $t . '_' . $id . '_' . $interface_id . ' name eth0 address ' . '50:' . sprintf('%02x', $t) . ':' . sprintf('%02x', $id / 512) . ':' . sprintf('%02x', $id % 512) . ':00:' . sprintf('%02x', $interface_id) . ' up'; error_log(date('M d H:i:s ') . 'INFO: starting ' . $cmd); exec($cmd, $o, $rc); // /opt/unetlab/wrappers/nsenter -t ${PID} -n ip addr add 1.1.1.1/24 dev eth0 // /opt/unetlab/wrappers/nsenter -t ${PID} -n ip route add default via 1.1.1.254 } // Start configuration process touch($n->getRunningPath() . '/.lock'); $cmd = 'nohup /opt/unetlab/scripts/config_' . $n->getTemplate() . '.py -a put -i ' . $n->getUuid() . ' -f ' . $n->getRunningPath() . '/startup-config -t ' . ($n->getDelay() + 300) . ' > /dev/null 2>&1 &'; exec($cmd, $o, $rc); error_log(date('M d H:i:s ') . 'INFO: importing ' . $cmd); } return 0; }
/** * Prepares a Node to be displayed in a navigation tree. * This function is used in the construction of: * - Test project specification -> we want ALL test cases defined in test project. * - Test execution -> we only want the test cases linked to a test plan. * * IMPORTANT: * when analising a container node (Test Suite) if it is empty and we have requested * some sort of filtering NODE WILL BE PRUNED. * * * status: one of the possible execution status of a test case. * * * tplan_tcases: map with testcase versions linked to test plan. * due to the multiples uses of this function, null has several meanings * * When we want to build a Test Project specification tree, * WE SET it to NULL, because we are not interested in a test plan. * * When we want to build a Test execution tree, we dont set it deliverately * to null, but null can be the result of NO tcversion linked => EMPTY TEST PLAN * * * status can be an array with multple values, to do OR search. * added version info from test cases in return data structure. * ignore_inactive_testcases: useful when building a Test Project Specification tree * to be used in the add/link test case to Test Plan. * tck_map: Test Case Keyword map: * null => no filter * empty map => filter out ALL test case ALWAYS * initialized map => filter out test case ONLY if NOT present in map. * * * added argument: * $map_node_tccount * key => node_id * values => node test case count * node name (useful only for debug purpouses * * IMPORTANT: this new argument is not useful for tree rendering * but to avoid duplicating logic to get test case count * * * return: map with keys: * 'total_count' * 'passed' * 'failed' * 'blocked' * 'not run' * * @internal revisions */ function prepareNode(&$db, &$node, &$decoding_info, &$map_node_tccount, $tck_map = null, &$tplan_tcases = null, $filters = null, $options = null) { static $status_descr_list; static $debugMsg; static $tables; static $my; static $enabledFiltersOn; static $activeVersionClause; static $filterOnTCVersionAttribute; static $filtersApplied; static $users2filter; static $results2filter; static $testPlanIsNotEmpty; $tpNode = null; if (!$tables) { $debugMsg = 'Class: ' . __CLASS__ . ' - ' . 'Method: ' . __FUNCTION__ . ' - '; $tables = tlObjectWithDB::getDBTables(array('tcversions', 'nodes_hierarchy', 'testplan_tcversions')); $status_descr_list = array_keys($decoding_info['status_descr_code']); $status_descr_list[] = 'testcase_count'; $my = array(); $my['options'] = array('hideTestCases' => 0, 'showTestCaseID' => 1, 'viewType' => 'testSpecTree', 'getExternalTestCaseID' => 1, 'ignoreInactiveTestCases' => 0, 'ignoreActiveTestCases' => 0); // added importance here because of "undefined" error in event log $my['filters'] = array('status' => null, 'assignedTo' => null, 'importance' => null, 'executionType' => null, 'filter_tc_id' => null); $my['options'] = array_merge($my['options'], (array) $options); $my['filters'] = array_merge($my['filters'], (array) $filters); $enabledFiltersOn['testcase_id'] = isset($my['filters']['filter_tc_id']); $enabledFiltersOn['testcase_name'] = isset($my['filters']['filter_testcase_name']); $enabledFiltersOn['executionType'] = isset($my['filters']['filter_execution_type']); $enabledFiltersOn['importance'] = isset($my['filters']['filter_priority']); $enabledFiltersOn['custom_fields'] = isset($my['filters']['filter_custom_fields']); $enabledFiltersOn['keywords'] = isset($tck_map); $filterOnTCVersionAttribute = $enabledFiltersOn['executionType'] || $enabledFiltersOn['importance']; $filtersApplied = false; foreach ($enabledFiltersOn as $filterValue) { $filtersApplied = $filtersApplied || $filterValue; } $activeVersionClause = $filterOnTCVersionAttribute ? " AND TCV.active=1 " : ''; $users2filter = isset($my['filters']['filter_assigned_user']) ? $my['filters']['filter_assigned_user'] : null; $results2filter = isset($my['filters']['filter_result_result']) ? $my['filters']['filter_result_result'] : null; $testPlanIsNotEmpty = !is_null($tplan_tcases) && count($tplan_tcases) > 0; } $tcase_counters = array_fill_keys($status_descr_list, 0); $node_type = isset($node['node_type_id']) ? $decoding_info['node_id_descr'][$node['node_type_id']] : null; if ($node_type == 'testcase') { // ABSOLUTELY First implicit filter to be applied when test plan is not empty. // is our test case present on Test Spec linked to Test Plan ? if ($testPlanIsNotEmpty && !isset($tplan_tcases[$node['id']])) { $node = null; } else { if ($enabledFiltersOn['keywords'] && !isset($tck_map[$node['id']]) || $enabledFiltersOn['testcase_name'] && stripos($node['name'], $my['filters']['filter_testcase_name']) === FALSE || $enabledFiltersOn['testcase_id'] && $node['id'] != $my['filters']['filter_tc_id']) { unset($tplan_tcases[$node['id']]); $node = null; } else { if ($my['options']['viewType'] == 'executionTree') { $tpNode = isset($tplan_tcases[$node['id']]) ? $tplan_tcases[$node['id']] : null; if (!($delete_node = is_null($tpNode))) { $delete_node = !is_null($results2filter) && !isset($results2filter[$tpNode['exec_status']]); if (!$delete_node && !is_null($users2filter)) { $somebody_wanted_but_nobody_there = isset($users2filter[TL_USER_SOMEBODY]) && !is_numeric($tpNode['user_id']); $unassigned_wanted_but_someone_assigned = isset($users2filter[TL_USER_NOBODY]) && !is_null($tpNode['user_id']); $wrong_user = !isset($users2filter[TL_USER_NOBODY]) && !isset($users2filter[TL_USER_SOMEBODY]) && !isset($users2filter[$tpNode['user_id']]); $delete_node = $unassigned_wanted_but_someone_assigned || $wrong_user || $somebody_wanted_but_nobody_there; } } if ($delete_node) { unset($tplan_tcases[$node['id']]); $node = null; } else { $externalID = ''; $node['tcversion_id'] = $tpNode['tcversion_id']; $node['version'] = $tpNode['version']; if ($my['options']['getExternalTestCaseID']) { if (!isset($tpNode['external_id'])) { $sql = " /* {$debugMsg} - line:" . __LINE__ . " */ " . " SELECT TCV.tc_external_id AS external_id " . " FROM {$tables['tcversions']} TCV " . " WHERE TCV.id=" . $node['tcversion_id']; $result = $db->exec_query($sql); $myrow = $db->fetch_array($result); $externalID = $myrow['external_id']; } else { $externalID = $tpNode['external_id']; } } $node['external_id'] = $externalID; } } if ($node && $my['options']['ignoreInactiveTestCases']) { // there are active tcversions for this node ??? // I'm doing this instead of creating a test case manager object, because // I think is better for performance. // // ======================================================================================= // 20070106 - franciscom // Postgres Problems // ======================================================================================= // Problem 1 - SQL Syntax // While testing with postgres // SELECT count(TCV.id) NUM_ACTIVE_VERSIONS -> Error // // At least for what I remember using AS to create COLUMN ALIAS IS REQUIRED and Standard // while AS is NOT REQUIRED (and with some DBMS causes errors) when you want to give a // TABLE ALIAS // // Problem 2 - alias case // At least in my installation the aliases column name is returned lower case, then // PHP fails when: // if($myrow['NUM_ACTIVE_VERSIONS'] == 0) // // $sql = " /* {$debugMsg} - line:" . __LINE__ . " */ " . " SELECT count(TCV.id) AS num_active_versions " . " FROM {$tables['tcversions']} TCV, {$tables['nodes_hierarchy']} NH " . " WHERE NH.parent_id=" . $node['id'] . " AND NH.id = TCV.id AND TCV.active=1"; $result = $db->exec_query($sql); $myrow = $db->fetch_array($result); if ($myrow['num_active_versions'] == 0) { $node = null; } } // TICKET 4496: added inactive testcase filter if ($node && $my['options']['ignoreActiveTestCases']) { $sql = " /* {$debugMsg} - line:" . __LINE__ . " */ " . " SELECT count(TCV.id) AS num_active_versions " . " FROM {$tables['tcversions']} TCV, {$tables['nodes_hierarchy']} NH " . " WHERE NH.parent_id=" . $node['id'] . " AND NH.id = TCV.id AND TCV.active=1"; $result = $db->exec_query($sql); $myrow = $db->fetch_array($result); if ($myrow['num_active_versions'] != 0) { $node = null; } } } } // ------------------------------------------------------------------- // ------------------------------------------------------------------- if ($node && ($my['options']['viewType'] == 'testSpecTree' || $my['options']['viewType'] == 'testSpecTreeForTestPlan')) { $sql = " /* {$debugMsg} - line:" . __LINE__ . " */ " . " SELECT COALESCE(MAX(TCV.id),0) AS targetid, TCV.tc_external_id AS external_id" . " FROM {$tables['tcversions']} TCV, {$tables['nodes_hierarchy']} NH " . " WHERE NH.id = TCV.id {$activeVersionClause} AND NH.parent_id={$node['id']} " . " GROUP BY TCV.tc_external_id "; $rs = $db->get_recordset($sql); if (is_null($rs)) { $node = null; } else { $node['external_id'] = $rs[0]['external_id']; $target_id = $rs[0]['targetid']; if ($filterOnTCVersionAttribute) { switch ($my['options']['viewType']) { case 'testSpecTreeForTestPlan': // Try to get info from linked tcversions // Platform is not needed $sql = " /* {$debugMsg} - line:" . __LINE__ . " */ " . " SELECT DISTINCT TPTCV.tcversion_id AS targetid " . " FROM {$tables['tcversions']} TCV " . " JOIN {$tables['nodes_hierarchy']} NH " . " ON NH.id = TCV.id {$activeVersionClause} " . " AND NH.parent_id={$node['id']} " . " JOIN {$tables['testplan_tcversions']} TPTCV " . " ON TPTCV.tcversion_id = TCV.id " . " AND TPTCV.testplan_id = " . " {$my['filters']['setting_testplan']}"; $rs = $db->get_recordset($sql); $target_id = !is_null($rs) ? $rs[0]['targetid'] : $target_id; break; } $sql = " /* {$debugMsg} - line:" . __LINE__ . " */ " . " SELECT TCV.execution_type " . " FROM {$tables['tcversions']} TCV " . " WHERE TCV.id = {$target_id} "; if ($enabledFiltersOn['executionType']) { $sql .= " AND TCV.execution_type = " . " {$my['filters']['filter_execution_type']} "; } if ($enabledFiltersOn['importance']) { $sql .= " AND TCV.importance = " . " {$my['filters']['filter_priority']} "; } $rs = $db->fetchRowsIntoMap($sql, 'execution_type'); if (is_null($rs)) { $node = null; } } } if (!is_null($node)) { // needed to avoid problems when using json_encode with EXTJS unset($node['childNodes']); $node['leaf'] = true; } } // ------------------------------------------------------------------- // ======================================================================== foreach ($tcase_counters as $key => $value) { $tcase_counters[$key] = 0; } if (isset($tpNode['exec_status'])) { $tc_status_descr = $decoding_info['status_code_descr'][$tpNode['exec_status']]; } else { $tc_status_descr = "not_run"; } $init_value = $node ? 1 : 0; $tcase_counters[$tc_status_descr] = $init_value; $tcase_counters['testcase_count'] = $init_value; if ($my['options']['hideTestCases']) { $node = null; } // ======================================================================== } // if($node_type == 'testcase') // ======================================================================== if (isset($node['childNodes']) && is_array($node['childNodes'])) { // node has to be a Test Suite ? $childNodes =& $node['childNodes']; $childNodesQty = count($childNodes); for ($idx = 0; $idx < $childNodesQty; $idx++) { $current =& $childNodes[$idx]; // I use set an element to null to filter out leaf menu items if (is_null($current)) { continue; } $counters_map = prepareNode($db, $current, $decoding_info, $map_node_tccount, $tck_map, $tplan_tcases, $my['filters'], $my['options']); foreach ($counters_map as $key => $value) { $tcase_counters[$key] += $counters_map[$key]; } } foreach ($tcase_counters as $key => $value) { $node[$key] = $tcase_counters[$key]; } if (isset($node['id'])) { $map_node_tccount[$node['id']] = array('testcount' => $node['testcase_count'], 'name' => $node['name']); } // node must be destroyed if empty had we have using filtering conditions if (($filtersApplied || !is_null($tplan_tcases)) && !$tcase_counters['testcase_count'] && $node_type != 'testproject') { $node = null; } } else { if ($node_type == 'testsuite') { // does this means is an empty test suite ??? - franciscom 20080328 $map_node_tccount[$node['id']] = array('testcount' => 0, 'name' => $node['name']); // If is an EMPTY Test suite and we have added filtering conditions, // We will destroy it. if ($filtersApplied || !is_null($tplan_tcases)) { $node = null; } } } return $tcase_counters; }
/** * */ function buildContentForTestPlanBranch(&$dbHandler, $itemsTree, $branchRoot, $tplanID, $platformIDSet, &$docInfo, $decode, &$tplanMgr, $options = null) { $linkedBy = array(); $branch_tsuites = null; $contentByPlatform = array(); $pnOptions = array('hideTestCases' => 0); $pnOptions = array_merge($pnOptions, (array) $options); $tsuite = new testsuite($dbHandler); $tInfo = $tsuite->get_by_id($branchRoot); $tInfo['node_type_id'] = $decode['node_descr_id']['testsuite']; $docInfo->title = htmlspecialchars(isset($tInfo['name']) ? $tInfo['name'] : $docInfo->testplan_name); $children_tsuites = $tsuite->tree_manager->get_subtree_list($branchRoot, $decode['node_descr_id']['testsuite']); if (!is_null($children_tsuites) and trim($children_tsuites) != "") { $branch_tsuites = explode(',', $children_tsuites); } $branch_tsuites[] = $branchRoot; $metrics = (object) array('estimatedExecTime' => null, 'realExecTime' => null); $filters = array('tsuites_id' => $branch_tsuites); foreach ($platformIDSet as $platform_id) { // IMPORTANTE NOTICE: // This need to be initialized on each iteration because prepareNode() make changes on it. $tInfo['childNodes'] = isset($itemsTree['childNodes']) ? $itemsTree['childNodes'] : null; $filters['platform_id'] = $platform_id; $metrics->estimatedExecTime[$platform_id] = null; $metrics->realExecTime[$platform_id] = null; $avalon = $tplanMgr->getLTCVNewGeneration($tplanID, $filters, array('addExecInfo' => true)); $k2l = array_keys($avalon); foreach ($k2l as $key) { $linkedBy[$platform_id][$key] = $avalon[$key][$platform_id]; } // After architecture changes on how CF design values for Test Cases are // managed, we need the test case version ID and not test case ID // In addition if we loop over Platforms we need to save this set each time!!! $items2loop = !is_null($linkedBy[$platform_id]) ? array_keys($linkedBy[$platform_id]) : null; if (!is_null($items2loop)) { foreach ($items2loop as $rdx) { $metrics->estimatedExecTime[$platform_id][] = $linkedBy[$platform_id][$rdx]['tcversion_id']; } } // Prepare Node -> pn $pnFilters = null; $dummy4reference = null; $contentByPlatform[$platform_id]['childNodes'] = array(); if (!is_null($linkedBy[$platform_id])) { prepareNode($dbHandler, $tInfo, $decode, $dummy4reference, $dummy4reference, $linkedBy[$platform_id], $pnFilters, $pnOptions); $contentByPlatform[$platform_id]['childNodes'] = array($tInfo); } } $metrics->realExecTime = $linkedBy; return array($contentByPlatform, $metrics); }
$branch_tsuites = explode(',', $children_tsuites); } $branch_tsuites[] = $args->itemID; $filters = array('tsuites_id' => $branch_tsuites, 'platform_id' => $platform_id); $tp_tcs = $tplan_mgr->get_linked_tcversions($args->tplan_id, $filters); $tcase_filter = !is_null($tp_tcs) ? array_keys((array) $tp_tcs) : null; $tInfo['node_type_id'] = $hash_descr_id['testsuite']; $tInfo['childNodes'] = isset($subtree['childNodes']) ? $subtree['childNodes'] : null; //@TODO: schlundus, can we speed up with NO_EXTERNAL? $dummy = null; $pnFilters = null; $pnOptions = array('hideTestCases' => 0); // 3624 $pnOptions = array_merge($pnOptions, $pnOptionsAdd); // prepareNode($db,$tInfo,$decoding_hash,$dummy,$dummy,$tp_tcs,SHOW_TESTCASES); prepareNode($db, $tInfo, $decoding_hash, $dummy, $dummy, $tp_tcs, $pnFilters, $pnOptions); $doc_info->title = htmlspecialchars(isset($tInfo['name']) ? $tInfo['name'] : $doc_info->testplan_name); $tree['childNodes'] = array($tInfo); $treeForPlatform[$platform_id] = $tree; } break; } // switch($doc_info->content_range) // Create list of execution id, that will be used to compute execution time if // CF_EXEC_TIME custom field exists and is linked to current testproject $doc_data->statistics = null; if ($printingOptions['metrics']) { $executed_qty = 0; if ($tp_tcs) { foreach ($tp_tcs as $tcase_id => $info) { if ($info['exec_status'] != $status_descr_code['not_run']) {
/** * @return array a map: * key => node_id * values => node test case count considering test cases presents * in the nodes of the subtree that starts on node_id * Means test case can not be sons/daughters of node_id. * * node name (useful only for debug purpouses). */ function get_testplan_nodes_testcount(&$db, $tproject_id, $tproject_name, $tplan_id, $tplan_name, $keywordsFilter = null) { $tplan_mgr = new testplan($db); $tproject_mgr = new testproject($db); $tree_manager = $tplan_mgr->tree_manager; $tcase_node_type = $tree_manager->node_descr_id['testcase']; $hash_descr_id = $tree_manager->get_available_node_types(); $hash_id_descr = array_flip($hash_descr_id); $resultsCfg = config_get('results'); $decoding_hash = array('node_id_descr' => $hash_id_descr, 'status_descr_code' => $resultsCfg['status_code'], 'status_code_descr' => $resultsCfg['code_status']); $test_spec = $tproject_mgr->get_subtree($tproject_id, RECURSIVE_MODE); $linkedFilters = array('keyword_id' => $keywordsFilter->items); $tplan_tcases = $tplan_mgr->get_linked_tcversions($tplan_id, $linkedFilters); if (is_null($tplan_tcases)) { $tplan_tcases = array(); } $test_spec['name'] = $tproject_name; $test_spec['id'] = $tproject_id; $test_spec['node_type_id'] = $hash_descr_id['testproject']; $map_node_tccount = array(); if ($test_spec) { $tck_map = null; if (!is_null($keywordsFilter)) { $tck_map = $tproject_mgr->get_keywords_tcases($tproject_id, $keywordsFilter->items, $keywordsFilter->type); } //@TODO: schlundus, can we speed up with NO_EXTERNAL? $filters = null; $options = array('hideTestCases' => 0, 'viewType' => 'executionTree'); $testcase_counters = prepareNode($db, $test_spec, $decoding_hash, $map_node_tccount, $tck_map, $tplan_tcases, $filters, $options); $test_spec['testcase_count'] = $testcase_counters['testcase_count']; } return $map_node_tccount; }
/** * Function to start a node. * * @param Node $n Node * @param Int $id Node ID * @param Int $t Tenant ID * @param Array $nets Array of networks * @return int 0 means ok */ function start($n, $id, $t, $nets) { if ($n->getStatus() !== 0) { // Node is in running or building state return 0; } $rc = prepareNode($n, $id, $t, $nets); if ($rc !== 0) { // Failed to prepare the node return $rc; } list($bin, $flags) = $n->getCommand(); if ($bin == False || $flags == False) { // Invalid CMD line error_log('ERROR: ' . $GLOBALS['messages'][80046]); return 80046; } if (!chdir($n->getRunningPath())) { // Failed to change directory error_log('ERROR: ' . $GLOBALS['messages'][80047]); return 80047; } // Starting the node switch ($n->getNType()) { default: // Invalid node_type error_log('ERROR: ' . $GLOBALS['messages'][80038]); return 80028; case 'iol': $cmd = '/opt/unetlab/wrappers/iol_wrapper -T ' . $t . ' -D ' . $id . ' -t "' . $n->getName() . '" -F /opt/unetlab/addons/iol/bin/' . $n->getImage() . ' -d ' . $n->getDelay() . ' -e ' . $n->getEthernetCount() . ' -s ' . $n->getSerialCount(); // Adding Serial links foreach ($n->getSerials() as $interface_id => $interface) { if ($interface->getRemoteId() > 0) { $cmd .= ' -l ' . $interface_id . ':localhost:' . $interface->getRemoteId() . ':' . $interface->getRemoteIf(); } } break; case 'dynamips': $cmd = '/opt/unetlab/wrappers/dynamips_wrapper -T ' . $t . ' -D ' . $id . ' -t "' . $n->getName() . '" -F /opt/unetlab/addons/dynamips/' . $n->getImage() . ' -d ' . $n->getDelay(); break; case 'qemu': $cmd = '/opt/unetlab/wrappers/qemu_wrapper -T ' . $t . ' -D ' . $id . ' -t "' . $n->getName() . '" -F ' . $bin . ' -d ' . $n->getDelay(); if ($n->getConsole() == 'vnc') { // Disable telnet (wrapper) console $cmd .= ' -x'; } break; } $cmd .= ' -- ' . $flags . ' > ' . $n->getRunningPath() . '/wrapper.txt 2>&1 &'; exec($cmd, $o, $rc); error_log('INFO: CWD is ' . getcwd()); error_log('INFO: starting ' . $cmd); return 0; }
/** * Creates data for tree menu used on : * - Execution of Test Cases * - Remove Test cases from test plan * * @internal Revisions: * * 20111031 - franciscom - TICKET */ function generateExecTree(&$db, &$menuUrl, $env, $filters, $options) { $tplan_tcases = null; $tck_map = null; $idx = 0; $apply_other_filters = true; $map_node_tccount = array(); $renderOpt = array(); $renderAux = array(); $resultsCfg = config_get('results'); $tplan_mgr = new testplan($db); $tcase_mgr = new testcase($db); $tproject_mgr = new testproject($db); // --------------------------------------------------------------------------------------------- // initialize configuration and options // --------------------------------------------------------------------------------------------- $tproject_id = $env['tproject_id']; $tplan_id = $env['tplan_id']; $my['filters'] = normalizeFilters($filters); $node_types = $tproject_mgr->tree_manager->get_available_node_types(); $renderAux['hash_id_descr'] = array_flip($node_types); $renderAux['testCasePrefix'] = $tproject_mgr->getTestCasePrefix($tproject_id) . config_get('testcase_cfg')->glue_character; $decoding_hash = array('node_id_descr' => $renderAux['hash_id_descr'], 'status_descr_code' => $resultsCfg['status_code'], 'status_code_descr' => $resultsCfg['code_status']); $renderOpt['showTestCaseID'] = config_get('treemenu_show_testcase_id'); $renderOpt['hideTCs'] = isset($filters->hide_testcases) ? $filters->hide_testcases : false; $renderOpt['showTestSuiteContents'] = isset($filters->show_testsuite_contents) ? $filters->show_testsuite_contents : true; $renderOpt['useCounters'] = isset($options->useCounters) ? $options->useCounters : false; $renderOpt['colorOptions'] = isset($options->colorOptions) ? $options->colorOptions : null; $renderOpt['tc_action_enabled'] = isset($options->tc_action_enabled) ? $options->tc_action_enabled : false; $colorBySelectedBuild = isset($options->testcases_colouring_by_selected_build) ? $options->testcases_colouring_by_selected_build : false; // --------------------------------------------------------------------------------------------- // echo __LINE__; $test_spec = getTestSpec4ExecTree($tplan_mgr->tree_manager, $env, $my['filters']); // new dBug($my['filters']); // new dBug($test_spec); if ($doIt = !is_null($test_spec)) { if (is_null($my['filters']->filter_tc_id) || $my['filters']->filter_tc_id >= 0) { list($tplan_tcases, $tck_map) = getTPlanTCases4ExecTree($db, $tproject_mgr, $tplan_mgr, $env, $my['filters']); } // new dBug($tplan_tcases); // new dBug($tck_map); if (is_null($tplan_tcases)) { $tplan_tcases = array(); $apply_other_filters = false; } else { $tplan_tcases = applyFilters4ExeTree($tplan_mgr, $tplan_tcases, $env['tplan_id'], $resultsCfg, $filters); // new dBug($tplan_tcases); } $apply_other_filters = !is_null($tplan_tcases) && count($tplan_tcases) > 0; // BUGID 3450 - Change colors/counters in exec tree. // Means: replace exec status in filtered array $tplan_tcases by the one of last execution of selected build. // Since this changes exec status, replacing is done after filtering by status. // It has to be done before call to prepareNode() though, because that one sets the counters according to status. if ($apply_other_filters && (!is_null($renderOpt['colorOptions']) && $colorBySelectedBuild)) { $tplan_tcases = updateStatus4ExecTree($db, $tplan_tcases, $env['tplan_id'], $filters->selected_build, $resultsCfg); } // 20080224 - franciscom - // After reviewing code, seems that assignedTo has no sense because tp_tcs // has been filtered. // Then to avoid changes to prepareNode() due to include_unassigned, // seems enough to set assignedTo to 0, if include_unassigned==true $pnFilters['assignedTo'] = $my['filters']->filter_assigned_user_include_unassigned ? null : $my['filters']->filter_assigned_user; $keys2init = array('filter_testcase_name', 'filter_execution_type', 'filter_priority'); foreach ($keys2init as $keyname) { $pnFilters[$keyname] = isset($filters->{$keyname}) ? $filters->{$keyname} : null; } $pnOptions = array('hideTestCases' => $renderOpt['hideTCs'], 'viewType' => 'executionTree'); // new dBug($tplan_tcases); // new dBug($tck_map); $testcase_counters = prepareNode($db, $test_spec, $decoding_hash, $map_node_tccount, $tck_map, $tplan_tcases, $pnFilters, $pnOptions); foreach ($testcase_counters as $key => $value) { $test_spec[$key] = $testcase_counters[$key]; } $keys = array_keys($tplan_tcases); // IMPORTANT NOTICE: process makes changes on $test_spec renderExecTreeNode($env, 1, $test_spec, $tplan_tcases, $menuUrl, $renderOpt, $renderAux); } // if($test_spec) $treeMenu = new stdClass(); $treeMenu->menustring = ''; $treeMenu->rootnode = new stdClass(); $treeMenu->rootnode->name = $test_spec['text']; $treeMenu->rootnode->id = $test_spec['id']; $treeMenu->rootnode->leaf = $test_spec['leaf']; $treeMenu->rootnode->text = $test_spec['text']; $treeMenu->rootnode->position = $test_spec['position']; $treeMenu->rootnode->href = $test_spec['href']; $menustring = ''; // new dBug($test_spec['childNodes']); if ($doIt) { // Change key ('childNodes') to the one required by Ext JS tree. $menustring = str_ireplace('childNodes', 'children', json_encode($test_spec['childNodes'])); // Remove null elements (Ext JS tree do not like it ). // :null happens on -> "children":null,"text" that must become "children":[],"text" // $menustring = str_ireplace(array(':null',',null','null,'),array(':[]','',''), $menustring); $menustring = str_ireplace(array(':null', ',null', 'null,', 'null'), array(':[]', '', '', ''), $menustring); } // new dBug($treeMenu->rootnode->href); // $menustring = '[{"id":"12","name":"GABA","children":[{"id":"19","name":"API","children":[{"id":"20","name":"set execution result","children":[{"id":"21","name":"set exec result - test plan WITHOUT PLATFORMS","children":[],"leaf":true,"testlink_node_type":"testcase","testlink_node_name":"set exec result - test plan WITHOUT PLATFORMS","text":"PTW-1<\/b>:set exec result - test plan WITHOUT PLATFORMS<\/span>","position":"1000","href":"javascript:ST(21,22)"},{"id":"23","name":"set exec result - test plan WITH WRONG PLATFORM NAME","children":[],"leaf":true,"testlink_node_type":"testcase","testlink_node_name":"set exec result - test plan WITH WRONG PLATFORM NAME","text":"PTW-2<\/b>:set exec result - test plan WITH WRONG PLATFORM NAME<\/span>","position":"1010","href":"javascript:ST(23,24)"},{"id":"25","name":"set exec result - test plan WITH WRONG PLATFORM ID","children":[],"leaf":true,"testlink_node_type":"testcase","testlink_node_name":"set exec result - test plan WITH WRONG PLATFORM ID","text":"PTW-3<\/b>:set exec result - test plan WITH WRONG PLATFORM ID<\/span>","position":"1020","href":"javascript:ST(25,26)"}],"leaf":false,"testlink_node_type":"testsuite","testlink_node_name":"set execution result","text":"set execution result (3)","position":"1","href":"javascript:STS(20,0)"}],"leaf":false,"testlink_node_type":"testsuite","testlink_node_name":"API","text":"API (3)","position":"0","href":"javascript:STS(19,0)"},{"id":"32","name":"Custom Fields Management","children":[{"id":"33","name":"EXPORT - Go back management","children":[],"leaf":true,"testlink_node_type":"testcase","testlink_node_name":"EXPORT - Go back management","text":"PTW-6<\/b>:EXPORT - Go back management<\/span>","position":"1000","href":"javascript:ST(33,34)"},{"id":"35","name":"IMPORT - Go back management","children":[],"leaf":true,"testlink_node_type":"testcase","testlink_node_name":"IMPORT - Go back management","text":"PTW-7<\/b>:IMPORT - Go back management<\/span>","position":"1010","href":"javascript:ST(35,36)"}],"leaf":false,"testlink_node_type":"testsuite","testlink_node_name":"Custom Fields Management","text":"Custom Fields Management (2)","position":"2","href":"javascript:STS(32,0)"}],"leaf":false,"testlink_node_type":"testsuite","testlink_node_name":"GABA","text":"GABA (5)","position":"1","href":"javascript:STS(12,0)"}]'; $treeMenu->menustring = $menustring; // new dBug($menustring); return array($treeMenu, $keys); }