Russell Bryant <russ...@ovn.org> wrote on 25/01/2016 10:06:35 PM:
 
> On 01/16/2016 03:16 AM, Liran Schour wrote:
> > Python idl works now with "monitor_cond" method. Add test
> > for backward compatibility with old "monitor" method.
> > 
> > Signed-off-by: Liran Schour <lir...@il.ibm.com>
> 
> As requested by Andy Zhou, this review is focused on Python specific
> issues, and not necessarily a review to make sure it matches the
> implementation on the server side.
> 
> > diff --git a/python/ovs/db/data.py b/python/ovs/db/data.py
> > index 6baff38..0d382e1 100644
> > --- a/python/ovs/db/data.py
> > +++ b/python/ovs/db/data.py
> > @@ -386,6 +386,18 @@ class Datum(object):
> >              s.append(tail)
> >          return ''.join(s)
> > 
> > +    def diff(self, datum):
> > +        if self.type.n_max > 1 or len(self.values) == 0:
> > +            for k, v in datum.values.iteritems():
> 
> I'm in the middle of submitting a conversion of this library to be
> compatible with Python 3.  One of the patches I just merged was to make
> dict iteration Python 3 compatible.  On this line, you should now use:
> 
>     for k, v in six.iteritems(datum.values):
>

Will fix it.
 
> > +                if k in self.values and v == self.values[k]:
> > +                    del self.values[k]
> > +                else:
> > +                    self.values[k] = v
> > +        else:
> > +            return datum
> > +
> > +        return self
> > +
> >      def as_list(self):
> >          if self.type.is_map():
> >              return [[k.value, v.value] for k, v in 
self.values.iteritems()]
> > diff --git a/python/ovs/db/idl.py b/python/ovs/db/idl.py
> > index 17ed15b..e95f42e 100644
> > --- a/python/ovs/db/idl.py
> > +++ b/python/ovs/db/idl.py
> > @@ -30,6 +30,9 @@ ROW_CREATE = "create"
> >  ROW_UPDATE = "update"
> >  ROW_DELETE = "delete"
> > 
> > +class Update_version():
> 
> Please make new classes inherit from object, like this:
> 
> class Update_version(object):
> 
> If you install flake8 and the hacking flake8 plugin, it should complain
> about this.
> 
> 
> > +    OVSDB_UPDATE =  0,
> > +    OVSDB_UPDATE2 = 1.
> 
> but I'm actually not sure why a class is needed here.  How about just
> constants not wrapped in a class?
>

Right. No need for a class here.

> >  class Idl(object):
> >      """Open vSwitch Database Interface Definition Language (OVSDB 
IDL).
> > @@ -83,6 +86,10 @@ class Idl(object):
> >        currently being constructed, if there is one, or None 
otherwise.
> >  """
> > 
> > +    IDL_S_INITIAL = 0
> > +    IDL_S_MONITOR_REQUESTED = 1
> > +    IDL_S_MONITOR_COND_REQUESTED = 2
> > +
> >      def __init__(self, remote, schema):
> >          """Creates and returns a connection to the database named
> 'db_name' on
> >          'remote', which should be in a form acceptable to
> > @@ -113,6 +120,8 @@ class Idl(object):
> >          self._monitor_request_id = None
> >          self._last_seqno = None
> >          self.change_seqno = 0
> > +        self.uuid = uuid.uuid1()
> 
> I would use uuid.uuid4() here instead of uuid1(), unless you have a
> particular reason to need uuid1().
>

Will use uuid.uuid64() instead.

> > +        self.state = self.IDL_S_INITIAL
> > 
> >          # Database locking.
> >          self.lock_name = None          # Name of lock we need, 
> None if none.
> > @@ -131,6 +140,7 @@ class Idl(object):
> >              table.need_table = False
> >              table.rows = {}
> >              table.idl = self
> > +            table.condition = []
> > 
> >      def close(self):
> >          """Closes the connection to the database.  The IDL will no 
longer
> > @@ -177,11 +187,15 @@ class Idl(object):
> >              if msg is None:
> >                  break
> >              if (msg.type == ovs.jsonrpc.Message.T_NOTIFY
> > +                and msg.method == "update2"
> > +                and len(msg.params) == 2):
> > +                # Database contents changed.
> > +                self.__parse_update(msg.params[1], 
> Update_version.OVSDB_UPDATE2)
> > +            elif (msg.type == ovs.jsonrpc.Message.T_NOTIFY
> >                  and msg.method == "update"
> > -                and len(msg.params) == 2
> > -                and msg.params[0] is None):
> > +                and len(msg.params) == 2):
> >                  # Database contents changed.
> > -                self.__parse_update(msg.params[1])
> > +                self.__parse_update(msg.params[1], 
> Update_version.OVSDB_UPDATE)
> >              elif (msg.type == ovs.jsonrpc.Message.T_REPLY
> >                    and self._monitor_request_id is not None
> >                    and self._monitor_request_id == msg.id):
> > @@ -190,8 +204,13 @@ class Idl(object):
> >                      self.change_seqno += 1
> >                      self._monitor_request_id = None
> >                      self.__clear()
> > -                    self.__parse_update(msg.result)
> > -                except error.Error as e:
> > +                    if self.state == 
self.IDL_S_MONITOR_COND_REQUESTED:
> > +                        self.__parse_update(msg.result, 
> Update_version.OVSDB_UPDATE2)
> > +                    else:
> > +                        assert self.state == 
self.IDL_S_MONITOR_REQUESTED
> > +                        self.__parse_update(msg.result, 
> Update_version.OVSDB_UPDATE)
> > +
> > +                except error.Error, e:
> >                      vlog.err("%s: parse error in received schema: %s"
> >                                % (self._session.get_name(), e))
> >                      self.__error()
> > @@ -211,6 +230,11 @@ class Idl(object):
> >              elif msg.type == ovs.jsonrpc.Message.T_NOTIFY and 
> msg.id == "echo":
> >                  # Reply to our echo request.  Ignore it.
> >                  pass
> > +            elif (msg.type == ovs.jsonrpc.Message.T_ERROR and
> > +                  self.state == self.IDL_S_MONITOR_COND_REQUESTED and
> > +                  self._monitor_request_id == msg.id):
> > +                      if msg.error == "unknown method":
> > +                          self.__send_monitor_request()
> 
> The indentation here is a little odd.  I would expect these last 2 lines
> to be 4 spaces indented from "elif" above.
>

Will fix this.
 
> >              elif (msg.type in (ovs.jsonrpc.Message.T_ERROR,
> >                                 ovs.jsonrpc.Message.T_REPLY)
> >                    and self.__txn_process_reply(msg)):
> > @@ -225,6 +249,21 @@ class Idl(object):
> > 
> >          return initial_change_seqno != self.change_seqno
> > 
> > +    def cond_update(self, table_name, add, remove):
> > +        """Change conditions for this IDL session. If session is 
> not already
> > +        connected, add condtion to table and submit it on 
> send_monitor_request.
> > +        Otherwise  send monitor_cond_update method with the 
> requested changes."""
> > +        table = self.tables.get(table_name)
> > +        if not table:
> > +            raise error.Error('Unknown table "%s"' % table_name)
> > +        if self._session.is_connected():
> > +            self.__send_cond_update(table, add ,remove)
> > +        else:
> > +            if remove:
> > +                raise error.Error('Non-empty remove condition on 
> unconnected'
> > +                                  'idl session')
> > +            self.__add_condition(table, add)
> > +
> >      def wait(self, poller):
> >          """Arranges for poller.block() to wake up when self.run()
> has something
> >          to do or when activity occurs on a transaction on 'self'."""
> > @@ -280,6 +319,21 @@ class Idl(object):
> >          :type updates:  Row
> >          """
> > 
> > +    def __send_cond_update(self, table, add ,remove):
> > +        monitor_cond_update = {table.name: [{"added": add,
> > +                                            "removed": remove}]}
> > +        old_uuid = str(self.uuid)
> > +        self.uuid = uuid.uuid1()
> 
> As with earlier, is uuid1() intentional, or should you just use uuid4() 
?
>

Same as above, will use uuid.uuid64().

> > +        params = [old_uuid, str(self.uuid), monitor_cond_update]
> > +        msg = ovs.jsonrpc.Message.create_request
> ("monitor_cond_update", params)
> > +        msg_id = msg.id
> > +        self._session.send(msg)
> > +
> > +    def __add_condition(self, table, add):
> > +        for clause in add:
> > +            if not clause in table.condition:
> > +                table.condition.append(clause)
> > +
> >      def __clear(self):
> >          changed = False
> > 
> > @@ -337,6 +391,13 @@ class Idl(object):
> >                  self.is_lock_contended = True
> > 
> >      def __send_monitor_request(self):
> > +        if self.state == self.IDL_S_INITIAL:
> > +            self.state = self.IDL_S_MONITOR_COND_REQUESTED
> > +            method = "monitor_cond"
> > +        else:
> > +            self.state = self.IDL_S_MONITOR_REQUESTED
> > +            method = "monitor"
> > +
> >          monitor_requests = {}
> >          for table in self.tables.itervalues():
> >              columns = []
> > @@ -346,23 +407,26 @@ class Idl(object):
> >                      (column not in self.readonly[table.name])):
> >                      columns.append(column)
> >              monitor_requests[table.name] = {"columns": columns}
> > +            if method == "monitor_cond" and table.condition:
> > +                monitor_requests[table.name]["where"] = 
table.condition
> > +                table.condition = None
> > +
> >          msg = ovs.jsonrpc.Message.create_request(
> > -            "monitor", [self._db.name, None, monitor_requests])
> > +            method, [self._db.name, str(self.uuid), 
monitor_requests])
> >          self._monitor_request_id = msg.id
> >          self._session.send(msg)
> > 
> > -    def __parse_update(self, update):
> > +    def __parse_update(self, update, version):
> >          try:
> > -            self.__do_parse_update(update)
> > -        except error.Error as e:
> > +            self.__do_parse_update(update, version)
> > +        except error.Error, e:
> >              vlog.err("%s: error parsing update: %s"
> >                       % (self._session.get_name(), e))
> > 
> > -    def __do_parse_update(self, table_updates):
> > +    def __do_parse_update(self, table_updates, version):
> >          if type(table_updates) != dict:
> >              raise error.Error("<table-updates> is not an object",
> >                                table_updates)
> > -
> 
> This looks like an unrelated formatting change.
>

Right.
 
> >          for table_name, table_update in table_updates.iteritems():
> >              table = self.tables.get(table_name)
> >              if not table:
> > @@ -387,6 +451,11 @@ class Idl(object):
> >                                        'is not an object'
> >                                        % (table_name, uuid_string))
> > 
> > +                if version == Update_version.OVSDB_UPDATE2:
> > +                    if self.__process_update2(table, uuid, 
row_update):
> > +                        self.change_seqno += 1
> > +                    continue
> > +
> >                  parser = ovs.db.parser.Parser(row_update, 
"row-update")
> >                  old = parser.get_optional("old", [dict])
> >                  new = parser.get_optional("new", [dict])
> > @@ -399,6 +468,46 @@ class Idl(object):
> >                  if self.__process_update(table, uuid, old, new):
> >                      self.change_seqno += 1
> > 
> > +    def __process_update2(self, table, uuid, row_update):
> > +        row = table.rows.get(uuid)
> > +        changed = False
> > +        if "delete" in row_update:
> > +            if row:
> > +                del table.rows[uuid]
> > +                self.notify(ROW_DELETE, row)
> > +                changed = True
> > +            else:
> > +                # XXX rate-limit
> > +                vlog.warn("cannot delete missing row %s from table"
> > +                          "%s" % (uuid, table.name))
> > +        elif "insert" in row_update or "initial" in row_update:
> > +            if row:
> > +                vlog.warn("cannot add existing row %s from table"
> > +                          " %s" % (uuid, table.name))
> > +                del table.rows[uuid]
> > +            row = self.__create_row(table, uuid)
> > +            if "insert" in row_update:
> > +                row_update = row_update['insert']
> > +            else:
> > +                row_update = row_update['initial']
> > +            self.__add_default(table, row_update)
> > +            if self.__row_update(table, row, row_update):
> > +                changed = True
> > +                self.notify(ROW_CREATE, row)
> > +        elif "modify" in row_update:
> > +            if not row:
> > +                raise error.Error('Modify non-existing row')
> > +
> > +            self.__apply_diff(table, row, row_update['modify'])
> > +            self.notify(ROW_UPDATE, row,
> > +                        Row.from_json(self, table,
> > +                                      uuid, row_update['modify']))
> > +            changed = True
> > +        else:
> > +            raise error.Error('<row-update> unknown operation',
> > +                              row_update)
> > +        return changed
> > +
> >      def __process_update(self, table, uuid, old, new):
> >          """Returns True if a column changed, False otherwise."""
> >          row = table.rows.get(uuid)
> > @@ -439,6 +548,42 @@ class Idl(object):
> >                  self.notify(op, row, Row.from_json(self, table, uuid, 
old))
> >          return changed
> > 
> > +    def __add_default(self, table, row_update):
> > +        for column in table.columns.itervalues():
> > +            if column.name not in row_update:
> > +                if ((table.name not in self.readonly) or
> > +                    (table.name in self.readonly) and
> > +                    (column.name not in self.readonly[table.name])):
> > +                    if column.type.n_min != 0 and not 
column.type.is_map():
> > +                        if column.type.key.type == 
ovs.db.types.UuidType:
> > +                            row_update[column.name] = 
> ovs.ovsuuid.to_json(column.type.key.type.default)
> 
> Line length here is too long.  Please install 'flake8', re-run
> configure, and then fix any issues it complains about, which should
> include lines that are too long.
> 
> 
> -- 
> Russell Bryant
>

Thanks,
- Liran 


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

Reply via email to