Exemplo n.º 1
0
    def _init_win(self, window):
        '''Require at least 70 columns and 6 lines to fit current needs for
        display of partitions and slices. Builds two inner ScrollWindows for
        displaying/editing the data.

        '''
        if self.area.columns < 70:
            raise ValueError("Insufficient space - area.columns < 70")
        if self.area.lines < 6:
            raise ValueError("Insufficient space - area.lines < 6")
        self.win_width = (self.area.columns - DiskWindow.DEAD_ZONE
                          + DiskWindow.SCROLL_PAD) / 2

        super(DiskWindow, self)._init_win(window)

        win_area = WindowArea(self.area.lines - 1, self.win_width, 2, 0)
        win_area.scrollable_lines = self.area.lines - 2
        self.left_win = ScrollWindow(win_area, window=self, add_obj=False)
        self.left_win.color = None
        self.left_win.highlight_color = None
        win_area.x_loc = self.win_width + DiskWindow.DEAD_ZONE
        win_area.scrollable_lines = 2 * MAX_EXT_PARTS
        self.right_win = ScrollWindow(win_area, window=self, add_obj=False)
        self.right_win.color = None
        self.right_win.highlight_color = None
Exemplo n.º 2
0
 def _show(self):
     super(NSNISAuto, self)._show()
     if self.nameservice.nameservice != 'NIS':
         raise SkipException
     y_loc = self._paint_opening()
     y_loc += self.center_win.add_paragraph(self.intro2, y_loc)
     y_loc += 1
     ynlist = [_('Find one'),
               _('Specify one')]
     area = WindowArea(x_loc=0, y_loc=y_loc,
                       scrollable_lines=len(ynlist) + 1)
     area.lines = self.win_size_y - (y_loc + 1)
     area.columns = self.win_size_x
     self.scroll_region = ScrollWindow(area, window=self.center_win)
     y_loc += 1  # blank line
     # add the entries to the screen
     for idx, yon in enumerate(ynlist):
         y_loc += 1
         win_area = WindowArea(lines=1, columns=textwidth(yon) + 1,
                               y_loc=idx, x_loc=INDENT)
         ListItem(win_area, window=self.scroll_region, text=yon,
                  data_obj=yon)
         self.main_win.do_update()
     self.center_win.activate_object(self.scroll_region)
     self.scroll_region.activate_object_force(self.cur_nisnschoice_idx,
                                              force_to_top=True)
     y_loc += 1  # blank line
     self.center_win.add_paragraph(self.intro3, y_loc)
Exemplo n.º 3
0
    def _show(self):
        '''Prepare a text summary and display it to the user in a ScrollWindow
        
        '''

        global LOGGER
        LOGGER = logging.getLogger(INSTALL_LOGGER_NAME)

        self.sysconfig = solaris_install.sysconfig.profile.from_engine()

        y_loc = 1
        y_loc += self.center_win.add_paragraph(SummaryScreen.PARAGRAPH, y_loc)

        y_loc += 1
        summary_text = self.build_summary()

        LOGGER.info(
            "The following configuration is used for "
            "installation: %s\n", summary_text)
        # Wrap the summary text, accounting for the INDENT (used below in
        # the call to add_paragraph)
        max_chars = self.win_size_x - SummaryScreen.INDENT - 1
        summary_text = convert_paragraph(summary_text, max_chars)
        area = WindowArea(x_loc=0,
                          y_loc=y_loc,
                          scrollable_lines=(len(summary_text) + 1))
        area.lines = self.win_size_y - y_loc
        area.columns = self.win_size_x
        scroll_region = ScrollWindow(area, window=self.center_win)
        scroll_region.add_paragraph(summary_text, start_x=SummaryScreen.INDENT)

        self.center_win.activate_object(scroll_region)
Exemplo n.º 4
0
    def display_help(self):
        '''Display the single file help screen'''
        # customize header
        help_header = "%s: %s"
        terminalui.LOGGER.debug("self.screen is =%s", self.screen)
        if self.screen in self.help_dict:
            help_header = help_header % (_("Help"),
                                         self.help_dict[self.screen][1])
            help_text = self.get_help_text(self.help_dict[self.screen][0])
        else:
            help_header = help_header % (_("Help"), _("Not Available"))
            help_text = _("Help for this screen is not available")

        self.main_win.set_header_text(help_header)

        help_text = convert_paragraph(help_text, self.win_size_x - 5)
        terminalui.LOGGER.debug("help_text #lines=%d, text is \n%s",
                                len(help_text), help_text)
        area = WindowArea(x_loc=0,
                          y_loc=1,
                          scrollable_lines=(len(help_text) + 1))
        area.lines = self.win_size_y - 1
        area.columns = self.win_size_x
        self.scroll_region = ScrollWindow(area, window=self.center_win)
        self.scroll_region.add_paragraph(help_text, start_x=(area.x_loc + 3))
        self.center_win.activate_object(self.scroll_region)
Exemplo n.º 5
0
 def _show(self):
     ''' called upon display of a screen '''
     super(NSDNSChooser, self)._show()
     y_loc = self._paint_opening()
     LOGGER.debug(self.nameservice)
     # allow the user to choose DNS or not
     ynlist = [_('Configure DNS'), _('Do not configure DNS')]
     area = WindowArea(x_loc=0,
                       y_loc=y_loc,
                       scrollable_lines=len(ynlist) + 1)
     area.lines = self.win_size_y - (y_loc + 1)
     area.columns = self.win_size_x
     self.scroll_region_dns = ScrollWindow(area, window=self.center_win)
     # add the entries to the screen
     for idx, yon in enumerate(ynlist):
         win_area = WindowArea(1, textwidth(yon) + 1, idx, INDENT)
         ListItem(win_area,
                  window=self.scroll_region_dns,
                  text=yon,
                  data_obj=yon)
     # finalize positioning
     self.main_win.do_update()
     self.center_win.activate_object(self.scroll_region_dns)
     self.scroll_region_dns.activate_object_force(self.cur_dnschoice_idx,
                                                  force_to_top=True)
Exemplo n.º 6
0
 def _show(self):
     ''' called upon display of a screen '''
     super(NSAltChooser, self)._show()
     y_loc = self._paint_opening()
     LOGGER.debug(self.nameservice)
     # allow the user to select an alternate name service
     area = WindowArea(x_loc=0,
                       y_loc=y_loc,
                       scrollable_lines=len(NameService.USER_CHOICE_LIST) +
                       1)
     area.lines = self.win_size_y - (y_loc + 1)
     area.columns = self.win_size_x
     self.scroll_region = ScrollWindow(area, window=self.center_win)
     # add the entries to the screen
     menu_item_max_width = self.win_size_x - NameService.SCROLL_SIZE
     for idx, nsn in enumerate(NameService.USER_CHOICE_LIST):
         y_loc += 1
         hilite = min(menu_item_max_width, textwidth(nsn) + 1)
         win_area = WindowArea(1, hilite, idx, INDENT)
         ListItem(win_area,
                  window=self.scroll_region,
                  text=nsn,
                  data_obj=nsn)
     # finalize positioning
     self.main_win.do_update()
     self.center_win.activate_object(self.scroll_region)
     self.scroll_region.activate_object_force(self.cur_nschoice_idx,
                                              force_to_top=True)
Exemplo n.º 7
0
    def _show(self):
        '''Prepare a text summary and display it to the user in a ScrollWindow
        
        '''

        global LOGGER
        LOGGER = logging.getLogger(INSTALL_LOGGER_NAME)
        
        self.sysconfig = solaris_install.sysconfig.profile.from_engine()
        
        y_loc = 1
        y_loc += self.center_win.add_paragraph(SummaryScreen.PARAGRAPH, y_loc)
        
        y_loc += 1
        summary_text = self.build_summary()

        LOGGER.info("The following configuration is used for "
                    "installation: %s\n", summary_text)
        # Wrap the summary text, accounting for the INDENT (used below in
        # the call to add_paragraph)
        max_chars = self.win_size_x - SummaryScreen.INDENT - 1
        summary_text = convert_paragraph(summary_text, max_chars)
        area = WindowArea(x_loc=0, y_loc=y_loc,
                          scrollable_lines=(len(summary_text) + 1))
        area.lines = self.win_size_y - y_loc
        area.columns = self.win_size_x
        scroll_region = ScrollWindow(area, window=self.center_win)
        scroll_region.add_paragraph(summary_text, start_x=SummaryScreen.INDENT)
        
        self.center_win.activate_object(scroll_region)
Exemplo n.º 8
0
    def test_active_object(self):
        '''Test that arrow key changes active object'''
        lines = 4
        extra_lines = 9
        scroll_win = ScrollWindow(WindowArea(lines,
                                             70,
                                             0,
                                             0,
                                             scrollable_lines=lines +
                                             extra_lines),
                                  color_theme=ColorTheme(force_bw=True))
        scroll_win.active_object = 0
        myobj0 = MockEditField()
        myobj0.area = MockInnerWin()
        myobj0.area.y_loc = 1
        myobj0.active = True
        myobj1 = MockEditField()
        myobj1.area = MockInnerWin()
        myobj1.area.y_loc = 3
        myobj1.active = False
        scroll_win.objects.append(myobj0)
        scroll_win.objects.append(myobj1)

        key = scroll_win.on_arrow_key(curses.KEY_DOWN)
        self.assertEquals(key, None)
        self.assertEquals(scroll_win.active_object, 1)
Exemplo n.º 9
0
 def test_scroll_no_args(self):
     '''Test that scroll called with no args throws ValueError'''
     scroll_win = ScrollWindow(WindowArea(70, 70, 0, 0,
                                          scrollable_lines=75),
                               color_theme=ColorTheme(force_bw=True))
     self.assertTrue(scroll_win.get_use_vert_scroll_bar())
     self.assertEquals(scroll_win.current_line[0], 0)
     self.assertRaises(ValueError, scroll_win.scroll)
 def test_scroll_no_args(self):
     '''Test that scroll called with no args throws ValueError'''
     scroll_win = ScrollWindow(WindowArea(70, 70, 0, 0,
                               scrollable_lines=75),
                               color_theme=ColorTheme(force_bw=True))
     self.assertTrue(scroll_win.get_use_vert_scroll_bar())
     self.assertEquals(scroll_win.current_line[0], 0)
     self.assertRaises(ValueError, scroll_win.scroll)
 def test_scroll_to_bottom(self):
     '''Test to scroll multiple lines to bottom of scrollarea'''
     lines = 70
     extra_lines = 5
     scroll_win = ScrollWindow(WindowArea(lines, 70, 0, 0, 
                               scrollable_lines=lines + extra_lines),
                               color_theme=ColorTheme(force_bw=True))
     scroll_win.scroll(scroll_to_line=5)
     self.assertTrue(scroll_win.at_bottom())
 def test_scroll_one_col(self):
     '''Test to scroll one column '''
     scroll_win = ScrollWindow(WindowArea(70, 70, 0, 0, 
                               scrollable_columns=75),
                               color_theme=ColorTheme(force_bw=True))
     self.assertTrue(scroll_win.get_use_horiz_scroll_bar())
     self.assertEquals(scroll_win.current_line[1], 0)
     scroll_win.scroll(columns=1)
     self.assertEquals(scroll_win.current_line[1], 1)
 def test_scroll_to_right(self):
     '''Test to scroll multiple columns to right of scrollarea'''
     cols = 70
     extra_cols = 5
     scroll_win = ScrollWindow(WindowArea(70, cols, 0, 0, 
                               scrollable_columns=cols+extra_cols),
                               color_theme=ColorTheme(force_bw=True))
     scroll_win.scroll(scroll_to_column=5)
     self.assertTrue(scroll_win.at_right())
Exemplo n.º 14
0
    def _show(self):
        '''Create a scrollable region and fill it with the install log'''

        self.center_win.border_size = (0, 0)
        self.scroll_area = WindowArea(self.win_size_y, self.win_size_x, 0, 0,
                                      len(self.get_log_data()))
        log = ScrollWindow(self.scroll_area, window=self.center_win)
        log.add_paragraph(self.get_log_data(), 0, 2)
        self.center_win.activate_object(log)
Exemplo n.º 15
0
 def test_scroll_one_line(self):
     '''Test to scroll one line '''
     scroll_win = ScrollWindow(WindowArea(70, 70, 0, 0,
                                          scrollable_lines=75),
                               color_theme=ColorTheme(force_bw=True))
     self.assertTrue(scroll_win.get_use_vert_scroll_bar())
     self.assertEquals(scroll_win.current_line[0], 0)
     scroll_win.scroll(lines=1)
     self.assertEquals(scroll_win.current_line[0], 1)
 def test_scroll_past_left(self):
     '''Test to scroll past left, should end up at left '''
     cols = 70
     extra_cols = 5
     scroll_win = ScrollWindow(WindowArea(70, cols, 0, 0, 
                               scrollable_columns=cols+extra_cols),
                               color_theme=ColorTheme(force_bw=True))
     self.assertTrue(scroll_win.at_left())
     scroll_win.scroll(columns=-3)
     self.assertTrue(scroll_win.at_left())
 def test_scroll_past_top(self):
     '''Test to scroll past top, should end up at top '''
     lines = 70
     extra_lines = 5
     scroll_win = ScrollWindow(WindowArea(lines, 70, 0, 0, 
                               scrollable_lines=lines + extra_lines),
                               color_theme=ColorTheme(force_bw=True))
     self.assertTrue(scroll_win.at_top())
     scroll_win.scroll(lines=-3)
     self.assertTrue(scroll_win.at_top())
Exemplo n.º 18
0
    def test_no_ut_refresh(self):
        '''Ensure deep_refresh is updating nested window screen location '''

        scroll_win = ScrollWindow(WindowArea(60,
                                             70,
                                             0,
                                             0,
                                             scrollable_columns=75),
                                  color_theme=ColorTheme(force_bw=True))
        scroll_win.window = MockInnerWin()
        scroll_win.area.lower_right_y = 20
        scroll_win.area.lower_right_x = 20
        myscroll = ScrollWindow(WindowArea(10, 10, 0, 0,
                                           scrollable_columns=15),
                                color_theme=ColorTheme(force_bw=True))
        myscroll.window = MockInnerWin()
        myscroll.area.lower_right_y = 16
        myscroll.area.lower_right_x = 18
        scroll_win.objects.append(myscroll)
        scroll_win.area.y_loc = 3
        scroll_win.area.x_loc = 5
        abs_y = 12
        abs_x = 15
        scroll_win.latest_yx = (abs_y, abs_x)
        scroll_win.no_ut_refresh()
        self.assertEquals(myscroll.latest_yx[0], scroll_win.area.y_loc + abs_y)
        self.assertEquals(myscroll.latest_yx[1], scroll_win.area.x_loc + abs_x)
    def test_vert_scrollbar_created(self):
        '''Ensure vertical scrollbar is created or not appropriately'''
        scroll_win = ScrollWindow(WindowArea(70, 70, 0, 0, 
                                  scrollable_lines=75),
                                  color_theme=ColorTheme(force_bw=True))
        self.assertTrue(scroll_win.get_use_vert_scroll_bar())

        scroll_win = ScrollWindow(WindowArea(70, 70, 0, 0, 
                                  scrollable_lines=70),
                                  color_theme=ColorTheme(force_bw=True))
        self.assertFalse(scroll_win.get_use_vert_scroll_bar())
    def test_horiz_scrollbar_created(self):
        '''Ensure horizontal scrollbar is created or not appropriately'''
        scroll_win = ScrollWindow(WindowArea(70, 70, 0, 0, 
                                  scrollable_columns=75),
                                  color_theme=ColorTheme(force_bw=True))
        self.assertTrue(scroll_win.get_use_horiz_scroll_bar())

        scroll_win = ScrollWindow(WindowArea(70, 70, 0, 0, 
                                  scrollable_columns=69),
                                  color_theme=ColorTheme(force_bw=True))
        self.assertFalse(scroll_win.get_use_horiz_scroll_bar())
 def test_act_obj_indexerr_not_edge(self):
     '''Test arrow key, active object, IndexError, not at edge'''
     lines = 4
     extra_lines = 9
     scroll_win = ScrollWindow(WindowArea(lines, 70, 0, 0, 
                               scrollable_lines=lines + extra_lines),
                               color_theme=ColorTheme(force_bw=True))
     scroll_win.active_object = 0
     scroll_win.objects.append(object())
     key = scroll_win.on_arrow_key(curses.KEY_DOWN)
     self.assertEquals(scroll_win.current_line[0], 1)
     self.assertEquals(key, None)
Exemplo n.º 22
0
class NSNISAuto(NameService):

    HEADER_TEXT = _("NIS Name Server")
    HELP_DATA = (SCI_HELP + "/%s/nis.txt", HEADER_TEXT)

    def __init__(self, main_win, screen=None):
        super(NSNISAuto, self).__init__(main_win)
        self.intro = \
                _("Specify how to find a name server for this system.")
        self.intro2 = \
                _("Either let the software search for a name server, "
                  "or specify a name server in the following screen.  ")
        self.intro3 = \
                _("The software can find a name server only if that "
                  "server is on the local subnet.")

    def _show(self):
        super(NSNISAuto, self)._show()
        if self.nameservice.nameservice != 'NIS':
            raise SkipException
        y_loc = self._paint_opening()
        y_loc += self.center_win.add_paragraph(self.intro2, y_loc)
        y_loc += 1
        ynlist = [_('Find one'), _('Specify one')]
        area = WindowArea(x_loc=0,
                          y_loc=y_loc,
                          scrollable_lines=len(ynlist) + 1)
        area.lines = self.win_size_y - (y_loc + 1)
        area.columns = self.win_size_x
        self.scroll_region = ScrollWindow(area, window=self.center_win)
        y_loc += 1  # blank line
        # add the entries to the screen
        for idx, yon in enumerate(ynlist):
            y_loc += 1
            win_area = WindowArea(lines=1,
                                  columns=textwidth(yon) + 1,
                                  y_loc=idx,
                                  x_loc=INDENT)
            ListItem(win_area,
                     window=self.scroll_region,
                     text=yon,
                     data_obj=yon)
            self.main_win.do_update()
        self.center_win.activate_object(self.scroll_region)
        self.scroll_region.activate_object_force(self.cur_nisnschoice_idx,
                                                 force_to_top=True)
        y_loc += 1  # blank line
        self.center_win.add_paragraph(self.intro3, y_loc)

    def on_change_screen(self):
        self.cur_nisnschoice_idx = self.scroll_region.active_object
        idx = self.cur_nisnschoice_idx
        self.nameservice.nis_auto = idx
Exemplo n.º 23
0
 def test_scroll_to_right(self):
     '''Test to scroll multiple columns to right of scrollarea'''
     cols = 70
     extra_cols = 5
     scroll_win = ScrollWindow(WindowArea(70,
                                          cols,
                                          0,
                                          0,
                                          scrollable_columns=cols +
                                          extra_cols),
                               color_theme=ColorTheme(force_bw=True))
     scroll_win.scroll(scroll_to_column=5)
     self.assertTrue(scroll_win.at_right())
Exemplo n.º 24
0
 def test_scroll_to_bottom(self):
     '''Test to scroll multiple lines to bottom of scrollarea'''
     lines = 70
     extra_lines = 5
     scroll_win = ScrollWindow(WindowArea(lines,
                                          70,
                                          0,
                                          0,
                                          scrollable_lines=lines +
                                          extra_lines),
                               color_theme=ColorTheme(force_bw=True))
     scroll_win.scroll(scroll_to_line=5)
     self.assertTrue(scroll_win.at_bottom())
Exemplo n.º 25
0
 def _show(self):
     '''Display the static paragraph WELCOME_TEXT and all
        applicable bullet items'''
     sc_options = get_sc_options_from_doc()
     max_width = self.win_size_x - WelcomeScreen.INDENT - 1
     text = convert_paragraph(WelcomeScreen.WELCOME_TEXT, max_width)
     # list configuration groups in a comma-separated list with
     # bullet on first line and indentation on subsequent lines
     grouplist = list()
     if configure_group(SC_GROUP_NETWORK):
         grouplist.append(_("network"))
     elif configure_group(SC_GROUP_IDENTITY):
         grouplist.append(_("system hostname"))
     if configure_group(SC_GROUP_LOCATION):
         grouplist.append(_("time zone"))
     if configure_group(SC_GROUP_DATETIME):
         grouplist.append(_("date and time"))
     if configure_group(SC_GROUP_USERS):
         grouplist.append(_("user and root accounts"))
     if configure_group(SC_GROUP_NS):
         grouplist.append(_("name services"))
     grouplist = ", ".join(grouplist)
     grouplist = convert_paragraph(grouplist,
                                   max_width - len(WelcomeScreen.BULLET))
     for ln in range(len(grouplist)):
         if ln == 0:
             text.append(WelcomeScreen.BULLET + grouplist[ln])
         else:
             text.append(WelcomeScreen.BULLET_INDENT + grouplist[ln])
     # display navigation instructions and profile path
     fmt = {"scprof": sc_options.profile}
     text.extend(convert_paragraph(WelcomeScreen.NAVIPRO_TEXT % fmt,
                                   max_width))
     # indent and align while bulletting
     for bullet in WelcomeScreen.BULLET_ITEMS:
         btext = convert_paragraph(bullet,
                                   max_width - len(WelcomeScreen.BULLET))
         for ln in range(len(btext)):
             if ln == 0:
                 text.append(WelcomeScreen.BULLET + btext[ln])
             else:
                 text.append(WelcomeScreen.BULLET_INDENT + btext[ln])
     # prepare welcome text in entire window for scrolling
     area = WindowArea(x_loc=0, y_loc=1, scrollable_lines=(len(text) + 1))
     area.lines = self.win_size_y - 1
     area.columns = self.win_size_x
     scroll_region = ScrollWindow(area, window=self.center_win)
     scroll_region.add_paragraph(text, start_x=WelcomeScreen.INDENT)
     self.center_win.activate_object(scroll_region)
Exemplo n.º 26
0
class NSAltChooser(NameService):

    HEADER_TEXT = _("Alternate Name Service")
    HELP_DATA = (SCI_HELP + "/%s/name_service.txt", HEADER_TEXT)

    def __init__(self, main_win):
        super(NSAltChooser, self).__init__(main_win)
        self.intro = \
                _("From the list below, select one name service to be "
                  "used by this system. If the desired name service is not "
                  "listed, select None. The selected name service may be "
                  "used in conjunction with DNS.")

    def _show(self):
        ''' called upon display of a screen '''
        super(NSAltChooser, self)._show()
        y_loc = self._paint_opening()
        LOGGER.debug(self.nameservice)
        # allow the user to select an alternate name service
        area = WindowArea(x_loc=0,
                          y_loc=y_loc,
                          scrollable_lines=len(NameService.USER_CHOICE_LIST) +
                          1)
        area.lines = self.win_size_y - (y_loc + 1)
        area.columns = self.win_size_x
        self.scroll_region = ScrollWindow(area, window=self.center_win)
        # add the entries to the screen
        menu_item_max_width = self.win_size_x - NameService.SCROLL_SIZE
        for idx, nsn in enumerate(NameService.USER_CHOICE_LIST):
            y_loc += 1
            hilite = min(menu_item_max_width, textwidth(nsn) + 1)
            win_area = WindowArea(1, hilite, idx, INDENT)
            ListItem(win_area,
                     window=self.scroll_region,
                     text=nsn,
                     data_obj=nsn)
        # finalize positioning
        self.main_win.do_update()
        self.center_win.activate_object(self.scroll_region)
        self.scroll_region.activate_object_force(self.cur_nschoice_idx,
                                                 force_to_top=True)

    def on_change_screen(self):
        ''' called when changes submitted by user for all screens '''
        # Save the chosen index and object when leaving the screen
        self.cur_nschoice_idx = self.scroll_region.active_object
        idx = self.cur_nschoice_idx
        LOGGER.info("on_change_screen NS chosen=%s", idx)
        self.nameservice.nameservice = NameService.CHOICE_LIST[idx]
Exemplo n.º 27
0
 def _show(self):
     '''Display the static paragraph WELCOME_TEXT and all
        applicable bullet items'''
     sc_options = get_sc_options_from_doc()
     max_width = self.win_size_x - WelcomeScreen.INDENT - 1
     text = convert_paragraph(WelcomeScreen.WELCOME_TEXT, max_width)
     # list configuration groups in a comma-separated list with
     # bullet on first line and indentation on subsequent lines
     grouplist = list()
     if configure_group(SC_GROUP_NETWORK):
         grouplist.append(_("network"))
     elif configure_group(SC_GROUP_IDENTITY):
         grouplist.append(_("system hostname"))
     if configure_group(SC_GROUP_LOCATION):
         grouplist.append(_("time zone"))
     if configure_group(SC_GROUP_DATETIME):
         grouplist.append(_("date and time"))
     if configure_group(SC_GROUP_USERS):
         grouplist.append(_("user and root accounts"))
     if configure_group(SC_GROUP_NS):
         grouplist.append(_("name services"))
     grouplist = ", ".join(grouplist)
     grouplist = convert_paragraph(grouplist,
                                   max_width - len(WelcomeScreen.BULLET))
     for ln in range(len(grouplist)):
         if ln == 0:
             text.append(WelcomeScreen.BULLET + grouplist[ln])
         else:
             text.append(WelcomeScreen.BULLET_INDENT + grouplist[ln])
     # display navigation instructions and profile path
     fmt = {"scprof": sc_options.profile}
     text.extend(convert_paragraph(WelcomeScreen.NAVIPRO_TEXT % fmt,
                                   max_width))
     # indent and align while bulletting
     for bullet in WelcomeScreen.BULLET_ITEMS:
         btext = convert_paragraph(bullet,
                                   max_width - len(WelcomeScreen.BULLET))
         for ln in range(len(btext)):
             if ln == 0:
                 text.append(WelcomeScreen.BULLET + btext[ln])
             else:
                 text.append(WelcomeScreen.BULLET_INDENT + btext[ln])
     # prepare welcome text in entire window for scrolling
     area = WindowArea(x_loc=0, y_loc=1, scrollable_lines=(len(text) + 1))
     area.lines = self.win_size_y - 1
     area.columns = self.win_size_x
     scroll_region = ScrollWindow(area, window=self.center_win)
     scroll_region.add_paragraph(text, start_x=WelcomeScreen.INDENT)
     self.center_win.activate_object(scroll_region)
Exemplo n.º 28
0
 def test_act_obj_indexerr_not_edge(self):
     '''Test arrow key, active object, IndexError, not at edge'''
     lines = 4
     extra_lines = 9
     scroll_win = ScrollWindow(WindowArea(lines,
                                          70,
                                          0,
                                          0,
                                          scrollable_lines=lines +
                                          extra_lines),
                               color_theme=ColorTheme(force_bw=True))
     scroll_win.active_object = 0
     scroll_win.objects.append(object())
     key = scroll_win.on_arrow_key(curses.KEY_DOWN)
     self.assertEquals(scroll_win.current_line[0], 1)
     self.assertEquals(key, None)
Exemplo n.º 29
0
class NSDNSChooser(NameService):

    HEADER_TEXT = _("DNS Name Service")
    HELP_DATA = (SCI_HELP + "/%s/name_service.txt", HEADER_TEXT)
    HELP_FORMAT = "%s"

    def __init__(self, main_win):
        super(NSDNSChooser, self).__init__(main_win)
        LOGGER.debug('in NSDNSChooser init')
        self.intro = \
                _("Indicates whether or not the system should use the DNS "
                  "name service.")

    def _show(self):
        ''' called upon display of a screen '''
        super(NSDNSChooser, self)._show()
        y_loc = self._paint_opening()
        LOGGER.debug(self.nameservice)
        # allow the user to choose DNS or not
        ynlist = [_('Configure DNS'), _('Do not configure DNS')]
        area = WindowArea(x_loc=0,
                          y_loc=y_loc,
                          scrollable_lines=len(ynlist) + 1)
        area.lines = self.win_size_y - (y_loc + 1)
        area.columns = self.win_size_x
        self.scroll_region_dns = ScrollWindow(area, window=self.center_win)
        # add the entries to the screen
        for idx, yon in enumerate(ynlist):
            win_area = WindowArea(1, textwidth(yon) + 1, idx, INDENT)
            ListItem(win_area,
                     window=self.scroll_region_dns,
                     text=yon,
                     data_obj=yon)
        # finalize positioning
        self.main_win.do_update()
        self.center_win.activate_object(self.scroll_region_dns)
        self.scroll_region_dns.activate_object_force(self.cur_dnschoice_idx,
                                                     force_to_top=True)

    def on_change_screen(self):
        ''' called when changes submitted by user for all screens '''
        # Save the chosen index and object when leaving the screen
        self.cur_dnschoice_idx = self.scroll_region_dns.active_object
        self.nameservice.dns = (self.cur_dnschoice_idx == 0)
        LOGGER.info("on_change_screen DNS chosen? %s", self.nameservice.dns)
Exemplo n.º 30
0
    def display_help_topics(self):
        '''Display the help topics screen.'''

        self.main_win.set_header_text(self.help_header)
        y_loc = 1

        y_loc += self.center_win.add_paragraph(self.intro,
                                               y_loc,
                                               1,
                                               max_x=(self.win_size_x - 1))
        y_loc += 1

        area = WindowArea(scrollable_lines=(len(self.help_info) + 1),
                          y_loc=y_loc,
                          x_loc=0)
        terminalui.LOGGER.debug("lines=%s", len(self.help_dict))
        area.lines = self.win_size_y - (y_loc + 1)
        area.columns = self.win_size_x

        self.scroll_region = ScrollWindow(area, window=self.center_win)

        # add the entries to the screen
        terminalui.LOGGER.debug("range=%s", len(self.help_info))
        for idx, info in enumerate(self.help_info):
            # create ListItem for each help topic
            topic_format = info[1]
            topic_title = self.help_dict[info[0]][1]
            help_topic = topic_format % topic_title
            hilite = min(self.win_size_x, textwidth(help_topic) + 1)
            list_item = ListItem(WindowArea(1, hilite, idx, 0),
                                 window=self.scroll_region,
                                 text=help_topic)
            terminalui.LOGGER.debug("self.screen_last=%s", self.screen_last)
            if self.screen_last == info[0]:
                terminalui.LOGGER.debug("Set cur_help_idx = %s", idx)
                self.cur_help_idx = idx
        terminalui.LOGGER.debug("beg_y=%d, beg_x=%d",
                                *list_item.window.getbegyx())

        self.center_win.activate_object(self.scroll_region)
        self.scroll_region.activate_object(self.cur_help_idx)
    def test_active_object(self):
        '''Test that arrow key changes active object'''
        lines = 4
        extra_lines = 9
        scroll_win = ScrollWindow(WindowArea(lines, 70, 0, 0, 
                                  scrollable_lines=lines + extra_lines),
                                  color_theme=ColorTheme(force_bw=True))
        scroll_win.active_object = 0
        myobj0 = MockEditField()
        myobj0.area = MockInnerWin()
        myobj0.area.y_loc = 1
        myobj0.active = True
        myobj1 = MockEditField()
        myobj1.area = MockInnerWin()
        myobj1.area.y_loc = 3
        myobj1.active = False
        scroll_win.objects.append(myobj0)
        scroll_win.objects.append(myobj1)

        key = scroll_win.on_arrow_key(curses.KEY_DOWN)
        self.assertEquals(key, None)
        self.assertEquals(scroll_win.active_object, 1)
Exemplo n.º 32
0
 def _show(self):
     super(NSLDAPProxyBindChooser, self)._show()
     # check dictionary of screens associated with name service selections
     if self.nameservice.nameservice != 'LDAP':
         raise SkipException
     y_loc = self._paint_opening()
     ynlist = [_('No'),
               _('Yes')]
     area = WindowArea(x_loc=0, y_loc=y_loc,
                       scrollable_lines=len(ynlist) + 1)
     area.lines = self.win_size_y - (y_loc + 1)
     area.columns = self.win_size_x
     self.scroll_region = ScrollWindow(area, window=self.center_win)
     # add the entries to the screen
     for idx, yon in enumerate(ynlist):
         win_area = WindowArea(1, textwidth(yon) + 1, idx, INDENT)
         ListItem(win_area, window=self.scroll_region, text=yon,
                  data_obj=yon)
     self.main_win.do_update()
     self.center_win.activate_object(self.scroll_region)
     self.scroll_region.activate_object_force(self.cur_pbchoice_idx,
                                                  force_to_top=True)
Exemplo n.º 33
0
class NSLDAPProxyBindChooser(NameService):

    HEADER_TEXT = _("LDAP Proxy")
    HELP_DATA = (SCI_HELP + "/%s/ldap_proxy.txt", HEADER_TEXT)

    def __init__(self, main_win):
        super(NSLDAPProxyBindChooser, self).__init__(main_win)
        self.intro = _('Does the profile specify a proxy credential level '
                       'and an authentication method other than None?')

    def _show(self):
        super(NSLDAPProxyBindChooser, self)._show()
        # check dictionary of screens associated with name service selections
        if self.nameservice.nameservice != 'LDAP':
            raise SkipException
        y_loc = self._paint_opening()
        ynlist = [_('No'), _('Yes')]
        area = WindowArea(x_loc=0,
                          y_loc=y_loc,
                          scrollable_lines=len(ynlist) + 1)
        area.lines = self.win_size_y - (y_loc + 1)
        area.columns = self.win_size_x
        self.scroll_region = ScrollWindow(area, window=self.center_win)
        # add the entries to the screen
        for idx, yon in enumerate(ynlist):
            win_area = WindowArea(1, textwidth(yon) + 1, idx, INDENT)
            ListItem(win_area,
                     window=self.scroll_region,
                     text=yon,
                     data_obj=yon)
        self.main_win.do_update()
        self.center_win.activate_object(self.scroll_region)
        self.scroll_region.activate_object_force(self.cur_pbchoice_idx,
                                                 force_to_top=True)

    def on_change_screen(self):
        self.cur_pbchoice_idx = self.scroll_region.active_object
        idx = self.cur_pbchoice_idx
        self.nameservice.ldap_proxy_bind = idx
Exemplo n.º 34
0
    def _show(self):
        '''Prepare a text summary from the DOC and display it
        to the user in a ScrollWindow

        '''
        y_loc = 1
        y_loc += self.center_win.add_paragraph(SummaryScreen.PARAGRAPH, y_loc)

        y_loc += 1
        self.sysconfig = solaris_install.sysconfig.profile.from_engine()
        summary_text = self.build_summary()
        # Wrap the summary text, accounting for the INDENT (used below in
        # the call to add_paragraph)
        max_chars = self.win_size_x - SummaryScreen.INDENT - 1
        summary_text = convert_paragraph(summary_text, max_chars)
        area = WindowArea(x_loc=0, y_loc=y_loc,
                          scrollable_lines=(len(summary_text) + 1))
        area.lines = self.win_size_y - y_loc
        area.columns = self.win_size_x
        scroll_region = ScrollWindow(area, window=self.center_win)
        scroll_region.add_paragraph(summary_text, start_x=SummaryScreen.INDENT)

        self.center_win.activate_object(scroll_region)
Exemplo n.º 35
0
    def _show(self):
        '''Prepare a text summary from the DOC and display it
        to the user in a ScrollWindow

        '''
        y_loc = 1
        y_loc += self.center_win.add_paragraph(SummaryScreen.PARAGRAPH, y_loc)

        y_loc += 1
        self.sysconfig = solaris_install.sysconfig.profile.from_engine()
        summary_text = self.build_summary()
        # Wrap the summary text, accounting for the INDENT (used below in
        # the call to add_paragraph)
        max_chars = self.win_size_x - SummaryScreen.INDENT - 1
        summary_text = convert_paragraph(summary_text, max_chars)
        area = WindowArea(x_loc=0, y_loc=y_loc,
                          scrollable_lines=(len(summary_text) + 1))
        area.lines = self.win_size_y - y_loc
        area.columns = self.win_size_x
        scroll_region = ScrollWindow(area, window=self.center_win)
        scroll_region.add_paragraph(summary_text, start_x=SummaryScreen.INDENT)

        self.center_win.activate_object(scroll_region)
Exemplo n.º 36
0
 def test_scroll_past_bottom(self):
     '''Test to scroll past bottom, should end up at bottom '''
     lines = 70
     extra_lines = 5
     scroll_win = ScrollWindow(WindowArea(lines,
                                          70,
                                          0,
                                          0,
                                          scrollable_lines=lines +
                                          extra_lines),
                               color_theme=ColorTheme(force_bw=True))
     self.assertTrue(scroll_win.at_top())
     self.assertFalse(scroll_win.at_bottom())
     scroll_win.scroll(lines=10)
     self.assertFalse(scroll_win.at_top())
     self.assertTrue(scroll_win.at_bottom())
Exemplo n.º 37
0
 def test_scroll_past_right(self):
     '''Test to scroll past right, should end up at right '''
     cols = 70
     extra_cols = 5
     scroll_win = ScrollWindow(WindowArea(70,
                                          cols,
                                          0,
                                          0,
                                          scrollable_columns=cols +
                                          extra_cols),
                               color_theme=ColorTheme(force_bw=True))
     self.assertTrue(scroll_win.at_left())
     self.assertFalse(scroll_win.at_right())
     scroll_win.scroll(columns=10)
     self.assertFalse(scroll_win.at_left())
     self.assertTrue(scroll_win.at_right())
Exemplo n.º 38
0
    def reset(self):
        '''Create the InnerWindows representing the header, footer/border,
        error line, and main central_area

        '''
        window_size = self.initscr.getmaxyx()
        win_size_y = window_size[0]
        win_size_x = window_size[1]
        footer_area = WindowArea(1, win_size_x, win_size_y - 1, 0)
        self.footer = InnerWindow(footer_area,
                                  color_theme=self.theme,
                                  color=self.theme.border)
        top = self.initscr.derwin(1, win_size_x, 0, 0)
        left = self.initscr.derwin(win_size_y - 2, 1, 1, 0)
        right = self.initscr.derwin(win_size_y - 2, 1, 1, win_size_x - 1)
        self.footer.more_windows = [top, left, right]
        self.footer.set_color(self.theme.border)
        header_area = WindowArea(1, win_size_x - 2, 1, 1)
        self.header = InnerWindow(header_area,
                                  color_theme=self.theme,
                                  color=self.theme.header)
        central_win_area = WindowArea(win_size_y - 4, win_size_x - 2, 2, 1)
        self.central_area = InnerWindow(central_win_area,
                                        border_size=(0, 2),
                                        color_theme=self.theme)
        self._active_win = self.central_area
        popup_win_area = WindowArea(central_win_area.lines - 10,
                                    central_win_area.columns - 20, 5, 10,
                                    central_win_area.lines - 10)
        self.popup_win = ScrollWindow(popup_win_area,
                                      window=self.central_area,
                                      color=self.theme.error_msg,
                                      highlight_color=self.theme.error_msg)
        error_area = WindowArea(1, win_size_x - 2, win_size_y - 2, 1)
        self.error_line = ErrorWindow(error_area, color_theme=self.theme)
        self.reset_actions()
Exemplo n.º 39
0
    def test_vert_scrollbar_created(self):
        '''Ensure vertical scrollbar is created or not appropriately'''
        scroll_win = ScrollWindow(WindowArea(70, 70, 0, 0,
                                             scrollable_lines=75),
                                  color_theme=ColorTheme(force_bw=True))
        self.assertTrue(scroll_win.get_use_vert_scroll_bar())

        scroll_win = ScrollWindow(WindowArea(70, 70, 0, 0,
                                             scrollable_lines=70),
                                  color_theme=ColorTheme(force_bw=True))
        self.assertFalse(scroll_win.get_use_vert_scroll_bar())
Exemplo n.º 40
0
    def test_horiz_scrollbar_created(self):
        '''Ensure horizontal scrollbar is created or not appropriately'''
        scroll_win = ScrollWindow(WindowArea(70,
                                             70,
                                             0,
                                             0,
                                             scrollable_columns=75),
                                  color_theme=ColorTheme(force_bw=True))
        self.assertTrue(scroll_win.get_use_horiz_scroll_bar())

        scroll_win = ScrollWindow(WindowArea(70,
                                             70,
                                             0,
                                             0,
                                             scrollable_columns=69),
                                  color_theme=ColorTheme(force_bw=True))
        self.assertFalse(scroll_win.get_use_horiz_scroll_bar())
    def test_no_ut_refresh(self):
        '''Ensure deep_refresh is updating nested window screen location '''

        scroll_win = ScrollWindow(WindowArea(60, 70, 0, 0, 
                                  scrollable_columns=75),
                                  color_theme=ColorTheme(force_bw=True))
        scroll_win.window = MockInnerWin()
        scroll_win.area.lower_right_y = 20
        scroll_win.area.lower_right_x = 20
        myscroll = ScrollWindow(WindowArea(10, 10, 0, 0,
                                scrollable_columns=15),
                                color_theme=ColorTheme(force_bw=True))
        myscroll.window = MockInnerWin()
        myscroll.area.lower_right_y = 16
        myscroll.area.lower_right_x = 18
        scroll_win.objects.append(myscroll)
        scroll_win.area.y_loc = 3
        scroll_win.area.x_loc = 5
        abs_y = 12
        abs_x = 15
        scroll_win.latest_yx = (abs_y, abs_x)
        scroll_win.no_ut_refresh()
        self.assertEquals(myscroll.latest_yx[0], scroll_win.area.y_loc + abs_y)
        self.assertEquals(myscroll.latest_yx[1], scroll_win.area.x_loc + abs_x)
class NICSelect(BaseScreen):
    '''Allow user to choose which ethernet connection to manually configure'''
    
    MAX_NICS = 15
    
    HEADER_TEXT = _("Manual Network Configuration")
    PARAGRAPH = _("Select the one wired network connection to be configured"
                  " during installation")
    
    HELP_DATA = (SCI_HELP + "/%s/network_manual.txt",
                 _("Manual Network Configuration"))
    HELP_FORMAT = "  %s"
    
    LIST_OFFSET = 2

    def __init__(self, main_win):
        global LOGGER
        if LOGGER is None:
            LOGGER = logging.getLogger(INSTALL_LOGGER_NAME + ".sysconfig")
        
        super(NICSelect, self).__init__(main_win)
        self.list_area = WindowArea(1, 0, 0, NICSelect.LIST_OFFSET)

        # find_links() returns tuple containing
        #  * dictionary of configurable NICs
        #  * number of NICs mandated from global zone.
        self.ether_nics = NetworkInfo.find_links()[0]
        self.nic = None
    
    def _show(self):
        '''Create a list of NICs to choose from. If more than 15 NICs are
        found, create a scrolling region to put them in
        
        '''
        self.nic = solaris_install.sysconfig.profile.from_engine().nic
        if self.nic.type != NetworkInfo.MANUAL:
            raise SkipException
        if len(self.ether_nics) == 1:
            self.set_nic_in_profile(self.ether_nics[0])
            raise SkipException
        
        if self.nic.nic_iface is None:
            selected_nic_name = ""
        else:
            selected_nic_name = NetworkInfo.get_nic_name(self.nic.nic_iface)
        
        y_loc = 1
        y_loc += self.center_win.add_paragraph(NICSelect.PARAGRAPH, y_loc)
        
        selected_nic = 0
        
        y_loc += 1
        max_nics = min(NICSelect.MAX_NICS, self.center_win.area.lines - y_loc)
        if len(self.ether_nics) > max_nics:
            columns = self.win_size_x - NICSelect.LIST_OFFSET
            win_area = WindowArea(lines=max_nics, columns=columns,
                                  y_loc=y_loc, x_loc=NICSelect.LIST_OFFSET,
                                  scrollable_lines=len(self.ether_nics))
            self.scroll_region = ScrollWindow(win_area, window=self.center_win)
            self.list_region = self.scroll_region
            y_loc = 0
        else:
            self.scroll_region = None
            self.list_region = self.center_win
        
        for nic in self.ether_nics:
            self.list_area.y_loc = y_loc

            #
            # display list item in form of "NIC name (NIC device)" -
            # e.g. "net0 (bge0)"
            # If NIC device is not populated, display just NIC name.
            #
            list_item_text = NetworkInfo.get_nic_desc(nic)

            # list item width
            self.list_area.columns = len(list_item_text) + 1

            list_item = ListItem(self.list_area, window=self.list_region,
                                 text=list_item_text, data_obj=nic)
            if NetworkInfo.get_nic_name(nic) == selected_nic_name:
                selected_nic = list_item
            y_loc += 1
        
        self.main_win.do_update()
        if self.scroll_region:
            self.center_win.activate_object(self.scroll_region)
            self.scroll_region.activate_object_force(selected_nic,
                                                     force_to_top=True)
        else:
            self.center_win.activate_object(selected_nic)
    
    def on_change_screen(self):
        '''Save the highlighted NIC as the selected NIC'''
        selected_nic = self.list_region.get_active_object().data_obj
        self.set_nic_in_profile(selected_nic)
    
    def set_nic_in_profile(self, selected_nic):
        '''Store selected NIC in the profile '''
        LOGGER.info("Selecting %s for manual configuration",
                    NetworkInfo.get_nic_desc(selected_nic))
        nic = solaris_install.sysconfig.profile.from_engine().nic
        nic.nic_iface = selected_nic
Exemplo n.º 43
0
    def test_scroll_right_left_arrow(self):
        '''Test to scroll right and left with arrow key '''
        cols = 3
        extra_cols = 5
        scroll_win = ScrollWindow(WindowArea(10,
                                             cols,
                                             0,
                                             0,
                                             scrollable_columns=cols +
                                             extra_cols),
                                  color_theme=ColorTheme(force_bw=True))
        scroll_win.active_object = None

        self.assertTrue(scroll_win.at_left())
        key = scroll_win.on_arrow_key(curses.KEY_RIGHT)
        self.assertEqual(key, None)
        self.assertFalse(scroll_win.at_left())

        key = scroll_win.on_arrow_key(curses.KEY_LEFT)
        self.assertEqual(key, None)
        self.assertTrue(scroll_win.at_left())

        key = scroll_win.on_arrow_key(curses.KEY_LEFT)
        self.assertEqual(key, curses.KEY_LEFT)
        self.assertTrue(scroll_win.at_left())

        scroll_win.scroll(columns=extra_cols - 2)
        self.assertFalse(scroll_win.at_left())
        self.assertFalse(scroll_win.at_right())
        scroll_win.on_arrow_key(curses.KEY_RIGHT)
        self.assertTrue(scroll_win.at_right())

        scroll_win.scroll(columns=-(extra_cols - 2))
        self.assertFalse(scroll_win.at_left())
        self.assertFalse(scroll_win.at_right())
        scroll_win.on_arrow_key(curses.KEY_LEFT)
        self.assertTrue(scroll_win.at_left())
    def _show(self):
        '''Create a list of NICs to choose from. If more than 15 NICs are
        found, create a scrolling region to put them in
        
        '''
        self.nic = solaris_install.sysconfig.profile.from_engine().nic
        if self.nic.type != NetworkInfo.MANUAL:
            raise SkipException
        if len(self.ether_nics) == 1:
            self.set_nic_in_profile(self.ether_nics[0])
            raise SkipException
        
        if self.nic.nic_iface is None:
            selected_nic_name = ""
        else:
            selected_nic_name = NetworkInfo.get_nic_name(self.nic.nic_iface)
        
        y_loc = 1
        y_loc += self.center_win.add_paragraph(NICSelect.PARAGRAPH, y_loc)
        
        selected_nic = 0
        
        y_loc += 1
        max_nics = min(NICSelect.MAX_NICS, self.center_win.area.lines - y_loc)
        if len(self.ether_nics) > max_nics:
            columns = self.win_size_x - NICSelect.LIST_OFFSET
            win_area = WindowArea(lines=max_nics, columns=columns,
                                  y_loc=y_loc, x_loc=NICSelect.LIST_OFFSET,
                                  scrollable_lines=len(self.ether_nics))
            self.scroll_region = ScrollWindow(win_area, window=self.center_win)
            self.list_region = self.scroll_region
            y_loc = 0
        else:
            self.scroll_region = None
            self.list_region = self.center_win
        
        for nic in self.ether_nics:
            self.list_area.y_loc = y_loc

            #
            # display list item in form of "NIC name (NIC device)" -
            # e.g. "net0 (bge0)"
            # If NIC device is not populated, display just NIC name.
            #
            list_item_text = NetworkInfo.get_nic_desc(nic)

            # list item width
            self.list_area.columns = len(list_item_text) + 1

            list_item = ListItem(self.list_area, window=self.list_region,
                                 text=list_item_text, data_obj=nic)
            if NetworkInfo.get_nic_name(nic) == selected_nic_name:
                selected_nic = list_item
            y_loc += 1
        
        self.main_win.do_update()
        if self.scroll_region:
            self.center_win.activate_object(self.scroll_region)
            self.scroll_region.activate_object_force(selected_nic,
                                                     force_to_top=True)
        else:
            self.center_win.activate_object(selected_nic)
class DiskScreen(BaseScreen):
    '''
    Allow the user to select a (valid) disk target for installation
    Display the partition/slice table for the highlighted disk
    
    '''
    
    HEADER_TEXT = _("Disks")
    PARAGRAPH = _("Where should %(release)s be installed?") % RELEASE
    REC_SIZE_TEXT = _("Recommended size: ")
    MIN_SIZE_TEXT = _("    Minimum size: ")
    DISK_SEEK_TEXT = _("Seeking disks on system")
    FOUND_x86 = _("The following partitions were found on the disk.")
    FOUND_SPARC = _("The following slices were found on the disk.")
    PROPOSED_x86 = _("A partition table was not found. The following is "
                     "proposed.")
    PROPOSED_SPARC = _("A VTOC label was not found. The following "
                       "is proposed.")
    PROPOSED_GPT = _("A GPT labeled disk was found. The following is "
                     "proposed.")
    TOO_SMALL = _("Too small")
    TOO_BIG_WARN = _("Limited to %.1f TB")
    GPT_LABELED = _("GPT labeled disk")
    NO_DISKS = _("No disks found. Additional device drivers may "
                 "be needed.")
    NO_TARGETS = _("%(release)s cannot be installed on any disk") % RELEASE
    TGT_ERROR = _("An error occurred while searching for installation"
                  " targets. Please check the install log and file a bug"
                  " at defect.opensolaris.org.")
    
    DISK_HEADERS = [(8, _("Type")),
                    (10, _(" Size(GB)")),
                    (6, _("Boot")),
                    (26, _("Device")),
                    (10, _("Vendor")),
                    (3, ""),
                    (10, _("Notes"))] #blank header for the notes column
    VENDOR_LEN = 15

    SPINNER = ["\\", "|", "/", "-"]
    
    DISK_WARNING_HEADER = _("Warning")
    DISK_WARNING_TOOBIG = _("Only the first %.1fTB can be used.")
    DISK_WARNING_GPT = _("You have chosen a GPT labeled disk. Installing "
                         "onto a GPT labeled disk will cause the loss "
                         "of all existing data and the disk will be "
                         "relabeled as SMI.")

    CANCEL_BUTTON = _("Cancel")
    CONTINUE_BUTTON = _("Continue")
    
    HELP_DATA = (TUI_HELP + "/%s/disks.txt", _("Disks"))
    
    def __init__(self, main_win, target_controller):

        global LOGGER
        LOGGER = logging.getLogger(INSTALL_LOGGER_NAME)

        super(DiskScreen, self).__init__(main_win)
        if platform.processor() == "i386":
            self.found_text = DiskScreen.FOUND_x86
            self.proposed_text = DiskScreen.PROPOSED_x86
        else:
            self.found_text = DiskScreen.FOUND_SPARC
            self.proposed_text = DiskScreen.PROPOSED_SPARC
        
        disk_header_text = []
        for header in DiskScreen.DISK_HEADERS:
            header_str = fit_text_truncate(header[1], header[0] - 1,
                                           just="left")
            disk_header_text.append(header_str)
        self.disk_header_text = " ".join(disk_header_text)
        max_note_size = DiskScreen.DISK_HEADERS[5][0]
        self.too_small_text = DiskScreen.TOO_SMALL[:max_note_size]
        max_disk_size = (Size(MAX_VTOC)).get(Size.tb_units)
        too_big_warn = DiskScreen.TOO_BIG_WARN % max_disk_size
        self.too_big_warn = too_big_warn[:max_note_size]
        self.disk_warning_too_big = \
            DiskScreen.DISK_WARNING_TOOBIG % max_disk_size
        
        self.disks = []
        self.existing_pools = []
        self.disk_win = None
        self.disk_detail = None
        self.num_targets = 0
        self.td_handle = None
        self._size_line = None
        self.selected_disk_index = 0
        self._minimum_size = None
        self._recommended_size = None

        self.engine = InstallEngine.get_instance()
        self.doc = self.engine.data_object_cache
        self.tc = target_controller
        self._target_discovery_completed = False
        self._target_discovery_status = InstallEngine.EXEC_SUCCESS
        self._image_size = None
    
    def determine_minimum(self):
        '''Returns minimum install size, fetching first if needed'''
        self.determine_size_data()
        return self._minimum_size
    
    minimum_size = property(determine_minimum)
    
    def determine_recommended(self):
        '''Returns recommended install size, fetching first if needed'''
        self.determine_size_data()
        return self._recommended_size
    
    recommended_size = property(determine_recommended)
    
    def determine_size_data(self):
        '''Retrieve the minimum and recommended sizes and generate the string
        to present that information.
        
        '''
        if self._minimum_size is None or self._recommended_size is None:
            self._recommended_size = get_recommended_size(self.tc)
            self._minimum_size = get_minimum_size(self.tc)
    
    def get_size_line(self):
        '''Returns the line of text displaying the min/recommended sizes'''
        if self._size_line is None:
            rec_size_str = locale.format("%.1f",
                self.recommended_size.get(Size.gb_units)) + LOCALIZED_GB
            min_size_str = locale.format("%.1f",
                self.minimum_size.get(Size.gb_units)) + LOCALIZED_GB
            self._size_line = DiskScreen.REC_SIZE_TEXT + rec_size_str + \
                DiskScreen.MIN_SIZE_TEXT + min_size_str

        return self._size_line
    
    size_line = property(get_size_line)
    
    def wait_for_disks(self):
        '''Block while waiting for libtd to finish. Catch F9 and quit
        if needed
        
        '''
        self.main_win.actions.pop(curses.KEY_F2, None)
        self.main_win.actions.pop(curses.KEY_F6, None)
        self.main_win.actions.pop(curses.KEY_F3, None)
        self.main_win.show_actions()

        self.center_win.add_text(DiskScreen.DISK_SEEK_TEXT, 5, 1,
                                 self.win_size_x - 3)
        self.main_win.do_update()
        offset = textwidth(DiskScreen.DISK_SEEK_TEXT) + 2
        spin_index = 0
        self.center_win.window.timeout(250)

        while not self._target_discovery_completed:
            input_key = self.main_win.getch()
            if input_key == curses.KEY_F9:
                if self.confirm_quit():
                    raise QuitException
            self.center_win.add_text(DiskScreen.SPINNER[spin_index], 5, offset)
            self.center_win.no_ut_refresh()
            self.main_win.do_update()
            spin_index = (spin_index + 1) % len(DiskScreen.SPINNER)

        self.center_win.window.timeout(-1)
        self.center_win.clear()

        # check the result of target discovery
        if self._target_discovery_status is not InstallEngine.EXEC_SUCCESS:
            err_data = (errsvc.get_errors_by_mod_id(TARGET_DISCOVERY))[0]
            LOGGER.error("Target discovery failed")
            err = err_data.error_data[liberrsvc.ES_DATA_EXCEPTION]
            LOGGER.error(err)
            raise TargetDiscoveryError(("Unexpected error (%s) during target "
                "discovery. See log for details.") % err)

    def _td_callback(self, status, errsvc):
        '''Callback function for Target Discovery checkpoint execution.
           The status value is saved to be interpreted later.
           This function sets the self._target_discovery_completed 
           value to true so the wait_for_disks() function will know
           to stop displaying the spinner.
 
        '''

        self._target_discovery_status = status
        self._target_discovery_completed = True

    def _show(self):
        '''Create a list of disks to choose from and create the window
        for displaying the partition/slice information from the selected
        disk
        
        '''

        self.wait_for_disks()

        discovered_target = self.doc.persistent.get_first_child( \
            name=Target.DISCOVERED)

        LOGGER.debug(discovered_target)
        if discovered_target is None:
            self.center_win.add_paragraph(DiskScreen.NO_DISKS, 1, 1,
                                          max_x=(self.win_size_x - 1))
            return

        self.disks = discovered_target.get_children(class_type=Disk)
        if not self.disks:
            self.center_win.add_paragraph(DiskScreen.NO_TARGETS, 1, 1,
                                          max_x=(self.win_size_x - 1))
            return

        if self._image_size is None:
            try:
                self._image_size = Size(str(get_image_size(LOGGER)) + \
                    Size.mb_units)
                LOGGER.debug("Image_size: %s", self._image_size)
            except:
                # Unable to get the image size for some reason, allow
                # the target controller to use it's default size.
                LOGGER.debug("Unable to get image size") 
                self._image_size = FALLBACK_IMAGE_SIZE

        # initialize the target controller so the min/max size for
        # the installation can be calculated.  Explicitly do not
        # want to select an initial disk at this time in case
        # none of the disks discovered is usable.  The target controller
        # initialization needs to be done everytime we show the disk selection
        # screen so the desired target node in the DOC can be re-populated
        # with information from target discovery.
        self.tc.initialize(image_size=self._image_size, no_initial_disk=True)
         
        # Go through all the disks found and find ones that have
        # enough space for installation.  At the same time, see if any
        # existing disk is the boot disk.  If a boot disk is found, move
        # it to the front of the list
        num_usable_disks = 0
        boot_disk = None
        for disk in self.disks:
            LOGGER.debug("size: %s, min: %s" % \
                         (disk.disk_prop.dev_size, self.minimum_size))
            if disk.disk_prop.dev_size >= self.minimum_size:
                if disk.is_boot_disk():
                    boot_disk = disk
                num_usable_disks += 1
        if boot_disk is not None:
            self.disks.remove(boot_disk)
            self.disks.insert(0, boot_disk)

        if num_usable_disks == 0:
            self.center_win.add_paragraph(DiskScreen.NO_DISKS, 1, 1,
                                          max_x=(self.win_size_x - 1))
            return

        self.main_win.reset_actions()
        self.main_win.show_actions()
        
        y_loc = 1
        self.center_win.add_text(DiskScreen.PARAGRAPH, y_loc, 1)
        
        y_loc += 1
        self.center_win.add_text(self.size_line, y_loc, 1)
        
        y_loc += 2
        self.center_win.add_text(self.disk_header_text, y_loc, 1)
        
        y_loc += 1
        self.center_win.window.hline(y_loc, self.center_win.border_size[1] + 1,
                                     curses.ACS_HLINE,
                                     textwidth(self.disk_header_text))
        
        y_loc += 1
        disk_win_area = WindowArea(4, textwidth(self.disk_header_text) + 2,
                                   y_loc, 0)
        disk_win_area.scrollable_lines = len(self.disks) + 1
        self.disk_win = ScrollWindow(disk_win_area,
                                     window=self.center_win)
        
        disk_item_area = WindowArea(1, disk_win_area.columns - 2, 0, 1)
        disk_index = 0
        len_type = DiskScreen.DISK_HEADERS[0][0] - 1
        len_size = DiskScreen.DISK_HEADERS[1][0] - 1
        len_boot = DiskScreen.DISK_HEADERS[2][0] - 1
        len_dev = DiskScreen.DISK_HEADERS[3][0] - 1
        len_mftr = DiskScreen.DISK_HEADERS[4][0] - 1
        for disk in self.disks:
            disk_text_fields = []
            if disk.disk_prop is None or disk.disk_prop.dev_type is None:
                continue
            type_field = disk.disk_prop.dev_type[:len_type]
            type_field = ljust_columns(type_field, len_type)
            disk_text_fields.append(type_field)
            disk_size = disk.disk_prop.dev_size.get(Size.gb_units)
            size_field = locale.format("%*.1f", (len_size, disk_size))
            disk_text_fields.append(size_field)
            if disk.is_boot_disk():
                bootable_field = "+".center(len_boot)
            else:
                bootable_field = " " * (len_boot)
            disk_text_fields.append(bootable_field)
            device_field = disk.ctd[:len_dev]
            device_field = ljust_columns(device_field, len_dev)
            disk_text_fields.append(device_field)
            vendor = disk.disk_prop.dev_vendor
            if vendor is not None:
                mftr_field = vendor[:len_mftr]
                mftr_field = ljust_columns(mftr_field, len_mftr)
            else:
                mftr_field = " " * len_mftr
            disk_text_fields.append(mftr_field)
            selectable = True
            if disk.disk_prop.dev_size < self.minimum_size:
                note_field = self.too_small_text
                selectable = False
            elif disk_size > Size(MAX_VTOC).get(Size.gb_units):
                note_field = self.too_big_warn
            else:
                note_field = ""
            disk_text_fields.append(note_field)
            disk_text = " ".join(disk_text_fields)
            disk_item_area.y_loc = disk_index
            disk_list_item = ListItem(disk_item_area, window=self.disk_win,
                                      text=disk_text, add_obj=selectable)
            disk_list_item.on_make_active = on_activate
            disk_list_item.on_make_active_kwargs["disk"] = disk
            disk_list_item.on_make_active_kwargs["disk_select"] = self
            disk_index += 1

        self.disk_win.no_ut_refresh()
        
        y_loc += 7
        disk_detail_area = WindowArea(6, 70, y_loc, 1)

        self.disk_detail = DiskWindow(disk_detail_area, self.disks[0],
                                      target_controller=self.tc,
                                      window=self.center_win)
        
        self.main_win.do_update()
        self.center_win.activate_object(self.disk_win)
        self.disk_win.activate_object(self.selected_disk_index)
    
    def on_change_screen(self):
        ''' Save the index of the current selected object
        in case the user returns to this screen later
        
        '''

        # Save the index of the selected object
        self.selected_disk_index = self.disk_win.active_object

        LOGGER.debug("disk_selection.on_change_screen, saved_index: %s",
                     self.selected_disk_index)
        LOGGER.debug(self.doc.persistent)
    
    def start_discovery(self):

        # start target discovery
        if not self._target_discovery_completed:
            errsvc.clear_error_list()

            self.engine.execute_checkpoints(pause_before=TRANSFER_PREP,
                                            callback=self._td_callback)

    def validate(self):
        '''Validate the size of the disk.'''

        warning_txt = []

        disk = self.disk_detail.ui_obj.doc_obj
        disk_size_gb = disk.disk_prop.dev_size.get(Size.gb_units)
        max_size_gb = Size(MAX_VTOC).get(Size.gb_units)
        if disk_size_gb > max_size_gb:
            warning_txt.append(self.disk_warning_too_big)
        warning_txt = " ".join(warning_txt)
        
        if warning_txt:
            # warn the user and give user a chance to change
            result = self.main_win.pop_up(DiskScreen.DISK_WARNING_HEADER,
                                          warning_txt,
                                          DiskScreen.CANCEL_BUTTON,
                                          DiskScreen.CONTINUE_BUTTON)
            
            if not result:
                raise UIMessage() # let user select different disk
Exemplo n.º 46
0
class TimeZone(BaseScreen):
    '''Allow user to select timezone based on already selected
    continent and country.
    
    '''
    
    UTC_TEXT = _("UTC/GMT")
    SCROLL_SIZE = 2
    BORDER_WIDTH = (0, 3)
    REGIONS = "regions"
    LOCATIONS = "locations"
    TIMEZONE = "timezone"
    
    HELP_DATA = (SCI_HELP + "/%s/timezone.txt", _("Time Zone"))
    
    def __init__(self, main_win, screen=None):
        global LOGGER
        if LOGGER is None:
            LOGGER = logging.getLogger(INSTALL_LOGGER_NAME + ".sysconfig")
        
        super(TimeZone, self).__init__(main_win)
        self.sys_info = None
        if screen is None:
            self.screen = TimeZone.TIMEZONE
        else:
            self.screen = screen
        self.tz_tuples = None
        self.tz_list = None
        self.cur_timezone_idx = 0
        self.cur_timezone_parent = None
        self.last_timezone_parent = None
        self.cur_continent = None
        self.cur_country = None
        self.scroll_region = None
        self.last_country = None
        self.last_continent = None
        if self.screen == TimeZone.TIMEZONE:
            self.header_text = _("Time Zone")
            self.intro = _("Select your time zone.")
            self.title = _("Time Zones")
        elif self.screen == TimeZone.LOCATIONS:
            self.header_text = _("Time Zone: Locations")
            self.intro = _("Select the location that contains your time zone.")
            self.title = _("Locations")
            self.help_data = (None, None)
        else:
            self.header_text = _("Time Zone: Regions")
            self.intro = _("Select the region that contains your time zone.")
            self.title = _("Regions")
            self.help_data = (None, None)
    
    def _show(self):
        '''Create the list of time zones'''
        LOGGER.debug("self.screen %s", self.screen)
        
        sc_profile = solaris_install.sysconfig.profile.from_engine()
        
        if sc_profile.system is None:
            sc_profile.system = SystemInfo()
        self.sys_info = sc_profile.system
        
        self.cur_country = self.sys_info.tz_country
        self.cur_continent = self.sys_info.tz_region
        
        if self.cur_continent == SystemInfo.UTC and self.screen != "regions":
            raise SkipException
        
        self.center_win.border_size = TimeZone.BORDER_WIDTH
        
        if self.screen == TimeZone.LOCATIONS:
            self.cur_timezone_parent = self.cur_continent
        elif self.screen == TimeZone.TIMEZONE:
            self.cur_timezone_parent = self.cur_country
        
        LOGGER.debug("cur_continent %s, cur_country %s",
                      self.cur_continent, self.cur_country)
        
        y_loc = 1
        
        y_loc += self.center_win.add_paragraph(self.intro, y_loc)
        
        y_loc += 1
        menu_item_max_width = self.win_size_x - TimeZone.SCROLL_SIZE
        self.center_win.add_text(self.title, y_loc, TimeZone.SCROLL_SIZE)
        y_loc += 1
        self.center_win.window.hline(y_loc, 3, curses.ACS_HLINE, 40)
        
        y_loc += 1
        
        tz_list = self.get_timezones(self.cur_continent, self.cur_country)
        
        area = WindowArea(x_loc=0, y_loc=y_loc,
                          scrollable_lines=len(tz_list) + 1)
        area.lines = self.win_size_y - (y_loc + 1)
        area.columns = self.win_size_x
        LOGGER.debug("area.lines=%s, area.columns=%s",
                      area.lines, area.columns)
        self.scroll_region = ScrollWindow(area, window=self.center_win)
        
        utc = 0
        if self.screen == TimeZone.REGIONS:
            utc_area = WindowArea(1, len(TimeZone.UTC_TEXT) + 1, 0,
                                  TimeZone.SCROLL_SIZE)
            utc_item = ListItem(utc_area, window=self.scroll_region,
                                text=TimeZone.UTC_TEXT,
                                data_obj=SystemInfo.UTC)
            utc = 1
        
        # add the entries to the screen
        for idx, timezone in enumerate(tz_list):
            LOGGER.log(LOG_LEVEL_INPUT, "tz idx = %i name= %s",
                        idx, tz_list[idx])
            hilite = min(menu_item_max_width, len(timezone) + 1)
            win_area = WindowArea(1, hilite, idx + utc, TimeZone.SCROLL_SIZE)
            list_item = ListItem(win_area, window=self.scroll_region,
                                 text=timezone, data_obj=timezone)
            y_loc += 1
        
        self.main_win.do_update()
        self.center_win.activate_object(self.scroll_region)
        LOGGER.debug("self.cur_timezone_idx=%s", self.cur_timezone_idx)
        self.scroll_region.activate_object_force(self.cur_timezone_idx,
                                                 force_to_top=True)
    
    def get_timezones(self, continent, country_code):
        '''Get the timezone info, a list of tuples, each with:
            [0] timezone name
            [1] timezone name descriptive
            [2] localized timezone name
        '''
        
        LOGGER.debug("get_timezones continent=%s", continent)
        LOGGER.debug("get_timezones country_code=%s", country_code)
        LOGGER.debug("get_timezones self.cur_timezone_parent=%s,"
                      " self.last_timezone_parent=%s",
                      self.cur_timezone_parent, self.last_timezone_parent)
        
        if (self.tz_list is None or self.cur_timezone_parent !=
            self.last_timezone_parent):
            self.tz_list = []
            self.cur_timezone_idx = 0
            
            # pass get_tz_info the correct parameters:
            #   none - to get regions/continents
            #   continent  ("America") - to get countries
            #   continent and country code ("America", "US")  - to get the 
            #      timezones
            if self.screen == TimeZone.REGIONS:
                self.tz_tuples = get_tz_info()
            elif self.screen == TimeZone.LOCATIONS:
                self.tz_tuples = get_tz_info(continent)
            else:
                self.tz_tuples = get_tz_info(continent, country_code)
            
            # get name to display. First choice is localized name, then
            # descriptive name, then plain name
            LOGGER.debug("number of timezones=%i", len(self.tz_tuples))
            for item in self.tz_tuples:
                if item[2]:
                    LOGGER.debug("tz2 = %s", item[2])
                    self.tz_list.append(item[2])
                elif item[1]:
                    LOGGER.debug("tz1 = %s", item[1])
                    self.tz_list.append(item[1])
                else:
                    LOGGER.debug("tz0 = %s", item[0])
                    self.tz_list.append(item[0])
        
        return self.tz_list

    def on_change_screen(self):
        '''Save the chosen timezone's index and name when leaving the screen'''
        self.cur_timezone_idx = self.scroll_region.active_object
        idx = self.cur_timezone_idx
        self.last_timezone_parent = self.cur_timezone_parent
        if self.screen == TimeZone.REGIONS:
            if (self.scroll_region.get_active_object().data_obj ==
                SystemInfo.UTC):
                self.sys_info.tz_region_idx = 0
                self.sys_info.tz_region = SystemInfo.UTC
                self.sys_info.tz_country = SystemInfo.UTC
                self.sys_info.tz_timezone = SystemInfo.UTC
                self.sys_info.tz_display_name = TimeZone.UTC_TEXT
            else:
                self.sys_info.tz_region_idx = idx
                self.sys_info.tz_region = self.tz_tuples[idx - 1][0]
            LOGGER.debug("on_change_screen sys_info.tz_region: %s",
                          self.sys_info.tz_region)
        elif self.screen == TimeZone.LOCATIONS:
            self.sys_info.tz_country_idx = idx
            self.sys_info.tz_country = self.tz_tuples[idx][0]
            self.last_continent = self.cur_continent
            LOGGER.debug("on_change_screen sys_info.tz_country: %s",
                          self.sys_info.tz_country)
            LOGGER.debug("on_change_screen sys_info.tz_country_idx: %s",
                          self.sys_info.tz_country_idx)
        else:
            self.sys_info.tz_timezone_idx = idx
            self.sys_info.tz_timezone = self.tz_tuples[idx][0]
            selected_tz = self.scroll_region.get_active_object().data_obj
            self.sys_info.tz_display_name = selected_tz
            self.last_country = self.cur_country
            self.cur_timezone_idx = self.scroll_region.active_object
            LOGGER.debug("on_change_screen self.sys_info.tz_timezone: %s",
                          self.sys_info.tz_timezone)
            LOGGER.debug("on_change_screen self.sys_info.tz_timezone_idx:%s",
                          self.sys_info.tz_timezone_idx)
Exemplo n.º 47
0
 def _show(self):
     '''Create the list of time zones'''
     LOGGER.debug("self.screen %s", self.screen)
     
     sc_profile = solaris_install.sysconfig.profile.from_engine()
     
     if sc_profile.system is None:
         sc_profile.system = SystemInfo()
     self.sys_info = sc_profile.system
     
     self.cur_country = self.sys_info.tz_country
     self.cur_continent = self.sys_info.tz_region
     
     if self.cur_continent == SystemInfo.UTC and self.screen != "regions":
         raise SkipException
     
     self.center_win.border_size = TimeZone.BORDER_WIDTH
     
     if self.screen == TimeZone.LOCATIONS:
         self.cur_timezone_parent = self.cur_continent
     elif self.screen == TimeZone.TIMEZONE:
         self.cur_timezone_parent = self.cur_country
     
     LOGGER.debug("cur_continent %s, cur_country %s",
                   self.cur_continent, self.cur_country)
     
     y_loc = 1
     
     y_loc += self.center_win.add_paragraph(self.intro, y_loc)
     
     y_loc += 1
     menu_item_max_width = self.win_size_x - TimeZone.SCROLL_SIZE
     self.center_win.add_text(self.title, y_loc, TimeZone.SCROLL_SIZE)
     y_loc += 1
     self.center_win.window.hline(y_loc, 3, curses.ACS_HLINE, 40)
     
     y_loc += 1
     
     tz_list = self.get_timezones(self.cur_continent, self.cur_country)
     
     area = WindowArea(x_loc=0, y_loc=y_loc,
                       scrollable_lines=len(tz_list) + 1)
     area.lines = self.win_size_y - (y_loc + 1)
     area.columns = self.win_size_x
     LOGGER.debug("area.lines=%s, area.columns=%s",
                   area.lines, area.columns)
     self.scroll_region = ScrollWindow(area, window=self.center_win)
     
     utc = 0
     if self.screen == TimeZone.REGIONS:
         utc_area = WindowArea(1, len(TimeZone.UTC_TEXT) + 1, 0,
                               TimeZone.SCROLL_SIZE)
         utc_item = ListItem(utc_area, window=self.scroll_region,
                             text=TimeZone.UTC_TEXT,
                             data_obj=SystemInfo.UTC)
         utc = 1
     
     # add the entries to the screen
     for idx, timezone in enumerate(tz_list):
         LOGGER.log(LOG_LEVEL_INPUT, "tz idx = %i name= %s",
                     idx, tz_list[idx])
         hilite = min(menu_item_max_width, len(timezone) + 1)
         win_area = WindowArea(1, hilite, idx + utc, TimeZone.SCROLL_SIZE)
         list_item = ListItem(win_area, window=self.scroll_region,
                              text=timezone, data_obj=timezone)
         y_loc += 1
     
     self.main_win.do_update()
     self.center_win.activate_object(self.scroll_region)
     LOGGER.debug("self.cur_timezone_idx=%s", self.cur_timezone_idx)
     self.scroll_region.activate_object_force(self.cur_timezone_idx,
                                              force_to_top=True)
class DiskWindow(InnerWindow):
    '''Display and edit disk information, including partitions and slices'''

    STATIC_PARTITION_HEADERS = [(12, _("Primary"), _("Logical")),
                                (10, _(" Size(GB)"), _(" Size(GB)"))]

    EDIT_PARTITION_HEADERS = [(13, _("Primary"), _("Logical")),
                              (10, _(" Size(GB)"), _(" Size(GB)")),
                              (7, _(" Avail"), _(" Avail"))]

    STATIC_SLICE_HEADERS = [(13, _("Slice"), _("Slice")),
                            (2, "#", "#"),
                            (10, _(" Size(GB)"), _(" Size(GB)"))]

    EDIT_SLICE_HEADERS = [(13, _("Slice"), _("Slice")),
                          (2, "#", "#"),
                          (10, _(" Size(GB)"), _(" Size(GB)")),
                          (7, _(" Avail"), _(" Avail"))]

    ADD_KEYS = {curses.KEY_LEFT: no_action,
                curses.KEY_RIGHT: no_action}

    DEAD_ZONE = 3
    SCROLL_PAD = 2

    MIN_SIZE = None
    REC_SIZE = None

    SIZE_PRECISION = Size(UI_PRECISION).get(Size.gb_units)

    DESTROYED_MARK = EditField.ASTERISK_CHAR

    def __init__(self, area, disk_info, editable=False,
                 error_win=None, target_controller=None, **kwargs):
        '''See also InnerWindow.__init__

        disk_info (required) - Either a Disk or Partition object
        containing the data to be represented. If a Partition objects is
        provided, it will be used for displaying slice
        data within that partition. If Disk has partition(s), those are
        displayed. If not, but it has slices, then those are displayed. If
        neither partition data nor slice data are available, a ValueError is
        raised.

        headers (required) - List of tuples to populate the header of this
        window with. The first item in each tuple should be the width of the
        header, the second item should be the left side header.

        editable (optional) - If True, the window will be created such that
        data is editable.

        target_controller(optional) - Target controller

        '''

        global LOGGER
        LOGGER = logging.getLogger(INSTALL_LOGGER_NAME)

        self.headers = None
        self.orig_ext_part_field = None
        self.orig_logicals_active = False
        self.ext_part_field = None
        self.error_win = error_win
        self.editable = editable
        self.win_width = None
        self.left_win = None
        self.right_win = None
        self.list_area = None
        self.edit_area = None
        super(DiskWindow, self).__init__(area, add_obj=editable, **kwargs)
        self.left_header_string = None
        self.right_header_string = None
        self._orig_data = None
        self.disk_info = None
        self.has_partition_data = False
        self.key_dict[curses.KEY_LEFT] = self.on_arrow_key
        self.key_dict[curses.KEY_RIGHT] = self.on_arrow_key
        if self.editable:
            self.key_dict[curses.KEY_F5] = self.change_type

        self.tc = target_controller
        self._ui_obj = None
        self.ui_obj = disk_info

        self.set_disk_info(ui_obj=self.ui_obj)

        LOGGER.debug(self.ui_obj)

        if platform.processor() == "sparc":
            self.is_x86 = False
        else:
            self.is_x86 = True

    @property
    def ui_obj(self):
        return self._ui_obj

    @ui_obj.setter
    def ui_obj(self, part):
        ''' create and set the value for ui_obj depending on type '''
        if isinstance(part, Disk):
            self._ui_obj = UIDisk(self.tc, parent=None, doc_obj=part)
        elif isinstance(part, Partition):
            self._ui_obj = UIPartition(self.tc, parent=None, doc_obj=part)
        else:
            # Must be a either a Disk or Partition.  It's an error to be here
            raise RuntimeError("disk_info object is invalid")

    def _init_win(self, window):
        '''Require at least 70 columns and 6 lines to fit current needs for
        display of partitions and slices. Builds two inner ScrollWindows for
        displaying/editing the data.

        '''
        if self.area.columns < 70:
            raise ValueError("Insufficient space - area.columns < 70")
        if self.area.lines < 6:
            raise ValueError("Insufficient space - area.lines < 6")
        self.win_width = (self.area.columns - DiskWindow.DEAD_ZONE
                          + DiskWindow.SCROLL_PAD) / 2

        super(DiskWindow, self)._init_win(window)

        win_area = WindowArea(self.area.lines - 1, self.win_width, 2, 0)
        win_area.scrollable_lines = self.area.lines - 2
        self.left_win = ScrollWindow(win_area, window=self, add_obj=False)
        self.left_win.color = None
        self.left_win.highlight_color = None
        win_area.x_loc = self.win_width + DiskWindow.DEAD_ZONE
        win_area.scrollable_lines = 2 * MAX_EXT_PARTS
        self.right_win = ScrollWindow(win_area, window=self, add_obj=False)
        self.right_win.color = None
        self.right_win.highlight_color = None

    def set_disk_info(self, ui_obj=None, disk_info=None, no_part_ok=False):
        '''Set up this DiskWindow to represent disk_info'''

        if ui_obj is not None:
            disk_info = ui_obj.doc_obj
        elif disk_info is not None:
            self.ui_obj = disk_info
        else:
            # Should never be this case
            raise RuntimeError("Unable to find ui_obj or disk_info")

        part_list = disk_info.get_children(class_type=Partition)
        if part_list:
            self.has_partition_data = True
        else:
            slice_list = disk_info.get_children(class_type=Slice)
            if slice_list:
                self.has_partition_data = False
            else:
                # No partitions and no slices
                if no_part_ok:
                    if self.is_x86:
                        self.has_partition_data = True
                    else:
                        self.has_partition_data = False
                else:
                    return

        if self.has_partition_data:
            if self.editable:
                self.headers = DiskWindow.EDIT_PARTITION_HEADERS
                self.list_area = WindowArea(1, self.headers[0][0] +
                                            self.headers[1][0],
                                            0, DiskWindow.SCROLL_PAD)
                self.edit_area = WindowArea(1, self.headers[1][0], 0,
                                            self.headers[0][0])
            else:
                self.headers = DiskWindow.STATIC_PARTITION_HEADERS
        else:
            if self.editable:
                self.headers = DiskWindow.EDIT_SLICE_HEADERS
                self.list_area = WindowArea(1, self.headers[0][0] +
                                            self.headers[1][0] +
                                            self.headers[2][0],
                                            0, DiskWindow.SCROLL_PAD)
                self.edit_area = WindowArea(1, self.headers[2][0], 0,
                                            self.headers[0][0] +
                                            self.headers[1][0])
            else:
                self.headers = DiskWindow.STATIC_SLICE_HEADERS

        LOGGER.debug("have_partition: %s", self.has_partition_data)
        LOGGER.debug(self.ui_obj)

        self.ui_obj.add_unused_parts(no_part_ok=no_part_ok)

        self.left_win.clear()
        self.right_win.clear()
        self.window.erase()
        self.print_headers()

        if self.editable:
            self.active_object = None
            self.build_edit_fields()
            self.right_win.bottom = max(0, len(self.right_win.all_objects) -
                                        self.right_win.area.lines)
            if self.has_partition_data:
                self.orig_ext_part_field = None
                for obj in self.left_win.objects:
                    if (obj.data_obj.is_extended()):
                        self.orig_ext_part_field = obj
                        self.orig_logicals_active = True
                        break
        else:
            self.print_data()

    def print_headers(self):
        '''Print the headers for the displayed data.

        header[0] - The width of this column. header[1] and header[2] are
                    trimmed to this size
        header[1] - The internationalized text for the left window
        header[2] - The internationalized text for the right window

        '''
        self.left_header_string = []
        self.right_header_string = []
        for header in self.headers:
            left_header_str = header[1]
            right_header_str = header[2]
            # Trim the header to fit in the column width,
            # splitting columns with at least 1 space
            # Pad with extra space(s) to align the columns
            left_header_str = fit_text_truncate(left_header_str,
                                                header[0] - 1, just="left")
            self.left_header_string.append(left_header_str)
            right_header_str = fit_text_truncate(right_header_str,
                                                header[0] - 1, just="left")
            self.right_header_string.append(right_header_str)
        self.left_header_string = " ".join(self.left_header_string)
        self.right_header_string = " ".join(self.right_header_string)
        LOGGER.debug(self.left_header_string)
        self.add_text(self.left_header_string, 0, DiskWindow.SCROLL_PAD)
        right_win_offset = (self.win_width + DiskWindow.DEAD_ZONE +
                            DiskWindow.SCROLL_PAD)
        self.add_text(self.right_header_string, 0, right_win_offset)
        self.window.hline(1, DiskWindow.SCROLL_PAD, curses.ACS_HLINE,
                          textwidth(self.left_header_string))
        self.window.hline(1, right_win_offset, curses.ACS_HLINE,
                          textwidth(self.right_header_string))
        self.no_ut_refresh()

    def print_data(self):
        '''Print static (non-editable) data.

        Slices - fill the left side, then remaining slices on the right side.
        If for some reason not all slices fit, indicate how many more slices
        there area

        Partitions - Put standard partitions on the left, logical partitions
        on the right

        '''

        part_index = 0
        data = self.ui_obj.get_parts_in_use()

        if len(data) == 0:
            return   # should never be this case

        if self.has_partition_data:
            max_parts = MAX_PRIMARY_PARTS
        else:
            max_parts = min(len(data), self.left_win.area.lines)

        win = self.left_win
        y_loc = 0
        for next_data in data:
            LOGGER.debug("next_data: %s", next_data)
            if y_loc >= max_parts:
                if win is self.left_win:
                    win = self.right_win
                    y_loc = 0
                    max_parts = win.area.lines
                else:
                    num_extra = len(data) - part_index
                    if self.has_partition_data:
                        more_parts_txt = _("%d more partitions") % num_extra
                    else:
                        more_parts_txt = _("%d more slices") % num_extra
                    win.add_text(more_parts_txt, win.area.lines, 3)
                    break
            x_loc = DiskWindow.SCROLL_PAD
            field = 0
            win.add_text(next_data.get_description(), y_loc, x_loc,
                         self.headers[field][0] - 1)
            x_loc += self.headers[field][0]
            field += 1
            if not self.has_partition_data:
                win.add_text(str(next_data.name), y_loc, x_loc,
                             self.headers[field][0] - 1)
                x_loc += self.headers[field][0]
                field += 1
            win.add_text(locale.format("%*.1f", (self.headers[field][0] - 1,
                next_data.size.get(Size.gb_units))), y_loc, x_loc,
                self.headers[field][0] - 1)
            x_loc += self.headers[field][0]
            y_loc += 1
            field += 1
            part_index += 1
        self.right_win.use_vert_scroll_bar = False
        self.no_ut_refresh()

    def build_edit_fields(self):
        '''Build subwindows for editing partition sizes

        For slices, fill the left side, then the right (right side scrolling as
        needed, though this shouldn't happen unless the number of slices on
        disk exceeds 8 for some reason)

        For partitions, fill the left side up to MAX_PRIMARY_PARTS,
        and place all logical partitions on the right.

        '''

        data = self.ui_obj.get_parts_in_use()

        if self.has_partition_data:
            max_left_parts = MAX_PRIMARY_PARTS
        else:
            if len(data) == 0:
                return   # should never be this case
            max_left_parts = min(len(data), self.left_win.area.lines)

        part_iter = iter(data)
        try:
            next_part = part_iter.next()
            self.objects.append(self.left_win)
            for y_loc in range(max_left_parts):
                self.list_area.y_loc = y_loc
                self.create_list_item(next_part, self.left_win, self.list_area)
                next_part = part_iter.next()
            self.objects.append(self.right_win)
            for y_loc in range(self.right_win.area.scrollable_lines):
                self.list_area.y_loc = y_loc
                self.create_list_item(next_part, self.right_win,
                                      self.list_area)
                next_part = part_iter.next()
            if len(data) > max_left_parts:
                self.right_win.use_vert_scroll_bar = True
        except StopIteration:
            if len(self.right_win.all_objects) <= self.right_win.area.lines:
                self.right_win.use_vert_scroll_bar = False
            self.right_win.no_ut_refresh()
        else:
            raise ValueError("Could not fit all partitions in DiskWindow")
        self.no_ut_refresh()

    def create_list_item(self, next_part, win, list_area):
        '''Add an entry for next_part (a Partition or Slice) to
        the DiskWindow

        '''
        list_item = ListItem(list_area, window=win, data_obj=next_part)
        list_item.key_dict.update(DiskWindow.ADD_KEYS)
        edit_field = EditField(self.edit_area, window=list_item,
                               numeric_pad=" ",
                               validate=decimal_valid,
                               on_exit=on_exit_edit,
                               error_win=self.error_win,
                               add_obj=False,
                               data_obj=next_part)
        edit_field.right_justify = True
        edit_field.validate_kwargs["disk_win"] = self
        edit_field.on_exit_kwargs["disk_win"] = self
        edit_field.key_dict.update(DiskWindow.ADD_KEYS)
        self.update_part(part_field=list_item)
        return list_item

    def update_part(self, part_info=None, part_field=None):
        '''Sync changed partition data to the screen.'''
        if part_field is None:
            if part_info is None:
                raise ValueError("Must supply either part_info or part_field")
            part_field = self.find_part_field(part_info)[1]
        elif part_info is None:
            part_info = part_field.data_obj
        elif part_field.data_obj is not part_info:
            raise ValueError("part_field must be a ListItem associated with "
                             "part_info")
        if not isinstance(part_field, ListItem):
            raise TypeError("part_field must be a ListItem associated with "
                            "part_info")
        if self.has_partition_data:
            desc_text = part_info.get_description()
        else:
            desc_length = self.headers[0][0] - 1
            desc_text = "%-*.*s %s" % (desc_length, desc_length,
                                       part_info.get_description(),
                                       part_info.name)
        part_field.set_text(desc_text)
        edit_field = part_field.all_objects[0]
        edit_field.set_text(locale.format("%.1f",
                                          part_info.size.get(Size.gb_units)))
        self.mark_if_destroyed(part_field)
        self._update_edit_field(part_info, part_field, edit_field)

        self.update_avail_space(part_info=part_info)
        if self.has_partition_data:
            if part_info.is_extended():
                self.ext_part_field = part_field

    def _update_edit_field(self, part_info, part_field, edit_field):
        '''If the partition/slice is editable, add it to the .objects list.
        If it's also the part_field that's currently selected, then activate
        the edit field.

        '''
        if part_info.editable():
            part_field.objects = [edit_field]
            active_win = self.get_active_object()
            if active_win is not None:
                if active_win.get_active_object() is part_field:
                    part_field.activate_object(edit_field)
        else:
            edit_field.make_inactive()
            part_field.objects = []
            part_field.active_object = None

    def mark_if_destroyed(self, part_field):
        '''Determine if the partition/slice represented by part_field has
        changed such that its contents will be destroyed.

        '''
        part_info = part_field.data_obj
        destroyed = part_info.modified()
        self.mark_destroyed(part_field, destroyed)

    def mark_destroyed(self, part_field, destroyed):
        '''If destroyed is True, add an asterisk indicating that the
        partition or slice's content will be destroyed during installation.
        Otherwise, clear the asterisk

        '''
        y_loc = part_field.area.y_loc
        x_loc = part_field.area.x_loc - 1
        if part_field in self.right_win.objects:
            win = self.right_win
        else:
            win = self.left_win
        if destroyed:
            win.window.addch(y_loc, x_loc, DiskWindow.DESTROYED_MARK,
                             win.color_theme.inactive)
        else:
            win.window.addch(y_loc, x_loc, InnerWindow.BKGD_CHAR)

    def update_avail_space(self, part_number=None, part_info=None):
        '''Update the 'Avail' column for the specified slice or partition.
        If no number is given, all avail columns are updated

        '''
        if part_number is None and part_info is None:
            self._update_all_avail_space()
        else:
            self._update_avail_space(part_number, part_info)

    def _update_all_avail_space(self):
        '''Update the 'Avail' column for all slices or partitions.'''
        idx = 0
        for item in self.left_win.objects:
            self.update_avail_space(idx)
            idx += 1
        for item in self.right_win.objects:
            self.update_avail_space(idx)
            idx += 1
        y_loc = idx - len(self.left_win.objects)
        if self.has_partition_data:
            x_loc = self.headers[0][0] + self.headers[1][0] + 1
            field = 2
        else:
            x_loc = (self.headers[0][0] + self.headers[1][0] +
                     self.headers[2][0] + 1)
            field = 3
        if y_loc > 0:
            self.right_win.add_text(" " * self.headers[field][0],
                                    y_loc, x_loc)

    def _update_avail_space(self, part_number=None, part_info=None):
        '''Update the 'Avail' column for the specified slice or partition.'''
        if part_number is None:
            win, item = self.find_part_field(part_info)
        elif part_number < len(self.left_win.objects):
            win = self.left_win
            item = win.objects[part_number]
        else:
            win = self.right_win
            item = win.objects[part_number - len(self.left_win.objects)]
        if self.has_partition_data:
            x_loc = self.headers[0][0] + self.headers[1][0] + 1
            field = 2
        else:
            x_loc = (self.headers[0][0] + self.headers[1][0] +
                     self.headers[2][0] + 1)
            field = 3
        y_loc = item.area.y_loc
        part = item.data_obj
        max_space = part.get_max_size()
        max_space = locale.format("%*.1f", (self.headers[field][0],
                                             max_space.get(Size.gb_units)))
        win.add_text(max_space, y_loc, x_loc)

    def find_part_field(self, part_info):
        '''Given a PartitionInfo or SliceInfo object, find the associated
        ListItem. This search compares by reference, and will only succeed
        if you have a handle to the exact object referenced by the ListItem

        '''
        for win in [self.left_win, self.right_win]:
            for item in win.objects:
                if item.data_obj is part_info:
                    return win, item
        raise ValueError("Part field not found")

    def reset(self, dummy=None):
        '''Reset ui_obj to value found from Target Discovery.
        Meaningful only for editable DiskWindows

        '''
        if not self.editable:
            return
        doc = InstallEngine.get_instance().doc

        # "reset" the desired target
        reset_obj = None
        if isinstance(self.ui_obj, UIDisk):
            reset_obj = (self.tc.reset_layout(disk=self.ui_obj.doc_obj))[0]
        else:
            # reset the partition by removing the modified Partition, and
            # resetting it with the partition found during target discovery.

            discovered_obj = self.ui_obj.discovered_doc_obj

            desired_disk = get_desired_target_disk(doc)
            desired_part = get_solaris_partition(doc)

            desired_disk.delete_partition(desired_part)
            part_copy = deepcopy(discovered_obj)
            desired_disk.insert_children(part_copy)

            # get the updated reference
            reset_obj = get_solaris_partition(doc)

        dump_doc("After doing reset")

        self.set_disk_info(disk_info=reset_obj)
        self.activate_solaris_data()

    def activate_solaris_data(self):
        '''Find the Solaris Partition / ZFS Root Pool Slice and activate it.

        '''

        if self.editable:
            solaris_part = self.ui_obj.get_solaris_data()
            if solaris_part is None:
                LOGGER.debug("No Solaris data, activating default")
                self.activate_object()
                self.right_win.scroll(scroll_to_line=0)
                return
            disk_order = self.ui_obj.get_parts_in_use().index(solaris_part)
            LOGGER.debug("solaris disk at disk_order = %s", disk_order)
            self.activate_index(disk_order)

    def make_active(self):
        '''On activate, select the solaris partition or ZFS root pool,
        instead of defaulting to 0

        '''
        self.set_color(self.highlight_color)
        self.activate_solaris_data()

    def on_arrow_key(self, input_key):
        '''
        On curses.KEY_LEFT: Move from the right win to the left win
        On curses.KEY_RIGHT: Move from the left to the right

        '''
        if (input_key == curses.KEY_LEFT and
            self.get_active_object() is self.right_win and
            len(self.left_win.objects) > 0):

            active_object = self.right_win.get_active_object().area.y_loc
            if (active_object >= len(self.left_win.objects)):
                active_object = len(self.left_win.objects) - 1
            self.activate_object(self.left_win)
            self.left_win.activate_object(active_object)
            return None
        elif (input_key == curses.KEY_RIGHT and
              self.get_active_object() is self.left_win and
              len(self.right_win.objects) > 0):
            active_line = (self.left_win.active_object +
                             self.right_win.current_line[0])
            active_object = None
            force_to_top = False
            for obj in self.right_win.objects:
                if obj.area.y_loc >= active_line:
                    active_object = obj
                    off_screen = (self.right_win.current_line[0] +
                                  self.right_win.area.lines)
                    if active_object.area.y_loc > off_screen:
                        force_to_top = True
                    break
            if active_object is None:
                active_object = 0
            self.left_win.activate_object(-1, loop=True)
            self.activate_object(self.right_win)
            self.right_win.activate_object_force(active_object,
                                                 force_to_top=force_to_top)
            return None
        return input_key

    def no_ut_refresh(self, abs_y=None, abs_x=None):
        '''Refresh self, left win and right win explicitly'''
        super(DiskWindow, self).no_ut_refresh()
        self.left_win.no_ut_refresh(abs_y, abs_x)
        self.right_win.no_ut_refresh(abs_y, abs_x)

    def change_type(self, dummy):
        '''Cycle the type for the currently active object, and
        update its field

        '''
        LOGGER.debug("changing type")

        part_field = self.get_active_object().get_active_object()
        part_info = part_field.data_obj

        part_order = self.ui_obj.get_parts_in_use().index(part_info)

        old_obj = part_info.discovered_doc_obj
        old_type = list()
        if old_obj is not None:
            if self.has_partition_data:
                old_type.append(old_obj.part_type)
            else:
                if old_obj.in_zpool is not None:
                    old_type.append(old_obj.in_zpool)
                else:
                    in_use = part_info.doc_obj.in_use
                    if in_use is not None:
                        if in_use['used_name']:
                            old_type.append((in_use['used_name'])[0])

        LOGGER.debug("extra type to cycle: %s", old_type)
        part_info.cycle_type(extra_type=old_type)
        self.set_disk_info(ui_obj=self.ui_obj, no_part_ok=True)
        self.activate_index(part_order)

        return None

    def create_extended(self, ext_part_field):
        '''If this is the original extended partition, restore the original
        logical partitions. Otherwise, create a single unused logical
        partition.

        '''
        if not ext_part_field.data_obj.modified():
            self.right_win.clear()
            self.orig_logicals_active = True
            logicals = deepcopy(self._orig_data.get_logicals())
            self.disk_info.partitions.extend(logicals)
            for idx, logical in enumerate(logicals):
                self.list_area.y_loc = idx
                self.create_list_item(logical, self.right_win, self.list_area)
            if self.right_win not in self.objects:
                self.objects.append(self.right_win)
            self.right_win.activate_object_force(0, force_to_top=True)
            self.right_win.make_inactive()
            self.right_win.no_ut_refresh()
        else:
            # Leave old data be, create new Unused logical partition
            if self.right_win not in self.objects:
                self.objects.append(self.right_win)
            self.append_unused_logical()

    def activate_index(self, obj_index):
        '''Activate the object at the specified index '''

        if obj_index < len(self.left_win.objects):
            LOGGER.debug("activating in left_win")
            self.left_win.activate_object(obj_index)
            self.activate_object(self.left_win)
            self.right_win.scroll(scroll_to_line=0)
        else:
            activate = obj_index - len(self.left_win.objects)
            LOGGER.debug('activating in right win')
            self.right_win.activate_object_force(activate, force_to_top=True)
            self.activate_object(self.right_win)
            left_active = self.left_win.get_active_object()
            if left_active is not None:
                left_active.make_inactive()

    def append_unused_logical(self):
        '''Adds a single Unused logical partition to the right window'''
        new_part = self.disk_info.append_unused_logical()
        self.list_area.y_loc = len(self.right_win.all_objects)
        bottom = self.list_area.y_loc - self.right_win.area.lines + 1
        self.right_win.bottom = max(0, bottom)
        self.create_list_item(new_part, self.right_win, self.list_area)
        scroll = len(self.right_win.all_objects) > self.right_win.area.lines
        self.right_win.use_vert_scroll_bar = scroll
        self.right_win.no_ut_refresh()
Exemplo n.º 49
0
    def _show(self):
        '''Create a list of NICs to choose from. If more than 15 NICs are
        found, create a scrolling region to put them in
        
        '''
        self.nic = solaris_install.sysconfig.profile.from_engine().nic
        if self.nic.type != NetworkInfo.MANUAL:
            raise SkipException
        if len(self.ether_nics) == 1:
            self.set_nic_in_profile(self.ether_nics[0])
            raise SkipException

        if self.nic.nic_iface is None:
            selected_nic_name = ""
        else:
            selected_nic_name = NetworkInfo.get_nic_name(self.nic.nic_iface)

        y_loc = 1
        y_loc += self.center_win.add_paragraph(NICSelect.PARAGRAPH, y_loc)

        selected_nic = 0

        y_loc += 1
        max_nics = min(NICSelect.MAX_NICS, self.center_win.area.lines - y_loc)
        if len(self.ether_nics) > max_nics:
            columns = self.win_size_x - NICSelect.LIST_OFFSET
            win_area = WindowArea(lines=max_nics,
                                  columns=columns,
                                  y_loc=y_loc,
                                  x_loc=NICSelect.LIST_OFFSET,
                                  scrollable_lines=len(self.ether_nics))
            self.scroll_region = ScrollWindow(win_area, window=self.center_win)
            self.list_region = self.scroll_region
            y_loc = 0
        else:
            self.scroll_region = None
            self.list_region = self.center_win

        for nic in self.ether_nics:
            self.list_area.y_loc = y_loc

            #
            # display list item in form of "NIC name (NIC device)" -
            # e.g. "net0 (bge0)"
            # If NIC device is not populated, display just NIC name.
            #
            list_item_text = NetworkInfo.get_nic_desc(nic)

            # list item width
            self.list_area.columns = len(list_item_text) + 1

            list_item = ListItem(self.list_area,
                                 window=self.list_region,
                                 text=list_item_text,
                                 data_obj=nic)
            if NetworkInfo.get_nic_name(nic) == selected_nic_name:
                selected_nic = list_item
            y_loc += 1

        self.main_win.do_update()
        if self.scroll_region:
            self.center_win.activate_object(self.scroll_region)
            self.scroll_region.activate_object_force(selected_nic,
                                                     force_to_top=True)
        else:
            self.center_win.activate_object(selected_nic)
Exemplo n.º 50
0
    def test_scroll_down_up_arrow(self):
        '''Test to scroll down and up with arrow key '''
        lines = 4
        extra_lines = 9
        scroll_win = ScrollWindow(WindowArea(lines,
                                             70,
                                             0,
                                             0,
                                             scrollable_lines=lines +
                                             extra_lines),
                                  color_theme=ColorTheme(force_bw=True))
        scroll_win.active_object = None

        self.assertTrue(scroll_win.at_top())
        key = scroll_win.on_arrow_key(curses.KEY_DOWN)
        self.assertEqual(key, None)
        self.assertFalse(scroll_win.at_top())

        key = scroll_win.on_arrow_key(curses.KEY_UP)
        self.assertEqual(key, None)
        self.assertTrue(scroll_win.at_top())

        key = scroll_win.on_arrow_key(curses.KEY_UP)
        self.assertEqual(key, curses.KEY_UP)
        self.assertTrue(scroll_win.at_top())

        scroll_win.scroll(extra_lines - 2)
        self.assertFalse(scroll_win.at_bottom())
        scroll_win.on_arrow_key(curses.KEY_DOWN)
        self.assertTrue(scroll_win.at_bottom())

        scroll_win.scroll(-(extra_lines - 2))
        self.assertFalse(scroll_win.at_top())
        scroll_win.on_arrow_key(curses.KEY_UP)
        self.assertTrue(scroll_win.at_top())
    def test_scroll_right_left_arrow(self):
        '''Test to scroll right and left with arrow key '''
        cols = 3
        extra_cols = 5
        scroll_win = ScrollWindow(WindowArea(10, cols, 0, 0, 
                                  scrollable_columns=cols+extra_cols),
                                  color_theme=ColorTheme(force_bw=True))
        scroll_win.active_object = None

        self.assertTrue(scroll_win.at_left())
        key = scroll_win.on_arrow_key(curses.KEY_RIGHT)
        self.assertEqual(key, None)
        self.assertFalse(scroll_win.at_left())

        key = scroll_win.on_arrow_key(curses.KEY_LEFT)
        self.assertEqual(key, None)
        self.assertTrue(scroll_win.at_left())

        key = scroll_win.on_arrow_key(curses.KEY_LEFT)
        self.assertEqual(key, curses.KEY_LEFT)
        self.assertTrue(scroll_win.at_left())

        scroll_win.scroll(columns=extra_cols-2)
        self.assertFalse(scroll_win.at_left())
        self.assertFalse(scroll_win.at_right())
        scroll_win.on_arrow_key(curses.KEY_RIGHT)
        self.assertTrue(scroll_win.at_right())
            
        scroll_win.scroll(columns=-(extra_cols-2))
        self.assertFalse(scroll_win.at_left())
        self.assertFalse(scroll_win.at_right())
        scroll_win.on_arrow_key(curses.KEY_LEFT)
        self.assertTrue(scroll_win.at_left())
    def test_scroll_down_up_arrow(self):
        '''Test to scroll down and up with arrow key '''
        lines = 4
        extra_lines = 9
        scroll_win = ScrollWindow(WindowArea(lines, 70, 0, 0, 
                                  scrollable_lines=lines + extra_lines),
                                  color_theme=ColorTheme(force_bw=True))
        scroll_win.active_object = None

        self.assertTrue(scroll_win.at_top())
        key = scroll_win.on_arrow_key(curses.KEY_DOWN)
        self.assertEqual(key, None)
        self.assertFalse(scroll_win.at_top())

        key = scroll_win.on_arrow_key(curses.KEY_UP)
        self.assertEqual(key, None)
        self.assertTrue(scroll_win.at_top())

        key = scroll_win.on_arrow_key(curses.KEY_UP)
        self.assertEqual(key, curses.KEY_UP)
        self.assertTrue(scroll_win.at_top())

        scroll_win.scroll(extra_lines-2)
        self.assertFalse(scroll_win.at_bottom())
        scroll_win.on_arrow_key(curses.KEY_DOWN)
        self.assertTrue(scroll_win.at_bottom())
            
        scroll_win.scroll(-(extra_lines-2))
        self.assertFalse(scroll_win.at_top())
        scroll_win.on_arrow_key(curses.KEY_UP)
        self.assertTrue(scroll_win.at_top())
    def _show(self):
        '''Create a list of disks to choose from and create the window
        for displaying the partition/slice information from the selected
        disk
        
        '''

        self.wait_for_disks()

        discovered_target = self.doc.persistent.get_first_child( \
            name=Target.DISCOVERED)

        LOGGER.debug(discovered_target)
        if discovered_target is None:
            self.center_win.add_paragraph(DiskScreen.NO_DISKS, 1, 1,
                                          max_x=(self.win_size_x - 1))
            return

        self.disks = discovered_target.get_children(class_type=Disk)
        if not self.disks:
            self.center_win.add_paragraph(DiskScreen.NO_TARGETS, 1, 1,
                                          max_x=(self.win_size_x - 1))
            return

        if self._image_size is None:
            try:
                self._image_size = Size(str(get_image_size(LOGGER)) + \
                    Size.mb_units)
                LOGGER.debug("Image_size: %s", self._image_size)
            except:
                # Unable to get the image size for some reason, allow
                # the target controller to use it's default size.
                LOGGER.debug("Unable to get image size") 
                self._image_size = FALLBACK_IMAGE_SIZE

        # initialize the target controller so the min/max size for
        # the installation can be calculated.  Explicitly do not
        # want to select an initial disk at this time in case
        # none of the disks discovered is usable.  The target controller
        # initialization needs to be done everytime we show the disk selection
        # screen so the desired target node in the DOC can be re-populated
        # with information from target discovery.
        self.tc.initialize(image_size=self._image_size, no_initial_disk=True)
         
        # Go through all the disks found and find ones that have
        # enough space for installation.  At the same time, see if any
        # existing disk is the boot disk.  If a boot disk is found, move
        # it to the front of the list
        num_usable_disks = 0
        boot_disk = None
        for disk in self.disks:
            LOGGER.debug("size: %s, min: %s" % \
                         (disk.disk_prop.dev_size, self.minimum_size))
            if disk.disk_prop.dev_size >= self.minimum_size:
                if disk.is_boot_disk():
                    boot_disk = disk
                num_usable_disks += 1
        if boot_disk is not None:
            self.disks.remove(boot_disk)
            self.disks.insert(0, boot_disk)

        if num_usable_disks == 0:
            self.center_win.add_paragraph(DiskScreen.NO_DISKS, 1, 1,
                                          max_x=(self.win_size_x - 1))
            return

        self.main_win.reset_actions()
        self.main_win.show_actions()
        
        y_loc = 1
        self.center_win.add_text(DiskScreen.PARAGRAPH, y_loc, 1)
        
        y_loc += 1
        self.center_win.add_text(self.size_line, y_loc, 1)
        
        y_loc += 2
        self.center_win.add_text(self.disk_header_text, y_loc, 1)
        
        y_loc += 1
        self.center_win.window.hline(y_loc, self.center_win.border_size[1] + 1,
                                     curses.ACS_HLINE,
                                     textwidth(self.disk_header_text))
        
        y_loc += 1
        disk_win_area = WindowArea(4, textwidth(self.disk_header_text) + 2,
                                   y_loc, 0)
        disk_win_area.scrollable_lines = len(self.disks) + 1
        self.disk_win = ScrollWindow(disk_win_area,
                                     window=self.center_win)
        
        disk_item_area = WindowArea(1, disk_win_area.columns - 2, 0, 1)
        disk_index = 0
        len_type = DiskScreen.DISK_HEADERS[0][0] - 1
        len_size = DiskScreen.DISK_HEADERS[1][0] - 1
        len_boot = DiskScreen.DISK_HEADERS[2][0] - 1
        len_dev = DiskScreen.DISK_HEADERS[3][0] - 1
        len_mftr = DiskScreen.DISK_HEADERS[4][0] - 1
        for disk in self.disks:
            disk_text_fields = []
            if disk.disk_prop is None or disk.disk_prop.dev_type is None:
                continue
            type_field = disk.disk_prop.dev_type[:len_type]
            type_field = ljust_columns(type_field, len_type)
            disk_text_fields.append(type_field)
            disk_size = disk.disk_prop.dev_size.get(Size.gb_units)
            size_field = locale.format("%*.1f", (len_size, disk_size))
            disk_text_fields.append(size_field)
            if disk.is_boot_disk():
                bootable_field = "+".center(len_boot)
            else:
                bootable_field = " " * (len_boot)
            disk_text_fields.append(bootable_field)
            device_field = disk.ctd[:len_dev]
            device_field = ljust_columns(device_field, len_dev)
            disk_text_fields.append(device_field)
            vendor = disk.disk_prop.dev_vendor
            if vendor is not None:
                mftr_field = vendor[:len_mftr]
                mftr_field = ljust_columns(mftr_field, len_mftr)
            else:
                mftr_field = " " * len_mftr
            disk_text_fields.append(mftr_field)
            selectable = True
            if disk.disk_prop.dev_size < self.minimum_size:
                note_field = self.too_small_text
                selectable = False
            elif disk_size > Size(MAX_VTOC).get(Size.gb_units):
                note_field = self.too_big_warn
            else:
                note_field = ""
            disk_text_fields.append(note_field)
            disk_text = " ".join(disk_text_fields)
            disk_item_area.y_loc = disk_index
            disk_list_item = ListItem(disk_item_area, window=self.disk_win,
                                      text=disk_text, add_obj=selectable)
            disk_list_item.on_make_active = on_activate
            disk_list_item.on_make_active_kwargs["disk"] = disk
            disk_list_item.on_make_active_kwargs["disk_select"] = self
            disk_index += 1

        self.disk_win.no_ut_refresh()
        
        y_loc += 7
        disk_detail_area = WindowArea(6, 70, y_loc, 1)

        self.disk_detail = DiskWindow(disk_detail_area, self.disks[0],
                                      target_controller=self.tc,
                                      window=self.center_win)
        
        self.main_win.do_update()
        self.center_win.activate_object(self.disk_win)
        self.disk_win.activate_object(self.selected_disk_index)