fix bug with hardcoded tag name
[raven.git] / apps / gacksadmin / gacks_functions.php
1 <?php
2
3 require_once 'form.php';
4
5 define(INFINITY, 2147483647);
6
7 define(STATE_PENDING, 0);
8 define(STATE_APPLY, 1);
9 define(STATE_APPLIED, 2);
10 define(STATE_INVOICED, 3);
11
12 define(KIND_CYCLE_CHARGE, 0);
13 define(KIND_SLOT_CHARGE, 1);
14 define(KIND_CYCLE_AGGREGATE, 2);
15 define(KIND_INVOICE, 10);
16 define(KIND_INVOICE_BEST_EFFORT, 11);
17 define(KIND_INVOICE_RESV, 12);
18 define(KIND_ADJUSTMENT, 20);
19 define(KIND_PAYMENT, 30);
20
21 function l_gacks_accounts ()       { return "/db/gacks/accounts.php"; }
22 function l_gacks_add_account ()    { return "/db/gacks/add_account.php"; }
23 function l_gacks_actions ()        { return "/db/gacks/action.php"; }
24 function l_gacks_account ($acctname, $acctkind)    { return "/db/gacks/account.php?account_name=$acctname&account_kind=$acctkind"; }
25 function l_gacks_reservations ()   { return "/db/gacks/reservations.php"; }
26 function l_gacks_reservation_set ()    { return "/db/gacks/reservation_set.php"; }
27 function l_gacks_invoice($name, $token, $state, $start_date, $end_date, $parent) { return "/db/gacks/invoices.php?account_name=$name&account_token=$token&state=$state&start_date=$start_date&end_date=$end_date&parent_id=$parent"; }
28 function l_gacks_all_invoices ()   { return l_gacks_invoice(NULL, NULL, STATE_INVOICED, time() - 30*24*60*60, NULL, NULL); }
29 function l_gacks_weekly ($y=NULL, $m=NULL, $d=NULL)         { return "/db/gacks/weekly.php?invoiceyear=$y&invoicemonth=$m&invoiceday=$d"; }
30 function l_gacks_node_status ()    { return "/db/gacks/nodestatus.php"; }
31 function l_gacks_wizard ()         { return "/db/gacks/wizard.php"; }
32 function l_gacks_nodelist ($account_name=NULL)         { return "/db/gacks/user_nodelist.php?account_name=$account_name"; }
33 function l_gacks_nodelist_download ($acctname) { return "/db/gacks/action.php?action=download-nodelist&account_name=$acctname&format=CSV"; }
34 function l_gacks_image ()         { return "/db/gacks/user_image.php"; }
35 function l_gacks_syndicate ()     { return "/db/gacks/user_syndicate.php"; }
36 function l_gacks_user_reservations() { return "/db/gacks/user_reservations.php"; }
37 function l_gacks_edit($item)       { return "/db/gacks/edit.php"; }
38 function l_gacks_delete($item)     { $timeStart=$item['timeStart']; $timeStop=$item['timeStop']; $id=$item['id']; $lastAllocator=end($item['allocatorHRNs']); return "/db/gacks/action.php?action=delete-reservation&timeStart=$timeStart&timeStop=$timeStop&resource_id=$id&lastAllocator=$lastAllocator"; }
39 function l_gacks_service_level($account_name=NULL)   { return "/db/gacks/user_service_level.php?account_name=$account_name"; }
40 function l_gacks_confirm_service($acct, $level, $autoRenew, $enableBestEffort) { return "/db/gacks/user_confirm_service.php?account_name=$acct&level=$level&autoRenew=$autoRenew&enableBestEffort=$enableBestEffort"; }
41 function l_gacks_add_reservation() { return "/db/gacks/user_add_reservation.php"; }
42 function l_gacks_persons()         { return "/db/gacks/user_persons.php"; }
43 function l_gacks_advanced($value, $url)        { $eurl=urlencode($url); return "/db/gacks/action.php?action=set-advanced&value=$value&url=$eurl"; }
44 function l_gacks_summary()         { return "/db/gacks/user_summary.php"; }
45
46 function gacksid($x) { return "gacksid:" . $x; }
47
48 function gackshrn($x) { return "hrn:" . $x; }
49
50 function slice_to_hrn($slice)
51 {
52    $slice = str_replace("_", ".", $slice);
53    $hrn = "plc.vicci." . $slice;
54    return $hrn;
55 }
56
57 function is_time_unimportant($x)
58 {
59     if (($x==KIND_CYCLE_CHARGE) || ($x==KIND_SLOT_CHARGE)) {
60         return FALSE;
61     } else {
62         return TRUE;
63     }
64 }
65
66 function gacks_config()
67 {
68     return parse_ini_file("/etc/gacks/gacks.conf", true);     // see also in gacksclient.php
69 }
70
71 function handle_as_string($handle)
72 {
73     $id = $handle['id'];
74     $unitStart = $handle['unitStart'];
75     $unitStop = $handle['unitStop'];
76     $timeStart = $handle['timeStart'];
77     $timeStop = $handle['timeStop'];
78
79     return "$id#$unitStart-$unitStop#$timeStart-$timeStop";
80 }
81
82 function verify_account_token($account_name, $account_token) {
83     //$handle = fopen("/root/gacks_account_secret.txt", "r");
84     //$secret = fgets($handle, 4096);
85     //fclose($handle);
86
87     $config = gacks_config();
88     $secret = $config['gacks']['account_secret'];
89
90     $secret = trim($secret);
91     $token = sha1($secret . $account_name);
92     $token = substr($token, 0, 8);
93
94     //print $secret . " " . $token . " " . $account_name . " " . $account_token;
95
96     return ($token == $account_token);
97 }
98
99 function gacksid_guess_prefix($x) {
100     if ((strpos($x, ".") !== false) and (strpos($x, "_") == false)) {
101         return "hrn:" . $x;
102     } else if ((strpos($x, ".") == false) and (strpos($x, "_") == true)) {
103         return "slice:" . $x;
104     } else {
105         // XXX this doesn't display an error to the user
106         throw new Exception("unable to guess whether name is a slice or hrn");
107     }
108 }
109
110 function level_selectors($value)
111 {
112     $level_selectors = array();
113     $level_selectors []= array("display"=>"Default", "value"=>"default");
114     $level_selectors []= array("display"=>"Silver", "value"=>"silver");
115     $level_selectors []= array("display"=>"Gold", "value"=>"gold");
116
117     foreach ($level_selectors as &$sel) {
118         if ($sel["value"] == $value) {
119             $sel["selected"] = True;
120         }
121     }
122
123     return $level_selectors;
124 }
125
126 function charge_kind_selectors($value)
127 {
128     $kind_selectors = array();
129     $kind_selectors []= array("display"=>"Cycle Charge", "value"=>"0");
130     $kind_selectors []= array("display"=>"Slot Charge", "value"=>"1");
131     $kind_selectors []= array("display"=>"Invoice Charge", "value"=>"10");
132     $kind_selectors []= array("display"=>"Adjustment", "value"=>"20");
133     $kind_selectors []= array("display"=>"Payment", "value"=>"30");
134
135     foreach ($kind_selectors as &$sel) {
136         if ($sel["value"] == $value) {
137             $sel["selected"] = True;
138         }
139     }
140
141     return $kind_selectors;
142 }
143
144 function bool_text($value, $true, $false)
145 {
146     if ($value) {
147         return $true;
148     } else {
149         return $false;
150     }
151 }
152
153 function bool_selectors($value)
154 {
155     if ($value) {
156         $value = 1;
157     } else {
158         $value = 0;
159     }
160
161     $bool_selectors = array();
162     $bool_selectors []= array("display"=>"Yes", "value"=>"1");
163     $bool_selectors []= array("display"=>"No", "value"=>"0");
164
165     foreach ($bool_selectors as &$sel) {
166         if ($sel["value"] == $value) {
167             $sel["selected"] = True;
168         }
169     }
170
171     return $bool_selectors;
172 }
173
174 function aggregate_records($records)
175 {
176    $aggs = array();
177
178    foreach ($records as $rec) {
179        $rec['key'] = $rec['id'] + '#' + $rec['timeStart'] + "-" + $rec['timeStop'] + ":" + implode(",", $rec['allocatorHRNs']) + ">" + $rec['consumerHRN'];
180        $rec['qty'] = $rec['unitStop'] - $rec['unitStart'];
181
182        $found = False;
183        foreach ($aggs as &$agg) {
184            if ($agg['key'] == $rec['key']) {
185                $agg['qty'] = $agg['qty'] + $rec['qty'];
186                $found = True;
187            }
188        }
189        if (!$found) {
190            $aggs []= $rec;
191        }
192    }
193
194    return $aggs;
195 }
196
197 function record_table($records, $timezone_seconds)
198 {
199     $headers=array();
200     $headers["id"] = "string";
201     $headers["start"] = "string";
202     $headers["stop"] = "string";
203     $headers["lastAllocator"] = "string";
204     $headers["consumer"] = "string";
205     $headers["qty"] = "int";
206     $headers["actions"] = "string";
207
208     $sort_column = 1;
209     $table = new PlekitTable("reservations", $headers, $sort_column);
210     $table->start();
211
212     $aggs = aggregate_records($records);
213
214     foreach ( $aggs as $item ) {
215             $table->row_start();
216             $table->cell($item['id']);
217             $table->cell(strftime("%Y-%m-%d %H:%M:%S", $item['timeStart']+$timezone_seconds));
218             $table->cell(strftime("%Y-%m-%d %H:%M:%S", $item['timeStop']+$timezone_seconds));
219             $table->cell(end($item['allocatorHRNs']));
220             $table->cell($item['consumerHRN']);
221             $table->cell($item['qty']);
222             $table->cell(href(l_gacks_delete($item), "delete")); // href(l_gacks_edit($item), "edit") . " "
223             $table->row_end();
224     }
225
226     $table->end();
227 }
228
229 function charge_detail($charge)
230 {
231     $details = new PlekitDetails(False);
232
233     $details->start();
234
235     $details->form_start(l_gacks_actions(), array());
236
237     $details->th_td("id", $charge["id"]);
238     $details->th_td("object/desc", $charge["object_desc"]);
239     $details->th_td("kind", $charge["kind_id"]);
240     $details->th_td("date", $charge["date"]);
241     $details->th_td("amount", $charge["amount"]);
242     $details->th_td("state", $charge["state"]);
243     $details->th_td("parent_id", $charge["parent_id"]);
244     $details->th_td("account_name", $charge["account_name"]);
245
246     $details->end();
247     $details->form_end();
248 }
249
250 function dollars($amount)
251 {
252     return "$ " . number_format($amount, 2);
253 }
254
255 function invoice_table($invoice, $account_name, $account_token, $options)
256 {
257     $invoice_kind = array();
258     $invoice_kind[KIND_CYCLE_CHARGE] = "best effort";
259     $invoice_kind[KIND_SLOT_CHARGE] = "reservation";
260     $invoice_kind[KIND_CYCLE_AGGREGATE] = "best effort";
261     $invoice_kind[KIND_INVOICE] = "daily invoice";
262     $invoice_kind[KIND_INVOICE_BEST_EFFORT] = "daily invoice";
263     $invoice_kind[KIND_INVOICE_RESV] = "daily invoice";
264     $invoice_kind[KIND_ADJUSTMENT] = "adjustment";
265     $invoice_kind[KIND_PAYMENT] = "payment";
266
267     $headers=array();
268     $headers["id"] = "string";
269     $headers["account_name"] = "string";
270     $headers["date"] = "string";
271     $headers["kind"] = "string";
272     $headers["description"] = "string";
273     $headers["amount"] = "int";
274
275     // ideally it would be nice if we could sort by 3 columns,
276     //    account_name, date, description
277     if ($account_name) {
278         $sort_column = 2; // date
279     } else {
280         $sort_column = 1; // account name
281     }
282
283     $table = new PlekitTable("invoices", $headers, $sort_column);
284     $table->start();
285
286     $charges = $invoice['charges'];
287
288     foreach ( $charges as $item ) {
289             //if ($options['date_only']) {
290             if (is_time_unimportant($item['kind_id'])) {
291                 $date = explode(' ', $item['date']);
292                 $date = $date[0];
293             } else {
294                 $date = $item['date'];
295             }
296             $table->row_start();
297             $table->cell(href(l_gacks_invoice($account_name, $account_token, NULL, NULL, NULL, $item['id']), $item['id']));
298             $table->cell($item['account_name']);
299             $table->cell($date);
300             $table->cell($invoice_kind[$item['kind_id']]);
301             $table->cell($item['object_desc']);
302             $table->cell(dollars($item['amount']), array("align"=>"right"));
303             $table->row_end();
304     }
305
306     $table->end();
307 }
308
309 # from http://cool-php-tutorials.blogspot.com/2010/02/easy-php-date-picker.html
310 function date_picker($name, $y, $m, $d)
311 {
312     $startyear = 2012;
313     $endyear = date("Y");
314
315     $months=array('','January','February','March','April','May',
316     'June','July','August', 'September','October','November','December');
317
318     // Month dropdown
319     $html="<select name=\"".$name."month\">";
320
321     for($i=1;$i<=12;$i++)
322     {
323        $html.="<option value='$i'";
324        if ($i==$m) {
325            $html.=" selected=true";
326        }
327        $html.=">$months[$i]</option>";
328     }
329     $html.="</select> ";
330
331     // Day dropdown
332     $html.="<select name=\"".$name."day\">";
333     for($i=1;$i<=31;$i++)
334     {
335        $html.="<option value='$i'";
336        if ($i==$d) {
337            $html.=" selected=true";
338        }
339        $html.=">$i</option>";
340     }
341     $html.="</select> ";
342
343     // Year dropdown
344     $html.="<select name=\"".$name."year\">";
345
346     for($i=$startyear;$i<=$endyear;$i++)
347     {
348       $html.="<option value='$i'";
349       if ($i==$y) {
350           $html.=" selected=true";
351       }
352       $html.=">$i</option>";
353     }
354     $html.="</select> ";
355
356     return $html;
357 }
358
359 function get_slices($plcapi, $person_id, $fields)
360 {
361     if (!in_array("name", $fields)) {
362         $fields []= "name";
363     }
364
365     $persons = $plcapi->GetPersons(array('person_id'=>$person_id),array('person_id','email','slice_ids','role_ids','site_ids'));
366     $person=$persons[0];
367     $slice_filter=array('slice_id' => $person['slice_ids']);
368     $user_slices=$plcapi->GetSlices($slice_filter,$fields);
369
370     $slices = array();
371     foreach ($user_slices as $slice) {
372         $slices[$slice['name']] = $slice;
373     }
374
375     $is_pi = in_array( 20, $person['role_ids']);
376     if ($is_pi) {
377         $slice_filter=array('site_id'=>$person['site_ids'][0]);
378         $pi_slices = $plcapi->GetSlices($slice_filter, $fields);
379
380         foreach ($pi_slices as $slice) {
381             if (!array_key_exists($slice['name'], $slices)) {
382                 $slices[$slice['name']] = $slice;
383             }
384         }
385     }
386
387     return $slices;
388 }
389
390 function get_account_names($plcapi, $person_id)
391 {
392     $slices = get_slices($plcapi, $person_id, array("name"));
393     $slicenames = array();
394     foreach ($slices as $name => $slice) {
395         $slicenames []= $name;
396     }
397
398     return $slicenames;
399 }
400
401 function account_selectors($plcapi, $person_id, $account_name)
402 {
403     $slicenames = get_account_names($plcapi, $person_id);
404
405     $selectors = array();
406     foreach ($slicenames as $slicename) {
407         if ($slicename == $account_name) {
408             $selectors []= array("display"=>$slicename, "value"=>$slicename, "selected"=>True);
409         } else {
410             $selectors []= array("display"=>$slicename, "value"=>$slicename);
411         }
412     }
413
414     return $selectors;
415 }
416
417 function &find_selector($needle, &$selectors)
418 {
419     foreach ($selectors as &$selector) {
420         if ($selector['value']==$needle) {
421             return $selector;
422         }
423     }
424     return NULL;
425 }
426
427 function select_selector($needle, &$selectors)
428 {
429     $selector = &find_selector($needle, $selectors);
430     if ($selector) {
431         $selector["selected"] = True;
432     }
433 }
434
435 function get_gacks_session()
436 {
437     if (!array_key_exists("gacks", $_SESSION)) {
438         return array("account_name" => NULL);
439     }
440     return $_SESSION['gacks'];
441 }
442
443 function update_gacks_session($updated_session)
444 {
445     $session = get_gacks_session();
446
447     foreach ($updated_session as $key => $value) {
448         $session[$key] = $value;
449     }
450
451     $_SESSION['gacks'] = $session;
452 }
453
454 function get_account_name($api, $_person_id, $form=NULL, $url=NULL)
455 {
456     $session = get_gacks_session();
457
458     $account_name = $_GET['account_name'];
459     if (!$account_name) {
460         $account_name = $_POST['account_name'];
461     }
462     if (!$account_name) {
463         $account_name = $session['account_name'];
464     }
465
466     drupal_add_js("misc/popup.js");
467
468     if ($form == NULL) {
469         $form = new PlekitForm(l_gacks_actions(), array("action"=>"set-account",
470                                                         "url"=>$_SERVER['REQUEST_URI']));
471         $form->start();
472         $needFormEnd = TRUE;
473     } else {
474         $needFormEnd = FALSE;
475     }
476
477     $selectors = account_selectors($api, $_person_id, $account_name);
478
479     if (($account_name != NULL) && (!find_selector($account_name, $selectors))) {
480         $account_name = NULL;
481     }
482
483     print "Slice name:<br>";
484     if ($url != NULL) {
485         $onChange = "PopupMessage(); this.form.action=\"$url\"; this.form.submit();";
486     } else {
487         $onChange = "PopupMessage(); this.form.submit();";
488     }
489     print $form->select_html("account_name", $selectors, array("onChange"=> $onChange));
490
491     if ($needFormEnd) {
492         $form->end();
493     }
494
495     if ((!$account_name) && ($selectors)) {
496         $account_name = $selectors[0]["value"];
497     }
498
499     return $account_name;
500 }
501
502 // This makes a combobox that when it is changed, it will pop up a "Please Wait"
503 // message and refresh the page.
504 //
505 // &$value is passed by reference, so that it will automatically be set to the
506 // first item in the combobox if it is NULL.
507
508 function auto_refresh_combo($form, $name, $selectors, &$value, $url)
509 {
510     foreach ($selectors as &$sel) {
511         if ($sel["value"] == $value) {
512             $sel["selected"] = True;
513         } else {
514             $sel["selected"] = False;
515         }
516     }
517
518     if (($value!=NULL) && (!find_selector($value, $selectors))) {
519         $value = NULL;
520     }
521
522     if ($value==NULL) {
523         if (count($selectors)>=1) {
524             $value = $selectors[0]['value'];
525         }
526     }
527
528     $onChange = "PopupMessage(); this.form.action=\"$url\"; this.form.method=\"get\"; this.form.submit();";
529     return $form->select_html($name, $selectors, array("onChange"=> $onChange));
530 }
531
532 // Combobox for Gacks account names. In addition to the features supported by
533 // auto_refresh_combo, it automatically populates the selectors with the slices
534 // that the user has access to, and gets and sets the account_name in the
535 // session variables.
536
537 function account_name_combo($api, $_person_id, $form, &$account_name, $url)
538 {
539     $session = get_gacks_session();
540     if ($account_name==NULL) {
541         $account_name = $session['account_name'];
542     } else {
543         // If a new $account_name was passed in, then update the session
544         // variable.
545         if ($account_name!=$session['account_name']) {
546              update_gacks_session(array("account_name" => $account_name));
547         }
548     }
549
550     $selectors = account_selectors($api, $_person_id, $account_name);
551
552     return auto_refresh_combo($form, "account_name", $selectors, $account_name, $url);
553 }
554
555 function timezone_combo($form, &$timezone, $url)
556 {
557     $session = get_gacks_session();
558     if ($timezone==NULL) {
559         $timezone = $session['timezone'];
560     } else {
561         // If a new $timezone was passed in, then update the session
562         // variable.
563         if ($timezone!=$session['timezone']) {
564              update_gacks_session(array("timezone" => $timezone));
565         }
566     }
567
568     $selectors = array();
569     for($i=-12;$i<=14;$i++) {
570         if ($i<0) {
571             $selectors []= array("display" => "GMT" . $i, "value" => $i);
572         } else {
573             $selectors []= array("display" => "GMT+" . $i, "value" => $i);
574         }
575     }
576
577     return auto_refresh_combo($form, "timezone", $selectors, $timezone, $url);
578 }
579
580 function account_table($plcapi, $gacksapi, $person_id)
581 {
582     $slices = get_slices($plcapi, $person_id, array("name","person_ids","node_ids"));
583
584     $accounts = array();
585     foreach ($slices as $slicename => $slice) {
586          $accounts[$slicename] = $gacksapi->get_account(gacksid($slicename), "user");
587     }
588
589     $headers=array();
590     $headers["name"] = array("type"=>"string", "title"=>"Name of slice");
591     $headers["level"] = array("type"=>"string", "title"=>"Service level");
592     $headers["be"] = array("type"=>"string", "title"=>"Enable Best Effort service when reservations are not in effect");
593     $headers["users"] = array("type"=>"integer", "title"=>"Number of users authorized in this slice");
594     $headers["slivers"] = array("type"=>"integer", "title"=>"Number of slivers this slice is deployed on");
595     $headers["billing contacts"] = array("type"=>"string", "title"=>"Email addresses of billing contacts for this slice");
596
597     $table = new PlekitTable("accounts", $headers, 0);
598     $table->start();
599
600     foreach ($accounts as $name => $account) {
601         $slice = $slices[$name];
602         $table->row_start();
603         $table->cell(href(l_gacks_service_level($name), $name));
604         $table->cell(href(l_gacks_service_level($name), $account["level"]));
605         $table->cell(href(l_gacks_service_level($name), bool_text(!$account["freezeUnreserved"], "enabled", "disabled")));
606         $table->cell(count($slice["person_ids"]));
607         $table->cell(href(l_gacks_nodelist($name), count($slice["node_ids"])));
608         $table->cell(href(l_gacks_service_level($name), $account["billingContacts"]));
609
610         $table->row_end();
611     }
612
613     $table->end();
614
615 }
616
617 function date_combo($form, $name, &$y, &$m, &$d, $url)
618 {
619     $month_selectors = array();
620     $month_selectors []= array("display" => "Jan", "value" => 1);
621     $month_selectors []= array("display" => "Feb", "value" => 2);
622     $month_selectors []= array("display" => "Mar", "value" => 3);
623     $month_selectors []= array("display" => "Apr", "value" => 4);
624     $month_selectors []= array("display" => "May", "value" => 5);
625     $month_selectors []= array("display" => "Jun", "value" => 6);
626     $month_selectors []= array("display" => "Jul", "value" => 7);
627     $month_selectors []= array("display" => "Aug", "value" => 8);
628     $month_selectors []= array("display" => "Sep", "value" => 9);
629     $month_selectors []= array("display" => "Oct", "value" => 10);
630     $month_selectors []= array("display" => "Nov", "value" => 11);
631     $month_selectors []= array("display" => "Dec", "value" => 12);
632
633     $year_selectors = array();
634     for($i=2012;$i<=2022;$i++) {
635         $year_selectors []= array("display" => $i, "value" => $i);
636     }
637
638     $day_selectors = array();
639     for($i=1;$i<=31;$i++) {
640         $day_selectors []= array("display" => $i, "value" => $i);
641     }
642
643     $m_combo = auto_refresh_combo($form, $name . "_m", $month_selectors, $m, $url);
644     $d_combo = auto_refresh_combo($form, $name . "_d", $day_selectors, $d, $url);
645     $y_combo = auto_refresh_combo($form, $name . "_y", $year_selectors, $y, $url);
646
647     return $m_combo . $d_combo . $y_combo;
648 }
649
650 function get_slice_tag($api, $slicename, $tagname)
651 {
652     $image_tags = $api->GetSliceTags(array("tagname" => $tagname, "name" => $slicename));
653     if (count($image_tags) > 0) {
654         return $image_tags[0]['value'];
655     } else {
656         return NULL;
657     }
658 }
659
660 function set_slice_tag($api, $slicename, $tagname, $value)
661 {
662     $tags = $api->GetSliceTags(array("tagname" => $tagname, "name" => $slicename));
663     if (count($tags) > 0) {
664         if (!$value) {
665             $api->DeleteSliceTag($tags[0]['slice_tag_id']);
666         } else if ($tags[0]['slice_tag_id'] != $value) {
667             $api->UpdateSliceTag($tags[0]['slice_tag_id'], $value);
668         }
669     } else {
670         $api->AddSliceTag($slicename, $tagname, $value);
671     }
672 }
673
674 function get_slice_image($api, $slicename)
675 {
676     return get_slice_tag($api, $slicename, "vref");
677 }
678
679 function set_slice_image($api, $slicename, $value)
680 {
681     set_slice_tag($api, $slicename, "vref", $value);
682 }
683
684 function get_slice_headnode($api, $slicename)
685 {
686     $ipList_tags = $api->GetSliceTags(array("tagname" => "vsys_ipList", "name" => $slicename));
687     if (count($ipList_tags) > 0) {
688         $ipList = $ipList_tags[0]['value'];
689         $ips = explode(",", $ipList);
690         if (count($ips)>0) {
691             return $ips[0];
692         } else {
693             return NULL;
694         }
695     } else {
696         return NULL;
697     }
698 }
699
700 function time_selectors($start_date, $min_date)
701 {
702     for($i=0;$i<24;$i++) {
703         if ($start_date+$i*60*60 >= $min_date) {
704             $selectors []= array("display" => "$i:00:00", "value"=>$i);
705         }
706     }
707
708     return $selectors;
709 }
710
711 function get_timezone()
712 {
713     if (isset($_GET['timezone_offset_minutes'])) {
714         $minutes = $_GET['timezone_offset_minutes'];
715 /*        echo "GMT offset (in minutes, from the browser): ". $minutes ."<br />\n";
716         echo "GMT: ". gmdate("Y-m-d H:i:s") ."<br />\n";
717
718         $local = gmmktime(gmdate("H"),gmdate("i")-$minutes); // adjust GMT by client's offset
719
720         echo "Calculated client's date/time: ". gmdate("Y-m-d h:i:s a",$local) ."<br />\n";*/
721
722         return $minutes;
723     } else {
724         if  (!strchr($_SERVER['REQUEST_URI'], "?")) {
725             $url = $_SERVER['REQUEST_URI'] . "?";
726         } else {
727             $url = $_SERVER['REQUEST_URI'] . "&";
728         }
729
730         echo "<script language='javascript'>\n";
731         echo "var d = new Date();\n";
732         echo "location.href=\"${url}timezone_offset_minutes=\" + (-d.getTimezoneOffset());\n";
733         echo "</script>\n";
734         exit();
735     }
736 }
737
738 function manage_slivers_tabs()
739 {
740     $tabs = array();
741
742     $tabs['Show Slivers'] = array('method'=>'GET',
743                                'url'=>l_gacks_nodelist(),
744                                'bubble'=>"Show slivers (also known as nodes or VMs) in your slice");
745
746     $tabs['Add Slivers'] = array('method'=>'GET',
747                                'url'=>l_gacks_wizard(),
748                                'bubble'=>"Add slivers (also known as nodes or VMs) to your slice");
749
750     $tabs['Select Image'] = array('method'=>'GET',
751                                'url'=>l_gacks_image(),
752                                'bubble'=>"Select image to use in this slice");
753
754     $tabs['Shared Filesystem'] = array('method'=>'GET',
755                                 'url'=>l_gacks_syndicate(),
756                                 'bubble'=>"Enabled access to Syndicate shared filesystem");
757
758     return $tabs;
759 }
760
761 // This creates a centered div that sizes itself to fit the objects that are
762 // inside of it. Put it and some other stuff around a plekit table and it will
763 // make the contents all line up with the table.
764 //
765 // This fails in IE
766 function shrinkdiv_start()
767 {
768 //   print '<div style="width: 100px; margin: 0 auto;">';
769    print '<div style="text-align: center;">';
770    print '<div style="display: inline-block; text-align: left;">';
771 }
772
773 function shrinkdiv_end()
774 {
775     print '</div></div>';
776 }