)]}'
{"etc/quantum/plugins/bigswitch/restproxy.ini":[{"author":{"_account_id":6659,"name":"Paul Michali","email":"pc@michali.net","username":"pcm"},"unresolved":false,"context_lines":[{"line_number":53,"context_line":""},{"line_number":54,"context_line":"[ROUTER]"},{"line_number":55,"context_line":"# Specify the default router rules installed in newly created tenant routers"},{"line_number":56,"context_line":"# Specify multiple times for multiple rules "},{"line_number":57,"context_line":"# Format is \u003ctenant\u003e:\u003csource\u003e:\u003cdestination\u003e:\u003caction\u003e"},{"line_number":58,"context_line":"# Optionally, a comma-separated list of nexthops may be included after \u003caction\u003e"},{"line_number":59,"context_line":"# Use an * to specify default for all tenants"}],"source_content_type":"text/x-properties","patch_set":15,"id":"AAAAPn%2F%2F9i4%3D","line":56,"updated":"2013-06-17 11:04:04.000000000","message":"Nit: Extraneous space at end of line","commit_id":"94a699b6c3c9cc1fe02c62c522cb346d2353e142"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":53,"context_line":""},{"line_number":54,"context_line":"[ROUTER]"},{"line_number":55,"context_line":"# Specify the default router rules installed in newly created tenant routers"},{"line_number":56,"context_line":"# Specify multiple times for multiple rules "},{"line_number":57,"context_line":"# Format is \u003ctenant\u003e:\u003csource\u003e:\u003cdestination\u003e:\u003caction\u003e"},{"line_number":58,"context_line":"# Optionally, a comma-separated list of nexthops may be included after \u003caction\u003e"},{"line_number":59,"context_line":"# Use an * to specify default for all tenants"}],"source_content_type":"text/x-properties","patch_set":15,"id":"AAAAPn%2F%2F9EM%3D","line":56,"in_reply_to":"AAAAPn%2F%2F9i4%3D","updated":"2013-06-17 14:43:23.000000000","message":"Done","commit_id":"94a699b6c3c9cc1fe02c62c522cb346d2353e142"}],"quantum/db/migration/alembic_migrations/versions/5918cbddab04_add_tables_for_route.py":[{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":55,"context_line":"                    sa.ForeignKeyConstraint([\u0027router_id\u0027], [\u0027routers.id\u0027],"},{"line_number":56,"context_line":"                                            ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":57,"context_line":"                    sa.PrimaryKeyConstraint(\u0027id\u0027),"},{"line_number":58,"context_line":"                    mysql_engine\u003d\u0027InnoDB\u0027)"},{"line_number":59,"context_line":"    op.create_table(\u0027nexthops\u0027,"},{"line_number":60,"context_line":"                    sa.Column(\u0027rule_id\u0027, sa.Integer(), nullable\u003dFalse),"},{"line_number":61,"context_line":"                    sa.Column(\u0027nexthop\u0027, sa.String(length\u003d64), nullable\u003dFalse),"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAPn%2F%2F7Ng%3D","line":58,"updated":"2013-06-18 06:18:18.000000000","message":"mysql_engine should not be in the migration.","commit_id":"845c977977b5a26faa9084130149e8497ab59063"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":55,"context_line":"                    sa.ForeignKeyConstraint([\u0027router_id\u0027], [\u0027routers.id\u0027],"},{"line_number":56,"context_line":"                                            ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":57,"context_line":"                    sa.PrimaryKeyConstraint(\u0027id\u0027),"},{"line_number":58,"context_line":"                    mysql_engine\u003d\u0027InnoDB\u0027)"},{"line_number":59,"context_line":"    op.create_table(\u0027nexthops\u0027,"},{"line_number":60,"context_line":"                    sa.Column(\u0027rule_id\u0027, sa.Integer(), nullable\u003dFalse),"},{"line_number":61,"context_line":"                    sa.Column(\u0027nexthop\u0027, sa.String(length\u003d64), nullable\u003dFalse),"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAPn%2F%2F52s%3D","line":58,"in_reply_to":"AAAAPn%2F%2F7Ng%3D","updated":"2013-06-18 17:34:58.000000000","message":"Done","commit_id":"845c977977b5a26faa9084130149e8497ab59063"},{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":62,"context_line":"                    sa.ForeignKeyConstraint([\u0027rule_id\u0027], [\u0027routerrules.id\u0027],"},{"line_number":63,"context_line":"                                            ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":64,"context_line":"                    sa.PrimaryKeyConstraint(\u0027rule_id\u0027, \u0027nexthop\u0027),"},{"line_number":65,"context_line":"                    mysql_engine\u003d\u0027InnoDB\u0027)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"def downgrade(active_plugin\u003dNone, options\u003dNone):"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAPn%2F%2F7NQ%3D","line":65,"updated":"2013-06-18 06:18:18.000000000","message":"same as above","commit_id":"845c977977b5a26faa9084130149e8497ab59063"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":62,"context_line":"                    sa.ForeignKeyConstraint([\u0027rule_id\u0027], [\u0027routerrules.id\u0027],"},{"line_number":63,"context_line":"                                            ondelete\u003d\u0027CASCADE\u0027),"},{"line_number":64,"context_line":"                    sa.PrimaryKeyConstraint(\u0027rule_id\u0027, \u0027nexthop\u0027),"},{"line_number":65,"context_line":"                    mysql_engine\u003d\u0027InnoDB\u0027)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"def downgrade(active_plugin\u003dNone, options\u003dNone):"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAPn%2F%2F52o%3D","line":65,"in_reply_to":"AAAAPn%2F%2F7NQ%3D","updated":"2013-06-18 17:34:58.000000000","message":"Done","commit_id":"845c977977b5a26faa9084130149e8497ab59063"}],"quantum/plugins/bigswitch/extensions/routerrule.py":[{"author":{"_account_id":6659,"name":"Paul Michali","email":"pc@michali.net","username":"pcm"},"change_message_id":"9df87d0b410679d4fcb64c16a65172b9f72da5f6","unresolved":false,"context_lines":[{"line_number":35,"context_line":"                \"The number of rules exceeds the maximum %(quota)s.\")"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"# Validates and converts router rules to the appropriate data structure"},{"line_number":39,"context_line":"def convert_to_valid_router_rules(data):"},{"line_number":40,"context_line":"    if not isinstance(data, list):"},{"line_number":41,"context_line":"        msg \u003d _(\"Invalid data format for router rule: \u0027%s\u0027\") % data"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAPX%2F%2F3oI%3D","line":38,"updated":"2013-06-07 02:43:15.000000000","message":"Move down as a docstring for function","commit_id":"735e7fbe1d90e030fc5702a5d1af182608f28365"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":35,"context_line":"                \"The number of rules exceeds the maximum %(quota)s.\")"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"# Validates and converts router rules to the appropriate data structure"},{"line_number":39,"context_line":"def convert_to_valid_router_rules(data):"},{"line_number":40,"context_line":"    if not isinstance(data, list):"},{"line_number":41,"context_line":"        msg \u003d _(\"Invalid data format for router rule: \u0027%s\u0027\") % data"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAPX%2F%2F2WY%3D","line":38,"in_reply_to":"AAAAPX%2F%2F3oI%3D","updated":"2013-06-07 16:22:10.000000000","message":"Done","commit_id":"735e7fbe1d90e030fc5702a5d1af182608f28365"},{"author":{"_account_id":6659,"name":"Paul Michali","email":"pc@michali.net","username":"pcm"},"change_message_id":"9df87d0b410679d4fcb64c16a65172b9f72da5f6","unresolved":false,"context_lines":[{"line_number":68,"context_line":"            if msg:"},{"line_number":69,"context_line":"                LOG.debug(msg)"},{"line_number":70,"context_line":"                raise qexception.InvalidInput(error_message\u003dmsg)"},{"line_number":71,"context_line":"        if (not rule[\u0027action\u0027] \u003d\u003d \u0027permit\u0027 and not rule[\u0027action\u0027] \u003d\u003d \u0027deny\u0027):"},{"line_number":72,"context_line":"            msg \u003d _(\"Action must be either permit or deny.\""},{"line_number":73,"context_line":"                    \" \u0027%s\u0027 was provided\") % rule[\u0027action\u0027]"},{"line_number":74,"context_line":"            LOG.debug(msg)"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAPX%2F%2F3oE%3D","line":71,"updated":"2013-06-07 02:43:15.000000000","message":"remove parens","commit_id":"735e7fbe1d90e030fc5702a5d1af182608f28365"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":68,"context_line":"            if msg:"},{"line_number":69,"context_line":"                LOG.debug(msg)"},{"line_number":70,"context_line":"                raise qexception.InvalidInput(error_message\u003dmsg)"},{"line_number":71,"context_line":"        if (not rule[\u0027action\u0027] \u003d\u003d \u0027permit\u0027 and not rule[\u0027action\u0027] \u003d\u003d \u0027deny\u0027):"},{"line_number":72,"context_line":"            msg \u003d _(\"Action must be either permit or deny.\""},{"line_number":73,"context_line":"                    \" \u0027%s\u0027 was provided\") % rule[\u0027action\u0027]"},{"line_number":74,"context_line":"            LOG.debug(msg)"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAPX%2F%2F2WU%3D","line":71,"in_reply_to":"AAAAPX%2F%2F3oE%3D","updated":"2013-06-07 16:22:10.000000000","message":"Done","commit_id":"735e7fbe1d90e030fc5702a5d1af182608f28365"},{"author":{"_account_id":6659,"name":"Paul Michali","email":"pc@michali.net","username":"pcm"},"change_message_id":"9df87d0b410679d4fcb64c16a65172b9f72da5f6","unresolved":false,"context_lines":[{"line_number":81,"context_line":"    return rules"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"class Routerrule():"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"    @classmethod"},{"line_number":87,"context_line":"    def get_name(cls):"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAPX%2F%2F3oA%3D","line":84,"updated":"2013-06-07 02:43:15.000000000","message":"(object)","commit_id":"735e7fbe1d90e030fc5702a5d1af182608f28365"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":81,"context_line":"    return rules"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"class Routerrule():"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"    @classmethod"},{"line_number":87,"context_line":"    def get_name(cls):"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAPX%2F%2F2WQ%3D","line":84,"in_reply_to":"AAAAPX%2F%2F3oA%3D","updated":"2013-06-07 16:22:10.000000000","message":"Done","commit_id":"735e7fbe1d90e030fc5702a5d1af182608f28365"},{"author":{"_account_id":6659,"name":"Paul Michali","email":"pc@michali.net","username":"pcm"},"unresolved":false,"context_lines":[{"line_number":70,"context_line":"            if msg:"},{"line_number":71,"context_line":"                LOG.debug(msg)"},{"line_number":72,"context_line":"                raise qexception.InvalidInput(error_message\u003dmsg)"},{"line_number":73,"context_line":"        if not rule[\u0027action\u0027] \u003d\u003d \u0027permit\u0027 and not rule[\u0027action\u0027] \u003d\u003d \u0027deny\u0027:"},{"line_number":74,"context_line":"            msg \u003d _(\"Action must be either permit or deny.\""},{"line_number":75,"context_line":"                    \" \u0027%s\u0027 was provided\") % rule[\u0027action\u0027]"},{"line_number":76,"context_line":"            LOG.debug(msg)"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAPX%2F%2F2PE%3D","line":73,"updated":"2013-06-07 17:09:42.000000000","message":"Guess you could say...\n\nif rule[\u0027action\u0027] not in [\u0027permit\u0027, \u0027deny\u0027]:","commit_id":"d999d5b2d57097e6b690a51c37b7d33b7cf606cf"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":70,"context_line":"            if msg:"},{"line_number":71,"context_line":"                LOG.debug(msg)"},{"line_number":72,"context_line":"                raise qexception.InvalidInput(error_message\u003dmsg)"},{"line_number":73,"context_line":"        if not rule[\u0027action\u0027] \u003d\u003d \u0027permit\u0027 and not rule[\u0027action\u0027] \u003d\u003d \u0027deny\u0027:"},{"line_number":74,"context_line":"            msg \u003d _(\"Action must be either permit or deny.\""},{"line_number":75,"context_line":"                    \" \u0027%s\u0027 was provided\") % rule[\u0027action\u0027]"},{"line_number":76,"context_line":"            LOG.debug(msg)"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAPX%2F%2F2Nw%3D","line":73,"in_reply_to":"AAAAPX%2F%2F2PE%3D","updated":"2013-06-07 17:16:02.000000000","message":"Done","commit_id":"d999d5b2d57097e6b690a51c37b7d33b7cf606cf"},{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":48,"context_line":"    for rule in data:"},{"line_number":49,"context_line":"        msg \u003d attr._verify_dict_keys(expected_keys, rule)"},{"line_number":50,"context_line":"        if msg:"},{"line_number":51,"context_line":"            msg \u003d attr._verify_dict_keys(expected_keys + [\u0027nexthops\u0027], rule)"},{"line_number":52,"context_line":"        if msg:"},{"line_number":53,"context_line":"            LOG.debug(msg)"},{"line_number":54,"context_line":"            raise qexception.InvalidInput(error_message\u003dmsg)"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2FyOw%3D","line":51,"updated":"2013-06-10 19:23:38.000000000","message":"Why verify everything twice?","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":48,"context_line":"    for rule in data:"},{"line_number":49,"context_line":"        msg \u003d attr._verify_dict_keys(expected_keys, rule)"},{"line_number":50,"context_line":"        if msg:"},{"line_number":51,"context_line":"            msg \u003d attr._verify_dict_keys(expected_keys + [\u0027nexthops\u0027], rule)"},{"line_number":52,"context_line":"        if msg:"},{"line_number":53,"context_line":"            LOG.debug(msg)"},{"line_number":54,"context_line":"            raise qexception.InvalidInput(error_message\u003dmsg)"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2Fx98%3D","line":51,"in_reply_to":"AAAAPX%2F%2FyOw%3D","updated":"2013-06-10 21:52:28.000000000","message":"Done","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":748,"name":"Armando Migliaccio","email":"armamig@gmail.com","username":"armando-migliaccio"},"unresolved":false,"context_lines":[{"line_number":35,"context_line":"                \"The number of rules exceeds the maximum %(quota)s.\")"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"def convert_to_valid_router_rules(data):"},{"line_number":39,"context_line":"    \"\"\""},{"line_number":40,"context_line":"    Validates and converts router rules to the appropriate data structure"},{"line_number":41,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2FuME%3D","line":38,"updated":"2013-06-11 23:22:23.000000000","message":"This sequence of checks are kind of hard to read and follow; it would be good if this could be refactored so that the exception is raised once, like there is one composed logical expression and one if statement.","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":35,"context_line":"                \"The number of rules exceeds the maximum %(quota)s.\")"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"def convert_to_valid_router_rules(data):"},{"line_number":39,"context_line":"    \"\"\""},{"line_number":40,"context_line":"    Validates and converts router rules to the appropriate data structure"},{"line_number":41,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2Ft8E%3D","line":38,"in_reply_to":"AAAAPX%2F%2FuME%3D","updated":"2013-06-12 01:58:45.000000000","message":"I combined them into a list comprehension. It\u0027s definitely easier to read, but it required a few more functions.","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":748,"name":"Armando Migliaccio","email":"armamig@gmail.com","username":"armando-migliaccio"},"unresolved":false,"context_lines":[{"line_number":35,"context_line":"                \"The number of rules exceeds the maximum %(quota)s.\")"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"def convert_to_valid_router_rules(data):"},{"line_number":39,"context_line":"    \"\"\""},{"line_number":40,"context_line":"    Validates and converts router rules to the appropriate data structure"},{"line_number":41,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":10,"id":"AAAAPX%2F%2FsXg%3D","line":38,"updated":"2013-06-12 17:25:30.000000000","message":"sweet, this is a lot cleaner, however I wonder if the use of a list for \u0027rules\u0027 is the best decision from a complexity standpoint. How many rules can we have in the average case? You set a default to 200, it\u0027d be good to see how this algorithm perform under such a load.","commit_id":"8b48937afbdf745eca815112a0d388a1841046b5"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":35,"context_line":"                \"The number of rules exceeds the maximum %(quota)s.\")"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"def convert_to_valid_router_rules(data):"},{"line_number":39,"context_line":"    \"\"\""},{"line_number":40,"context_line":"    Validates and converts router rules to the appropriate data structure"},{"line_number":41,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":10,"id":"AAAAPX%2F%2FrLQ%3D","line":38,"in_reply_to":"AAAAPX%2F%2Fr9Y%3D","updated":"2013-06-13 00:19:35.000000000","message":"I\u0027ve adjusted the duplication check to run once at the start and to ignore actions and next hops as it should have to begin with. \n\nNew performance numbers.\n\n\u003e\u003e\u003e timeit.timeit(\"routerrule.convert_to_valid_router_rules([{\u0027source\u0027:str(n),\u0027destination\u0027:\u0027any\u0027,\u0027action\u0027:\u0027deny\u0027} for n in netaddr.IPNetwork(\u0027172.24.0.0/16\u0027).subnet(27)]).__len__()\", number\u003d1, setup\u003d\"import routerrule; import netaddr\")\n0.13071203231811523\n\n130 msec for 2048 rules.\n\n\u003e\u003e\u003e timeit.timeit(\"routerrule.convert_to_valid_router_rules([{\u0027source\u0027:str(n),\u0027destination\u0027:\u0027any\u0027,\u0027action\u0027:\u0027deny\u0027} for n in netaddr.IPNetwork(\u0027172.24.0.0/16\u0027).subnet(32)]).__len__()\", number\u003d1, setup\u003d\"import routerrule; import netaddr\")\n4.388872146606445\n\n4.38 seconds for 65535 rules.","commit_id":"8b48937afbdf745eca815112a0d388a1841046b5"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":35,"context_line":"                \"The number of rules exceeds the maximum %(quota)s.\")"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"def convert_to_valid_router_rules(data):"},{"line_number":39,"context_line":"    \"\"\""},{"line_number":40,"context_line":"    Validates and converts router rules to the appropriate data structure"},{"line_number":41,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":10,"id":"AAAAPX%2F%2Fr9Y%3D","line":38,"in_reply_to":"AAAAPX%2F%2FsXg%3D","updated":"2013-06-12 19:40:38.000000000","message":"\u003e\u003e\u003e import timeit\n\u003e\u003e\u003e timeit.timeit(\"routerrule.convert_to_valid_router_rules([{\u0027source\u0027:str(n),\u0027destination\u0027:\u0027any\u0027,\u0027action\u0027:\u0027deny\u0027} for n in netaddr.IPNetwork(\u0027172.24.0.0/16\u0027).subnet(27)]).__len__()\", number\u003d1, setup\u003d\"import routerrule; import netaddr\")\n0.29547691345214844\n\nJust under 300 msec to validate 2048 rules. This only happens on the infrequent user-initiated router creation or update, so 300 msec is reasonable. \n\n\u003e\u003e\u003e timeit.timeit(\"routerrule.convert_to_valid_router_rules([{\u0027source\u0027:str(n),\u0027destination\u0027:\u0027any\u0027,\u0027action\u0027:\u0027deny\u0027} for n in netaddr.IPNetwork(\u0027172.24.0.0/16\u0027).subnet(24)]).__len__()\", number\u003d1, setup\u003d\"import routerrule; import netaddr\")\n0.02560710906982422\n\nOnly 25 msec for 256 rules.","commit_id":"8b48937afbdf745eca815112a0d388a1841046b5"},{"author":{"_account_id":1653,"name":"garyk","email":"gkotton@vmware.com","username":"garyk"},"unresolved":false,"context_lines":[{"line_number":46,"context_line":"    _validate_uniquerules(data)"},{"line_number":47,"context_line":"    rules \u003d []"},{"line_number":48,"context_line":"    expected_keys \u003d [\u0027source\u0027, \u0027destination\u0027, \u0027action\u0027]"},{"line_number":49,"context_line":"    for rule in data:"},{"line_number":50,"context_line":"        try:"},{"line_number":51,"context_line":"            if not isinstance(rule[\u0027nexthops\u0027], list):"},{"line_number":52,"context_line":"                rule[\u0027nexthops\u0027] \u003d rule[\u0027nexthops\u0027].split(\u0027+\u0027)"}],"source_content_type":"text/x-python","patch_set":11,"id":"AAAAPn%2F%2F%2Boo%3D","line":49,"updated":"2013-06-16 06:44:33.000000000","message":"Do you want to check for duplicate rules?","commit_id":"71fb6491484e844c3bb39fbe6cbe93c2d81a1e3a"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":46,"context_line":"    _validate_uniquerules(data)"},{"line_number":47,"context_line":"    rules \u003d []"},{"line_number":48,"context_line":"    expected_keys \u003d [\u0027source\u0027, \u0027destination\u0027, \u0027action\u0027]"},{"line_number":49,"context_line":"    for rule in data:"},{"line_number":50,"context_line":"        try:"},{"line_number":51,"context_line":"            if not isinstance(rule[\u0027nexthops\u0027], list):"},{"line_number":52,"context_line":"                rule[\u0027nexthops\u0027] \u003d rule[\u0027nexthops\u0027].split(\u0027+\u0027)"}],"source_content_type":"text/x-python","patch_set":11,"id":"AAAAPn%2F%2F%2Boc%3D","line":49,"in_reply_to":"AAAAPn%2F%2F%2Boo%3D","updated":"2013-06-16 07:06:12.000000000","message":"_validate_uniquerules(data) up above does that.","commit_id":"71fb6491484e844c3bb39fbe6cbe93c2d81a1e3a"},{"author":{"_account_id":1653,"name":"garyk","email":"gkotton@vmware.com","username":"garyk"},"unresolved":false,"context_lines":[{"line_number":72,"context_line":"    return rules"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"def _validate_nexthops(nexthops):"},{"line_number":76,"context_line":"    for ip in nexthops:"},{"line_number":77,"context_line":"        msg \u003d attr._validate_ip_address(ip)"},{"line_number":78,"context_line":"        if msg:"}],"source_content_type":"text/x-python","patch_set":11,"id":"AAAAPn%2F%2F%2Bos%3D","line":75,"updated":"2013-06-16 06:44:33.000000000","message":"do you want to check if the user duplicates nexthops?","commit_id":"71fb6491484e844c3bb39fbe6cbe93c2d81a1e3a"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":72,"context_line":"    return rules"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"def _validate_nexthops(nexthops):"},{"line_number":76,"context_line":"    for ip in nexthops:"},{"line_number":77,"context_line":"        msg \u003d attr._validate_ip_address(ip)"},{"line_number":78,"context_line":"        if msg:"}],"source_content_type":"text/x-python","patch_set":11,"id":"AAAAPn%2F%2F%2Bns%3D","line":75,"in_reply_to":"AAAAPn%2F%2F%2Bos%3D","updated":"2013-06-16 07:06:12.000000000","message":"Yes. I updated the code and updated the unit test to check for this.\n\nThanks","commit_id":"71fb6491484e844c3bb39fbe6cbe93c2d81a1e3a"},{"author":{"_account_id":2874,"name":"yong sheng gong","email":"gong.yongsheng@99cloud.net","username":"gongysh"},"unresolved":false,"context_lines":[{"line_number":37,"context_line":""},{"line_number":38,"context_line":"def convert_to_valid_router_rules(data):"},{"line_number":39,"context_line":"    \"\"\""},{"line_number":40,"context_line":"    Validates and converts router rules to the appropriate data structure"},{"line_number":41,"context_line":"    \"\"\""},{"line_number":42,"context_line":"    if not isinstance(data, list):"},{"line_number":43,"context_line":"        emsg \u003d _(\"Invalid data format for router rule: \u0027%s\u0027\") % data"}],"source_content_type":"text/x-python","patch_set":14,"id":"AAAAPn%2F%2F%2BEk%3D","line":40,"updated":"2013-06-17 03:41:17.000000000","message":"can we add one accepted data example?","commit_id":"56715ad727a40dd6ff3e91ff144ea215a6374b8e"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":37,"context_line":""},{"line_number":38,"context_line":"def convert_to_valid_router_rules(data):"},{"line_number":39,"context_line":"    \"\"\""},{"line_number":40,"context_line":"    Validates and converts router rules to the appropriate data structure"},{"line_number":41,"context_line":"    \"\"\""},{"line_number":42,"context_line":"    if not isinstance(data, list):"},{"line_number":43,"context_line":"        emsg \u003d _(\"Invalid data format for router rule: \u0027%s\u0027\") % data"}],"source_content_type":"text/x-python","patch_set":14,"id":"AAAAPn%2F%2F%2BAA%3D","line":40,"in_reply_to":"AAAAPn%2F%2F%2BEk%3D","updated":"2013-06-17 08:32:08.000000000","message":"Done","commit_id":"56715ad727a40dd6ff3e91ff144ea215a6374b8e"},{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":53,"context_line":"    rules \u003d []"},{"line_number":54,"context_line":"    expected_keys \u003d [\u0027source\u0027, \u0027destination\u0027, \u0027action\u0027]"},{"line_number":55,"context_line":"    for rule in data:"},{"line_number":56,"context_line":"        try:"},{"line_number":57,"context_line":"            if not isinstance(rule[\u0027nexthops\u0027], list):"},{"line_number":58,"context_line":"                rule[\u0027nexthops\u0027] \u003d rule[\u0027nexthops\u0027].split(\u0027+\u0027)"},{"line_number":59,"context_line":"        except KeyError:"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAPn%2F%2F7NM%3D","line":56,"updated":"2013-06-18 06:18:18.000000000","message":"replace 56-60:\n\nif not isinstance(rule.get(\u0027nexthops\u0027, []), list):\n     rule[\u0027nexthops\u0027] \u003d rule[\u0027nexthops\u0027].split(\u0027+\u0027)","commit_id":"845c977977b5a26faa9084130149e8497ab59063"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":53,"context_line":"    rules \u003d []"},{"line_number":54,"context_line":"    expected_keys \u003d [\u0027source\u0027, \u0027destination\u0027, \u0027action\u0027]"},{"line_number":55,"context_line":"    for rule in data:"},{"line_number":56,"context_line":"        try:"},{"line_number":57,"context_line":"            if not isinstance(rule[\u0027nexthops\u0027], list):"},{"line_number":58,"context_line":"                rule[\u0027nexthops\u0027] \u003d rule[\u0027nexthops\u0027].split(\u0027+\u0027)"},{"line_number":59,"context_line":"        except KeyError:"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAPn%2F%2F500%3D","line":56,"in_reply_to":"AAAAPn%2F%2F7NM%3D","updated":"2013-06-18 17:34:58.000000000","message":"I had to modify this because it would have left \u0027nexthops\u0027 undefined for a rule without it present.","commit_id":"845c977977b5a26faa9084130149e8497ab59063"},{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":58,"context_line":"                rule[\u0027nexthops\u0027] \u003d rule[\u0027nexthops\u0027].split(\u0027+\u0027)"},{"line_number":59,"context_line":"        except KeyError:"},{"line_number":60,"context_line":"            rule[\u0027nexthops\u0027] \u003d []"},{"line_number":61,"context_line":"        src \u003d rule[\u0027source\u0027]"},{"line_number":62,"context_line":"        if rule[\u0027source\u0027] \u003d\u003d \u0027any\u0027:"},{"line_number":63,"context_line":"            src \u003d \u00270.0.0.0/0\u0027"},{"line_number":64,"context_line":"        dst \u003d rule[\u0027destination\u0027]"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAPn%2F%2F7M8%3D","line":61,"updated":"2013-06-18 06:18:18.000000000","message":"source \u003d \u00270.0.0.0/0\u0027 if rule[\u0027source\u0027] \u003d\u003d \u0027any\u0027 else rule[\u0027source\u0027]","commit_id":"845c977977b5a26faa9084130149e8497ab59063"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":58,"context_line":"                rule[\u0027nexthops\u0027] \u003d rule[\u0027nexthops\u0027].split(\u0027+\u0027)"},{"line_number":59,"context_line":"        except KeyError:"},{"line_number":60,"context_line":"            rule[\u0027nexthops\u0027] \u003d []"},{"line_number":61,"context_line":"        src \u003d rule[\u0027source\u0027]"},{"line_number":62,"context_line":"        if rule[\u0027source\u0027] \u003d\u003d \u0027any\u0027:"},{"line_number":63,"context_line":"            src \u003d \u00270.0.0.0/0\u0027"},{"line_number":64,"context_line":"        dst \u003d rule[\u0027destination\u0027]"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAPn%2F%2F5zQ%3D","line":61,"in_reply_to":"AAAAPn%2F%2F7M8%3D","updated":"2013-06-18 17:34:58.000000000","message":"Done","commit_id":"845c977977b5a26faa9084130149e8497ab59063"},{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":61,"context_line":"        src \u003d rule[\u0027source\u0027]"},{"line_number":62,"context_line":"        if rule[\u0027source\u0027] \u003d\u003d \u0027any\u0027:"},{"line_number":63,"context_line":"            src \u003d \u00270.0.0.0/0\u0027"},{"line_number":64,"context_line":"        dst \u003d rule[\u0027destination\u0027]"},{"line_number":65,"context_line":"        if rule[\u0027destination\u0027] \u003d\u003d \u0027any\u0027:"},{"line_number":66,"context_line":"            dst \u003d \u00270.0.0.0/0\u0027"},{"line_number":67,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAPn%2F%2F7NE%3D","line":64,"updated":"2013-06-18 06:18:18.000000000","message":"dst \u003d \u00270.0.0.0/0\u0027 if rule[\u0027destination\u0027] \u003d\u003d \u0027any\u0027 else rule[\u0027destination\u0027]","commit_id":"845c977977b5a26faa9084130149e8497ab59063"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        src \u003d rule[\u0027source\u0027]"},{"line_number":62,"context_line":"        if rule[\u0027source\u0027] \u003d\u003d \u0027any\u0027:"},{"line_number":63,"context_line":"            src \u003d \u00270.0.0.0/0\u0027"},{"line_number":64,"context_line":"        dst \u003d rule[\u0027destination\u0027]"},{"line_number":65,"context_line":"        if rule[\u0027destination\u0027] \u003d\u003d \u0027any\u0027:"},{"line_number":66,"context_line":"            dst \u003d \u00270.0.0.0/0\u0027"},{"line_number":67,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAPn%2F%2F5zU%3D","line":64,"in_reply_to":"AAAAPn%2F%2F7NE%3D","updated":"2013-06-18 17:34:58.000000000","message":"This barely goes over the 80 char limit.\nI moved 0.0.0.0/0 up into a variable to make it fit. Let me know if that\u0027s okay.","commit_id":"845c977977b5a26faa9084130149e8497ab59063"},{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":65,"context_line":"        if rule[\u0027destination\u0027] \u003d\u003d \u0027any\u0027:"},{"line_number":66,"context_line":"            dst \u003d \u00270.0.0.0/0\u0027"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"        errors \u003d [msg for msg in"},{"line_number":69,"context_line":"                  [attr._verify_dict_keys(expected_keys, rule, False),"},{"line_number":70,"context_line":"                   attr._validate_subnet(dst),"},{"line_number":71,"context_line":"                   attr._validate_subnet(src),"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAPn%2F%2F7IU%3D","line":68,"updated":"2013-06-18 06:18:18.000000000","message":"Please reformat to make this easier to read:\n            errors \u003d [\n                attr._verify_dict_keys(expected_keys, rule, False),\n                attr._validate_subnet(dst),\n                attr._validate_subnet(src),\n                _validate_nexthops(rule[\u0027nexthops\u0027]),\n                _validate_action(rule[\u0027action\u0027])\n            ]\n            errors \u003d [m for m in errors if m]","commit_id":"845c977977b5a26faa9084130149e8497ab59063"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":65,"context_line":"        if rule[\u0027destination\u0027] \u003d\u003d \u0027any\u0027:"},{"line_number":66,"context_line":"            dst \u003d \u00270.0.0.0/0\u0027"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"        errors \u003d [msg for msg in"},{"line_number":69,"context_line":"                  [attr._verify_dict_keys(expected_keys, rule, False),"},{"line_number":70,"context_line":"                   attr._validate_subnet(dst),"},{"line_number":71,"context_line":"                   attr._validate_subnet(src),"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAPn%2F%2F5zY%3D","line":68,"in_reply_to":"AAAAPn%2F%2F7IU%3D","updated":"2013-06-18 17:34:58.000000000","message":"Done","commit_id":"845c977977b5a26faa9084130149e8497ab59063"},{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":100,"context_line":"    for r in rules:"},{"line_number":101,"context_line":"        if \u0027source\u0027 not in r or \u0027destination\u0027 not in r:"},{"line_number":102,"context_line":"            continue"},{"line_number":103,"context_line":"        pairs.append((r[\u0027source\u0027], r[\u0027destination\u0027]))"},{"line_number":104,"context_line":"    pairs.sort(key\u003dlambda x: (x[0], x[1]))"},{"line_number":105,"context_line":"    for i, p in enumerate(pairs):"},{"line_number":106,"context_line":"        if i \u003d\u003d 0:"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAPn%2F%2F7H4%3D","line":103,"updated":"2013-06-18 06:18:18.000000000","message":"If there are multiple pairs of nonunique rules this only returns one.  Consider replacing 104-111:\n\nif len(set(pairs)) !\u003d len(pairs):\n    error \u003d _(\"Duplicate router rules (src,dst)  found \u0027%s\u0027\") % pairs\n    LOG.debug(error)\n    raise qexception.InvalidInput(error_message\u003derror)","commit_id":"845c977977b5a26faa9084130149e8497ab59063"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":100,"context_line":"    for r in rules:"},{"line_number":101,"context_line":"        if \u0027source\u0027 not in r or \u0027destination\u0027 not in r:"},{"line_number":102,"context_line":"            continue"},{"line_number":103,"context_line":"        pairs.append((r[\u0027source\u0027], r[\u0027destination\u0027]))"},{"line_number":104,"context_line":"    pairs.sort(key\u003dlambda x: (x[0], x[1]))"},{"line_number":105,"context_line":"    for i, p in enumerate(pairs):"},{"line_number":106,"context_line":"        if i \u003d\u003d 0:"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAPn%2F%2F5yg%3D","line":103,"in_reply_to":"AAAAPn%2F%2F7H4%3D","updated":"2013-06-18 17:34:58.000000000","message":"Done","commit_id":"845c977977b5a26faa9084130149e8497ab59063"}],"quantum/plugins/bigswitch/plugin.py":[{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":73,"context_line":"LOG \u003d logging.getLogger(__name__)"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"# Include the BigSwitch Extensions path in the api_extensions"},{"line_number":76,"context_line":"EXTENSIONS_PATH \u003d \u0027quantum/plugins/bigswitch/extensions\u0027"},{"line_number":77,"context_line":"if not cfg.CONF.api_extensions_path:"},{"line_number":78,"context_line":"    cfg.CONF.set_override(\u0027api_extensions_path\u0027,"},{"line_number":79,"context_line":"                          EXTENSIONS_PATH)"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2FyNo%3D","line":76,"updated":"2013-06-10 19:23:38.000000000","message":"This should be relative to the location of this file.\n\nos.path.join(os.path.dirname(__file__), \u0027../extensions\u0027)","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":73,"context_line":"LOG \u003d logging.getLogger(__name__)"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"# Include the BigSwitch Extensions path in the api_extensions"},{"line_number":76,"context_line":"EXTENSIONS_PATH \u003d \u0027quantum/plugins/bigswitch/extensions\u0027"},{"line_number":77,"context_line":"if not cfg.CONF.api_extensions_path:"},{"line_number":78,"context_line":"    cfg.CONF.set_override(\u0027api_extensions_path\u0027,"},{"line_number":79,"context_line":"                          EXTENSIONS_PATH)"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2Fx9g%3D","line":76,"in_reply_to":"AAAAPX%2F%2FyNo%3D","updated":"2013-06-10 21:52:28.000000000","message":"Done","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":79,"context_line":"                          EXTENSIONS_PATH)"},{"line_number":80,"context_line":"else:"},{"line_number":81,"context_line":"    extensions \u003d cfg.CONF.api_extensions_path.split(\u0027:\u0027)"},{"line_number":82,"context_line":"    if EXTENSIONS_PATH not in extensions:"},{"line_number":83,"context_line":"        extensions.append(EXTENSIONS_PATH)"},{"line_number":84,"context_line":"        cfg.CONF.set_override(\u0027api_extensions_path\u0027,"},{"line_number":85,"context_line":"                              \u0027:\u0027.join(extensions))"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2FyNM%3D","line":82,"updated":"2013-06-10 19:23:38.000000000","message":"Item to consider...\n\nThis is dangerous because there is no way for someone to turn the ext off.  I think adding if is missing is ok, but if a deployer explicitly sets the extensions path it should probably be left alone.","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":79,"context_line":"                          EXTENSIONS_PATH)"},{"line_number":80,"context_line":"else:"},{"line_number":81,"context_line":"    extensions \u003d cfg.CONF.api_extensions_path.split(\u0027:\u0027)"},{"line_number":82,"context_line":"    if EXTENSIONS_PATH not in extensions:"},{"line_number":83,"context_line":"        extensions.append(EXTENSIONS_PATH)"},{"line_number":84,"context_line":"        cfg.CONF.set_override(\u0027api_extensions_path\u0027,"},{"line_number":85,"context_line":"                              \u0027:\u0027.join(extensions))"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2Fx70%3D","line":82,"in_reply_to":"AAAAPX%2F%2FyNM%3D","updated":"2013-06-10 21:52:28.000000000","message":"Done","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":114,"context_line":"cfg.CONF.register_opts(restproxy_opts, \"RESTPROXY\")"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"router_opts \u003d ["},{"line_number":117,"context_line":"    cfg.StrOpt(\u0027tenant_default_routerrules\u0027, default\u003d\u0027*:any:any:permit;\u0027,"},{"line_number":118,"context_line":"               help\u003d_(\"The default router rules installed in new \""},{"line_number":119,"context_line":"                      \"tenant routers. Rules are separated by semi-colons. \""},{"line_number":120,"context_line":"                      \"Format is \u003ctenant\u003e:\u003csource\u003e:\u003cdestination\u003e:\u003caction\u003e\""}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2FyMs%3D","line":117,"updated":"2013-06-10 19:23:38.000000000","message":"Why not use a ListOpt here?","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":114,"context_line":"cfg.CONF.register_opts(restproxy_opts, \"RESTPROXY\")"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"router_opts \u003d ["},{"line_number":117,"context_line":"    cfg.StrOpt(\u0027tenant_default_routerrules\u0027, default\u003d\u0027*:any:any:permit;\u0027,"},{"line_number":118,"context_line":"               help\u003d_(\"The default router rules installed in new \""},{"line_number":119,"context_line":"                      \"tenant routers. Rules are separated by semi-colons. \""},{"line_number":120,"context_line":"                      \"Format is \u003ctenant\u003e:\u003csource\u003e:\u003cdestination\u003e:\u003caction\u003e\""}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2Fx9c%3D","line":117,"in_reply_to":"AAAAPX%2F%2FyMs%3D","updated":"2013-06-10 21:52:28.000000000","message":"ListOpt requires the use of the comma to separate strings, but we need comma separation for the specification of multiple nexthops in a single rule. \n\nSo rules are semi-colon separation, and inside a rule there may be comma-separated nexthops.","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":882,"context_line":"                defaultset.append(parsedrule)"},{"line_number":883,"context_line":"            if tenantid \u003d\u003d tenant:"},{"line_number":884,"context_line":"                tenantset.append(parsedrule)"},{"line_number":885,"context_line":"        if len(tenantset) \u003e 0:"},{"line_number":886,"context_line":"            return tenantset"},{"line_number":887,"context_line":"        return defaultset"},{"line_number":888,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2FyMY%3D","line":885,"updated":"2013-06-10 19:23:38.000000000","message":"if tenantset:","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":882,"context_line":"                defaultset.append(parsedrule)"},{"line_number":883,"context_line":"            if tenantid \u003d\u003d tenant:"},{"line_number":884,"context_line":"                tenantset.append(parsedrule)"},{"line_number":885,"context_line":"        if len(tenantset) \u003e 0:"},{"line_number":886,"context_line":"            return tenantset"},{"line_number":887,"context_line":"        return defaultset"},{"line_number":888,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2Fx8I%3D","line":885,"in_reply_to":"AAAAPX%2F%2FyMY%3D","updated":"2013-06-10 21:52:28.000000000","message":"Done","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":748,"name":"Armando Migliaccio","email":"armamig@gmail.com","username":"armando-migliaccio"},"unresolved":false,"context_lines":[{"line_number":74,"context_line":"LOG \u003d logging.getLogger(__name__)"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"# Include the BigSwitch Extensions path in the api_extensions"},{"line_number":77,"context_line":"EXTENSIONS_PATH \u003d os.path.join(os.path.dirname(__file__), \u0027./extensions\u0027)"},{"line_number":78,"context_line":"if not cfg.CONF.api_extensions_path:"},{"line_number":79,"context_line":"    cfg.CONF.set_override(\u0027api_extensions_path\u0027,"},{"line_number":80,"context_line":"                          EXTENSIONS_PATH)"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2FuL4%3D","line":77,"updated":"2013-06-11 23:22:23.000000000","message":"you don\u0027t need the ./","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":74,"context_line":"LOG \u003d logging.getLogger(__name__)"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"# Include the BigSwitch Extensions path in the api_extensions"},{"line_number":77,"context_line":"EXTENSIONS_PATH \u003d os.path.join(os.path.dirname(__file__), \u0027./extensions\u0027)"},{"line_number":78,"context_line":"if not cfg.CONF.api_extensions_path:"},{"line_number":79,"context_line":"    cfg.CONF.set_override(\u0027api_extensions_path\u0027,"},{"line_number":80,"context_line":"                          EXTENSIONS_PATH)"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2Ft8A%3D","line":77,"in_reply_to":"AAAAPX%2F%2FuL4%3D","updated":"2013-06-12 01:58:45.000000000","message":"Done","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":748,"name":"Armando Migliaccio","email":"armamig@gmail.com","username":"armando-migliaccio"},"unresolved":false,"context_lines":[{"line_number":109,"context_line":"cfg.CONF.register_opts(restproxy_opts, \"RESTPROXY\")"},{"line_number":110,"context_line":""},{"line_number":111,"context_line":"router_opts \u003d ["},{"line_number":112,"context_line":"    cfg.StrOpt(\u0027tenant_default_routerrules\u0027, default\u003d\u0027*:any:any:permit;\u0027,"},{"line_number":113,"context_line":"               help\u003d_(\"The default router rules installed in new \""},{"line_number":114,"context_line":"                      \"tenant routers. Rules are separated by semi-colons. \""},{"line_number":115,"context_line":"                      \"Format is \u003ctenant\u003e:\u003csource\u003e:\u003cdestination\u003e:\u003caction\u003e\""}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2FuLo%3D","line":112,"updated":"2013-06-11 23:22:23.000000000","message":"I would add and extra _ between router and rules, it\u0027s easier to read.","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":109,"context_line":"cfg.CONF.register_opts(restproxy_opts, \"RESTPROXY\")"},{"line_number":110,"context_line":""},{"line_number":111,"context_line":"router_opts \u003d ["},{"line_number":112,"context_line":"    cfg.StrOpt(\u0027tenant_default_routerrules\u0027, default\u003d\u0027*:any:any:permit;\u0027,"},{"line_number":113,"context_line":"               help\u003d_(\"The default router rules installed in new \""},{"line_number":114,"context_line":"                      \"tenant routers. Rules are separated by semi-colons. \""},{"line_number":115,"context_line":"                      \"Format is \u003ctenant\u003e:\u003csource\u003e:\u003cdestination\u003e:\u003caction\u003e\""}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2Ft74%3D","line":112,"in_reply_to":"AAAAPX%2F%2FuLo%3D","updated":"2013-06-12 01:58:45.000000000","message":"Done","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":748,"name":"Armando Migliaccio","email":"armamig@gmail.com","username":"armando-migliaccio"},"unresolved":false,"context_lines":[{"line_number":321,"context_line":"class QuantumRestProxyV2(db_base_plugin_v2.QuantumDbPluginV2,"},{"line_number":322,"context_line":"                         routerrule_db.RouterRule_db_mixin):"},{"line_number":323,"context_line":""},{"line_number":324,"context_line":"    supported_extension_aliases \u003d [\"router\", \"binding\", \"router_rules\"]"},{"line_number":325,"context_line":""},{"line_number":326,"context_line":"    def __init__(self):"},{"line_number":327,"context_line":"        LOG.info(_(\u0027QuantumRestProxy: Starting plugin. Version\u003d%s\u0027),"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2FuLE%3D","line":324,"updated":"2013-06-11 23:22:23.000000000","message":"I wonder what is the relationship with extraroute and router_rules. I saw on launchpad that there was an initial attempt (then superseded by this one) to wire the extraroute extension to the plugin. Can you fill me in on the rationale? Is that because the extraroute extension does not allow the specification of the action? If so, wouldn\u0027t be better to fix the extraroute extension available to all plugins rather than proliferating multiple slightly different plugin extensions that aim at doing similar things?","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":321,"context_line":"class QuantumRestProxyV2(db_base_plugin_v2.QuantumDbPluginV2,"},{"line_number":322,"context_line":"                         routerrule_db.RouterRule_db_mixin):"},{"line_number":323,"context_line":""},{"line_number":324,"context_line":"    supported_extension_aliases \u003d [\"router\", \"binding\", \"router_rules\"]"},{"line_number":325,"context_line":""},{"line_number":326,"context_line":"    def __init__(self):"},{"line_number":327,"context_line":"        LOG.info(_(\u0027QuantumRestProxy: Starting plugin. Version\u003d%s\u0027),"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2FokQ%3D","line":324,"in_reply_to":"AAAAPX%2F%2FoyM%3D","updated":"2013-06-13 20:32:04.000000000","message":"I added additional information to the blueprint to clarify the difference, which I will also paste here.\n\n\u003d\u003d\u003d\u003dFrom the blueprint\u003d\u003d\u003d\u003d\n\nThis extension does not have any relation to the extraroute extension. It controls a fundamentally different aspect of the network traffic.\n\nThe extraroute extension is for adding routes to a routing table for the router to use to make forwarding decisions. \n\nThe routing_rules extension is used to apply stateless ACLs to the router to control traffic flow between subnets before the routing table is reached.\n\nThis is being submitted as a vendor-specific extension due to the presence of the \u0027nexthops\u0027 attribute. It can be used to specify the interfaces used to handle traffic from clients in order to prevent hair-pinning and other network inefficiencies. In other words, it is a next hop for the traffic as it leaves the client, not the next hop once it reaches the router.","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":748,"name":"Armando Migliaccio","email":"armamig@gmail.com","username":"armando-migliaccio"},"unresolved":false,"context_lines":[{"line_number":321,"context_line":"class QuantumRestProxyV2(db_base_plugin_v2.QuantumDbPluginV2,"},{"line_number":322,"context_line":"                         routerrule_db.RouterRule_db_mixin):"},{"line_number":323,"context_line":""},{"line_number":324,"context_line":"    supported_extension_aliases \u003d [\"router\", \"binding\", \"router_rules\"]"},{"line_number":325,"context_line":""},{"line_number":326,"context_line":"    def __init__(self):"},{"line_number":327,"context_line":"        LOG.info(_(\u0027QuantumRestProxy: Starting plugin. Version\u003d%s\u0027),"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2FoyM%3D","line":324,"in_reply_to":"AAAAPX%2F%2FsJQ%3D","updated":"2013-06-13 19:53:35.000000000","message":"I would agree that a base extension needs to be lowest common denominator, but I don\u0027t see how other plugins couldn\u0027t elevate themselves at doing what you\u0027re aiming to do here. That said, it is also perfectly acceptable for a plugin to reply (politely ;) that a specific extension action cannot be honored because of lack of support, especially if it is a corner case rather than the norm, at least in my opinion.\nI think this has become quite a long discussion and I hope that more people to chime in. My main concern is that from a 10000-feet standpoint extraroute and router_rules may be confused to be doing the same thing. I understand that this is a plugin-specific extension, but at the same time I don\u0027t want developers to think that it is okay to go on and _duplicate_ and tweak a basic feature in their own plugin, just because it\u0027s _easier_. I realize that this is not your case, but with lack of blueprint documentation and design discussions that\u0027s what it looked like.\n\nThanks for helping me understand.","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":321,"context_line":"class QuantumRestProxyV2(db_base_plugin_v2.QuantumDbPluginV2,"},{"line_number":322,"context_line":"                         routerrule_db.RouterRule_db_mixin):"},{"line_number":323,"context_line":""},{"line_number":324,"context_line":"    supported_extension_aliases \u003d [\"router\", \"binding\", \"router_rules\"]"},{"line_number":325,"context_line":""},{"line_number":326,"context_line":"    def __init__(self):"},{"line_number":327,"context_line":"        LOG.info(_(\u0027QuantumRestProxy: Starting plugin. Version\u003d%s\u0027),"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2FsJQ%3D","line":324,"in_reply_to":"AAAAPX%2F%2FsfM%3D","updated":"2013-06-12 18:39:33.000000000","message":"I don\u0027t see how we could easily consolidate the requirements of the extraroute extension and this one.  A plugin implementing the extraroute extension can translate it directly into entries in a routing table, but if we merge these changes that would no longer be the case. It is true that an extraroute could be a special case with source \u0027any\u0027, action \u0027permit\u0027, a destination and one next hop. However, how would something expecting an extraroute handle the following cases: a specific source, no next hops, multiple next hops, or a deny action? All of the plugins that want to implement extra routes for routing table entries but not support these new features would then need to throw errors for all of these cases. \n\nThis extension allows for the creation of basic ACLs in the router and won\u0027t affect the routing table. It is possible that a plugin could support both extensions, translating the extraroutes into routing table entries and the router rules into routing policies via ACLs or route maps. The name name router_rules was chosen because it maps directly to functionality in the controller backend by the same name. The use of next_hops as upstream router selection for clients is also non-standard, which is why this is implemented as a vendor-specific extension.\n\nCompared to FWaaS, these are simple stateless layer 3 ACLs, so they are very limited in granularity, but they have a much lower performance cost since they don\u0027t keep state and just need to match by a bitmask in the IP header. \n\nI want to emphasize that this is a plugin-specific extension to map directly to functionality in this specific backend, similar to the Nicira network gateway or the NEC packet filter.","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":748,"name":"Armando Migliaccio","email":"armamig@gmail.com","username":"armando-migliaccio"},"unresolved":false,"context_lines":[{"line_number":321,"context_line":"class QuantumRestProxyV2(db_base_plugin_v2.QuantumDbPluginV2,"},{"line_number":322,"context_line":"                         routerrule_db.RouterRule_db_mixin):"},{"line_number":323,"context_line":""},{"line_number":324,"context_line":"    supported_extension_aliases \u003d [\"router\", \"binding\", \"router_rules\"]"},{"line_number":325,"context_line":""},{"line_number":326,"context_line":"    def __init__(self):"},{"line_number":327,"context_line":"        LOG.info(_(\u0027QuantumRestProxy: Starting plugin. Version\u003d%s\u0027),"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2FsfE%3D","line":324,"in_reply_to":"AAAAPX%2F%2Ft5k%3D","updated":"2013-06-12 16:38:38.000000000","message":"yup, gotcha.","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":321,"context_line":"class QuantumRestProxyV2(db_base_plugin_v2.QuantumDbPluginV2,"},{"line_number":322,"context_line":"                         routerrule_db.RouterRule_db_mixin):"},{"line_number":323,"context_line":""},{"line_number":324,"context_line":"    supported_extension_aliases \u003d [\"router\", \"binding\", \"router_rules\"]"},{"line_number":325,"context_line":""},{"line_number":326,"context_line":"    def __init__(self):"},{"line_number":327,"context_line":"        LOG.info(_(\u0027QuantumRestProxy: Starting plugin. Version\u003d%s\u0027),"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2Ft5k%3D","line":324,"in_reply_to":"AAAAPX%2F%2Ft7s%3D","updated":"2013-06-12 02:09:09.000000000","message":"Sorry, I meant to say \u0027extensions\u0027 instead of \u0027plugins\u0027. The comment should read:\n\nThe extensions were too different to merge together. extraroute is missing the concept of source matching, an action, and multiple next hop addresses. The information from the extraroute extension would equate with entries in a routing table, where as the information from this extension would more equate with entries in an access control list.","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":748,"name":"Armando Migliaccio","email":"armamig@gmail.com","username":"armando-migliaccio"},"unresolved":false,"context_lines":[{"line_number":321,"context_line":"class QuantumRestProxyV2(db_base_plugin_v2.QuantumDbPluginV2,"},{"line_number":322,"context_line":"                         routerrule_db.RouterRule_db_mixin):"},{"line_number":323,"context_line":""},{"line_number":324,"context_line":"    supported_extension_aliases \u003d [\"router\", \"binding\", \"router_rules\"]"},{"line_number":325,"context_line":""},{"line_number":326,"context_line":"    def __init__(self):"},{"line_number":327,"context_line":"        LOG.info(_(\u0027QuantumRestProxy: Starting plugin. Version\u003d%s\u0027),"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2FsfM%3D","line":324,"in_reply_to":"AAAAPX%2F%2Ft7s%3D","updated":"2013-06-12 16:38:38.000000000","message":"Thanks, that helps clarify things. So is router_rules an appropriate name? I am not 100% in agreement with you that the extraroute and router_rules are too different to merge. It sounds like extraroute is a special case of router_rules (or router_rules a generalization of extraroute) where the former\u0027s only action is \u0027accept\u0027, can forward just to a single hop, and does not look at the source address to make decisions. If this has to do more with ACL\u0027s how does this effort relates to FWaaS?\n\nIt\u0027d be good to grab these thoughts on a blueprint page so that other developers are aware of what\u0027s going  on too.","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":321,"context_line":"class QuantumRestProxyV2(db_base_plugin_v2.QuantumDbPluginV2,"},{"line_number":322,"context_line":"                         routerrule_db.RouterRule_db_mixin):"},{"line_number":323,"context_line":""},{"line_number":324,"context_line":"    supported_extension_aliases \u003d [\"router\", \"binding\", \"router_rules\"]"},{"line_number":325,"context_line":""},{"line_number":326,"context_line":"    def __init__(self):"},{"line_number":327,"context_line":"        LOG.info(_(\u0027QuantumRestProxy: Starting plugin. Version\u003d%s\u0027),"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2Ft7s%3D","line":324,"in_reply_to":"AAAAPX%2F%2FuLE%3D","updated":"2013-06-12 01:58:45.000000000","message":"The plugins were too different to merge together. extraroute is missing the concept of source matching, an action, and multiple next hop addresses. The information from the extraroute plugin would equate with entries in a routing table, where as the information from this plugin would more equate with entries in an access control list.","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":2874,"name":"yong sheng gong","email":"gong.yongsheng@99cloud.net","username":"gongysh"},"unresolved":false,"context_lines":[{"line_number":77,"context_line":"EXTENSIONS_PATH \u003d os.path.join(os.path.dirname(__file__), \u0027extensions\u0027)"},{"line_number":78,"context_line":"if not cfg.CONF.api_extensions_path:"},{"line_number":79,"context_line":"    cfg.CONF.set_override(\u0027api_extensions_path\u0027,"},{"line_number":80,"context_line":"                          EXTENSIONS_PATH)"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"restproxy_opts \u003d ["},{"line_number":83,"context_line":"    cfg.StrOpt(\u0027servers\u0027, default\u003d\u0027localhost:8800\u0027,"}],"source_content_type":"text/x-python","patch_set":14,"id":"AAAAPn%2F%2F%2BFI%3D","line":80,"updated":"2013-06-17 03:41:17.000000000","message":"what will happen to \"router\", \"binding\" if the extension path is changed to new defined one?","commit_id":"56715ad727a40dd6ff3e91ff144ea215a6374b8e"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":77,"context_line":"EXTENSIONS_PATH \u003d os.path.join(os.path.dirname(__file__), \u0027extensions\u0027)"},{"line_number":78,"context_line":"if not cfg.CONF.api_extensions_path:"},{"line_number":79,"context_line":"    cfg.CONF.set_override(\u0027api_extensions_path\u0027,"},{"line_number":80,"context_line":"                          EXTENSIONS_PATH)"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"restproxy_opts \u003d ["},{"line_number":83,"context_line":"    cfg.StrOpt(\u0027servers\u0027, default\u003d\u0027localhost:8800\u0027,"}],"source_content_type":"text/x-python","patch_set":14,"id":"AAAAPn%2F%2F91s%3D","line":80,"in_reply_to":"AAAAPn%2F%2F%2BFI%3D","updated":"2013-06-17 08:32:08.000000000","message":"The \"router\" and \"binding\" extensions aliases are not handled by this configuration value because they are quantum extensions, not plugin extensions. \n\nIf this extensions path is overwritten, only the routerrule extension won\u0027t be loaded so the router_rules key will be removed from all router objects when interacting with the quantum API.","commit_id":"56715ad727a40dd6ff3e91ff144ea215a6374b8e"},{"author":{"_account_id":2874,"name":"yong sheng gong","email":"gong.yongsheng@99cloud.net","username":"gongysh"},"unresolved":false,"context_lines":[{"line_number":109,"context_line":"cfg.CONF.register_opts(restproxy_opts, \"RESTPROXY\")"},{"line_number":110,"context_line":""},{"line_number":111,"context_line":"router_opts \u003d ["},{"line_number":112,"context_line":"    cfg.StrOpt(\u0027tenant_default_router_rules\u0027, default\u003d\u0027*:any:any:permit;\u0027,"},{"line_number":113,"context_line":"               help\u003d_(\"The default router rules installed in new \""},{"line_number":114,"context_line":"                      \"tenant routers. Rules are separated by semi-colons. \""},{"line_number":115,"context_line":"                      \"Format is \u003ctenant\u003e:\u003csource\u003e:\u003cdestination\u003e:\u003caction\u003e\""}],"source_content_type":"text/x-python","patch_set":14,"id":"AAAAPn%2F%2F%2BEs%3D","line":112,"updated":"2013-06-17 03:41:17.000000000","message":"we can use MultiStrOpt","commit_id":"56715ad727a40dd6ff3e91ff144ea215a6374b8e"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":109,"context_line":"cfg.CONF.register_opts(restproxy_opts, \"RESTPROXY\")"},{"line_number":110,"context_line":""},{"line_number":111,"context_line":"router_opts \u003d ["},{"line_number":112,"context_line":"    cfg.StrOpt(\u0027tenant_default_router_rules\u0027, default\u003d\u0027*:any:any:permit;\u0027,"},{"line_number":113,"context_line":"               help\u003d_(\"The default router rules installed in new \""},{"line_number":114,"context_line":"                      \"tenant routers. Rules are separated by semi-colons. \""},{"line_number":115,"context_line":"                      \"Format is \u003ctenant\u003e:\u003csource\u003e:\u003cdestination\u003e:\u003caction\u003e\""}],"source_content_type":"text/x-python","patch_set":14,"id":"AAAAPn%2F%2F%2BA8%3D","line":112,"in_reply_to":"AAAAPn%2F%2F%2BEs%3D","updated":"2013-06-17 08:32:08.000000000","message":"Done","commit_id":"56715ad727a40dd6ff3e91ff144ea215a6374b8e"},{"author":{"_account_id":2874,"name":"yong sheng gong","email":"gong.yongsheng@99cloud.net","username":"gongysh"},"unresolved":false,"context_lines":[{"line_number":879,"context_line":"                tenantset.append(parsedrule)"},{"line_number":880,"context_line":"        if tenantset:"},{"line_number":881,"context_line":"            return tenantset"},{"line_number":882,"context_line":"        return defaultset"},{"line_number":883,"context_line":""},{"line_number":884,"context_line":"    def create_router(self, context, router):"},{"line_number":885,"context_line":"        LOG.debug(_(\"QuantumRestProxyV2: create_router() called\"))"}],"source_content_type":"text/x-python","patch_set":14,"id":"AAAAPn%2F%2F%2BE4%3D","line":882,"updated":"2013-06-17 03:41:17.000000000","message":"why do we need defaultset? how about just return tenantset to replace line 880-882?","commit_id":"56715ad727a40dd6ff3e91ff144ea215a6374b8e"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":879,"context_line":"                tenantset.append(parsedrule)"},{"line_number":880,"context_line":"        if tenantset:"},{"line_number":881,"context_line":"            return tenantset"},{"line_number":882,"context_line":"        return defaultset"},{"line_number":883,"context_line":""},{"line_number":884,"context_line":"    def create_router(self, context, router):"},{"line_number":885,"context_line":"        LOG.debug(_(\"QuantumRestProxyV2: create_router() called\"))"}],"source_content_type":"text/x-python","patch_set":14,"id":"AAAAPn%2F%2F%2BB8%3D","line":882,"in_reply_to":"AAAAPn%2F%2F%2BE4%3D","updated":"2013-06-17 08:32:08.000000000","message":"defaultset is there for the case when tenantset is empty (i.e. there were no rules found that matched the tenant passed into the function).\n\nIf I just return tenantset, it will be empty when there are no tenant rules when it should be returning the default rules.","commit_id":"56715ad727a40dd6ff3e91ff144ea215a6374b8e"},{"author":{"_account_id":6659,"name":"Paul Michali","email":"pc@michali.net","username":"pcm"},"unresolved":false,"context_lines":[{"line_number":110,"context_line":""},{"line_number":111,"context_line":"router_opts \u003d ["},{"line_number":112,"context_line":"    cfg.MultiStrOpt(\u0027tenant_default_router_rule\u0027, default\u003d[\u0027*:any:any:permit\u0027],"},{"line_number":113,"context_line":"                    help\u003d_(\"The default router rules installed in new tenant\""},{"line_number":114,"context_line":"                           \" routers. Repeat the config option for each rule.\""},{"line_number":115,"context_line":"                           \"Format is \u003ctenant\u003e:\u003csource\u003e:\u003cdestination\u003e:\u003caction\u003e\""},{"line_number":116,"context_line":"                           \" Use an * to specify default for all tenants.\")),"}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAPn%2F%2F9iY%3D","line":113,"updated":"2013-06-17 11:04:04.000000000","message":"Nit: Would use spaces at end of lines, instead of start of next line for readability.","commit_id":"94a699b6c3c9cc1fe02c62c522cb346d2353e142"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":110,"context_line":""},{"line_number":111,"context_line":"router_opts \u003d ["},{"line_number":112,"context_line":"    cfg.MultiStrOpt(\u0027tenant_default_router_rule\u0027, default\u003d[\u0027*:any:any:permit\u0027],"},{"line_number":113,"context_line":"                    help\u003d_(\"The default router rules installed in new tenant\""},{"line_number":114,"context_line":"                           \" routers. Repeat the config option for each rule.\""},{"line_number":115,"context_line":"                           \"Format is \u003ctenant\u003e:\u003csource\u003e:\u003cdestination\u003e:\u003caction\u003e\""},{"line_number":116,"context_line":"                           \" Use an * to specify default for all tenants.\")),"}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAPn%2F%2F9GU%3D","line":113,"in_reply_to":"AAAAPn%2F%2F9iY%3D","updated":"2013-06-17 14:43:23.000000000","message":"Done","commit_id":"94a699b6c3c9cc1fe02c62c522cb346d2353e142"},{"author":{"_account_id":6659,"name":"Paul Michali","email":"pc@michali.net","username":"pcm"},"unresolved":false,"context_lines":[{"line_number":111,"context_line":"router_opts \u003d ["},{"line_number":112,"context_line":"    cfg.MultiStrOpt(\u0027tenant_default_router_rule\u0027, default\u003d[\u0027*:any:any:permit\u0027],"},{"line_number":113,"context_line":"                    help\u003d_(\"The default router rules installed in new tenant\""},{"line_number":114,"context_line":"                           \" routers. Repeat the config option for each rule.\""},{"line_number":115,"context_line":"                           \"Format is \u003ctenant\u003e:\u003csource\u003e:\u003cdestination\u003e:\u003caction\u003e\""},{"line_number":116,"context_line":"                           \" Use an * to specify default for all tenants.\")),"},{"line_number":117,"context_line":"    cfg.IntOpt(\u0027max_router_rules\u0027, default\u003d200,"}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAPn%2F%2F9iU%3D","line":114,"updated":"2013-06-17 11:04:04.000000000","message":"Need space after period.","commit_id":"94a699b6c3c9cc1fe02c62c522cb346d2353e142"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":111,"context_line":"router_opts \u003d ["},{"line_number":112,"context_line":"    cfg.MultiStrOpt(\u0027tenant_default_router_rule\u0027, default\u003d[\u0027*:any:any:permit\u0027],"},{"line_number":113,"context_line":"                    help\u003d_(\"The default router rules installed in new tenant\""},{"line_number":114,"context_line":"                           \" routers. Repeat the config option for each rule.\""},{"line_number":115,"context_line":"                           \"Format is \u003ctenant\u003e:\u003csource\u003e:\u003cdestination\u003e:\u003caction\u003e\""},{"line_number":116,"context_line":"                           \" Use an * to specify default for all tenants.\")),"},{"line_number":117,"context_line":"    cfg.IntOpt(\u0027max_router_rules\u0027, default\u003d200,"}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAPn%2F%2F9GQ%3D","line":114,"in_reply_to":"AAAAPn%2F%2F9iU%3D","updated":"2013-06-17 14:43:23.000000000","message":"Done","commit_id":"94a699b6c3c9cc1fe02c62c522cb346d2353e142"},{"author":{"_account_id":2874,"name":"yong sheng gong","email":"gong.yongsheng@99cloud.net","username":"gongysh"},"unresolved":false,"context_lines":[{"line_number":878,"context_line":"                tenantset.append(parsedrule)"},{"line_number":879,"context_line":"        if tenantset:"},{"line_number":880,"context_line":"            return tenantset"},{"line_number":881,"context_line":"        return defaultset"},{"line_number":882,"context_line":""},{"line_number":883,"context_line":"    def create_router(self, context, router):"},{"line_number":884,"context_line":"        LOG.debug(_(\"QuantumRestProxyV2: create_router() called\"))"}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAPn%2F%2F9Xg%3D","line":881,"updated":"2013-06-17 13:06:41.000000000","message":"replace line 879-881 with \u0027return tenantset\u0027 and remove line 859.","commit_id":"94a699b6c3c9cc1fe02c62c522cb346d2353e142"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":878,"context_line":"                tenantset.append(parsedrule)"},{"line_number":879,"context_line":"        if tenantset:"},{"line_number":880,"context_line":"            return tenantset"},{"line_number":881,"context_line":"        return defaultset"},{"line_number":882,"context_line":""},{"line_number":883,"context_line":"    def create_router(self, context, router):"},{"line_number":884,"context_line":"        LOG.debug(_(\"QuantumRestProxyV2: create_router() called\"))"}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAPn%2F%2F9G4%3D","line":881,"in_reply_to":"AAAAPn%2F%2F9Xg%3D","updated":"2013-06-17 14:43:23.000000000","message":"That will not work. If the defaultset list is not built, nothing would be returned when a tenant is passed into the function that doesn\u0027t match any rules, which is incorrect behavior. \n\nIf a tenant is passed into the function that doesn\u0027t match any rules, the default rules need to be returned.","commit_id":"94a699b6c3c9cc1fe02c62c522cb346d2353e142"}],"quantum/plugins/bigswitch/routerrule_db.py":[{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":84,"context_line":"                router_id\u003drouter[\u0027id\u0027],"},{"line_number":85,"context_line":"                quota\u003dcfg.CONF.ROUTER.max_router_rules)"},{"line_number":86,"context_line":"        query \u003d context.session.query(RouterRule)"},{"line_number":87,"context_line":"        router_rules \u003d query.filter(RouterRule.router_id \u003d\u003d router[\u0027id\u0027]).all()"},{"line_number":88,"context_line":"        for rule in router_rules:"},{"line_number":89,"context_line":"            nh_del_context \u003d context.session.query(NextHop)"},{"line_number":90,"context_line":"            nh_del_context.filter_by(rule_id\u003drule[\u0027id\u0027]).delete()"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2FyLo%3D","line":87,"updated":"2013-06-10 19:23:38.000000000","message":"router_rules \u003d query.filter_by(router_id\u003drouter[\u0027id\u0027]).all()","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":84,"context_line":"                router_id\u003drouter[\u0027id\u0027],"},{"line_number":85,"context_line":"                quota\u003dcfg.CONF.ROUTER.max_router_rules)"},{"line_number":86,"context_line":"        query \u003d context.session.query(RouterRule)"},{"line_number":87,"context_line":"        router_rules \u003d query.filter(RouterRule.router_id \u003d\u003d router[\u0027id\u0027]).all()"},{"line_number":88,"context_line":"        for rule in router_rules:"},{"line_number":89,"context_line":"            nh_del_context \u003d context.session.query(NextHop)"},{"line_number":90,"context_line":"            nh_del_context.filter_by(rule_id\u003drule[\u0027id\u0027]).delete()"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2Fx7Y%3D","line":87,"in_reply_to":"AAAAPX%2F%2FyLo%3D","updated":"2013-06-10 21:52:28.000000000","message":"Done","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":87,"context_line":"        router_rules \u003d query.filter(RouterRule.router_id \u003d\u003d router[\u0027id\u0027]).all()"},{"line_number":88,"context_line":"        for rule in router_rules:"},{"line_number":89,"context_line":"            nh_del_context \u003d context.session.query(NextHop)"},{"line_number":90,"context_line":"            nh_del_context.filter_by(rule_id\u003drule[\u0027id\u0027]).delete()"},{"line_number":91,"context_line":"        del_context \u003d context.session.query(RouterRule)"},{"line_number":92,"context_line":"        del_context.filter_by(router_id\u003drouter[\u0027id\u0027]).delete()"},{"line_number":93,"context_line":"        context.session.flush()"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2FyLU%3D","line":90,"updated":"2013-06-10 19:23:38.000000000","message":"Why explicitly delete here?  You should be able to set cascading to work correctly.","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":87,"context_line":"        router_rules \u003d query.filter(RouterRule.router_id \u003d\u003d router[\u0027id\u0027]).all()"},{"line_number":88,"context_line":"        for rule in router_rules:"},{"line_number":89,"context_line":"            nh_del_context \u003d context.session.query(NextHop)"},{"line_number":90,"context_line":"            nh_del_context.filter_by(rule_id\u003drule[\u0027id\u0027]).delete()"},{"line_number":91,"context_line":"        del_context \u003d context.session.query(RouterRule)"},{"line_number":92,"context_line":"        del_context.filter_by(router_id\u003drouter[\u0027id\u0027]).delete()"},{"line_number":93,"context_line":"        context.session.flush()"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2FxqY%3D","line":90,"in_reply_to":"AAAAPX%2F%2FyLU%3D","updated":"2013-06-10 21:52:28.000000000","message":"Done","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":118,"context_line":""},{"line_number":119,"context_line":"    def _get_router_rules_by_router_id(self, context, id):"},{"line_number":120,"context_line":"        query \u003d context.session.query(RouterRule)"},{"line_number":121,"context_line":"        router_rules \u003d query.filter(RouterRule.router_id \u003d\u003d id).all()"},{"line_number":122,"context_line":"        return self._make_router_rule_list(router_rules)"},{"line_number":123,"context_line":""},{"line_number":124,"context_line":"    def get_router(self, context, id, fields\u003dNone):"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2FyLA%3D","line":121,"updated":"2013-06-10 19:23:38.000000000","message":"query.flter_by(router_id\u003did)","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":118,"context_line":""},{"line_number":119,"context_line":"    def _get_router_rules_by_router_id(self, context, id):"},{"line_number":120,"context_line":"        query \u003d context.session.query(RouterRule)"},{"line_number":121,"context_line":"        router_rules \u003d query.filter(RouterRule.router_id \u003d\u003d id).all()"},{"line_number":122,"context_line":"        return self._make_router_rule_list(router_rules)"},{"line_number":123,"context_line":""},{"line_number":124,"context_line":"    def get_router(self, context, id, fields\u003dNone):"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2Fx7U%3D","line":121,"in_reply_to":"AAAAPX%2F%2FyLA%3D","updated":"2013-06-10 21:52:28.000000000","message":"Done","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":748,"name":"Armando Migliaccio","email":"armamig@gmail.com","username":"armando-migliaccio"},"unresolved":false,"context_lines":[{"line_number":26,"context_line":""},{"line_number":27,"context_line":"LOG \u003d logging.getLogger(__name__)"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"class RouterRule(model_base.BASEV2):"},{"line_number":31,"context_line":"    id \u003d sa.Column(sa.Integer, primary_key\u003dTrue)"},{"line_number":32,"context_line":"    source \u003d sa.Column(sa.String(64), nullable\u003dFalse)"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2FuKU%3D","line":29,"updated":"2013-06-11 23:22:23.000000000","message":"wouldn\u0027t we need a migration script for existing schemas?","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":748,"name":"Armando Migliaccio","email":"armamig@gmail.com","username":"armando-migliaccio"},"unresolved":false,"context_lines":[{"line_number":26,"context_line":""},{"line_number":27,"context_line":"LOG \u003d logging.getLogger(__name__)"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"class RouterRule(model_base.BASEV2):"},{"line_number":31,"context_line":"    id \u003d sa.Column(sa.Integer, primary_key\u003dTrue)"},{"line_number":32,"context_line":"    source \u003d sa.Column(sa.String(64), nullable\u003dFalse)"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2Fse8%3D","line":29,"in_reply_to":"AAAAPX%2F%2Ft7I%3D","updated":"2013-06-12 16:38:38.000000000","message":"gotcha.","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":26,"context_line":""},{"line_number":27,"context_line":"LOG \u003d logging.getLogger(__name__)"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"class RouterRule(model_base.BASEV2):"},{"line_number":31,"context_line":"    id \u003d sa.Column(sa.Integer, primary_key\u003dTrue)"},{"line_number":32,"context_line":"    source \u003d sa.Column(sa.String(64), nullable\u003dFalse)"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2Ft7I%3D","line":29,"in_reply_to":"AAAAPX%2F%2FuKU%3D","updated":"2013-06-12 01:58:45.000000000","message":"No, I don\u0027t believe it is necessary since it is contained in its own tables.","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":748,"name":"Armando Migliaccio","email":"armamig@gmail.com","username":"armando-migliaccio"},"unresolved":false,"context_lines":[{"line_number":30,"context_line":"class RouterRule(model_base.BASEV2):"},{"line_number":31,"context_line":"    id \u003d sa.Column(sa.Integer, primary_key\u003dTrue)"},{"line_number":32,"context_line":"    source \u003d sa.Column(sa.String(64), nullable\u003dFalse)"},{"line_number":33,"context_line":"    destination \u003d sa.Column(sa.String(64), nullable\u003dFalse)"},{"line_number":34,"context_line":"    nexthops \u003d orm.relationship(\u0027NextHop\u0027, cascade\u003d\u0027all,delete\u0027)"},{"line_number":35,"context_line":"    action \u003d sa.Column(sa.String(10), nullable\u003dFalse)"},{"line_number":36,"context_line":"    router_id \u003d sa.Column(sa.String(36),"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2FuIM%3D","line":33,"updated":"2013-06-11 23:22:23.000000000","message":"I am not sure I understand the design or the logical model here: why is nexthop primary key with rule_id in the NextHop table? Is the relation between RouterRule and NextHop one-to-many or one-to-one? The former case does not entirely make sense to me, in the latter case, there is no need to have hops stored in a different table. Could you clarify?\n\nAlso, it looks like the table routerroutes (that comes with the extraroute extension) captures some of the information you are capturing here; this comment relates to what I have asked before by the way.","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":748,"name":"Armando Migliaccio","email":"armamig@gmail.com","username":"armando-migliaccio"},"unresolved":false,"context_lines":[{"line_number":30,"context_line":"class RouterRule(model_base.BASEV2):"},{"line_number":31,"context_line":"    id \u003d sa.Column(sa.Integer, primary_key\u003dTrue)"},{"line_number":32,"context_line":"    source \u003d sa.Column(sa.String(64), nullable\u003dFalse)"},{"line_number":33,"context_line":"    destination \u003d sa.Column(sa.String(64), nullable\u003dFalse)"},{"line_number":34,"context_line":"    nexthops \u003d orm.relationship(\u0027NextHop\u0027, cascade\u003d\u0027all,delete\u0027)"},{"line_number":35,"context_line":"    action \u003d sa.Column(sa.String(10), nullable\u003dFalse)"},{"line_number":36,"context_line":"    router_id \u003d sa.Column(sa.String(36),"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2Fse4%3D","line":33,"in_reply_to":"AAAAPX%2F%2Ft7A%3D","updated":"2013-06-12 16:38:38.000000000","message":"Based on the other comments, this is much clearer, thanks.","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":30,"context_line":"class RouterRule(model_base.BASEV2):"},{"line_number":31,"context_line":"    id \u003d sa.Column(sa.Integer, primary_key\u003dTrue)"},{"line_number":32,"context_line":"    source \u003d sa.Column(sa.String(64), nullable\u003dFalse)"},{"line_number":33,"context_line":"    destination \u003d sa.Column(sa.String(64), nullable\u003dFalse)"},{"line_number":34,"context_line":"    nexthops \u003d orm.relationship(\u0027NextHop\u0027, cascade\u003d\u0027all,delete\u0027)"},{"line_number":35,"context_line":"    action \u003d sa.Column(sa.String(10), nullable\u003dFalse)"},{"line_number":36,"context_line":"    router_id \u003d sa.Column(sa.String(36),"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPX%2F%2Ft7A%3D","line":33,"in_reply_to":"AAAAPX%2F%2FuIM%3D","updated":"2013-06-12 01:58:45.000000000","message":"The relationship is one-to-many. Multiple nexthops are used by the controller so it can select the optimal path for traffic depending on router locations.","commit_id":"29c24c6533fd52724f2ad94792491d884b8131b1"},{"author":{"_account_id":1653,"name":"garyk","email":"gkotton@vmware.com","username":"garyk"},"unresolved":false,"context_lines":[{"line_number":13,"context_line":"#    distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT"},{"line_number":14,"context_line":"#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the"},{"line_number":15,"context_line":"#    License for the specific language governing permissions and limitations"},{"line_number":16,"context_line":"#    under the License."},{"line_number":17,"context_line":"from oslo.config import cfg"},{"line_number":18,"context_line":"import sqlalchemy as sa"},{"line_number":19,"context_line":"from sqlalchemy import orm"}],"source_content_type":"text/x-python","patch_set":11,"id":"AAAAPn%2F%2F%2Bow%3D","line":16,"updated":"2013-06-16 06:44:33.000000000","message":"new line","commit_id":"71fb6491484e844c3bb39fbe6cbe93c2d81a1e3a"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":13,"context_line":"#    distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT"},{"line_number":14,"context_line":"#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the"},{"line_number":15,"context_line":"#    License for the specific language governing permissions and limitations"},{"line_number":16,"context_line":"#    under the License."},{"line_number":17,"context_line":"from oslo.config import cfg"},{"line_number":18,"context_line":"import sqlalchemy as sa"},{"line_number":19,"context_line":"from sqlalchemy import orm"}],"source_content_type":"text/x-python","patch_set":11,"id":"AAAAPn%2F%2F%2Bno%3D","line":16,"in_reply_to":"AAAAPn%2F%2F%2Bow%3D","updated":"2013-06-16 07:06:12.000000000","message":"Done","commit_id":"71fb6491484e844c3bb39fbe6cbe93c2d81a1e3a"},{"author":{"_account_id":2874,"name":"yong sheng gong","email":"gong.yongsheng@99cloud.net","username":"gongysh"},"unresolved":false,"context_lines":[{"line_number":99,"context_line":"            context.session.add(router_rule)"},{"line_number":100,"context_line":"        context.session.flush()"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def _make_router_rule_list(self, router_rules):"},{"line_number":103,"context_line":"        ruleslist \u003d []"},{"line_number":104,"context_line":"        for rule in router_rules:"},{"line_number":105,"context_line":"            hops \u003d [hop[\u0027nexthop\u0027] for hop in rule[\u0027nexthops\u0027]]"}],"source_content_type":"text/x-python","patch_set":14,"id":"AAAAPn%2F%2F%2BEc%3D","line":102,"updated":"2013-06-17 03:41:17.000000000","message":"how about overriding the _make_router_dict directly so that we don\u0027t need to override many of the functions in this function.","commit_id":"56715ad727a40dd6ff3e91ff144ea215a6374b8e"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":99,"context_line":"            context.session.add(router_rule)"},{"line_number":100,"context_line":"        context.session.flush()"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def _make_router_rule_list(self, router_rules):"},{"line_number":103,"context_line":"        ruleslist \u003d []"},{"line_number":104,"context_line":"        for rule in router_rules:"},{"line_number":105,"context_line":"            hops \u003d [hop[\u0027nexthop\u0027] for hop in rule[\u0027nexthops\u0027]]"}],"source_content_type":"text/x-python","patch_set":14,"id":"AAAAPn%2F%2F99M%3D","line":102,"in_reply_to":"AAAAPn%2F%2F%2BEc%3D","updated":"2013-06-17 08:32:08.000000000","message":"_make_router_dict does not have the database context passed into it so I cannot lookup the rules in that function. I would still have to override all of the \u0027_router\u0027 functions to call the database to lookup the router rules. Therefore, I wouldn\u0027t be saving any lines of code since I would just be replacing the _make_router_rule_list function with an override of _make_router_dict. \n\nAlso, I\u0027m not sure of the code etiquette here, but shouldn\u0027t I avoid overriding private helper functions?","commit_id":"56715ad727a40dd6ff3e91ff144ea215a6374b8e"},{"author":{"_account_id":2874,"name":"yong sheng gong","email":"gong.yongsheng@99cloud.net","username":"gongysh"},"unresolved":false,"context_lines":[{"line_number":99,"context_line":"            context.session.add(router_rule)"},{"line_number":100,"context_line":"        context.session.flush()"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def _make_router_rule_list(self, router_rules):"},{"line_number":103,"context_line":"        ruleslist \u003d []"},{"line_number":104,"context_line":"        for rule in router_rules:"},{"line_number":105,"context_line":"            hops \u003d [hop[\u0027nexthop\u0027] for hop in rule[\u0027nexthops\u0027]]"}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAPn%2F%2F9W0%3D","line":102,"updated":"2013-06-17 13:06:41.000000000","message":"I prefer to overritde _make_router_dict so that we don\u0027t have to override all other functions.","commit_id":"94a699b6c3c9cc1fe02c62c522cb346d2353e142"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":99,"context_line":"            context.session.add(router_rule)"},{"line_number":100,"context_line":"        context.session.flush()"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def _make_router_rule_list(self, router_rules):"},{"line_number":103,"context_line":"        ruleslist \u003d []"},{"line_number":104,"context_line":"        for rule in router_rules:"},{"line_number":105,"context_line":"            hops \u003d [hop[\u0027nexthop\u0027] for hop in rule[\u0027nexthops\u0027]]"}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAPn%2F%2F9CU%3D","line":102,"in_reply_to":"AAAAPn%2F%2F9W0%3D","updated":"2013-06-17 14:43:23.000000000","message":"Please see my reply to your comment on the previous patch set. Due to \u0027context\u0027 not being passed into _make_router_dict, all of the same methods will have to be overwritten anyway to populate router[\u0027router_rules\u0027] with the objects from the database.","commit_id":"94a699b6c3c9cc1fe02c62c522cb346d2353e142"},{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":42,"context_line":"class NextHop(model_base.BASEV2):"},{"line_number":43,"context_line":"    rule_id \u003d sa.Column(sa.Integer,"},{"line_number":44,"context_line":"                        sa.ForeignKey(\u0027routerrules.id\u0027,"},{"line_number":45,"context_line":"                                      ondelete\u003d\"CASCADE\"), primary_key\u003dTrue)"},{"line_number":46,"context_line":"    nexthop \u003d sa.Column(sa.String(64), nullable\u003dFalse, primary_key\u003dTrue)"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAPn%2F%2F7Hg%3D","line":45,"updated":"2013-06-18 06:18:18.000000000","message":"primary_key should be justified with sa.Integer, sa.ForeignKey","commit_id":"845c977977b5a26faa9084130149e8497ab59063"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":42,"context_line":"class NextHop(model_base.BASEV2):"},{"line_number":43,"context_line":"    rule_id \u003d sa.Column(sa.Integer,"},{"line_number":44,"context_line":"                        sa.ForeignKey(\u0027routerrules.id\u0027,"},{"line_number":45,"context_line":"                                      ondelete\u003d\"CASCADE\"), primary_key\u003dTrue)"},{"line_number":46,"context_line":"    nexthop \u003d sa.Column(sa.String(64), nullable\u003dFalse, primary_key\u003dTrue)"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAPn%2F%2F5yU%3D","line":45,"in_reply_to":"AAAAPn%2F%2F7Hg%3D","updated":"2013-06-18 17:34:58.000000000","message":"Done","commit_id":"845c977977b5a26faa9084130149e8497ab59063"}],"quantum/tests/unit/bigswitch/test_router_db.py":[{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":335,"context_line":"                                {\u0027router\u0027: {\u0027router_rules\u0027: router_rules}})"},{"line_number":336,"context_line":""},{"line_number":337,"context_line":"            body \u003d self._show(\u0027routers\u0027, r[\u0027router\u0027][\u0027id\u0027])"},{"line_number":338,"context_line":"            self.assertTrue(\u0027router_rules\u0027 in body[\u0027router\u0027])"},{"line_number":339,"context_line":"            rules \u003d body[\u0027router\u0027][\u0027router_rules\u0027]"},{"line_number":340,"context_line":"            self.assertEqual(_strip_rule_ids(rules), router_rules)"},{"line_number":341,"context_line":"            # Try after adding another rule"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2FyFc%3D","line":338,"updated":"2013-06-10 19:23:38.000000000","message":"self.assertIn()","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":335,"context_line":"                                {\u0027router\u0027: {\u0027router_rules\u0027: router_rules}})"},{"line_number":336,"context_line":""},{"line_number":337,"context_line":"            body \u003d self._show(\u0027routers\u0027, r[\u0027router\u0027][\u0027id\u0027])"},{"line_number":338,"context_line":"            self.assertTrue(\u0027router_rules\u0027 in body[\u0027router\u0027])"},{"line_number":339,"context_line":"            rules \u003d body[\u0027router\u0027][\u0027router_rules\u0027]"},{"line_number":340,"context_line":"            self.assertEqual(_strip_rule_ids(rules), router_rules)"},{"line_number":341,"context_line":"            # Try after adding another rule"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2Fx64%3D","line":338,"in_reply_to":"AAAAPX%2F%2FyFc%3D","updated":"2013-06-10 21:52:28.000000000","message":"Done","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":346,"context_line":"                                {\u0027router\u0027: {\u0027router_rules\u0027: router_rules}})"},{"line_number":347,"context_line":""},{"line_number":348,"context_line":"            body \u003d self._show(\u0027routers\u0027, r[\u0027router\u0027][\u0027id\u0027])"},{"line_number":349,"context_line":"            self.assertTrue(\u0027router_rules\u0027 in body[\u0027router\u0027])"},{"line_number":350,"context_line":"            rules \u003d body[\u0027router\u0027][\u0027router_rules\u0027]"},{"line_number":351,"context_line":"            self.assertEqual(_strip_rule_ids(rules), router_rules)"},{"line_number":352,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2FyFY%3D","line":349,"updated":"2013-06-10 19:23:38.000000000","message":"assertIn()","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":346,"context_line":"                                {\u0027router\u0027: {\u0027router_rules\u0027: router_rules}})"},{"line_number":347,"context_line":""},{"line_number":348,"context_line":"            body \u003d self._show(\u0027routers\u0027, r[\u0027router\u0027][\u0027id\u0027])"},{"line_number":349,"context_line":"            self.assertTrue(\u0027router_rules\u0027 in body[\u0027router\u0027])"},{"line_number":350,"context_line":"            rules \u003d body[\u0027router\u0027][\u0027router_rules\u0027]"},{"line_number":351,"context_line":"            self.assertEqual(_strip_rule_ids(rules), router_rules)"},{"line_number":352,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2Fx68%3D","line":349,"in_reply_to":"AAAAPX%2F%2FyFY%3D","updated":"2013-06-10 21:52:28.000000000","message":"Done","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":411,"context_line":"                                expected_code\u003dexc.HTTPBadRequest.code)"},{"line_number":412,"context_line":"            # make sure good rules persisted during bad updates"},{"line_number":413,"context_line":"            body \u003d self._show(\u0027routers\u0027, r_id)"},{"line_number":414,"context_line":"            self.assertTrue(\u0027router_rules\u0027 in body[\u0027router\u0027])"},{"line_number":415,"context_line":"            self.assertEqual(good_rules,"},{"line_number":416,"context_line":"                             _strip_rule_ids(body[\u0027router\u0027][\u0027router_rules\u0027]))"},{"line_number":417,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2FyFE%3D","line":414,"updated":"2013-06-10 19:23:38.000000000","message":"assertIn()","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":411,"context_line":"                                expected_code\u003dexc.HTTPBadRequest.code)"},{"line_number":412,"context_line":"            # make sure good rules persisted during bad updates"},{"line_number":413,"context_line":"            body \u003d self._show(\u0027routers\u0027, r_id)"},{"line_number":414,"context_line":"            self.assertTrue(\u0027router_rules\u0027 in body[\u0027router\u0027])"},{"line_number":415,"context_line":"            self.assertEqual(good_rules,"},{"line_number":416,"context_line":"                             _strip_rule_ids(body[\u0027router\u0027][\u0027router_rules\u0027]))"},{"line_number":417,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAPX%2F%2Fx7A%3D","line":414,"in_reply_to":"AAAAPX%2F%2FyFE%3D","updated":"2013-06-10 21:52:28.000000000","message":"Done","commit_id":"e92e7d043a7f8a4b704131aa1903fece2834aba2"},{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":394,"context_line":""},{"line_number":395,"context_line":"            # Missing nexthops should be populated with an empty list"},{"line_number":396,"context_line":"            light_rules \u003d copy.deepcopy(good_rules)"},{"line_number":397,"context_line":"            del(light_rules[0][\u0027nexthops\u0027])"},{"line_number":398,"context_line":"            body \u003d self._update(\u0027routers\u0027, r_id,"},{"line_number":399,"context_line":"                                {\u0027router\u0027: {\u0027router_rules\u0027: light_rules}})"},{"line_number":400,"context_line":"            body \u003d self._show(\u0027routers\u0027, r_id)"}],"source_content_type":"text/x-python","patch_set":17,"id":"AAAAPn%2F%2Fxls%3D","line":397,"updated":"2013-06-21 15:04:01.000000000","message":"del is a python keyword.. no need to wrap it in parens.\n\ndel light_rules[0][\u0027nexthops\u0027]","commit_id":"a90ee262d80afa931120bd45f5c1cf13cff90195"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":394,"context_line":""},{"line_number":395,"context_line":"            # Missing nexthops should be populated with an empty list"},{"line_number":396,"context_line":"            light_rules \u003d copy.deepcopy(good_rules)"},{"line_number":397,"context_line":"            del(light_rules[0][\u0027nexthops\u0027])"},{"line_number":398,"context_line":"            body \u003d self._update(\u0027routers\u0027, r_id,"},{"line_number":399,"context_line":"                                {\u0027router\u0027: {\u0027router_rules\u0027: light_rules}})"},{"line_number":400,"context_line":"            body \u003d self._show(\u0027routers\u0027, r_id)"}],"source_content_type":"text/x-python","patch_set":17,"id":"AAAAPn%2F%2FxPo%3D","line":397,"in_reply_to":"AAAAPn%2F%2Fxls%3D","updated":"2013-06-21 17:20:13.000000000","message":"Done","commit_id":"a90ee262d80afa931120bd45f5c1cf13cff90195"},{"author":{"_account_id":2592,"name":"Mark McClain","email":"mark@mcclain.xyz","username":"markmcclain"},"unresolved":false,"context_lines":[{"line_number":472,"context_line":"def _strip_rule_ids(rules):"},{"line_number":473,"context_line":"    cleaned \u003d []"},{"line_number":474,"context_line":"    for rule in rules:"},{"line_number":475,"context_line":"        del(rule[\u0027id\u0027])"},{"line_number":476,"context_line":"        cleaned.append(rule)"},{"line_number":477,"context_line":"    return cleaned"}],"source_content_type":"text/x-python","patch_set":17,"id":"AAAAPn%2F%2Fxlw%3D","line":475,"updated":"2013-06-21 15:04:01.000000000","message":"del is a python keyword.. no need to wrap it in parens.\n\ndel rule[\u0027id\u0027]","commit_id":"a90ee262d80afa931120bd45f5c1cf13cff90195"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"4132ddf0c1fc682b33944441d3e28b5f3025a295","unresolved":false,"context_lines":[{"line_number":472,"context_line":"def _strip_rule_ids(rules):"},{"line_number":473,"context_line":"    cleaned \u003d []"},{"line_number":474,"context_line":"    for rule in rules:"},{"line_number":475,"context_line":"        del(rule[\u0027id\u0027])"},{"line_number":476,"context_line":"        cleaned.append(rule)"},{"line_number":477,"context_line":"    return cleaned"}],"source_content_type":"text/x-python","patch_set":17,"id":"AAAAPn%2F%2FxPk%3D","line":475,"in_reply_to":"AAAAPn%2F%2Fxlw%3D","updated":"2013-06-21 17:20:13.000000000","message":"Done","commit_id":"a90ee262d80afa931120bd45f5c1cf13cff90195"}]}
