On 05/ 6/11 03:25 PM, Karen Tung wrote:

Hi Keith,

Thank you for your code review.  Please see my responses inline.

On 05/02/11 13:12, Keith Mitchell wrote:
Hi Karen,

My comments for the UI portion or below. Mostly nits, other than the Threading points I brought up in person.

Thanks,
Keith

General:

The directory structure used to be:

usr/src/cmd/text-install/osol_install/{text_install,profile}/<file>

Originally, this was so that the Text Installer UI could be run without building the gate; I think that stopped working or became rather complicated at some point since the Text Installer went back - in any case, I think it's easier to run from the proto area these days.

Given that, instead of collapsing to text-install/solaris_install (which initially confused me, looking at text-install/solaris_install/__init__.py), can you just collapse it to:
usr/src/cmd/text-install
and
usr/src/cmd/text-install/profile
That makes sense, and it will help to reduce my typing. :-)
We won't need "usr/src/cmd/text-install/profile" since we
are just using DOC objects now. After your suggested update above, we will
have the following:

usr/src/cmd/text-install (all the python files will be here)
usr/src/cmd/text-install/helpfiles  (for all the help files)
usr/src/cmd/svc (this is the SMF service)

Excellent.


Logging:

In a few cases, I'll point out that it's better to use:
logger.debug("my message: %s", my_arg)
rather than
logger.debug("my message: " + my_arg)

The reason is that for the former, if the log level is set such that debug statements are ignored, then the relatively expensive string formatting operation will be skipped; in the latter, the concatenation is done regardless of log level, which isn't desirable. For both the cases I mention and the ones I don't, please update usage.
OK, I wasn't aware that there's a difference, I will pay attention and fix all of them.

If you have code that is run frequently (say a function call that is called in a loop, lots and lots of times), string formatting operations are expensive and could slow down that code significantly. If the formatting is just being done for logging purposes, it may be for nothing, too (for example, if the logging level is set to WARN but the statement is logging.debug()). The syntax logger.debug("my message: %s", my_arg) defers the string formatting to the logging module - if the statement would get ignored, the formatting is skipped, and much time is saved.

It's a minor difference, *most* of the time irrelevant to what we do, but a good habit to be in.


import *:

It's best to avoid 'import *' - it becomes difficult, when coming back to the code later, to figure out where a given function was imported from. I'd suggest replacing with 'import x as y; y.func(); y.variable" etc.
Yes, Drew pointed this out as well.  I have cleaned up all of them now.

Thanks!


if <list> is None or len(<list>) == 0:

These sorts of checks can universally be replaced with a simple: "if <list>:". Both empty lists and None return False in a boolean context.
This is also fixed now.

=========

usr/src/cmd/text-install/solaris_install/__init__.py

41, 90: Nit: Spaces around '='
Fixed.

58/253: StderrCalledProcessError is a subclass of CalledProcessError; based on your usage, you only need CalledProcessError
Fixed.

97: Maybe just me, but it would seem this is bending things a bit more than needed - rather than create all these values here, can we not just invoke eng.register_checkpoint() with desired arguments as part of prepare_engine()? I don't see much gain by separating the data as such.
The reason I have it done this way is I want to have the checkpoint names defined, because some of them are used elsewhere in the text installer app. Since I have the checkpoint names defined, I thought I will
have the checkpoint information defined in the same place too.

I played around with moving the checkpoint information to having it just inside register_checkpoint. It seems to look better. However, I will still need to have the checkpoint names defined separately.

That'll work.


257, 345-348: Nit: Spacing
Fixed.

402: Would it be possible to log the install_data object here? Or does that not provide the same value as before?
Printing the install_data object here is not too useful, since the install_data object only have trivial information about location of the log file...etc.. I think it will be useful to dump the whole DOC here, since all
install related information is now stored in the DOC.
Since we want to provide as much information as possible when there's an install failure,
I will dump both the DOC and the install_data object here.

Sounds like a good idea.


usr/src/cmd/text-install/solaris_install/disk_selection.py

113: Since you never read from the global LOGGER, you don't need to set it as a global - the instances can all be replaced (in this file and elsewhere) with logger (or LOGGER) = logging.getLogger(INSTALL_LOGGER_NAME)
As we discussed, I have fixed the places where I have to get an reference to the logger before the global one is set in the file. For the ones that's needed globally in the file,
I just left them as is.

Sounds good.


128: This looks like it's no longer used and can be deleted.
max_disk_size is used immediately in the next line to calculate the
too_big_warn variable.

I must've blinked when looking at that line, sorry!



247: There's an extraneous set of parentheses here.
You mean this line:

246 LOGGER.debug("size: %s, min: %s",
247 (disk.disk_prop.dev_size, self.minimum_size))

The parentheses is actually needed. However, there's a bug
that the last character for line 246 should be '%', instead of
','. I fixed the bug, but I have to have the parentheses.

Per my previous logger comment, it should be:

246 LOGGER.debug("size: %s, min: %s",
247                          disk.disk_prop.dev_size, self.minimum_size)

;-)


257: This should reference NO_TARGETS still. Also, I think 229 should probably use the NO_DISKS message.
Yes, fixed as suggested.

319, 393: Can you clarify why the handling of GPT labeled disks is being changed?
At this time, GPT labeled disks are not support in the target code. So, I just removed the code for now. When GPT disk support are added to the target code, we can add
the support back in.

They weren't supported initially either. The code there was set to inform the user that the disk was GPT labeled; the user would then be informed that the label would be overwritten with an fdisk label when attempting to go to the next screen.


331: Nit: on_active() has a reference to target controller via "disk_select.tc"; a separate parameter isn't strictly required
Good point.  Remove the extra parameter passed.

355: Nit: Change to:
LOGGER.debug("disk_selection.on_change_screen, saved_index: %s", self.selected_disk_index)
Fixed.

367-389: This function should be collapsed into 359:start_discovery. It shouldn't be necessary to run in a separate thread explicitly (see 362), since you can invoke execute_checkpoints() without blocking. wait_for_disks() on 170 needs to be integrated with some form of callback.
Fixed.

426: Change to "if not parts:"
fixed.

usr/src/cmd/text-install/solaris_install/disk_window.py

250: Change to:
LOGGER.debug("have_partition: %s", self.has_partition_data)
fixed

337: Logging formatting
fixed

345/348: Since the statements are the same now, this can get pulled outside the innermost 'if' block
fixed

458/460: If this doesn't need any special formatting, change %i to %s and remove the cast to int()
fixed

545-546: I'm concerned to see this code removed. Admittedly, it was a workaround for an issue I was having with the "size" field for deleted logical partitions still appearing. Can you point me to the equivalent replacement?
As you indicated below, every time we make any change, the change is done in the DOC, and the UI is completely redraw to display the state of the UI. I think I removed this block of code because it is comparing something to the "original" data which we no longer use. Furthermore, I haven't done much testing in regards to logical partitions. I plan to do that after the initial putback. If I found problems and find the need to
re-use some of all of this code, I will restore it.

Ok.



717-719: Nit: Replace with:
if in_use["used_by"]:
fixed.

723, 852: I don't think it's correct to call activate_solaris_data. The user will want the currently selected field to remain the same. Although after seeing what was done here, I can see perhaps how 545-546 worked; it's re-drawing the entire screen.
Yes, it is not correct to call activate_solaris_data() at these 2 locations. I have changed it so that I will get the index of the selected item before changes to the DOC and re-drawing the entire screen is done. After the screen is re-drawn, I activate the object at the index I saved.

Great, thanks.


764: This function looks like it no longer does any work - please remove it.
yep, removed.

usr/src/cmd/text-install/solaris_install/fdisk_partitions.py

162: Nit: "if not all_slices:"
fixed.

209-212: Could be:
found_parts = bool(all_parts)
fixed

246: This seems to be a behavioral change. The 'if' block there was intended to ensure that if the user selected a given option, moved forward/backward screens, then came back to this screen, the selection would be unchanged.

The functional behavior that needs to be preserved is: after getting to the summary screen, I should be able to hit F2/F3 to bounce between any set of screens without having my selections get modified from what I first chose.
ah, ok.   I guess I miss understood what the original code was checking.
Since there is no flag in the DOC for indicating whether whole disk/whole partition
is to be used, to preserve the original behavior, I added a flag in the
FDiskPart class. This flag will have initial value of true so use_whole_segment is selected. In the on_continue() function, I set it to indicate whether the user selected to
use whole segment or not.

Sounds good.


usr/src/cmd/text-install/solaris_install/install_progress.py

As with TD, the engine should handle the threading now.
Fixed.

usr/src/cmd/text-install/solaris_install/install_status.py

69/80: Should the reference to this object not get pulled from the engine's DOC?
No, because I no longer store this object in the DOC. "install_data" is now
an object that is initialized when the text installer starts.  It
just stores a few "house keeping" information for the text installer.
It just gets passed into the other classes that needs it.
No other DOC components needs to read/write it's value.
I figure that there's no point to store it in the DOC.

Ok, that clarifies.



usr/src/cmd/text-install/solaris_install/log_viewer.py

Same question
same answer. :-)

usr/src/cmd/text-install/solaris_install/partition_edit_screen.py

115, 120, 125: I believe these need to be reverted.
fixed.

177-202: Not the ideal place for this logic, but that's partly my fault. Still, with the "old" stuff we had a function called "create_default_layout()" to cover similar scenarios; perhaps TargetController needs something like create_default_{disk,partition,slice}_layout() functions?
Actually, this logic will be removed once we can boot GPT labeled disks/partitions.
I will put a comment here to indicate that.  We do have functionality
similar to create_default_disk_layout() in the target controller, to take care
of the case where you have an empty disk.  For partition,
there's no need for a "default" layout. If there's no previous partition,
you are required to select the whole partition.

I will put a comment here about the fact that the code should be removed
when GPT labeled disk/partition is supported.

Ok.



Also, what happens with perform_final_validation() here - I doubt it would fail, but what if it does?
perform_final_validation() shouldn't fail. If it does, the whole application will quit. The perform_final_validation() function raise "ValueError" if there's a validation problem.
The user can see the log file to see why.

Ok. I find that strange, but I guess that's a question for target, not text install.



270/282: Why is perform_final_validation() only called for x86_slice_mode here?

I was trying to prevent perform_final_validation() to be called when we are modifying the partition layout, since we don't want to validate the final layout until the slices are also modified.

I forgot that will also block out the case for SPARC. So, I need to change line 270 to
only return only when it is x86 and x86_slice_mode.


usr/src/cmd/text-install/solaris_install/progress.py

No comments

usr/src/cmd/text-install/solaris_install/summary.py

48: Nit: Spaces around '='
fixed

203: Lingering commented line
fixed.

usr/src/cmd/text-install/solaris_install/text-install

No comments

usr/src/cmd/text-install/solaris_install/ti_target_utils.py

51, 52, 53, 55: These variables seem like they should be 'owned' by something in target
I found PART_TYPE_EXTENDED, BOOT_SLICE and BACKUP_SLICE defined in target. So, those will be used. I didn't find 191 defined in target yet. I am going to keep it here for now, and file
a bug against target to define it.

Ok.



75/78: The must_have_target_disk parameter seems at odds with the usage. For example, if there is not target disk, the list returned on 78 by the get_descendants call would be length 0, correct? So there would be an immediate IndexError from trying to get the [0] item from that list, or from trying to call get_children on line 81.
This is one of the first function I wrote when I was working on this, and I think I was trying to be flexible. :-) I will remove the must_have_target_disk parameter from all the functions. I can not think of a case where I use these functions without a desired target. So, the desired
target tree must exist.

Ok.


83-84: Seems odd to raise a RuntimeError here when the DOC has its own mechanism for raising errors when an expected object isn't found.
The get_first_child() function can not accept the not_found_is_err argument. So, I was checking. Now, I have changed it to use get_descendants() call which does support not_found_is_err.

Ah, ok.


Some of the other functions in this file suffer from similar concerns.

537, 553: "Wrong class" errors should be TypeError
Fixed.

571, 580: Nit: Might just be me, but I think these should be ValueErrors (or AttributeErrors?)
Actually, if the objects are not in use, we should never be calling those functions. So, the fact that those function are called is a big problem. That's why I think
they are RuntimeError.

Ok. I'm fine with how it is.

But just to clarify why I brought it up at all, I think it's arguable in either direction; the end result is an uncaught exception, either way. As a general rule I like to see "specific" exceptions (ValueError, AttributeError, TypeError) over "general" ones like RuntimeError, when possible.


566-569: Nit: With how frequently this if/else block is repeated, it might be convenient to have an "obj()" method. Then these could be replaced with:

return self.obj().name

Where obj() returns self.doc_obj or self.empty_space_obj as appropriate (or raises Value/Attribute/RuntimeError if ui_type isn't properly set)

obj() could also be a property, if desired
I remembered started in this route, eventually, I abandoned it. This is because if I were to go this route, I would need to define functions in the EmptySpace object parallel to all the functions defined for the Partition object. I also want to use the same EmptySpace object for the Slices. Slice objects have some different functions/properties defined for it than Partition objects. After I rewrote this a few times trying to make it work, I decided to just go with this not elegant route. When I do the re-factoring work you mentioned below to combine UIDisk/UIPartition/UISlice, I can also tackle this
and make it better.

That makes sense. Using obj() would end up replacing all the 'if/else' blocks with 'if isinstance(...)', so there's no real gain unless EmptySpace is fleshed out to be "duck-typed" similar to a Partition object.


738-741: Nit: could be:
return (discovered_size_byte - size_byte > precision)
Fixed

UIDisk/UIPartition/UISlice: There's room to condense this file with a proper abstract parent class. There's quite a bit of very similar code in functions of the same name. Admittedly an existing problem, of sorts, and not immediately critical; though filing a bug to follow-up and address this later would be good, if there's not time/inclination to do so now.
Since these classes are so critical to the UI layout, and took me a long time to get them right,
I don't want to take the risk of doing major restructuring now.
I will file a bug to re-examine and improve them later.

Completely agree with that.



1116: I'm concerned by the hardcoding of 'rpool' here (and elsewhere). Is this going to limit us, should we, say, decide to allow the user to enter an arbitrary name for the ROOT POOL in the future?
This is just a temporary limitation. It's my plan to restore the existing text installer's feature of using the next available root pool name. Another bug to fix after my initial putback. :-)

Ok.


usr/src/cmd/text-install/solaris_install/welcome.py

No comments

Thank you so much again for doing the code review.

You're welcome!

- Keith


--Karen


On 04/26/11 01:38 PM, Karen Tung wrote:
Hi everyone,

I am looking for reviewers for changes that move
the Text Installer to the CUD architecture.

I divided up the changes into the following 4 groups.
I would like to get at least 1 person looking at each group.
Please email me privately and let me know which group
you like to review.

I don't think a code walk through is needed, but if you think
having one will be useful, please let me know and I can set one
up on Thurs. AM.

The webrev is at:
http://cr.opensolaris.org/~ktung/text-to-cud/

Please provide me your comments as soon as possible.
I am more than happy to get multiple sets of comments as
you go through the code.

I would like to get most of your comments by COB next Monday, 5/2/2011.







_______________________________________________
caiman-discuss mailing list
[email protected]
http://mail.opensolaris.org/mailman/listinfo/caiman-discuss

Reply via email to