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 = "";
50 // Keyboard-layout attribute
51 public $installKeyboardlayout = "";
52 public $installKeyboardlayoutList = array();
54 // Mirror related attribute
55 public $installMirror = "";
56 public $installMirrorList = array();
58 public $objectclasses = array();
59 public $attributes = array("installRelease", "installTemplate","installKeyboardlayout","installSystemLocale",
60 "installTimezone","installTimeUTC","installNTPServer","installMirror",
61 "installRootEnabled","installRootPasswordHash","installKernelPackage",
62 "installPartitionTable","installConfigManagement","installBootstrapMethod");
65 /* Some plugin management related attributes
66 * See class plugin for details.
67 */
68 public $view_logged = FALSE;
69 public $ignore_account = FALSE;
70 public $parent = NULL;
72 /*! \brief Initialize the plugin and its widgets.
73 * Finally call init() to load values from the backend.
74 */
75 function __construct(&$config, $dn, $parent)
76 {
77 plugin::plugin($config, $dn);
79 $this->is_account = $this->initially_was_account = FALSE;
81 $this->_device = &$parent;
82 $this->deviceUUID = $parent->deviceUUID;
84 // Set default password hash
85 $this->hash = $this->config->get_cfg_value("core","passwordDefaultHash");
87 // Get list of password hashes
88 $tmp = passwordMethod::get_available_methods();
89 $this->hashes = array();
90 foreach($tmp['name'] as $name){
91 $this->hashes[$name] = $name;
92 }
94 // Initialize plugin
95 $this->init_static_info();
96 $this->init($initially = TRUE);
97 }
99 function init($initially = FALSE)
100 {
101 // Init the object values.
102 $this->init_client_info();
104 // Prepare NTP servers list
105 $this->installNTPServerList= new sortableListing($this->installNTPServer);
106 $this->installNTPServerList->setDeleteable(true);
107 $this->installNTPServerList->setEditable(false);
108 $this->installNTPServerList->setColspecs(array('*'));
109 $this->installNTPServerList->setWidth("100%");
110 $this->installNTPServerList->setHeight("70px");
112 // Preset values for new devices
113 if(!$this->is_account){
114 $this->installTemplate = key($this->installationTemplates);
115 $this->installRelease = key($this->templateToRelease[$this->installTemplate]);
116 }else{
118 if(!isset($this->installationTemplates[$this->installTemplate])){
120 // The selected template is no longer available, select the next selectable template.
121 $new = key($this->installationTemplates);
123 if($initially){
124 $message = sprintf(_("The selected template '%s' is no longer available. Selecting '%s' as replacement!"),
125 $this->installTemplate, $new);
126 msg_dialog::display(_("Warning"), $message, WARNING_DIALOG);
127 }
128 $this->installTemplate = $new;
129 $installRelease = key($this->templateToRelease[$this->installTemplate]);
131 }elseif(!isset($this->installationTemplates[$this->installTemplate]['method'])){
133 // Not necessary to warn the user here, the input fields will be empty and thus
134 // avoid saving.
136 }elseif(!in_array($this->installRelease, $this->templateToRelease[$this->installTemplate])){
138 // The selected release is no longer available for the current template
139 // Warn the user and select the next selectable release.
140 $new = key($this->templateToRelease[$this->installTemplate]);
141 if($initially){
142 $message = sprintf(_("The selected release '%s' is no longer available. Selecting '%s' as replacement!"),
143 $this->installRelease, $new);
144 }
145 $this->installRelease = $new;
146 msg_dialog::display(_("Warning"), $message, WARNING_DIALOG);
147 }
148 }
150 // Update selectable items like kernels and mirrors depending on the current setup (relase)
151 $this->installBootstrapMethod = $this->installationTemplates[$this->installTemplate]['method'];
152 $this->reloadInstallationKernelPackages($initially);
153 $this->reloadInstallationMirrors($initially);
154 }
157 /*! \brief Loads client-information values from the GOsa-backend using jsonRPC
158 */
159 function init_client_info()
160 {
161 if(empty($this->deviceUUID)){
162 return;
163 }
165 $rpc = $this->config->getRpcHandle();
166 $res = $rpc->systemGetBaseInstallParameters($this->deviceUUID);
168 // Failed to load backend values, keep reported error and return with FALSE;
169 $this->rpcError = !$rpc->success();
170 if(!$rpc->success()){
171 $this->rpcErrorMessage = $rpc->get_error();
172 msg_dialog::display(_("Error"), msgPool::rpcError($this->rpcErrorMessage), ERROR_DIALOG);
173 return(NULL);
174 }
176 // Apply received options
177 $this->is_account = $res == True;
178 if($this->is_account){
180 $map = array(
181 'ntp-servers' => "installNTPServer",
182 'template' => "installTemplate",
183 'keyboard-layout' => "installKeyboardlayout");
185 // We receive an array for these attributes, but require a string instead
186 // we just use the first element of the array.
187 $mapArray = array(
188 'release' => "installRelease",
189 'timezone' => "installTimezone",
190 'utc' => "installTimeUTC",
191 'kernel' => "installKernelPackage",
192 'system-locale' => "installSystemLocale",
193 'root-user' => "installRootEnabled",
194 'root-hash' => "installRootPasswordHash",
195 'disk-setup' => "installPartitionTable");
197 foreach($res as $name => $data){
198 if(isset($map[$name])){
199 $target = $map[$name];
200 $value = $res[$name];
201 }elseif(isset($mapArray[$name])){
202 $target = $mapArray[$name];
203 $value = $res[$name][0];
204 }
205 $this->$target = $value;
206 }
208 // Convert Bool values to Bool.
209 $boolean = array("installRootEnabled", "installTimeUTC");
210 foreach($boolean as $attr){
211 $this->$attr = ($this->$attr != FALSE);
212 }
213 }
215 return;
216 }
219 function init_static_info()
220 {
221 // Load static values.
222 foreach(array(
223 "timeozones" => "getTimezones",
224 "distributions" => "loadDistributions",
225 "keyboardLayouts" => "loadInstallationKeyboardLayouts",
226 "installationTemplates" => "loadInstallationTemplates",
227 "installationMethods" => "loadInstallationMethods",
228 "locales" => "getSystemLocales" ) as $target => $func){
229 $$target = $this->$func();
230 if($$target == NULL){
231 $this->initFailed = TRUE;
232 msg_dialog::display(_("Error"), msgPool::rpcError($this->rpcErrorMessage), ERROR_DIALOG);
233 return;
234 }
235 }
237 // Assign fetchted values
238 $this->timezones = $timeozones;
239 $this->installBootstrapMethodList = $installationMethods['installBootstrapMethodList'];
240 $this->installConfigManagementList = $installationMethods['installConfigManagementList'];
241 $this->installSystemLocaleList = $locales;
242 $this->installKeyboardlayoutList = $keyboardLayouts;
243 $this->distributions = $distributions;
245 # Create template to relase map
246 $this->templateToRelease = array();
248 // Walk through installation templates and use the 'repositories' attribute
249 // to supported releases.
250 foreach($installationTemplates as $name => $tdata){
252 $mName = isset($this->installBootstrapMethodList[$tdata['method']]) ?
253 $this->installBootstrapMethodList[$tdata['method']]: $tdata['method'];
255 $this->installationTemplateNames[$name] = $tdata['description']." (".$mName.")";
256 $this->installationTemplates[$name] = $tdata;
257 $this->templateToRelease[$name] = array();
259 // Check if the 'repository'-category of the template can be found in any
260 // received release list.
261 if(isset($installationMethods[$tdata['method']]['repositories'])){
262 $repos = $installationMethods[$tdata['method']]['repositories'];
263 foreach($distributions as $dist){
264 if(in_array($dist['type']['name'],$repos) && isset($dist['releases'])){
265 foreach($dist['releases'] as $release){
266 $rname = $dist['name'].'/'.$release['name'];
267 $this->templateToRelease[$name][$rname] = $rname;
268 }
269 }
270 }
271 }
272 }
273 }
276 function check()
277 {
278 // Check if the parents deviceUUID has changed
279 if($this->deviceUUID != $this->_device->deviceUUID){
280 $this->deviceUUID = $this->_device->deviceUUID;
281 print "The device uuid has changed.";
282 }
283 }
286 function execute()
287 {
288 // Log account access
289 if($this->is_account && !$this->view_logged){
290 $this->view_logged = TRUE;
291 new log("view","Device/".get_class($this),$this->dn);
292 }
294 /***************
295 Handle account state
296 ***************/
298 // Allow to add or remove the distribution list extension
299 if(isset($_POST['modify_state'])){
300 if($this->is_account && $this->acl_is_removeable()){
301 $this->is_account= FALSE;
302 }elseif(!$this->is_account && $this->acl_is_createable()){
303 $this->is_account= TRUE;
304 }
305 }
307 // Show account status-changer
308 $display = "";
309 if ($this->parent !== NULL){
310 if ($this->is_account){
311 $display= $this->show_disable_header(_("Remove install profile"),
312 msgPool::featuresEnabled(_("Install profile")));
313 } else {
314 $display= $this->show_enable_header(_("Add install profile"),
315 msgPool::featuresDisabled(_("Install profile")));
316 return ($display);
317 }
318 }
320 /***************
321 Root password hash dialog
322 ***************/
324 if($this->setPasswordHash){
325 $this->dialog = TRUE;
326 $smarty = get_smarty();
327 $smarty->assign('hashes', set_post($this->hashes));
328 $smarty->assign('hash', set_post($this->hash));
329 return($smarty->fetch(get_template_path('goto/Device/SetPassword.tpl', TRUE)));
330 }
332 /***************
333 Generate HTML content
334 ***************/
336 $this->installNTPServerList->setAcl($this->getacl('installNTPServer'));
337 $this->installNTPServerList->update();
339 plugin::execute();
340 $smarty = get_smarty();
341 $smarty->assign('installTemplateList', $this->installationTemplateNames);
342 $smarty->assign('installReleaseList', $this->templateToRelease[$this->installTemplate]);
345 $smarty->assign('timezones', $this->timezones);
346 $smarty->assign('installKeyboardlayoutList', $this->installKeyboardlayoutList);
347 $smarty->assign('installKernelPackageList', $this->installKernelPackageList);
348 $smarty->assign('installMirrorList', $this->installMirrorList);
349 $smarty->assign('installSystemLocaleList', $this->installSystemLocaleList);
350 $smarty->assign('installNTPServerList', $this->installNTPServerList->render());
352 $smarty->assign('installBootstrapMethod', $this->installBootstrapMethod);
353 $smarty->assign('installBootstrapMethodList', $this->installBootstrapMethodList);
354 $smarty->assign('installConfigManagement', $this->installConfigManagement);
356 // Assign list of available config-management types.
357 if(isset($this->installConfigManagementList[$this->installBootstrapMethod])){
358 $smarty->assign('installConfigManagementList', $this->installConfigManagementList[$this->installBootstrapMethod]);
359 }else{
360 $smarty->assign('installConfigManagementList', array());
361 }
363 foreach($this->attributes as $attr){
364 $smarty->assign($attr, $this->$attr);
365 }
366 $this->dialog = false;
367 return($display.$smarty->fetch(get_template_path('goto/Device/InstallRecipe.tpl', TRUE)));
368 }
371 function save_object()
372 {
373 if(isset($_POST['InstallRecipePosted'])){
375 $currentInstallMethod = $this->installConfigManagement;
377 $oldRelease = $this->installRelease;
378 plugin::save_object();
379 $this->installRootEnabled = isset($_POST['installRootEnabled']);
380 $this->installTimeUTC = isset($_POST['installTimeUTC']);
383 if(isset($_POST['setPasswordHash'])){
384 $this->setPasswordHash = true;
385 }
387 $this->installNTPServerList->save_object();
388 $this->installNTPServer = $this->installNTPServerList->getMaintainedData();
389 if(isset($_POST['installNTPServer_Input']) && isset($_POST['installNTPServer_Add'])){
390 $add = get_post('installNTPServer_Input');
391 if(!in_array($add, $this->installNTPServer) && !empty($add)){
392 $this->installNTPServer[] = $add;
393 }
394 }
395 $this->installNTPServerList->setListData($this->installNTPServer);
396 $this->installBootstrapMethod = $this->installationTemplates[$this->installTemplate]['method'];
398 // The selected release is no longer available for the current template
399 if(!in_array($this->installRelease, $this->templateToRelease[$this->installTemplate])){
400 $this->installRelease = key($this->templateToRelease[$this->installTemplate]);
401 }
403 // Reload list of kernel packages and mirrors
404 if($oldRelease != $this->installRelease){
405 $this->reloadInstallationKernelPackages();
406 $this->reloadInstallationMirrors();
407 }
408 }
410 if(isset($_POST['cancelPassword'])) $this->setPasswordHash =false;
411 if(isset($_POST['setPassword'])) {
412 $this->setPasswordHash =false;
413 $hash = get_post('passwordHash');
415 // Not sure, why this is here, but maybe some encryption methods require it.
416 mt_srand((double) microtime()*1000000);
418 // Generate the requested hash
419 $methods = new passwordMethod($this->config, $this->dn);
420 $available = $methods->get_available_methods();
421 $test = new $available[$hash]($this->config,$this->dn);
422 $this->installRootPasswordHash = @$test->generate_hash(get_post('rootPassword'));
423 }
424 }
427 function save()
428 {
429 if(!$this->installRootEnabled) $this->installRootPasswordHash = "";
431 $map = array(
432 "installNTPServer"=>'ntp-servers',
433 "installTemplate"=>'template',
434 "installRelease"=>'release',
435 "installTimezone"=>'timezone',
436 "installTimeUTC"=>'utc',
437 "installKernelPackage"=>'kernel',
438 "installSystemLocale"=>'system-locale',
439 "installRootEnabled"=>'root-user',
440 "installRootPasswordHash"=>'root-hash',
441 "installPartitionTable"=>'disk-setup',
442 "installKeyboardlayout"=>'keyboard-layout',
443 );
445 // Collect values to be saved.
446 $data = array();
447 foreach($map as $source => $dest){
448 if(!empty($this->$source)){
449 $data[$dest] = $this->$source;
450 }
451 }
453 // Enforce an array for ntp-servers
454 $data['ntp-servers'] = array_values($data['ntp-servers']);
456 // Save Boolean like a String
457 $boolean = array("root-user", "utc");
458 foreach($boolean as $attr){
459 $data[$attr] = ($data[$attr]) ? $data[$attr] = TRUE : $data[$attr] = FALSE;
460 }
462 $rpc = $this->config->getRpcHandle();
463 $res = $rpc->systemSetBaseInstallParameters($this->deviceUUID, $data);
465 // Failed to load backend values, keep reported error and return with FALSE;
466 $this->rpcError = !$rpc->success();
467 if(!$rpc->success()){
468 $this->rpcErrorMessage = $rpc->get_error();
469 msg_dialog::display(_("Error"), msgPool::rpcError($this->rpcErrorMessage), ERROR_DIALOG);
470 return(NULL);
471 }
473 }
476 function remove_from_parent()
477 {
478 print "Missing";
479 }
482 /*! \brief Refreshes the list of selectable kernel packages.
483 */
484 function reloadInstallationKernelPackages($initially = FALSE)
485 {
486 // Do nothing if no release is given.
487 if(empty($this->installRelease)){
488 $this->installKernelPackageList = array();
489 return;
490 }
492 $rpc = $this->config->getRpcHandle();
493 $res = $rpc->getKernelPackages($this->installRelease);
495 // Failed to load backend values, keep reported error and return with FALSE;
496 $this->rpcError = !$rpc->success();
497 if(!$rpc->success()){
498 $this->rpcErrorMessage = $rpc->get_error();
499 msg_dialog::display(_("Error"), msgPool::rpcError($this->rpcErrorMessage), ERROR_DIALOG);
500 }else{
501 $this->installKernelPackageList = array();
502 foreach($res as $name){
503 $this->installKernelPackageList[$name] = $name;
504 }
506 if(!isset($this->installKernelPackageList[$this->installKernelPackage])){
507 $new = key($this->installKernelPackageList);
508 if($initially){
509 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);
510 }
511 $this->installKernelPackage = $new;
512 }
513 }
514 }
517 /*! \brief Returns a list of distributions on success.
518 * In case of an error, it returns NULL.
519 */
520 function loadDistributions()
521 {
522 $rpc = $this->config->getRpcHandle();
523 $res = $rpc->getDistributions();
525 // Failed to load backend values, keep reported error and return with FALSE;
526 $this->rpcError = !$rpc->success();
527 if(!$rpc->success()){
528 $this->rpcErrorMessage = $rpc->get_error();
529 return(NULL);
530 }
531 return($res);
532 }
535 /*! \brief Returns a list of timezones on success.
536 * In case of an error, it returns NULL.
537 */
538 function getTimezones()
539 {
540 $rpc = $this->config->getRpcHandle();
541 $res = $rpc->getTimezones();
543 // Failed to load backend values, keep reported error and return with FALSE;
544 $this->rpcError = !$rpc->success();
545 if(!$rpc->success()){
546 $this->rpcErrorMessage = $rpc->get_error();
547 return(NULL);
548 }
549 return($res);
550 }
553 /*! \brief Returns a list of installation mirrors on success.
554 * In case of an error, it returns NULL.
555 */
556 function reloadInstallationMirrors($initially = FALSE)
557 {
558 $res = array(
559 'dc=intranet,dc=gonicus,dc=de' => 'Intranet',
560 'ou=systems,dc=intranet,dc=gonicus,dc=de' => 'System');
561 $this->installMirrorList =$res;
562 }
565 /*! \brief Returns a list of installation templates on success.
566 * In case of an error, it returns NULL.
567 */
568 function loadInstallationTemplates()
569 {
570 $rpc = $this->config->getRpcHandle();
571 $res = $rpc->installListTemplates();
573 // Failed to load backend values, keep reported error and return with FALSE;
574 $this->rpcError = !$rpc->success();
575 if(!$rpc->success()){
576 $this->rpcErrorMessage = $rpc->get_error();
577 return(NULL);
578 }
579 return($res);
580 }
583 /*! \brief Returns a list of keyboard layouts on success.
584 * In case of an error, it returns NULL.
585 */
586 function loadInstallationKeyboardLayouts()
587 {
588 $rpc = $this->config->getRpcHandle();
589 $res = $rpc->getKeyboardModels();
591 // Failed to load backend values, keep reported error and return with FALSE;
592 $this->rpcError = !$rpc->success();
593 if(!$rpc->success()){
594 $this->rpcErrorMessage = $rpc->get_error();
595 return(NULL);
596 }
597 $lay = array();
598 foreach($res as $key => $data){
599 $lay[$key] = "{$data[0]} - {$data[2]}";
600 }
601 asort($lay);
602 return($lay);
603 }
606 /*! \brief Returns a list of system locales on success.
607 * In case of an error, it returns NULL.
608 */
609 function getSystemLocales()
610 {
611 $rpc = $this->config->getRpcHandle();
612 $res = $rpc->getSystemLocales();
614 // Failed to load backend values, keep reported error and return with FALSE;
615 $this->rpcError = !$rpc->success();
616 if(!$rpc->success()){
617 $this->rpcErrorMessage = $rpc->get_error();
618 msg_dialog::display(_("Error"), msgPool::rpcError($this->rpcErrorMessage), ERROR_DIALOG);
619 return(NULL);
620 }
622 return($res);
623 }
626 /*! \brief Try to load install and bootstrap methods from the GOsa-backend
627 * This is done via jsonRPC, if calling the backend method fails,
628 * this method returns FALSE, in case of success it return TRUE;
629 */
630 function loadInstallationMethods()
631 {
632 $rpc = $this->config->getRpcHandle();
633 $res = $rpc->getSupportedBaseInstallMethods();
635 // Failed to load backend values, keep reported error and return with FALSE;
636 $this->rpcError = !$rpc->success();
637 if(!$rpc->success()){
638 $this->rpcErrorMessage = $rpc->get_error();
639 return(NULL);
640 }
642 // Walk through result and set bootstrap methods.
643 foreach($res as $name => $method){
644 $res['installBootstrapMethodList'][$name] = $method['name'];
645 foreach($method['methods'] as $m){
646 $res['installConfigManagementList'][$name][$m] = $m;
647 }
648 }
649 return($res);
650 }
653 static function plInfo()
654 {
655 return (array(
656 "plShortName" => _("Device"),
657 "plDescription" => _("Registered device"),
658 "plSelfModify" => FALSE,
659 "plDepends" => array(),
660 "plPriority" => 1,
661 "plSection" => array("administration"),
662 "plCategory" => array("Device"),
663 "plProvidedAcls" => array(
664 "member" => _("Member"),
665 "installTemplate" => _("Installation template"),
666 "installRelease" => _("Installation release"),
668 "installBootstrapMethod" => _("Bootstrap method"),
669 "installConfigManagement" => _("Config management"),
670 "installKeyboardlayout" => _("Keyboard layout"),
671 "installSystemLocale" => _("System locale"),
672 "installTimezone" => _("Timezone"),
673 "installTimeUTC" => _("Time"),
674 "installNTPServer" => _("NTP-Server"),
675 "installMirror" => _("Mirror"),
676 "installRootEnabled" => _("Root login enabled"),
677 "installRootPasswordHash" => _("Root password hash"),
678 "installKernelPackage" => _("Kernel package"),
679 "installPartitionTable" => _("Partition table")
680 )
681 )
682 );
683 }
684 }
685 ?>