예제 #1
0
 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)
     logging.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()
예제 #2
0
 def test_textwidth(self):
     ''' test textwidth() '''
     # without tab
     self.assertEqual(textwidth('A\u00c0\u3042'), 1 + 1 + 2)
     self.assertEqual(textwidth('A\u00c0\u3042'.encode(get_encoding())),
                      1 + 1 + 2)
     # with tab
     self.assertEqual(textwidth('\tA\u00c0\u3042'), 4 + 1 + 1 + 2)
     self.assertEqual(textwidth('\tA\u00c0\u3042'.encode(get_encoding())),
                      4 + 1 + 1 + 2)
예제 #3
0
 def get_cursor_loc(self):
     '''Cursor should be positioned at the end of the entered text'''
     win_loc = self.window.getbegyx()
     x_loc = win_loc[1]
     if not self.clear_on_enter:
         x_loc += min(textwidth(self.get_text()), self.area.columns)
     return (win_loc[0], x_loc)
예제 #4
0
 def show_actions(self):
     '''Read through the actions dictionary, displaying all the actions
     descriptive text along the footer (along with a prefix linked to
     its associated keystroke)
     
     '''
     self.footer.window.clear()
     if InnerWindow.USE_ESC:
         prefix = " Esc-"
     else:
         prefix = "  F"
     strings = []
     length = 0
     action_format = "%s%i_%s"
     for key in sorted(self.actions.keys()):
         key_num = key - curses.KEY_F0
         action_text = self.actions[key].text
         action_str = action_format % (prefix, key_num, action_text)
         strings.append(action_str)
     display_str = "".join(strings)
     max_len = self.footer.window.getmaxyx()[1]
     length = textwidth(display_str)
     if not InnerWindow.USE_ESC:
         length += (len(" Esc-") - len("  F")) * len(self.actions)
     if length > max_len:
         raise ValueError("Can't display footer actions - string too long")
     self.footer.window.addstr(display_str.encode(get_encoding()))
     self.footer.window.noutrefresh()
예제 #5
0
    def __init__(self, main_win):
        super(UserScreen, self).__init__(main_win)

        self.max_text_len = (self.win_size_x - UserScreen.PASS_SCREEN_LEN -
                             UserScreen.ITEM_OFFSET) / 2
        max_field = max(textwidth(UserScreen.ROOT_LABEL),
                        textwidth(UserScreen.CONFIRM_LABEL),
                        textwidth(UserScreen.NAME_LABEL),
                        textwidth(UserScreen.USERNAME_LABEL),
                        textwidth(UserScreen.USER_PASS_LABEL))
        self.text_len = min(max_field + 1, self.max_text_len)
        self.list_area = WindowArea(1, self.text_len, 0,
                                    UserScreen.ITEM_OFFSET)
        scrollable_columns = UserInfo.MAX_PASS_LEN + 1
        self.edit_area = WindowArea(1,
                                    UserScreen.PASS_SCREEN_LEN + 1,
                                    0,
                                    self.text_len,
                                    scrollable_columns=scrollable_columns)
        self.username_edit_area = WindowArea(1, UserInfo.MAX_USERNAME_LEN + 1,
                                             0, self.text_len)
        err_x_loc = 2 * self.max_text_len - self.text_len
        err_width = (self.text_len + UserScreen.PASS_SCREEN_LEN)
        self.error_area = WindowArea(1, err_width, 0, err_x_loc)
        self.root = None
        self.user = None
        self.root_pass_list = None
        self.root_pass_edit = None
        self.root_pass_err = None
        self.root_confirm_err = None
        self.root_confirm_list = None
        self.root_confirm_edit = None
        self.real_name_err = None
        self.real_name_list = None
        self.real_name_edit = None
        self.username_err = None
        self.username_list = None
        self.username_edit = None
        self.user_pass_err = None
        self.user_pass_list = None
        self.user_pass_edit = None
        self.user_confirm_err = None
        self.user_confirm_list = None
        self.user_confirm_edit = None
예제 #6
0
    def __init__(self, main_win):
        super(ZpoolScreen, self).__init__(main_win)

        pool_header_text = []
        for header in ZpoolScreen.POOL_HEADERS:
            header_str = fit_text_truncate(header[1],
                                           header[0] - 1,
                                           just="left")
            pool_header_text.append(header_str)
        self.pool_header_text = " ".join(pool_header_text)

        self.existing_pools = []
        self.num_targets = 0
        max_note_size = ZpoolScreen.POOL_HEADERS[2][0]
        self.too_small_text = ZpoolScreen.TOO_SMALL[:max_note_size]
        self._size_line = None
        self.selected_pool = 0
        self._minimum_size = None
        self._recommended_size = None
        self.pool_win = None

        max_field = max(textwidth(ZpoolScreen.BE_LABEL),
                        textwidth(ZpoolScreen.BE_NAME_EMPTY_ERROR),
                        textwidth(ZpoolScreen.BE_NAME_UNALLOWED_ERROR),
                        textwidth(ZpoolScreen.NO_POOLS))

        self.max_text_len = int((self.win_size_x - ZpoolScreen.BE_SCREEN_LEN -
                                 ZpoolScreen.ITEM_OFFSET) / 2)
        self.text_len = min(max_field + 1, self.max_text_len)
        self.list_area = WindowArea(1, self.text_len, 0,
                                    ZpoolScreen.ITEM_OFFSET)

        self.edit_area = WindowArea(1, ZpoolScreen.BE_SCREEN_LEN + 1, 0,
                                    self.text_len)
        err_x_loc = 2
        err_width = (self.text_len + ZpoolScreen.BE_SCREEN_LEN)
        self.error_area = WindowArea(1, err_width + 1, 0, err_x_loc)
        self.be_name_list = None
        self.be_name_edit = None
        self.be_name_err = None

        self.boot_configuration_item = None
        self.do_copy = False  # Flag indicating if install_profile.pool_name
예제 #7
0
 def _set_text(self, text):
     '''Used internally to bypass the the public
     interface's numeric_pad functionality'''
     if text is None:
         text = u""
     self.clear_text()
     logging.log(LOG_LEVEL_INPUT,
                 "_set_text textwidth=%s, columns=%s, text=%s",
                 textwidth(text), self.area.columns, text)
     length_diff = textwidth(text) - self.area.columns
     if (length_diff > 0):
         self.scroll(columns=length_diff)
     for idx, char in enumerate(text):
         if length_diff > 0 and idx == length_diff:
             self.textbox.do_command(EditField.LARROW_CHAR)
         elif self.masked:
             self.textbox.do_command(self.masked_char)
         else:
             self.textbox.do_command(ord(char))
         self.text.append(char)
     self.no_ut_refresh()
예제 #8
0
    def wait_for_disks(self):
        '''Block while waiting for libtd to finish. Catch F9 and quit
        if needed
        
        '''
        if self.td_handle is None:
            self.start_discovery()
        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()
        if self.td_handle.is_alive():
            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 self.td_handle.is_alive():
                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()

        # Get the list of existing zpools on the
        # system and based on that come up with 
        # a unique name for the root pool 
        index = 1
        pool_name = "rpool"
        while pool_name in self.existing_pools:
            pool_name = "rpool%d" % index
            index += 1

        # Set the SliceInfo.DEFAULT_POOL to the unique
        # pool name
        SliceInfo.DEFAULT_POOL.data = pool_name

        # Export all zpools, which could be imported due to zpool install
        export_zpools()
예제 #9
0
    def __init__(self, main_win):
        super(NetworkTypeScreen, self).__init__(main_win)
        self.hostfield_offset = textwidth(NetworkTypeScreen.HOSTNAME_TEXT)
        self.menu_item_desc_max = (self.win_size_x -
                                   NetworkTypeScreen.ITEM_DESC_OFFSET)

        self.net_type_dict = {}
        self.sys_info = None
        self.automatic = None
        self.manual = None
        self.none_option = None
        self.hostname = None
        self.nic_info = NetworkInfo()
        self.ether_nics = NetworkInfo.find_links()
        self.have_nic = True
        if len(self.ether_nics) == 0:
            self.have_nic = False
예제 #10
0
    def handle_input(self, input_key):
        '''
        For each keystroke, determine if it's a special character (and needs
        to end editing), printable character, or backspace.
        
        For special characters, send the return the done-editing code (CTRL-G),
        and store the special character for processing by parent window
        objects.
        
        If printable, append it to self.text, and try to validate. If
        validation fails, reject the character.
        
        '''
        input_key = self.translate_input(input_key)
        if self.is_special_char(input_key):
            self.input_key = input_key
            return EditField.CMD_DONE_EDIT
        else:
            self.input_key = None
        if isprint(input_key) or (ismeta(input_key)
                                  and input_key < curses.KEY_MIN):
            # isprint: ASCII characters
            # ismeta and < curses.KEY_MIN: Remaining UTF-8 characters
            # > curses.KEY_MIN: Special key such as down arrow, backspace, etc.
            self.text.append(unichr(input_key))
            if not self.is_valid():
                if len(self.text) > 0:
                    self.text.pop()
                return None
            if self.masked:
                input_key = self.masked_char
        elif input_key == curses.KEY_BACKSPACE:
            if len(self.text) > 0:
                del_char = self.text.pop()
                del_width = charwidth(del_char)
                if textwidth(self.get_text()) >= self.area.columns:
                    self.scroll(columns=-del_width)
            self.is_valid()
            # Run self.is_valid here so that any functional side effects can
            # occur, but don't check the return value (removing a character
            # from a valid string should never be invalid, and even if it were,
            # it would not make sense to add the deleted character back in)

        return input_key
예제 #11
0
    def wait_for_disks(self):
        '''Block while waiting for libtd to finish. Catch F9 and quit
        if needed
        
        '''
        if self.td_handle is None:
            self.start_discovery()
        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()
        if self.td_handle.is_alive():
            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 self.td_handle.is_alive():
                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()

        # Get the list of existing zpools on the
        # system and based on that come up with 
        # a unique name for the root pool 
        index = 1
        pool_name = "rpool"
        while pool_name in self.existing_pools:
            pool_name = "rpool%d" % index
            index += 1

        # Set the SliceInfo.DEFAULT_POOL to the unique
        # pool name
        SliceInfo.DEFAULT_POOL.data = pool_name
예제 #12
0
    def display_help_topics(self):
        '''Display the help topics screen.'''

        self.main_win.set_header_text(HelpScreen.HELP_HEADER)
        y_loc = 1

        y_loc += self.center_win.add_paragraph(HelpScreen.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)
        logging.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
        logging.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]
            help_topic = self.get_help_topic(info[0])
            help_topic = topic_format % help_topic
            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)
            help_screens = info[0]
            logging.debug("help_screens=%s", list(help_screens))
            logging.debug("self.screen_last=%s", self.screen_last)
            if self.screen_last in help_screens:
                logging.debug("Set cur_help_idx = %s", idx)
                self.cur_help_idx = idx
        logging.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)
예제 #13
0
    def add_text(self,
                 text,
                 start_y=0,
                 start_x=0,
                 max_chars=None,
                 centered=False):
        '''Add a single line of text to the window
        
        'text' must fit within the specified space, or it will be truncated
        
        '''
        win_y, win_x = self.window.getmaxyx()
        logging.log(
            LOG_LEVEL_INPUT, "start_y=%d, start_x=%d, max_chars=%s, "
            "centered=%s, win_max_x=%s, win_max_y=%s", start_y, start_x,
            max_chars, centered, win_x, win_y)
        max_x = self.window.getmaxyx()[1] - self.border_size[1]
        start_x += self.border_size[1]

        abs_max_chars = max_x - start_x
        if max_chars is None:
            max_chars = abs_max_chars
        else:
            max_chars = min(max_chars, abs_max_chars)

        text = fit_text_truncate(text, max_chars)

        if centered:
            start_x = (max_x - textwidth(text)) / 2 + start_x

        text = unicode(text)
        text = text.encode(get_encoding())
        logging.log(
            LOG_LEVEL_INPUT, "calling addstr with params start_y=%s,"
            "start_x=%s, text=%s", start_y, start_x, text)
        self.window.addstr(start_y, start_x, text)
        self.no_ut_refresh()
예제 #14
0
    def pop_up(self,
               header,
               question,
               left_btn_txt,
               right_btn_txt,
               color=None):
        '''Suspend the current screen, setting the header
        to 'header', presenting the 'question,' and providing two 'buttons'.
        Returns True if the RIGHT button is selected, False if the LEFT is
        selected. The LEFT button is initially selected.
        
        '''

        # Hide the cursor, storing its previous state (visibility) so
        # it can be restored when finished. Then, move the cursor
        # to the default position (in case this terminal type does not support
        # hiding the cursor entirely)
        try:
            old_cursor_state = curses.curs_set(0)
        except curses.error:
            old_cursor_state = 2
        cursor_loc = curses.getsyx()
        curses.setsyx(self.cursor_pos[0], self.cursor_pos[1])

        # Add the header, a border, and the question to the window
        self.popup_win.window.border()
        header_x = (self.popup_win.area.columns - textwidth(header)) / 2
        self.popup_win.add_text(header, 0, header_x)
        y_loc = 2
        y_loc += self.popup_win.add_paragraph(question, y_loc, 2)
        y_loc += 2

        # Set the background color based on the parameter given, or choose
        # a default based on the theme. Set the highlight_color by flipping
        # the A_REVERSE bit of the color
        if color is None:
            color = self.popup_win.color
        self.popup_win.set_color(color)
        highlight_color = color ^ curses.A_REVERSE

        # Create two "buttons" of equal size by finding the larger of the
        # two, and centering them
        max_len = max(textwidth(left_btn_txt), textwidth(right_btn_txt))
        left_btn_txt = " [ %s ]" % left_btn_txt.center(max_len)
        right_btn_txt = " [ %s ]" % right_btn_txt.center(max_len)
        button_len = textwidth(left_btn_txt) + 1
        win_size = self.popup_win.window.getmaxyx()
        left_area = WindowArea(1, button_len, y_loc,
                               (win_size[1] / 2) - (button_len + 2))
        left_button = ListItem(left_area,
                               window=self.popup_win,
                               text=left_btn_txt,
                               color=color,
                               highlight_color=highlight_color)
        right_area = WindowArea(1, button_len, y_loc, win_size[1] / 2 + 2)
        right_button = ListItem(right_area,
                                window=self.popup_win,
                                text=right_btn_txt,
                                color=color,
                                highlight_color=highlight_color)

        # Highlight the left button, clear any errors on the screen,
        # and display the pop up
        self.popup_win.activate_object(left_button)
        self.popup_win.no_ut_refresh()
        self.error_line.clear_err()
        self.do_update()

        self._active_win = self.popup_win
        # Loop until the user selects an option.
        input_key = None
        while input_key != curses.KEY_ENTER:
            input_key = self.getch()
            input_key = self.popup_win.process(input_key)
            if input_key == curses.KEY_LEFT:
                self.popup_win.activate_object(left_button)
            elif input_key == curses.KEY_RIGHT:
                self.popup_win.activate_object(right_button)
            self.do_update()
        self._active_win = self.central_area
        user_selected = (self.popup_win.get_active_object() is right_button)

        # Clear the pop up and restore the previous screen, including the
        # cursor position and visibility
        self.popup_win.clear()
        self.central_area.redrawwin()
        curses.setsyx(cursor_loc[0], cursor_loc[1])
        try:
            curses.curs_set(old_cursor_state)
        except curses.error:
            pass
        self.do_update()

        return user_selected
예제 #15
0
    def _show(self):
        '''Create a list of pools to choose from, ask user to select BE
        name and if we should overwrite pool's boot configuration
        
        '''
        if not self.install_profile.install_to_pool:
            raise SkipException

        if len(self.existing_pools) == 0:
            self.existing_pools.extend(get_zpool_list())
        self.num_targets = 0

        if len(self.existing_pools) == 0:
            self.center_win.add_paragraph(ZpoolScreen.NO_POOLS,
                                          1,
                                          1,
                                          max_x=(self.win_size_x - 1))
            return

        for pool in self.existing_pools:
            free_gb = get_zpool_free_size(pool) / 1024 / 1024 / 1024
            if (get_zpool_free_size(pool) / 1024 / 1024 / 1024 >
                    self.minimum_size):
                self.num_targets += 1
            else:
                logging.info("Skipping pool %s: need %d GB, free %d GB" %
                             (pool, self.minimum_size, free_gb))

        if self.num_targets == 0:
            self.center_win.add_paragraph(ZpoolScreen.NO_TARGETS,
                                          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(ZpoolScreen.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.pool_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.pool_header_text))

        y_loc += 1
        pool_win_area = WindowArea(4,
                                   textwidth(self.pool_header_text) + 2, y_loc,
                                   0)
        pool_win_area.scrollable_lines = len(self.existing_pools) + 1
        self.pool_win = ScrollWindow(pool_win_area, window=self.center_win)

        pool_item_area = WindowArea(1, pool_win_area.columns - 2, 0, 1)
        pool_index = 0
        len_name = ZpoolScreen.POOL_HEADERS[0][0] - 1
        len_size = ZpoolScreen.POOL_HEADERS[2][0] - 1
        for pool in self.existing_pools:
            pool_text_fields = []
            name_field = pool[:len_name]
            name_field = ljust_columns(name_field, len_name)
            pool_text_fields.append(name_field)
            pool_size = get_zpool_free_size(pool) / 1024 / 1024 / 1024
            size_field = "%*.1f" % (len_size, pool_size)
            pool_text_fields.append(size_field)
            selectable = True
            if pool_size < self.minimum_size:
                note_field = self.too_small_text
                selectable = False
            else:
                note_field = ""
            pool_text_fields.append(note_field)
            pool_text = " ".join(pool_text_fields)
            pool_item_area.y_loc = pool_index
            pool_list_item = ListItem(pool_item_area,
                                      window=self.pool_win,
                                      text=pool_text,
                                      add_obj=selectable)
            pool_list_item.on_make_active = on_activate
            pool_list_item.on_make_active_kwargs["pool_select"] = self

            pool_index += 1
        self.pool_win.no_ut_refresh()

        y_loc += 7
        self.list_area.y_loc = y_loc
        y_loc += 2
        self.error_area.y_loc = y_loc
        self.be_name_err = ErrorWindow(self.error_area, window=self.center_win)
        self.be_name_list = ListItem(self.list_area,
                                     window=self.center_win,
                                     text=ZpoolScreen.BE_LABEL)
        self.be_name_edit = EditField(self.edit_area,
                                      window=self.be_name_list,
                                      validate=be_name_valid,
                                      error_win=self.be_name_err,
                                      text=self.install_profile.be_name)

        y_loc += 2
        boot_configuration_width = textwidth(
            ZpoolScreen.OVERWRITE_BOOT_CONFIGURATION_LABEL) + 5
        cols = int((self.win_size_x - boot_configuration_width) / 2)
        boot_configuration_area = WindowArea(1, boot_configuration_width,
                                             y_loc, cols)

        self.boot_configuration_item = MultiListItem(
            boot_configuration_area,
            window=self.center_win,
            text=ZpoolScreen.OVERWRITE_BOOT_CONFIGURATION_LABEL,
            used=self.install_profile.overwrite_boot_configuration)

        self.boot_configuration_item.on_select = on_select_obc
        self.boot_configuration_item.on_select_kwargs["pool_select"] = self

        self.main_win.do_update()
        self.center_win.activate_object(self.pool_win)
        self.pool_win.activate_object(self.selected_pool)
        # Set the flag so that the pool is not copied by on_change_screen,
        # unless on_activate gets called as a result of the user changing
        # the selected pool.
        self.do_copy = False
예제 #16
0
    def _show(self):
        '''Display partition data for selected disk, and present the two
        choices
        
        '''
        if self.x86_slice_mode:
            disk = self.install_profile.disk
            self.disk_info = disk.get_solaris_data()
            if self.disk_info is None:
                err_msg = "Critical error - no Solaris partition found"
                logging.error(err_msg)
                raise ValueError(err_msg)
            logging.debug("bool(self.disk_info.slices)=%s",
                          bool(self.disk_info.slices))
            logging.debug("self.disk_info.modified()=%s",
                          self.disk_info.modified())
            if not self.disk_info.slices or self.disk_info.modified():
                logging.debug("Setting partition.use_whole_segment,"
                              "creating default layout, and skipping")
                self.disk_info.use_whole_segment = True
                # We only do slice level editing on x86 if there are
                # existing slices on an existing (unmodified)Solaris
                # partition
                self.disk_info.create_default_layout()
                raise SkipException
            disp_disk = self.install_profile.original_disk.get_solaris_data()
            logging.debug("Preserved partition with existing slices:"
                          " presenting option to install into a slice")
        else:
            self.disk_info = self.install_profile.disk
            disp_disk = self.install_profile.original_disk
            if self.disk_info.boot:
                bootable = FDiskPart.BOOT_TEXT
            else:
                bootable = u""
            header_text = self.header_text % \
                            {"size" : self.disk_info.size.size_as("gb"),
                             "type" : self.disk_info.type,
                             "bootable" : bootable}
            self.main_win.set_header_text(header_text)

        y_loc = 1
        y_loc += self.center_win.add_paragraph(self.paragraph, start_y=y_loc)

        y_loc += 1
        if self.is_x86 and not self.x86_slice_mode:
            found_parts = bool(self.disk_info.partitions)
        else:
            found_parts = bool(self.disk_info.slices)
        if found_parts:
            next_line = self.found
        else:
            next_line = self.proposed
        y_loc += self.center_win.add_paragraph(next_line, start_y=y_loc)

        y_loc += 1
        disk_win_area = WindowArea(6, 70, y_loc, 0)
        self.disk_win = DiskWindow(disk_win_area,
                                   disp_disk,
                                   window=self.center_win)
        y_loc += disk_win_area.lines

        y_loc += 3
        whole_disk_width = textwidth(self.use_whole) + 3
        cols = (self.win_size_x - whole_disk_width) / 2
        whole_disk_item_area = WindowArea(1, whole_disk_width, y_loc, cols)
        self.whole_disk_item = ListItem(whole_disk_item_area,
                                        window=self.center_win,
                                        text=self.use_whole,
                                        centered=True)

        y_loc += 1
        partial_width = textwidth(self.use_part) + 3
        cols = (self.win_size_x - partial_width) / 2
        partial_item_area = WindowArea(1, partial_width, y_loc, cols)
        self.partial_disk_item = ListItem(partial_item_area,
                                          window=self.center_win,
                                          text=self.use_part,
                                          centered=True)

        self.main_win.do_update()
        if self.disk_info.use_whole_segment:
            self.center_win.activate_object(self.whole_disk_item)
        else:
            self.center_win.activate_object(self.partial_disk_item)
예제 #17
0
    def _show(self):
        '''Display partition data for selected disk, and present the two
        choices
        
        '''
        if self.install_profile.install_to_pool:
            raise SkipException

        if self.x86_slice_mode:
            if len(self.install_profile.disks) > 1:
                # When installing on multiple disks use only whole disk EFI type
                logging.error("Not looking at partitions on multi-dev install")
                raise SkipException
            disk = self.install_profile.disks[0]
            self.disk_info = disk.get_solaris_data()
            if self.disk_info is None:
                # No partitions selected - it's whole disk EFI install
                logging.error("No partitions were selected. Continuing.")
                raise SkipException
            logging.debug("bool(self.disk_info.slices)=%s",
                          bool(self.disk_info.slices))
            logging.debug("self.disk_info.modified()=%s",
                          self.disk_info.modified())
            if not self.disk_info.slices or self.disk_info.modified():
                logging.debug("Setting partition.use_whole_segment,"
                              "creating default layout, and skipping")
                self.disk_info.use_whole_segment = True
                # We only do slice level editing on x86 if there are
                # existing slices on an existing (unmodified)Solaris
                # partition
                self.disk_info.create_default_layout()
                raise SkipException
            disp_disk = self.install_profile.original_disks[
                0].get_solaris_data()
            logging.debug("Preserved partition with existing slices:"
                          " presenting option to install into a slice")
        else:
            if len(self.install_profile.disks) > 1:
                suggested_pool_types = ['mirror']
                if len(self.install_profile.disks) > 2:
                    suggested_pool_types.append('raidz')
                if len(self.install_profile.disks) > 3:
                    suggested_pool_types.append('raidz2')
                if len(self.install_profile.disks) > 4:
                    suggested_pool_types.append('raidz3')

                # Show selected disks
                header_text = self.HEADER_ZPOOL % (SliceInfo.DEFAULT_POOL.data)
                self.main_win.set_header_text(header_text)
                y_loc = 1
                y_loc += self.center_win.add_paragraph(self.SELECTED_DISKS,
                                                       start_y=y_loc)
                for disk in self.install_profile.disks:
                    y_loc += self.center_win.add_paragraph(self.DISK_INFO % {
                        "name": disk.name,
                        "size": disk.size
                    },
                                                           start_y=y_loc)
                y_loc += 2
                y_loc += self.center_win.add_paragraph(self.SELECT_POOL_TYPE,
                                                       start_y=y_loc)
                pool_type_win_area = WindowArea(1, 1, y_loc, 0)
                selected_pool_type = 0
                for pool_type in suggested_pool_types:
                    pool_type_win_area.y_loc = y_loc
                    pool_type_win_area.columns = len(pool_type) + 1
                    list_item = ListItem(pool_type_win_area,
                                         window=self.center_win,
                                         text=pool_type,
                                         data_obj=pool_type)
                    if pool_type == self.selected_pool_type_name:
                        selected_pool_type = list_item
                    y_loc += 1
                    self.main_win.do_update()
                self.center_win.activate_object(selected_pool_type)
            else:
                self.disk_info = self.install_profile.disks[0]
                disp_disk = self.install_profile.original_disks[0]
                if self.disk_info.boot:
                    bootable = FDiskPart.BOOT_TEXT
                else:
                    bootable = ""
                header_text = self.header_text % \
                                {"size" : self.disk_info.size.size_as("gb"),
                                 "type" : self.disk_info.type,
                                 "bootable" : bootable}
                self.main_win.set_header_text(header_text)

        if len(self.install_profile.disks) == 1:
            y_loc = 1
            y_loc += self.center_win.add_paragraph(self.paragraph,
                                                   start_y=y_loc)

            y_loc += 1
            if self.is_x86 and not self.x86_slice_mode:
                found_parts = bool(self.disk_info.partitions)
            else:
                found_parts = bool(self.disk_info.slices)
            if found_parts:
                next_line = self.found
            else:
                next_line = self.proposed
            y_loc += self.center_win.add_paragraph(next_line, start_y=y_loc)

            y_loc += 1
            disk_win_area = WindowArea(6, 70, y_loc, 0)
            self.disk_win = DiskWindow(disk_win_area,
                                       disp_disk,
                                       window=self.center_win)
            y_loc += disk_win_area.lines

            y_loc += 3
            whole_disk_width = textwidth(self.use_whole) + 3
            cols = int((self.win_size_x - whole_disk_width) / 2)
            whole_disk_item_area = WindowArea(1, whole_disk_width, y_loc, cols)
            self.whole_disk_item = ListItem(whole_disk_item_area,
                                            window=self.center_win,
                                            text=self.use_whole,
                                            centered=True)

            y_loc += 1
            partial_width = textwidth(self.use_part) + 3
            cols = int((self.win_size_x - partial_width) / 2)
            partial_item_area = WindowArea(1, partial_width, y_loc, cols)
            self.partial_disk_item = ListItem(partial_item_area,
                                              window=self.center_win,
                                              text=self.use_part,
                                              centered=True)

            self.main_win.do_update()
            if self.disk_info.use_whole_segment:
                self.center_win.activate_object(self.whole_disk_item)
            else:
                self.center_win.activate_object(self.partial_disk_item)
예제 #18
0
    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
        
        '''
        if self.install_profile.install_to_pool:
            raise SkipException

        self.wait_for_disks()
        self.num_targets = 0
        
        if not self.disks:
            self.center_win.add_paragraph(DiskScreen.NO_DISKS, 1, 1,
                                          max_x=(self.win_size_x - 1))
            return
        
        if isinstance(self.disks[0], BaseException):
            if len(self.disks) == 1:
                raise tgt.TgtError(("Unexpected error (%s) during target "
                                    "discovery. See log for details.") %
                                    self.disks[0])
            else:
                self.disks = self.disks[1:]
                logging.warn("Failure in target discovery, but one or more"
                             " disks found. Continuing.")
        
        boot_disk = self.disks[0]
        for disk in self.disks:
            if (disk.size.size_as("gb") > self.minimum_size):
                self.num_targets += 1
            if disk.boot:
                boot_disk = disk
        self.disks.remove(boot_disk)
        self.disks.insert(0, boot_disk)
        
        if self.num_targets == 0:
            self.center_win.add_paragraph(DiskScreen.NO_TARGETS, 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_use = DiskScreen.DISK_HEADERS[0][0] - 1
        len_type = DiskScreen.DISK_HEADERS[1][0] - 1
        len_size = DiskScreen.DISK_HEADERS[2][0] - 1
        len_boot = DiskScreen.DISK_HEADERS[3][0] - 1
        len_dev = DiskScreen.DISK_HEADERS[4][0] - 1
        len_mftr = DiskScreen.DISK_HEADERS[5][0] - 1
        for disk in self.disks:
            disk_text_fields = []
            type_field = disk.type[:len_type]
            type_field = ljust_columns(type_field, len_type)
            disk_text_fields.append(type_field)
            disk_size = disk.size.size_as("gb")
            size_field = "%*.1f" % (len_size, disk_size)
            disk_text_fields.append(size_field)
            if disk.boot:
                bootable_field = "+".center(len_boot)
            else:
                bootable_field = " " * (len_boot)
            disk_text_fields.append(bootable_field)
            device_field = disk.name[:len_dev]
            device_field = ljust_columns(device_field, len_dev)
            disk_text_fields.append(device_field)
            if disk.vendor is not None:
                mftr_field = disk.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_size < self.minimum_size:
                note_field = self.too_small_text
                selectable = False
            elif DiskInfo.GPT in disk.label:
                note_field = DiskScreen.GPT_LABELED
            elif disk_size > SliceInfo.MAX_VTOC.size_as("gb"):
                note_field = self.too_big_warn
            else:
                note_field = ""
            # Use first selectable disk if no disk was used yet
            if disk.used is None and not self.one_disk_used and selectable:
               disk.used = True
               self.one_disk_used = True
            disk_text_fields.append(note_field)
            disk_text = " ".join(disk_text_fields)
            disk_item_area.y_loc = disk_index
            disk_list_item = MultiListItem(disk_item_area, window=self.disk_win,
                                      text=disk_text, add_obj=selectable, used=disk.used)
            disk_list_item.on_make_active = on_activate
            disk_list_item.on_make_active_kwargs["disk_info"] = disk
            disk_list_item.on_make_active_kwargs["disk_select"] = self

            disk_list_item.on_select = on_select
            disk_list_item.on_select_kwargs["disk_info"] = disk
            disk_list_item.on_select_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],
                                      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)
        # Set the flag so that the disk is not copied by on_change_screen,
        # unless on_select gets called as a result of the user changing
        # the selected disks.
        self.do_copy = False
예제 #19
0
 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()
     self.num_targets = 0
     
     if not self.disks:
         self.center_win.add_paragraph(DiskScreen.NO_DISKS, 1, 1,
                                       max_x=(self.win_size_x - 1))
         return
     
     if isinstance(self.disks[0], BaseException):
         if len(self.disks) == 1:
             raise tgt.TgtError(("Unexpected error (%s) during target "
                                 "discovery. See log for details.") %
                                 self.disks[0])
         else:
             self.disks = self.disks[1:]
             logging.warn("Failure in target discovery, but one or more"
                          " disks found. Continuing.")
     
     boot_disk = self.disks[0]
     for disk in self.disks:
         if (disk.size.size_as("gb") > self.minimum_size):
             self.num_targets += 1
         if disk.boot:
             boot_disk = disk
     self.disks.remove(boot_disk)
     self.disks.insert(0, boot_disk)
     
     if self.num_targets == 0:
         self.center_win.add_paragraph(DiskScreen.NO_TARGETS, 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 = []
         type_field = disk.type[:len_type]
         type_field = ljust_columns(type_field, len_type)
         disk_text_fields.append(type_field)
         disk_size = disk.size.size_as("gb")
         size_field = "%*.1f" % (len_size, disk_size)
         disk_text_fields.append(size_field)
         if disk.boot:
             bootable_field = "+".center(len_boot)
         else:
             bootable_field = " " * (len_boot)
         disk_text_fields.append(bootable_field)
         device_field = disk.name[:len_dev]
         device_field = ljust_columns(device_field, len_dev)
         disk_text_fields.append(device_field)
         if disk.vendor is not None:
             mftr_field = disk.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_size < self.minimum_size:
             note_field = self.too_small_text
             selectable = False
         elif DiskInfo.GPT in disk.label:
             note_field = DiskScreen.GPT_LABELED
         elif disk_size > SliceInfo.MAX_VTOC.size_as("gb"):
             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_info"] = 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],
                                   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)
     # Set the flag so that the disk is not copied by on_change_screen,
     # unless on_activate gets called as a result of the user changing
     # the selected disk.
     self.do_copy = False