Thanks for the review comments. Applied the comments and the comments are
mentioned inline.

I will share Patch V2 in next email.

From:  Reid Price <r...@nicira.com>
Date:  Tue, 10 Jul 2012 18:57:12 -0700
To:  Arun Sharma <arun.sha...@calsoftinc.com>
Cc:  <dev@openvswitch.org>
Subject:  Re: [ovs-dev] [PATCH] ovs-bugtool: Added --ovs option to get only
ovs related information

A few comments inline

On Tue, Jul 10, 2012 at 12:07 PM, Arun Sharma <arun.sha...@calsoftinc.com>
wrote:
> diff --git a/utilities/bugtool/ovs-bugtool.in <http://ovs-bugtool.in>
> b/utilities/bugtool/ovs-bugtool.in <http://ovs-bugtool.in>
> index 3bafa13..af2bb6e 100755
> --- a/utilities/bugtool/ovs-bugtool.in <http://ovs-bugtool.in>
> +++ b/utilities/bugtool/ovs-bugtool.in <http://ovs-bugtool.in>
> @@ -404,6 +404,10 @@ def main(argv = None):
>      global ANSWER_YES_TO_ALL, SILENT_MODE
>      global entries, data, dbg, unlimited_data
> 
> +    # Filter flags
> +    only_ovs_info = False
> +    filter_data = False
> +
>      # we need access to privileged files, exit if we are not running as root
>      if os.getuid() != 0:
>          print >>sys.stderr, "Error: ovs-bugtool must be run as root"
> 
> @@ -493,6 +500,9 @@ def main(argv = None):
>      if ANSWER_YES_TO_ALL:
>          output("Warning: '--yestoall' argument provided, will not prompt for
> individual files.")
> 
> +    if only_ovs_info:
> +        filter_data = True

It seems like filter_data is redundantly equivalent to only_ovs_info.  Is
this desired?

[Arun] - Its not redundant. Basically the intention was to keep another
variable which will say "collect all information or not."
             Variable name 'filter_data' was kept to identify is there any
kind of filtering required or not.
             If 'filter_data' is False then bug tool should collect all
info. To make it more meaningful, i have renamed this variable to
'collect_all_info'.


> @@ -561,7 +571,7 @@ exclude those logs from the archive.
>      cmd_output(CAP_MULTIPATH, [DMSETUP, 'table'])
>      func_output(CAP_MULTIPATH, 'multipathd_topology', multipathd_topology)
>      cmd_output(CAP_MULTIPATH, [MPPUTIL, '-a'])
> -    if CAP_MULTIPATH in entries:
> +    if CAP_MULTIPATH in entries and not filter_data:
>          dump_rdac_groups(CAP_MULTIPATH)
> 
>      tree_output(CAP_NETWORK_CONFIG, SYSCONFIG_NETWORK_SCRIPTS, IFCFG_RE)
> @@ -609,10 +619,12 @@ exclude those logs from the archive.
>              vspidfile = open(OPENVSWITCH_VSWITCHD_PID)
>              vspid = int(vspidfile.readline().strip())
>              vspidfile.close()
> -            for b in bond_list(vspid):
> -                cmd_output(CAP_NETWORK_STATUS,
> -                           [OVS_APPCTL, '-t', '@RUNDIR@/ovs-vswitchd.%s.ctl'
> % vspid, '-e' 'bond/show %s' % b],
> -                           'ovs-appctl-bond-show-%s.out' % b)
> +            if not filter_data or only_ovs_info:

Won't this always be true, since filter_data == only_ovs_info?
Perhaps you mean 'not filter_data' as you did near line 576 above, or 'not
(filter_data or only_ovs_info)'?

[Arun] - Same comment apply as above for 'filter_data' which is renamed now
to 'collect_all_info'.
             The intention was to collect the information if "no" filtering
is asked or "only ovs info" is asked.
              After renaming the variable, the condition is more meaningful
and self explanatory -
                      if collect_all_info or only_ovs_info:

 
> +                for b in bond_list(vspid):
> +                    cmd_output(CAP_NETWORK_STATUS,
> +                               [OVS_APPCTL, '-t',
> +                                '@RUNDIR@/ovs-vswitchd.%s.ctl' % vspid, '-e'
> 'bond/show %s' % b],
> +                               'ovs-appctl-bond-show-%s.out' % b)

 
> @@ -650,15 +662,30 @@ exclude those logs from the archive.
>      tree_output(CAP_YUM, APT_SOURCES_LIST_D)
>      cmd_output(CAP_YUM, [DPKG_QUERY, '-W', '-f=${Package} ${Version}
> ${Status}\n'], 'dpkg-packages')
> 
> -    try:
> -        load_plugins()
> -    except:
> -        pass
> -
> +    # Filter out ovs related information if --ovs option passed
> +    if only_ovs_info:
> +        ovs_info_caps = [CAP_NETWORK_STATUS, CAP_SYSTEM_LOGS,
> +                         CAP_NETWORK_CONFIG]
> +        ovs_info_list = ['process-tree']
> +        for (k, v) in data.items():
> +            cap = v['cap']
> +            ovs_info = k[0] if v.has_key('filename') else k
> +            if ovs_info not in ovs_info_list and cap not in ovs_info_caps:
> +                del data[k]

Some suggestions, just wrote them inline as comments or by changing the
line.
 - maybe comment on not using iteritems
 - 'in' preferred over 'has_key'
 - pythonisms from 2.6 might not be supported

# We cannot use iteritems, since we modify 'data' as we pass through
for (k, v) in data.items():
    cap = v['cap']
    # if __ else __ isn't supported in python 2.4, which Xen might still use
    # could still do a 1-liner like
    # info = (('filename' in v) and [k[0]] or [k])[0]
    if 'filename' in v:
        info = k[0]
    else:
        info = k
    if info not in ovs_info_list and cap not in ovs_info_caps:
        del data[k]
 
 [Arun] - Done.

> +
> +        load_plugins(False, 'ovs')

python style wants load_plugins(just_capabilities=False, filter='ovs')
I'm unsure why you explicitly mark just_capabilities False here, but leave
it
to be determined by the default below.

[Arun] - Done. I think i can call as below and just_capabilities remains
default False as expected.
              load_plugins(filter='ovs')

This changes the behavior - exceptions from load_plugins(False, 'ovs') will
be raised instead of caught and ignored (as below).  Is this deliberate?
 
[Arun] - Oops, missed out. It was not intentional.

> +    else:
> +       try:
> +           load_plugins()
> +       except:
> +           pass
> +
>      # permit the user to filter out data
> -    for k in sorted(data.keys()):
> -        if not ANSWER_YES_TO_ALL and not yes("Include '%s'? [Y/n]: " % k):
> -            del data[k]
> +    for (k, v) in sorted(data.items()):

I don't know what load_plugins does, but it seems like you might
be able to merge these two iterations through data, if it doesn't effect
things.

[Arun] - It will effect the things if we try to merge. load_plugins adds
key:value in 'data' which
             is basically adding rules to set how to collect information
(could be command output, filename, function returns output).
             In first iteration, which is inside condition (if
only_ovs_info), it deletes some elements from 'data' based on the filtering
condition. 
             Then in second iteration called after load_plugins is called in
any of the above conditions (with or without filtering).
             The second iteration used to prompts user, if they want to
perform another level of filtering by pressing (Y/N) for each data element
to collect.
 
> +       cap = v['cap']
> +       key = k[0] if v.has_key('filename') else k

see comment above about the identical line

[Arun] - Done
 
> +       if not ANSWER_YES_TO_ALL and not yes("Include '%s'? [Y/n]: " % key):
> +           del data[k]
> 
>      # collect selected data now
>      output_ts('Running commands to collect data')
> @@ -773,7 +800,7 @@ def module_info(cap):
> 
> 
>  def multipathd_topology(cap):
> -    pipe = Popen([MULTIPATHD, '-k'], bufsize=1, stdin=PIPE,
> +    pipe = Popen([MULTIPATHD, '-k'], bufsize=1, stdin=PIPE,
>                       stdout=PIPE, stderr=dev_null)
>      stdout, stderr = pipe.communicate('show topology')
> 
> @@ -837,7 +864,7 @@ def dump_rdac_groups(cap):
>                  group, _ = line.split(None, 1)
>                  cmd_output(cap, [MPPUTIL, '-g', group])
> 
> -def load_plugins(just_capabilities = False):
> +def load_plugins(just_capabilities = False, filter = None):

python style prefers no spaces around '=' here, though I see existing code
had it that way.

[Arun] - Done. True, there shouldn't be any space. Initially I thought to
make it consistent with current.
             But after reviewing the code, it was observed in most places
that it does not uses spaces and in few places
             it use spaces. Removed the spaces now.
 
>      def getText(nodelist):
>          rc = ""
>          for node in nodelist:
> @@ -851,7 +878,7 @@ def load_plugins(just_capabilities = False):
>          if val in ['true', 'false', 'yes', 'no']:
>              ret = val in ['true', 'yes']
>          return ret
> -
> +
>      for dir in [d for d in os.listdir(PLUGIN_DIR) if
> os.path.isdir(os.path.join(PLUGIN_DIR, d))]:
>          if not caps.has_key(dir):
>              if not os.path.exists("%s/%s.xml" % (PLUGIN_DIR, dir)):
> @@ -881,28 +908,34 @@ def load_plugins(just_capabilities = False):
> 
>          if just_capabilities:
>              continue
> -
> +
>          plugdir = os.path.join(PLUGIN_DIR, dir)
>          for file in [f for f in os.listdir(plugdir) if f.endswith('.xml')]:
>              xmldoc = parse(os.path.join(plugdir, file))
>              assert xmldoc.documentElement.tagName == "collect"
> 
>              for el in xmldoc.documentElement.getElementsByTagName("*"):
> +                filters_tmp = el.getAttribute("filters")
> +                filters = [] if filters_tmp == '' else filters_tmp.split(',')

More post 2.5-ism, perhaps
[Arun] - Done, Used as below
             if filters_tmp == '':
                  filters = []
             else:
                  filters = filters_tmp.split(',')

  filters = filters_tmp and filters_tmp.split(',') or []

>                  if el.tagName == "files":
>                      newest_first = getBoolAttr(el, 'newest_first')
> -                    file_output(dir, getText(el.childNodes).split(),
> -                                newest_first=newest_first)
> +                    if filter == None or filter in filters:

style prefers 'is None'

  if filter is None or filter in filters:

same for below.

[Arun] - Done

> +                        file_output(dir, getText(el.childNodes).split(),
> +                                    newest_first=newest_first)
>                  elif el.tagName == "directory":
>                      pattern = el.getAttribute("pattern")
>                      if pattern == '': pattern = None
>                      negate = getBoolAttr(el, 'negate')
>                      newest_first = getBoolAttr(el, 'newest_first')
> -                    tree_output(dir, getText(el.childNodes), pattern and
> re.compile(pattern) or None,
> -                                negate=negate, newest_first=newest_first)
> +                    if filter == None or filter in filters:
> +                        tree_output(dir, getText(el.childNodes),
> +                                    pattern and re.compile(pattern) or None,
> +                                    negate=negate, newest_first=newest_first)
>                  elif el.tagName == "command":
>                      label = el.getAttribute("label")
>                      if label == '': label = None
> -                    cmd_output(dir, getText(el.childNodes), label)
> +                    if filter == None or filter in filters:
> +                        cmd_output(dir, getText(el.childNodes), label)

It seems like you could move the filter to above the if/elif blocks to avoid
having to get the attributes at all, since you don't use any of that
information
to make the filtering choice.  Is that possible?

[Arun] - I hope here you mean, to keep condition "if filter is None or
filter in filters:" above the if/elif block which is actually common for all
three different kind of elements "files, directory, command". This will help
to avoid fetching attributes of those elements which it will never use if
the condition becomes false.
If this is what you mean? i have fixed this.

Seems reasonable overall.

  -Reid


_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to