1 <?php
2 /*
3 * This code is part of GOsa (http://www.gosa-project.org)
4 * Copyright (C) 2003-2008 GONICUS GmbH
5 *
6 * ID: $$Id$$
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
23 /*!
24 \brief This class represents the host action queue.
25 \author Fabian Hickert <hickert@gonicus.de>
26 \version 2.6
27 \date 24.10.2007
29 This class is a queue handler, which allows adding,removing,
30 priority settings,stop and resume actions... for each queue entry
31 */
32 class hostActionQueue {
34 private $o_config = NULL;
35 private $s_queue_file = "";
36 private $s_error = "";
37 private $b_error = FALSE;
39 private $a_queue = array();
40 private $i_pointer = 0;
41 private $b_queue_loaded = false;
42 private $i_fileversion = 0;
44 private $id_entry_map = array();
46 public function __construct($config)
47 {
48 $this->o_config= $config;
50 /* Define source file */
51 $this->s_queue_file = CONFIG_DIR."/gotomasses_machines";
53 $file = $this->o_config->search("gotomasses", "STORAGE_FILE",array('menu'));
54 if(!empty($file)){
55 $this->s_queue_file = $file;
56 }
57 }
59 private function _reload_queue()
60 {
61 $this->_reset_error();
62 $this->b_queue_loaded = FALSE;
63 $this->b_error = FALSE;
64 $this->s_error = "";
65 $this->i_pointer = 0;
67 /* Check file accessibility */
68 if(!file_exists($this->s_queue_file)){
69 $this->set_error(sprintf(_("Can't locate gotomasses queue file '%s'."),$this->s_queue_file));
70 return(FALSE);
71 }
72 if(!is_readable($this->s_queue_file)){
73 $this->set_error(sprintf(_("Can't read gotomasses queue file '%s'."),$this->s_queue_file));
74 return(FALSE);
75 }
77 /* Check if file contents could be read */
78 $fp = @fopen($this->s_queue_file,"r");
79 if(!$fp){
80 $this->set_error(sprintf(_("Can't read gotomasses storage file '%s'."),$this->s_queue_file));
81 return(FALSE);
82 }
83 $this->i_fileversion = filemtime($this->s_queue_file);
84 clearstatcache();
86 /* Get file contents */
87 $data ="";
88 while(!feof($fp)){
89 $data.= fread($fp,512);
90 }
92 /* Get lines from file */
93 $this->a_queue = array();
94 $comment = "";
95 $rows = split("\n",$data);
97 $used_ids = array();
99 /* Walk trough rows and parse data */
100 foreach($rows as $row){
102 /* Skip empty lines */
103 $row = trim($row);
104 if(empty($row)){
105 continue;
106 }
108 /* Get comment, if available */
109 if(preg_match("/^#/",$row)){
110 $comment = preg_replace("/^#/","",$row);
111 continue;
112 }
114 $entry_id = $task_id= "";
116 /* Comment must be set correctly */
117 if(empty($comment)){
118 $desc = "";
119 }else{
120 $task_id =preg_replace("/^.*taskid:([0-9a-z]*).*$/i","\\1",$comment);
121 $entry_id=preg_replace("/^.*entryid:([0-9a-z]*).*$/i","\\1",$comment);
122 $desc =preg_replace("/^.*desc:(.*)$/","\\1",$comment);
123 }
124 if($task_id == "" || empty($task_id)){
125 $task_id = $this->get_new_id();
126 }
127 if($entry_id == "" || empty($entry_id)){
128 $entry_id = $this->get_new_id();
129 }
131 /* Get unige id */
132 while(in_array($entry_id,$used_ids)){
133 $entry_id = $this->get_new_id();
134 }
135 $used_ids[] = $entry_id;
137 /* Split row into minutes/ hours ...*/
138 $row = preg_replace('/[\t ]/umi'," ",$row);
139 $row = preg_replace('/ */umi'," ",$row);
140 $parts = split(" ",$row);
142 if(count($parts) != 10){
143 msg_dialog::display(_("GOsa infrastructure"), _("Cannot read broken entry - skipped!"), WARNING_DIALOG);
144 }else{
146 $entry = array();
147 $entry['TASK_ID'] = $task_id;
148 $entry['ID'] = $entry_id;
149 $entry['Minute'] = $parts[0];
150 $entry['Hour'] = $parts[1];
151 $entry['Day'] = $parts[2];
152 $entry['Month'] = $parts[3];
153 $entry['Weekday'] = $parts[4];
154 $entry['Action'] = $parts[5];
155 $entry['OGroup'] = $parts[6];
156 $entry['Zone'] = $parts[7];
157 $entry['Section'] = $parts[8];
158 if($entry['Action'] == "initial_install"){
159 $tmp2 = split(";",$parts[9]);
160 foreach($tmp2 as $target){
161 $tmp = split(",",$target);
162 $entry['Initial_Target'][] = array(
163 "MAC" => $tmp[0],
164 "IP" => $tmp[1],
165 "NAME" => $tmp[2]);
166 }
167 $entry['Target'] = array();
168 }else{
169 $entry['Initial_Target'] = array();
170 $entry['Target'] = split(";",$parts[9]);
171 }
172 $entry['Comment'] = $desc;
173 $this->a_queue[] = $entry;
174 }
175 $comment = "";
176 }
178 /* Udpate ENTRY_ID -> id mapping */
179 reset($this->a_queue);
180 foreach($this->a_queue as $id => $entry){
181 $this->id_entry_map[$entry['ID']] = $id;
182 }
184 return(TRUE);
185 }
188 private function _save_data()
189 {
190 $this->_reset_error();
192 /* Check file accessibility */
193 if(!file_exists($this->s_queue_file)){
194 $this->set_error(sprintf(_("Can't locate gotomasses queue file '%s'."),$this->s_queue_file));
195 return(FALSE);
196 }
197 if(!is_writeable($this->s_queue_file)){
198 $this->set_error(sprintf(_("Can't write gotomasses queue file '%s'."),$this->s_queue_file));
199 return(FALSE);
200 }
201 if($this->i_fileversion != filemtime($this->s_queue_file)){
202 $this->set_error(_("The queue file was modified since last reload. Can't save changes."));
203 return(FALSE);
204 }
205 $fp = @fopen($this->s_queue_file,"w");
206 if(!$fp){
207 $this->set_error(sprintf(_("Can't write gotomasses queue file '%s'."),$this->s_queue_file));
208 return(FALSE);
209 }
211 $str = "#GOsa generated file, please just modify if you really know what you do.";
212 reset($this->a_queue);
213 foreach($this->a_queue as $task){
214 $str .= "\n#taskid:".trim($task['TASK_ID']).";entryid:".$task['ID'].";desc:".trim($task['Comment']);
215 $str .= "\n";
216 if($task['Action'] == "initial_install"){
217 $str .= "* * * * * ";
218 }else{
219 $str .= str_pad($task['Minute'] ,5," ")." ";
220 $str .= str_pad($task['Hour'] ,5," ")." ";
221 $str .= str_pad($task['Day'] ,5," ")." ";
222 $str .= str_pad($task['Month'] ,5," ")." ";
223 $str .= str_pad($task['Weekday'],5," ")." ";
224 }
225 $str .= str_pad($task['Action'] ,5," ")." ";
226 $str .= str_pad($task['OGroup'] ,5," ")." ";
227 $str .= str_pad($task['Zone'] ,5," ")." ";
228 $str .= str_pad($task['Section'],5," ")." ";
229 if($task['Action'] == "initial_install"){
230 foreach($task['Initial_Target'] as $target){
231 $str .= trim($target['MAC']).",".trim($target['IP']).",".trim($target['NAME']).";";
232 }
233 }else{
234 foreach($task['Target'] as $target){
235 $str .= $target.";";
236 }
237 }
238 $str = preg_replace("/;$/","",$str);
239 }
241 /* Write contents */
242 $str .= "\n";
243 fwrite($fp,$str);
244 fclose($fp);
245 clearstatcache();
246 $this->i_fileversion = filemtime($this->s_queue_file);
247 clearstatcache();
249 /* Update ENTRY_ID -> id mapping */
250 reset($this->a_queue);
251 foreach($this->a_queue as $id => $entry){
252 $this->id_entry_map[$entry['ID']] = $id;
253 }
255 return(TRUE);
256 }
258 private function _add_entry($entry,$task_id = "")
259 {
260 if($task_id == "" || empty($task_id)){
261 $task_id = $this->get_new_id();
262 }
263 $entry['TASK_ID'] = $task_id;
264 if(!isset($entry['ID']) || empty($entry['ID']) || !isset($entry['ID']) || empty($entry['ID'])){
265 $entry['ID'] = $this->get_new_id();
266 }
267 $this->a_queue[] = $entry;
269 return(true);
270 }
272 public function get_entry($id)
273 {
274 if(isset($this->a_queue[$this->id_entry_map[$id]])){
275 return($this->a_queue[$this->id_entry_map[$id]]);
276 }else{
277 $this->set_error(sprintf(_("Entry with id '%s' not found."),$id));
278 }
279 }
281 public function update_entry($id,$entry)
282 {
283 if(isset($this->id_entry_map[$id])){
284 $this->a_queue[$this->id_entry_map[$id]] = $entry;
285 return($this->_save_data());
286 }else{
287 $this->set_error(sprintf(_("Could not update entry, entry with id '%s' not found."),$id));
288 }
289 }
291 public function remove_entry($id)
292 {
293 if(isset($this->id_entry_map[$id])){
294 unset($this->a_queue[$this->id_entry_map[$id]]);
295 unset($this->id_entry_map[$id]);
296 return($this->_save_data());
297 }else{
298 $this->set_error(sprintf(_("Could not remove entry, entry with id '%s' not found."),$id));
299 }
300 }
302 public function id_exists($id)
303 {
304 return(isset($this->id_entry_map[$id]));
305 }
308 public function add($entry)
309 {
310 if(!$this->_add_entry($entry)){
311 return(FALSE);
312 }
313 return($this->_save_data());
314 }
316 public function add_multiple($array)
317 {
318 $task_id = $this->get_new_id();
319 foreach($array as $entry){
320 if(!$this->_add_entry($entry,$task_id)){
321 return(FALSE);
322 }
323 }
324 return($this->_save_data());
325 }
327 public function fetch()
328 {
329 if(isset($this->a_queue[$this->i_pointer])){
330 $p = $this->a_queue[$this->i_pointer];
331 $this->i_pointer ++;
332 return($p);
333 }
334 return(FALSE);
335 }
337 public function load()
338 {
339 return($this->_reload_queue());
340 }
342 public function save()
343 {
344 return($this->_save_data());
345 }
347 private function _reset_error()
348 {
349 $this->b_error = FALSE;
350 $this->s_error = "";
351 }
353 private function set_error($str)
354 {
355 $this->b_error = TRUE;
356 $this->s_error = $str;
357 }
359 public function is_error()
360 {
361 return($this->b_error);
362 }
364 public function get_error()
365 {
366 return($this->s_error);
367 }
369 public function max_entry_priority($id)
370 {
371 if(!$this->id_exists($id)){
372 $this->set_error(sprintf(_("Can't set priority for ID '%s'. ID does not exist."),$id));
373 return(FALSE);
374 }
375 $tmp = array();
376 $tmp[]= $this->get_entry($id);
377 reset($this->a_queue);
378 foreach($this->a_queue as $key => $entry){
379 if($id != $entry['ID']){
380 $tmp[] = $entry;
381 }
382 }
383 $this->a_queue=$tmp;
384 return($this->_save_data());
385 }
387 public function increase_entry_priority($id)
388 {
389 if(!$this->id_exists($id)){
390 $this->set_error(sprintf(_("Can't set priority for ID '%s'. ID does not exist."),$id));
391 return(FALSE);
392 }
393 $tmp = array();
394 $skip = NULL;
395 $next = NULL;
396 reset($this->a_queue);
397 foreach($this->a_queue as $key => $entry){
398 if($next != NULL){
399 if($id == $entry['ID']){
400 $tmp[] = $entry;
401 $tmp[] = $next;
402 $next = NULL;
403 }else{
404 $tmp[] = $next;
405 $next = $entry;
406 }
407 }else{
408 $next = $entry;
409 }
410 }
411 if($next != NULL){
412 $tmp[] = $next;
413 }
414 $this->a_queue=$tmp;
415 return($this->_save_data());
416 }
418 public function decrease_entry_priority($id)
419 {
420 if(!$this->id_exists($id)){
421 $this->set_error(sprintf(_("Can't set priority for ID '%s'. ID does not exist."),$id));
422 return(FALSE);
423 }
424 $tmp = array();
425 $skip = NULL;
426 reset($this->a_queue);
427 foreach($this->a_queue as $key => $entry){
428 if($id != $entry['ID']){
429 $tmp[] = $entry;
430 if($skip != NULL){
431 $tmp[] = $skip;
432 $skip = NULL;
433 }
434 }else{
435 $skip = $entry;
436 }
437 }
438 if($skip != NULL){
439 $tmp[] = $skip;
440 }
441 $this->a_queue=$tmp;
442 return($this->_save_data());
443 }
445 private function get_new_id()
446 {
447 $mt = microtime();
448 $sec = preg_replace("/^0.([0-9]*) ([0-9]*)$/","\\2",$mt);
449 $msec = preg_replace("/^0.([0-9]*) ([0-9]*)$/","\\1",$mt);
450 return(strtoupper(base_convert($sec,10,36).base_convert($msec,10,36)));
451 }
453 public function min_entry_priority($id)
454 {
455 if(!$this->id_exists($id)){
456 $this->set_error(sprintf(_("Can't set priority for ID '%s'. ID does not exist."),$id));
457 return(FALSE);
458 }
459 reset($this->a_queue);
460 $tmp = array();
461 foreach($this->a_queue as $key => $entry){
462 if($id != $entry['ID']){
463 $tmp[] = $entry;
464 }
465 }
466 $tmp[]= $this->get_entry($id);
467 $this->a_queue=$tmp;
468 return($this->_save_data());
469 }
470 }
471 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
472 ?>