Hi Jean,
        Thank you for the review! My comments are in-line.
                                                        Thank you,
                                                        Clay

On Mon, 28 Sep 2009, jeanm wrote:

>
> I found time to do this when I thought I wouldn't. Using the following 
> webrev:
> http://cr.opensolaris.org/~clayb/delete_service/webrev2. I haven't checked to 
> see
> if others have commented on these items. Pardon me if they have.
>
> Also, if you just want to discuss this in the office instead of an email 
> thread I'm fine with that.
> Sometimes it's easier.
>
> Jean
>
>
> usr/src/cmd/installadm/delete_client.py.html
>
> General:
> This is the delete-client file but there are references to delete-service 
> throughout. That causes me to be confused
> since I know they are different and have different functionality. Is this a 
> cut and paste issue? Or similar functionality
> between the two?

I only see delete_service mentioned when the delete_service module is 
called for various functions. This is a shared code approach as 
delete_client is a subset of the functionality exported by delete_service.

> line 78-81: Since you're hardcoding the first %s to installadm why bother 
> with the %s in the first place? I actually
> don't think you even need the 2nd %s. This is run in delete-client. If prog 
> is something other than that, this message
> would be extremely confusing.

This is just to make it more modular as these commands will hopefully all 
collapse down to installadm as soon as create-service becomes Python. 
Until then this just prevents hard coding bits. Yes, prog should be 
delete-client actually to mimick how delete-client reports errors today.

This is achieved using the /usr/lib/installadm/delete-client symlink which 
points to /usr/lib/installadm/delete_client.py. The reason for printing 
the program name is just since it has these two execution possibilities. 
The reason for having the delete_client is so that the module is 
importable by Python (modules needing to be [a-zA-Z0-9_].py.

> line 43: Wouldn't it be more helpful to say a tuple representing....

You want me to be helpful now, that's just too much! Thanks for the 
catch, I've changed it to:

     Returns: A tuple of a class object representing client to delete
              and an options object

> line 62: Why did you hang this off of options?

This is an option the functions expect to be set. This comes from 
delete_service being able to delete an image, so as the comment says:
"we do not deleteImage for a delete-client so set it False"

Further, looking at line 89 (the only place options is really used) we see 
that indeed deleteImage is used there, and we can correlate from line 60 
(the comment) image deletion is hard coded off.

Note: I swapped line 60 (the comment for line 62) and line 61. I 
accidentally got them out of order.

> usr/src/cmd/installadm/delete_service.py.html
>
> lines 837-840 : same comment as lines 78-81 in delete-client.py

Same reasons as with delete_client

> line 64: this really returns a tuple. Same comment as line 62 of 
> delete_client.py

Same fix as delete_client

> General comment: I find that putting comments into the middle of a group of
>   code that is line continued makes the code difficult to read.
> Ex.
>
> 377             files = [image_path,
> 378                 # must strip the leading path separator from image_path 
> as
> 379                 # os.join won't concatenate two absolute paths
> 380                 os.path.join('/var/ai/image-server/images/',
> 381                 image_path.lstrip(os.sep))]

Hrm, I know we talked about this. I find this breaks up the logic so I can 
see the intention behind it. I see the list files consists of only two 
elements:
image_path
os.path.join('var/ai/image-server/images/',image_path.strip(os.sep))

Further, following better formatting allowed by PEP8 I think this should 
be formatted as follows which more clearly shows that it's two separate 
elements in the list:
files = [image_path,
          # must strip the leading path separator from image_path as
          # os.join won't concatenate two absolute paths
          os.path.join('/var/ai/image-server/images/',
                       image_path.lstrip(os.sep))]

Also, do you use an editor or viewer which does syntax highlighting? I 
just realized since my vi is configured for syntax highlighting, comments 
are lighter than code, so I don't even visually notice them -- unless I 
question what the code's doing and this lessens the distraction immensely.

> Another general comment. There are lots of hard coded paths. This makes 
> changes
> to these paths in the future very difficult to maintain in the code.

Yes, I'm not fond of them. This is tracked in 4402 (Pull fixed strings 
in A/I server python code out to a separate module) which is a holder for 
finding an elegant way to pull out these various paths. It seems we should 
have a module we import for various install components and their paths but 
perhaps there's better or different -- it's too big to design that here 
though.

> line 196:
> It would be cleaner to just do
> if not return_val
>   return 1
> return return_val
>
> But you should be sure that return_val is None at the top. Certainly is 
> easier to read and cleaner.

This was accidentally left in from some tinkering I could've sworn I'd 
gotten them.

This is further incredibly inexcusable, as I'm returning -1, 0, 1 which is 
asinine in the days of Python. It should have been something 
transparently obvious to a developer and user (e.g. "failure", "okay", 
"human assistance needed"). I've now ensured these returns are stripped 
from stop_service() and remove_DHCP_macro().

> line 403-425: Seems like there should be a lot simpler way of just removing a 
> line from vfstab.
> Is there?

Um, this seems pretty short?

We've gotta open the file and handle the file not existing, opening, etc. 
(first except on IOError).

Next, we've gotta look for the entry (which will throw a 
ValueError/IndexError depending on where we fail - if we fail).

Lastly, we need to remove the line and need to check that the write took 
(second IOError exception).

Am I missing how this could be streamlined though?

> line 455-456: Boy that looks unmaintainable. If there is a more maintainable 
> way to do this I
> would suggest it. If not, you need a big old comment there.

Thanks to Ethan's code review comments this was changed. Please see 
457-458 from 
http://cr.opensolaris.org/~clayb/delete_service/webrev3.ethan/usr/src/cmd/installadm/delete_service.py.html

However, this was just a simple regex looking for:
"<anything>-s <anything up to a space, stored as path><anything to EOL>"
and replaced that whole string with what was found and stored as path.

> lines 556-559: Seems a little long for list comprehension. I believe we had 
> discussed anything past about
> 2 lines should be considered for breaking up. Could this be done? It would 
> make the code easier to read
> and probably easier to maintain.

Sure, this was two lines but I was asked to expand fn to filename by 
another reviewer. How does it work if just pulled out of the for loop. It 
is three lines still but we get a much cleaner presentation (as it's only 
three statements in three lines):

# build a list of grub menus from baseDir
menus =  [filename for filename in os.listdir(baseDir) if
          # only select files which start with grub menu prefix
           filename.startswith(grub_menu_prefix) and
          # do not select the menu file the service uses
           filename != os.path.basename(menuLst.file_name)]

> line 584: Realistically, could this be in any other field than mountpoint? If 
> not, could this code be simplified?

I'm not sure what code there is to simplify. Line 584 is a comment and the 
next line of code seems trivial to the extreme (just seeing if a string is 
in a list):

(line 587)
if boot_archive in com.MNTTab().fields.MOUNT_POINT:

> line 612: why? It's not already able to be executed? Are we fixing something 
> here that should be fixed elsewhere?

That's the problem is that it's not executable, we're setting it so that 
we can run it. To set the <tftpdir>/rm.<service name> script so we can run 
it, we have to chmod it.

Yes, create-service should get rid of the rm.<service name> scripts. See 
bug: 10853 (create-service:Should consider removing 
/tftpboot/rm.<service|client> scripts). Until then it's an interface were 
someone might stash something so let's honor it until we get rid of them.

As an aside, in the meantime - partially thanks to the 30 create-service 
bugs, the majority of this file is to give us a working foothold from 
which to clean things up. See Drew's comments about how bizarre it is to 
have a script which reverse engineers the entirety of an AI service.

> lines 625-634: Since the point of this function is to remove the tftpboot 
> files, why don't you just remove these files
> if the rmCmd hasn't? It certainly would be more efficient that appending them 
> to files now and removing them later.
> And clearer as to the state of the system after this function is called. 
> Plus, the header comments say the function removes them.

Ah thanks I've fixed the comment. The intention is to not remove anything 
except in the main function body, as this aids in debugging since it 
provides a central list and order, as well as allowing breadcrumbs until 
we've gathered all we can since we're piecing together what's left of a 
service.

The comment now reads:
Handle file removal in /tftpboot by building a list of files to remove:
First, adds pxegrub.<directory pointed to by /tftpboot/<service
  name> i.e. pxegrub.I86PC.OpenSolaris-1
Unmounts directory which is boot archive (will be something like
  I86PC.OpenSolaris-4) and removes /etc/vfstab entry for mount point

Calls /tftpboot/rm.<service name> which should remove:
        /tftpboot/<service name>
        /tftpboot/menu.lst.<service name>
        (if the above aren't removed by the rm.<service name> script they
          are added to the remove list)
Adds /tftpboot/rm.<service name>

Returns: If unable to find tftp root - None
          Success - A list of file paths to remove

> Why not have check_wanboot_conf also make sure everything is cleaned up. Then 
> you don't need the code at 696 ad 699 to
> add onto the fileToRemove list. Could we also then get rid of 714+? I think 
> all that would be left is then explicit files which
> could then just be rm'd. In general this seems more complicated than it needs 
> to be.

We need to remove the files provided by the list filesToRemove which 
has the paths returned by:
find_service_directory
find_image_path

As well as (for services):
check_wanboot_conf (for SPARC)
           -  or  -
removeTFTPBootFiles (X86)

So 714+ gets rid of these collections, not just check_wanboot_conf or 
removeTFTPBootFiles. Further, 696 and 699 are not the same; one is for 
SPARC and thus check_wanboot_conf, while the other is for X86 and thus 
removeTFTPBootFiles.

I'm perhaps missing something in your suggestion here?

> usr/src/cmd/installadm/installadm_common.py
>
> I lied. I say Ethan's comment about Unix. I agree.

I've changed UnixFile() to File_()

> lines 393-494: do we really need to do this in this manner? For example 
> VFSTab creates a database of the vfstab file. So far I've seen the mountpoint 
> field looked at for the boot_archive. Seems like overkill for that. If we 
> foresee needed more detailed parsability in the future I'm fine with it. 
> Otherwise I wonder....

Yup, we only use a few fields from each file but this is pretty simple 
now. Many people felt this functionality would be good to have available 
for general extensibility (and as the inetd.conf was a nit request which 
took ten minutes to add (the time for me to man -s 4 inetd.conf and type) 
it seems pretty trivial now (one just needs to give field names and a 
file name).

I'm not sure what you're asking here, other than is this easy? Yes

> Jean
>
>
>
>
>

Reply via email to