Package pyanaconda :: Package textw :: Module add_drive_text
[hide private]
[frames] | no frames]

Source Code for Module pyanaconda.textw.add_drive_text

  1  # 
  2  # Copyright (C) 2010  Red Hat, Inc.  All rights reserved. 
  3  # 
  4  # This program is free software; you can redistribute it and/or modify 
  5  # it under the terms of the GNU General Public License as published by 
  6  # the Free Software Foundation; either version 2 of the License, or 
  7  # (at your option) any later version. 
  8  # 
  9  # This program is distributed in the hope that it will be useful, 
 10  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 11  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 12  # GNU General Public License for more details. 
 13  # 
 14  # You should have received a copy of the GNU General Public License 
 15  # along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 16  # 
 17   
 18  from pyanaconda import iutil 
 19  from pyanaconda import network 
 20  from pyanaconda.storage import iscsi 
 21  from pyanaconda.storage import fcoe 
 22  from pyanaconda.storage import zfcp 
 23  from snack import * 
 24  from constants_text import * 
 25  from pyanaconda.constants import * 
 26  import pyanaconda.partIntfHelpers as pih  
 27   
 28  import gettext 
 29  _ = lambda x: gettext.ldgettext("anaconda", x) 
 30   
 31  import logging 
 32  log = logging.getLogger("anaconda") 
33 34 # iSCSI Wizard classes and helpers 35 36 -class GridEntry(object):
37 - def __init__(self, text, disabled=False, password=False, width=20):
38 self.text = text 39 self.disabled = disabled 40 self.password = password 41 self.width = width
42
43 -class iSCSITextWizard(pih.iSCSIWizard):
44 - def __init__(self, screen):
45 self.screen = screen 46 self.entry_target_ip = None 47 self.entry_initiator = None 48 self.entry_disc_username = None 49 self.entry_disc_password = None 50 self.entry_disc_r_username = None 51 self.entry_disc_r_password = None 52 self.entry_login_username = None 53 self.entry_login_password = None 54 self.entry_login_r_username = None 55 self.entry_login_r_password = None 56 self.listbox_disc = None 57 self.listbox_login = None 58 self.listbox_nodes = None
59 60 @staticmethod
61 - def _auth_entries(cred_type):
62 all_entries = [ 63 GridEntry(_("CHAP Username:")), 64 GridEntry(_("CHAP Password:"), password=True), 65 GridEntry(_("Reverse CHAP Username:")), 66 GridEntry(_("Reverse CHAP Password:"), password=True) 67 ] 68 69 entries = [None for i in range(4)] 70 if cred_type == pih.CRED_ONE[0]: 71 entries = all_entries[0:2] + [None for i in range(2)] 72 elif cred_type == pih.CRED_BOTH[0]: 73 entries = all_entries 74 return entries
75 76 @staticmethod
77 - def _build_grid(grid_entries):
78 entries = [] 79 grid = Grid(2, len(grid_entries)) 80 for (i, ge) in enumerate(grid_entries): 81 if ge: 82 grid.setField(Label(ge.text), 0, i) 83 entry = Entry(ge.width, password=ge.password) 84 if ge.disabled: 85 entry.setFlags(FLAG_DISABLED, FLAGS_SET) 86 grid.setField(entry, 1, i) 87 else: 88 entry = None 89 # we want Nones in grid_entries result in Nones in return value 90 entries.append(entry) 91 return (grid, entries)
92 93 @staticmethod
94 - def _value_when(entry):
95 return entry.value() if entry else None
96
97 - def _discovery_auth_dialog(self):
98 if self.listbox_disc.current() == pih.CRED_NONE[0]: 99 # we need not collect anything 100 return True 101 102 grid = GridForm(self.screen, _("iSCSI Discovery Credentials"), 1, 3) 103 grid.add(TextboxReflowed(50, 104 _("Please enter the iSCSI " 105 "discovery credentials.")), 106 0, 0) 107 auth_entries = self._auth_entries(self.listbox_disc.current()) 108 (basic_grid, entries) = self._build_grid(auth_entries) 109 (self.entry_disc_username, 110 self.entry_disc_password, 111 self.entry_disc_r_username, 112 self.entry_disc_r_password) = entries 113 114 grid.add(basic_grid, 0, 1, padding=(0, 1, 0, 1)) 115 116 grid.buttons = ButtonBar(self.screen, 117 [TEXT_OK_BUTTON,TEXT_CANCEL_BUTTON]) 118 grid.add(grid.buttons, 0, 2, padding=(0, 1, 0, -1)) 119 120 return self._run_grid(grid)
121
122 - def _discovery_setup_dialog(self, initiator, initiator_set):
123 grid = GridForm(self.screen, _("iSCSI Discovery"), 1, 7) 124 header_text = TextboxReflowed(60, 125 _("To use iSCSI disks, you must provide " 126 "the address of your iSCSI target and " 127 "the iSCSI initiator name you've " 128 "configured for your host.")) 129 grid.add(header_text, 0, 0) 130 131 entry_list = [ 132 GridEntry(_("Target IP Address:"), width=40), 133 GridEntry(_("iSCSI Initiator Name:"), 134 disabled=initiator_set, 135 width=40) 136 ] 137 (basic_grid, (self.entry_target_ip, self.entry_initiator)) = \ 138 self._build_grid(entry_list) 139 self.entry_initiator.set(initiator) 140 grid.add(basic_grid, 0, 1) 141 142 grid.add(TextboxReflowed(60, 143 _("What kind of iSCSI discovery " 144 "authentication do you wish to perform:")), 145 0, 2, padding=(0, 1, 0, 0)) 146 147 self.listbox_disc = Listbox(3, scroll=1) 148 self.listbox_disc.append(*reversed(pih.CRED_NONE)) 149 self.listbox_disc.append(*reversed(pih.CRED_ONE)) 150 self.listbox_disc.append(*reversed(pih.CRED_BOTH)) 151 grid.add(self.listbox_disc, 0, 3) 152 153 grid.add(TextboxReflowed(60, 154 _("What kind of iSCSI login authentication " 155 "do you wish to perform:")), 156 0, 4, padding=(0, 1, 0, 0)) 157 158 self.listbox_login = Listbox(3, scroll=1) 159 self.listbox_login.append(*reversed(pih.CRED_NONE)) 160 self.listbox_login.append(*reversed(pih.CRED_ONE)) 161 self.listbox_login.append(*reversed(pih.CRED_BOTH)) 162 self.listbox_login.append(*reversed(pih.CRED_REUSE)) 163 grid.add(self.listbox_login, 0, 5) 164 165 grid.buttons = ButtonBar(self.screen, 166 [TEXT_OK_BUTTON, TEXT_CANCEL_BUTTON]) 167 grid.add(grid.buttons, 0, 6, padding=(0, 1, 0, -1)) 168 169 return self._run_grid(grid)
170
171 - def _run_grid(self, grid):
172 result = grid.run() 173 button = grid.buttons.buttonPressed(result) 174 self.screen.popWindow() 175 return True if button == TEXT_OK_CHECK else False
176
177 - def destroy_dialogs(self):
178 pass
179
180 - def display_discovery_dialog(self, initiator, initiator_set):
181 # this is in fact two dialogs here due to limited screen space in TUI 182 return self._discovery_setup_dialog(initiator, initiator_set) and \ 183 self._discovery_auth_dialog()
184
185 - def display_login_dialog(self):
186 # in TUI, the login credentials are asked for with nodes list, so this 187 # should never stop us: 188 return True
189
190 - def display_nodes_dialog(self, found_nodes):
191 grid_height = 4 192 basic_grid = None 193 if self.listbox_login.current() not in \ 194 (pih.CRED_NONE[0], pih.CRED_REUSE[0]): 195 auth_entries = self._auth_entries(self.listbox_login.current()) 196 (basic_grid, entries) = self._build_grid(auth_entries) 197 (self.entry_login_username, 198 self.entry_login_password, 199 self.entry_login_r_username, 200 self.entry_login_r_password) = entries 201 202 grid_height += 1 203 204 grid = GridForm(self.screen, _("iSCSI Discovered Nodes"), 1, 5) 205 grid.add(TextboxReflowed(50, 206 _("Check the nodes you wish to log into:")), 207 0, 0) 208 209 listbox = CheckboxTree(5, scroll=1) 210 # unfortunately, Listbox.add won't accept node directly as the second 211 # argument, we have to remember the list and use an index 212 for i, node in enumerate(found_nodes): 213 listbox.append(node.name, i, selected=True) 214 grid.add(listbox, 0, 1, padding=(0, 1, 0, 1)) 215 216 if basic_grid: 217 grid.add(TextboxReflowed(60, 218 _("Please enter iSCSI login credentials " 219 "for the selected nodes:")), 220 0, 2) 221 grid.add(basic_grid, 0, 3, padding=(0, 1, 0, 1)) 222 223 grid.buttons = ButtonBar(self.screen, 224 [TEXT_OK_BUTTON, TEXT_CANCEL_BUTTON]) 225 grid.add(grid.buttons, 0, 4, padding=(0, 0, 0, -1)) 226 227 rc = self._run_grid(grid) 228 selected_nodes = [node for (i, node) in enumerate(found_nodes) 229 if i in listbox.getSelection()] 230 return (rc, selected_nodes)
231
232 - def display_success_dialog(self, success_nodes, fail_nodes, fail_reason):
233 buttons = [TEXT_OK_BUTTON] 234 msg = _("Successfully logged into all the selected nodes.") 235 msg_reason = _("Reason:") 236 if fail_nodes: 237 buttons.append(TEXT_RETRY_BUTTON) 238 msg = _("Could not log into the following nodes:\n") 239 msg = reduce(lambda s1, s2: "%s\n%s" % (s1, s2), fail_nodes, msg) 240 if fail_reason: 241 msg = "%s\n\n%s\n%s" % (msg, msg_reason, fail_reason) 242 243 rc = ButtonChoiceWindow(self.screen, 244 _("iSCSI Login Results"), 245 msg, 246 buttons) 247 return True if rc == TEXT_OK_CHECK else False
248
249 - def get_discovery_dict(self):
250 251 dct = { 252 'username' : self._value_when(self.entry_disc_username), 253 'password' : self._value_when(self.entry_disc_password), 254 'r_username' : self._value_when(self.entry_disc_r_username), 255 'r_password' : self._value_when(self.entry_disc_r_password) 256 } 257 entered_ip = self.entry_target_ip.value() 258 (ip, port) = pih.parse_ip(entered_ip) 259 dct["ipaddr"] = ip 260 dct["port"] = port 261 return dct
262
263 - def get_initiator(self):
264 return self.entry_initiator.value()
265
266 - def get_login_dict(self):
267 auth_kind = self.listbox_login.current() 268 if auth_kind == pih.CRED_REUSE[0]: 269 discovery_dict = self.get_discovery_dict() 270 dct = dict((k,discovery_dict[k]) for k in discovery_dict if k in 271 ['username', 272 'password', 273 'r_username', 274 'r_password']) 275 else: 276 dct = { 277 'username' : self._value_when(self.entry_login_username), 278 'password' : self._value_when(self.entry_login_password), 279 'r_username' : self._value_when(self.entry_login_r_username), 280 'r_password' : self._value_when(self.entry_login_r_password) 281 } 282 283 return dct
284
285 - def set_initiator(self, initiator, initiator_set):
286 pass
287
288 # general add drive stuff 289 290 -class addDriveDialog(object):
291 - def __init__(self, anaconda):
292 self.anaconda = anaconda
293
294 - def addDriveDialog(self, screen):
295 newdrv = [] 296 if iscsi.has_iscsi(): 297 newdrv.append("Add iSCSI target") 298 if iutil.isS390(): 299 newdrv.append( "Add zFCP LUN" ) 300 if fcoe.has_fcoe(): 301 newdrv.append("Add FCoE SAN") 302 303 if len(newdrv) == 0: 304 return INSTALL_BACK 305 306 (button, choice) = ListboxChoiceWindow(screen, 307 _("Advanced Storage Options"), 308 _("How would you like to modify " 309 "your drive configuration?"), 310 newdrv, 311 [ TEXT_OK_BUTTON, TEXT_BACK_BUTTON], 312 width=55, height=3) 313 314 if button == TEXT_BACK_CHECK: 315 return INSTALL_BACK 316 if newdrv[choice] == "Add zFCP LUN": 317 try: 318 return self.addZFCPDriveDialog(screen) 319 except ValueError as e: 320 ButtonChoiceWindow(screen, _("Error"), str(e)) 321 return INSTALL_BACK 322 elif newdrv[choice] == "Add FCoE SAN": 323 try: 324 return self.addFcoeDriveDialog(screen) 325 except ValueError as e: 326 ButtonChoiceWindow(screen, _("Error"), str(e)) 327 return INSTALL_BACK 328 else: 329 try: 330 return self.addIscsiDriveDialog(screen) 331 except (ValueError, IOError) as e: 332 ButtonChoiceWindow(screen, _("Error"), str(e)) 333 return INSTALL_BACK
334
335 - def addZFCPDriveDialog(self, screen):
336 (button, entries) = EntryWindow(screen, 337 _("Add FCP Device"), 338 _("zSeries machines can access industry-standard SCSI devices via Fibre Channel (FCP). You need to provide a 16 bit device number, a 64 bit World Wide Port Name (WWPN), and a 64 bit FCP LUN for each device."), 339 prompts = [ "Device number", 340 "WWPN", 341 "FCP LUN" ] ) 342 if button == TEXT_CANCEL_CHECK: 343 return INSTALL_BACK 344 345 devnum = entries[0].strip() 346 wwpn = entries[1].strip() 347 fcplun = entries[2].strip() 348 349 # This may throw a value error, which gets handled by addDriveDialog() 350 zfcp.ZFCP().addFCP(devnum, wwpn, fcplun) 351 352 return INSTALL_OK
353
354 - def addFcoeDriveDialog(self, screen):
355 netdevs = self.anaconda.network.netdevices 356 devs = netdevs.keys() 357 devs.sort() 358 359 if not devs: 360 ButtonChoiceWindow(screen, _("Error"), 361 _("No network cards present.")) 362 return INSTALL_BACK 363 364 grid = GridFormHelp(screen, _("Add FCoE SAN"), "fcoeconfig", 365 1, 4) 366 367 tb = TextboxReflowed(60, 368 _("Select which NIC is connected to the FCoE SAN.")) 369 grid.add(tb, 0, 0, anchorLeft = 1, padding = (0, 0, 0, 1)) 370 371 interfaceList = Listbox(height=len(devs), scroll=1) 372 for dev in devs: 373 hwaddr = netdevs[dev].get("HWADDR") 374 if hwaddr: 375 desc = "%s - %.50s" % (dev, hwaddr) 376 else: 377 desc = dev 378 379 interfaceList.append(desc, dev) 380 381 interfaceList.setCurrent(devs[0]) 382 grid.add(interfaceList, 0, 1, padding = (0, 1, 0, 0)) 383 384 dcbCheckbox = Checkbox(_("Use DCB"), 1) 385 grid.add(dcbCheckbox, 0, 2, anchorLeft = 1) 386 387 buttons = ButtonBar(screen, [TEXT_OK_BUTTON, TEXT_BACK_BUTTON] ) 388 grid.add(buttons, 0, 3, anchorLeft = 1, growx = 1) 389 390 result = grid.run() 391 if buttons.buttonPressed(result) == TEXT_BACK_CHECK: 392 screen.popWindow() 393 return INSTALL_BACK 394 395 nic = interfaceList.current() 396 dcb = dcbCheckbox.selected() 397 398 fcoe.fcoe().addSan(nic=nic, dcb=dcb, 399 intf=self.anaconda.intf) 400 401 screen.popWindow() 402 return INSTALL_OK
403
404 - def addIscsiDriveDialog(self, screen):
405 if not network.hasActiveNetDev(): 406 ButtonChoiceWindow(screen, _("Error"), 407 "Must have a network configuration set up " 408 "for iSCSI config. Please boot with " 409 "'linux asknetwork'") 410 log.info("addIscsiDriveDialog(): early exit, network disabled.") 411 return INSTALL_BACK 412 413 wizard = iSCSITextWizard(screen) 414 login_ok_nodes = pih.drive_iscsi_addition(self.anaconda, wizard) 415 if len(login_ok_nodes): 416 return INSTALL_OK 417 log.info("addIscsiDriveDialog(): no new nodes added") 418 return INSTALL_BACK
419