From 07352939a3914a01359298f20b737db818186a7e Mon Sep 17 00:00:00 2001 From: Panos Date: Fri, 24 Sep 2010 15:03:19 +0200 Subject: [PATCH] adding new files for testing the column configuration panel (modified only my_slice.css) --- planetlab/css/my_slice.css | 33 +- planetlab/includes/plc_visibletags2.php | 88 ++ planetlab/slices/slice2.php | 962 ++++++++++++++++++++ plekit/php/columns.php | 557 ++++++++++++ plekit/php/tophat_api.php | 292 ++++++ plekit/php/updateColumn.php | 49 ++ plekit/php/updateConf.php | 29 + plekit/table/columns.js | 1078 +++++++++++++++++++++++ 8 files changed, 3087 insertions(+), 1 deletion(-) create mode 100644 planetlab/includes/plc_visibletags2.php create mode 100644 planetlab/slices/slice2.php create mode 100644 plekit/php/columns.php create mode 100644 plekit/php/tophat_api.php create mode 100644 plekit/php/updateColumn.php create mode 100644 plekit/php/updateConf.php create mode 100644 plekit/table/columns.js diff --git a/planetlab/css/my_slice.css b/planetlab/css/my_slice.css index c79af1f..d33730f 100644 --- a/planetlab/css/my_slice.css +++ b/planetlab/css/my_slice.css @@ -40,4 +40,35 @@ table#leases_data { #leases_buttons { padding: 0px 10px 10px 10px; } #leases_clear { position: relative; left: 30%;} #leases_submit { position: relative; left: 60%; } - + + +/*panos: some additional styles for the column configuration */ + +div#toggle-container-my-slice-nodes-configuration { + background: #f8f8f8; +} + +div.out{background-color:white; color:black} +div.in{background-color:#CAE8EA; color:#4f6b72} +div.selected{background-color:gray; color:black} +div.invisible{display:none} + +.myslice { + font: 11px Arial, Helvetica, sans-serif; + color: gray; +} + +.myslice .title { + font: 11px; + font-weight: bold; +} + +.myslice .desc { + font: 11px; + font-style: italic; +} + +.myslice .subtitle{ + color: #bb9c61; +} + diff --git a/planetlab/includes/plc_visibletags2.php b/planetlab/includes/plc_visibletags2.php new file mode 100644 index 0000000..10341c3 --- /dev/null +++ b/planetlab/includes/plc_visibletags2.php @@ -0,0 +1,88 @@ +api=$api; + $this->type=$type; + $this->columns=NULL; + } + + // returns an ordered set of columns - compute only once + function columns () { + # if cached + if ($this->columns != NULL) + return $this->columns; + + // scan tag types to find relevant additional columns + $tag_types = $this->api->GetTagTypes(array('category'=>"$type*/ui*")); + + $columns = array(); + foreach ($tag_types as $tag_type) { + $tagname=$tag_type['tagname']; + $column=array(); + $column['tagname']=$tagname; + // defaults + $column['header']=$tagname; + $column['rank']=$tagname; + $column['type']='string'; + $column['description']=$tag_type['description']; + // split category and parse any setting + $category_tokens=explode('/',$tag_type['category']); + foreach ($category_tokens as $token) { + $assign=explode('=',$token); + if (count($assign)==2) + $column[$assign[0]]=$assign[1]; + } + $columns []= $column; + } + + // sort upon 'rank' + usort ($columns, create_function('$col1,$col2','return strcmp($col1["header"],$col2["header"]);')); + + # cache for next time + $this->columns=$columns; +// plc_debug('columns',$columns); + return $columns; + } + + // extract tagname + function column_names () { + return array_map(create_function('$tt','return $tt["tagname"];'),$this->columns()); + } + + // to add with array_merge to the headers part of the Plekit Table + function headers () { + $headers=array(); + $columns=$this->columns(); + foreach ($columns as $column) + //panos: needed a few more fields in the header array + $headers[$column['header']]=array('header'=>$column['header'],'type'=>$column['type'],'tagname'=>$column['tagname'],'title'=>$column['description']); + /* + if ($column['header'] == $column['tagname']) + $headers[$column['header']]=$column['type']; + else + $headers[$column['header']]=array('type'=>$column['type'],'title'=>$column['description']); + */ + return $headers; + } + + // to add with array_merge to the notes part of the Plekit Table + function notes () { + $notes=array(); + $columns=$this->columns(); + foreach ($columns as $column) + if ($column['header'] != $column['tagname']) + $notes []= strtoupper($column['header']) . ' = ' . $column['description']; + return $notes; + } + +} +?> diff --git a/planetlab/slices/slice2.php b/planetlab/slices/slice2.php new file mode 100644 index 0000000..385c8b5 --- /dev/null +++ b/planetlab/slices/slice2.php @@ -0,0 +1,962 @@ + +'); + +// -------------------- admins potentially need to get full list of users +ini_set('memory_limit','32M'); + +// -------------------- +// recognized URL arguments +$slice_id=intval($_GET['id']); +if ( ! $slice_id ) { plc_error('Malformed URL - id not set'); return; } + +//////////////////// +// Get all columns as we focus on only one entry +$slices= $api->GetSlices( array($slice_id)); + +if (empty($slices)) { + drupal_set_message ("Slice " . $slice_id . " not found"); + return; + } + +$slice=$slices[0]; + +// pull all node info to vars +$name= $slice['name']; +$expires = date( "d/m/Y", $slice['expires'] ); +$site_id= $slice['site_id']; + +$person_ids=$slice['person_ids']; + +// get peers +$peer_id= $slice['peer_id']; +$peers=new Peers ($api); +$local_peer = ! $peer_id; + +// gets site info +$sites= $api->GetSites( array( $site_id ) ); +$site=$sites[0]; +$site_name= $site['name']; +$max_slices = $site['max_slices']; + +//////////////////////////////////////// building blocks for the renew area +// Constants +global $DAY; $DAY = 24*60*60; +global $WEEK; $WEEK = 7 * $DAY; +global $MAX_WEEKS; $MAX_WEEKS= 8; // weeks from today +global $GRACE_DAYS; $GRACE_DAYS=10; // days for renewal promoted on top +global $NOW; $NOW=mktime(); + +//////////////////////////////////////////////////////////// +// make the renew area on top and open if the expiration time is less than 10 days from now +function renew_needed ($slice) { + global $DAY, $NOW, $GRACE_DAYS; + $current_exp=$slice['expires']; + + $time_left = $current_exp - $NOW; + $visible = $time_left/$DAY <= $GRACE_DAYS; + return $visible; +} + +function renew_area ($slice,$site,$visible) { + global $DAY, $WEEK, $MAX_WEEKS, $GRACE_DAYS, $NOW; + + $current_exp=$slice['expires']; + $current_text = gmstrftime("%A %b-%d-%y %T %Z", $current_exp); + $max_exp= $NOW + ($MAX_WEEKS * $WEEK); // seconds since epoch + $max_text = gmstrftime("%A %b-%d-%y %T %Z", $max_exp); + + // xxx some extra code needed to enable this area only if the slice description is OK: + // description and url must be non void + $toggle= + new PlekitToggle('renew',"Expires $current_text - Renew this slice", + array("bubble"=> + "Enter this zone if you wish to renew your slice", + 'visible'=>$visible)); + $toggle->start(); + + // xxx message could take roles into account + if ($site['max_slices']<=0) { + $message= <<< EOF +

Slice creation and renewal have been temporarily disabled for your +site details page to find +out more about your site's nodes, and how to contact your site's PI(s) +and Technical Contact(s).

+EOF; + echo $message; + + } else { + // xxx this is a rough cut and paste from the former UI + // showing a datepicker view could be considered as well with some extra work + // calculate possible extension lengths + $selectors = array(); + foreach ( array ( 1 => "One more week", + 2 => "Two more weeks", + 3 => "Three more weeks", + 4 => "One more month" ) as $weeks => $text ) { + $candidate_exp = $current_exp + $weeks*$WEEK; + if ( $candidate_exp < $max_exp) { + $selectors []= array('display'=>"$text (" . gmstrftime("%A %b-%d-%y %T %Z", $candidate_exp) . ")", + 'value'=>$candidate_exp); + $max_renewal_weeks=$weeks; + $max_renewal_date= gmstrftime("%A %b-%d-%y %T %Z", $candidate_exp); + } + } + + if ( empty( $selectors ) ) { + print <<< EOF +
+Slices annot be renewed more than $MAX_WEEKS weeks from now, i.e. not beyond $max_text. +For this reason, the current slice cannot be renewed any further into the future, try again closer to expiration date. +
+EOF; + } else { + print <<< EOF +
+

You must provide a short description as well as a link to a project website before renewing it. +Do not provide bogus information; if a complaint is lodged against your slice +and PlanetLab Operations is unable to determine what the normal behavior of your slice is, +your slice may be deleted to resolve the complaint.

+

NOTE: +Slices cannot be renewed beyond another $max_renewal_weeks week(s) ($max_renewal_date). +

+
+EOF; + + $form = new PlekitForm (l_actions(), + array('action'=>'renew-slice', + 'slice_id'=>$slice['slice_id'])); + $form->start(); + print $form->label_html('expires','Duration'); + print $form->select_html('expires',$selectors,array('label'=>'Pick one')); + print $form->submit_html('renew-button','Renew'); + $form->end(); + } + } + + $toggle->end(); +} + +//////////////////////////////////////////////////////////// + +$am_in_slice = in_array(plc_my_person_id(),$person_ids); + +if ($am_in_slice) { + drupal_set_title("My slice " . $name); + } else { + drupal_set_title("Slice " . $name); +} + +$privileges = ( $local_peer && (plc_is_admin() || plc_is_pi() || $am_in_slice)); +$tags_privileges = $privileges || plc_is_admin(); + +$tabs=array(); +$tabs [] = tab_nodes_slice($slice_id); +$tabs [] = tab_site($site_id); + +// are these the right privileges for deletion ? +if ($privileges) { + $tabs ['Delete']= array('url'=>l_actions(), + 'method'=>'post', + 'values'=>array('action'=>'delete-slice','slice_id'=>$slice_id), + 'bubble'=>"Delete slice $name", + 'confirm'=>"Are you sure to delete slice $name"); + + $tabs["Events"]=array_merge(tablook_event(), + array('url'=>l_event("Slice","slice",$slice_id), + 'bubble'=>"Events for slice $name")); + $tabs["Comon"]=array_merge(tablook_comon(), + array('url'=>l_comon("slice_id",$slice_id), + 'bubble'=>"Comon page about slice $name")); +} + +plekit_linetabs($tabs); + +//////////////////////////////////////// +$peers->block_start($peer_id); + +//////////////////////////////////////// renewal area +// (1) close to expiration : show on top and open + +if ($local_peer ) { + $renew_visible = renew_needed ($slice); + if ($renew_visible) renew_area ($slice,$site,true); + } + + +//////////////////// details +// default for opening the details section or not ? +if ($local_peer) { + $default_show_details = true; + } else { + $default_show_details = ! $renew_visible; + } + +$toggle = + new PlekitToggle ('my-slice-details',"Details", + array('bubble'=> + 'Display and modify details for that slice', + 'visible'=>get_arg('show_details',$default_show_details))); +$toggle->start(); + +$details=new PlekitDetails($privileges); +$details->form_start(l_actions(),array('action'=>'update-slice', + 'slice_id'=>$slice_id, + 'name'=>$name)); + +$details->start(); +if (! $local_peer) { + $details->th_td("Peer",$peers->peer_link($peer_id)); + $details->space(); + } + + +$details->th_td('Name',$slice['name']); +$details->th_td('Description',$slice['description'],'description', + array('input_type'=>'textarea', + 'width'=>50,'height'=>5)); +$details->th_td('URL',$slice['url'],'url',array('width'=>50)); +$details->tr_submit("submit","Update Slice"); +$details->th_td('Expires',$expires); +$details->th_td('Instantiation',$slice['instantiation']); +$details->th_td('Site',l_site_obj($site)); +// xxx show the PIs here +//$details->th_td('PIs',...); +$details->end(); + +$details->form_end(); +$toggle->end(); + +//////////////////// persons +$person_columns = array('email','person_id','first_name','last_name','roles'); +// get persons in slice +if (!empty($person_ids)) + $persons=$api->GetPersons(array('person_id'=>$slice['person_ids']),$person_columns); +// just propose to add everyone else +// xxx this is maybe too much for admins as it slows stuff down +// as regular persons can see only a fraction of the db anyway +$potential_persons= + $api->GetPersons(array('~person_id'=>$slice['person_ids'], + 'peer_id'=>NULL, + 'enabled'=>true), + $person_columns); +$count=count($persons); + +$toggle= + new PlekitToggle ('my-slice-persons',"$count users", + array('bubble'=> + 'Manage accounts attached to this slice', + 'visible'=>get_arg('show_persons',false))); +$toggle->start(); + +////////// people currently in +// visible: +// hide if both current+add are included +// so user can chose which section is of interest +// show otherwise +$toggle_persons = new PlekitToggle ('my-slice-persons-current', + "$count people currently in $name", + array('visible'=>get_arg('show_persons_current',!$privileges))); +$toggle_persons->start(); + +$headers=array(); +$headers['email']='string'; +$headers['first']='string'; +$headers['last']='string'; +$headers['R']='string'; +if ($privileges) $headers[plc_delete_icon()]="none"; +$table=new PlekitTable2('persons',$headers,'0', NULL, + array('notes_area'=>false)); +$form=new PlekitForm(l_actions(),array('slice_id'=>$slice['slice_id'])); +$form->start(); +$table->start(); +if ($persons) foreach ($persons as $person) { + $table->row_start(); + $table->cell(l_person_obj($person)); + $table->cell($person['first_name']); + $table->cell($person['last_name']); + $table->cell(plc_vertical_table ($person['roles'])); + if ($privileges) $table->cell ($form->checkbox_html('person_ids[]',$person['person_id'])); + $table->row_end(); +} +// actions area +if ($privileges) { + + // remove persons + $table->tfoot_start(); + + $table->row_start(); + $table->cell($form->submit_html ("remove-persons-from-slice","Remove selected"), + array('hfill'=>true,'align'=>'right')); + $table->row_end(); + } +$table->end(); +$toggle_persons->end(); + +////////// people to add +if ($privileges) { + $count=count($potential_persons); + $toggle_persons = new PlekitToggle ('my-slice-persons-add', + "$count people may be added to $name", + array('visible'=>get_arg('show_persons_add',false))); + $toggle_persons->start(); + if ( ! $potential_persons ) { + // xxx improve style + echo "

No person to add

"; + } else { + $headers=array(); + $headers['email']='string'; + $headers['first']='string'; + $headers['last']='string'; + $headers['R']='string'; + $headers['+']="none"; + $options = array('notes_area'=>false, + 'search_width'=>15, + 'pagesize'=>8); + // show search for admins only as other people won't get that many names to add + if ( ! plc_is_admin() ) $options['search_area']=false; + + $table=new PlekitTable2('add_persons',$headers,'0',NULL,$options); + $form=new PlekitForm(l_actions(),array('slice_id'=>$slice['slice_id'])); + $form->start(); + $table->start(); + if ($potential_persons) foreach ($potential_persons as $person) { + $table->row_start(); + $table->cell(l_person_obj($person)); + $table->cell($person['first_name']); + $table->cell($person['last_name']); + $table->cell(plc_vertical_table ($person['roles'])); + $table->cell ($form->checkbox_html('person_ids[]',$person['person_id'])); + $table->row_end(); + } + // add users + $table->tfoot_start(); + $table->row_start(); + $table->cell($form->submit_html ("add-persons-in-slice","Add selected"), + array('hfill'=>true,'align'=>'right')); + $table->row_end(); + $table->end(); + $form->end(); + } + $toggle_persons->end(); +} +$toggle->end(); + +//////////////////////////////////////////////////////////// Nodes +// the nodes details to display here +// (1) we search for the tag types for which 'category' matches 'node*/ui*' +// all these tags will then be tentatively displayed in this area +// (2) further information can also be optionally specified in the category: +// (.) we split the category with '/' and search for assignments of the form var=value +// (.) header can be set to supersede the column header (default is tagname) +// (.) rank can be used for ordering the columns (default is tagname) +// (.) type is passed to the javascript table, for sorting (default is 'string') + +// minimal list as a start +//$node_fixed_columns = array('hostname','node_id','slice_ids_whitelist','boot_state','last_contact'); +// create a VisibleTags object : basically the list of tag columns to show +//$visibletags = new VisibleTags ($api, 'node'); +//$visiblecolumns = $visibletags->column_names(); +//$node_columns=array_merge($node_fixed_columns,$visiblecolumns); + + + +/* TEST PlekitColumns */ + +//prepare fix and configurable columns + +$fix_columns = array(); +$fix_columns[]=array('tagname'=>'hostname', 'header'=>'hostname', 'type'=>'string', 'title'=>'The name of the node'); +$fix_columns[]=array('tagname'=>'peer_id', 'header'=>'AU', 'type'=>'string', 'title'=>'Authority'); +$fix_columns[]=array('tagname'=>'run_level', 'header'=>'ST', 'type'=>'string', 'title'=>'Status'); + +$visibletags = new VisibleTags ($api, 'node'); +$visibletags->columns(); +$tag_columns = $visibletags->headers(); + +$extra_columns = array(); +$extra_columns[]=array('tagname'=>'site_id', 'header'=>'SN', 'type'=>'string', 'title'=>'Site name', 'description'=>'Site name'); + +//$configurable_columns = array_merge($tag_columns, $extra_columns); +//usort ($configurable_columns, create_function('$col1,$col2','return strcmp($col1["header"],$col2["header"]);')); + + +$first_time_configuration = 'false'; +$default_configuration = "hostname:f|ST:f|AU:f|Rw|AST"; +$column_configuration = ""; + +$DescTags=$api->GetSliceTags (array('slice_id'=>$slice['slice_id'])); +for ($i=0; $iGOT CONFIGURATION: ".$column_configuration); + +//$test_configuration = "hostname:f|AU:f|ST:f|Rw|AST"; +//print("

Parsing configuration ".$test_configuration); + + +$ConfigureColumns =new PlekitColumns($column_configuration, $fix_columns, $tag_columns, $extra_columns); + +$node_requested_data = $ConfigureColumns->node_tags(); +$nodes=$api->GetNodes(array('node_id'=>$slice['node_ids']),$node_requested_data); +$potential_nodes=$api->GetNodes(array('~node_id'=>$slice['node_ids']),$node_requested_data); + +//$nodes = array(); +//$potential_nodes = array(); + +//print("

RESULTS for ".print_r(array('~node_id'=>$slice['node_ids']))); +//print_r($nodes); + +$count=count($nodes); + +$toggle=new PlekitToggle ('my-slice-nodes',"$count nodes", + array('bubble'=> + 'Manage nodes attached to this slice', + 'visible'=>get_arg('show_nodes',false))); +$toggle->start(); + + +$toggle_nodes=new PlekitToggle('my-slice-nodes-configuration', + "Node table column configuration", + array('visible'=>'1')); + +$toggle_nodes->start(); + + +//usort ($table_headers, create_function('$col1,$col2','return strcmp($col1["header"],$col2["header"]);')); + +//print("

HEADERS TO SHOW

"); +//print_r($headersToShow); + +//print("

TABLE HEADERS

"); +//print_r($table_headers); + +print("

"); +print(""); +print(""); +print(""); +print(""); +//print(""); + +$ConfigureColumns->javascript_vars(); + +$ConfigureColumns->configuration_panel_html(true); + +print("
"); + +$toggle_nodes->end(); + + +////////// nodes currently in + +$count=count($nodes); + +$toggle_nodes=new PlekitToggle('my-slice-nodes-current', + "$count nodes currently in $name", + array('visible'=>get_arg('show_nodes_current',!$privileges))); + +$toggle_nodes->start(); + +$edit_header = array(); +if ($privileges) $edit_header[plc_delete_icon()]="none"; + +$table_options = array('search_width'=>15, + 'pagesize'=>20); +//$table=new PlekitTable2('nodes',$headers,'1',$table_options); +//$table=new PlekitTable2('nodes_pairwise',array_merge($ConfigureColumns->plekit_columns_get_headers(),$edit_header),NULL,$headersToShow, $table_option); +//$headersToShow = $ConfigureColumns->plekit_columns_visible(); + +$table=new PlekitTable2('nodes',array_merge($ConfigureColumns->get_headers(),$edit_header),NULL,NULL, $table_option); + +$form=new PlekitForm(l_actions(),array('slice_id'=>$slice['slice_id'])); +$form->start(); +$table->start(); +if ($nodes) foreach ($nodes as $node) { + $table->row_start(); + + $table->cell($node['node_id'], array('display'=>'none')); + $table->cell(l_node_obj($node)); + + $peers->cell($table,$node['peer_id']); + $run_level=$node['run_level']; + list($label,$class) = Node::status_label_class_($node); + $table->cell ($label,array('name'=>'ST', 'class'=>$class, 'display'=>'table-cell')); + + +$ConfigureColumns->cells($table, $node); + + + + if ($privileges) $table->cell ($form->checkbox_html('node_ids[]',$node['node_id'])); + $table->row_end(); +} +// actions area +if ($privileges) { + + // remove nodes + $table->tfoot_start(); + + $table->row_start(); + $table->cell($form->submit_html ("remove-nodes-from-slice","Remove selected"), + array('hfill'=>true,'align'=>'right')); + $table->row_end(); + } +$table->end(); +$toggle_nodes->end(); + +////////// nodes to add +if ($privileges) { + $new_potential_nodes = array(); + if ($potential_nodes) foreach ($potential_nodes as $node) { + $emptywl=empty($node['slice_ids_whitelist']); + $inwl = (!emptywl) and in_array($slice['slice_id'],$node['slice_ids_whitelist']); + if ($emptywl or $inwl) + $new_potential_nodes[]=$node; + } + $potential_nodes=$new_potential_nodes; + + $count=count($potential_nodes); + $toggle_nodes=new PlekitToggle('my-slice-nodes-add', + "$count more nodes available", + array('visible'=>get_arg('show_nodes_add',false))); + $toggle_nodes->start(); + + if ( ! $potential_nodes ) { + // xxx improve style + echo "

No node to add

"; + } else { + + $edit_header = array(); + if ($privileges) $edit_header['+']="none"; + + //$table=new PlekitTable2('add_nodes',$headers,'1', $table_options); + $table=new PlekitTable2('add_nodes',array_merge($ConfigureColumns->get_headers(), $edit_header),NULL,$headersToShow, $table_options); + $form=new PlekitForm(l_actions(), + array('slice_id'=>$slice['slice_id'])); + $form->start(); + $table->start(); + + if ($potential_nodes) foreach ($potential_nodes as $node) { + $table->row_start(); + + $table->cell($node['node_id'], array('display'=>'none')); + $table->cell(l_node_obj($node)); + + $peers->cell($table,$node['peer_id']); + $run_level=$node['run_level']; + list($label,$class) = Node::status_label_class_($node); + $table->cell ($label,array('name'=>'ST', 'class'=>$class, 'display'=>'table-cell')); + +$ConfigureColumns->cells($table, $node); + + $table->cell ($form->checkbox_html('node_ids[]',$node['node_id'])); + $table->row_end(); + } + // add nodes + $table->tfoot_start(); + $table->row_start(); + $table->cell($form->submit_html ("add-nodes-in-slice","Add selected"), + array('hfill'=>true,'align'=>'right')); + $table->row_end(); + $table->end(); + $form->end(); + } + $toggle_nodes->end(); +} +$toggle->end(); + +//////////////////////////////////////////////////////////// Tags +//if ( $local_peer ) { + $tags=$api->GetSliceTags (array('slice_id'=>$slice_id)); + function get_tagname ($tag) { return $tag['tagname'];} + $tagnames = array_map ("get_tagname",$tags); + + $toggle = new PlekitToggle ('slice-tags',count_english_warning($tags,'tag'), + array('bubble'=>'Inspect and set tags on tat slice', + 'visible'=>get_arg('show_tags',false))); + $toggle->start(); + + $headers=array( + "Name"=>"string", + "Value"=>"string", + "Node"=>"string", + "NodeGroup"=>"string"); + if ($tags_privileges) $headers[plc_delete_icon()]="none"; + + $table_options=array("notes_area"=>false,"pagesize_area"=>false,"search_width"=>10); + $table=new PlekitTable2("slice_tags",$headers,'0',NULL,$table_options); + $form=new PlekitForm(l_actions(), + array('slice_id'=>$slice['slice_id'])); + $form->start(); + $table->start(); + if ($tags) { + foreach ($tags as $tag) { + $node_name = "ALL"; + if ($tag['node_id']) { + $nodes = $api->GetNodes(array('node_id'=>$tag['node_id'])); + if($nodes) { + $node = $nodes[0]; + $node_name = $node['hostname']; + } + } + $nodegroup_name="n/a"; + if ($tag['nodegroup_id']) { + $nodegroup=$api->GetNodeGroups(array('nodegroup_id'=>$tag['nodegroup_id'])); + if ($nodegroup) { + $nodegroup = $nodegroup[0]; + $nodegroup_name = $nodegroup['groupname']; + } + } + $table->row_start(); + $table->cell(l_tag_obj($tag)); + $table->cell($tag['value']); + $table->cell($node_name); + $table->cell($nodegroup_name); + if ($tags_privileges) $table->cell ($form->checkbox_html('slice_tag_ids[]',$tag['slice_tag_id'])); + $table->row_end(); + } + } + if ($tags_privileges) { + $table->tfoot_start(); + $table->row_start(); + $table->cell($form->submit_html ("delete-slice-tags","Remove selected"), + array('hfill'=>true,'align'=>'right')); + $table->row_end(); + + $table->row_start(); + function tag_selector ($tag) { + return array("display"=>$tag['tagname'],"value"=>$tag['tag_type_id']); + } + $all_tags= $api->GetTagTypes( array ("category"=>"slice*","-SORT"=>"+tagname"), array("tagname","tag_type_id")); + $selector_tag=array_map("tag_selector",$all_tags); + + function node_selector($node) { + return array("display"=>$node["hostname"],"value"=>$node['node_id']); + } + $all_nodes = $api->GetNodes( array ("node_id" => $slice['node_ids']), array("hostname","node_id")); + $selector_node=array_map("node_selector",$all_nodes); + + function nodegroup_selector($ng) { + return array("display"=>$ng["groupname"],"value"=>$ng['nodegroup_id']); + } + $all_nodegroups = $api->GetNodeGroups( array("groupname"=>"*"), array("groupname","nodegroup_id")); + $selector_nodegroup=array_map("nodegroup_selector",$all_nodegroups); + + $table->cell($form->select_html("tag_type_id",$selector_tag,array('label'=>"Choose Tag"))); + $table->cell($form->text_html("value","",array('width'=>8))); + $table->cell($form->select_html("node_id",$selector_node,array('label'=>"All Nodes"))); + $table->cell($form->select_html("nodegroup_id",$selector_nodegroup,array('label'=>"No Nodegroup"))); + $table->cell($form->submit_html("add-slice-tag","Set Tag"),array('columns'=>2,'align'=>'left')); + $table->row_end(); + } + + $table->end(); + $form->end(); + $toggle->end(); +//} + + +//////////////////////// renew slice +if ($local_peer ) { + if ( ! $renew_visible) renew_area ($slice,$site,false); + } + +$peers->block_end($peer_id); + +// Print footer +include 'plc_footer.php'; + +?> + + + diff --git a/plekit/php/columns.php b/plekit/php/columns.php new file mode 100644 index 0000000..987d9be --- /dev/null +++ b/plekit/php/columns.php @@ -0,0 +1,557 @@ + +'); + +class PlekitColumns { + +var $column_configuration = ""; +var $reference_node = ""; +var $first_time = false; + +var $all_headers = array(); +var $this_table_headers = array(); +var $visible_headers = array(); + +var $all_columns = array(); +var $fix_columns = array(); +var $tag_columns = array(); +var $extra_columns = array(); + +var $table_ids; + +var $HopCount = array(); + + function PlekitColumns ($column_configuration, $fix_columns, $tag_columns, $extra_columns=NULL, $this_table_headers=NULL) { + + $this->fix_columns = $fix_columns; + $this->tag_columns = $tag_columns; + $this->extra_columns = $extra_columns; + + //print("

FIX

"); + //print_r($this->fix_columns); + //print("

TAG

"); + //print_r($this->tag_columns); + //print("

EXTRA

"); + //print_r($this->extra_columns); + + $this->prepare_headers(); + $this->parse_configuration($column_configuration); + + $this->visible_headers = $this->get_visible(); + + //print("

VISIBLE

"); + //print_r($this->visible_headers); + + $this->all_columns = array_merge($fix_columns, $tag_columns, $extra_columns); +} + + + +/* + +INFO + +*/ + +function prepare_headers() { + +foreach ($this->fix_columns as $column) { +$this->all_headers[$column['header']]=array('header'=>$column['header'],'type'=>$column['type'],'tagname'=>$column['tagname'],'title'=>$column['title'], 'description'=>$column['title'], 'label'=>$column['header'], 'fixed'=>true, 'visible'=>false); +} + +foreach ($this->tag_columns as $column) { +$this->all_headers[$column['header']]=array('header'=>$column['header'],'type'=>$column['type'],'tagname'=>$column['tagname'],'title'=>$column['tagname'], 'description'=>$column['title'], 'label'=>$this->removeDuration($column['header']),'visible'=>false); +} + +foreach ($this->extra_columns as $column) { +$this->all_headers[$column['header']]=array('header'=>$column['header'],'type'=>$column['type'],'tagname'=>$column['tagname'],'title'=>$column['tagname'], 'description'=>$column['title'], 'label'=>$this->removeDuration($column['header']),'visible'=>false); +} + +return $this->all_headers; + +} + + +function get_headers() { + +return $this->all_headers; + +} + +function node_tags() { + + $fetched_tags = array('node_id'); + + foreach ($this->all_headers as $h) + { + if ($h['visible'] == true) + $fetched_tags[] = $h['tagname']; + } + + return $fetched_tags; +} + +function print_headers() { + + $headers = ""; + + foreach ($this->all_headers as $h) + { + $headers.="
".$h['header'].":".$h['label'].":".$h['tagname']; + } + return $headers; +} + +function get_visible() { + + $visibleHeaders = array(); + + foreach ($this->all_headers as $h) + { + if ($h['visible'] == true) + $visibleHeaders[] = $h['header']; + } + return $visibleHeaders; +} + +function headerIsVisible($header_name) { + +$headersToShow = $this->visible_headers; + + + if ($this->inTypeC($header_name."w") || $this->inTypeC($header_name."m") || $this->inTypeC($header_name."y")) + return (in_array($header_name."w", $headersToShow) || in_array($header_name."m", $headersToShow) || in_array($header_name."y", $headersToShow)); + else + return in_array($header_name, $headersToShow); +} + + + + +/* + +CONFIGURATION + +*/ + + +function parse_configuration($column_configuration) { + + $this->column_configuration = $column_configuration; + //$this->default_configuration = $default_configuration; + + $columns_conf = explode("|", $column_configuration); + foreach ($columns_conf as $c) + { + $conf = explode(":",$c); + + $this->all_headers[$conf[0]]['visible']=true; + //print("

".$conf[0]."should be visible now"); + //print_r($this->all_headers[$conf[0]]); + + if ($conf[1] == "f") + continue; + + else if ($this->inTypeC($conf[0])) + { + $this->all_headers[$conf[0]]['duration']= substr($conf[0], strlen($conf[0])-1, strlen($conf[0])); + $threshold = explode(",",$conf[1]); + $this->all_headers[$conf[0]]['threshold']=$threshold; + } + else if ($this->inTypeD($conf[0])) + { + $this->reference_node = $conf[1]; + $this->reference_node = "planetlab-europe-07.ipv6.lip6.fr"; + $this->all_headers[$conf[0]]['refnode']=$this->reference_node; + $threshold = explode(",",$conf[1]); + $this->all_headers[$conf[0]]['threshold']=$threshold; + } + else if ($this->inTypeA($conf[0])) + { + $exclude_list = explode(",",$conf[1]); + $this->all_headers[$conf[0]]['exclude_list']=$exclude_list; + } + else + { + $threshold = explode(",",$conf[1]); + $this->all_headers[$conf[0]]['threshold']=$threshold; + } + } +} + + + + + +/* + +CELLS + +*/ + +function getHopCount($ref_node, $planetlab_nodes) +{ + +$tophat_auth = array( 'AuthMethod' => 'password', 'Username' => 'guest', 'AuthString' => 'guest'); +$tophat_api = new TopHatAPI($tophat_auth); + +$traceroute = $tophat_api->Get('traceroute', 'latest', array('src_hostname' => $ref_node, 'dst_hostname' => $planetlab_nodes), array('dst_hostname', 'hop_count') ); + +$hopcount = array(); + +if ($traceroute) foreach ($traceroute as $t) +$hopcount[$t['dst_hostname']]=$t['hop_count']; +return $hopcount; +} + + +//Depending on the columns selected more data might need to be fetched from +//external sources + +function fetch_data($nodes) { + +//TopHat pairwise data + + if ($this->reference_node != "") + { + $dd = array(); + + if ($nodes) foreach ($nodes as $n) + $dd[] = $n['hostname']; + + if ($potential_nodes) foreach ($potential_nodes as $n) + $dd[] = $n['hostname']; + + print("Calling tophat api for reference node = ".$this->reference_node); + $st = time() + microtime(); + $HopCount = $this->getHopCount($this->reference_node, $dd); + printf(" (%.2f ms)
", (time() + microtime()-$st)*100); + //print_r($HopCount); + } + +} + + +function excludeItems($value, $exclude_list, $hh) { + + if ($value == "") + $value = "n/a"; + + if ($exclude_list) + if (in_array($value, $exclude_list)) + return array($value, array('name'=>$hh, 'display'=>'table-cell')); + else + return array($value, array('name'=>$hh, 'display'=>'table-cell')); + + return array($value, array('name'=>$hh, 'display'=>'table-cell')); +} + +function checkThreshold($value, $threshold, $hh) { + + if ($value == "") + return array("n/a", array('name'=>$hh, 'display'=>'table-cell')); + + if ($threshold) + if ((float) $value >= (float) $threshold[0] && (float) $value <= (float) $threshold[1]) + return array(round($value,1), array('name'=>$hh, 'display'=>'table-cell')); + else + return array(round($value,1), array('name'=>$hh, 'display'=>'table-cell')); + + return array(round($value,1), array('name'=>$hh, 'display'=>'table-cell')); +} + + +function cells($table, $node) { + + +foreach ($this->all_headers as $h) +{ + +if (!$h['fixed'] && $h['visible']) +{ +if ($this->inTypeC($h['header'])) +{ + $tagname = $h['tagname']; + $value = $node[$tagname]; + $v = $this->checkThreshold($value, $h['threshold'], $h['header']); + $table->cell($v[0],$v[1]); +} +else if ($this->inTypeB($h['header'])) +{ + $value = $node[$h['tagname']]; + $v = $this->checkThreshold($value, $h['threshold'], $h['header']); + $table->cell($v[0],$v[1]); +} +else if ($this->inTypeD($h['header'])) +{ + $value = $this->HopCount[$node['hostname']]; + $v = $this->excludeItems($value, $h['threshold'], $h['header']); + $table->cell($v[0],$v[1]); +} +else if ($this->inTypeA($h['header'])) +{ + $value = $node[$h['tagname']]; + $v = $this->excludeItems($value, $h['exclude_list'], $h['header']); + $table->cell($v[0],$v[1]); +} +else +{ + $value = $node[$h['tagname']]; + $table->cell($value,array('name'=>$h['header'], 'display'=>'table-cell')); +} +} +else + $table->cell("??", array('name'=>$h['header'], 'display'=>'none')); + +} + +} + + +/* + +HTML + +*/ + + +function javascript_vars() { + +print(""); + +$all_columns_string = ""; +foreach ($this->all_headers as $h) + $all_columns_string.= $h['header'].","; + +print(""); + +} + +function configuration_panel_html($showDescription) { + + +if ($showDescription) + $table_width = 700; +else + $table_width = 350; + +print(""); +print(""); + +if ($showDescription) + print(""); + +print(""); + +if ($showDescription) +{ + print(""); +} + +print(""); + +if ($showDescription) + print(""); + +print("
Add/delete columnsColumn description and configuration
"); + + print('
'); +print (""); + $prev_label=""; + $optionclass = "out"; + foreach ($this->all_headers as $h) + { + if ($h['header'] == "hostname") + continue; + + if ($h['fixed']) + $disabled = "disabled=true"; + else + $disabled = ""; + + if ($this->headerIsVisible($h['label'])) + { + $selected = "checked=true"; + //print("header ".$h['label']." checked!"); + } + else + { + $selected = ""; + } + + if ($prev_label == $h['label']) + continue; + + $prev_label = $h['label']; + + print (""); + } + + print("
".$h['label']." ".$h['title']." 
"); + print("
            
"); +//print(""); +//print(""); +print(""); +print(" "); +print(" 
"); +} + +function column_filter () { + +echo <<< EOF + +Highlight +

+ +EOF; +} + + function column_html ($colHeader, $colName, $colId, $fulldesc, $visible) { + + if ($visible) + $display = 'display:table-cell'; + else + $display = 'color:red;display:none'; + + return " + +

$colHeader
+ + "; + } + + function column_fix_html ($colHeader, $colName, $colId) { + + $display = 'display:table-cell'; + + $res=""; + $res.= "
$colHeader
"; + + return $res; + } + + +function graph_html($colHeader) { + + return "

Show details on mouse over"; + + } + +function threshold_html($colHeader) { + + $updatecall = "updateColumnThreshold('".$colHeader."',window.document.getElementById('min".$colHeader."').value,window.document.getElementById('max".$colHeader."').value);"; + + $bubble="Grey-out values between (low) and (high)  "; + + return $bublle; +} + + +/* + +UTILS + +*/ + +//simple strings +function inTypeA($header_name) { + $typeA = array('ST','SN','RES','OS','NRR','NTP','NSR','NSF','NDS','NTH','NEC','LRN','LCY','LPR','LCN','LAT','LON','IP','ASN','AST'); + return in_array($header_name, $typeA); +} + +//integers +function inTypeB($header_name) { + $typeB = array('BW','DS','MS','CC','CR','AS','DU','CN'); + return in_array($header_name, $typeB); +} + +//statistical values +function inTypeC($header_name) { + $typeC = array('Rw','Rm','Ry','Lw','Lm','Ly','Sw','Sm','Sy','CFw','CFm','CFy','BUw','BUm','BUy','MUw','MUm','MUy','SSHw','SSHm','SSHy'); + return in_array($header_name, $typeC); +} + +//tophat +function inTypeD($header_name) { + $typeD = array('HC'); + return in_array($header_name, $typeD); +} + + +function removeDuration($header) +{ + if ($this->inTypeC($header)) + return substr($header, 0, strlen($header)-1); + else + return $header; +} + +} + +?> + + diff --git a/plekit/php/tophat_api.php b/plekit/php/tophat_api.php new file mode 100644 index 0000000..50eb146 --- /dev/null +++ b/plekit/php/tophat_api.php @@ -0,0 +1,292 @@ +auth = $auth; + $this->server = $server; + $this->port = $port; + $this->path = $path; + $this->cainfo = $cainfo; + $this->errors = array(); + $this->trace = array(); + $this->calls = array(); + $this->multicall = false; + } + + function error_log($error_msg, $backtrace_level = 1) + { + $backtrace = debug_backtrace(); + $file = $backtrace[$backtrace_level]['file']; + $line = $backtrace[$backtrace_level]['line']; + + $this->errors[] = 'TopHatAPI error: ' . $error_msg . ' in ' . $file . ' on line ' . $line; + error_log(end($this->errors)); + } + + function error() + { + if (empty($this->trace)) { + return NULL; + } else { + $last_trace = end($this->trace); + return implode("\\n", $last_trace['errors']); + } + } + + function trace() + { + return $this->trace; + } + + function microtime_float() + { + list($usec, $sec) = explode(" ", microtime()); + return ((float) $usec + (float) $sec); + } + + function call($method, $args = NULL) + { + if ($this->multicall) { + $this->calls[] = array ('methodName' => $method, + 'params' => $args); + return NULL; + } else { + return $this->internal_call ($method, $args, 3); + } + } + + function internal_call($method, $args = NULL, $backtrace_level = 2) + { + $curl = curl_init(); + + // Verify peer certificate if talking over SSL + if ($this->port == 443) { + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // XXX 2 + if (!empty($this->cainfo)) { + curl_setopt($curl, CURLOPT_CAINFO, $this->cainfo); + } elseif (defined('PLC_API_CA_SSL_CRT')) { + curl_setopt($curl, CURLOPT_CAINFO, PLC_API_CA_SSL_CRT); + } + $url = 'https://'; + } else { + $url = 'http://'; + } + + // Set the URL for the request + $url .= $this->server . ':' . $this->port . '/' . $this->path; + curl_setopt($curl, CURLOPT_URL, $url); + + // Marshal the XML-RPC request as a POST variable. is an + // extension to the XML-RPC spec that is supported in our custom + // version of xmlrpc.so via the 'allow_null' output_encoding key. + $request = xmlrpc_encode_request($method, $args, array('allow_null' => TRUE)); + curl_setopt($curl, CURLOPT_POSTFIELDS, $request); + + // Construct the HTTP header + $header[] = 'Content-type: text/xml'; + $header[] = 'Content-length: ' . strlen($request); + curl_setopt($curl, CURLOPT_HTTPHEADER, $header); + + // Set some miscellaneous options + curl_setopt($curl, CURLOPT_TIMEOUT, 180); + + // Get the output of the request + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + $t0 = $this->microtime_float(); + $output = curl_exec($curl); + $t1 = $this->microtime_float(); + + if (curl_errno($curl)) { + $this->error_log('curl: ' . curl_error($curl), true); + $ret = NULL; + } else { + $ret = xmlrpc_decode($output); + if (is_array($ret) && xmlrpc_is_fault($ret)) { + $this->error_log('Fault Code ' . $ret['faultCode'] . ': ' . + $ret['faultString'], $backtrace_level, true); + $ret = NULL; + } + } + + curl_close($curl); + + $this->trace[] = array('method' => $method, + 'args' => $args, + 'runtime' => $t1 - $t0, + 'return' => $ret, + 'errors' => $this->errors); + $this->errors = array(); + + return $ret; + } + + function begin() + { + if (!empty($this->calls)) { + $this->error_log ('Warning: multicall already in progress'); + } + + $this->multicall = true; + } + + function commit() + { + if (!empty ($this->calls)) { + $ret = array(); + $results = $this->internal_call ('system.multicall', array ($this->calls)); + foreach ($results as $result) { + if (is_array($result)) { + if (xmlrpc_is_fault($result)) { + $this->error_log('Fault Code ' . $result['faultCode'] . ': ' . + $result['faultString'], 1, true); + $ret[] = NULL; + // Thierry - march 30 2007 + // using $adm->error() is broken with begin/commit style + // this is because error() uses last item in trace and checks for ['errors'] + // when using begin/commit we do run internal_call BUT internal_call checks for + // multicall's result globally, not individual results, so ['errors'] comes empty + // I considered hacking internal_call + // to *NOT* maintain this->trace at all when invoked with multicall + // but it is too complex to get all values right + // so let's go for the hacky way, and just record individual errors at the right place + $this->trace[count($this->trace)-1]['errors'][] = end($this->errors); + } else { + $ret[] = $result[0]; + } + } else { + $ret[] = $result; + } + } + } else { + $ret = NULL; + } + + $this->calls = array(); + $this->multicall = false; + + return $ret; + } + + // + // TopHatAPI Methods + // + + // Gets measurement information. + // + // Returns the measurement (cf doc). + + function Test($param = NULL) + { + $args[] = $this->auth; + if (func_num_args() > 0) $args[] = $param; + return $this->call('Test', $args); + } + + function Get($method, $timestamp, $input_filter = NULL, $output_fields = NULL, $callback = NULL) + { + $args[] = $this->auth; + $args[] = $method; + $args[] = $timestamp; + if (func_num_args() > 2) $args[] = $input_filter; + if (func_num_args() > 3) $args[] = $output_fields; + if (func_num_args() > 4) $args[] = $callback; + return $this->call('Get', $args); + } + + // TDMI Methods + + function GetPlatforms($input_filter = NULL, $output_fields = NULL) + { + $args[] = $this->auth; + if (func_num_args() > 0) $args[] = $input_filter; + if (func_num_args() > 1) $args[] = $output_fields; + return $this->call('GetPlatforms', $args); + } + + function GetTraceroutes($input_filter = NULL, $output_fields = NULL) + { + $args[] = $this->auth; + if (func_num_args() > 0) $args[] = $input_filter; + if (func_num_args() > 1) $args[] = $output_fields; + return $this->call('GetTraceroutes', $args); + } + + // Imported PLC Methods + + // Returns a new session key if a user or node authenticated + // successfully, faults otherwise. + + function GetSession () + { + $args[] = $this->auth; + return $this->call('GetSession', $args); + } + + // Returns an array of structs containing details about users sessions. If + // session_filter is specified and is an array of user identifiers or + // session_keys, or a struct of session attributes, only sessions matching the + // filter will be returned. If return_fields is specified, only the + // specified details will be returned. + + function GetSessions ($session_filter = NULL) + { + $args[] = $this->auth; + if (func_num_args() > 0) $args[] = $session_filter; + return $this->call('GetSessions', $args); + } + + // Returns an array of structs containing details about users. If + // person_filter is specified and is an array of user identifiers or + // usernames, or a struct of user attributes, only users matching the + // filter will be returned. If return_fields is specified, only the + // specified details will be returned. + // + // Users and techs may only retrieve details about themselves. PIs + // may retrieve details about themselves and others at their + // sites. Admins and nodes may retrieve details about all accounts. + + function GetPersons ($person_filter = NULL, $return_fields = NULL) + { + $args[] = $this->auth; + if (func_num_args() > 0) $args[] = $person_filter; + if (func_num_args() > 1) $args[] = $return_fields; + return $this->call('GetPersons', $args); + } + + // Returns 1 if the user or node authenticated successfully, faults + // otherwise. + + function AuthCheck () + { + $args[] = $this->auth; + return $this->call('AuthCheck', $args); + } + +} + +?> diff --git a/plekit/php/updateColumn.php b/plekit/php/updateColumn.php new file mode 100644 index 0000000..a030cf9 --- /dev/null +++ b/plekit/php/updateColumn.php @@ -0,0 +1,49 @@ + +GetSlices( array($slice_id)); + +if (empty($slices)) { + drupal_set_message ("Slice " . $slice_id . " not found"); + return; + } + +$slice=$slices[0]; + +$nodetags = array('node_id'); +$extratags = explode("|", $tagN); + +$nodes=$api->GetNodes(array('node_id'=>$slice['node_ids']),array_merge($nodetags, $extratags)); +$potential_nodes=$api->GetNodes(array('~node_id'=>$slice['node_ids']),array_merge($nodetags, $extratags)); + +echo "---attached---"; +if ($nodes) foreach ($nodes as $node) { + echo "|".$node['node_id']; + foreach ($extratags as $t) + echo ":".$node[$t]; +} +echo "|---potential---"; +if ($potential_nodes) foreach ($potential_nodes as $potential_node) { + echo "|".$potential_node['node_id']; + foreach ($extratags as $t) + echo ":".$potential_node[$t]; +} + +?> + diff --git a/plekit/php/updateConf.php b/plekit/php/updateConf.php new file mode 100644 index 0000000..4722688 --- /dev/null +++ b/plekit/php/updateConf.php @@ -0,0 +1,29 @@ +$value); +$api->UpdateSlice( $slice_id , $fields ); + +$myFile = "/var/log/myslice-log"; +$fh = fopen($myFile, 'a') or die("can't open file"); +$stringData = "\n".date('Ymd-H:i')."|".$slice_id.":".$value; +fwrite($fh, $stringData); +fclose($fh); + +?> diff --git a/plekit/table/columns.js b/plekit/table/columns.js new file mode 100644 index 0000000..115fc7c --- /dev/null +++ b/plekit/table/columns.js @@ -0,0 +1,1078 @@ + +/* $Id: table.js 13009 2009-04-10 10:49:28Z baris $ */ + +var filtered_color = "grey"; +var normal_color = "black"; + + +function inTypeA(header_name) { + var typeA = ['ST','SN','RES','OS','NRR','NTP','NSR','NSF','NDS','NTH','NEC','LRN','LCY','LPR','LCN','LAT','LON','IP','ASN','AST']; + return typeA.indexOf(header_name); +} + +function inTypeB(header_name) { + var typeB = ['BW','DS','MS','CC','CR','AS','MU','DU','CN']; + return typeB.indexOf(header_name); +} + +function inTypeC(header_name) { + var typeC = ['Rw','Rm','Ry','BWw','BWm','BWy','Lw','Lm','Ly','Sw','Sm','Sy','CFw','CFm','CFy','BUw','BUm','BUy','MUw','MUm','MUy','SSHw','SSHm','SSHy']; + return typeC.indexOf(header_name); +} + +function inTypeD(header_name) { + var typeD = ['HC']; + return typeD.indexOf(header_name); +} + +function debugfilter(s) { + document.getElementById('debug').innerHTML+=s; +} + +function scrollList(tableid) { + +debugfilter("here"); + +if (event.keyCode == 40) + debugfilter("down"); +else if (event.keyCode == 38) + debugfilter("up"); + +} + +function highlightOption(divid) { + +//debugfilter("highlighting option "+divid); + +for (var kk in column_headers) { + +if (document.getElementById(kk)) + document.getElementById(kk).className = 'out'; +} + +document.getElementById(divid).className = 'selected'; + +showDescription(divid); + +} + + +function showDescription(h) { + + //debugfilter("showing description "+h); + + if (document.getElementById('selectdescr')) + { + if (window['desc'+h]) + document.getElementById('selectdescr').innerHTML = ""+window['desc'+h]; + else if (column_table[h] && column_table[h]['description']) + document.getElementById('selectdescr').innerHTML = column_table[h]['description']; + else + document.getElementById('selectdescr').innerHTML = "No description provided"; + } +} + + +function overrideTitles() { + + //debugfilter("

overriding..."); + + for (var kk in column_headers) { + + //debugfilter("here "+kk); + + if (document.getElementById(kk) && window['title'+kk]) + document.getElementById('htitle'+kk).innerHTML = window['title'+kk]; + } + +} + +function changeCheckStatus(column) { + + +if (document.getElementById('selectdescr')) +{ +showDescription(document.getElementById(column).value); + +if (document.getElementById(column).checked) + addColumn(document.getElementById(column).value); +else + deleteColumn(document.getElementById(column).value); +} + +} + +function updatePeriod(h) { + deleteColumn2(h, h+'w'); + deleteColumn2(h, h+'m'); + deleteColumn2(h, h+'y'); + addColumn(h); +} + +function filterByType(selectedtype) { + +var notselectedyet = true; + +for (var kk in column_headers) { + + if (document.getElementById(kk)) + { + if (window['type'+kk] == selectedtype) + { + document.getElementById(kk).className = 'in'; + if (notselectedyet) + highlightOption(kk); + notselectedyet = false; + } + else + document.getElementById(kk).className = 'out'; + } +} +} + + +/* + +RESET/SAVE CONFIGURATION +*/ + + +function resetColumns() { + + for (var kk in column_table) { + + if (column_table[kk]['visible'] == true && column_table[kk]['fetch'] == false) + deleteColumn(kk); + else if (column_table[kk]['visible'] == false && column_table[kk]['fetch'] == true) + addColumn(kk); + } + +} + +function resetCols(which_conf) { + + var target_configuration = "|"+document.getElementById(which_conf).value+"|"; + + //debugfilter("

Target configuration = "+target_configuration); + + for (var kk in column_table) { + //debugfilter("in "+kk+" "); + + if (target_configuration.indexOf("|"+kk+"|")>=0) + { + if (document.getElementById('check'+kk)) + if (document.getElementById('check'+kk).checked == false) + { + debugfilter("

Adding "+kk); + addColumn(kk); + } + } + else + { + if (document.getElementById('check'+kk)) + if (document.getElementById('check'+kk).checked == true) + { + debugfilter("

Deleting "+kk); + deleteColumn(kk); + } + } + } +} + +function saveConfiguration(which_conf) +{ + var slice_id = document.getElementById('slice_id').value; + + var target_configuration = document.getElementById(which_conf).value; + + debugfilter("saving configuration "+target_configuration); + updateColumnConfiguration(slice_id, target_configuration); +} + +function updateColumnConfiguration(slice_id, value) +{ + + if (window.XMLHttpRequest) + {// code for IE7+, Firefox, Chrome, Opera, Safari + xmlhttp=new XMLHttpRequest(); + } + else + {// code for IE6, IE5 + xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); + } + xmlhttp.onreadystatechange=function() + { + if (xmlhttp.readyState==4) // && xmlhttp.status==200) + { + //value=xmlhttp.responseText; + //debugfilter(value); + if (document.getElementById('column_configuration')) + document.getElementById('column_configuration').value=value; + } + } + xmlhttp.open("GET","/plekit/php/updateConf.php?value="+value+"&slice_id="+slice_id+"&tagName=Configuration",true); + + xmlhttp.send(); +} + + + +function resetConfiguration(which_conf) +{ + var slice_id = document.getElementById('slice_id').value; + var target_configuration = document.getElementById(which_conf).value; + + debugfilter("reseting configuration "+target_configuration); + + if (window.XMLHttpRequest) + {// code for IE7+, Firefox, Chrome, Opera, Safari + xmlhttp=new XMLHttpRequest(); + } + else + {// code for IE6, IE5 + xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); + } + xmlhttp.onreadystatechange=function() + { + if (xmlhttp.readyState==4) // && xmlhttp.status==200) + { + //value=xmlhttp.responseText; + //debugfilter(value); + window.location.reload(true); + } + } + xmlhttp.open("GET","/plekit/php/updateConf.php?value="+target_configuration+"&slice_id="+slice_id+"&tagName=Configuration",true); + + xmlhttp.send(); +} + +function addColumnToConfiguration(column) { + + + var old_configuration = document.getElementById('column_configuration').value; + var slice_id = document.getElementById('slice_id').value; + + var new_configuration = ""; + + if (old_configuration != "") + new_configuration = old_configuration += "|"+column; + else + new_configuration = column; + + //debugfilter("new configuration = "+new_configuration); + + updateColumnConfiguration(slice_id, new_configuration); +} + + + +/* + +ADD/REMOVE COLUMNS + +*/ + + +function getHTTPObject() +{ + if (typeof XMLHttpRequest != 'undefined') + { return new XMLHttpRequest(); } + + try + { return new ActiveXObject("Msxml2.XMLHTTP"); } + catch (e) + { + try { return new ActiveXObject("Microsoft.XMLHTTP"); } + catch (e) {} + } + return false; +} + + +function load_html(column, url) { + var req = getHTTPObject(); + var res; + req.open('GET', url, true); + req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + req.onreadystatechange = + function() { + if (req.readyState == 4) + { updateColumnData(column, req.responseText); } + } + req.send(null); +} + +function updateColumnData(column,data) { + + +var headers = column.split("|"); +var data_table = data.split("|"); + +//debugfilter("

headers[0] = "+headers[0]); +//debugfilter("

sample line = "+data_table[2]); + + + var node_data; + + var table_id1 = 'nodes'; + var table=$(table_id1); + var css='#'+table_id1+'>tbody'; + var rows = $$(css)[0].rows; + + var data_array1 = new Array(); + + //debugfilter("COLUMN "+column+"

"); + + for (var node_index = 1; node_index < data_table.length; node_index++) { + if (data_table[node_index] == '---potential---') + break; + node_data = data_table[node_index].split(':'); + + data_array1[node_data[0]] = new Array(); + + for (var h_index=0; h_index < headers.length; h_index++) { + + if (node_data[h_index+1] == "") + data_array1[node_data[0]][h_index] = "n/a"; + else + data_array1[node_data[0]][h_index] = node_data[h_index+1]; + } + + } + + if (rows) + for (var row_index = 0; row_index < rows.length ; row_index++) { + var tr=rows[row_index]; + + for (var column_index=0; column_index < tr.cells.length; column_index++) { + //debugfilter("

node id = "+tr.cells[0].innerHTML); + var found_index = headers.indexOf(tr.cells[column_index].getAttribute('name')); + if (found_index != -1) + tr.cells[column_index].innerHTML = data_array1[tr.cells[0].innerHTML][found_index]; + } + } + +//potential nodes +if (data_table[node_index] == '---potential---') +{ + + var table_id2 = 'add_nodes'; + var table2=$(table_id2); + var css2='#'+table_id2+'>tbody'; + var rows2 = $$(css2)[0].rows; + + var data_array2 = new Array(); + + //debugfilter("COLUMN "+column+"

"); + + for (; node_index < data_table.length; node_index++) { + if (data_table[node_index] == '') + continue; + node_data = data_table[node_index].split(':'); + + data_array2[node_data[0]] = new Array(); + + for (var h_index=0; h_index < headers.length; h_index++) { + + if (node_data[h_index+1] == "") + data_array2[node_data[0]][h_index] = "n/a"; + else + data_array2[node_data[0]][h_index] = node_data[h_index+1]; + } + } + + if (rows) + for (var row_index = 0; row_index < rows2.length ; row_index++) { + var tr=rows2[row_index]; + + for (var column_index=0; column_index < tr.cells.length; column_index++) { + var found_index = headers.indexOf(tr.cells[column_index].getAttribute('name')); + if (found_index != -1) + tr.cells[column_index].innerHTML = data_array2[tr.cells[0].innerHTML][found_index]; + } + } + +} + + document.getElementById('loadingDiv').innerHTML = "" +} + + + + + +function addColumnCells(column,header) { + + //debugfilter("adding cells now: "+column+":"+header); + column_table[header]['visible']=true; + + var cells = document.getElementsByName(header); + + + //debugfilter("got cells -"+cells+"- for "+header); + for(var j = 0; j < cells.length; j++) + cells[j].style.display = "table-cell"; +} + +function addColumnSamples(column) { + + var cellsheader = document.getElementsByName("confheader"+column); + for(var j = 0; j < cellsheader.length; j++) + cellsheader[j].style.display = "table-cell"; + +} + +function addColumnAjax(column) { + + var selectedperiod=""; + + if (document.getElementById('selectperiod'+column)) + selectedperiod = document.getElementById('selectperiod'+column).value; + + var header = column+""+selectedperiod; + + addColumnCells(column, header); + + var t = column_table[header]['tagname']; + var slice_id = document.getElementById('slice_id').value; + document.getElementById('loadingDiv').innerHTML = "LOADING ..."; + var url = "/plekit/php/updateColumn.php?slice_id="+slice_id+"&tagName="+t; + load_html(header, url); + + addColumnToConfiguration(header); +} + + +function addColumn2(column) { + + var selectedperiod=""; + + if (document.getElementById('selectperiod'+column)) + selectedperiod = document.getElementById('selectperiod'+column).value; + + var header = column+""+selectedperiod; + + addColumnCells(column,header); + + addColumnToConfiguration(column); + + checkDataToFetch(); +} + +function addColumn(column) { + + var selectedperiod=""; + var header=column; + + //debugfilter("adding column "+column+" and header "+header); + + if (inTypeC(column)!=-1) + { + column = column.substring(0,column.length-1); + } + else if (document.getElementById('selectperiod'+column)) + { + selectedperiod = document.getElementById('selectperiod'+column).value; + header = column+""+selectedperiod; + } + + //debugfilter("adding "+column+","+header); + + addColumnCells(column, header); + + addColumnToConfiguration(header); + + column_table[header]['visible'] = true; + + checkDataToFetch(); +} + +function checkDataToFetch() { + +var dataExist = false; + +for (var kk in column_table) { + + if (document.getElementById(kk)) + { + if (column_table[kk]['visible'] == true && column_table[kk]['fetch'] == false) + { + document.getElementById('fetchbutton').disabled = false; + document.getElementById('fetchbutton').style.color = 'red'; + dataExist = true; + } + } +} + +if (!dataExist) +{ + document.getElementById('fetchbutton').disabled = true; + document.getElementById('fetchbutton').style.color = 'grey'; +} + +} + + +function fetchData() { + +var tagnames = ""; +var headers = ""; + +for (var kk in column_table) { + +if (column_table[kk]['visible'] == true && column_table[kk]['fetch'] == false) + if (tagnames == "") + { + tagnames = column_table[kk]['tagname']; + headers = kk; + } + else + { + tagnames += "|"+column_table[kk]['tagname']; + headers += "|"+kk; + } +} + +//debugfilter("fetching these columns: "+tagnames+ "("+headers+")"); + + var slice_id = document.getElementById('slice_id').value; + document.getElementById('loadingDiv').innerHTML = "    Loading data. Please wait ..."; + var url = "/plekit/php/updateColumn.php?slice_id="+slice_id+"&tagName="+tagnames; + load_html(headers, url); +} + +function deleteColumnCells(column, header) { + + column_table[header]['visible']=false; + + var cells = document.getElementsByName(header); + for(var j = 0; j < cells.length; j++) + cells[j].style.display = "none"; + +} + +function deleteColumnSample() { + var cellsheader = document.getElementsByName("confheader"+column); + for(var j = 0; j < cellsheader.length; j++) + cellsheader[j].style.display = "none"; + +} + +function deleteColumnFromConfiguration(column) { + + + var old_configuration = document.getElementById('column_configuration').value; + var slice_id = document.getElementById('slice_id').value; + + var old_columns = old_configuration.split("|"); + var new_columns = new Array(); + + for (var column_index = 0; column_index < old_columns.length ; column_index++) { + var conf = old_columns[column_index].split(':'); + if (conf[0] != column) + new_columns.push(old_columns[column_index]); + } + + var new_configuration = new_columns.join("|"); + updateColumnConfiguration(slice_id, new_configuration); + + checkDataToFetch(); +} + +function deleteColumn2(column, header) { + + deleteColumnCells(column,header); + + deleteColumnFromConfiguration(column); + + column_table[header]['visible'] = false; + document.getElementById('check'+column).checked = false; +} + +function deleteColumn(column) { + + var selectedperiod=""; + var header=column; + + if (inTypeC(column)!=-1) + { + column = column.substring(0,column.length-1); + } + else if (document.getElementById('selectperiod'+column)) + { + selectedperiod = document.getElementById('selectperiod'+column).value; + header = column+""+selectedperiod; + } + + //debugfilter("deleting "+column+","+header); + + deleteColumnCells(column,header); + + deleteColumnFromConfiguration(header); + + column_table[header]['visible'] = false; + + //document.getElementById('check'+column).checked = false; +} + + + + +/* + + +HIGHLIGHTING + + + +function updateColumnThreshold(column, minT, maxT) { + +debugfilter("updating threshold for "+column+" with "+minT+" and "+maxT); + +var cells = document.getElementsByName(column); + +for(var j = 0; j < cells.length; j++) +{ +var val = parseFloat(cells[j].innerHTML); + +if (val >= minT && val <= maxT) + cells[j].style.color = filtered_color; +else + cells[j].style.color = normal_color; +} + +var old_configuration = document.getElementById('column_configuration').value; +var slice_id = document.getElementById('slice_id').value; + +var old_columns = old_configuration.split("|"); +var new_columns = new Array(); + +for (var column_index = 0; column_index < old_columns.length ; column_index++) { + var conf = old_columns[column_index].split(':'); + if (conf[0] != column) + new_columns.push(old_columns[column_index]); + else + new_columns.push(column+":"+minT+","+maxT); +} + +var new_configuration = new_columns.join("|"); + +updateColumnConfiguration(slice_id, new_configuration); + +} + +function updateExcludeList(column, excludeList) { + +//debugfilter("updating list"); +debugfilter("updating list for "+column+" with "+excludeList); + +var cells = document.getElementsByName(column); + +for(var j = 1; j < cells.length; j++) +{ +var val = cells[j].innerHTML; + +if (excludeList == val) + cells[j].style.color = filtered_color; +else + cells[j].style.color = normal_color; +} + +var old_configuration = document.getElementById('column_configuration').value; +var slice_id = document.getElementById('slice_id').value; + +var old_columns = old_configuration.split("|"); +var new_columns = new Array(); + +for (var column_index = 0; column_index < old_columns.length ; column_index++) { + var conf = old_columns[column_index].split(':'); + if (conf[0] != column) + new_columns.push(old_columns[column_index]); + else + new_columns.push(column+":"+excludeList); +} + +var new_configuration = new_columns.join("|"); + +updateColumnConfiguration(slice_id, new_configuration); + +} + + + +/* + +ROW FILTERING + + +function plekit_table_showAll (slicetable_id) { + + var table=$(slicetable_id); + var css='#'+slicetable_id+'>tbody'; + var rows = $$(css)[0].rows; + + // scan rows, elaborate 'visible' + for (var row_index = 0; row_index < rows.length ; row_index++) { + var tr=rows[row_index]; + var visible=true; + plekit_table_row_visible(tr,visible); + } + + plekit_table_count_filtered(slicetable_id); + + tablePaginater.init(slicetable_id); + +} + +function plekit_table_count_filtered (slicetable_id) { + var table=$(slicetable_id); + var css='#'+slicetable_id+'>tbody'; + var rows = $$(css)[0].rows; + + var no_filtered=0; + + // scan rows, elaborate 'visible' + for (var row_index = 0; row_index < rows.length ; row_index++) { + var tr=rows[row_index]; + var filtered = false; + + for (var column_index=0; column_index < tr.cells.length; column_index++) + if (tr.cells[column_index].style.color == "red") + filtered = true; + + if (filtered) + no_filtered++; + + } + + debugfilter(no_filtered+' nodes do not satisfy the requested threshold'); +} + + +function plekit_table_hide_filtered (slicetable_id) { + var table=$(slicetable_id); + var css='#'+slicetable_id+'>tbody'; + var rows = $$(css)[0].rows; + + var reg = /(^|\s)invisibleRow(\s|$)/; + + + if (!document.getElementById('filtercheck').checked) + { + plekit_table_showAll(slicetable_id); + return; + } + + var hidden=0; + + // scan rows, elaborate 'visible' + for (var row_index = 0; row_index < rows.length ; row_index++) { + var tr=rows[row_index]; + var visible=true; + + for (var column_index=0; column_index < tr.cells.length; column_index++) { + if (tr.cells[column_index].style.color == filtered_color) + visible = false; + } + if (!visible) + hidden++; + + plekit_table_row_visible(tr,visible); + } + + //debugfilter('hidden '+hidden+' nodes'); + debugfilter(hidden+' nodes do not satisfy the requested threshold (hidden)'); + + tablePaginater.init(slicetable_id); +} + + + + +function plekit_table_apply_config(slicetable_id, configuration) { + +var new_configuration = document.getElementById('new_conf').value; +var all_columns = new_configuration.split("|"); + +var min_values = new Array(); +var max_values = new Array(); + + +for (var column_index = 0; column_index < all_columns.length ; column_index++) { + + var conf = all_columns[column_index].split(':'); + + if (inTypeB(conf[0]) != -1) + { + var threshold = conf[1].split(','); + if (threshold.length == 2) + { + min_values.push(parseFloat(threshold[0])); + max_values.push(parseFloat(threshold[1])); + } + } + else if (inTypeC(conf[0]) == -1) + { + var threshold = conf[2].split(','); + if (threshold.length == 2) + { + min_values.push(parseInt(threshold[0])); + max_values.push(parseInt(threshold[1])); + } + } + else + { + min_values.push(-1); + max_values.push(-1); + } + +} + + var table=$(slicetable_id); + var css='#'+slicetable_id+'>tbody'; + var rows = $$(css)[0].rows; + + + var no_filtered=0; + + for (var row_index = 0; row_index < rows.length ; row_index++) { + + var tr=rows[row_index]; + + var filtered = false; + + for (var column_index = 0; column_index < all_columns.length ; column_index++) + if (min_values[column_index]!=-1) + { + var val = parseFloat(tr.cells[3+column_index].innerHTML); + + if (val >= min_values[column_index] && val <= max_values[column_index]) + { + tr.cells[3+column_index].style.color = filtered_color; + filtered = true; + } + else + tr.cells[3+column_index].style.color = normal_color; + } + else + if (tr.cells[3+column_index].style.color == filtered_color) + filtered = true; + + + if (filtered) + no_filtered++; + } + + debugfilter(no_filtered+' nodes do not satisfy the requested threshold'); + + //tablePaginater.init(slicetable_id); + +} + + +function reset_select () { + var table=$(slicetable_id); + var css='#'+slicetable_id+'>tbody'; + var rows = $$(css)[0].rows; + +var action = document.getElementById('onlyselected'); +action.checked=false; + + // scan rows, elaborate 'visible' + for (var row_index = 0; row_index < rows.length ; row_index++) { + var tr=rows[row_index]; + + document.getElementById("check"+tr.id).checked=false; + + } + + plekit_table_count_nodes(); +} + +} + + +function plekit_table_select_filter () { + var table=$(slicetable_id); + var css='#'+slicetable_id+'>tbody'; + var rows = $$(css)[0].rows; + + var reg = /(^|\s)invisibleRow(\s|$)/; + + var action = document.getElementById('onlyselected'); + if (!action.checked) + plekit_table_reset_filter(); + + // scan rows, elaborate 'visible' + for (var row_index = 0; row_index < rows.length ; row_index++) { + var tr=rows[row_index]; + var visible=true; + + if (action.checked) + { + if(tr.className.search(reg) == -1) + if(!document.getElementById("check"+tr.id).checked) + visible=false; + } + + if(tr.className.search(reg) != -1) + visible=false; + + plekit_table_row_visible(tr,visible); + } + + tablePaginater.init(slicetable_id); + plekit_table_count_nodes(); +} + +function plekit_table_select_filter2 () { + var table=$(slicetable_id); + var css='#'+slicetable_id+'>tbody'; + var rows = $$(css)[0].rows; + + var reg = /(^|\s)invisibleRow(\s|$)/; + + var action = document.getElementById('onlyselected'); + + // scan rows, elaborate 'visible' + for (var row_index = 0; row_index < rows.length ; row_index++) { + var tr=rows[row_index]; + var visible=true; + + if (action.checked) + { + if(tr.className.search(reg) == -1) + if(!document.getElementById("check"+tr.id).checked) + visible=false; + } + + if(tr.className.search(reg) != -1) + visible=false; + + plekit_table_row_visible(tr,visible); + } + + tablePaginater.init(slicetable_id); + plekit_table_count_nodes(); +} + +function CheckTopNodes(n) { + var table=$(slicetable_id); + var css='#'+slicetable_id+'>tbody'; + var rows = $$(css)[0].rows; + var reg = /(^|\s)invisibleRow(\s|$)/; + + var checked=0; + + for (var row_index = 0; row_index < rows.length ; row_index++) { + var tr=rows[row_index]; + + if(tr.className.search(reg) == -1) { + if (checkedtbody'; + var rows = $$(css)[0].rows; + var reg = /(^|\s)invisibleRow(\s|$)/; + + var r = n/plekit_table_visible_count(); + var checked=0; + + for (var row_index = 0; row_index < rows.length ; row_index++) { + var tr=rows[row_index]; + + if(tr.className.search(reg) == -1) { + if(Math.random() < r) { + document.getElementById("check"+tr.id).checked=true; + checked++; + }; + if (checked>=n) + break; + }; + }; +}; + + +function plekit_table_visible_count() { + var table=$(slicetable_id); + var css='#'+slicetable_id+'>tbody'; + var rows = $$(css)[0].rows; + var reg = /(^|\s)invisibleRow(\s|$)/; + var v=0; + + for (var row_index = 0; row_index < rows.length ; row_index++) { + var tr=rows[row_index]; + + if(tr.className.search(reg) == -1) + { + v++; + } + } + + return v; +} + + +function plekit_table_count_nodes() { + var table=$(slicetable_id); + var css='#'+slicetable_id+'>tbody'; + var rows = $$(css)[0].rows; + var reg = /(^|\s)invisibleRow(\s|$)/; + var n=0; + var v=0; + var s=0; + + for (var row_index = 0; row_index < rows.length ; row_index++) { + var tr=rows[row_index]; + + n++; + var ch = document.getElementById("check"+tr.id); + + if(tr.className.search(reg) == -1) + v++; + else + { + if (ch.checked) + ch.checked=false; + }; + + if (ch.checked) + s++; + + }; + + var dd = document.getElementById('node_statistics'); + dd.innerHTML = "Total: "+n+" - Shown: "+v+" - Selected: "+s; +}; + +function AutoSelect() +{ + var a = document.getElementById('automatic').value; + var n = parseInt(document.getElementById('no_nodes').value); + + if (isNaN(n)) + return; + + if (a == "random") + CheckRandomNodes(n); + else if (a == "top") + CheckTopNodes(n); + + plekit_table_select_filter2(); + plekit_table_count_nodes(); +} + +*/ -- 2.43.0