5bb4da912b19fc5f37c89bf30e76c18e6854b3fd
1 <?php
3 define("DEBUG_FAI_FUNC",FALSE);
5 /* TEST PHASE .... */
7 /* Returns all object for the given release.
8 This function resolves the releases
9 from base up to the given dn.
10 */
11 function get_all_objects_for_given_base($Current_DN,$filter,$detailed = false)
12 {
13 global $config;
14 $ldap = $config->get_ldap_link();
15 $ldap->cd($config->current['BASE']);
17 /* Collect some basic informations and initialize some variables */
18 $base_release = get_release_dn($Current_DN);
19 $previous_releases = array_reverse(get_previous_releases_of_this_release($base_release,true));
20 $res = array();
21 $tmp = array();
23 /* We must also include the given release dn */
24 $previous_releases[] = $base_release;
26 /* Walk through all releases */
27 foreach($previous_releases as $release){
29 /* Get fai departments */
30 $deps_to_search = get_FAI_departments($release);
32 /* For every single department (ou=hoos,ou ..) */
33 foreach($deps_to_search as $fai_base){
35 /* Ldap search for fai classes specified in this release */
36 $ldap->cd($fai_base);
37 $ldap->search($filter,array("dn","objectClass","FAIstate"));
39 /* check the returned objects, and add/replace them in our return variable */
40 while($attr = $ldap->fetch()){
42 $buffer = array();
43 $name = str_ireplace($release,"",$attr['dn']);
45 if(isset($attr['FAIstate'][0])){
46 if(preg_match("/removed$/",$attr['FAIstate'][0])){
47 if(isset($res[$name])){
48 unset($res[$name]);
49 }
50 continue;
51 }
52 }
55 /* In detailed mode are some additonal informations visible */
56 if($detailed){
58 /* Create list of parents */
59 if(isset($res[$name])){
60 $buffer = $res[$name];
61 $buffer['parents'][] = $res[$name]['dn'];
62 }else{
63 $buffer['parents'] = array();
64 }
66 /* Append objectClass to resulsts */
67 $buffer['objectClass'] = $attr['objectClass'];
68 unset($buffer['objectClass'][0]);
69 }
71 /* Add this object to our list */
72 $buffer['dn'] = $attr['dn'];
73 $res[$name] = $buffer;
74 }
75 }
76 }
77 return($res);
78 }
82 /* Return the object defining ObjectClass e.g. FAIscriptEntry */
83 function get_FAI_type($attr)
84 {
85 $arr = array( "FAIprofile","FAIpartitionTable", "FAIpartitionDisk","FAIpartitionEntry","FAIhook","FAIhookEntry",
86 "FAIscriptEntry","FAIscript","FAIvariable","FAIvariableEntry","FAIpackageList","FAItemplate",
87 "FAItemplateEntry","FAIdebconfInfo","FAIrepository","FAIrepositoryServer","FAIbranch","FAIreleaseTag");
88 foreach($arr as $name){
89 if(in_array($name,$attr['objectClass'])){
90 preg_match("");
91 return($name);
92 }
93 }
94 if(DEBUG_FAI_FUNC) { echo "Not found"; }
95 return("");
96 }
99 /* Return all relevant FAI departments */
100 function get_FAI_departments($suffix = "")
101 {
102 $arr = array("hooks","scripts","disk","packages","profiles","templates","variables");
103 $tmp = array();
104 if(preg_match("/^,/",$suffix)){
105 $suffix = preg_replace("/^,/","",$suffix);
106 }
107 foreach($arr as $name){
108 if(empty($suffix)){
109 $tmp[$name] = "ou=".$name;
110 }else{
111 $tmp[$name] = "ou=".$name.",".$suffix;
112 }
113 }
114 return($tmp);
115 }
118 /* Return all releases within the given base */
119 function get_all_releases_from_base($dn)
120 {
121 global $config;
122 $base = "ou=fai,ou=configs,ou=systems,".$dn;
123 $res = array();
125 $ldap = $config->get_ldap_link();
126 $ldap->cd($base);
127 $ldap->search("(objectClass=FAIbranch)",array("ou","dn"));
128 while($attrs = $ldap->fetch()){
129 $res[$attrs['dn']] = $attrs['ou'][0];
130 }
131 return($res);
132 }
135 /* Add this object to list of objects, that must be checked for release saving */
136 function prepare_to_save_FAI_object($Current_DN,$objectAttrs,$removed = false)
137 {
138 /* Get ldap object */
139 global $config;
140 $addObj['Current_DN'] = $Current_DN;
141 $addObj['objectAttrs']= $objectAttrs;
142 $addObj['removed'] = $removed;
143 $addObj['diff'] = TRUE;
145 if(!$removed){
146 $ldap = $config->get_ldap_link();
147 $ldap->cd($config->current['BASE']);
149 /* Get some basic informations */
150 $parent_obj = get_parent_release_object($Current_DN);
151 if(!empty($parent_obj)){
152 $ldap->cat($parent_obj,array("*"));
153 $attrs = prepare_ldap_fetch_to_be_saved($ldap->fetch());
155 if(!array_diff_FAI( $attrs,$objectAttrs)){
156 $addObj['diff'] = FALSE;
157 }
158 }
159 }
161 $_SESSION['FAI_objects_to_save'][$Current_DN] = $addObj;
162 }
165 /* Detect differences in attribute arrays */
166 function array_diff_FAI($ar1,$ar2)
167 {
168 foreach($ar1 as $key1 => $val1){
170 if((is_array($val1)) && (count($val1)==1)){
171 $ar1[$key1] = $val1[0];
172 }
174 if(!isset($ar2[$key1])){
175 return(true);
176 }
178 if((is_array($ar2[$key1])) && (count($ar2[$key1])==1)){
179 $val1 = $val1[0];
180 $ar2[$key1] = $ar2[$key1][0];
181 }
182 }
183 if(count( array_diff($ar1,$ar2))){
184 return(true);
185 }else{
186 return(false);
187 }
188 }
191 /* check which objects must be saved, and save them */
192 function save_release_changes_now()
193 {
194 /* Variable init*/
195 $to_save = array();
197 /* check which objects must be saved */
198 foreach($_SESSION['FAI_objects_to_save'] as $Current_DN => $object){
199 if($object['diff']){
200 $sub_name = $Current_DN;
201 while(isset($_SESSION['FAI_objects_to_save'][$sub_name])){
202 $to_save[strlen($sub_name)][$sub_name] = $_SESSION['FAI_objects_to_save'][$sub_name];
203 unset($_SESSION['FAI_objects_to_save'][$sub_name]);
204 $sub_name = preg_replace('/^[^,]+,/', '', $sub_name);
205 }
206 }
207 }
209 /* Sort list of objects that must be saved, and ensure that
210 container objects are safed, before their childs are saved */
211 ksort($to_save);
212 $tmp = array();
213 foreach($to_save as $SubObjects){
214 foreach($SubObjects as $object){
215 $tmp[] = $object;
216 }
217 }
218 $to_save = $tmp;
220 /* Save objects and manage the correct release behavior*/
221 foreach($to_save as $save){
223 $Current_DN = $save['Current_DN'];
224 $removed = $save['removed'];
225 $objectAttrs= $save['objectAttrs'];
227 /* Get ldap object */
228 global $config;
229 $ldap = $config->get_ldap_link();
230 $ldap->cd($config->current['BASE']);
232 /* Get some basic informations */
233 $base_release = get_release_dn($Current_DN);
234 $sub_releases = get_sub_releases_of_this_release($base_release,true);
235 $parent_obj = get_parent_release_object($Current_DN);
236 $following_releases = get_sub_releases_of_this_release($base_release,true);
238 /* Check if given dn exists or if is a new entry */
239 $ldap->cat($Current_DN);
240 if(!$ldap->count()){
241 $is_new = true;
242 }else{
243 $is_new = false;
244 }
246 /* if parameter removed is true, we have to add FAIstate to the current attrs
247 FAIstate should end with ...|removed after this operation */
248 if($removed ){
249 $ldap->cat($Current_DN);
251 /* Get current object, because we must add the FAIstate ...|removed */
252 if((!$ldap->count()) && !empty($parent_obj)){
253 $ldap->cat($parent_obj);
254 }
256 /* Check if we have found a suiteable object */
257 if(!$ldap->count()){
258 echo "Error can't remove this object ".$Current_DN;
259 return;
260 }else{
262 /* Set FAIstate to current objectAttrs */
263 $objectAttrs = prepare_ldap_fetch_to_be_saved($ldap->fetch());
264 if(isset($objectAttrs['FAIstate'][0])){
265 if(!preg_match("/removed$/",$objectAttrs['FAIstate'][0])){
266 $objectAttrs['FAIstate'][0] .= "|removed";
267 }
268 }else{
269 $objectAttrs['FAIstate'][0] = "|removed";
270 }
271 }
272 }
274 /* Check if this a leaf release or not */
275 if(count($following_releases) == 0 ){
277 /* This is a leaf object. It isn't unherited by any other object */
278 if(DEBUG_FAI_FUNC) {
279 echo "<b>Saving directly, is a leaf object</b><br> ".$Current_DN;
280 print_a($objectAttrs);
281 }
282 save_FAI_object($Current_DN,$objectAttrs);
283 }else{
285 /* This object is inherited by some sub releases */
287 /* Get all releases, that inherit this object */
288 $r = get_following_releases_that_inherit_this_object($Current_DN);
290 /* Get parent object */
291 $ldap->cat($parent_obj);
292 $parent_attrs = prepare_ldap_fetch_to_be_saved($ldap->fetch());
294 /* New objects require special handling */
295 if($is_new){
297 /* check if there is already an entry named like this,
298 in one of our parent releases */
299 if(!empty($parent_obj)){
300 if(DEBUG_FAI_FUNC) {
301 echo "There is already an entry named like this.</b><br>";
303 echo "<b>Saving main object</b>".$Current_DN;
304 print_a($objectAttrs);
305 }
306 save_FAI_object($Current_DN,$objectAttrs);
308 foreach($r as $key){
309 if(DEBUG_FAI_FUNC) {
310 echo "<b>Saving parent to following release</b> ".$key;
311 print_a($parent_attrs);
312 }
313 save_FAI_object($key,$parent_attrs);
314 }
315 }else{
317 if(DEBUG_FAI_FUNC) {
318 echo "<b>Saving main object</b>".$Current_DN;
319 print_a($objectAttrs);
320 }
321 save_FAI_object($Current_DN,$objectAttrs);
323 if(isset($objectAttrs['FAIstate'])){
324 $objectAttrs['FAIstate'] .= "|removed";
325 }else{
326 $objectAttrs['FAIstate'] = "|removed";
327 }
329 foreach($r as $key ){
330 if(DEBUG_FAI_FUNC) {
331 echo "<b>Create an empty placeholder in follwing release</b> ".$key;
332 print_a($objectAttrs);
333 }
334 save_FAI_object($key,$objectAttrs);
335 }
336 }
337 }else{
339 /* check if we must patch the follwing release */
340 if(!empty($r)){
341 foreach($r as $key ){
342 if(DEBUG_FAI_FUNC) {
343 echo "<b>Copy current objects original attributes to next release</b> ".$key;
344 print_a($parent_attrs);
345 }
346 save_FAI_object($key,$parent_attrs);
347 }
348 }
350 if(DEBUG_FAI_FUNC) {
351 echo "<b>Saving current object</b>".$parent_obj;
352 print_a($objectAttrs);
353 }
354 save_FAI_object($parent_obj,$objectAttrs);
356 if(($parent_obj != $Current_DN)){
357 print_red(sprintf(_("Error, following objects should be equal '%s' and '%s'"),$parent_obj,$Current_DN));
358 }
359 }
360 }
361 }
362 $_SESSION['FAI_objects_to_save'] = array();
363 }
366 /* this function will remove all unused (deleted) objects,
367 that have no parent object */
368 function clean_up_releases($Current_DN)
369 {
370 global $config;
371 $ldap = $config->get_ldap_link();
372 $ldap->cd($config->current['BASE']);
374 /* Collect some basic informations and initialize some variables */
375 $base_release = get_release_dn($Current_DN);
376 $previous_releases = array_reverse(get_previous_releases_of_this_release($base_release,true));
377 $Kill = array();
378 $Skip = array();
380 /* We must also include the given release dn */
381 $previous_releases[] = $base_release;
383 /* Walk through all releases */
384 foreach($previous_releases as $release){
386 /* Get fai departments */
387 $deps_to_search = get_FAI_departments($release);
389 /* For every single department (ou=hoos,ou ..) */
390 foreach($deps_to_search as $fai_base){
392 /* Ldap search for fai classes specified in this release */
393 $ldap->cd($fai_base);
394 $ldap->search("(objectClass=FAIclass)",array("dn","objectClass","FAIstate"));
396 /* check the returned objects, and add/replace them in our return variable */
397 while($attr = $ldap->fetch()){
399 $buffer = array();
400 $name = str_ireplace($release,"",$attr['dn']);
402 if(isset($attr['FAIstate'][0])&&(preg_match("/removed$/",$attr['FAIstate'][0]))){
404 /* Check if this object is required somehow */
405 if(!isset($Skip[$name])){
406 $Kill[$attr['dn']] = $attr['dn'];
407 }
408 }else{
410 /* This object is required (not removed), so do not
411 delete any following sub releases of this object */
412 $Skip[$name] = $attr['dn'];
413 }
414 }
415 }
416 }
417 return($Kill);
418 }
421 function prepare_ldap_fetch_to_be_saved($attrs)
422 {
423 foreach($attrs as $key => $value){
424 if(is_numeric($key) || ($key == "count") || ($key == "dn")){
425 unset($attrs[$key]);
426 }
427 if(is_array($value) && isset($value['count'])){
428 unset($attrs[$key]['count']);
429 }
430 }
431 return($attrs);
432 }
435 function save_FAI_object($dn,$attrs)
436 {
437 global $config;
438 $ldap = $config->get_ldap_link();
439 $ldap->cd($config->current['BASE']);
440 $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $dn));
441 $ldap->cd($dn);
443 $ldap->cat($dn,array("dn"));
444 if($ldap->count()){
446 if(!isset($attrs['FAIstate'])){
447 $attrs['FAIstate'] = array();
448 }
450 $ldap->modify($attrs);
451 }else{
452 $ldap->add($attrs);
453 }
454 show_ldap_error($ldap->get_error(),sprintf(_("Release management failed, can't save '%s'"),$dn));
455 }
458 function get_following_releases_that_inherit_this_object($dn)
459 {
460 global $config;
461 $ldap = $config->get_ldap_link();
462 $ldap->cd($config->current['BASE']);
464 $ret = array();
466 /* Get base release */
467 $base_release = get_release_dn($dn);
469 /* Get previous release dns */
470 $sub_releases = get_sub_releases_of_this_release($base_release);
472 /* Get dn suffix. Example "FAIvairableEntry=keksdose,FAIvariable=Keksregal," */
473 $dn_suffix = str_ireplace($base_release,"",$dn);
475 /* Check if given object also exists whitin one of these releases */
476 foreach($sub_releases as $p_release => $name){
478 $check_dn = $dn_suffix.$p_release;
480 $ldap->cat($check_dn,array("dn","objectClass"));
482 if($ldap->count()){
483 //return($ret);
484 }else{
485 $ret[$check_dn]=$check_dn;
486 }
487 }
488 return($ret);
489 }
492 /* Get previous version of the object dn */
493 function get_parent_release_object($dn,$include_myself=true)
494 {
495 global $config;
496 $ldap = $config->get_ldap_link();
497 $ldap->cd($config->current['BASE']);
498 $previous_releases= array();
500 /* Get base release */
501 $base_release = get_release_dn($dn);
502 if($include_myself){
503 $previous_releases[] = $base_release;
504 }
506 /* Get previous release dns */
507 $tmp = get_previous_releases_of_this_release($base_release,true);
508 foreach($tmp as $release){
509 $previous_releases[] = $release;
510 }
512 /* Get dn suffix. Example "FAIvairableEntry=keksdose,FAIvariable=Keksregal," */
513 $dn_suffix = str_ireplace($base_release,"",$dn);
515 /* Check if given object also exists whitin one of these releases */
516 foreach($previous_releases as $p_release){
517 $check_dn = $dn_suffix.$p_release;
518 $ldap->cat($check_dn,array("dn","objectClass"));
520 if($ldap->count()){
521 return($check_dn);
522 }
523 }
524 return("");
525 }
528 /* return release names of all parent releases */
529 function get_previous_releases_of_this_release($dn,$flat)
530 {
531 global $config;
532 $ldap = $config->get_ldap_link();
533 $ldap->cd($config->current['BASE']);
534 $ret = array();
536 /* Explode dns into pieces, to be able to build parent dns */
537 $dns_to_check = ldap_explode_dn(str_ireplace(",".$config->current['BASE'],"",$dn),0);
538 if(!is_array($dns_to_check)){
539 return;
540 }
542 /* Unset first entry which represents the given dn */
543 unset($dns_to_check['count']);
544 unset($dns_to_check[key($dns_to_check)]);
546 /* Create dns addresses and check if this dn is a release dn */
547 $id = 0;
548 while(count($dns_to_check)){
550 /* build parent dn */
551 $new_dn = "";
552 foreach($dns_to_check as $part){
553 $new_dn .= $part.",";
554 }
555 $new_dn .= $config->current['BASE'];
557 /* check if this dn is a release */
558 if(is_release_department($new_dn)){
559 if($flat){
560 $ret[$id] = $new_dn;
561 }else{
562 $ret = array($new_dn=>$ret);
563 }
564 $id ++;
565 }else{
566 return($ret);
567 }
568 reset($dns_to_check);
569 unset($dns_to_check[key($dns_to_check)]);
570 }
571 return($ret);
572 }
575 /* This function returns all sub release names, recursivly */
576 function get_sub_releases_of_this_release($dn,$flat = false)
577 {
578 global $config;
579 $res = array();
580 $ldap = $config->get_ldap_link();
581 $ldap->cd($config->current['BASE']);
582 $ldap->ls("(objectClass=FAIbranch)",$dn,array("objectClass","dn","ou"));
583 while($attr = $ldap->fetch()){
585 /* Append department name */
586 if($flat){
587 $res[$attr['dn']] = $attr['ou'][0];
588 }else{
589 $res[$attr['dn']] = array();
590 }
592 /* Get sub release departments of this department */
593 if(in_array("FAIbranch",$attr['objectClass'])) {
594 if($flat){
595 $tmp = get_sub_releases_of_this_release($attr['dn'],$flat);
596 foreach($tmp as $dn => $value){
597 $res[$dn]=$value;
598 }
599 }else{
600 $res[$attr['dn']] = get_sub_releases_of_this_release($attr['dn']);
601 }
602 }
603 }
604 return($res);
605 }
608 /* Check if the given department is a release department */
609 function is_release_department($dn)
610 {
611 global $config;
612 $ldap = $config->get_ldap_link();
613 $ldap->cd($config->current['BASE']);
614 $ldap->cat($dn,array("objectClass","ou"));
616 /* Check objectClasses and name to check if this is a release department */
617 if($ldap->count()){
618 $attrs = $ldap->fetch();
620 $ou = "";
621 if(isset($attrs['ou'][0])){
622 $ou = $attrs['ou'][0];
623 }
625 if((in_array("FAIbranch",$attrs['objectClass'])) || ($ou == "fai")){
626 return($attrs['dn']);
627 }
628 }
629 return(false);
630 }
633 /* This function returns the dn of the object release */
634 function get_release_dn($Current_DN)
635 {
636 global $config;
637 $ldap = $config->get_ldap_link();
638 $ldap->cd($config->current['BASE']);
640 /* Split dn into pices */
641 $dns_to_check = ldap_explode_dn(str_ireplace(",".$config->current['BASE'],"",$Current_DN),0);
642 if(!is_array($dns_to_check)){
643 return;
644 }
646 /* Use dn pieces, to create sub dns like
647 ou=test,ou=1,ou=0...
648 ou=1,ou=0...
649 ou=0...
650 To check which dn is our release container.
651 */
652 unset($dns_to_check['count']);
653 while(count($dns_to_check)){
655 /* Create dn */
656 $new_dn = "";
657 foreach($dns_to_check as $part){
658 $new_dn .= $part.",";
659 }
660 $new_dn .= $config->current['BASE'];
662 /* Check if this dn is a release dn */
663 if(is_release_department($new_dn)){
664 return($new_dn);
665 }
667 /* Remove first element of dn pieces */
668 reset($dns_to_check);
669 unset($dns_to_check[key($dns_to_check)]);
670 }
671 return("");
672 }
674 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
675 ?>