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");
8 var $objectclasses = array("top","FAIclass","FAIpartitionTable");
10 /* Specific attributes */
11 var $cn = ""; // The class name for this object
12 var $description = ""; // The description for this set of partitions
13 var $disks = array(); // All defined Disks
14 var $is_dialog = false; // specifies which buttons will be shown to save or abort
15 var $dialog = NULL; // a dialog, e.g. new disk dialog
17 var $FAIstate = "";
18 var $base = "";
19 var $release = "";
20 var $copy_paste_mode = false;
21 var $cut_paste_mode = false;
23 var $CopyPasteVars = array("disks");
25 function faiPartitionTable ($config, $dn= NULL)
26 {
27 /* Load Attributes */
28 plugin::plugin ($config, $dn);
30 $this->acl ="#all#";
32 /* If "dn==new" we try to create a new entry
33 * Else we must read all objects from ldap which belong to this entry.
34 * First read disks from ldap ... and then the partition definitions for the disks.
35 */
36 if($dn != "new"){
37 $this->dn =$dn;
39 /* Set acls
40 */
41 $ui = get_userinfo();
42 $acl = get_permissions ($this->dn, $ui->subtreeACL);
43 $acli = get_module_permission($acl, "FAIclass", $this->dn);
44 $this->acl=$acli;
46 /* Get FAIstate
47 */
48 if(isset($this->attrs['FAIstate'][0])){
49 $this->FAIstate = $this->attrs['FAIstate'][0];
50 }
52 /* Read all disks from ldap taht are defined fot this partition table
53 */
54 $ldap = $this->config->get_ldap_link();
55 $ldap->cd ($this->dn);
56 $ldap->search("(&(objectClass=FAIclass)(objectClass=FAIpartitionDisk))",array("*"));
57 while($object = $ldap->fetch()){
58 $this->disks[$object['cn'][0]]['status'] = "edited";
59 $this->disks[$object['cn'][0]]['dn'] = $object['dn'];
60 $this->disks[$object['cn'][0]]['cn'] = $object['cn'][0];
61 if(isset($object['description'][0])){
62 $this->disks[$object['cn'][0]]['description'] = $object['description'][0];
63 }else{
64 $this->disks[$object['cn'][0]]['description'] = "";
65 }
66 $this->disks[$object['cn'][0]]['partitions'] = array();
67 }
69 /* read all partitions for each disk
70 */
71 foreach($this->disks as $name => $disk){
72 $ldap->cd ($disk['dn']);
73 $ldap->search("(&(objectClass=FAIclass)(objectClass=FAIpartitionEntry))",array("*"));
74 while($partition = $ldap->fetch()){
76 /* remove count ... from ldap result
77 */
78 foreach($partition as $key=>$val){
79 if((is_numeric($key))||($key=="count")||($key=="dn")){
80 unset($partition[$key]);
81 }else{
82 $partition[$key] = $val[0];
83 }
84 }
86 /* Append fetched partitions
87 */
88 $partition['status']="edited";
89 $this->disks[$name]['partitions'][$partition['FAIpartitionNr']] = $partition;
90 }
91 ksort($this->disks[$name]['partitions']);
92 }
93 }
94 ksort($this->disks);
95 }
97 function execute()
98 {
99 /* Call parent execute */
100 plugin::execute();
102 /* Fill templating stuff */
103 $smarty= get_smarty();
104 $display= "";
106 /* Add Disk to this Partitionset
107 * This code adds a new HDD to the disks
108 * A new Dialog will be opened
109 */
110 if(isset($_POST['AddDisk'])){
111 $usedDiskNames =array();
112 foreach($this->disks as $key=>$disk){
113 $usedDiskNames[]= $key;
114 }
115 $this->dialog = new faiPartitionTableEntry($this->config,$this->dn,$usedDiskNames);
116 $this->dialog->acl = $this->acl;
117 $this->dialog->FAIstate = $this->FAIstate;
118 $this->is_dialog = true;
119 }
121 /* Edit disk.
122 * Open dialog which allows us to edit the selected entry
123 */
125 if($this->dn != "new"){
126 $_SESSION['objectinfo']= $this->dn;
127 }
129 if((isset($_POST['EditDisk']))&&(isset($_POST['disks']))){
130 $usedDiskNames =array();
132 $Udisk = $_POST['disks'][0];
134 foreach($this->disks as $key=>$disk){
135 if($key != $Udisk){
136 $usedDiskNames[]= $key;
137 }
138 }
139 $this->dialog = new faiPartitionTableEntry($this->config,$this->dn,$usedDiskNames,$this->disks[$Udisk]);
140 $this->dialog->acl = $this->acl;
141 $this->dialog->FAIstate = $this->FAIstate;
143 /* Set object info string, which will be displayed in plugin info line */
144 if(isset($this->disks[$Udisk]['dn'])){
145 $_SESSION['objectinfo'] = $this->disks[$Udisk]['dn'];
146 }else{
147 $_SESSION['objectinfo'] = "";
148 }
150 $this->is_dialog = true;
151 }
153 /* Edit aborted, close dialog, without saving anything
154 */
155 if(isset($_POST['CancelDisk'])){
156 unset($this->dialog);
157 $this->dialog = NULL;
158 $this->is_dialog=false;
159 }
161 /* Dialog saved
162 * Save given data from Dialog, if no error is occured
163 */
164 if(isset($_POST['SaveDisk'])){
166 if($this->FAIstate != "freeze"){
167 $this->dialog->save_object();
168 if(count($this->dialog->check())){
169 foreach($this->dialog->check() as $msg){
170 print_red($msg);
171 }
172 }else{
173 $disk = $this->dialog->save();
174 if(isset($disk['rename'])){
175 if($this->disks[$disk['rename']['from']]['status']=="edited"){
176 $this->disks[$disk['rename']['from']]['status']="delete";
177 }else{
178 unset($this->disks[$disk['rename']['from']]);
179 }
181 foreach($disk['partitions'] as $key => $val){
182 if($disk['partitions'][$key]['status']!="delete"){
183 $disk['partitions'][$key]['status']= "new";
184 }
185 }
187 $disk['status']="new";
188 $disk['cn']= $disk['rename']['to'];
189 }
191 $this->disks[$disk['cn']]=$disk;
192 unset($this->dialog);
193 $this->dialog = NULL;
194 $this->is_dialog=false;
195 ksort($this->disks);
196 }
197 }else{
198 $this->dialog = NULL;
199 $this->is_dialog=false;
200 }
201 }
203 /* Delete selected disk drive from list
204 * Assign delete status for all its partitions
205 */
206 if((isset($_POST['DelDisk']))&&(!empty($_POST['disks']))){
207 if($this->FAIstate != "freeze"){
208 foreach($_POST['disks'] as $disk) {
209 if($this->disks[$disk]['status']=="edited"){
210 $this->disks[$disk."-delete"]=$this->disks[$disk];
211 unset($this->disks[$disk]);
212 $disk = $disk."-delete";
213 $this->disks[$disk]['status']="delete";
214 foreach($this->disks[$disk]['partitions'] as $name => $value ){
215 if($value['status']=="edited"){
216 $this->disks[$disk]['partitions'][$name]['status']="delete";
217 }else{
218 unset($this->disks[$disk]['partitions'][$name]);
219 }
220 }
221 }else{
222 unset($this->disks[$disk]);
223 }
224 }
225 }
226 }
228 /* Display dialog if one is defined
229 */
230 if(isset($this->dialog)){
231 $this->dialog->save_object();
232 return($this->dialog->execute());
233 }
235 /* Assign all attributes to smarty engine
236 */
237 foreach($this->attributes as $attrs){
238 $smarty->assign($attrs,$this->$attrs);
239 if($this->$attrs){
240 $smarty->assign($attrs."CHK"," ");
241 }else{
242 $smarty->assign($attrs."CHK"," disabled ");
243 }
244 }
246 foreach($this->attributes as $attr){
247 $smarty->assign($attr."ACL",chkacl($this->acl,$attr));
248 }
250 $disks = $this->getDisks();
251 $smarty->assign("disks" ,$disks);
252 $display.= $smarty->fetch(get_template_path('faiPartitionTable.tpl', TRUE));
253 return($display);
254 }
256 function getDisks(){
257 /* Return all available disks for this partition table
258 * Return in listBox friendly array
259 */
260 $a_return = array();
261 foreach($this->disks as $key => $disk){
262 if($disk['status'] != "delete"){
263 $cnt=0;
264 foreach($disk['partitions'] as $val){
265 if($val['status']!="delete"){
266 $cnt ++;
267 }
268 }
269 if(!empty($disk['description'])){
270 if($cnt == 1){
271 $a_return[$key]= $disk['cn']." [".$disk['description']."], ".sprintf(_("%s partition"), $cnt);
272 }else{
273 $a_return[$key]= $disk['cn']." [".$disk['description']."], ".sprintf(_("%s partition(s)"), $cnt);
274 }
275 }else{
276 if($cnt == 1){
277 $a_return[$key]= $disk['cn'].", ".sprintf(_("%s partition"), $cnt);
278 }else{
279 $a_return[$key]= $disk['cn'].", ".sprintf(_("%s partition(s)"), $cnt);
280 }
281 }
282 }
283 }
284 return($a_return);
285 }
288 /* Delete me, and all my subtrees
289 */
290 function remove_from_parent()
291 {
292 $ldap = $this->config->get_ldap_link();
293 $ldap->cd ($this->dn);
294 $ldap->rmdir_recursive($this->dn);
295 $this->handle_post_events("remove");
297 /* This cannot be removed... */
298 }
301 /* Save data to object
302 */
303 function save_object()
304 {
305 if($this->FAIstate == "freeze") return;
306 plugin::save_object();
307 foreach($this->attributes as $attrs){
308 if(isset($_POST[$attrs])){
309 $this->$attrs = $_POST[$attrs];
310 }
311 }
312 }
315 /* Check supplied data */
316 function check()
317 {
318 /* Call common method to give check the hook */
319 $message= plugin::check();
321 /* If this is a new script, check if a script with this name already exists */
322 if(!empty($this->release) && ($this->copy_paste_mode || $this->cut_paste_mode) ){
324 /* Check if current name is already used for fai scripts in selected release */
325 $dn = 'cn='.$this->cn.",ou=disk,".$this->release;
326 $ldap = $this->config->get_ldap_link();
327 $ldap->cat($dn);
328 if($ldap->count()){
330 $r =convert_department_dn($this->release);;
331 $message[] = sprintf(_("Can't insert a new fai partition table named '%s' in '%s' there is already one defined with the given name."),$this->cn,$r);
332 }
333 }
334 return ($message);
335 }
338 /* Save to LDAP */
339 function save()
340 {
342 plugin::save();
343 /* Save current settings.
344 * 1 : We must save the partition table, with its description and cn
345 * 2 : Append Disk with cn and description.
346 * 3 : Save partitions for each disk
347 */
349 /* Copy & Paste : Ensure that FAIstate is copied too */
350 if($this->copy_paste_mode && preg_match("/freeze/",$this->FAIstate)){
351 $this->attrs['FAIstate'] = $this->FAIstate;
352 }
354 $ldap = $this->config->get_ldap_link();
356 if($this->new){
357 $ldap->cd($this->config->current['BASE']);
358 $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $this->dn));
359 $ldap->cd($this->dn);
360 $ldap->add($this->attrs);
361 }else{
362 /* Add partition table to ldap
363 */
364 $ldap->cd($this->dn);
365 $this->cleanup();
366 $ldap->modify ($this->attrs);
367 }
368 show_ldap_error($ldap->get_error(), _("Saving FAI partition table base failed"));
370 /* Do object tagging */
371 $this->handle_object_tagging();
373 /* Sort entries, because we must delete entries with status="delete" first */
374 $order = array();
375 foreach($this->disks as $key => $disk){
376 if($disk['status'] == "delete"){
377 $order[$key] = $disk;
378 }
379 }
380 foreach($this->disks as $key => $disk){
381 if($disk['status'] != "delete"){
382 $order[$key] = $disk;
383 }
384 }
386 /* Append all disks to ldap */
387 foreach($order as $cn=>$disk){
388 $disk_dn = "cn=".$disk['cn'].",".$this->dn;
389 $disk_attrs['cn'] = $disk['cn'];
390 $disk_attrs['description'] = $disk['description'];
391 $disk_attrs['objectClass'] = array("top","FAIclass","FAIpartitionDisk");
393 /* We currently use the copy & paste method */
394 if($this->copy_paste_mode){
395 $disk['status'] = "new";
396 }
398 if($disk['status']=="new"){
399 $ldap->cat($disk_dn,array("objectClass"));
400 if($ldap->count()){
401 $disk['status']="edited";
402 }
403 }
405 /* Fix problem with missing objectClass "gosaAdministrativeUnitTag" for disks */
406 $ldap->cat($disk_dn,array("objectClass"));
407 $attrs = $ldap->fetch();
408 if(isset($attrs['objectClass']) && in_array_ics("gosaAdministrativeUnitTag",$attrs['objectClass'])){
409 $disk_attrs['objectClass'][] = "gosaAdministrativeUnitTag";
410 }
412 if($disk['status'] == "delete"){
413 $ldap->cd($disk_dn);
414 $ldap->rmdir_recursive($disk_dn);
415 show_ldap_error($ldap->get_error(), _("Removing FAI partition table failed"));
416 }elseif($disk['status']== "edited"){
417 if(empty($disk_attrs['description'])){
418 $disk_attrs['description']=array();
419 }
420 $ldap->cd($disk_dn);
421 $this->cleanup();
422 $ldap->modify ($disk_attrs);
423 show_ldap_error($ldap->get_error(), _("Saving FAI partition table failed"));
424 }elseif($disk['status']== "new"){
425 if(empty($disk_attrs['description'])){
426 unset($disk_attrs['description']);
427 }
428 $ldap->cd($this->config->current['BASE']);
429 $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $disk_dn));
430 $ldap->cd($disk_dn);
431 $ldap->add($disk_attrs);
432 show_ldap_error($ldap->get_error(), _("Saving FAI partition table failed"));
433 }else{
434 print_red("unknown status while saving disks");
435 }
437 $this->handle_object_tagging($disk_dn, $this->gosaUnitTag);
439 /* Collect all opperations. Delete first than add new entries .*/
440 $Todo['delete'] = array();
441 $Todo['rest'] = array();
443 /* Skip partition handling if current disk is marked as deleted */
444 if($disk['status']!="delete"){
446 /* Add all partitions */
447 foreach($disk['partitions'] as $part_nr => $partition){
449 /* Create attribute array */
450 $partition_attrs = array();
451 foreach($partition as $key => $value){
452 if(!empty($value)){
453 $partition_attrs[$key]=$value;
454 }else{
455 unset($partition_attrs[$key]);
456 }
457 }
459 /* Create partition dn and add necessary attributes */
460 $partition_attrs['FAIpartitionNr']= $part_nr;
461 $partition_dn= "FAIpartitionNr=".$partition_attrs['FAIpartitionNr'].",".$disk_dn;
462 $partition_attrs['objectClass']= array("top","FAIclass","FAIpartitionEntry");
463 $partition_attrs['cn']= $partition_attrs['FAIpartitionNr'];
465 /* Unset status attributes */
466 unset($partition_attrs['status']);
467 unset($partition_attrs['old_cn']);
469 /* We currently use the copy & paste method */
470 if($this->copy_paste_mode){
471 $partition['status']="new";
472 }
474 /* Check if this partition is realy new .. */
475 if($partition['status']=="new"){
476 $ldap->cat($partition_dn,array("objectClass"));
477 if($ldap->count()){
478 $partition['status']="edited";
479 }
480 }
482 /* Set mount point top swap if it is emtpy */
483 if((!isset($partition['FAImountPoint']))||(empty($partition['FAImountPoint']))){
484 $partition_attrs['FAImountPoint']="swap";
485 }
487 /* Collect all operations */
488 if(($partition['status'] == "delete")&&($disk['status']!="new")){
490 $partition_dn_del = "FAIpartitionNr=".$partition['FAIpartitionNr'].",".$disk_dn;
492 $Todo['delete'][$partition_dn_del] = $partition_attrs;
493 }elseif($partition['status'] == "new"){
494 $Todo['rest'][$partition_dn] = $partition_attrs;
495 }elseif($partition['status'] == "edited"){
496 $Todo['rest'][$partition_dn] = $partition_attrs;
497 }
498 }
499 }
501 /* First of all, delete old entries */
502 foreach($Todo['delete'] as $partition_dn => $attrs){
503 $ldap->cd($partition_dn);
504 $res = $ldap->rmdir_recursive($partition_dn);
505 show_ldap_error($ldap->get_error(), _("Removing FAI partition table entry failed"));
506 }
508 /* Add/edit entries */
509 foreach($Todo['rest'] as $partition_dn => $partition_attrs){
511 /* Check if entry exists */
512 $ldap->cat($partition_dn);
513 if($ldap->count()){
515 /* Fix problem with missing objectClass "gosaAdministrativeUnitTag" for partitions */
516 $attrs = $ldap->fetch();
517 if(isset($attrs['objectClass']) && in_array_ics("gosaAdministrativeUnitTag",$attrs['objectClass'])){
518 $partition_attrs['objectClass'][] = "gosaAdministrativeUnitTag";
519 }
520 if(empty($partition_attrs['description'])){
521 $partition_attrs['description']=array();
522 }
523 if(empty($partition_attrs['FAIfsOptions'])){
524 $partition_attrs['FAIfsOptions']=array();
525 }
526 if(empty($partition_attrs['FAImountOptions'])){
527 $partition_attrs['FAImountOptions']=array();
528 }
529 if(empty($partition_attrs['FAIpartitionFlags'])){
530 $partition_attrs['FAIpartitionFlags']=array();
531 }
532 $ldap->cd($partition_dn);
533 $this->cleanup();
534 $ldap->modify ($partition_attrs);
535 show_ldap_error($ldap->get_error(), _("Saving FAI partition table entry failed"));
536 }else{
538 if(empty($partition_attrs['description'])){
539 unset($partition_attrs['description']);
540 }
542 $ldap->cd($this->config->current['BASE']);
543 $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $partition_dn));
544 $ldap->cd($partition_dn);
545 if (isset($partition_attrs['gosaUnitTag']) && !in_array_ics("gosaAdministrativeUnitTag",$partition_attrs['objectClass'])){
546 $partition_attrs['objectClass'][]= "gosaAdministrativeUnitTag";
547 }
548 $ldap->add($partition_attrs);
549 show_ldap_error($ldap->get_error(), _("Saving FAI partition table entry failed"));
550 }
551 $this->handle_object_tagging($partition_dn, $this->gosaUnitTag);
552 }
553 }
554 $this->handle_post_events("add");
555 }
558 /* return copy & paste dialog
559 */
560 function getCopyDialog()
561 {
562 /* Ask for cn */
563 $smarty = get_smarty();
564 $smarty->assign("cn" ,$this->cn);
565 $str = $smarty->fetch(get_template_path("paste_fai_object.tpl",TRUE));
566 $ret = array();
567 $ret['string'] = $str;
568 $ret['status'] = "";
569 return($ret);
570 }
572 /* Get posted cn */
573 function saveCopyDialog()
574 {
575 if(isset($_POST['cn'])){
576 $this->cn = $_POST['cn'];
577 }
578 }
579 }
581 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
582 ?>