/[smeserver]/cdrom.image/sme9/updates/text.py
ViewVC logotype

Contents of /cdrom.image/sme9/updates/text.py

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (show annotations) (download) (as text)
Mon Oct 28 23:02:23 2013 UTC (10 years, 8 months ago) by charliebrady
Branch: MAIN
Content type: text/x-python
Remove "Re-initialize" option for unpartitioned drives. [SME: 7933]

1 #
2 # text.py - text mode frontend to anaconda
3 #
4 # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.
5 # All rights reserved.
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #
20 # Author(s): Erik Troan <ewt@redhat.com>
21 # Matt Wilson <msw@redhat.com>
22 #
23
24 from snack import *
25 import sys
26 import os
27 import isys
28 import iutil
29 import time
30 import signal
31 import parted
32 import product
33 import string
34 from language import expandLangs
35 from flags import flags
36 from constants_text import *
37 from constants import *
38 import network
39 from installinterfacebase import InstallInterfaceBase
40 import imputil
41
42 import gettext
43 _ = lambda x: gettext.ldgettext("anaconda", x)
44 P_ = lambda x, y, z: gettext.ldngettext("anaconda", x, y, z)
45
46 import logging
47 log = logging.getLogger("anaconda")
48
49 stepToClasses = {
50 "language" : ("language_text", "LanguageWindow"),
51 "keyboard" : ("keyboard_text", "KeyboardWindow"),
52 "welcome" : ("welcome_text", "WelcomeWindow"),
53 "parttype" : ("partition_text", "PartitionTypeWindow"),
54 "addswap" : ("upgrade_text", "UpgradeSwapWindow"),
55 "upgrademigratefs" : ("upgrade_text", "UpgradeMigrateFSWindow"),
56 "zfcpconfig": ("zfcp_text", ("ZFCPWindow")),
57 "findinstall" : ("upgrade_text", ("UpgradeExamineWindow")),
58 "upgbootloader": ("upgrade_bootloader_text", "UpgradeBootloaderWindow"),
59 "network" : ("network_text", ("HostnameWindow")),
60 "timezone" : ("timezone_text", "TimezoneWindow"),
61 "accounts" : ("userauth_text", "RootPasswordWindow"),
62 "tasksel": ("task_text", "TaskWindow"),
63 "install" : ("progress_text", "setupForInstall"),
64 "complete" : ("complete_text", "FinishedWindow"),
65 }
66
67 if iutil.isS390():
68 stepToClasses["bootloader"] = ("zipl_text", ( "ZiplWindow"))
69
70 class InstallWindow:
71 def __call__ (self, screen):
72 raise RuntimeError, "Unimplemented screen"
73
74 class WaitWindow:
75 def pop(self):
76 self.screen.popWindow()
77 self.screen.refresh()
78
79 def refresh(self):
80 pass
81
82 def __init__(self, screen, title, text):
83 self.screen = screen
84 width = 40
85 if (len(text) < width): width = len(text)
86
87 t = TextboxReflowed(width, text)
88
89 g = GridForm(self.screen, title, 1, 1)
90 g.add(t, 0, 0)
91 g.draw()
92 self.screen.refresh()
93
94 class OkCancelWindow:
95 def getrc(self):
96 return self.rc
97
98 def __init__(self, screen, title, text):
99 rc = ButtonChoiceWindow(screen, title, text,
100 buttons=[TEXT_OK_BUTTON, _("Cancel")])
101 if rc == string.lower(_("Cancel")):
102 self.rc = 1
103 else:
104 self.rc = 0
105
106 class ProgressWindow:
107 def pop(self):
108 self.screen.popWindow()
109 self.screen.refresh()
110 del self.scale
111 self.scale = None
112
113 def pulse(self):
114 pass
115
116 def set(self, amount):
117 self.scale.set(int(float(amount) * self.multiplier))
118 self.screen.refresh()
119
120 def refresh(self):
121 pass
122
123 def __init__(self, screen, title, text, total, updpct = 0.05, pulse = False):
124 self.multiplier = 1
125 if total == 1.0:
126 self.multiplier = 100
127 self.screen = screen
128 width = 55
129 if (len(text) > width): width = len(text)
130
131 t = TextboxReflowed(width, text)
132
133 g = GridForm(self.screen, title, 1, 2)
134 g.add(t, 0, 0, (0, 0, 0, 1), anchorLeft=1)
135
136 self.scale = Scale(int(width), int(float(total) * self.multiplier))
137 if not pulse:
138 g.add(self.scale, 0, 1)
139
140 g.draw()
141 self.screen.refresh()
142
143 class LuksPassphraseWindow:
144 def __init__(self, screen, passphrase = "", preexist = False):
145 self.screen = screen
146 self.passphrase = passphrase
147 self.minLength = 8
148 self.preexist = preexist
149 self.txt = _("Choose a passphrase for the encrypted devices. You "
150 "will be prompted for this passphrase during system boot.")
151 self.rc = None
152
153 def run(self):
154 toplevel = GridForm(self.screen, _("Passphrase for encrypted device"),
155 1, 5)
156
157 txt = TextboxReflowed(65, self.txt)
158 toplevel.add(txt, 0, 0)
159
160 passphraseentry = Entry(60, password = 1)
161 toplevel.add(passphraseentry, 0, 1, (0,0,0,1))
162
163 confirmentry = Entry(60, password = 1)
164 toplevel.add(confirmentry, 0, 2, (0,0,0,1))
165
166 if self.preexist:
167 globalcheckbox = Checkbox(_("Also add this passphrase to all existing encrypted devices"), isOn = True)
168 toplevel.add(globalcheckbox, 0, 3)
169
170 buttons = ButtonBar(self.screen, [TEXT_OK_BUTTON, TEXT_CANCEL_BUTTON])
171 toplevel.add(buttons, 0, 4, growx=1)
172
173 passphraseentry.set(self.passphrase)
174 confirmentry.set(self.passphrase)
175
176 while True:
177 rc = toplevel.run()
178 res = buttons.buttonPressed(rc)
179
180 passphrase = None
181 if res == TEXT_OK_CHECK or rc == "F12":
182 passphrase = passphraseentry.value()
183 confirm = confirmentry.value()
184
185 if passphrase != confirm:
186 ButtonChoiceWindow(self.screen,
187 _("Error with passphrase"),
188 _("The passphrases you entered were "
189 "different. Please try again."),
190 buttons=[TEXT_OK_BUTTON])
191 passphraseentry.set("")
192 confirmentry.set("")
193 continue
194
195 if len(passphrase) < self.minLength:
196 ButtonChoiceWindow(self.screen,
197 _("Error with passphrase"),
198 P_("The passphrase must be at least "
199 "%d character long.",
200 "The passphrase must be at least "
201 "%d characters long.",
202 self.minLength)
203 % (self.minLength,),
204 buttons=[TEXT_OK_BUTTON])
205 passphraseentry.set("")
206 confirmentry.set("")
207 continue
208 else:
209 passphrase = self.passphrase
210 passphraseentry.set(self.passphrase)
211 confirmentry.set(self.passphrase)
212
213 retrofit = False
214 if self.preexist:
215 retrofit = globalcheckbox.selected()
216 self.rc = passphrase
217 return (self.rc, retrofit)
218
219 def pop(self):
220 self.screen.popWindow()
221
222 class PassphraseEntryWindow:
223 def __init__(self, screen, device):
224 self.screen = screen
225 self.txt = _("Device %s is encrypted. In order to "
226 "access the device's contents during "
227 "installation you must enter the device's "
228 "passphrase below.") % (device,)
229 self.rc = None
230
231 def run(self):
232 toplevel = GridForm(self.screen, _("Passphrase"), 1, 4)
233
234 txt = TextboxReflowed(65, self.txt)
235 toplevel.add(txt, 0, 0)
236
237 passphraseentry = Entry(60, password = 1)
238 toplevel.add(passphraseentry, 0, 1, (0,0,0,1))
239
240 globalcheckbox = Checkbox(_("This is a global passphrase"))
241 toplevel.add(globalcheckbox, 0, 2)
242
243 buttons = ButtonBar(self.screen, [TEXT_OK_BUTTON, TEXT_CANCEL_BUTTON])
244 toplevel.add(buttons, 0, 3, growx=1)
245
246 rc = toplevel.run()
247 res = buttons.buttonPressed(rc)
248
249 passphrase = None
250 isglobal = False
251 if res == TEXT_OK_CHECK or rc == "F12":
252 passphrase = passphraseentry.value().strip()
253 isglobal = globalcheckbox.selected()
254
255 self.rc = (passphrase, isglobal)
256 return self.rc
257
258 def pop(self):
259 self.screen.popWindow()
260
261 class InstallInterface(InstallInterfaceBase):
262 def progressWindow(self, title, text, total, updpct = 0.05, pulse = False):
263 return ProgressWindow(self.screen, title, text, total, updpct, pulse)
264
265 def exitWindow(self, title, text):
266 return self.messageWindow(title, text, type="custom",
267 custom_buttons=[_("Exit installer")])
268
269 def messageWindow(self, title, text, type="ok", default = None,
270 custom_icon=None, custom_buttons=[]):
271 text = str(text)
272 if type == "ok":
273 ButtonChoiceWindow(self.screen, title, text,
274 buttons=[TEXT_OK_BUTTON])
275 elif type == "yesno":
276 if default and default == "no":
277 btnlist = [TEXT_NO_BUTTON, TEXT_YES_BUTTON]
278 else:
279 btnlist = [TEXT_YES_BUTTON, TEXT_NO_BUTTON]
280 rc = ButtonChoiceWindow(self.screen, title, text,
281 buttons=btnlist)
282 if rc == "yes":
283 return 1
284 else:
285 return 0
286 elif type == "custom":
287 tmpbut = []
288 for but in custom_buttons:
289 tmpbut.append(string.replace(but,"_",""))
290
291 rc = ButtonChoiceWindow(self.screen, title, text, width=60,
292 buttons=tmpbut)
293
294 idx = 0
295 for b in tmpbut:
296 if string.lower(b) == rc:
297 return idx
298 idx = idx + 1
299 return 0
300 else:
301 return OkCancelWindow(self.screen, title, text)
302
303 def detailedMessageWindow(self, title, text, longText=None, type="ok",
304 default=None, custom_icon=None,
305 custom_buttons=[], expanded=False):
306 t = TextboxReflowed(60, text, maxHeight=8)
307
308 # if it is a string, just print it as it is (#674322)
309 if isinstance(longText, basestring):
310 lt = Textbox(60, 6, longText, scroll=1, wrap=1)
311 # if the argument is anything else we have to join it together (#654074)
312 else:
313 lt = Textbox(60, 6, "\n".join(longText), scroll=1, wrap=1)
314
315 g = GridFormHelp(self.screen, title, help, 1, 3)
316 g.add(t, 0, 0)
317 g.add(lt, 0, 1, padding = (0, 1, 0, 1))
318
319 if type == "ok":
320 bb = ButtonBar(self.screen, [TEXT_OK_BUTTON])
321 g.add(bb, 0, 2, growx = 1)
322 return bb.buttonPressed(g.runOnce(None, None))
323 elif type == "yesno":
324 if default and default == "no":
325 buttons = [TEXT_NO_BUTTON, TEXT_YES_BUTTON]
326 else:
327 buttons = [TEXT_YES_BUTTON, TEXT_NO_BUTTON]
328
329 bb = ButtonBar(self.screen, buttons)
330 g.add(bb, 0, 2, growx = 1)
331 rc = bb.buttonPressed(g.runOnce(None, None))
332
333 if rc == "yes":
334 return 1
335 else:
336 return 0
337 elif type == "custom":
338 buttons = []
339 idx = 0
340
341 for button in custom_buttons:
342 buttons.append(string.replace(button, "_", ""))
343
344 bb = ButtonBar(self.screen, buttons)
345 g.add(bb, 0, 2, growx = 1)
346 rc = bb.buttonPressed(g.runOnce(None, None))
347
348 for b in buttons:
349 if string.lower(b) == rc:
350 return idx
351 idx += 1
352
353 return 0
354 else:
355 return self.messageWindow(title, text, type, default, custom_icon,
356 custom_buttons)
357
358 def createRepoWindow(self):
359 self.messageWindow(_("Error"),
360 _("Repository editing is not available in text mode."))
361
362 def editRepoWindow(self, repoObj):
363 self.messageWindow(_("Error"),
364 _("Repository editing is not available in text mode."))
365
366 def entryWindow(self, title, text, prompt, entrylength = None):
367 (res, value) = EntryWindow(self.screen, title, text, [prompt])
368 if res == "cancel":
369 return None
370 r = value[0]
371 r.strip()
372 return r
373
374 def getLuksPassphrase(self, passphrase = "", preexist = False):
375 w = LuksPassphraseWindow(self.screen, passphrase = passphrase,
376 preexist = preexist)
377 rc = w.run()
378 w.pop()
379 return rc
380
381 def passphraseEntryWindow(self, device):
382 w = PassphraseEntryWindow(self.screen, device)
383 (passphrase, isglobal) = w.run()
384 w.pop()
385 return (passphrase, isglobal)
386
387 def enableNetwork(self):
388 if len(self.anaconda.id.network.netdevices) == 0:
389 return False
390 from netconfig_text import NetworkConfiguratorText
391 w = NetworkConfiguratorText(self.screen, self.anaconda)
392 ret = w.run()
393 return ret != INSTALL_BACK
394
395 def kickstartErrorWindow(self, text):
396 s = _("The following error was found while parsing the "
397 "kickstart configuration file:\n\n%s") %(text,)
398 self.messageWindow(_("Error Parsing Kickstart Config"),
399 s,
400 type = "custom",
401 custom_buttons = [("_Reboot")],
402 custom_icon="error")
403
404 def mainExceptionWindow(self, shortText, longTextFile):
405 from meh.ui.text import MainExceptionWindow
406 log.critical(shortText)
407 exnWin = MainExceptionWindow(shortText, longTextFile, screen=self.screen)
408 return exnWin
409
410 def saveExceptionWindow(self, accountManager, signature, *args, **kwargs):
411 from meh.ui.text import SaveExceptionWindow
412 network.saveExceptionEnableNetwork(self)
413 win = SaveExceptionWindow (accountManager, signature, screen=self.screen,
414 *args, **kwargs)
415 win.run()
416
417 def waitWindow(self, title, text):
418 return WaitWindow(self.screen, title, text)
419
420 def beep(self):
421 # no-op. could call newtBell() if it was bound
422 pass
423
424 def drawFrame(self):
425 self.screen.drawRootText (0, 0, self.screen.width * " ")
426 if productArch:
427 self.screen.drawRootText (0, 0, _("Welcome to %(productName)s for %(productArch)s") % {'productName': productName, 'productArch': productArch})
428 else:
429 self.screen.drawRootText (0, 0, _("Welcome to %s") % productName)
430
431 self.screen.pushHelpLine(_(" <Tab>/<Alt-Tab> between elements | <Space> selects | <F12> next screen"))
432
433 def setScreen(self, screen):
434 self.screen = screen
435
436 def shutdown(self):
437 self.screen.finish()
438 self.screen = None
439
440 def suspend(self):
441 self.screen.suspend()
442
443 def resume(self):
444 self.screen.resume()
445
446 def __init__(self):
447 InstallInterfaceBase.__init__(self)
448 signal.signal(signal.SIGINT, signal.SIG_IGN)
449 signal.signal(signal.SIGTSTP, signal.SIG_IGN)
450 self.screen = SnackScreen()
451 self._inconsistentLVMAnswers = {}
452
453 def __del__(self):
454 if self.screen:
455 self.screen.finish()
456
457 def isRealConsole(self):
458 """Returns True if this is a _real_ console that can do things, False
459 for non-real consoles such as serial, i/p virtual consoles or xen."""
460 if flags.serial or flags.virtpconsole:
461 return False
462 if isys.isPseudoTTY(0):
463 return False
464 if isys.isVioConsole():
465 return False
466 return True
467
468 def resetInitializeDiskQuestion(self):
469 pass
470
471 def questionInitializeDisk(self, path, description, size, details=""):
472 if not path:
473 return False
474 return True
475
476 def resetReinitInconsistentLVMQuestion(self):
477 self._inconsistentLVMAnswers = {}
478
479 def questionReinitInconsistentLVM(self, pv_names=None, lv_name=None, vg_name=None):
480
481 retVal = False # The less destructive default
482 allSet = frozenset(["all"])
483
484 if not pv_names or (lv_name is None and vg_name is None):
485 return retVal
486
487 # We are caching answers so that we don't ask for ignoring
488 # in each storage.reset() again (note that reinitialization is
489 # done right after confirmation in dialog, not as a planned
490 # action).
491 key = frozenset(pv_names)
492 if key in self._inconsistentLVMAnswers:
493 log.info("UI not asking about disk initialization, "
494 "using cached answer: %s" % self._inconsistentLVMAnswers[key])
495 return self._inconsistentLVMAnswers[key]
496 elif allSet in self._inconsistentLVMAnswers:
497 log.info("UI not asking about disk initialization, "
498 "using cached answer: %s" % self._inconsistentLVMAnswers[allSet])
499 return self._inconsistentLVMAnswers[allSet]
500
501 if vg_name is not None:
502 message = "Volume Group %s" % vg_name
503 elif lv_name is not None:
504 message = "Logical Volume %s" % lv_name
505
506 na = {'msg': message, 'pvs': ", ".join(pv_names)}
507 rc = self.messageWindow(_("Warning"),
508 _("Error processing LVM.\n"
509 "There is inconsistent LVM data on %(msg)s. You can "
510 "reinitialize all related PVs (%(pvs)s) which will erase "
511 "the LVM metadata, or ignore which will preserve the "
512 "contents. This action may also be applied to all other "
513 "PVs with inconsistent metadata.") % na,
514 type="custom",
515 custom_buttons = [ _("_Ignore"),
516 _("Ignore _all"),
517 _("_Re-initialize"),
518 _("Re-ini_tialize all") ],
519 custom_icon="question")
520 if rc == 0:
521 retVal = False
522 elif rc == 1:
523 key = allSet
524 retVal = False
525 elif rc == 2:
526 retVal = True
527 elif rc == 3:
528 key = allSet
529 retVal = True
530
531 self._inconsistentLVMAnswers[key] = retVal
532 return retVal
533
534 def run(self, anaconda):
535 self.anaconda = anaconda
536 instLang = anaconda.id.instLanguage
537
538 if instLang.getFontFile(instLang.instLang) == "none":
539 if not anaconda.isKickstart:
540 ButtonChoiceWindow(self.screen, "Language Unavailable",
541 "%s display is unavailable in text mode. "
542 "The installation will continue in "
543 "English." % (instLang.instLang,),
544 buttons=[TEXT_OK_BUTTON])
545
546 if not self.isRealConsole():
547 self.screen.suspendCallback(spawnShell, self.screen)
548
549 # drop into the python debugger on ctrl-z if we're running in test mode
550 if flags.debug:
551 self.screen.suspendCallback(debugSelf, self.screen)
552
553 self.instLanguage = anaconda.id.instLanguage
554
555 # draw the frame after setting up the fallback
556 self.drawFrame()
557
558 lastrc = INSTALL_OK
559 (step, instance) = anaconda.dispatch.currentStep()
560 while step:
561 (file, classNames) = stepToClasses[step]
562
563 if type(classNames) != type(()):
564 classNames = (classNames,)
565
566 if lastrc == INSTALL_OK:
567 step = 0
568 else:
569 step = len(classNames) - 1
570
571 while step >= 0 and step < len(classNames):
572 # reget the args. they could change (especially direction)
573 (foo, args) = anaconda.dispatch.currentStep()
574 nextWindow = None
575
576 while 1:
577 try:
578 found = imputil.imp.find_module(file)
579 loaded = imputil.imp.load_module(classNames[step],
580 found[0], found[1],
581 found[2])
582 nextWindow = loaded.__dict__[classNames[step]]
583 break
584 except ImportError, e:
585 rc = ButtonChoiceWindow(self.screen, _("Error!"),
586 _("An error occurred when attempting "
587 "to load an installer interface "
588 "component.\n\nclassName = %s")
589 % (classNames[step],),
590 buttons=[_("Exit"), _("Retry")])
591
592 if rc == string.lower(_("Exit")):
593 sys.exit(0)
594
595 win = nextWindow()
596
597 #log.info("TUI running step %s (class %s, file %s)" %
598 #(step, file, classNames))
599
600 rc = win(self.screen, instance)
601
602 if rc == INSTALL_NOOP:
603 rc = lastrc
604
605 if rc == INSTALL_BACK:
606 step = step - 1
607 anaconda.dispatch.dir = DISPATCH_BACK
608 elif rc == INSTALL_OK:
609 step = step + 1
610 anaconda.dispatch.dir = DISPATCH_FORWARD
611
612 lastrc = rc
613
614 if step == -1:
615 if not anaconda.dispatch.canGoBack():
616 ButtonChoiceWindow(self.screen, _("Cancelled"),
617 _("I can't go to the previous step "
618 "from here. You will have to try "
619 "again."),
620 buttons=[_("OK")])
621 anaconda.dispatch.gotoPrev()
622 else:
623 anaconda.dispatch.gotoNext()
624
625 (step, args) = anaconda.dispatch.currentStep()
626
627 self.screen.finish()
628
629 def setSteps(self, anaconda):
630 anaconda.dispatch.skipStep("filtertype", permanent=1)
631 anaconda.dispatch.skipStep("filter", permanent=1)
632 anaconda.dispatch.skipStep("cleardiskssel", permanent=1)
633 anaconda.dispatch.skipStep("group-selection", permanent=1)
634
635 def killSelf(screen):
636 screen.finish()
637 os._exit(0)
638
639 def debugSelf(screen):
640 screen.suspend()
641 import pdb
642 try:
643 pdb.set_trace()
644 except:
645 sys.exit(-1)
646 screen.resume()
647
648 def spawnShell(screen):
649 screen.suspend()
650 print("\n\nType <exit> to return to the install program.\n")
651 if os.path.exists("/bin/sh"):
652 iutil.execConsole()
653 else:
654 print("Unable to find /bin/sh to execute! Not starting shell")
655 time.sleep(5)
656 screen.resume()

admin@koozali.org
ViewVC Help
Powered by ViewVC 1.2.1 RSS 2.0 feed