Hi all,
        I believe the final webrev is now available. I'm running the final 
regression tests (so please excuse the two non-collapsed in deltas in the 
webrev) however, they are available at (diff and full):
http://cr.opensolaris.org/~clayb/delete_service/webrev3.diff
http://cr.opensolaris.org/~clayb/delete_service/webrev3

Please let me know if I failed to address anything.

                                                        Thank you,
                                                        Clay

On Mon, 28 Sep 2009, Ethan Quach wrote:

>
>
> Clay Baenziger wrote:
>> Hi Ethan,
>>     Comments in-line. New differential webrev at 
>> http://cr.opensolaris.org/~clayb/delete_service/webrev3.ethan/
>>
>>                 Thank you,
>>                 Clay
>> 
>> On Fri, 25 Sep 2009, Ethan Quach wrote:
>> 
>>> Clay,
>>> 
>>> 
>>> I have some additional comments on the updated webrev ...
>>> 
>>> 
>>> usr/src/cmd/installadm/installadm.c
>>> -----------------------------------
>>> 946 - Don't we need to check to see if we just deleted the
>>>      last service somewhere around here, and if so, disable our
>>>      smf service? Or is this logic somewhere else that I'm missing?
>> 
>> No, apparently sending a SIGTERM to Apache was causing the service to 
>> restart and then stay in maintenance. I now, instead check if we're the 
>> last service and set the service to maintenance and no-longer kill the 
>> apache process (as the SMF stop method does that).
>
> okay.
>
>> 
>>> usr/src/cmd/installadm/installadm_common.py
>>> -------------------------------------------
>>> 36 - What's the significance of using the name "Unix" here?
>> 
>> None much. It was suggested in the code walk through by someone. However, 
>> it has no meaning and perhaps should just be File_ as it just trivially 
>> extends the file class.
>
> Okay, can you please go ahead and make this change then.  My
> concern was that if our goal for this code is for it to approach
> something portable, then naming something that wasn't necessarily
> Unix specific with that name could cause confusion down the line.
>
>>> 65 - In this method, if newlines = False, and blanklines = True,
>>>     what will get returned at 107 when processing a blankline in
>>>     from a file?  An empty string '' ??
>> 
>> An empty string would be returned but from line 104 not 107. Why, are you 
>> thinking a particular use should be warned against in the docstring?
>
> Sorry, that's what I meant to ask about, the earlier return at 105ish.
>
> Let me restate the comment then...
>
> At 107, it returns the empty string to denote to the caller that we're
> out of lines, but if we're returning the empty string at 105 for the
> case above, then won't the caller get confused?
>
> i.e. if we're processing a file with an empty line in the middle of
> the file somewhere, and its being processed with newlines = False and
> blanklines = True, won't this wad of code (readlines() + readline() )
> stop processing in the middle of the file?
>
>>> 
>>> usr/src/cmd/installadm/delete-service.py
>>> ----------------------------------------
>>> 413 - I dislike how you have to visit an additional time just
>>>      to check existence.  I thought there existed some NO_IDX
>>>      exception when searching a list.  If so, you can then just
>>>      wrap 415 in a try
>> 
>> Hi Ethan, there is a ValueError thrown. I think we're getting into pretty 
>> micro-style/optimization here. However, I can change the code from:
>> 
>> To find out this is a value error, try:
>>>>> a=[1,2]
>>>>> a[3]
>> Traceback (most recent call last):
>>   File "<stdin>", line 1, in ?
>> IndexError: list index out of range
>> 
>> (This is what vfstabObj.fields.MOUNT_POINT[idx] could in all fairness 
>> raise)
>> 
>>>>> a.index(3)
>> Traceback (most recent call last):
>>   File "<stdin>", line 1, in ?
>> ValueError: list.index(x): x not in list
>> 
>> (This is what vfstabObj.fields.MOUNT_POINT.index(boot_archive) would raise)
>> 
>> Thus the code now reads:
>>
>>     # look for filesystem in /etc/vfstab
>>     try:
>>             # calculate index for mount point
>>             idx = vfstabObj.fields.MOUNT_POINT.index(boot_archive)
>>             try:
>>                 # remove line containing micro root
>>                 del(vfstabObj.fields.MOUNT_POINT[idx])
>>             except IOError, e:
>>                 sys.stderr.write(str(e) + "\n")
>>         # microroot was not found in /etc/vfstab
>>         except (ValueError, IndexError):
>>             sys.stderr.write (_("Microroot for service %s " +
>>                                 "not in vfstab.\n") % service.serviceName)
>>         return
>>
>>>      try:
>>>          idx = vfstabObj.fields.MOUNT_POINT.index(boot_archive)
>>>
>>>          try:
>>>              # remove line containing micro root
>>>              del(vfstabObj.fields.MOUNT_POINT[idx])
>>>          except IOError, e:
>>>              sys.stderr.write(str(e) + "\n")
>>>
>>>      except NO_INDEX_OR_WHATEVER_THE_EX_IS, e:
>>>          sys.stderr.write (_("Microroot for service %s " +
>>>                   "not in vfstab.\n") % service.serviceName)
>>> 
>>>
>>>      (Ideally, I would have like to have seen the caller not
>>>       need to handle the idx at all, but I won't push for that
>>>       at this point.)
>> 
>> Dude, I can't make it magically delete things, one has to tell it what you 
>> want to delete. How else would one specify what to delete? This is a list 
>> after all, not an associative array (aka dictionary) as otherwise the 
>> DBFile would have to have knowledge of what columns contain unique data and 
>> which can have repeated data.
>> 
>
> That's part of the point.  Why should the caller need to know if the
> vfstabObj is a list or an array?  Secondly, your current implementation
> has the caller extracting something from the object, just to pass it
> back into the object.  That something is the idx in this case, and
> there doesn't seem to be any value or meaning for the caller to
> ever have to handle that.  So my hinted suggestion was to build a
> member function for the object to hide that detail.  For example,
> the caller code could end up looking like this:
>
>   try:
>       vfstabObj.delentry_by_mntpnt(boot_archive)
>
>       # or if we want to parameterize the field out ...
>       # (this is probably not correct python syntax, but I know
>       # its possible somehow.)
>       # vfstabObj.delentry(com.VFSTAB.fields.MOUNT_POINT, boot_archive)
>
>   except (ValueError, IndexError):
>
>   except IOError, e:
>
>   except Whatever Else:
>
>
> Is this over java-fying the code?
>
> Lastly, as I noted in the original comment, this is not something
> I am not pushing for this in this putback, but since you're asking
> I'm just clarifying what my comment was.
>
> Based on Jan's comment and your filing of 11537, the vfstab
> looks like it may be handled differently altogether in our AI
> server tools, correct?
>
>
>> 
>>> 453 - This doesn't look correct.  The manpage for in.tftpd
>>>      does not say that 'homedir' is the argument to the -s
>>>      option.  In fact, based on the synopsis, it looks like
>>>      'homedir' can float.
>>>
>>>      SYNOPSIS
>>>           in.tftpd [-d] [-T rexmtval] [-s] [homedir]
>>> 
>>>
>>>      So it seems you have to parse fields.SERVER_ARGUMENTS,
>>>      looking for the argument that's not an option, and not
>>>      an option argument.
>> 
>> Thank you for catching this! I've fixed it to take the last argument -- 
>> much easier to parse out too.
>
> Did you check whether or not the [homedir] argument can float?
> Based on the synopsis, [homedir] looks like it can be put anywhere
> in the command line, not necessarily always at the end.  Can you
> verify whether or not this is the case?
>
>> 
>>> 474-478 - I really think we should leave it up to the caller
>>>      to check this, so that the interface of findTFTProot()
>>>      is defined as always to return something, with the default
>>>      being /tftpboot
>>>
>>>      (Looking ahead at your code, the callers already do this
>>>       checking)
>> 
>> Actually this is broken both ways. The callers try to build a path off an 
>> unset baseDir variable. I added a meaningful error for the user that we 
>> can't do much deleting without a TFTProot (this egregious enough I'm 
>> tempted to do a SystemExit, but right now I've added the following checks 
>> after line 501:
>>     else:
>>         sys.stderr.write (_("Unable to remove the grub executable, boot "+
>>                             "archive, or menu.lst file\nwithout a valid "+
>>                             "tftp root directory.\n"))
>
>
> Okay, that's fine.
>
> Comment on new delete_service.py file:
> 471-473 - Can you update this error message to be more clear?
> I couldn't tell from the message that something doesn't exist.
> Here's a suggested rewrite of the comment
>
> "The tftp root directory (%s) found from the configuration
> file (%s) does not exist.  Using default: %s\n"
>
>
> 482-483 - Same comment.
>
> "The tftp root directory (%s) does not exist.\n"
>
>> 
>> 
>>> 500-501, 688-689 - Umm, can you please make findTFTProot()
>>>      cache its answer then.  The chances of someone changing
>>>      /etc/inetd.conf in between time is negligible afaic.
>>>
>>>      And actually, if you do my previously suggested comment,
>>>      you can remove the if()'s at 500 and 688.
>> 
>> As the inetd class will be caching the data this is trivial in code 
>> runtime. And not easily coded (as findTFTProot is a function not a class) 
>> further 500-501, 688-689 are in different scopes (well one's a nested 
>> function of the other but that would be very ugly to understand where those 
>> vars are coming from to get it to persist). If you think this will save 
>> more than 500ms off the runtime of this program I'll profile it to see but 
>> this is trivial and very over-optimizing to concern ourselves with.
>
> Since you're not taking my original comment for 474-478 above,
> nevermind this comment.
>
>> 
>>> 
>>> usr/src/cmd/installadm/delete_client.py 
>>> ---------------------------------------
>>> 41 - this comment isn't needed anymore.
>> 
>> I've changed from:
>> "Parse and validate options when called as delete-client"
>> to:
>> "Parse and validate options"
>> 
>> and for further concern I've changed from parse_client_options to 
>> parse_options.
>
> Okay thanks.
>
>> 
>> Please I'd like to stop working on nits and ensure the program works this 
>> has been out for code review for greater than nearly a month.
>
> You've got a large amount of delta here for the differential though.
> You can't expect to make this much change again and not get an
> initial-like review for the parts that are freshly written.
>
>> 
>>> 43 - is this comment still accurate?
>> 
>> It is, but perhaps changing service to client would cause less confusion as 
>> it returns a client_Data class
>
> That would be a good start.
>
>
> thanks,
> -ethan
>
>
>> 
>>> usr/src/pkgdefs/SUNWinstalladm-tools/prototype_com
>>> --------------------------------------------------
>>> 45-48 - Is there a benefit for doing this symlinking?  Why don't
>>>        we just deliver two binaries, delete-service and
>>>        delete-client?
>> 
>> The symlinks are just to conform to how the other binaries appear in 
>> /usr/lib/installadm. For python to be able to import it needs module names 
>> to conform to [a-zA-Z0-9_]*.py and thus we need to at least deliver 
>> delete_service.py for delete client to import. It seemed prudent to start 
>> moving things that way thus the reason for doing delete_client.py.
>> 
>>> thanks,
>>> -ethan
>>> 
>>> 
>>> Clay Baenziger wrote:
>>>> Hi again all,
>>>>     I got a way to get webrev to work for me to do a differential 
>>>> including delete_service.py (still known as delete-service.py in the 
>>>> differentail webrev). See:
>>>> http://cr.opensolaris.org/~clayb/delete_service/webrev2.diff2/
>>>>
>>>>                             Thank you,
>>>>                             Clay
>>>> 
>>>> On Wed, 23 Sep 2009, Clay Baenziger wrote:
>>>> 
>>>>> Hi again all,
>>>>>     Well the addition of a thousand lines of code and 50+ pages of 
>>>>> comments I think I've got this re-spun for everyone's enjoyment, please 
>>>>> see:
>>>>> 
>>>>> http://cr.opensolaris.org/~clayb/delete_service/webrev2.diff/
>>>>> (Unfortunately I can't get webrev to track that delete-service.py became 
>>>>> delete_service.py (so that it can be imported by delete_client))
>>>>> 
>>>>> Or full webrev:
>>>>> http://cr.opensolaris.org/~clayb/delete_service/webrev2/
>>>>> 
>>>>> The bug list has grown to include:
>>>>> 4526     delete-service is not deleting service as described in section 
>>>>> 4.3.2
>>>>>     ai_design_doc
>>>>> 6587    delete-service shouldn't remove the source image if there's 
>>>>> other
>>>>>     services actives 'linked' to the same source image
>>>>> 8666    create-service: prints out SMF messages no matter what's going 
>>>>> on
>>>>> 8773    create-service followed quickly by delete-service hangs
>>>>> 10740    Need way to interact with SMF from Python for installadm 
>>>>> components
>>>>>     in Python
>>>>> 11292    delete-client: should remove SPARC clients too
>>>>> 11486    delete-service/delete-client: should check inetd.conf for tftp 
>>>>> root
>>>>> 
>>>>> 
>>>>> To Drew:
>>>>> --------
>>>>> To address the ps(1) pain, I consolidated the function down and filed 
>>>>> 11524 - Should look to using PSI (Python System
>>>>>     Information) for Python process management
>>>>> 
>>>>> I looked into Bill's bootadm work but I don't fit an "alternate root" 
>>>>> environment and I'd still need to provide a lot of parsing anyways.
>>>>> 
>>>>> To Sundar:
>>>>> ----------
>>>>> I think our phone call Thursday cleared up your questions?
>>>>> 
>>>>> For those in the code walk-through:
>>>>> -----------------------------------
>>>>> I chose to append our findings of being able to have both a SPARC and 
>>>>> X86 client to a bug on create-client rather than address finding all 
>>>>> possible nooks for a client and spewing lots of not found messages to a 
>>>>> user (or having to catch the messages in funky ways).
>>>>> 
>>>>> Jack:
>>>>> -----
>>>>> Per the agreement between Drew's coding style suggestions, those of 
>>>>> PEP8's hanging indents and Google's Python style guide I've followed 
>>>>> PEP8/Google's Style guide, however, I hope next Tuesday we'll have time 
>>>>> to come to a consensus on Python style there as this should expand past 
>>>>> this one push, of course. Thank you for getting me to think about this 
>>>>> so much!
>>>>>
>>>>>                             Thank you,
>>>>>                             Clay
>>>>> 
>>> 
>>> 
>>> 
>
>

On Mon, 28 Sep 2009, Jack Schwartz wrote:

> Hi Clay.
>
> I can commit to re-reviewing the parts which I commented on earlier and maybe 
> a little more. This is almost like a whole new review and my time is limited. 
> I spent a few hours today, and will spend a few more probably tomorrow.
>
> Is anyone reviewing the new installadm_common.py?  I thought I saw that Drew 
> can't do it.  If you want me to, please explain the syntax for 74 - 93 of 
> installadm_common.py.
>
>   Thanks,
>   Jack
>
> On 09/28/09 09:41, Clay Baenziger wrote:
>> Hi Jack,
>>     I was wondering if you had an ETA when you'd be able to get me your 
>> delete-service code review comments back. Ethan and I would really like to 
>> get this pushed as things just keep backing up behind this.
>>                             Thank you,
>>                             Clay
>
>

On Mon, 28 Sep 2009, Evan Layton wrote:

> Hi Clay,
>
> Just a few more comments on the "C" code only...
>
> installadm.c
>
> line 899 - This needs to be changed as we discussed earlier today so
> that we give a bit more description about what this function does. Also we 
> need to add a bit more description on what type of thing 
> SERVICE_DELETE_SCRIPT does. for example maybe saying something like "the 
> remaining clean-up is done by SERVICE_DELETE_SCRIPT" ( if that's at all 
> accurate... ;-) ) would help.
>
> line 1168 The comment here is a bit misleading. What this really does here is 
> if there are no service instances with a state set to "on" the we put the smf 
> service into maintenance mode. We should state that this is what is happening 
> instead of saying it disables something.
>
> Also this points out the fact that the state can either be on or off but 
> there can be a third state where we've temporarily disabled a service 
> instance but still want it to start up the next time the SMF service is 
> started. This transient state is not dealt with in here but is definitely 
> outside the scope of this fix and I believe this is now covered in bug 11604 
> that you filed earlier.
>
> ai_utils.c
> line 166 - It might be helpful to state here why no data out of the handle is 
> needed here instead of just stating that we don't need anything out of the 
> handle here. Maybe something along the lines of saying that the handle is not 
> needed for this call since we not destroying the property stored in the 
> handle.
>
>
> libaiscf_backend.c
> line 82 - This isn't really "bound" to our handle but is stored in the 
> handle. It may make more sense to say "Allocate and initialize a property 
> group and store it in the handle".
>
> line 87 - Same thing but with the instance.
>
> line 90 - maybe "Make sure we have what's needed to run SMF" ?
>
> libaiscf_instance.c
> line 264, 316 - Closure should be closure so that it matches the actual 
> parameter.
>
> libaiscf_service.c
> line 259 - should be "static PyObject *AIservice_print(PyObject *self) {"
>           Also this doesn't actually print anything out does it? Seems
>           like a confusing name for this function. Not a big deal I
>           guess but it could cause confusion. (sorry I didn't notice
>           this before...)
>
>
> -evan
>
> Clay Baenziger wrote:
>> Hi again all,
>>     I got a way to get webrev to work for me to do a differential including 
>> delete_service.py (still known as delete-service.py in the differentail 
>> webrev). See:
>> http://cr.opensolaris.org/~clayb/delete_service/webrev2.diff2/
>>
>>                             Thank you,
>>                             Clay
>> 
>> On Wed, 23 Sep 2009, Clay Baenziger wrote:
>> 
>>> Hi again all,
>>>     Well the addition of a thousand lines of code and 50+ pages of 
>>> comments I think I've got this re-spun for everyone's enjoyment, please 
>>> see:
>>> 
>>> http://cr.opensolaris.org/~clayb/delete_service/webrev2.diff/
>>> (Unfortunately I can't get webrev to track that delete-service.py became 
>>> delete_service.py (so that it can be imported by delete_client))
>>> 
>>> Or full webrev:
>>> http://cr.opensolaris.org/~clayb/delete_service/webrev2/
>>> 
>>> The bug list has grown to include:
>>> 4526     delete-service is not deleting service as described in section 
>>> 4.3.2
>>>     ai_design_doc
>>> 6587    delete-service shouldn't remove the source image if there's other
>>>     services actives 'linked' to the same source image
>>> 8666    create-service: prints out SMF messages no matter what's going on
>>> 8773    create-service followed quickly by delete-service hangs
>>> 10740    Need way to interact with SMF from Python for installadm 
>>> components
>>>     in Python
>>> 11292    delete-client: should remove SPARC clients too
>>> 11486    delete-service/delete-client: should check inetd.conf for tftp 
>>> root
>>> 
>>> 
>>> To Drew:
>>> --------
>>> To address the ps(1) pain, I consolidated the function down and filed 
>>> 11524 - Should look to using PSI (Python System
>>>     Information) for Python process management
>>> 
>>> I looked into Bill's bootadm work but I don't fit an "alternate root" 
>>> environment and I'd still need to provide a lot of parsing anyways.
>>> 
>>> To Sundar:
>>> ----------
>>> I think our phone call Thursday cleared up your questions?
>>> 
>>> For those in the code walk-through:
>>> -----------------------------------
>>> I chose to append our findings of being able to have both a SPARC and X86 
>>> client to a bug on create-client rather than address finding all possible 
>>> nooks for a client and spewing lots of not found messages to a user (or 
>>> having to catch the messages in funky ways).
>>> 
>>> Jack:
>>> -----
>>> Per the agreement between Drew's coding style suggestions, those of PEP8's 
>>> hanging indents and Google's Python style guide I've followed 
>>> PEP8/Google's Style guide, however, I hope next Tuesday we'll have time to 
>>> come to a consensus on Python style there as this should expand past this 
>>> one push, of course. Thank you for getting me to think about this so much!
>>>
>>>                             Thank you,
>>>                             Clay
>>> 
>
>

On Mon, 28 Sep 2009, Sundar Yamunachari wrote:

> Clay Baenziger wrote:
>> Hi again all,
>> Well the addition of a thousand lines of code and 50+ pages of comments I 
>> think I've got this re-spun for everyone's enjoyment, please see:
>> 
>> http://cr.opensolaris.org/~clayb/delete_service/webrev2.diff/
>> (Unfortunately I can't get webrev to track that delete-service.py became 
>> delete_service.py (so that it can be imported by delete_client))
>> 
>> Or full webrev:
>> http://cr.opensolaris.org/~clayb/delete_service/webrev2/
>> 
>> The bug list has grown to include:
>> 4526 delete-service is not deleting service as described in section 4.3.2
>> ai_design_doc
>> 6587 delete-service shouldn't remove the source image if there's other
>> services actives 'linked' to the same source image
>> 8666 create-service: prints out SMF messages no matter what's going on
>> 8773 create-service followed quickly by delete-service hangs
>> 10740 Need way to interact with SMF from Python for installadm components
>> in Python
>> 11292 delete-client: should remove SPARC clients too
>> 11486 delete-service/delete-client: should check inetd.conf for tftp root
>> 
>> 
>> To Drew:
>> --------
>> To address the ps(1) pain, I consolidated the function down and filed 11524 
>> - Should look to using PSI (Python System
>> Information) for Python process management
>> 
>> I looked into Bill's bootadm work but I don't fit an "alternate root" 
>> environment and I'd still need to provide a lot of parsing anyways.
>> 
>> To Sundar:
>> ----------
>> I think our phone call Thursday cleared up your questions?
>> 
>> For those in the code walk-through:
>> -----------------------------------
>> I chose to append our findings of being able to have both a SPARC and X86 
>> client to a bug on create-client rather than address finding all possible 
>> nooks for a client and spewing lots of not found messages to a user (or 
>> having to catch the messages in funky ways).
>> 
>> Jack:
>> -----
>> Per the agreement between Drew's coding style suggestions, those of PEP8's 
>> hanging indents and Google's Python style guide I've followed PEP8/Google's 
>> Style guide, however, I hope next Tuesday we'll have time to come to a 
>> consensus on Python style there as this should expand past this one push, 
>> of course. Thank you for getting me to think about this so much!
>> 
>> Thank you,
>> Clay
>> _______________________________________________
>> caiman-discuss mailing list
>> caiman-discuss at opensolaris.org
>> http://mail.opensolaris.org/mailman/listinfo/caiman-discuss
> Clay,
>
> *delete_service.py:*
> 542, 544: microroot --> boot archive
> 749: Why we need the python2.4 here? I don't like the hard-coded value here.
>
> *installadm_common.py:*
> 53, 65, 109: Suggestion: change the name of the booleans to make it clearer.
> comments ->skipComments, newlines->removeNewlines and 
> blanklines->skipBlanklines
> 288, 302: What is the difference between __getitem__() and gte()?
> 641: enpty --> empty
> 740-791: function clients(net)
> The output of pntadm -P <net> may have some entries missing some values. For 
> example these four entries are from ins3525-svr. Check whether your code 
> handles all the four entries.
>
> # pntadm -p 10.6.35.0
>
> Client ID Flags Client IP Server IP Lease Expiration Macro Comment
>
> 010003BA866375 03 10.6.35.180 10.6.35.8 Forever 010003BA866375 line2-280r
>
> 0100144F0057A8 03 10.6.35.103 10.6.35.8 Forever 0100144F0057A8       --> No 
> comment field
>
> 00 05   10.6.35.247 10.6.35.8 Zero line2-x4100-sp --> No macro assigned
>
> 010007E923F7A6 05 10.6.35.179 10.6.35.8 06/28/2004       --> No macro or 
> comment
>
>
> *SUNWinstalladm-tools/prototype_com:*
> 46, 47: Why we need these definitions?
>
> Thanks,
> Sundar
>
>

On Wed, 30 Sep 2009, jeanm wrote:

> Clay Baenziger wrote:
>> 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.
> And line 26 which is a general overview of the file. The comment you just 
> made might be nice somewhere since it does explain why
> delete-service is in the delete-client code.
>
>> 
>>> 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 makes sense then. If eventually it will be just one function call with 
> parameters then I'm fine with leaving it in for now.
>> 
>> 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
> Thanks.
>> 
>>> 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"
> So you're saying that the delete-service functionality might need this, 
> correct? In which case I'm fine with it.
>> 
>> 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.
> But if this was really the only reason we would just return a boolean. If 
> however as stated above, delete-service would use it then you have it right.
>> 
>> 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.
> No and the code review utility didn't either. In this particular case I'm 
> fine with leaving this. Other cases it becomes much more distracting. Usually 
> where you have multi line list comprehensions.
>> 
>>> 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.
> Great. Thanks.
>> 
>>> 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().
> Thanks.
>> 
>>> 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?
> Well this went with the comment much further down about parsing the files in 
> general. The idea is that if you got rid of all of the code it would be 
> simpler. However from your response below it appears that having this is good 
> so I'll shut up. ;-)
>
>> 
>>> 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.
> The point was that a lot of people aren't that familiar with reg ex's. Very 
> prone to maintenance mistakes so explaining what it's doing
> and maybe even how would be nice.
>> 
>>> 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)]
> OK.
>> 
>>> 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:
> Same response as above wrt to mountpoint in /etc/vfstab
>> 
>>> 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.
> OK. Seems like something would be wrong it it wasn't executable but it's nice 
> you're fixing the situation since you can. Why abort if you can fix as you're 
> doing.
>> 
>> 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.
> I'd have to disagree. I'd love to see things removed in the appropriate 
> functions. So then you would know if you return from function 
> removeTFTPBootFiles that all the tftpboot files are gone. I'd be confused it 
> they weren't.
>> 
>> 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
> Can they be removed in the functions?
>> 
>> As well as (for services):
>> check_wanboot_conf (for SPARC)
>>        -  or  -
>> removeTFTPBootFiles (X86)
>> 
> But if these actually removed the files then you wouldn't need them to be 
> gone here.
>> 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?
> I think so. Right now you're checking to see if you need to remove a file and 
> placing it in a list. The list is later parsed and the file removed. That's 
> extra computation and complexity. Why not check to see if you need to remove 
> the file and remove it? Unless the file is needed later it's much simpler.
>> 
>>> 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
> The greater extensibility answer was appropriate for my question. Guess I 
> wasn't clear. Sorry. It was a long code review.
>
> Jean
>
>> 
>>> Jean
>>> 
>>> 
>>> 
>>> 
>>> 
>
>

Reply via email to