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()
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)
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)
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()
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
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
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()
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()
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
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
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
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)
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()
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
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
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)
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)
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
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