1 <?php
3 class InstallRecipe extends plugin
4 {
6 public $rpcErrorMessage = "";
7 public $deviceUUID = "";
9 // Template options
10 public $installTemplate = "";
11 public $installationTemplateNames = array();
12 public $templateToRelease = array();
13 public $installationTemplates = array();
15 // The selected installation release
16 public $installRelease = "";
18 // Selected config management variant
19 public $installConfigManagement = '';
20 public $installConfigManagementList = array();
22 // Bootstrap method
23 public $installBootstrapMethod = '';
24 public $installBootstrapMethodList = array();
26 // Timezone settings
27 public $installTimezone = "";
28 public $installTimeUTC = "";
30 // Kernel packages
31 public $installKernelPackage = "";
32 public $installKernelPackageList = array();
34 // System Locale
35 public $installSystemLocale = "";
36 public $installSystemLocaleList = array();
38 // Selected NTP Server
39 public $installNTPServer = array();
40 public $installNTPServerList = NULL;
42 // Root password
43 public $installRootEnabled = "";
44 public $installRootPasswordHash = "";
45 public $setPasswordHash = FALSE;
47 // Partition table variables
48 public $installPartitionTable = "";
49 private $partitionEdit = NULL;
51 // Keyboard-layout attribute
52 public $installKeyboardlayout = "";
53 public $installKeyboardlayoutList = array();
55 // Mirror related attribute
56 public $installMirror = "";
57 public $installMirrorList = array();
59 public $objectclasses = array();
60 public $attributes = array("installRelease", "installTemplate","installKeyboardlayout","installSystemLocale",
61 "installTimezone","installTimeUTC","installNTPServer","installMirror",
62 "installRootEnabled","installRootPasswordHash","installKernelPackage",
63 "installPartitionTable","installConfigManagement","installBootstrapMethod");
66 /* Some plugin management related attributes
67 * See class plugin for details.
68 */
69 public $view_logged = FALSE;
70 public $ignore_account = FALSE;
71 public $parent = NULL;
73 /*! \brief Initialize the plugin and its widgets.
74 * Finally call init() to load values from the backend.
75 */
76 function __construct(&$config, $dn, $parent)
77 {
78 plugin::plugin($config, $dn);
80 $this->is_account = $this->initially_was_account = FALSE;
82 $this->_device = &$parent;
83 $this->deviceUUID = $parent->deviceUUID;
85 // Set default password hash
86 $this->hash = $this->config->get_cfg_value("core","passwordDefaultHash");
88 // Get list of password hashes
89 $tmp = passwordMethod::get_available_methods();
90 $this->hashes = array();
91 foreach($tmp['name'] as $name){
92 $this->hashes[$name] = $name;
93 }
95 // Initialize plugin
96 $this->init_static_info();
97 $this->init($initially = TRUE);
98 }
100 function init($initially = FALSE)
101 {
102 // Init the object values.
103 $this->init_client_info();
105 // Prepare NTP servers list
106 $this->installNTPServerList= new sortableListing($this->installNTPServer);
107 $this->installNTPServerList->setDeleteable(true);
108 $this->installNTPServerList->setEditable(false);
109 $this->installNTPServerList->setColspecs(array('*'));
110 $this->installNTPServerList->setWidth("100%");
111 $this->installNTPServerList->setHeight("70px");
113 // Preset values for new devices
114 if(!$this->is_account){
115 $this->installTemplate = key($this->installationTemplates);
116 $this->installRelease = key($this->templateToRelease[$this->installTemplate]);
117 }else{
119 if(!isset($this->installationTemplates[$this->installTemplate])){
121 // The selected template is no longer available, select the next selectable template.
122 $new = key($this->installationTemplates);
124 if($initially){
125 $message = sprintf(_("The selected template '%s' is no longer available. Selecting '%s' as replacement!"),
126 $this->installTemplate, $new);
127 msg_dialog::display(_("Warning"), $message, WARNING_DIALOG);
128 }
129 $this->installTemplate = $new;
130 $installRelease = key($this->templateToRelease[$this->installTemplate]);
132 }elseif(!isset($this->installationTemplates[$this->installTemplate]['method'])){
134 // Not necessary to warn the user here, the input fields will be empty and thus
135 // avoid saving.
137 }elseif(!in_array($this->installRelease, $this->templateToRelease[$this->installTemplate])){
139 // The selected release is no longer available for the current template
140 // Warn the user and select the next selectable release.
141 $new = key($this->templateToRelease[$this->installTemplate]);
142 if($initially){
143 $message = sprintf(_("The selected release '%s' is no longer available. Selecting '%s' as replacement!"),
144 $this->installRelease, $new);
145 }
146 $this->installRelease = $new;
147 msg_dialog::display(_("Warning"), $message, WARNING_DIALOG);
148 }
149 }
152 // Update selectable items like kernels and mirrors depending on the current setup (relase)
153 $this->installBootstrapMethod = $this->installationTemplates[$this->installTemplate]['method'];
154 $this->reloadInstallationKernelPackages($initially);
155 $this->reloadInstallationMirrors($initially);
157 // Preset the config management method.
158 if(!isset($this->installConfigManagementList[$this->installBootstrapMethod][$this->installConfigManagement])){
159 if(isset($this->installConfigManagementList[$this->installBootstrapMethod]) &&
160 count($this->installConfigManagementList[$this->installBootstrapMethod])){
161 $this->installConfigManagement = key($this->installConfigManagementList[$this->installBootstrapMethod]);
162 }
163 }
164 }
167 /*! \brief Loads client-information values from the GOsa-backend using jsonRPC
168 */
169 function init_client_info()
170 {
171 if(empty($this->deviceUUID)){
172 return;
173 }
175 // Load base install Method
176 $rpc = $this->config->getRpcHandle();
177 $res = $rpc->systemGetBaseInstallParameters($this->deviceUUID);
179 // Failed to load backend values, keep reported error and return with FALSE;
180 $this->rpcError = !$rpc->success();
181 if(!$rpc->success()){
182 $this->rpcErrorMessage = $rpc->get_error();
183 msg_dialog::display(_("Error"), msgPool::rpcError($this->rpcErrorMessage), ERROR_DIALOG);
184 return(NULL);
185 }
187 // Apply received options
188 $this->is_account = $res == True;
189 if($this->is_account){
191 $map = array(
192 'ntp-servers' => "installNTPServer",
193 'template' => "installTemplate",
194 'keyboard-layout' => "installKeyboardlayout");
196 // We receive an array for these attributes, but require a string instead
197 // we just use the first element of the array.
198 $mapArray = array(
199 'release' => "installRelease",
200 'timezone' => "installTimezone",
201 'utc' => "installTimeUTC",
202 'kernel' => "installKernelPackage",
203 'system-locale' => "installSystemLocale",
204 'root-user' => "installRootEnabled",
205 'root-hash' => "installRootPasswordHash",
206 'disk-setup' => "installPartitionTable");
208 foreach($res as $name => $data){
209 if(isset($map[$name])){
210 $target = $map[$name];
211 $value = $res[$name];
212 }elseif(isset($mapArray[$name])){
213 $target = $mapArray[$name];
214 $value = $res[$name][0];
215 }
216 $this->$target = $value;
217 }
219 // Convert Bool values to Bool.
220 $boolean = array("installRootEnabled", "installTimeUTC");
221 foreach($boolean as $attr){
222 $this->$attr = ($this->$attr != FALSE && !preg_match("/false/i", $this->$attr));
223 }
224 }
226 return;
227 }
230 function init_static_info()
231 {
232 // Load static values.
233 foreach(array(
234 "timeozones" => "getTimezones",
235 "distributions" => "loadDistributions",
236 "keyboardLayouts" => "loadInstallationKeyboardLayouts",
237 "installationTemplates" => "loadInstallationTemplates",
238 "installationMethods" => "loadInstallationMethods",
239 "locales" => "getSystemLocales" ) as $target => $func){
240 $$target = $this->$func();
241 if($$target == NULL){
242 $this->initFailed = TRUE;
243 msg_dialog::display(_("Error"), msgPool::rpcError($this->rpcErrorMessage), ERROR_DIALOG);
244 return;
245 }
246 }
248 // Assign fetchted values
249 $this->timezones = $timeozones;
250 $this->installBootstrapMethodList = $installationMethods['installBootstrapMethodList'];
251 $this->installConfigManagementList = $installationMethods['installConfigManagementList'];
252 $this->installSystemLocaleList = $locales;
253 $this->installKeyboardlayoutList = $keyboardLayouts;
254 $this->distributions = $distributions;
256 # Create template to relase map
257 $this->templateToRelease = array();
259 // Walk through installation templates and use the 'repositories' attribute
260 // to supported releases.
261 foreach($installationTemplates as $name => $tdata){
263 $mName = isset($this->installBootstrapMethodList[$tdata['method']]) ?
264 $this->installBootstrapMethodList[$tdata['method']]: $tdata['method'];
266 $this->installationTemplateNames[$name] = $tdata['description']." (".$mName.")";
267 $this->installationTemplates[$name] = $tdata;
268 $this->templateToRelease[$name] = array();
270 // Check if the 'repository'-category of the template can be found in any
271 // received release list.
272 if(isset($installationMethods[$tdata['method']]['repositories'])){
273 $repos = $installationMethods[$tdata['method']]['repositories'];
274 foreach($distributions as $dist){
275 if(in_array($dist['type']['name'],$repos) && isset($dist['releases'])){
276 foreach($dist['releases'] as $release){
277 $rname = $dist['name'].'/'.$release['name'];
278 $this->templateToRelease[$name][$rname] = $rname;
279 }
280 }
281 }
282 }
283 }
284 }
287 function check()
288 {
289 // Check if the parents deviceUUID has changed
290 if($this->deviceUUID != $this->_device->deviceUUID){
291 $this->deviceUUID = $this->_device->deviceUUID;
292 print "The device uuid has changed.";
293 }
294 }
297 function execute()
298 {
299 // Log account access
300 if($this->is_account && !$this->view_logged){
301 $this->view_logged = TRUE;
302 new log("view","Device/".get_class($this),$this->dn);
303 }
305 /***************
306 Handle account state
307 ***************/
309 // Allow to add or remove the distribution list extension
310 if(isset($_POST['modify_state'])){
311 if($this->is_account && $this->acl_is_removeable()){
312 $this->is_account= FALSE;
313 }elseif(!$this->is_account && $this->acl_is_createable()){
314 $this->is_account= TRUE;
315 }
316 }
318 // Show account status-changer
319 $display = "";
320 if ($this->parent !== NULL){
321 if ($this->is_account){
322 $display= $this->show_disable_header(_("Remove base installation"),
323 msgPool::featuresEnabled(_("Base installation")));
324 } else {
325 $display= $this->show_enable_header(_("Add base installation"),
326 msgPool::featuresDisabled(_("Base installation")));
327 return ($display);
328 }
329 }
331 /***************
332 Root password hash dialog
333 ***************/
335 $this->dialog = FALSE;
336 if($this->setPasswordHash){
337 $this->dialog = TRUE;
338 $smarty = get_smarty();
339 $smarty->assign('hashes', set_post($this->hashes));
340 $smarty->assign('hash', set_post($this->hash));
341 return($smarty->fetch(get_template_path('goto/Device/SetPassword.tpl', TRUE)));
342 }
344 /***************
345 Partition dialog
346 ***************/
348 if(isset($_POST['partition_finish']) && $this->partitionEdit){
349 $this->installPartitionTable = $this->partitionEdit->save();
350 $this->partitionEdit = NULL;
351 }
352 if(isset($_POST['partition_cancel']) && $this->partitionEdit){
353 $this->partitionEdit = NULL;
354 }
355 if(isset($_POST['edit_installPartitionTable'])){
356 $this->partitionEdit = new DevicePartition($this->config, $this->installPartitionTable);
357 }
358 if($this->partitionEdit){
359 $this->partitionEdit->save_object();
360 $this->dialog = TRUE;
361 return($this->partitionEdit->execute());
362 }
366 /***************
367 Generate HTML content
368 ***************/
370 $this->installNTPServerList->setAcl($this->getacl('installNTPServer'));
371 $this->installNTPServerList->update();
373 plugin::execute();
374 $smarty = get_smarty();
376 // Assign ACLs
377 foreach($this->attributes as $attr){
378 $smarty->assign("{$attr}ACL", $this->getacl($attr));
379 }
381 $smarty->assign('installTemplateList', $this->installationTemplateNames);
382 $smarty->assign('installReleaseList', $this->templateToRelease[$this->installTemplate]);
383 $smarty->assign('timezones', $this->timezones);
384 $smarty->assign('installKeyboardlayoutList', $this->installKeyboardlayoutList);
385 $smarty->assign('installKernelPackageList', $this->installKernelPackageList);
386 $smarty->assign('installMirrorList', $this->installMirrorList);
387 $smarty->assign('installSystemLocaleList', $this->installSystemLocaleList);
388 $smarty->assign('installNTPServerList', $this->installNTPServerList->render());
390 $smarty->assign('installBootstrapMethod', $this->installBootstrapMethod);
391 $smarty->assign('installBootstrapMethodList', $this->installBootstrapMethodList);
392 $smarty->assign('installConfigManagement', $this->installConfigManagement);
394 // Assign list of available config-management types.
395 if(isset($this->installConfigManagementList[$this->installBootstrapMethod])){
396 $smarty->assign('installConfigManagementList', $this->installConfigManagementList[$this->installBootstrapMethod]);
397 }else{
398 $smarty->assign('installConfigManagementList', array());
399 }
401 foreach($this->attributes as $attr){
402 $smarty->assign($attr, $this->$attr);
403 }
404 $this->dialog = false;
405 return($display.$smarty->fetch(get_template_path('goto/Device/InstallRecipe.tpl', TRUE)));
406 }
409 function save_object()
410 {
411 if(isset($_POST['InstallRecipePosted'])){
413 $currentInstallMethod = $this->installConfigManagement;
415 $oldRelease = $this->installRelease;
416 plugin::save_object();
417 $this->installRootEnabled = isset($_POST['installRootEnabled']);
418 $this->installTimeUTC = isset($_POST['installTimeUTC']);
421 if(isset($_POST['setPasswordHash'])){
422 $this->setPasswordHash = true;
423 }
425 $this->installNTPServerList->save_object();
426 $this->installNTPServer = $this->installNTPServerList->getMaintainedData();
427 if(isset($_POST['installNTPServer_Input']) && isset($_POST['installNTPServer_Add'])){
428 $add = get_post('installNTPServer_Input');
429 if(!in_array($add, $this->installNTPServer) && !empty($add)){
430 $this->installNTPServer[] = $add;
431 }
432 }
433 $this->installNTPServerList->setListData($this->installNTPServer);
434 $this->installBootstrapMethod = $this->installationTemplates[$this->installTemplate]['method'];
436 // The selected release is no longer available for the current template
437 if(!in_array($this->installRelease, $this->templateToRelease[$this->installTemplate])){
438 $this->installRelease = key($this->templateToRelease[$this->installTemplate]);
439 }
441 // Reload list of kernel packages and mirrors
442 if($oldRelease != $this->installRelease){
443 $this->reloadInstallationKernelPackages();
444 $this->reloadInstallationMirrors();
445 }
446 }
448 if(isset($_POST['cancelPassword'])) $this->setPasswordHash =false;
449 if(isset($_POST['setPassword'])) {
450 $this->setPasswordHash =false;
451 $hash = get_post('passwordHash');
453 // Not sure, why this is here, but maybe some encryption methods require it.
454 mt_srand((double) microtime()*1000000);
456 // Generate the requested hash
457 $methods = new passwordMethod($this->config, $this->dn);
458 $available = $methods->get_available_methods();
459 $test = new $available[$hash]($this->config,$this->dn);
460 $this->installRootPasswordHash = @$test->generate_hash(get_post('rootPassword'));
461 }
462 }
465 function save()
466 {
467 if(!$this->installRootEnabled) $this->installRootPasswordHash = "";
469 $map = array(
470 "installTemplate"=>'template',
471 "installRelease"=>'release',
472 "installTimezone"=>'timezone',
473 "installTimeUTC"=>'utc',
474 "installKernelPackage"=>'kernel',
475 "installSystemLocale"=>'system-locale',
476 "installRootEnabled"=>'root-user',
477 "installRootPasswordHash"=>'root-hash',
478 "installPartitionTable"=>'disk-setup',
479 "installKeyboardlayout"=>'keyboard-layout',
480 "installBootstrapMethod"=>'method',
481 );
483 // Collect values to be saved.
484 $data = array();
485 foreach($map as $source => $dest){
486 if(!empty($this->$source)){
487 $data[$dest] = $this->$source;
488 }
489 }
491 // Enforce an array for ntp-servers
492 if(!empty($this->installNTPServer)){
493 $data['ntp-servers'] = array_values($this->installNTPServer);
494 }
496 // Save Boolean like a String
497 $boolean = array("root-user" => "installRootEnabled", "utc" => "installTimeUTC");
498 foreach($boolean as $attr => $source){
499 $data[$attr] = ($this->$source) ? $data[$attr] = "TRUE" : $data[$attr] = "FALSE";
500 }
502 // Set the base installation parameters
503 $rpc = $this->config->getRpcHandle();
504 $res = $rpc->systemSetBaseInstallParameters($this->deviceUUID, $data);
506 // Handle errors
507 $this->rpcError = !$rpc->success();
508 if(!$rpc->success()){
509 $this->rpcErrorMessage = $rpc->get_error();
510 msg_dialog::display(_("Error"), msgPool::rpcError($this->rpcErrorMessage), ERROR_DIALOG);
511 return(NULL);
512 }
513 }
516 function remove_from_parent()
517 {
518 print "Missing";
519 }
522 /*! \brief Refreshes the list of selectable kernel packages.
523 */
524 function reloadInstallationKernelPackages($initially = FALSE)
525 {
526 // Do nothing if no release is given.
527 if(empty($this->installRelease)){
528 $this->installKernelPackageList = array();
529 return;
530 }
532 $release = preg_replace("/^[^\/]*\//","", $this->installRelease);
533 $rpc = $this->config->getRpcHandle();
534 $res = $rpc->getKernelPackages($release);
536 // Failed to load backend values, keep reported error and return with FALSE;
537 $this->rpcError = !$rpc->success();
538 if(!$rpc->success()){
539 $this->rpcErrorMessage = $rpc->get_error();
540 msg_dialog::display(_("Error"), msgPool::rpcError($this->rpcErrorMessage), ERROR_DIALOG);
541 }else{
542 $this->installKernelPackageList = array();
543 foreach($res as $data){
544 $name = $data['name'];
545 $this->installKernelPackageList[$name] = $name;
546 }
548 if(!isset($this->installKernelPackageList[$this->installKernelPackage])){
549 $new = key($this->installKernelPackageList);
550 if($initially && $this->is_account){
551 msg_dialog::display(_("Warning"), sprintf(_("The selected kernel package '%s' is no longer available! The kernel package '%s' was selected as replacement!"), $this->installKernelPackage, $new), WARNING_DIALOG);
552 }
553 $this->installKernelPackage = $new;
554 }
555 }
556 }
559 /*! \brief Returns a list of distributions on success.
560 * In case of an error, it returns NULL.
561 */
562 function loadDistributions()
563 {
564 $rpc = $this->config->getRpcHandle();
565 $res = $rpc->getDistributions();
567 // Failed to load backend values, keep reported error and return with FALSE;
568 $this->rpcError = !$rpc->success();
569 if(!$rpc->success()){
570 $this->rpcErrorMessage = $rpc->get_error();
571 return(NULL);
572 }
573 return($res);
574 }
577 /*! \brief Returns a list of timezones on success.
578 * In case of an error, it returns NULL.
579 */
580 function getTimezones()
581 {
582 $rpc = $this->config->getRpcHandle();
583 $res = $rpc->getTimezones();
585 // Failed to load backend values, keep reported error and return with FALSE;
586 $this->rpcError = !$rpc->success();
587 if(!$rpc->success()){
588 $this->rpcErrorMessage = $rpc->get_error();
589 return(NULL);
590 }
591 return($res);
592 }
595 /*! \brief Returns a list of installation mirrors on success.
596 * In case of an error, it returns NULL.
597 */
598 function reloadInstallationMirrors($initially = FALSE)
599 {
600 $res = array(
601 'dc=intranet,dc=gonicus,dc=de' => 'Intranet',
602 'ou=systems,dc=intranet,dc=gonicus,dc=de' => 'System');
603 $this->installMirrorList =$res;
604 }
607 /*! \brief Returns a list of installation templates on success.
608 * In case of an error, it returns NULL.
609 */
610 function loadInstallationTemplates()
611 {
612 $rpc = $this->config->getRpcHandle();
613 $res = $rpc->installListTemplates();
615 // Failed to load backend values, keep reported error and return with FALSE;
616 $this->rpcError = !$rpc->success();
617 if(!$rpc->success()){
618 $this->rpcErrorMessage = $rpc->get_error();
619 return(NULL);
620 }
621 return($res);
622 }
625 /*! \brief Returns a list of keyboard layouts on success.
626 * In case of an error, it returns NULL.
627 */
628 function loadInstallationKeyboardLayouts()
629 {
630 $rpc = $this->config->getRpcHandle();
631 $res = $rpc->getKeyboardModels();
633 // Failed to load backend values, keep reported error and return with FALSE;
634 $this->rpcError = !$rpc->success();
635 if(!$rpc->success()){
636 $this->rpcErrorMessage = $rpc->get_error();
637 return(NULL);
638 }
639 $lay = array();
640 foreach($res as $key => $data){
641 $lay[$key] = "{$data[0]} - {$data[2]}";
642 }
643 asort($lay);
644 return($lay);
645 }
648 /*! \brief Returns a list of system locales on success.
649 * In case of an error, it returns NULL.
650 */
651 function getSystemLocales()
652 {
653 $rpc = $this->config->getRpcHandle();
654 $res = $rpc->getSystemLocales();
656 // Failed to load backend values, keep reported error and return with FALSE;
657 $this->rpcError = !$rpc->success();
658 if(!$rpc->success()){
659 $this->rpcErrorMessage = $rpc->get_error();
660 msg_dialog::display(_("Error"), msgPool::rpcError($this->rpcErrorMessage), ERROR_DIALOG);
661 return(NULL);
662 }
664 return($res);
665 }
668 /*! \brief Try to load install and bootstrap methods from the GOsa-backend
669 * This is done via jsonRPC, if calling the backend method fails,
670 * this method returns FALSE, in case of success it return TRUE;
671 */
672 function loadInstallationMethods()
673 {
674 $rpc = $this->config->getRpcHandle();
675 $res = $rpc->getSupportedBaseInstallMethods();
677 // Failed to load backend values, keep reported error and return with FALSE;
678 $this->rpcError = !$rpc->success();
679 if(!$rpc->success()){
680 $this->rpcErrorMessage = $rpc->get_error();
681 return(NULL);
682 }
684 // Walk through result and set bootstrap methods.
685 foreach($res as $name => $method){
686 $res['installBootstrapMethodList'][$name] = $method['name'];
687 foreach($method['methods'] as $m){
688 $res['installConfigManagementList'][$name][$m] = $m;
689 }
690 }
691 return($res);
692 }
695 static function plInfo()
696 {
697 return (array(
698 "plShortName" => _("Device"),
699 "plDescription" => _("Registered device"),
700 "plSelfModify" => FALSE,
701 "plDepends" => array(),
702 "plPriority" => 1,
703 "plSection" => array("administration"),
704 "plCategory" => array("Device"),
705 "plProvidedAcls" => array(
707 "installRelease" => _("Release"),
708 "installTemplate" => _("Template"),
709 "installKeyboardlayout" => _("Keyboard layout"),
710 "installSystemLocale" => _("Locale"),
711 "installTimezone" => _("Timezone"),
712 "installTimeUTC" => _("Utc"),
713 "installNTPServer" => _("Ntp server"),
714 "installMirror" => _("Mirror"),
715 "installRootEnabled" => _("Root login enabled"),
716 "installRootPasswordHash" => _("Root password hash"),
717 "installKernelPackage" => _("Kernel package"),
718 "installConfigManagement" => _("Config mangement"),
719 "installBootstrapMethod" => _("Bootstrap method"),
720 "installPartitionTable" => _("Partition table")
721 )
722 )
723 );
724 }
725 }
726 ?>