1 <?php
3 class faiPartitionTable extends plugin
4 {
5 /* attribute list for save action */
6 var $ignore_account = TRUE;
7 var $attributes = array("cn","description", "FAIpartitionMethod");
8 var $objectclasses = array("top","FAIclass","FAIpartitionTable");
10 var $subAttributes = array("cn","description");
11 var $subPartAttributes = array("cn","FAIpartitionNr","FAIpartitionSize","FAImountPoint","FAIfsType","FAIpartitionType","FAImountOptions","FAIfsOptions","FAIpartitionFlags","description");
13 var $sub64coded = array();
14 var $subBinary = array();
16 /* Specific attributes */
17 var $cn = ""; // The class name for this object
18 var $description = ""; // The description for this set of partitions
19 var $FAIpartitionMethod = ""; // "setup-storage" or not assigned
20 var $disks = array(); // All defined Disks
21 var $is_dialog = false; // specifies which buttons will be shown to save or abort
23 var $FAIstate = "";
24 var $ui;
26 var $view_logged = FALSE;
28 function faiPartitionTable (&$config, $dn= NULL)
29 {
30 /* Load Attributes */
31 plugin::plugin ($config, $dn);
33 /* If "dn==new" we try to create a new entry
34 * Else we must read all objects from ldap which belong to this entry.
35 */
36 $this->ui = get_userinfo();
37 if($dn != "new"){
38 $this->dn =$dn;
40 /* Read all leaf objects of this object (For FAIscript this would be FAIscriptEntry)
41 */
42 $res = FAI::get_all_objects_for_given_base($this->dn,"(&(objectClass=FAIclass)(objectClass=FAIpartitionDisk))");
43 foreach($res as $obj){
45 /* Skip not relevant objects */
46 if(!preg_match("/".preg_quote($this->dn, '/')."$/i",$obj['dn'])) continue;
47 $objects = array();
48 $objects['description'] = "";
49 $objects['status'] = "edited";
51 // Transform disk type into image later...
52 if (!isset($obj['FAIdiskType'])){
53 $objects['type'] = "old";
54 } else {
55 $objects['type'] = $obj['FAIdiskType'];
56 }
58 // Transform potential lvm information
59 if (isset($obj['FAIlvmDevice'])){
60 $objects['vg'] = $obj['FAIlvmDevice'];
61 }
63 $objects['dn'] = $obj['dn'];
64 $objects = $this->get_object_attributes($objects,$this->subAttributes);
65 $this->disks[$objects['cn']] = $objects;
66 $this->disks[$objects['cn']]['partitions'] = array();
67 }
69 /* read all partitions for each disk
70 */
71 foreach($this->disks as $name => $disk){
72 $res = FAI::get_all_objects_for_given_base($disk['dn'],"(&(objectClass=FAIclass)(objectClass=FAIpartitionEntry))");
73 foreach($res as $obj){
75 /* Skip not relevant objects */
76 if(!preg_match("/".preg_quote($disk['dn'], '/')."$/i",$obj['dn'])) continue;
78 $objects = array();
79 $objects['status'] = "edited";
80 $objects['dn'] = $obj['dn'];
81 $objects = $this->get_object_attributes($objects,$this->subPartAttributes);
82 unset($objects['dn']);;
83 $this->disks[$name]['partitions'][$objects['FAIpartitionNr']] = $objects;
84 }
85 }
86 }
88 $this->is_new = FALSE;
89 if($this->dn == "new"){
90 $this->is_new =TRUE;
91 }
92 ksort($this->disks);
93 }
96 function acl_base_for_current_object($dn)
97 {
98 if($dn == "new" || $dn == ""){
99 if($this->dn == "new"){
100 $dn= $this->parent->parent->acl_base;
101 }else{
102 $dn = $this->dn;
103 }
104 }
105 return($dn);
106 }
109 function execute()
110 {
111 /* Call parent execute */
112 plugin::execute();
114 if($this->is_account && !$this->view_logged){
115 $this->view_logged = TRUE;
116 new log("view","fai/".get_class($this),$this->dn);
117 }
119 /* Fill templating stuff */
120 $smarty= get_smarty();
121 $display= "";
123 /* Add Disk to this Partitionset
124 * This code adds a new HDD to the disks
125 * A new Dialog will be opened
126 */
127 if(isset($_POST['AddDisk']) && !preg_match("/freeze/i",$this->FAIstate)){
128 $usedDiskNames =array();
129 foreach($this->disks as $key=>$disk){
130 $usedDiskNames[]= $key;
131 }
132 $this->dialog = new faiPartitionTableEntry($this->config,$this->dn,$usedDiskNames);
133 $this->dialog->set_acl_base($this->acl_base_for_current_object($this->dn));
134 $this->dialog->set_acl_category("fai");
135 $this->dialog->FAIstate = $this->FAIstate;
136 $this->is_dialog = true;
137 }
139 /* Edit disk.
140 * Open dialog which allows us to edit the selected entry
141 */
143 if($this->dn != "new"){
144 set_object_info($this->dn);
145 }
147 /* Edit entries via GET */
148 $Udisk = null;
149 if(isset($_GET['act']) && isset($_GET['id'])){
150 if($_GET['act'] == "edit" && isset($this->disks[$_GET['id']])){
151 $Udisk= $_GET['id'];
152 }
153 }
155 /* New Listhandling */
156 foreach($_POST as $name => $value){
157 if(preg_match("/^edit_/",$name)){
158 $entry = preg_replace("/^edit_/","",$name);
159 $Udisk = base64_decode(preg_replace("/_.*/","",$entry));
160 break;
161 }
162 if(preg_match("/^delete_/",$name)){
163 $entry = preg_replace("/^delete_/","",$name);
164 $disk = base64_decode(preg_replace("/_.*/","",$entry));
166 if (!preg_match("/freeze/i", $this->FAIstate)){
167 if(isset($this->disks[$disk])){
169 /* Check for references */
170 $ignore = false;
171 $name = "";
172 foreach($this->disks as $dtest) {
173 // Is raid?
174 $device= null;
175 $name = $dtest['cn'];
177 if ($disk == "raid"){
178 $device = "md";
179 } else {
180 $device = $disk;
182 // Used by raid?
183 if (isset($this->disks[$name]['partitions'])){
184 foreach ($this->disks[$name]['partitions'] as $partition) {
185 if (preg_match("/${disk}\.?[0-9]+/", $partition['FAIpartitionSize'])){
186 $ignore = true;
187 break 2;
188 }
189 }
190 }
191 }
193 // Used by volgroup?
194 if (isset($this->disks[$name]["vg"])){
195 foreach ($this->disks[$name]["vg"] as $vg_element) {
196 if (preg_match("/^${device}\.?[0-9]+$/", $vg_element)){
197 $ignore = true;
198 break 2;
199 }
200 }
201 }
202 }
204 if ($ignore) {
205 msg_dialog::display(_("Error"), sprintf(_("The disk cannot be deleted while it is used in the '%s' disk definition!"), $name), ERROR_DIALOG);
206 } else {
207 if($this->disks[$disk]['status']=="edited"){
208 $this->disks[$disk."-delete"]=$this->disks[$disk];
209 unset($this->disks[$disk]);
210 $disk = $disk."-delete";
211 $this->disks[$disk]['status']="delete";
212 foreach($this->disks[$disk]['partitions'] as $name => $value ){
213 if($value['status']=="edited"){
214 $this->disks[$disk]['partitions'][$name]['status']="delete";
215 }else{
216 unset($this->disks[$disk]['partitions'][$name]);
217 }
218 }
219 }else{
220 unset($this->disks[$disk]);
221 }
222 }
224 }
225 }
226 break;
227 }
228 }
230 if($Udisk){
231 $usedDiskNames =array();
232 if(isset($this->disks[$Udisk])){
234 foreach($this->disks as $key=>$disk){
235 if($key != $Udisk){
236 $usedDiskNames[]= $key;
237 }
238 }
240 /* Set object info string, which will be displayed in plugin info line */
241 if(isset($this->disks[$Udisk]['dn'])){
242 set_object_info($this->disks[$Udisk]['dn']);
243 $dn = $this->disks[$Udisk]['dn'];
244 }else{
245 set_object_info("");
246 $dn = "new";
247 }
249 $this->dialog = new faiPartitionTableEntry($this->config,$this->dn,$usedDiskNames,$this->disks[$Udisk]);
250 $this->dialog->set_acl_base($this->acl_base_for_current_object($dn));
251 $this->dialog->set_acl_category("fai");
252 $this->dialog->FAIstate = $this->FAIstate;
254 $this->is_dialog = true;
255 }
256 }
258 /* Edit aborted, close dialog, without saving anything
259 */
260 if(isset($_POST['CancelDisk'])){
261 unset($this->dialog);
262 $this->dialog = FALSE;
263 $this->is_dialog=false;
264 }
266 /* Dialog saved
267 * Save given data from Dialog, if no error is occurred
268 */
269 if(isset($_POST['SaveDisk'])){
271 if (!preg_match("/freeze/i", $this->FAIstate)){
272 $this->dialog->save_object();
273 if(count($this->dialog->check())){
274 foreach($this->dialog->check() as $msg){
275 msg_dialog::display(_("Error"), $msg, ERROR_DIALOG);
276 }
277 }else{
278 $disk = $this->dialog->save();
279 if(isset($disk['rename'])){
280 if($this->disks[$disk['rename']['from']]['status']=="edited"){
281 $this->disks[$disk['rename']['from']]['status']="delete";
282 }else{
283 unset($this->disks[$disk['rename']['from']]);
284 }
286 foreach($disk['partitions'] as $key => $val){
287 if($disk['partitions'][$key]['status']!="delete"){
288 $disk['partitions'][$key]['status']= "new";
289 }
290 }
292 $disk['status']="new";
293 $disk['cn']= $disk['rename']['to'];
294 }
296 $this->disks[$disk['cn']]=$disk;
297 unset($this->dialog);
298 $this->dialog = FALSE;
299 $this->is_dialog=false;
300 ksort($this->disks);
301 }
302 }else{
303 $this->dialog = FALSE;
304 $this->is_dialog=false;
305 }
306 }
308 /* Display dialog if one is defined
309 */
310 if(is_object($this->dialog)){
311 $this->dialog->save_object();
312 return($this->dialog->execute());
313 }
315 /* Assign all attributes to smarty engine
316 */
317 foreach($this->attributes as $attrs){
318 $smarty->assign($attrs,$this->$attrs);
319 if($this->$attrs){
320 $smarty->assign($attrs."CHK"," ");
321 }else{
322 $smarty->assign($attrs."CHK"," disabled ");
323 }
324 }
326 $dn = $this->acl_base_for_current_object($this->dn);
327 $smarty->assign("sub_object_is_addable",
328 preg_match("/c/",$this->ui->get_permissions($dn,"fai/faiPartitionTableEntry")) &&
329 !preg_match("/freeze/",$this->FAIstate));
330 $smarty->assign("sub_object_is_removeable",
331 preg_match("/d/",$this->ui->get_permissions($dn,"fai/faiPartitionTableEntry")) &&
332 !preg_match("/freeze/",$this->FAIstate));
334 $tmp = $this->plInfo();
335 foreach($tmp['plProvidedAcls'] as $name => $translated){
336 $smarty->assign($name."ACL",$this->getacl($name,preg_match("/freeze/i",$this->FAIstate)));
337 }
339 /* Assign mode */
340 if ($this->FAIpartitionMethod == ""){
341 $smarty->assign("mode", "");
342 $smarty->assign("storage_mode", "disabled");
343 } else {
344 $smarty->assign("mode", "checked");
345 $smarty->assign("storage_mode", "");
346 }
347 if (!count($this->disks)) {
348 $smarty->assign("lockmode", "");
349 } else {
350 $smarty->assign("lockmode", "disabled");
351 }
352 if (isset($this->disks['raid'])){
353 $smarty->assign("addraid", "disabled");
354 } else {
355 $smarty->assign("addraid", "");
356 }
358 /* Divlist containing disks */
359 $divlist = new divSelectBox("FAItemplates");
360 $divlist->setHeight(400);
361 foreach($this->disks as $key => $disk){
362 $act = "";
364 $dn = "new";
365 if(isset($obj['dn'])){
366 $dn = $obj['dn'];
367 }
368 $dn = $this->acl_base_for_current_object($dn);
369 $acl = $this->ui->get_permissions($dn,"fai/faiPartitionTableEntry");
370 if(preg_match("/(r|w)/",$acl)) {
371 if($disk['status'] != "delete"){
373 $act .= "<input type='image' src='images/lists/edit.png' name='edit_%s' title='"._("edit")."' alt='"._("edit")."'>";
374 if(preg_match("/d/",$acl)){
375 $act .="<input type='image' src='images/lists/trash.png' name='delete_%s' title='"._("delete")."' alt='"._("delete")."'>";
376 }
378 $cnt=0;
379 foreach($disk['partitions'] as $val){
380 if($val['status']!="delete"){
381 $cnt ++;
382 }
383 }
385 $edit_link = "<a href='?plug=".$_GET['plug']."&act=edit&id=".$key."'>".$key."</a>";
386 $types= array("old" => "plugins/fai/images/fai_partitionTable.png", "disk" => "plugins/fai/images/fai_partitionTable.png",
387 "raid" => "plugins/fai/images/raid.png", "lvm" => "plugins/ogroups/images/list_ogroup.png");
388 $type = isset($disk['type'])?$types[$disk['type']]:$types['old'];
389 $divlist->AddEntry(array(
390 array("string"=> "<img border='0' src='".$type."'>", "attach"=>"style='width:16px'"),
391 array("string"=> $edit_link, "attach"=>"style='width:100px'"),
392 array("string"=> $disk['description']),
393 array("string"=> $cnt, "attach"=>"style='width:16px'"),
394 array("string"=>str_replace("%s",base64_encode($key),$act),
395 "attach"=>"style='border-right: 0px;width:50px;text-align:right;'")));
396 }
397 }
398 }
399 $smarty->assign("Entry_divlist",$divlist->DrawList());
401 $display.= $smarty->fetch(get_template_path('faiPartitionTable.tpl', TRUE));
402 return($display);
403 }
407 /* Delete me, and all my subtrees
408 */
409 function remove_from_parent()
410 {
411 $ldap = $this->config->get_ldap_link();
412 $ldap->cd ($this->dn);
414 $release = $this->parent->parent->fai_release;
415 $use_dn = preg_replace("/".preg_quote(FAI::get_release_dn($this->dn), '/')."/i", $release, $this->dn);
417 FAI::prepare_to_save_FAI_object($use_dn,array(),true);
418 new log("remove","fai/".get_class($this),$use_dn,$this->attributes);
419 foreach($this->disks as $disk){
420 $disk_dn = "cn=".$disk['cn'].",".$this->dn;
421 $use_dn = preg_replace("/".preg_quote(FAI::get_release_dn($this->dn), '/')."/i",$release, $disk_dn);
422 FAI::prepare_to_save_FAI_object($use_dn,array(),true);
423 foreach($disk['partitions'] as $key => $partition){
424 $partition_dn= "FAIpartitionNr=".$partition['FAIpartitionNr'].",".$disk_dn;
425 $use_dn = preg_replace("/".preg_quote(FAI::get_release_dn($this->dn), '/')."/i", $release, $partition_dn);
426 FAI::prepare_to_save_FAI_object($use_dn,array(),true);
427 }
428 }
429 }
432 /* Save data to object
433 */
434 function save_object()
435 {
436 if (preg_match("/freeze/", $this->FAIstate)) return;
437 plugin::save_object();
438 foreach($this->attributes as $attrs){
439 if(isset($_POST[$attrs])){
440 $this->$attrs = $_POST[$attrs];
441 }
442 }
443 }
446 /* Check supplied data */
447 function check()
448 {
449 /* Call common method to give check the hook */
450 $message= plugin::check();
452 /* Ensure that we do not overwrite an allready existing entry
453 */
454 if($this->is_new){
455 $release = $this->parent->parent->fai_release;
456 $new_dn= 'cn='.$this->cn.",".get_ou('faiPartitionRDN').get_ou('faiBaseRDN').$release;
457 $res = faiManagement::check_class_name("FAIpartitionTable",$this->cn,$new_dn);
458 if(isset($res[$this->cn])){
459 $message[] = msgPool::duplicated(_("Name"));
460 }
461 }
462 return ($message);
463 }
466 /* Save to LDAP */
467 function save()
468 {
470 plugin::save();
471 /* Save current settings.
472 * 1 : We must save the partition table, with its description and cn
473 * 2 : Append Disk with cn and description.
474 * 3 : Save partitions for each disk
475 */
477 $ldap = $this->config->get_ldap_link();
479 FAI::prepare_to_save_FAI_object($this->dn,$this->attrs);
481 if($this->initially_was_account){
482 new log("modify","fai/".get_class($this),$this->dn,$this->attributes);
483 }else{
484 new log("create","fai/".get_class($this),$this->dn,$this->attributes);
485 }
487 /* Sort entries, because we must delete entries with status="delete" first */
488 $order = array();
489 foreach($this->disks as $key => $disk){
490 if($disk['status'] == "delete"){
491 $order[$key] = $disk;
492 }
493 }
494 foreach($this->disks as $key => $disk){
495 if($disk['status'] != "delete"){
496 $order[$key] = $disk;
497 }
498 }
500 /* Append all disks to ldap */
501 foreach($order as $cn=>$disk){
502 $disk_dn = "cn=".$disk['cn'].",".$this->dn;
503 $disk_attrs['cn'] = $disk['cn'];
504 $disk_attrs['description'] = $disk['description'];
506 if(empty($disk_attrs['description']) && $disk['status'] == "edited"){
507 $disk_attrs['description'] = array();
508 }
510 $disk_attrs['objectClass'] = array("top","FAIclass","FAIpartitionDisk");
512 if($disk['status']=="new"){
513 $ldap->cat($disk_dn,array("objectClass"));
514 if($ldap->count()){
515 $disk['status']="edited";
516 }
517 }
519 /* Tag object */
520 $this->tag_attrs($disk_attrs, $disk_dn, $this->gosaUnitTag);
522 if($disk['status'] == "delete"){
523 FAI::prepare_to_save_FAI_object($disk_dn,array(),true);
524 $this->handle_post_events("remove");
525 }elseif($disk['status'] == "edited"){
526 FAI::prepare_to_save_FAI_object($disk_dn,$disk_attrs);
527 $this->handle_post_events("modify");
528 }elseif($disk['status']=="new"){
529 FAI::prepare_to_save_FAI_object($disk_dn,$disk_attrs);
530 $this->handle_post_events("add");
531 }
533 if($disk['status']!="delete")
534 /* Add all partitions */
535 foreach($disk['partitions'] as $key => $partition){
536 $partition_attrs = array();
538 foreach($partition as $key => $value){
539 if(!empty($value)){
540 $partition_attrs[$key]=$value;
541 }else{
542 unset($partition_attrs[$key]);
543 }
544 }
546 $partition_dn= "FAIpartitionNr=".$partition_attrs['FAIpartitionNr'].",".$disk_dn;
547 $partition_attrs['objectClass']= array("top","FAIclass","FAIpartitionEntry");
548 $partition_attrs['cn']= $partition_attrs['FAIpartitionNr'];
550 unset($partition_attrs['status']);
551 unset($partition_attrs['old_cn']);
553 if($partition['status']=="new"){
554 $ldap->cat($partition_dn,array("objectClass"));
555 if($ldap->count()){
556 $partition['status']="edited";
557 }
558 }
560 if((!isset($partition['FAImountPoint']))||(empty($partition['FAImountPoint']))){
561 $partition_attrs['FAImountPoint']="swap";
562 }
564 /* Tag object */
565 $this->tag_attrs($partition_attrs, $partition_dn, $this->gosaUnitTag);
567 if($partition['status'] == "delete"){
568 FAI::prepare_to_save_FAI_object($partition_dn,array(),true);
569 $this->handle_post_events("remove");
570 }elseif($partition['status'] == "edited"){
571 FAI::prepare_to_save_FAI_object($partition_dn,$partition_attrs);
572 $this->handle_post_events("modify");
573 }elseif($partition['status']=="new"){
574 FAI::prepare_to_save_FAI_object($partition_dn,$partition_attrs);
575 $this->handle_post_events("add");
576 }
577 }
578 }
579 $this->handle_post_events("add");
580 }
583 function PrepareForCopyPaste($source)
584 {
585 plugin::PrepareForCopyPaste($source);
587 /* Read all leaf objects of this object (For FAIscript this would be FAIscriptEntry)
588 */
589 $res = FAI::get_all_objects_for_given_base($source['dn'],"(&(objectClass=FAIclass)(objectClass=FAIpartitionDisk))");
590 foreach($res as $obj){
592 /* Skip not relevant objects */
593 if(!preg_match("/".preg_quote($source['dn'], '/')."$/i",$obj['dn'])) continue;
595 $objects = array();
596 $objects['description'] = "";
597 $objects['status'] = "edited";
598 $objects['dn'] = $obj['dn'];
599 $objects = $this->get_object_attributes($objects,$this->subAttributes);
600 $this->disks[$objects['cn']] = $objects;
601 $this->disks[$objects['cn']]['partitions'] = array();
602 }
604 /* read all partitions for each disk
605 */
606 foreach($this->disks as $name => $disk){
607 $res = FAI::get_all_objects_for_given_base($disk['dn'],"(&(objectClass=FAIclass)(objectClass=FAIpartitionEntry))");
608 foreach($res as $obj){
610 /* Skip not relevant objects */
611 if(!preg_match("/".preg_quote($disk['dn'], '/')."$/i",$obj['dn'])) continue;
613 $objects = array();
614 $objects['status'] = "edited";
615 $objects['dn'] = $obj['dn'];
616 $objects = $this->get_object_attributes($objects,$this->subPartAttributes);
617 unset($objects['dn']);;
618 $this->disks[$name]['partitions'][$objects['FAIpartitionNr']] = $objects;
619 }
620 }
621 ksort($this->disks);
622 }
625 /* Return plugin informations for acl handling */
626 static function plInfo()
627 {
628 return (array(
629 "plShortName" => _("Partition table"),
630 "plDescription" => _("FAI partition table"),
631 "plSelfModify" => FALSE,
632 "plDepends" => array(),
633 "plPriority" => 26,
634 "plSection" => array("administration"),
635 "plCategory" => array("fai"),
636 "plProvidedAcls" => array(
637 "cn" => _("Name")." ("._("Read only").")",
638 "description" => _("Description"))
639 ));
640 }
643 /*! \brief Used for copy & paste.
644 Returns a HTML input mask, which allows to change the cn of this entry.
645 @param Array Array containing current status && a HTML template.
646 */
647 function getCopyDialog()
648 {
649 $vars = array("cn");
650 $smarty = get_smarty();
651 $smarty->assign("cn", htmlentities($this->cn));
652 $str = $smarty->fetch(get_template_path("paste_generic.tpl",TRUE));
653 $ret = array();
654 $ret['string'] = $str;
655 $ret['status'] = "";
656 return($ret);
657 }
660 /*! \brief Used for copy & paste.
661 Some entries must be renamed to avaoid duplicate entries.
662 */
663 function saveCopyDialog()
664 {
665 if(isset($_POST['cn'])){
666 $this->cn = get_post('cn');
667 }
668 }
670 /* Reload some attributes */
671 function get_object_attributes($object,$attributes)
672 {
673 $ldap = $this->config->get_ldap_link();
674 $ldap->cd($this->config->current['BASE']);
675 $ldap->cat($object['dn'],$attributes);
676 $tmp = $ldap->fetch();
678 foreach($attributes as $attrs){
679 if(isset($tmp[$attrs][0])){
680 $var = $tmp[$attrs][0];
682 /* Check if we must decode some attributes */
683 if(in_array_ics($attrs,$this->sub64coded)){
684 $var = base64_decode($var);
685 }
687 /* check if this is a binary entry */
688 if(in_array_ics($attrs,$this->subBinary)){
689 $var = $ldap->get_attribute($object['dn'], $attrs,$r_array=0);
690 }
692 /* Fix slashes */
693 $var = addslashes($var);
694 $object[$attrs] = $var;
695 }
696 }
697 return($object);
698 }
700 }
702 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
703 ?>