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: class_faiManagement.inc 14742 2009-11-04 13:18:33Z hickert $$
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 class faiManagement extends management
24 {
25 var $plHeadline = "Software deployment";
26 var $plDescription = "Manage software packages and deployment recipes for Windows and Linux systems";
27 var $plIcon = "plugins/fai/images/plugin.png";
29 // Tab definition
30 protected $tabClass = "";
31 protected $tabType = "";
32 protected $aclCategory = "";
33 protected $aclPlugin = "";
34 protected $objectName = "FAI object";
35 protected $releaseSelector = NULL;
37 // Attributes Managed by this plugin can be used in post events
38 public $attributes = array("lock_type","lock_name","lock_dn");
40 var $dispNewBranch=false;
41 var $dispNewFreeze=false;
43 var $fai_release = ""; // The currently selected release while in release management mode!
44 var $fai_base = "";
45 var $acl_base = "";
47 var $lock_type = "";
48 var $lock_dn = "";
49 var $lock_name = "";
51 var $opsi = NULL;
54 function __construct($config,$ui)
55 {
56 $this->config = $config;
58 /* Check if the opsi plugin is installed.
59 */
60 if(class_available("opsi")){
61 $this->opsi = new opsi($this->config);;
62 }
64 $this->fai_base = get_ou("faiManagement", "faiBaseRDN").$this->config->current['BASE'];
65 $cfg_rel = $this->config->get_cfg_value("faiManagement","defaultFaiRelease");
67 if(!empty($cfg_rel)){
68 $this->fai_release = $cfg_rel;
69 }else{
70 $this->fai_release = $this->fai_base;
71 }
73 $releases = $this->getReleaseList();
74 if(!isset($releases[$this->fai_release])){
75 $this->fai_release = $this->fai_base;
76 }
78 $this->acl_base = $this->config->current['BASE'];
79 $this->ui = $ui;
80 $this->storagePoints = array(
81 get_ou("faiPartitionTable", "faiPartitionRDN"),
82 get_ou("faiPackage", "faiPackageRDN"),
83 get_ou("faiScript", "faiScriptRDN"),
84 get_ou("faiVariable", "faiVariableRDN"),
85 get_ou("faiHook", "faiHookRDN"),
86 get_ou("faiProfile", "faiProfileRDN"),
87 get_ou("faiTemplate", "faiTemplateRDN"));
89 // Build filter
90 if (session::global_is_set(get_class($this)."_filter")){
91 $filter= session::global_get(get_class($this)."_filter");
92 } else {
93 $filter = new filter(get_template_path("fai-filter.xml", true));
94 $filter->setObjectStorage($this->storagePoints);
95 }
96 $filter->elementValues['RELEASE'] = $this->fai_release;
97 $this->setFilter($filter);
99 // Build headpage
100 $headpage = new listing(get_template_path("fai-list.xml", true));
101 $headpage->setFilter($filter);
102 $headpage->setBase($this->fai_release);
103 $headpage->registerElementFilter("filterProperties", "faiManagement::filterProperties");
105 // Add copy&paste and snapshot handler.
106 if ($this->config->boolValueIsTrue("core", "copyPaste")){
107 $this->cpHandler = new CopyPasteHandler($this->config);
108 }
110 $this->registerAction("remove_multiple","removeEntryRequested");
111 $this->registerAction("new_profile","newEntry");
112 $this->registerAction("new_template","newEntry");
113 $this->registerAction("new_script","newEntry");
114 $this->registerAction("new_hook","newEntry");
115 $this->registerAction("new_variable","newEntry");
116 $this->registerAction("new_package","newEntry");
117 $this->registerAction("new_partition","newEntry");
118 $this->registerAction("newClassNameSelected","newClassNameSelected");
119 $this->registerAction("saveOpsiProperties","saveOpsiProperties");
120 $this->registerAction("editByGroup","editByGroup");
121 $this->registerAction("createBranch","createBranch");
122 $this->registerAction("createFreeze","createFreeze");
123 $this->registerAction("removeBranch","removeBranch");
124 $this->registerAction("removeBranchConfirmed","removeBranchConfirmed");
125 $this->registerAction("saveBranch","saveBranch");
126 $this->registerAction("PerformBranch","PerformBranch");
128 $releases = $this->getReleaseStates($this->config,$this->fai_base);
129 $this->releaseSelector = new releaseSelector($releases, $this->fai_release, $this->fai_base);
130 parent::__construct($config, $ui, "FAI object", $headpage);
131 }
134 /*! \brief Act on copy & paste actions here.
135 */
136 function copyPasteHandler($action="",$target=array(),$all=array(),$altTabClass ="",$altTabType="",$altAclCategory="",$altAclPlugin="")
137 {
138 // Collect real dns, the listed objects are grouped by their cn
139 $headpage = $this->getHeadpage();
140 if($action == "copy"){
142 if(count($target) == 1){
144 // We just want to copy a single FAI object, let the user choose entries from the FAI-Group
145 $entry = $headpage->getEntry($target[0]);
146 if(count($entry['GROUPS']) == 1){
147 $data = array_pop($entry['GROUPS']);
148 $type = $this->get_type($data);
149 $this->cpHandler->add_to_queue($data['dn'],"copy",$type[0],$type[2],'fai',$this);
150 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$g['dn'],"Entry copied!");
151 }else{
152 $this->dialogObject = new faiGroupHandle($entry['GROUPS'],"copy");
153 }
155 }else{
157 // More than one group was selected, expect that the user wants to copy the complete groups.
158 foreach($target as $t){
159 $entry = $headpage->getEntry($t);
161 // Check for valid FAI objects
162 if(in_array('FAKE_OC_FAI', $entry['objectClass'])){
163 foreach($entry['GROUPS'] as $g){
164 $type = $this->get_type($g);
165 $this->cpHandler->add_to_queue($g['dn'],"copy",$type[0],$type[2],'fai',$this);
166 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$g['dn'],"Entry copied!");
167 }
168 }
169 }
170 }
171 }
173 // Initiate pasting
174 if($action == "paste"){
175 $this->cpPastingStarted = TRUE;
176 }
178 // Display any c&p dialogs, eg. object modifications required before pasting.
179 if($this->cpPastingStarted && $this->cpHandler->entries_queued()){
180 $this->cpHandler->SetVar("base",$headpage->getBase());
181 $data = $this->cpHandler->execute();
182 FAI::save_release_changes_now();
183 if(!empty($data)){
184 return($data);
185 }
186 }
188 // Automatically disable pasting process since there is no entry left to paste.
189 if(isset($this->cpHandler) && !$this->cpHandler->entries_queued()){
190 $this->cpPastingStarted = FALSE;
191 }
192 return("");
193 }
196 /*! \brief A new FAI object was requested, let the user specify a name theis object now.
197 */
198 function newEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory="")
199 {
200 $types = array(
201 "new_partition" => "FAIpartitionTable",
202 "new_script" => "FAIscript",
203 "new_hook" => "FAIhook",
204 "new_variable" => "FAIvariable",
205 "new_template" => "FAItemplate",
206 "new_package" => "FAIpackageList");
207 $types_i18n = array(
208 "new_partition" => _("partition table"),
209 "new_script" => _("script"),
210 "new_hook" => _("hook"),
211 "new_variable" => _("variable"),
212 "new_template" => _("template"),
213 "new_package" => _("package list"));
215 if(isset($types[$action])){
216 $type_acl_mapping = array(
217 "FAIpartitionTable" => "faiPartitionTable",
218 "FAIpackageList" => "faiPackage",
219 "FAIscript" => "faiScript",
220 "FAIvariable" => "faiVariable",
221 "FAIhook" => "faiHook",
222 "FAIprofile" => "faiProfile",
223 "FAItemplate" => "faiTemplate");
225 $acl = $this->ui->get_permissions($this->acl_base,"fai/".$type_acl_mapping[$types[$action]]);
226 if(preg_match("/c/",$acl)){
227 $this->dialogObject = new askClassName($this->config,$this->dn,$this->ui,$types[$action]);
228 $this->dialogObject->parent = &$this;
229 }else{
230 msg_dialog::display(_("Permission error"),
231 sprintf(_("You have no permission to create a new %s!"), $types_i18n[$action]), ERROR_DIALOG);
232 }
233 }
234 if($action == "new_profile"){
235 $this->dn = "new" ;
237 $acl = $this->ui->get_permissions($this->acl_base,"fai/faiProfile");
238 if(preg_match("/c/",$acl)){
239 $type= $this->get_type(array("objectClass"=>array("FAIprofile")));
240 $str= management::newEntry('newEntry',array(),array(),$type[0],$type[2],'fai');
241 if($str) return($str);
242 $this->tabObject->set_acl_base($this->acl_base);
243 }else{
244 msg_dialog::display(_("Permission error"), sprintf(_("You have no permission to create a new %s!"), _("profile")), ERROR_DIALOG);
245 }
246 }
247 }
250 /*! \brief A new FAI class was requested and the user had a specify a name for it.
251 * Here we check if this name is useable and then open the edit dialogs.
252 */
253 function newClassNameSelected()
254 {
255 $this->dialogObject->save_object();
256 if(count($this->dialogObject->check())!=0){
257 foreach($this->dialogObject->check() as $msg){
258 msg_dialog::display(_("Error"), $msg, ERROR_DIALOG);
259 }
260 }elseif(isset($this->dialogObject->objectClass)){
261 $this->dn = "new" ;
262 $type= $this->get_type(array("objectClass"=>array($this->dialogObject->objectClass)));
263 $name = $this->dialogObject->save();
265 if(class_exists($type[0])){
266 $this->closeDialogs();
267 $str = management::newEntry('newEntry',array(),array(),$type[0],$type[2],"fai");
268 if($str) return($str);
269 $this->tabObject->set_acl_base($this->acl_base);
270 $this->tabObject->by_object[$type[1]]->cn = $name;
271 }
272 }
273 }
276 /*! \brief Edit the selected entry.
277 * If there was a FAI group clicked, display a dialog with all members of the group.
278 */
279 function editEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory="")
280 {
281 $headpage = $this->getHeadpage();
282 if(count($target) == 1){
283 $entry = $headpage->getEntry($target[0]);
284 if($entry){
286 // Edit Opsi objects here
287 if(in_array("opsi_local", $entry['TYPES']) || in_array("opsi_netboot", $entry['TYPES'])){
288 $name = $entry['cn'];
289 $cfg = $this->opsi->get_product_properties($name);
291 $str = management::editEntry('editEntry',array($name),array(),'tabs_opsiProdConfig','OPSIPRODCONFIG','opsi');
292 if($str) return($str);
293 if(isset($this->tabObject->by_object['opsiProperties'])){
294 $this->tabObject->by_object['opsiProperties']->set_cfg($cfg);
295 $this->tabObject->by_object['opsiProperties']->set_product($name);
296 $this->skipFooter = TRUE;
297 }else{
298 trigger_error("Unknown tab, please check config.");
299 }
301 }else{
303 // Edit FAI objects here
304 if(count($entry['GROUPS']) == 1){
305 $data = array_pop($entry['GROUPS']);
306 $type = $this->get_type($data);
307 $str = management::editEntry('editEntry',array($data['dn']),array(),$type[0],$type[2],"fai");
308 if($str) return($str);
309 $this->tabObject->by_object[$type[1]]->FAIstate = $data['FAIstate'];
310 $this->tabObject->read_only = preg_match("/freeze/i", $data['FAIstate']);
312 }else{
313 $this->dialogObject = new faiGroupHandle($entry['GROUPS'],"edit");
314 }
315 }
316 }
317 }
318 }
321 /*! \brief Save changes made in opsi dialogs.
322 */
323 function saveOpsiProperties()
324 {
325 if($this->tabObject instanceof tabs_opsiProdConfig && isset($_POST['save_properties'])){
326 $this->tabObject->save_object();
327 $op = $this->tabObject->by_object['opsiProperties'];
328 $name = $op->get_product();
329 $cfg = $op->get_cfg();
330 $this->opsi->set_product_properties($name,$cfg);
331 if($this->opsi->is_error()){
332 msg_dialog::display(_("Error"),msgPool::siError($this->opsi->get_error()),ERROR_DIALOG);
333 }else{
334 $this->remove_lock();
335 $this->closeDialogs();
336 }
337 }
338 }
341 /*! \brief Someone wants to remove some object(s)
342 * ask for a confirmation now.
343 */
344 function removeEntryRequested($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory="")
345 {
346 $this->closeDialogs();
347 if($action == "remove_multiple"){
349 // Collect objects to delete
350 $headpage = $this->getHeadpage();
351 $to_delete = array();
352 foreach($target as $id){
353 $object = $headpage->getEntry($id);
354 if(in_array("FAKE_OC_FAI", $object['objectClass'])){
355 foreach($object['GROUPS'] as $entry){
356 array_push($to_delete, $entry);
357 }
358 }
359 }
360 return($this->removeFAIObjects($to_delete));
361 }else{
363 // Try to remove a single object, only FAI objects can be removed!
364 $headpage = $this->getHeadpage();
365 if(count($target) == 1){
366 $entry = $headpage->getEntry($target[0]);
367 if($entry && in_array("FAKE_OC_FAI",$entry['objectClass'])){
368 $this->dialogObject = new faiGroupHandle($entry['GROUPS'],"remove");
369 }
370 }
371 }
372 }
375 /*! \brief Someone wants to remove some object(s)
376 * ask for a confirmation now.
377 */
378 function removeFAIObjects($to_delete)
379 {
380 // Close dialogs and remove locks for currently handled dns
381 $this->cancelEdit();
383 // Do not allow to remove objects with state freeezed
384 $errors = $disallowed = array();
386 foreach($to_delete as $obj){
387 $type = $this->get_type($obj);
388 $acl = $this->ui->get_permissions($obj['dn'],"fai/".$type[1]);
389 if(!preg_match("/d/",$acl)){
390 $disallowed[] = $obj['dn'];
391 }elseif(isset($obj['FAIstate']) && preg_match('/^freeze/', $obj['FAIstate'])){
392 $errors[] = $obj['dn'];
393 }else{
394 $this->dns[] = $obj['dn'];
395 }
396 }
397 if(count($errors)){
398 msg_dialog::display(_("Branch locked"),
399 sprintf(_("The following entries are locked, you can't remove them %s."),msgPool::buildList($errors)),INFO_DIALOG);
400 }
401 if(count($disallowed)){
402 msg_dialog::display(_("Permission error"), msgPool::permDelete($disallowed), ERROR_DIALOG);
403 }
405 // Check entry locking
406 $smarty = get_smarty();
407 if(count($this->dns)){
408 if ($user= get_multiple_locks($this->dns)){
409 return(gen_locked_message($user,$this->dns));
410 }
411 if(count($this->dns)){
413 // Add locks
414 $dns_names = array();
415 $types = array();
416 $h = $this->getHeadpage();
418 // Build list of object -labels
419 foreach($h->objectTypes as $type){
420 $map[$type['objectClass']]= $type['label'];
421 }
423 foreach($this->dns as $dn){
424 $tmp = $h->getType($dn);
425 if(isset($map[$tmp])){
426 $dns_names[] = '('._($map[$tmp]).') - '.LDAP::fix($dn);
427 }else{
428 $dns_names[] =LDAP::fix($dn);
429 }
430 }
431 add_lock ($this->dns, $this->ui->dn);
433 $smarty->assign("info",msgPool::deleteInfo($dns_names));
434 return($smarty->fetch(get_template_path('removeEntries.tpl')));
435 }
436 }
437 }
440 /*! \brief Entry removal is confirmed, now remove objects
441 */
442 function removeEntryConfirmed($action="",$target=array(),$all=array(),
443 $altTabClass="",$altTabType="",$altAclCategory="", $altAclPlugin="")
444 {
445 $ldap = $this->config->get_ldap_link();
446 $ldap->cd($this->config->current['BASE']);
448 $disallowed = array();
449 foreach($this->dns as $key => $dn){
450 $ldap->cat($dn);
451 if($ldap->count()){
452 $attrs = $ldap->fetch();
453 $type= $this->get_type($attrs);
454 $acl = $this->ui->get_permissions($dn,"fai/".$type[1]);
455 if(preg_match("/d/",$acl)){
457 // Delete the object
458 $this->dn = $dn;
459 $tabClass = $type[0];
460 $this->tabObject= new $tabClass($this->config,$this->config->data['TABS'][$type[2]],
461 $this->dn, "fai", true, true);
462 $this->tabObject->set_acl_base($this->dn);
463 $this->tabObject->parent = &$this;
464 $this->tabObject->by_object[$type[1]]->remove_from_parent ();
466 FAI::save_release_changes_now();
467 $to_del = FAI::clean_up_releases($dn);
468 foreach($to_del as $dn){
469 $ldap->rmdir_recursive($dn);
470 }
472 } else {
473 $disallowed[] = $dn;
474 new log("security","fai/".get_class($this),$dn,array(),"Tried to trick deletion.");
475 }
476 }
477 }
479 $this->remove_lock();
480 $this->closeDialogs();
482 /* Normally this shouldn't be reached, send some extra
483 logs to notify the administrator */
484 if(count($disallowed)){
485 msg_dialog::display(_("Permission error"), msgPool::permDelete($disallowed), ERROR_DIALOG);
486 }
487 }
490 /*! \brief Someone clicked on edit/remove for a grouped FAI object.
491 * We are now going to display a dialog to let the user select the entry
492 * he wants to perform the action on.
493 */
494 function editByGroup()
495 {
496 if($this->dialogObject instanceOf faiGroupHandle && $this->dialogObject->get_mode() == "edit"){
497 $this->dialogObject->save_object();
498 $entry = $this->dialogObject->get_selected();
499 $this->closeDialogs();
500 $data = array_pop($entry);
501 $type = $this->get_type($data);
502 $str = management::editEntry('editEntry',array($data['dn']),array(),$type[0],$type[2],'fai');
503 if($str) return($str);
504 $this->tabObject->by_object[$type[1]]->FAIstate = $data['FAIstate'];
505 $this->tabObject->read_only = preg_match("/freeze/i", $data['FAIstate']);
506 }elseif($this->dialogObject instanceOf faiGroupHandle && $this->dialogObject->get_mode() == "remove"){
507 $this->dialogObject->save_object();
508 $to_delete = $entry = $this->dialogObject->get_selected();
509 if(count($to_delete)) $this->closeDialogs();
510 return($this->removeFAIObjects($to_delete));
511 }elseif($this->dialogObject instanceOf faiGroupHandle && $this->dialogObject->get_mode() == "copy"){
512 $this->dialogObject->save_object();
513 $entries = $entry = $this->dialogObject->get_selected();
514 if(count($entries)){
515 foreach($entries as $entry){
516 $type = $this->get_type($entry);
517 $this->cpHandler->add_to_queue($entry['dn'],"copy",$type[0],$type[2],'fai',$this);
518 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$entry['dn'],"Entry copied!");
519 }
520 $this->closeDialogs();
521 }
522 }
523 }
526 /*! \brief Save dialog/object modifications
527 */
528 protected function saveChanges()
529 {
530 $str = management::saveChanges();
531 if($str) return($str);
533 // Now save changes
534 FAI::save_release_changes_now();
535 $to_del = FAI::clean_up_releases($this->last_dn);
536 $ldap= $this->config->get_ldap_link();
537 foreach($to_del as $dn){
538 $ldap->rmdir_recursive($dn);
539 }
540 }
543 /*! \brief Save dialog/object modifications but keep the dialogs opened
544 */
545 protected function applyChanges()
546 {
547 $str = management::applyChanges();
548 if($str) return($str);
550 // Now save changes
551 FAI::save_release_changes_now();
552 $to_del = FAI::clean_up_releases($this->last_dn);
553 foreach($to_del as $dn){
554 $ldap->rmdir_recursive($dn);
555 }
556 }
559 /*! \brief Initiates release removal
560 */
561 function removeBranch()
562 {
563 /* Check if we have a post remove method configured
564 * else skip this operation. (Skip:Button in the ui should be disabled in this case too)
565 */
566 if("" != $this->config->get_cfg_value("faiManagement","postremove")){
567 /* Load permissions for selected 'dn' and check if
568 we're allowed to remove this 'dn' */
569 if(preg_match("/d/",$this->ui->get_permissions($this->acl_base,"fai/faiManagement"))){
570 $smarty=get_smarty();
571 $smarty->assign("release_hidden",base64_encode($this->fai_release));
572 $smarty->assign("info", msgPool::deleteInfo(LDAP::fix($this->fai_release),_("FAI branch/freeze")));
573 return($smarty->fetch(get_template_path('remove_branch.tpl',TRUE)));
574 } else {
575 msg_dialog::display(_("Permission error"), _("You have no permission to delete this release!"), ERROR_DIALOG);
576 }
577 }
578 }
581 /*! \brief Remove a release after removal was confirmed
582 */
583 function removeBranchConfirmed()
584 {
585 /* Check if we have a post remove method configured
586 * else skip this operation. (Skip:Button in the ui should be disabled in this case too)
587 */
588 if("" != $this->config->get_cfg_value("faiManagement","postremove")){
590 if(!isset($_POST['release_hidden']) || base64_decode($_POST['release_hidden']) != $this->fai_release){
591 msg_dialog::display(_("Warning"),_("Release remove aborted because the release name check failed!"));
592 }else{
594 $bb = $this->fai_release;
595 $ldap = $this->config->get_ldap_link();
597 $br = $this->getBranches();
599 if(isset($br[$bb]) && preg_match("/d/",$this->ui->get_permissions($this->acl_base,"fai/faiManagement"))){
600 $name = $br[$bb];
602 $ldap->cd($bb);
603 $ldap->recursive_remove();
604 $ldap->cd(preg_replace('/,'.preg_quote(get_ou("faiManagement", "faiBaseRDN"), '/').'/i', ','.get_ou("application", "applicationRDN"), $bb));
605 $ldap->recursive_remove();
606 $ldap->cd(preg_replace('/,'.preg_quote(get_ou("faiManagement", "faiBaseRDN"), '/').'/i', ','.get_ou("mimetype", "mimetypeRDN"), $bb));
607 $ldap->recursive_remove();
609 /* Search for all groups with configured application menus.
610 - First search all groups, to ensure that we only remove entries form whithin groups.
611 - The search für menu configuration for the specified release and collect all those dns.
612 - Remove entries
613 */
614 $release_ou = preg_replace("/".preg_quote(get_ou("faiManagement", "faiBaseRDN"), '/').".*$/i","",$bb);
615 $ldap->cd($this->config->current['BASE']);
616 $ldap->search("(objectClass=posixGroup)",array("dn"));
618 /* Collect all group dns
619 */
620 $groups = array();
621 while($attrs = $ldap->fetch()){
622 $groups[] = $attrs['dn'];
623 }
626 /* Collect all group menu release dns that match the release we have removed
627 */
628 $dns = array();
629 foreach($groups as $dn){
630 $ldap->cd($dn);
631 $ldap->search("(objectClass=FAIbranch)",array("dn"));
632 while($attrs = $ldap->fetch()){
633 if(preg_match("/^".preg_quote($release_ou, '/')."/",$attrs['dn'])){
634 $dns[] = $attrs['dn'];
635 }
636 }
637 }
639 /* Finally remove collected release dns
640 */
641 foreach($dns as $dn){
642 $ldap->cd($dn);
643 $ldap->recursive_remove();
644 }
646 /* Post remove */
647 $this->fai_release = preg_replace("/^[^,]*+,/","", $this->fai_release);
649 $this->lock_name = $name;
650 $this->lock_dn = $bb;
651 $this->handle_post_events('remove');
653 // Update list and release selector to point to a valid release again.
654 $releases = $this->getReleaseStates($this->config,$this->fai_base);
655 if(!isset($releases[$this->fai_release])){
656 $this->fai_release = $this->fai_base;
657 }
659 $headpage = $this->getHeadpage();
660 $headpage->setBase($this->fai_release);
661 $headpage->update();
663 $this->releaseSelector->setBases($releases);
664 $this->releaseSelector->setBase($this->fai_release);
666 new log("remove","fai/".get_class($this),$br[$bb],array(),"Release removed");
667 }
668 }
669 }
670 }
673 /*! \brief Initiates release creation
674 */
675 function createBranch()
676 {
677 if($this->config->get_cfg_value("faiManagement", "postcreate") == ""){
678 msg_dialog::display(_("Configuration"), msgPool::cmdnotfound("POSTCREATE", get_class()), ERROR_DIALOG);
679 }elseif(!preg_match("/c/",$this->ui->get_permissions($this->acl_base,"fai/faiManagement"))){
680 msg_dialog::display(_("Permission error"), msgPool::permCreate(_("Branch")), ERROR_DIALOG);
681 }else{
682 $smarty = get_smarty();
683 $this->dispNewBranch=true;
684 $this->dispNewFreeze=false;
685 $smarty->assign("iframe",false);
686 if(isset($_POST['BranchName'])){
687 $smarty->assign("BranchName", get_post('BranchName'));
688 }else{
689 $smarty->assign("BranchName","");
690 }
691 return($smarty->fetch(get_template_path('faiNewBranch.tpl', TRUE, dirname(__FILE__))));
692 }
693 }
696 /*! \brief Initiates release creation
697 */
698 function createFreeze()
699 {
700 if($this->config->get_cfg_value("faiManagement", "postcreate") == ""){
701 msg_dialog::display(_("Configuration"), msgPool::cmdnotfound("POSTCREATE", get_class()), ERROR_DIALOG);
702 }elseif(!preg_match("/c/",$this->ui->get_permissions($this->acl_base,"fai/faiManagement"))){
703 msg_dialog::display(_("Permission error"), msgPool::permCreate(_("Branch")), ERROR_DIALOG);
704 }else{
705 $smarty = get_smarty();
706 $this->dispNewFreeze=true;
707 $this->dispNewBranch=false;
708 $smarty->assign("iframe",false);
709 if(isset($_POST['BranchName'])){
710 $smarty->assign("BranchName", get_post('BranchName'));
711 }else{
712 $smarty->assign("BranchName","");
713 }
714 return($smarty->fetch(get_template_path('faiNewBranch.tpl', TRUE, dirname(__FILE__))));
715 }
716 }
719 /*! \brief Creates a new branch
720 */
721 function PerformBranch()
722 {
723 if(!preg_match("/c/",$this->ui->get_permissions($this->acl_base,"fai/faiManagement"))){
724 msg_dialog::display(_("Permission error"), msgPool::permCreate(_("Branch")), ERROR_DIALOG);
725 }else{
727 /* In order to see error messages we have to reset the error handler.
728 Due to the exit();
729 */
730 restore_error_handler();
732 $this->dispNewBranch = false;
733 $this->dispNewFreeze = false;
735 $LASTPOST = session::get('LASTPOST');
736 $base = $LASTPOST['base'];
737 $_POST = session::get('LASTPOST');
738 $name = $_POST['BranchName'];
740 $type = $LASTPOST['type'];
741 $ldap = $this->config->get_ldap_link();
743 $baseToUse = $base;
744 if($this->fai_release != $this->fai_base){
745 $baseToUse = $this->fai_release;
746 }
748 /* Create new Release name to be able to set faidebianRelease for FAIpackageList */
750 $CurrentReleases = $this->getBranches();
751 $NewReleaseName = $name;
752 if(isset($CurrentReleases[$this->fai_release])) {
753 if($this->fai_release != $this->fai_base){
754 $NewReleaseName = $CurrentReleases[$this->fai_release]."/".$name;
755 $NewReleaseName = preg_replace("#\/#","/",$NewReleaseName);
756 }else{
757 $NewReleaseName = $name;
758 }
759 }
761 $targetReleaseDN = "ou=".$name.",".$baseToUse;
763 $appsEnabled = class_available("application");
764 $mimeEnabled = class_available("mimetype");
765 if($appsEnabled){
766 $appsrc = preg_replace("/".preg_quote(get_ou("faiManagement", "faiBaseRDN"), '/')."/i",
767 get_ou("application", "applicationRDN"),$baseToUse);
768 $appdst = preg_replace("/".preg_quote(get_ou("faiManagement", "faiBaseRDN"), '/')."/i",
769 get_ou("application", "applicationRDN"),"ou=".$name.",".$baseToUse) ;
770 }
771 if($mimeEnabled){
772 $mimesrc = preg_replace("/".preg_quote(get_ou("faiManagement", "faiBaseRDN"), '/')."/i",
773 get_ou("mimetype", "mimetypeRDN"),$baseToUse);
774 $mimedst = preg_replace("/".preg_quote(get_ou("faiManagement", "faiBaseRDN"), '/')."/i",
775 get_ou("mimetype", "mimetypeRDN"),"ou=".$name.",".$baseToUse) ;
776 }
778 $useBases = array();
779 $useBases[] = $baseToUse;
780 if($appsEnabled) $useBases[] = $appsrc;
781 if($mimeEnabled) $useBases[] = $mimesrc;
783 /* Check if source depeartments exist */
784 foreach($useBases as $dep){
785 $ldap->cd($this->config->current['BASE']);
786 $ldap->cat($dep);
787 if(!$ldap->count()){
788 $ldap->create_missing_trees($dep);
789 }
790 }
792 /* Print header to have styles included */
793 echo ' <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
794 <html>
795 <head>
796 <title></title>
797 <style type="text/css">@import url("themes/default/style.css");</style>
798 <script language="javascript" src="include/gosa.js" type="text/javascript"></script>
799 </head>
800 <body style="background: none;margin:3px;color:black">
801 ';
803 new log("create","fai/".get_class($this),$NewReleaseName,array(),"New $type created");
805 /* Duplicate group application releases
806 */
807 FAI::copy_FAI_group_releases($CurrentReleases[$this->fai_release],$name,$type);
809 /* Duplicate applications
810 */
811 if($appsEnabled){
812 $ldap->cat($appsrc,array("dn")) ;
813 if($ldap->count()){
814 $ldap->cd ($appdst);
815 $ldap->recursive_remove();
816 FAI::copy_FAI_resource_recursive($appsrc,$appdst,$NewReleaseName,$type,true);
817 }
818 }
820 /* Duplicate mime types
821 */
822 if($mimeEnabled){
823 $ldap->cat($mimesrc,array("dn")) ;
824 if($ldap->count()){
825 $ldap->cd ($mimedst);
826 $ldap->recursive_remove();
827 FAI::copy_FAI_resource_recursive($mimesrc,$mimedst,$NewReleaseName,$type,true);
828 }
829 }
831 $attr = array();
832 $attr['objectClass'] = array("organizationalUnit","FAIbranch");
833 $attr['ou'] = $name;
834 $attr['FAIstate'] = $type;
835 $ldap->cd($this->config->current['BASE']);
836 $ldap->cd("ou=".$name.",".$baseToUse);
837 $ldap->cat("ou=".$name.",".$baseToUse);
838 if($ldap->count()){
839 $ldap->modify($attr);
840 }else{
841 $ldap->add($attr);
842 }
844 /* Duplicate fai objects
845 */
846 // $ldap->cd ("ou=".$name.",".$baseToUse);
847 // $ldap->recursive_remove();
848 // FAI::copy_FAI_resource_recursive($baseToUse,"ou=".$name.",".$baseToUse,$NewReleaseName,$type,true);
850 echo "<div style='width:100%;text-align:right;'><form name='form' method='post' action='?plug=".$_GET['plug']."' target='_parent'>
851 <br><input type='submit' name='CloseIFrame' value='"._("Continue")."'>
852 <input type='hidden' name='php_c_check' value='1'>
853 </form></div>";
855 echo "<script language=\"javascript\" type=\"text/javascript\">scrollDown2();</script>" ;
857 /* Print footer to have valid html */
858 echo "</body></html>";
860 $this->dispNewFreeze = false;
862 /* Assign possible attributes */
863 $this->lock_type = $type;
864 $this->lock_name = $name;
865 $this->lock_dn = $baseToUse;
866 $this->handle_post_events('add');
868 /* Send daemon event to reload the fai release database
869 */
870 if(class_available("DaemonEvent") && class_available("gosaSupportDaemon")){
871 $events = DaemonEvent::get_event_types(SYSTEM_EVENT | HIDDEN_EVENT);
872 if(isset($events['TRIGGERED']['DaemonEvent_recreate_fai_release_db'])){
873 $evt = $events['TRIGGERED']['DaemonEvent_recreate_fai_release_db'];
874 $tmp = new $evt['CLASS_NAME']($this->config);
875 $tmp->set_type(TRIGGERED_EVENT);
876 $tmp->add_targets(array("GOSA"));
877 $o_queue = new gosaSupportDaemon();
878 if(!$o_queue->append($tmp)){
879 msg_dialog::display(_("Service infrastructure"),msgPool::siError($o_queue->get_error()),ERROR_DIALOG);
880 }
881 }
882 }else{
883 if($this->config->boolValueIsTrue("core","developmentMode")){
884 trigger_error("Unknown class DaemonEvent / gosaSupportDaemon");
885 msg_dialog::display(_("Fatal error"),
886 "Daemon events called but classes where not accessible, DaemonEvent gosaSupportDaemon",
887 FATAL_ERROR_DIALOG);
888 }
889 }
891 // Update list and release selector to point to the newly created release
892 $headpage = $this->getHeadpage();
893 $this->fai_release = $targetReleaseDN;
894 $headpage->setBase($this->fai_release);
895 $headpage->update();
897 $releases = $this->getReleaseStates($this->config,$this->fai_base);
898 $this->releaseSelector->setBases($releases);
899 $this->releaseSelector->setBase($this->fai_release);
900 exit();
901 }
902 }
905 /*! \brief Creates a new branch, after a useable name was specified.
906 */
907 function saveBranch()
908 {
909 if($this->dispNewBranch){
910 $type = "branch";
911 }else{
912 $type = "freeze";
913 }
915 /* Check branch name */
916 $name = $_POST['BranchName'];
917 $is_ok = true;
918 $smarty = get_smarty();
919 $smarty->assign("BranchName",$name);
920 $base= $this->fai_base;
922 /* Check used characters */
923 if(!preg_match("/^[0-9a-z\.]*$/",$name)){
924 msg_dialog::display(_("Error"), msgPool::invalid(_("Name"),$name,"/[0-9a-z\.]/"), ERROR_DIALOG);
925 $is_ok = false;
926 }
928 // Check if this name is already in use
929 if(!$this->CheckNewBranchName($_POST['BranchName'],$this->fai_release)){
930 msg_dialog::display(_("Error"), msgPool::duplicated(_("Name")), ERROR_DIALOG);
931 $is_ok = false;
932 }
934 // Handle errors
935 if(!$is_ok && $this->dispNewFreeze){
936 return($this->createFreeze());
937 }elseif(!$is_ok && $this->dispNewBranch){
938 return($this->createBranch());
939 }
941 // Now create new release
943 if(session::is_set('LASTPOST')){
944 $LASTPOST = session::get('LASTPOST');
945 }else{
946 $LASTPOST = array();
947 }
948 $LASTPOST['base'] = $base;
949 $LASTPOST['type'] = $type;
950 $LASTPOST['BranchName'] = $name;
951 session::set('LASTPOST',$LASTPOST);
952 $smarty->assign("iframe", true);
953 $smarty->assign("plugID", $_GET['plug']);
954 $display = $smarty->fetch(get_template_path('faiNewBranch.tpl', TRUE, dirname(__FILE__)));
955 return($display);
957 }
961 /*! \brief Returns a list of all releases for useable for drop down boxes.
962 * ou=fai... /
963 * ou=siga,ou=fai... siga
964 * ou=1,ou=siga,ou=fai... 1
965 */
966 function getReleaseList($base = "", $prefix ="")
967 {
968 $list = array();
969 if(empty($base)){
970 $base = $this->fai_base;
971 $list[$base] = "/";
972 }
974 $ldap = $this->config->get_ldap_link();
975 $ldap->ls("(objectClass=FAIbranch)",$base,array("ou","FAIstate"));
976 while($release = $ldap->fetch()){
977 $list[$release['dn']] = $prefix.$release['ou'][0];
978 $list = array_merge($list,$this->getReleaseList($release['dn'],$prefix." "));
979 }
980 return($list);
981 }
984 /*! \brief Returns a list of all releases for the releaseSelector
985 * ou=fai...
986 * ou=siga,ou=fai... "branch"
987 * ou=1,ou=siga,ou=fai... "freeze"
988 */
989 static function getReleaseStates($config,$base = "", $fai_base="")
990 {
991 $list = array();
992 if(empty($fai_base)){
993 $fai_base = $base;
994 $list[$base] = "";
995 }
997 $ldap = $config->get_ldap_link();
998 $ldap->ls("(objectClass=FAIbranch)",$base,array("ou","FAIstate"));
1000 while($release = $ldap->fetch()){
1001 $list[$release['dn']] = _("Release");
1002 if(isset($release['FAIstate'][0]) && preg_match("/freeze/i",$release['FAIstate'][0])){
1003 $list[$release['dn']] = _("Freeze");
1004 }
1005 $list = array_merge($list,faiManagement::getReleaseStates($config,$release['dn'], $fai_base));
1006 }
1007 return($list);
1008 }
1011 /*! \brief Returns a list of all releases with full release names
1012 * ou=fai... /
1013 * ou=siga,ou=fai... siga
1014 * ou=1,ou=siga,ou=fai... siga/1
1015 */
1016 function getBranches($base = false,$prefix = "")
1017 {
1018 $ret = array("/"=>$this->fai_base);
1019 $ldap = $this->config->get_ldap_link();
1020 if(!$base){
1021 $base = $this->fai_base;
1022 }
1023 $tmp = FAI::get_all_releases_from_base($base,true);
1024 foreach($tmp as $dn => $name){
1025 $ret[$name]=$dn;
1026 }
1027 ksort($ret);
1028 $ret = array_flip($ret);
1030 return ($ret);
1031 }
1034 /*! \brief Detects object info like corresponding tab,class,acl
1035 * e.g. [0] = tabsPartition
1036 * [1] = faiPartitionTable
1037 * [2] = FAIPARTITIONTABS
1038 */
1039 function get_type($array)
1040 {
1041 if(!isset($array['objectClass'])) return(array());
1042 if(in_array("FAIpartitionTable",$array['objectClass'])){
1043 return(array("tabsPartition","faiPartitionTable","FAIPARTITIONTABS"));
1044 }
1045 if(in_array("FAIscript",$array['objectClass'])){
1046 return(array("tabsScript","faiScript","FAISCRIPTTABS"));
1047 }
1048 if(in_array("FAItemplate",$array['objectClass'])){
1049 return(array("tabsTemplate","faiTemplate","FAITEMPLATETABS"));
1050 }
1051 if(in_array("FAIhook",$array['objectClass'])){
1052 return(array("tabsHook","faiHook","FAIHOOKTABS"));
1053 }
1054 if(in_array("FAIvariable",$array['objectClass'])){
1055 return(array("tabsVariable","faiVariable","FAIVARIABLETABS"));
1056 }
1057 if(in_array("FAIprofile",$array['objectClass'])){
1058 return(array("tabsProfile","faiProfile","FAIPROFILETABS"));
1059 }
1060 if(in_array("FAIpackageList",$array['objectClass'])){
1061 return(array("tabsPackage","faiPackage","FAIPACKAGETABS"));
1062 }
1063 return(array());
1064 }
1067 /*! \brief Checks if the given string can be used as class name
1068 */
1069 static function check_class_name($oc,$name,$dn)
1070 {
1071 $base = FAI::get_release_dn($dn);
1073 if($oc == "FAIprofile"){
1074 $f = "";
1075 $ocs = array("FAIprofile","FAItemplate","FAIhook","FAIpartitionTable","FAIpackageList","FAIscript","FAIvariable");
1076 foreach($ocs as $oc){
1077 $f .= "(objectClass=".$oc.")";
1078 }
1079 $res = FAI::get_all_objects_for_given_base($base,"(|".$f.")",TRUE);
1080 }else{
1081 $res = FAI::get_all_objects_for_given_base($base,"(objectClass=".$oc.")",TRUE);
1082 }
1083 $delete = array();
1084 $used = array();
1085 foreach($res as $object){
1086 $used[$object['cn'][0]]= $object['cn'][0];
1087 }
1088 return($used);
1089 }
1092 /*! \brief Checks if the given string can be used for a new release
1093 */
1094 function CheckNewBranchName($name,$base)
1095 {
1096 $f = $this->fai_release;
1097 if($name == ""){
1098 return(false);
1099 }elseif(in_array($name,$this->getBranches($f))) {
1100 return(false);
1101 }elseif(tests::is_department_name_reserved($name,$base)){
1102 return(false);
1103 }
1104 return(true);
1105 }
1108 /*! \brief This filter is used to display small icons for each listed object
1109 * instead of their typ names
1110 */
1111 static function filterProperties($row, $classes)
1112 {
1113 $objects = array(
1114 "FAIpartitionTable" => array("IMG"=> "plugins/fai/images/fai_partitionTable.png",
1115 "NAME"=>_("Partition table"),"KZL"=> "PT", "VAR"=>"ShowPartitions"),
1116 "FAIpackageList" => array("IMG"=> "plugins/fai/images/fai_packages.png",
1117 "NAME"=>_("Package list") , "KZL"=> "PL", "VAR"=>"ShowPackages"),
1118 "FAIscript" => array("IMG"=> "plugins/fai/images/fai_script.png",
1119 "NAME"=>_("Scripts") , "KZL"=> "S", "VAR"=>"ShowScripts"),
1120 "FAIvariable" => array("IMG"=> "plugins/fai/images/fai_variable.png",
1121 "NAME"=>_("Variables") , "KZL"=> "V", "VAR"=>"ShowVariables"),
1122 "FAIhook" => array("IMG"=> "plugins/fai/images/fai_hook.png",
1123 "NAME"=>_("Hooks"), "KZL"=> "H", "VAR"=>"ShowHooks"),
1124 "FAIprofile" => array("IMG"=> "plugins/fai/images/fai_profile.png",
1125 "NAME"=>_("Profile") , "KZL"=> "P", "VAR"=>"ShowProfiles"),
1126 "FAItemplate" => array("IMG"=> "plugins/fai/images/fai_template.png",
1127 "NAME"=>_("Templates") , "KZL"=> "T", "VAR"=>"ShowTemplates"),
1128 "opsi_netboot" => array("IMG"=> "plugins/opsi/images/netboot_package.png",
1129 "NAME"=>_("OPSI net boot product") , "KZL"=> "ON", "VAR"=>"ShowOpsiNetboot"),
1130 "opsi_local" => array("IMG"=> "plugins/opsi/images/local_package.png",
1131 "NAME"=>_("OPSI local boot product") , "KZL"=> "OL", "VAR"=>"ShowOpsiLocal"));
1133 $icon_list = "";
1134 foreach($objects as $type => $type_data){
1135 if(in_array($type, $classes)){
1136 $icon_list .= image($type_data['IMG'],'edit_'.$row.'_'.$type,$type_data['NAME']);
1137 }else{
1138 $icon_list .= image('images/empty.png');
1139 }
1140 }
1142 return $icon_list;
1143 }
1146 /*! \brief Overridden render method of class mangement.
1147 * this allows us to add a release selection box.
1148 */
1149 function renderList()
1150 {
1151 $filter = $this->getFilter();
1152 $headpage = $this->getHeadpage();
1153 $this->releaseSelector->update();
1154 $this->fai_release = $this->releaseSelector->getBase();
1155 $headpage->setBase($this->fai_release);
1156 $headpage->update();
1157 $smarty = get_smarty();
1158 $r = $this->config->get_cfg_value("faiManagement", "postremove");
1159 $c = $this->config->get_cfg_value("faiManagement", "postcreate");
1160 $smarty->assign("allow_create", $c);
1161 $smarty->assign("allow_remove", $r);
1162 $smarty->assign("RELEASE", $this->releaseSelector->render());
1163 $display = $headpage->render();
1164 return($this->getHeader().$display);
1165 }
1168 /*! \brief Convert POST and GET variables into actions.
1169 */
1170 function detectPostActions()
1171 {
1172 $action = management::detectPostActions();
1173 if(isset($_POST['remove_multiple'])) $action['action'] = "remove";
1174 if(isset($_POST['new_profile'])) $action['action'] = "new_profile";
1175 if(isset($_POST['new_template'])) $action['action'] = "new_template";
1176 if(isset($_POST['new_script'])) $action['action'] = "new_script";
1177 if(isset($_POST['new_hook'])) $action['action'] = "new_hook";
1178 if(isset($_POST['new_variable'])) $action['action'] = "new_variable";
1179 if(isset($_POST['new_package'])) $action['action'] = "new_package";
1180 if(isset($_POST['new_partition'])) $action['action'] = "new_partition";
1182 if(isset($_POST['save_properties'])) $action['action'] = "saveOpsiProperties";
1183 if(isset($_POST['cancel_properties'])) $action['action'] = "cancel";
1185 if(isset($_POST['edit_continue'])) $action['action'] = "newClassNameSelected";
1186 if(isset($_POST['edit_cancel'])) $action['action'] = "cancel";
1188 if(isset($_POST['faiGroupHandle_cancel'])) $action['action'] = "cancel";
1189 if(isset($_POST['CancelBranchName'])) $action['action'] = "cancel";
1190 if(isset($_POST['delete_branch_confirm'])) $action['action'] = "removeBranchConfirmed";
1191 if(isset($_GET['PerformBranch'])) $action['action'] = "PerformBranch";
1192 if(isset($_POST['UseBranchName'])) $action['action'] = "saveBranch";
1193 if(isset($_POST['faiGroupHandle_apply'])) $action['action'] = "editByGroup";
1194 if(isset($_GET['act']) && $_GET['act'] == "branch_branch") $action['action'] = "createBranch";
1195 if(isset($_GET['act']) && $_GET['act'] == "freeze_branch") $action['action'] = "createFreeze";
1196 if(isset($_GET['act']) && $_GET['act'] == "remove_branch") $action['action'] = "removeBranch";
1198 foreach($_POST as $name => $value){
1199 if(preg_match("/^edit_([0-9]*)_([a-z_]*)/i", $name)){
1200 $id = preg_replace("/^edit_([0-9]*)_([a-z_]*)/i","\\1", $name);
1201 $tab = preg_replace("/^edit_([0-9]*)_([a-z_]*)/i","\\2", $name);
1203 $headpage = $this->getHeadpage();
1204 $entry = $headpage->entries[$id];
1206 if(in_array('FAKE_OC_FAI', $entry['objectClass'])){
1207 unset($_POST[$name]);
1208 if(isset($headpage->entries[$id]['GROUPS'][$tab])){
1209 $data =$headpage->entries[$id]['GROUPS'][$tab];
1210 $type = $this->get_type($data);
1211 $str = management::editEntry('editEntry',array($data['dn']),array(),$type[0],$type[2],"fai");
1212 if($str) return($str);
1213 }
1214 }else{
1215 $str = $this->editEntry('editEntry',array($entry['dn']));
1216 if($str) return($str);
1217 }
1218 break;
1219 }
1220 }
1221 return($action);
1222 }
1225 static function plInfo()
1226 {
1227 return (array(
1228 "plShortName" => _("FAI releases"),
1229 "plDescription" => _("FAI release management"),
1230 "plSelfModify" => FALSE,
1231 "plDepends" => array(),
1232 "plPriority" => 0,
1233 "plSection" => array("administration"),
1234 "plRequirements"=> array(
1235 'onFailureDisablePlugin' => array(
1236 'faiDiskEntry',
1237 'faiHookEntry',
1238 'faiHook',
1239 'faiManagement',
1240 'faiPackageConfiguration',
1241 'faiPackage',
1242 'faiPartition',
1243 'faiPartitionTableEntry',
1244 'faiPartitionTable',
1245 'faiProfile',
1246 'faiScriptEntry',
1247 'faiScript',
1248 'faiSummaryTab',
1249 'faiTemplateEdit',
1250 'faiTemplateEntry',
1251 'faiTemplate',
1252 'faiVariableEntry',
1253 'faiVariable',
1254 'servrepository'
1255 ),
1256 'ldapSchema' => array(
1257 'FAIclass' => '>=2.7',
1258 'FAIbranch' => '>=2.7',
1259 'FAIdebconfInfo' => '>=2.7',
1260 'FAIobject' => '>=2.7',
1261 'FAIpackageList' => '>=2.7',
1262 'FAItemplate' => '>=2.7',
1263 'FAIscript' => '>=2.7',
1264 'FAIvariable' => '>=2.7',
1265 'FAIhook' => '>=2.7',
1266 'FAItemplateEntry' => '>=2.7',
1267 'FAIscriptEntry' => '>=2.7',
1268 'FAIvariableEntry' => '>=2.7',
1269 'FAIhookEntry' => '>=2.7',
1270 'FAIpartitionTable' => '>=2.7',
1271 'FAIpartitionDisk' => '>=2.7',
1272 'FAIpartitionEntry' => '>=2.7',
1273 'FAIprofile' => '>=2.7',
1274 'FAIpartitionEntry' => '>=2.7',
1275 'FAIrepository' => '>=2.7',
1276 'FAIrepositoryServer' => '>=2.7'
1277 )
1278 ),
1279 "plProperties" =>
1280 array(
1281 array(
1282 "name" => "faiBaseRDN",
1283 "type" => "rdn",
1284 "default" => "ou=fai,ou=configs,ou=systems,",
1285 "description" => _("RDN for FAI storage."),
1286 "check" => "gosaProperty::isRdn",
1287 "migrate" => "migrate_faiBaseRDN",
1288 "group" => "plugin",
1289 "mandatory" => TRUE
1290 ),
1291 array(
1292 "name" => "defaultFaiRelease",
1293 "type" => "dn",
1294 "default" => "",
1295 "description" => _("Name of the FAI default release."),
1296 "check" => "gosaProperty::isDn",
1297 "migrate" => "",
1298 "group" => "fai",
1299 "mandatory" => FALSE
1300 )
1301 ),
1303 "plCategory" => array("fai"=> array("description" => _("FAI"),"objectClass" => "FAIclass")),
1304 "plProvidedAcls"=> array()));
1305 }
1306 }
1307 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1308 ?>