)]}'
{"heat/engine/resources/neutron/router.py":[{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"056799d93c15ee4abbda5fa869ab50ae65300b4a","unresolved":false,"context_lines":[{"line_number":138,"context_line":"class RouterProperties(neutron.NeutronResource):"},{"line_number":139,"context_line":"    properties_schema \u003d {\u0027router_id\u0027: {\u0027Type\u0027: \u0027String\u0027,"},{"line_number":140,"context_line":"                                       \u0027Required\u0027: True},"},{"line_number":141,"context_line":"                         \u0027router\u0027: {\u0027Type\u0027: \u0027Map\u0027,"},{"line_number":142,"context_line":"                                    \u0027Required\u0027: True}}"},{"line_number":143,"context_line":""},{"line_number":144,"context_line":"    def __init__(self, name, json_snippet, stack):"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAQn%2F%2B9TU%3D","line":141,"updated":"2013-08-09 10:28:33.000000000","message":"This doesn\u0027t seem to describe the property very well, as it\u0027s actually a list of subnets from the look of the tests?","commit_id":"c42f9ef555ae0712f1639b6118ae25922f91eb4d"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"a4b9b179ec730964ed0fa15f9b645c0bf9da24c2","unresolved":false,"context_lines":[{"line_number":138,"context_line":"class RouterProperties(neutron.NeutronResource):"},{"line_number":139,"context_line":"    properties_schema \u003d {\u0027router_id\u0027: {\u0027Type\u0027: \u0027String\u0027,"},{"line_number":140,"context_line":"                                       \u0027Required\u0027: True},"},{"line_number":141,"context_line":"                         \u0027router\u0027: {\u0027Type\u0027: \u0027Map\u0027,"},{"line_number":142,"context_line":"                                    \u0027Required\u0027: True}}"},{"line_number":143,"context_line":""},{"line_number":144,"context_line":"    def __init__(self, name, json_snippet, stack):"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAQn%2F%2B9Mg%3D","line":141,"in_reply_to":"AAAAQn%2F%2B9TU%3D","updated":"2013-08-09 11:15:23.000000000","message":"I agree it\u0027s not very descriptive, but it needs to allow arbitrary updates to the router object so it can work with any type of router extension. In my example and the unit tests, I show the extra routes extension, but this could also be used for vendor specific router extensions.","commit_id":"c42f9ef555ae0712f1639b6118ae25922f91eb4d"},{"author":{"_account_id":4328,"name":"Steven Hardy","email":"steven.hardy@suse.com","username":"shardy"},"change_message_id":"056799d93c15ee4abbda5fa869ab50ae65300b4a","unresolved":false,"context_lines":[{"line_number":147,"context_line":"    def handle_create(self):"},{"line_number":148,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":149,"context_line":"        router_contents \u003d self.properties.get(\u0027router\u0027)"},{"line_number":150,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027: router_contents})"},{"line_number":151,"context_line":"        self.resource_id_set(\u0027%s:%s\u0027 % (router_id, router_contents))"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"    def handle_delete(self):"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAQn%2F%2B9TM%3D","line":150,"updated":"2013-08-09 10:28:33.000000000","message":"This indicates that this should probably not be a new resource at all (also implied by the name) seems like maybe this should just be some additional property of an existing resource, and that resource should implement handle_update to allow template modification post-create","commit_id":"c42f9ef555ae0712f1639b6118ae25922f91eb4d"},{"author":{"_account_id":7135,"name":"Liang Chen","email":"liangchen.linux@gmail.com","username":"Liang"},"change_message_id":"b3f7f3141f7908acdec042a553cf763d913d6e64","unresolved":false,"context_lines":[{"line_number":147,"context_line":"    def handle_create(self):"},{"line_number":148,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":149,"context_line":"        router_contents \u003d self.properties.get(\u0027router\u0027)"},{"line_number":150,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027: router_contents})"},{"line_number":151,"context_line":"        self.resource_id_set(\u0027%s:%s\u0027 % (router_id, router_contents))"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"    def handle_delete(self):"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAQ3%2F%2F6%2Bg%3D","line":150,"in_reply_to":"AAAAQ3%2F%2F%2Ffw%3D","updated":"2013-08-12 23:17:51.000000000","message":"I wonder how users specify a native Neutron router Id with the current implementation in this case. The router_id property is supposed to be a Ref Id in the template, right?","commit_id":"c42f9ef555ae0712f1639b6118ae25922f91eb4d"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"9891ad64990477a5e5bffa71e788fcfdf403c863","unresolved":false,"context_lines":[{"line_number":147,"context_line":"    def handle_create(self):"},{"line_number":148,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":149,"context_line":"        router_contents \u003d self.properties.get(\u0027router\u0027)"},{"line_number":150,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027: router_contents})"},{"line_number":151,"context_line":"        self.resource_id_set(\u0027%s:%s\u0027 % (router_id, router_contents))"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"    def handle_delete(self):"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAQ3%2F%2F%2Ffw%3D","line":150,"in_reply_to":"AAAAQ3%2F%2F%2Fg8%3D","updated":"2013-08-11 15:15:16.000000000","message":"Could that satisfy the use case where a template needs to add routes to an existing router?","commit_id":"c42f9ef555ae0712f1639b6118ae25922f91eb4d"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"8f6ea589a7445b3c933a396c2901b06b458f085e","unresolved":false,"context_lines":[{"line_number":147,"context_line":"    def handle_create(self):"},{"line_number":148,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":149,"context_line":"        router_contents \u003d self.properties.get(\u0027router\u0027)"},{"line_number":150,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027: router_contents})"},{"line_number":151,"context_line":"        self.resource_id_set(\u0027%s:%s\u0027 % (router_id, router_contents))"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"    def handle_delete(self):"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAQ3%2F%2F6j4%3D","line":150,"in_reply_to":"AAAAQ3%2F%2F6%2Bg%3D","updated":"2013-08-13 01:48:14.000000000","message":"A template could require an existing router ID as input. While it would be tedious to require that on the command-line for manual creation, it could be part of an automated process or a back-end to some GUI.\n\nIt is more logical that items that can be associated with a router via a router update operation should be allowed to be separate from the creation process in the templates. This is particularly important if an extra route (or some other router property) depends on the IP address of a particular instance that hasn\u0027t been created yet. We don\u0027t want to block the creation of the router just because some of the information for the properties aren\u0027t available yet.","commit_id":"c42f9ef555ae0712f1639b6118ae25922f91eb4d"},{"author":{"_account_id":7135,"name":"Liang Chen","email":"liangchen.linux@gmail.com","username":"Liang"},"change_message_id":"af2efd08495cf20ed0e64130964b239199ba27c4","unresolved":false,"context_lines":[{"line_number":147,"context_line":"    def handle_create(self):"},{"line_number":148,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":149,"context_line":"        router_contents \u003d self.properties.get(\u0027router\u0027)"},{"line_number":150,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027: router_contents})"},{"line_number":151,"context_line":"        self.resource_id_set(\u0027%s:%s\u0027 % (router_id, router_contents))"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"    def handle_delete(self):"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAQ3%2F%2F%2Fg8%3D","line":150,"in_reply_to":"AAAAQn%2F%2B9Lk%3D","updated":"2013-08-11 14:59:46.000000000","message":"Sounds like this can be handled in check_create_complete for a newly created router if this is implemented as some additional property.","commit_id":"c42f9ef555ae0712f1639b6118ae25922f91eb4d"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"a4b9b179ec730964ed0fa15f9b645c0bf9da24c2","unresolved":false,"context_lines":[{"line_number":147,"context_line":"    def handle_create(self):"},{"line_number":148,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":149,"context_line":"        router_contents \u003d self.properties.get(\u0027router\u0027)"},{"line_number":150,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027: router_contents})"},{"line_number":151,"context_line":"        self.resource_id_set(\u0027%s:%s\u0027 % (router_id, router_contents))"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"    def handle_delete(self):"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAQn%2F%2B9Lk%3D","line":150,"in_reply_to":"AAAAQn%2F%2B9TM%3D","updated":"2013-08-09 11:15:23.000000000","message":"I can make that modification. If I implement this as handle_update for the Router class, how would I trigger an update of a newly created router inside a template? (Treating the properties as a separate object made it relatively straight forward.)","commit_id":"c42f9ef555ae0712f1639b6118ae25922f91eb4d"},{"author":{"_account_id":8844,"name":"Mitsuru Kanabuchi","email":"kanabuchi.mitsuru@po.ntts.co.jp","username":"kanabuchi"},"change_message_id":"49682c916eceafb539b5afe0b5014eefb67025ae","unresolved":false,"context_lines":[{"line_number":181,"context_line":"                raise ex"},{"line_number":182,"context_line":""},{"line_number":183,"context_line":""},{"line_number":184,"context_line":"class RouterExtraRoutes(neutron.NeutronResource):"},{"line_number":185,"context_line":"    routes_schema \u003d {\u0027destination\u0027: {\u0027Type\u0027: \u0027String\u0027,"},{"line_number":186,"context_line":"                                     \u0027Required\u0027: True},"},{"line_number":187,"context_line":"                     \u0027nexthop\u0027: {\u0027Type\u0027: \u0027String\u0027,"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BNhs%3D","line":184,"updated":"2013-11-29 05:09:57.000000000","message":"I think, RouterRoutes is appropriate for class name, because neutron\u0027s property name is \"routes\". What do you think?","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"36e129bf71a121acfd2229b7fd4c816f844fee18","unresolved":false,"context_lines":[{"line_number":181,"context_line":"                raise ex"},{"line_number":182,"context_line":""},{"line_number":183,"context_line":""},{"line_number":184,"context_line":"class RouterExtraRoutes(neutron.NeutronResource):"},{"line_number":185,"context_line":"    routes_schema \u003d {\u0027destination\u0027: {\u0027Type\u0027: \u0027String\u0027,"},{"line_number":186,"context_line":"                                     \u0027Required\u0027: True},"},{"line_number":187,"context_line":"                     \u0027nexthop\u0027: {\u0027Type\u0027: \u0027String\u0027,"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BNbQ%3D","line":184,"in_reply_to":"AAAATn%2F%2BNhs%3D","updated":"2013-11-29 06:05:23.000000000","message":"I completely agree. For some reason I thought the property was \u0027extraroutes\u0027.","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":8844,"name":"Mitsuru Kanabuchi","email":"kanabuchi.mitsuru@po.ntts.co.jp","username":"kanabuchi"},"change_message_id":"49682c916eceafb539b5afe0b5014eefb67025ae","unresolved":false,"context_lines":[{"line_number":188,"context_line":"                                 \u0027Required\u0027: True}}"},{"line_number":189,"context_line":"    properties_schema \u003d {\u0027router_id\u0027: {\u0027Type\u0027: \u0027String\u0027,"},{"line_number":190,"context_line":"                                       \u0027Required\u0027: True},"},{"line_number":191,"context_line":"                         \u0027extraroutes\u0027: {\u0027Type\u0027: \u0027List\u0027,"},{"line_number":192,"context_line":"                                         \u0027Schema\u0027: {"},{"line_number":193,"context_line":"                                             \u0027Type\u0027: \u0027Map\u0027,"},{"line_number":194,"context_line":"                                             \u0027Schema\u0027: routes_schema"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BNhg%3D","line":191,"updated":"2013-11-29 05:09:57.000000000","message":"I think, \"routes\" is appropriate for property name, because neutron\u0027s property name is \"routes\".","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"36e129bf71a121acfd2229b7fd4c816f844fee18","unresolved":false,"context_lines":[{"line_number":188,"context_line":"                                 \u0027Required\u0027: True}}"},{"line_number":189,"context_line":"    properties_schema \u003d {\u0027router_id\u0027: {\u0027Type\u0027: \u0027String\u0027,"},{"line_number":190,"context_line":"                                       \u0027Required\u0027: True},"},{"line_number":191,"context_line":"                         \u0027extraroutes\u0027: {\u0027Type\u0027: \u0027List\u0027,"},{"line_number":192,"context_line":"                                         \u0027Schema\u0027: {"},{"line_number":193,"context_line":"                                             \u0027Type\u0027: \u0027Map\u0027,"},{"line_number":194,"context_line":"                                             \u0027Schema\u0027: routes_schema"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BNbI%3D","line":191,"in_reply_to":"AAAATn%2F%2BNhg%3D","updated":"2013-11-29 06:05:23.000000000","message":"Done","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":8844,"name":"Mitsuru Kanabuchi","email":"kanabuchi.mitsuru@po.ntts.co.jp","username":"kanabuchi"},"change_message_id":"49682c916eceafb539b5afe0b5014eefb67025ae","unresolved":false,"context_lines":[{"line_number":195,"context_line":"                                         },"},{"line_number":196,"context_line":"                                         \u0027Required\u0027: True}}"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":"    def __init__(self, name, json_snippet, stack):"},{"line_number":199,"context_line":"        super(RouterExtraRoutes, self).__init__(name, json_snippet, stack)"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":"    def handle_create(self):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BNhU%3D","line":198,"updated":"2013-11-29 05:09:57.000000000","message":"Function __init__ isn\u0027t necessary at here.","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"36e129bf71a121acfd2229b7fd4c816f844fee18","unresolved":false,"context_lines":[{"line_number":195,"context_line":"                                         },"},{"line_number":196,"context_line":"                                         \u0027Required\u0027: True}}"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":"    def __init__(self, name, json_snippet, stack):"},{"line_number":199,"context_line":"        super(RouterExtraRoutes, self).__init__(name, json_snippet, stack)"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":"    def handle_create(self):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BNbE%3D","line":198,"in_reply_to":"AAAATn%2F%2BNhU%3D","updated":"2013-11-29 06:05:23.000000000","message":"Done","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":8844,"name":"Mitsuru Kanabuchi","email":"kanabuchi.mitsuru@po.ntts.co.jp","username":"kanabuchi"},"change_message_id":"49682c916eceafb539b5afe0b5014eefb67025ae","unresolved":false,"context_lines":[{"line_number":197,"context_line":""},{"line_number":198,"context_line":"    def __init__(self, name, json_snippet, stack):"},{"line_number":199,"context_line":"        super(RouterExtraRoutes, self).__init__(name, json_snippet, stack)"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":"    def handle_create(self):"},{"line_number":202,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":203,"context_line":"        extraroutes \u003d self.properties.get(\u0027extraroutes\u0027)"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BNek%3D","line":200,"updated":"2013-11-29 05:09:57.000000000","message":"I think add_dependencies implementation is essential here.\nNeutron needs connectivity between router and subnet in advance of setting nexthop.","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":8844,"name":"Mitsuru Kanabuchi","email":"kanabuchi.mitsuru@po.ntts.co.jp","username":"kanabuchi"},"change_message_id":"d8fccfed0e1224ca32b609e8a47726f9fdad43a2","unresolved":false,"context_lines":[{"line_number":197,"context_line":""},{"line_number":198,"context_line":"    def __init__(self, name, json_snippet, stack):"},{"line_number":199,"context_line":"        super(RouterExtraRoutes, self).__init__(name, json_snippet, stack)"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":"    def handle_create(self):"},{"line_number":202,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":203,"context_line":"        extraroutes \u003d self.properties.get(\u0027extraroutes\u0027)"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BNCU%3D","line":200,"in_reply_to":"AAAATn%2F%2BNYQ%3D","updated":"2013-11-29 08:58:35.000000000","message":"The connectivity is necessary. I paste neutron\u0027s response when lacked connectivity. Please check it.\n----------\n{\"NeutronError\": {\"message\": \"Invalid format for routes: [{u\u0027nexthop\u0027: u\u002710.0.1.1\u0027, u\u0027destination\u0027: u\u0027192.168.0.0/24\u0027}], the nexthop is not connected with router\", \"type\": \"InvalidRoutes\", \"detail\": \"\"}}","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"36e129bf71a121acfd2229b7fd4c816f844fee18","unresolved":false,"context_lines":[{"line_number":197,"context_line":""},{"line_number":198,"context_line":"    def __init__(self, name, json_snippet, stack):"},{"line_number":199,"context_line":"        super(RouterExtraRoutes, self).__init__(name, json_snippet, stack)"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":"    def handle_create(self):"},{"line_number":202,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":203,"context_line":"        extraroutes \u003d self.properties.get(\u0027extraroutes\u0027)"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BNYQ%3D","line":200,"in_reply_to":"AAAATn%2F%2BNek%3D","updated":"2013-11-29 06:05:23.000000000","message":"Is this necessarily true? Routes can be added to a router just based on IP address regardless of connectivity. \n\nIf a route required the IP address of a connected device, wouldn\u0027t a Ref to that device\u0027s address automatically cause heat to wait until that device was online to fulfill that Ref?","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":8844,"name":"Mitsuru Kanabuchi","email":"kanabuchi.mitsuru@po.ntts.co.jp","username":"kanabuchi"},"change_message_id":"49682c916eceafb539b5afe0b5014eefb67025ae","unresolved":false,"context_lines":[{"line_number":202,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":203,"context_line":"        extraroutes \u003d self.properties.get(\u0027extraroutes\u0027)"},{"line_number":204,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":205,"context_line":"                                     {\u0027extraroutes\u0027: extraroutes}})"},{"line_number":206,"context_line":"        self.resource_id_set(\u0027%s:%s\u0027 % (router_id, extraroutes))"},{"line_number":207,"context_line":""},{"line_number":208,"context_line":"    def handle_delete(self):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BNeM%3D","line":205,"updated":"2013-11-29 05:09:57.000000000","message":"Neutron router\u0027s property name is \"routes\". Probably, error will occur at here.","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"36e129bf71a121acfd2229b7fd4c816f844fee18","unresolved":false,"context_lines":[{"line_number":202,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":203,"context_line":"        extraroutes \u003d self.properties.get(\u0027extraroutes\u0027)"},{"line_number":204,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":205,"context_line":"                                     {\u0027extraroutes\u0027: extraroutes}})"},{"line_number":206,"context_line":"        self.resource_id_set(\u0027%s:%s\u0027 % (router_id, extraroutes))"},{"line_number":207,"context_line":""},{"line_number":208,"context_line":"    def handle_delete(self):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BNa8%3D","line":205,"in_reply_to":"AAAATn%2F%2BNeM%3D","updated":"2013-11-29 06:05:23.000000000","message":"Done","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":8844,"name":"Mitsuru Kanabuchi","email":"kanabuchi.mitsuru@po.ntts.co.jp","username":"kanabuchi"},"change_message_id":"49682c916eceafb539b5afe0b5014eefb67025ae","unresolved":false,"context_lines":[{"line_number":206,"context_line":"        self.resource_id_set(\u0027%s:%s\u0027 % (router_id, extraroutes))"},{"line_number":207,"context_line":""},{"line_number":208,"context_line":"    def handle_delete(self):"},{"line_number":209,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":210,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":211,"context_line":"                                     {\u0027extraroutes\u0027: []}})"},{"line_number":212,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BNeE%3D","line":209,"updated":"2013-11-29 05:09:57.000000000","message":"I think, route_id should get from self.resource_id.","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"899496832c38d857e3581aa831a6763696b787ca","unresolved":false,"context_lines":[{"line_number":206,"context_line":"        self.resource_id_set(\u0027%s:%s\u0027 % (router_id, extraroutes))"},{"line_number":207,"context_line":""},{"line_number":208,"context_line":"    def handle_delete(self):"},{"line_number":209,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":210,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":211,"context_line":"                                     {\u0027extraroutes\u0027: []}})"},{"line_number":212,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BKd8%3D","line":209,"in_reply_to":"AAAATn%2F%2BNAo%3D","updated":"2013-11-30 08:40:41.000000000","message":"Oh I see. Perhaps the properties are not always available in the update and delete contexts. I have updated it to split the id.","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":8844,"name":"Mitsuru Kanabuchi","email":"kanabuchi.mitsuru@po.ntts.co.jp","username":"kanabuchi"},"change_message_id":"d8fccfed0e1224ca32b609e8a47726f9fdad43a2","unresolved":false,"context_lines":[{"line_number":206,"context_line":"        self.resource_id_set(\u0027%s:%s\u0027 % (router_id, extraroutes))"},{"line_number":207,"context_line":""},{"line_number":208,"context_line":"    def handle_delete(self):"},{"line_number":209,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":210,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":211,"context_line":"                                     {\u0027extraroutes\u0027: []}})"},{"line_number":212,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BNAo%3D","line":209,"in_reply_to":"AAAATn%2F%2BNa4%3D","updated":"2013-11-29 08:58:35.000000000","message":"I agreed that necessity of router id. My comment mean is about method of getting router_id. Other codes gets id from resource_id.split. I thought, similar implementation is also appropriate in here.","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"36e129bf71a121acfd2229b7fd4c816f844fee18","unresolved":false,"context_lines":[{"line_number":206,"context_line":"        self.resource_id_set(\u0027%s:%s\u0027 % (router_id, extraroutes))"},{"line_number":207,"context_line":""},{"line_number":208,"context_line":"    def handle_delete(self):"},{"line_number":209,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":210,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":211,"context_line":"                                     {\u0027extraroutes\u0027: []}})"},{"line_number":212,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BNa4%3D","line":209,"in_reply_to":"AAAATn%2F%2BNeE%3D","updated":"2013-11-29 06:05:23.000000000","message":"This needs the router_id though. Neutron doesn\u0027t have a notion of handling individual route items via the API, does it? The only way I was aware of updating routes was via the router_id and specifying the routes as a list in the routes property.","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":8844,"name":"Mitsuru Kanabuchi","email":"kanabuchi.mitsuru@po.ntts.co.jp","username":"kanabuchi"},"change_message_id":"49682c916eceafb539b5afe0b5014eefb67025ae","unresolved":false,"context_lines":[{"line_number":208,"context_line":"    def handle_delete(self):"},{"line_number":209,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":210,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":211,"context_line":"                                     {\u0027extraroutes\u0027: []}})"},{"line_number":212,"context_line":""},{"line_number":213,"context_line":""},{"line_number":214,"context_line":"def resource_mapping():"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BNdI%3D","line":211,"updated":"2013-11-29 05:09:57.000000000","message":"Neutron router\u0027s property name is \"routes\".\nTry and except NeutronClientException handling is necessary here.\nWe should avoid unnecessary raise in case of 404 error.","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"36e129bf71a121acfd2229b7fd4c816f844fee18","unresolved":false,"context_lines":[{"line_number":208,"context_line":"    def handle_delete(self):"},{"line_number":209,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":210,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":211,"context_line":"                                     {\u0027extraroutes\u0027: []}})"},{"line_number":212,"context_line":""},{"line_number":213,"context_line":""},{"line_number":214,"context_line":"def resource_mapping():"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BNa0%3D","line":211,"in_reply_to":"AAAATn%2F%2BNdI%3D","updated":"2013-11-29 06:05:23.000000000","message":"Done","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":8844,"name":"Mitsuru Kanabuchi","email":"kanabuchi.mitsuru@po.ntts.co.jp","username":"kanabuchi"},"change_message_id":"49682c916eceafb539b5afe0b5014eefb67025ae","unresolved":false,"context_lines":[{"line_number":210,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":211,"context_line":"                                     {\u0027extraroutes\u0027: []}})"},{"line_number":212,"context_line":""},{"line_number":213,"context_line":""},{"line_number":214,"context_line":"def resource_mapping():"},{"line_number":215,"context_line":"    if clients.neutronclient is None:"},{"line_number":216,"context_line":"        return {}"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BNco%3D","line":213,"updated":"2013-11-29 05:09:57.000000000","message":"I have a feeling that it need to implement handle_update.\nBecause UpdateReplace is not appropriate for this class.\nhandle_create would set routes property but, handle_delete would clear routes property after that.\nEventually, routes property would be always empty after updated, I guess.","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":8844,"name":"Mitsuru Kanabuchi","email":"kanabuchi.mitsuru@po.ntts.co.jp","username":"kanabuchi"},"change_message_id":"d8fccfed0e1224ca32b609e8a47726f9fdad43a2","unresolved":false,"context_lines":[{"line_number":210,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":211,"context_line":"                                     {\u0027extraroutes\u0027: []}})"},{"line_number":212,"context_line":""},{"line_number":213,"context_line":""},{"line_number":214,"context_line":"def resource_mapping():"},{"line_number":215,"context_line":"    if clients.neutronclient is None:"},{"line_number":216,"context_line":"        return {}"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BM9c%3D","line":213,"in_reply_to":"AAAATn%2F%2BNYg%3D","updated":"2013-11-29 08:58:35.000000000","message":"In my understand, json_snippet doesn\u0027t have previous routes.\nHowever, previous routes is unnecessary property for handle_update.\nBecause new routes should override from new template file\u0027s property.","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"36e129bf71a121acfd2229b7fd4c816f844fee18","unresolved":false,"context_lines":[{"line_number":210,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":211,"context_line":"                                     {\u0027extraroutes\u0027: []}})"},{"line_number":212,"context_line":""},{"line_number":213,"context_line":""},{"line_number":214,"context_line":"def resource_mapping():"},{"line_number":215,"context_line":"    if clients.neutronclient is None:"},{"line_number":216,"context_line":"        return {}"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BNYg%3D","line":213,"in_reply_to":"AAAATn%2F%2BNco%3D","updated":"2013-11-29 06:05:23.000000000","message":"I have added it in the next patch, but I\u0027m not exactly sure how the framework handles an update. Will it automatically include the previous routes in the json_snippet when an update comes?","commit_id":"325878a4b1275f87fe6f5f211dd16ab6e5a5f006"},{"author":{"_account_id":8844,"name":"Mitsuru Kanabuchi","email":"kanabuchi.mitsuru@po.ntts.co.jp","username":"kanabuchi"},"change_message_id":"a026d410d8f2cb0fc8e580e5852c9b3baa699999","unresolved":false,"context_lines":[{"line_number":192,"context_line":"                                    \u0027Schema\u0027: {\u0027Type\u0027: \u0027Map\u0027,"},{"line_number":193,"context_line":"                                               \u0027Schema\u0027: routes_schema},"},{"line_number":194,"context_line":"                                    \u0027Required\u0027: True}}"},{"line_number":195,"context_line":""},{"line_number":196,"context_line":"    def handle_create(self):"},{"line_number":197,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":198,"context_line":"        routes \u003d self.properties.get(\u0027routes\u0027)"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAATn%2F%2BM8w%3D","line":195,"updated":"2013-11-29 08:59:00.000000000","message":"UpdateAllowed attribute and update_allowed_keys need at around here.\nAnd add_dependencies is essential, please see previous patch replay.","commit_id":"0e1c9a0d76a7b1ae5816ed398b7108fbd2b1d897"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"1bf27f47e06ff1d1b86dbc42a587cf37fc780a6c","unresolved":false,"context_lines":[{"line_number":192,"context_line":"                                    \u0027Schema\u0027: {\u0027Type\u0027: \u0027Map\u0027,"},{"line_number":193,"context_line":"                                               \u0027Schema\u0027: routes_schema},"},{"line_number":194,"context_line":"                                    \u0027Required\u0027: True}}"},{"line_number":195,"context_line":""},{"line_number":196,"context_line":"    def handle_create(self):"},{"line_number":197,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":198,"context_line":"        routes \u003d self.properties.get(\u0027routes\u0027)"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAATn%2F%2BKc8%3D","line":195,"in_reply_to":"AAAATn%2F%2BM8w%3D","updated":"2013-11-30 08:57:29.000000000","message":"Done","commit_id":"0e1c9a0d76a7b1ae5816ed398b7108fbd2b1d897"},{"author":{"_account_id":8844,"name":"Mitsuru Kanabuchi","email":"kanabuchi.mitsuru@po.ntts.co.jp","username":"kanabuchi"},"change_message_id":"a026d410d8f2cb0fc8e580e5852c9b3baa699999","unresolved":false,"context_lines":[{"line_number":202,"context_line":""},{"line_number":203,"context_line":"    def handle_update(self, json_snippet, tmpl_diff, prop_diff):"},{"line_number":204,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":205,"context_line":"        routes \u003d self.prepare_update_properties(json_snippet)"},{"line_number":206,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":207,"context_line":"                                     {\u0027routes\u0027: routes}})"},{"line_number":208,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAATn%2F%2BM7g%3D","line":205,"updated":"2013-11-29 08:59:00.000000000","message":"The routes can\u0027t get from prepare_update_properties directly.","commit_id":"0e1c9a0d76a7b1ae5816ed398b7108fbd2b1d897"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"1bf27f47e06ff1d1b86dbc42a587cf37fc780a6c","unresolved":false,"context_lines":[{"line_number":202,"context_line":""},{"line_number":203,"context_line":"    def handle_update(self, json_snippet, tmpl_diff, prop_diff):"},{"line_number":204,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":205,"context_line":"        routes \u003d self.prepare_update_properties(json_snippet)"},{"line_number":206,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":207,"context_line":"                                     {\u0027routes\u0027: routes}})"},{"line_number":208,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAATn%2F%2BKc4%3D","line":205,"in_reply_to":"AAAATn%2F%2BM7g%3D","updated":"2013-11-30 08:57:29.000000000","message":"Done","commit_id":"0e1c9a0d76a7b1ae5816ed398b7108fbd2b1d897"},{"author":{"_account_id":4571,"name":"Steve Baker","email":"sbaker@redhat.com","username":"steve-stevebaker"},"change_message_id":"42f34144ec86b675c4c99eb4bcc6a39983cd4677","unresolved":false,"context_lines":[{"line_number":181,"context_line":"                raise ex"},{"line_number":182,"context_line":""},{"line_number":183,"context_line":""},{"line_number":184,"context_line":"class RouterRoutes(neutron.NeutronResource):"},{"line_number":185,"context_line":"    routes_schema \u003d {\u0027destination\u0027: {\u0027Type\u0027: \u0027String\u0027,"},{"line_number":186,"context_line":"                                     \u0027Required\u0027: True},"},{"line_number":187,"context_line":"                     \u0027nexthop\u0027: {\u0027Type\u0027: \u0027String\u0027,"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAATn%2F%2BKEU%3D","line":184,"updated":"2013-11-30 21:07:19.000000000","message":"The class can just be called Route","commit_id":"6278b66f7c31097920d99cc96977f9837e80f437"},{"author":{"_account_id":4571,"name":"Steve Baker","email":"sbaker@redhat.com","username":"steve-stevebaker"},"change_message_id":"42f34144ec86b675c4c99eb4bcc6a39983cd4677","unresolved":false,"context_lines":[{"line_number":186,"context_line":"                                     \u0027Required\u0027: True},"},{"line_number":187,"context_line":"                     \u0027nexthop\u0027: {\u0027Type\u0027: \u0027String\u0027,"},{"line_number":188,"context_line":"                                 \u0027Required\u0027: True}}"},{"line_number":189,"context_line":"    properties_schema \u003d {\u0027router_id\u0027: {\u0027Type\u0027: \u0027String\u0027,"},{"line_number":190,"context_line":"                                       \u0027Required\u0027: True},"},{"line_number":191,"context_line":"                         \u0027routes\u0027: {\u0027Type\u0027: \u0027List\u0027,"},{"line_number":192,"context_line":"                                    \u0027Schema\u0027: {\u0027Type\u0027: \u0027Map\u0027,"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAATn%2F%2BKEQ%3D","line":189,"updated":"2013-11-30 21:07:19.000000000","message":"This schema can collapse into a flat router_id, destination, nexthop","commit_id":"6278b66f7c31097920d99cc96977f9837e80f437"},{"author":{"_account_id":4571,"name":"Steve Baker","email":"sbaker@redhat.com","username":"steve-stevebaker"},"change_message_id":"42f34144ec86b675c4c99eb4bcc6a39983cd4677","unresolved":false,"context_lines":[{"line_number":198,"context_line":"    def add_dependencies(self, deps):"},{"line_number":199,"context_line":"        super(RouterRoutes, self).add_dependencies(deps)"},{"line_number":200,"context_line":"        for resource in self.stack.itervalues():"},{"line_number":201,"context_line":"            # depend on any RouterInterface in this template with the same"},{"line_number":202,"context_line":"            # router_id as this router_id"},{"line_number":203,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::RouterInterface\u0027) and"},{"line_number":204,"context_line":"                resource.properties.get(\u0027router_id\u0027) \u003d\u003d"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAATn%2F%2BKEM%3D","line":201,"updated":"2013-11-30 21:07:19.000000000","message":"Can you describe why these are needed?","commit_id":"6278b66f7c31097920d99cc96977f9837e80f437"},{"author":{"_account_id":8844,"name":"Mitsuru Kanabuchi","email":"kanabuchi.mitsuru@po.ntts.co.jp","username":"kanabuchi"},"change_message_id":"de8e2240f20a753f5298e09ff6a9a8fc6c778cfd","unresolved":false,"context_lines":[{"line_number":198,"context_line":"    def add_dependencies(self, deps):"},{"line_number":199,"context_line":"        super(RouterRoutes, self).add_dependencies(deps)"},{"line_number":200,"context_line":"        for resource in self.stack.itervalues():"},{"line_number":201,"context_line":"            # depend on any RouterInterface in this template with the same"},{"line_number":202,"context_line":"            # router_id as this router_id"},{"line_number":203,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::RouterInterface\u0027) and"},{"line_number":204,"context_line":"                resource.properties.get(\u0027router_id\u0027) \u003d\u003d"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAATn%2F%2BHkU%3D","line":201,"in_reply_to":"AAAATn%2F%2BKDQ%3D","updated":"2013-12-02 12:14:07.000000000","message":"Yes, I suggested add_dependencies implementation.\nCould you check PatchSet3\u0027s comment?","commit_id":"6278b66f7c31097920d99cc96977f9837e80f437"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"db4f928ea0f052d5ff7c1806338d3461ddb0dda4","unresolved":false,"context_lines":[{"line_number":198,"context_line":"    def add_dependencies(self, deps):"},{"line_number":199,"context_line":"        super(RouterRoutes, self).add_dependencies(deps)"},{"line_number":200,"context_line":"        for resource in self.stack.itervalues():"},{"line_number":201,"context_line":"            # depend on any RouterInterface in this template with the same"},{"line_number":202,"context_line":"            # router_id as this router_id"},{"line_number":203,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::RouterInterface\u0027) and"},{"line_number":204,"context_line":"                resource.properties.get(\u0027router_id\u0027) \u003d\u003d"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAATn%2F%2BKDQ%3D","line":201,"in_reply_to":"AAAATn%2F%2BKEM%3D","updated":"2013-11-30 21:19:10.000000000","message":"Mitsuru pointed out that the reference plugin in neutron will raise an exception if the nexthop address is on a network that can\u0027t be reached by the router.","commit_id":"6278b66f7c31097920d99cc96977f9837e80f437"},{"author":{"_account_id":4571,"name":"Steve Baker","email":"sbaker@redhat.com","username":"steve-stevebaker"},"change_message_id":"42f34144ec86b675c4c99eb4bcc6a39983cd4677","unresolved":false,"context_lines":[{"line_number":212,"context_line":"                        deps +\u003d (self, resource)"},{"line_number":213,"context_line":""},{"line_number":214,"context_line":"    def handle_create(self):"},{"line_number":215,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":216,"context_line":"        routes \u003d self.properties.get(\u0027routes\u0027)"},{"line_number":217,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":218,"context_line":"                                     {\u0027routes\u0027: routes}})"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAATn%2F%2BKEE%3D","line":215,"updated":"2013-11-30 21:07:19.000000000","message":"This should do the following:\n* fetch the router\n* look for an existing identical route, raise an error if it exists\n* append this route to the existing routes\n* do an update_router with the new routes list","commit_id":"6278b66f7c31097920d99cc96977f9837e80f437"},{"author":{"_account_id":4571,"name":"Steve Baker","email":"sbaker@redhat.com","username":"steve-stevebaker"},"change_message_id":"42f34144ec86b675c4c99eb4bcc6a39983cd4677","unresolved":false,"context_lines":[{"line_number":219,"context_line":"        self.resource_id_set(\u0027%s:%s\u0027 % (router_id, routes))"},{"line_number":220,"context_line":""},{"line_number":221,"context_line":"    def handle_update(self, json_snippet, tmpl_diff, prop_diff):"},{"line_number":222,"context_line":"        router_id \u003d self.resource_id.split(\u0027:\u0027)[0]"},{"line_number":223,"context_line":"        routes \u003d self.prepare_update_properties(json_snippet).get(\u0027routes\u0027)"},{"line_number":224,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":225,"context_line":"                                     {\u0027routes\u0027: routes}})"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAATn%2F%2BKD8%3D","line":222,"updated":"2013-11-30 21:07:19.000000000","message":"This should do the following:\n* fetch the router\n* look for the original route, and delete it if it exists\n* look for an existing identical new route, raise an error if it exists\n* append this route to the existing routes\n* do an update_router with the new routes list","commit_id":"6278b66f7c31097920d99cc96977f9837e80f437"},{"author":{"_account_id":4571,"name":"Steve Baker","email":"sbaker@redhat.com","username":"steve-stevebaker"},"change_message_id":"42f34144ec86b675c4c99eb4bcc6a39983cd4677","unresolved":false,"context_lines":[{"line_number":224,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":225,"context_line":"                                     {\u0027routes\u0027: routes}})"},{"line_number":226,"context_line":""},{"line_number":227,"context_line":"    def handle_delete(self):"},{"line_number":228,"context_line":"        if not self.resource_id:"},{"line_number":229,"context_line":"            return"},{"line_number":230,"context_line":"        router_id \u003d self.resource_id.split(\u0027:\u0027)[0]"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAATn%2F%2BKD4%3D","line":227,"updated":"2013-11-30 21:07:19.000000000","message":"This should do the following:\n* fetch the router\n* look for the existing route, and delete it if it exists (ignore if the route is already gone)","commit_id":"6278b66f7c31097920d99cc96977f9837e80f437"},{"author":{"_account_id":4571,"name":"Steve Baker","email":"sbaker@redhat.com","username":"steve-stevebaker"},"change_message_id":"42f34144ec86b675c4c99eb4bcc6a39983cd4677","unresolved":false,"context_lines":[{"line_number":244,"context_line":"        \u0027OS::Neutron::Router\u0027: Router,"},{"line_number":245,"context_line":"        \u0027OS::Neutron::RouterInterface\u0027: RouterInterface,"},{"line_number":246,"context_line":"        \u0027OS::Neutron::RouterGateway\u0027: RouterGateway,"},{"line_number":247,"context_line":"        \u0027OS::Neutron::RouterRoutes\u0027: RouterRoutes,"},{"line_number":248,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAATn%2F%2BKD0%3D","line":247,"updated":"2013-11-30 21:07:19.000000000","message":"Resource could be called OS::Neutron::Route","commit_id":"6278b66f7c31097920d99cc96977f9837e80f437"},{"author":{"_account_id":4571,"name":"Steve Baker","email":"sbaker@redhat.com","username":"steve-stevebaker"},"change_message_id":"eaa5cda1b0ee0815f76d5bf10eeb422ff8add9fa","unresolved":false,"context_lines":[{"line_number":221,"context_line":""},{"line_number":222,"context_line":"    def validate(self):"},{"line_number":223,"context_line":"        super(Route, self).validate()"},{"line_number":224,"context_line":"        for resource in self.stack.itervalues():"},{"line_number":225,"context_line":"            # verify no duplicate routes exist"},{"line_number":226,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::Route\u0027) and"},{"line_number":227,"context_line":"                resource.name !\u003d self.name and"}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAATn%2F9yqM%3D","line":224,"updated":"2013-12-05 21:18:52.000000000","message":"The self.stack.itervalues() in add_dependencies is a special case, it should be avoided if at all possible when there is an alternative to do an API call.\n\nThis should do a show_router and validate on the returned routes.","commit_id":"4374a8de330c711f9fb8fdf6d4ed1896ae4fd498"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"cc9f0d6a7c98c0eec8866b35b0fa64d82a0808e8","unresolved":false,"context_lines":[{"line_number":221,"context_line":""},{"line_number":222,"context_line":"    def validate(self):"},{"line_number":223,"context_line":"        super(Route, self).validate()"},{"line_number":224,"context_line":"        for resource in self.stack.itervalues():"},{"line_number":225,"context_line":"            # verify no duplicate routes exist"},{"line_number":226,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::Route\u0027) and"},{"line_number":227,"context_line":"                resource.name !\u003d self.name and"}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAATn%2F9yow%3D","line":224,"in_reply_to":"AAAATn%2F9yqM%3D","updated":"2013-12-05 21:28:33.000000000","message":"I think it makes more sense to just remove all of this code since checking for duplicates will be handled in create.","commit_id":"4374a8de330c711f9fb8fdf6d4ed1896ae4fd498"},{"author":{"_account_id":4571,"name":"Steve Baker","email":"sbaker@redhat.com","username":"steve-stevebaker"},"change_message_id":"eaa5cda1b0ee0815f76d5bf10eeb422ff8add9fa","unresolved":false,"context_lines":[{"line_number":242,"context_line":"            routes \u003d []"},{"line_number":243,"context_line":"        new_route \u003d {\u0027destination\u0027: self.properties.get(\u0027destination\u0027),"},{"line_number":244,"context_line":"                     \u0027nexthop\u0027: self.properties.get(\u0027nexthop\u0027)}"},{"line_number":245,"context_line":"        routes.append(new_route)"},{"line_number":246,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":247,"context_line":"                                     {\u0027routes\u0027: routes}})"},{"line_number":248,"context_line":"        self.resource_id_set(\u0027%s:%s:%s\u0027 % (router_id,"}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAATn%2F9yqU%3D","line":245,"updated":"2013-12-05 21:18:52.000000000","message":"Another check should be made here that the new_route doesn\u0027t already exist in routes, and raise a failure if it does. The duplicate route may have been created between validate and handle_create.","commit_id":"4374a8de330c711f9fb8fdf6d4ed1896ae4fd498"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"cc9f0d6a7c98c0eec8866b35b0fa64d82a0808e8","unresolved":false,"context_lines":[{"line_number":242,"context_line":"            routes \u003d []"},{"line_number":243,"context_line":"        new_route \u003d {\u0027destination\u0027: self.properties.get(\u0027destination\u0027),"},{"line_number":244,"context_line":"                     \u0027nexthop\u0027: self.properties.get(\u0027nexthop\u0027)}"},{"line_number":245,"context_line":"        routes.append(new_route)"},{"line_number":246,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":247,"context_line":"                                     {\u0027routes\u0027: routes}})"},{"line_number":248,"context_line":"        self.resource_id_set(\u0027%s:%s:%s\u0027 % (router_id,"}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAATn%2F9yoo%3D","line":245,"in_reply_to":"AAAATn%2F9yqU%3D","updated":"2013-12-05 21:28:33.000000000","message":"Done","commit_id":"4374a8de330c711f9fb8fdf6d4ed1896ae4fd498"},{"author":{"_account_id":6917,"name":"Bartosz Górski","email":"bartosz@codilime.com","username":"bartosz-gorski"},"change_message_id":"f9e6a3b398e4ddf0d961aefbe83a5738679d3307","unresolved":false,"context_lines":[{"line_number":195,"context_line":"            # depend on other routes to prevent a race condition from"},{"line_number":196,"context_line":"            # multiple routes updating the same router at the same time"},{"line_number":197,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::Route\u0027) and"},{"line_number":198,"context_line":"                resource.properties.get(\u0027router_id\u0027) \u003d\u003d"},{"line_number":199,"context_line":"                    self.properties.get(\u0027router_id\u0027)):"},{"line_number":200,"context_line":"                    # depend on routes with greater addresses to order"},{"line_number":201,"context_line":"                    # route installation"}],"source_content_type":"text/x-python","patch_set":8,"id":"AAAATn%2F9tjU%3D","line":198,"updated":"2013-12-06 20:48:06.000000000","message":"router_id is required property so it can not be None. You do not need to use get method. You can just look it up directly resource.properties.[\u0027router_id\u0027]\n\nThe same thing for nexthop and destination.","commit_id":"119266c16388fb679076a8d1d753b6708f03bf49"},{"author":{"_account_id":6456,"name":"Sahdev Zala","email":"spzala@us.ibm.com","username":"spzala"},"change_message_id":"632e1ed67939b89f02adaafeda9178c9e8340be5","unresolved":false,"context_lines":[{"line_number":187,"context_line":"                         \u0027destination\u0027: {\u0027Type\u0027: \u0027String\u0027,"},{"line_number":188,"context_line":"                                         \u0027Required\u0027: True},"},{"line_number":189,"context_line":"                         \u0027nexthop\u0027: {\u0027Type\u0027: \u0027String\u0027,"},{"line_number":190,"context_line":"                                     \u0027Required\u0027: True}}"},{"line_number":191,"context_line":""},{"line_number":192,"context_line":"    def add_dependencies(self, deps):"},{"line_number":193,"context_line":"        super(Route, self).add_dependencies(deps)"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAATn%2F9rrU%3D","line":190,"updated":"2013-12-08 00:10:01.000000000","message":"The schema is missing \u0027Description\u0027.","commit_id":"b3ffa79fe900c3f51857b7949a1c1e8ef9219583"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"9b478d2f562d26df94cf05357cc13a8c6f3874f5","unresolved":false,"context_lines":[{"line_number":187,"context_line":"                         \u0027destination\u0027: {\u0027Type\u0027: \u0027String\u0027,"},{"line_number":188,"context_line":"                                         \u0027Required\u0027: True},"},{"line_number":189,"context_line":"                         \u0027nexthop\u0027: {\u0027Type\u0027: \u0027String\u0027,"},{"line_number":190,"context_line":"                                     \u0027Required\u0027: True}}"},{"line_number":191,"context_line":""},{"line_number":192,"context_line":"    def add_dependencies(self, deps):"},{"line_number":193,"context_line":"        super(Route, self).add_dependencies(deps)"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAATn%2F9rAo%3D","line":190,"in_reply_to":"AAAATn%2F9rrU%3D","updated":"2013-12-08 21:35:42.000000000","message":"Done","commit_id":"b3ffa79fe900c3f51857b7949a1c1e8ef9219583"},{"author":{"_account_id":6456,"name":"Sahdev Zala","email":"spzala@us.ibm.com","username":"spzala"},"change_message_id":"43fd4bfb0b9964f75ff3444e4a522e686d73bfc4","unresolved":false,"context_lines":[{"line_number":190,"context_line":"        \u0027destination\u0027: {"},{"line_number":191,"context_line":"            \u0027Type\u0027: \u0027String\u0027,"},{"line_number":192,"context_line":"            \u0027Required\u0027: True,"},{"line_number":193,"context_line":"            \u0027Description\u0027: _(\u0027Network in CIDR notation\u0027)},"},{"line_number":194,"context_line":"        \u0027nexthop\u0027: {"},{"line_number":195,"context_line":"            \u0027Type\u0027: \u0027String\u0027,"},{"line_number":196,"context_line":"            \u0027Required\u0027: True,"}],"source_content_type":"text/x-python","patch_set":10,"id":"AAAATn%2F9q20%3D","line":193,"updated":"2013-12-09 00:14:44.000000000","message":"Kevin, thanks for addressing my previous comment and adding description. I noticed a minor inconsistency in the way you are ending sentence. i.e. missing ending full-stop here.","commit_id":"388423cc0cbf228e75c87175a8fe718758e4c95e"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"de832e2b3666c1e73bf2de804f151a1a3510f13d","unresolved":false,"context_lines":[{"line_number":190,"context_line":"        \u0027destination\u0027: {"},{"line_number":191,"context_line":"            \u0027Type\u0027: \u0027String\u0027,"},{"line_number":192,"context_line":"            \u0027Required\u0027: True,"},{"line_number":193,"context_line":"            \u0027Description\u0027: _(\u0027Network in CIDR notation\u0027)},"},{"line_number":194,"context_line":"        \u0027nexthop\u0027: {"},{"line_number":195,"context_line":"            \u0027Type\u0027: \u0027String\u0027,"},{"line_number":196,"context_line":"            \u0027Required\u0027: True,"}],"source_content_type":"text/x-python","patch_set":10,"id":"AAAATn%2F9qs8%3D","line":193,"in_reply_to":"AAAATn%2F9q20%3D","updated":"2013-12-09 01:54:35.000000000","message":"Done","commit_id":"388423cc0cbf228e75c87175a8fe718758e4c95e"},{"author":{"_account_id":6456,"name":"Sahdev Zala","email":"spzala@us.ibm.com","username":"spzala"},"change_message_id":"43fd4bfb0b9964f75ff3444e4a522e686d73bfc4","unresolved":false,"context_lines":[{"line_number":191,"context_line":"            \u0027Type\u0027: \u0027String\u0027,"},{"line_number":192,"context_line":"            \u0027Required\u0027: True,"},{"line_number":193,"context_line":"            \u0027Description\u0027: _(\u0027Network in CIDR notation\u0027)},"},{"line_number":194,"context_line":"        \u0027nexthop\u0027: {"},{"line_number":195,"context_line":"            \u0027Type\u0027: \u0027String\u0027,"},{"line_number":196,"context_line":"            \u0027Required\u0027: True,"},{"line_number":197,"context_line":"            \u0027Description\u0027: _(\u0027Nexthop IP adddress.\u0027)}}"}],"source_content_type":"text/x-python","patch_set":10,"id":"AAAATn%2F9q2o%3D","line":194,"updated":"2013-12-09 00:14:44.000000000","message":"Seeing the description, just a thought, I think it\u0027s a good idea to rename this to nexthop_ip for better readability? Thanks!","commit_id":"388423cc0cbf228e75c87175a8fe718758e4c95e"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"de832e2b3666c1e73bf2de804f151a1a3510f13d","unresolved":false,"context_lines":[{"line_number":191,"context_line":"            \u0027Type\u0027: \u0027String\u0027,"},{"line_number":192,"context_line":"            \u0027Required\u0027: True,"},{"line_number":193,"context_line":"            \u0027Description\u0027: _(\u0027Network in CIDR notation\u0027)},"},{"line_number":194,"context_line":"        \u0027nexthop\u0027: {"},{"line_number":195,"context_line":"            \u0027Type\u0027: \u0027String\u0027,"},{"line_number":196,"context_line":"            \u0027Required\u0027: True,"},{"line_number":197,"context_line":"            \u0027Description\u0027: _(\u0027Nexthop IP adddress.\u0027)}}"}],"source_content_type":"text/x-python","patch_set":10,"id":"AAAATn%2F9qs4%3D","line":194,"in_reply_to":"AAAATn%2F9q2o%3D","updated":"2013-12-09 01:54:35.000000000","message":"I would prefer not to rename it because then it will become inconsistent with the name used by neutron.","commit_id":"388423cc0cbf228e75c87175a8fe718758e4c95e"},{"author":{"_account_id":8415,"name":"Denis M.","email":"lildee1991@gmail.com","username":"dmakogon"},"change_message_id":"49b3bdb6c56b2ce8ecc81ca8bb64d356e1aa78ac","unresolved":false,"context_lines":[{"line_number":232,"context_line":""},{"line_number":233,"context_line":"    def handle_create(self):"},{"line_number":234,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":235,"context_line":"        routes \u003d self.neutron().show_router(router_id)\\"},{"line_number":236,"context_line":"            .get(\u0027router\u0027).get(\u0027routes\u0027)"},{"line_number":237,"context_line":"        if not routes:"},{"line_number":238,"context_line":"            routes \u003d []"}],"source_content_type":"text/x-python","patch_set":11,"id":"AAAATn%2F9piQ%3D","line":235,"updated":"2013-12-09 10:14:28.000000000","message":"it would be better avoid using \" \\ \", please use () instead","commit_id":"3808095b3000faade6ef5a140c33104bff6ec5ac"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"420099998ab2f7cfbf7ab54a6726956012f7e992","unresolved":false,"context_lines":[{"line_number":232,"context_line":""},{"line_number":233,"context_line":"    def handle_create(self):"},{"line_number":234,"context_line":"        router_id \u003d self.properties.get(\u0027router_id\u0027)"},{"line_number":235,"context_line":"        routes \u003d self.neutron().show_router(router_id)\\"},{"line_number":236,"context_line":"            .get(\u0027router\u0027).get(\u0027routes\u0027)"},{"line_number":237,"context_line":"        if not routes:"},{"line_number":238,"context_line":"            routes \u003d []"}],"source_content_type":"text/x-python","patch_set":11,"id":"AAAATn%2F9mYk%3D","line":235,"in_reply_to":"AAAATn%2F9piQ%3D","updated":"2013-12-09 19:54:14.000000000","message":"Done","commit_id":"3808095b3000faade6ef5a140c33104bff6ec5ac"},{"author":{"_account_id":8415,"name":"Denis M.","email":"lildee1991@gmail.com","username":"dmakogon"},"change_message_id":"49b3bdb6c56b2ce8ecc81ca8bb64d356e1aa78ac","unresolved":false,"context_lines":[{"line_number":236,"context_line":"            .get(\u0027router\u0027).get(\u0027routes\u0027)"},{"line_number":237,"context_line":"        if not routes:"},{"line_number":238,"context_line":"            routes \u003d []"},{"line_number":239,"context_line":"        new_route \u003d {\u0027destination\u0027: self.properties.get(\u0027destination\u0027),"},{"line_number":240,"context_line":"                     \u0027nexthop\u0027: self.properties.get(\u0027nexthop\u0027)}"},{"line_number":241,"context_line":"        if new_route in routes:"},{"line_number":242,"context_line":"            msg \u003d \u0027Route duplicates an existing route\u0027"}],"source_content_type":"text/x-python","patch_set":11,"id":"AAAATn%2F9phQ%3D","line":239,"updated":"2013-12-09 10:14:28.000000000","message":"if resource mantioned, should route be also mentioned ?\nIf it so, would it better to use [] instead if get() ?","commit_id":"3808095b3000faade6ef5a140c33104bff6ec5ac"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"420099998ab2f7cfbf7ab54a6726956012f7e992","unresolved":false,"context_lines":[{"line_number":236,"context_line":"            .get(\u0027router\u0027).get(\u0027routes\u0027)"},{"line_number":237,"context_line":"        if not routes:"},{"line_number":238,"context_line":"            routes \u003d []"},{"line_number":239,"context_line":"        new_route \u003d {\u0027destination\u0027: self.properties.get(\u0027destination\u0027),"},{"line_number":240,"context_line":"                     \u0027nexthop\u0027: self.properties.get(\u0027nexthop\u0027)}"},{"line_number":241,"context_line":"        if new_route in routes:"},{"line_number":242,"context_line":"            msg \u003d \u0027Route duplicates an existing route\u0027"}],"source_content_type":"text/x-python","patch_set":11,"id":"AAAATn%2F9mWM%3D","line":239,"in_reply_to":"AAAATn%2F9phQ%3D","updated":"2013-12-09 19:54:14.000000000","message":"Done","commit_id":"3808095b3000faade6ef5a140c33104bff6ec5ac"},{"author":{"_account_id":8415,"name":"Denis M.","email":"lildee1991@gmail.com","username":"dmakogon"},"change_message_id":"49b3bdb6c56b2ce8ecc81ca8bb64d356e1aa78ac","unresolved":false,"context_lines":[{"line_number":239,"context_line":"        new_route \u003d {\u0027destination\u0027: self.properties.get(\u0027destination\u0027),"},{"line_number":240,"context_line":"                     \u0027nexthop\u0027: self.properties.get(\u0027nexthop\u0027)}"},{"line_number":241,"context_line":"        if new_route in routes:"},{"line_number":242,"context_line":"            msg \u003d \u0027Route duplicates an existing route\u0027"},{"line_number":243,"context_line":"            raise exception.Error(msg)"},{"line_number":244,"context_line":"        routes.append(new_route)"},{"line_number":245,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"}],"source_content_type":"text/x-python","patch_set":11,"id":"AAAATn%2F9ph0%3D","line":242,"updated":"2013-12-09 10:14:28.000000000","message":"please add . in the end of sentence.","commit_id":"3808095b3000faade6ef5a140c33104bff6ec5ac"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"420099998ab2f7cfbf7ab54a6726956012f7e992","unresolved":false,"context_lines":[{"line_number":239,"context_line":"        new_route \u003d {\u0027destination\u0027: self.properties.get(\u0027destination\u0027),"},{"line_number":240,"context_line":"                     \u0027nexthop\u0027: self.properties.get(\u0027nexthop\u0027)}"},{"line_number":241,"context_line":"        if new_route in routes:"},{"line_number":242,"context_line":"            msg \u003d \u0027Route duplicates an existing route\u0027"},{"line_number":243,"context_line":"            raise exception.Error(msg)"},{"line_number":244,"context_line":"        routes.append(new_route)"},{"line_number":245,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"}],"source_content_type":"text/x-python","patch_set":11,"id":"AAAATn%2F9mYM%3D","line":242,"in_reply_to":"AAAATn%2F9ph0%3D","updated":"2013-12-09 19:54:14.000000000","message":"Done","commit_id":"3808095b3000faade6ef5a140c33104bff6ec5ac"},{"author":{"_account_id":8415,"name":"Denis M.","email":"lildee1991@gmail.com","username":"dmakogon"},"change_message_id":"49b3bdb6c56b2ce8ecc81ca8bb64d356e1aa78ac","unresolved":false,"context_lines":[{"line_number":244,"context_line":"        routes.append(new_route)"},{"line_number":245,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":246,"context_line":"                                     {\u0027routes\u0027: routes}})"},{"line_number":247,"context_line":"        self.resource_id_set(\u0027%s:%s:%s\u0027 % (router_id,"},{"line_number":248,"context_line":"                                           new_route[\u0027destination\u0027],"},{"line_number":249,"context_line":"                                           new_route[\u0027nexthop\u0027]))"},{"line_number":250,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"AAAATn%2F9pgk%3D","line":247,"updated":"2013-12-09 10:14:28.000000000","message":"it would be better avoid using such string formatting,\nplease use \u0027%(Key)s\u0027 % {\u0027Key\u0027: \u0027value} formatting","commit_id":"3808095b3000faade6ef5a140c33104bff6ec5ac"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"420099998ab2f7cfbf7ab54a6726956012f7e992","unresolved":false,"context_lines":[{"line_number":244,"context_line":"        routes.append(new_route)"},{"line_number":245,"context_line":"        self.neutron().update_router(router_id, {\u0027router\u0027:"},{"line_number":246,"context_line":"                                     {\u0027routes\u0027: routes}})"},{"line_number":247,"context_line":"        self.resource_id_set(\u0027%s:%s:%s\u0027 % (router_id,"},{"line_number":248,"context_line":"                                           new_route[\u0027destination\u0027],"},{"line_number":249,"context_line":"                                           new_route[\u0027nexthop\u0027]))"},{"line_number":250,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"AAAATn%2F9mWY%3D","line":247,"in_reply_to":"AAAATn%2F9pgk%3D","updated":"2013-12-09 19:54:14.000000000","message":"Done","commit_id":"3808095b3000faade6ef5a140c33104bff6ec5ac"},{"author":{"_account_id":8415,"name":"Denis M.","email":"lildee1991@gmail.com","username":"dmakogon"},"change_message_id":"49b3bdb6c56b2ce8ecc81ca8bb64d356e1aa78ac","unresolved":false,"context_lines":[{"line_number":253,"context_line":"            return"},{"line_number":254,"context_line":"        (router_id, destination, nexthop) \u003d self.resource_id.split(\u0027:\u0027)"},{"line_number":255,"context_line":"        try:"},{"line_number":256,"context_line":"            routes \u003d self.neutron().show_router(router_id)\\"},{"line_number":257,"context_line":"                .get(\u0027router\u0027).get(\u0027routes\u0027)"},{"line_number":258,"context_line":"            if not routes:"},{"line_number":259,"context_line":"                routes \u003d []"}],"source_content_type":"text/x-python","patch_set":11,"id":"AAAATn%2F9pgg%3D","line":256,"updated":"2013-12-09 10:14:28.000000000","message":"Please avoid using \\","commit_id":"3808095b3000faade6ef5a140c33104bff6ec5ac"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"420099998ab2f7cfbf7ab54a6726956012f7e992","unresolved":false,"context_lines":[{"line_number":253,"context_line":"            return"},{"line_number":254,"context_line":"        (router_id, destination, nexthop) \u003d self.resource_id.split(\u0027:\u0027)"},{"line_number":255,"context_line":"        try:"},{"line_number":256,"context_line":"            routes \u003d self.neutron().show_router(router_id)\\"},{"line_number":257,"context_line":"                .get(\u0027router\u0027).get(\u0027routes\u0027)"},{"line_number":258,"context_line":"            if not routes:"},{"line_number":259,"context_line":"                routes \u003d []"}],"source_content_type":"text/x-python","patch_set":11,"id":"AAAATn%2F9mYg%3D","line":256,"in_reply_to":"AAAATn%2F9pgg%3D","updated":"2013-12-09 19:54:14.000000000","message":"Done","commit_id":"3808095b3000faade6ef5a140c33104bff6ec5ac"},{"author":{"_account_id":4571,"name":"Steve Baker","email":"sbaker@redhat.com","username":"steve-stevebaker"},"change_message_id":"d6a87581b79299d366061c068d3bd70ebd7c3850","unresolved":false,"context_lines":[{"line_number":183,"context_line":""},{"line_number":184,"context_line":"class Route(neutron.NeutronResource):"},{"line_number":185,"context_line":"    properties_schema \u003d {"},{"line_number":186,"context_line":"        \u0027router_id\u0027: {"},{"line_number":187,"context_line":"            \u0027Type\u0027: \u0027String\u0027,"},{"line_number":188,"context_line":"            \u0027Required\u0027: True,"},{"line_number":189,"context_line":"            \u0027Description\u0027: _(\u0027The router id.\u0027)},"}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAATn%2F9gcc%3D","line":186,"updated":"2013-12-10 20:25:45.000000000","message":"Since this is a new resource, it really should use a typed Schema. All resources will be converted soon. see random_string.py","commit_id":"d7679d0c9f030b54a50e2e84d4bccd989baa1a63"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"736f63d7a1aca646d4f02124b0c8873473deee69","unresolved":false,"context_lines":[{"line_number":183,"context_line":""},{"line_number":184,"context_line":"class Route(neutron.NeutronResource):"},{"line_number":185,"context_line":"    properties_schema \u003d {"},{"line_number":186,"context_line":"        \u0027router_id\u0027: {"},{"line_number":187,"context_line":"            \u0027Type\u0027: \u0027String\u0027,"},{"line_number":188,"context_line":"            \u0027Required\u0027: True,"},{"line_number":189,"context_line":"            \u0027Description\u0027: _(\u0027The router id.\u0027)},"}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAATn%2F9gUM%3D","line":186,"in_reply_to":"AAAATn%2F9gcc%3D","updated":"2013-12-10 20:52:18.000000000","message":"Done","commit_id":"d7679d0c9f030b54a50e2e84d4bccd989baa1a63"},{"author":{"_account_id":4571,"name":"Steve Baker","email":"sbaker@redhat.com","username":"steve-stevebaker"},"change_message_id":"d6a87581b79299d366061c068d3bd70ebd7c3850","unresolved":false,"context_lines":[{"line_number":207,"context_line":"                    self.properties[\u0027router_id\u0027]):"},{"line_number":208,"context_line":"                    # depend on routes with greater addresses to order"},{"line_number":209,"context_line":"                    # route installation"},{"line_number":210,"context_line":"                    resname \u003d \u0027%s%s\u0027 % (resource.properties[\u0027nexthop\u0027],"},{"line_number":211,"context_line":"                                        resource.properties[\u0027destination\u0027])"},{"line_number":212,"context_line":"                    routes[resname] \u003d resource"},{"line_number":213,"context_line":"            myname \u003d \u0027%s%s\u0027 % (self.properties[\u0027nexthop\u0027],"}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAATn%2F9gcQ%3D","line":210,"updated":"2013-12-10 20:25:45.000000000","message":"without a delimiter here it looks like it would be possible to get unique nexthop/destination combos which join to be non-unique values. Maybe delimit with a :","commit_id":"d7679d0c9f030b54a50e2e84d4bccd989baa1a63"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"736f63d7a1aca646d4f02124b0c8873473deee69","unresolved":false,"context_lines":[{"line_number":207,"context_line":"                    self.properties[\u0027router_id\u0027]):"},{"line_number":208,"context_line":"                    # depend on routes with greater addresses to order"},{"line_number":209,"context_line":"                    # route installation"},{"line_number":210,"context_line":"                    resname \u003d \u0027%s%s\u0027 % (resource.properties[\u0027nexthop\u0027],"},{"line_number":211,"context_line":"                                        resource.properties[\u0027destination\u0027])"},{"line_number":212,"context_line":"                    routes[resname] \u003d resource"},{"line_number":213,"context_line":"            myname \u003d \u0027%s%s\u0027 % (self.properties[\u0027nexthop\u0027],"}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAATn%2F9gUE%3D","line":210,"in_reply_to":"AAAATn%2F9gcQ%3D","updated":"2013-12-10 20:52:18.000000000","message":"Done","commit_id":"d7679d0c9f030b54a50e2e84d4bccd989baa1a63"},{"author":{"_account_id":4571,"name":"Steve Baker","email":"sbaker@redhat.com","username":"steve-stevebaker"},"change_message_id":"d6a87581b79299d366061c068d3bd70ebd7c3850","unresolved":false,"context_lines":[{"line_number":255,"context_line":"        try:"},{"line_number":256,"context_line":"            routes \u003d self.neutron().show_router("},{"line_number":257,"context_line":"                router_id).get(\u0027router\u0027).get(\u0027routes\u0027)"},{"line_number":258,"context_line":"            if not routes:"},{"line_number":259,"context_line":"                routes \u003d []"},{"line_number":260,"context_line":"            try:"},{"line_number":261,"context_line":"                routes.remove({\u0027destination\u0027: destination,"}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAATn%2F9gbg%3D","line":258,"updated":"2013-12-10 20:25:45.000000000","message":"just do .get(\u0027routes\u0027, [])","commit_id":"d7679d0c9f030b54a50e2e84d4bccd989baa1a63"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"736f63d7a1aca646d4f02124b0c8873473deee69","unresolved":false,"context_lines":[{"line_number":255,"context_line":"        try:"},{"line_number":256,"context_line":"            routes \u003d self.neutron().show_router("},{"line_number":257,"context_line":"                router_id).get(\u0027router\u0027).get(\u0027routes\u0027)"},{"line_number":258,"context_line":"            if not routes:"},{"line_number":259,"context_line":"                routes \u003d []"},{"line_number":260,"context_line":"            try:"},{"line_number":261,"context_line":"                routes.remove({\u0027destination\u0027: destination,"}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAATn%2F9gUA%3D","line":258,"in_reply_to":"AAAATn%2F9gbg%3D","updated":"2013-12-10 20:52:18.000000000","message":"Done","commit_id":"d7679d0c9f030b54a50e2e84d4bccd989baa1a63"},{"author":{"_account_id":8641,"name":"DennyZhang","email":"filebat.mark@gmail.com","username":"dennyzhang"},"change_message_id":"833c58db90374a8e17659b8dea6709e597911d79","unresolved":false,"context_lines":[{"line_number":242,"context_line":"                raise ex"},{"line_number":243,"context_line":""},{"line_number":244,"context_line":""},{"line_number":245,"context_line":"class Route(neutron.NeutronResource):"},{"line_number":246,"context_line":"    properties_schema \u003d {"},{"line_number":247,"context_line":"        \u0027router_id\u0027: properties.Schema("},{"line_number":248,"context_line":"            properties.Schema.STRING,"}],"source_content_type":"text/x-python","patch_set":19,"id":"AAAATn%2F8tYs%3D","line":245,"updated":"2013-12-22 04:15:16.000000000","message":"Rename class to Router_route?\n\nWe have already got a class named Router. If we add another class named Route, it would be quite confusing for newcomers.","commit_id":"f77d232fa7dd9e8b4fc01952100a0629167371be"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"ee22d445390184283252003a447f7d7ba32169e7","unresolved":false,"context_lines":[{"line_number":242,"context_line":"                raise ex"},{"line_number":243,"context_line":""},{"line_number":244,"context_line":""},{"line_number":245,"context_line":"class Route(neutron.NeutronResource):"},{"line_number":246,"context_line":"    properties_schema \u003d {"},{"line_number":247,"context_line":"        \u0027router_id\u0027: properties.Schema("},{"line_number":248,"context_line":"            properties.Schema.STRING,"}],"source_content_type":"text/x-python","patch_set":19,"id":"AAAATn%2F8tXI%3D","line":245,"in_reply_to":"AAAATn%2F8tYs%3D","updated":"2013-12-22 05:19:06.000000000","message":"Done","commit_id":"f77d232fa7dd9e8b4fc01952100a0629167371be"},{"author":{"_account_id":4257,"name":"Zane Bitter","email":"zbitter@redhat.com","username":"zaneb"},"change_message_id":"2364d4bf1eb7acd86676c09f2b0de1bb47e33b79","unresolved":false,"context_lines":[{"line_number":262,"context_line":"        super(Route, self).add_dependencies(deps)"},{"line_number":263,"context_line":"        for resource in self.stack.itervalues():"},{"line_number":264,"context_line":"            # order routes to prevent a race condition from"},{"line_number":265,"context_line":"            # multiple routes updating the same router at the same time"},{"line_number":266,"context_line":"            routes \u003d {}"},{"line_number":267,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::Route\u0027) and"},{"line_number":268,"context_line":"                resource.properties[\u0027router_id\u0027] \u003d\u003d"}],"source_content_type":"text/x-python","patch_set":19,"id":"AAAATn%2F9AAc%3D","line":265,"updated":"2013-12-17 21:39:02.000000000","message":"This doesn\u0027t prevent race conditions at all, because dependencies don\u0027t cross stacks. It just covers up the race conditions when doing simple testing, and defers all of the errors until the bug reports from complex user deployments.","commit_id":"f77d232fa7dd9e8b4fc01952100a0629167371be"},{"author":{"_account_id":4257,"name":"Zane Bitter","email":"zbitter@redhat.com","username":"zaneb"},"change_message_id":"2364d4bf1eb7acd86676c09f2b0de1bb47e33b79","unresolved":false,"context_lines":[{"line_number":280,"context_line":"                    deps +\u003d (self, routes[resname])"},{"line_number":281,"context_line":"                    break"},{"line_number":282,"context_line":"            # depend on any RouterInterface in this template with the same"},{"line_number":283,"context_line":"            # router_id as this router_id"},{"line_number":284,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::RouterInterface\u0027) and"},{"line_number":285,"context_line":"                resource.properties[\u0027router_id\u0027] \u003d\u003d"},{"line_number":286,"context_line":"                    self.properties[\u0027router_id\u0027]):"}],"source_content_type":"text/x-python","patch_set":19,"id":"AAAATn%2F8%2F%2Fg%3D","line":283,"updated":"2013-12-17 21:39:02.000000000","message":"Huh? Do routes really need to be added to the router only after ports? Why?","commit_id":"f77d232fa7dd9e8b4fc01952100a0629167371be"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"80f47ff0c8c4e65810ae6716c90e633444f999ac","unresolved":false,"context_lines":[{"line_number":280,"context_line":"                    deps +\u003d (self, routes[resname])"},{"line_number":281,"context_line":"                    break"},{"line_number":282,"context_line":"            # depend on any RouterInterface in this template with the same"},{"line_number":283,"context_line":"            # router_id as this router_id"},{"line_number":284,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::RouterInterface\u0027) and"},{"line_number":285,"context_line":"                resource.properties[\u0027router_id\u0027] \u003d\u003d"},{"line_number":286,"context_line":"                    self.properties[\u0027router_id\u0027]):"}],"source_content_type":"text/x-python","patch_set":19,"id":"AAAATn%2F8%2F2Y%3D","line":283,"in_reply_to":"AAAATn%2F8%2F%2Fg%3D","updated":"2013-12-17 22:30:51.000000000","message":"Yes, if the nexthop address is not reachable by the router, neutron will raise an exception.","commit_id":"f77d232fa7dd9e8b4fc01952100a0629167371be"},{"author":{"_account_id":4257,"name":"Zane Bitter","email":"zbitter@redhat.com","username":"zaneb"},"change_message_id":"12a299deaeb4f5f89e8ba09b7bc3d59f69542d76","unresolved":false,"context_lines":[{"line_number":280,"context_line":"                    deps +\u003d (self, routes[resname])"},{"line_number":281,"context_line":"                    break"},{"line_number":282,"context_line":"            # depend on any RouterInterface in this template with the same"},{"line_number":283,"context_line":"            # router_id as this router_id"},{"line_number":284,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::RouterInterface\u0027) and"},{"line_number":285,"context_line":"                resource.properties[\u0027router_id\u0027] \u003d\u003d"},{"line_number":286,"context_line":"                    self.properties[\u0027router_id\u0027]):"}],"source_content_type":"text/x-python","patch_set":19,"id":"AAAATn%2F8%2FiM%3D","line":283,"in_reply_to":"AAAATn%2F8%2F2Y%3D","updated":"2013-12-17 23:13:46.000000000","message":"Then nexthop should be a reference to an interface, rather than an IP address, so that the dependencies are explicit in the template.","commit_id":"f77d232fa7dd9e8b4fc01952100a0629167371be"},{"author":{"_account_id":4257,"name":"Zane Bitter","email":"zbitter@redhat.com","username":"zaneb"},"change_message_id":"938ee5f9acf235d662c58b4faddef66f05d606a7","unresolved":false,"context_lines":[{"line_number":280,"context_line":"                    deps +\u003d (self, routes[resname])"},{"line_number":281,"context_line":"                    break"},{"line_number":282,"context_line":"            # depend on any RouterInterface in this template with the same"},{"line_number":283,"context_line":"            # router_id as this router_id"},{"line_number":284,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::RouterInterface\u0027) and"},{"line_number":285,"context_line":"                resource.properties[\u0027router_id\u0027] \u003d\u003d"},{"line_number":286,"context_line":"                    self.properties[\u0027router_id\u0027]):"}],"source_content_type":"text/x-python","patch_set":19,"id":"AAAATn%2F8%2FQw%3D","line":283,"in_reply_to":"AAAATn%2F8%2FYY%3D","updated":"2013-12-18 01:39:49.000000000","message":"Good point. In the AWS equivalent, you have to provide either a gateway, an EC2 instance or an interface: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-route.html","commit_id":"f77d232fa7dd9e8b4fc01952100a0629167371be"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"9877a0923a33a4ae135930a625d15dd0e1af9aeb","unresolved":false,"context_lines":[{"line_number":280,"context_line":"                    deps +\u003d (self, routes[resname])"},{"line_number":281,"context_line":"                    break"},{"line_number":282,"context_line":"            # depend on any RouterInterface in this template with the same"},{"line_number":283,"context_line":"            # router_id as this router_id"},{"line_number":284,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::RouterInterface\u0027) and"},{"line_number":285,"context_line":"                resource.properties[\u0027router_id\u0027] \u003d\u003d"},{"line_number":286,"context_line":"                    self.properties[\u0027router_id\u0027]):"}],"source_content_type":"text/x-python","patch_set":19,"id":"AAAATn%2F8%2FYY%3D","line":283,"in_reply_to":"AAAATn%2F8%2FiM%3D","updated":"2013-12-18 00:09:28.000000000","message":"No, the nexthop address can be anything on network the router is attached to (e.g. a neighbor router). Just an interface is ambiguous.","commit_id":"f77d232fa7dd9e8b4fc01952100a0629167371be"},{"author":{"_account_id":4257,"name":"Zane Bitter","email":"zbitter@redhat.com","username":"zaneb"},"change_message_id":"2364d4bf1eb7acd86676c09f2b0de1bb47e33b79","unresolved":false,"context_lines":[{"line_number":286,"context_line":"                    self.properties[\u0027router_id\u0027]):"},{"line_number":287,"context_line":"                        deps +\u003d (self, resource)"},{"line_number":288,"context_line":"            # depend on any RouterGateway in this template with the same"},{"line_number":289,"context_line":"            # router_id as this router_id"},{"line_number":290,"context_line":"            elif (resource.has_interface(\u0027OS::Neutron::RouterGateway\u0027) and"},{"line_number":291,"context_line":"                  resource.properties[\u0027router_id\u0027] \u003d\u003d"},{"line_number":292,"context_line":"                    self.properties[\u0027router_id\u0027]):"}],"source_content_type":"text/x-python","patch_set":19,"id":"AAAATn%2F8%2F%2FE%3D","line":289,"updated":"2013-12-17 21:39:02.000000000","message":"This is necessary for now, though fortunately we are about to deprecate RouterGateway because it shouldn\u0027t exist at all.","commit_id":"f77d232fa7dd9e8b4fc01952100a0629167371be"},{"author":{"_account_id":4257,"name":"Zane Bitter","email":"zbitter@redhat.com","username":"zaneb"},"change_message_id":"53c72ea5f27188e4402efdc4d5b5b358d6b662bd","unresolved":false,"context_lines":[{"line_number":352,"context_line":"            # order routes to prevent a race condition from"},{"line_number":353,"context_line":"            # multiple routes updating the same router at the same time"},{"line_number":354,"context_line":"            routes \u003d {}"},{"line_number":355,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::RouterRoute\u0027) and"},{"line_number":356,"context_line":"                resource.properties[\u0027router_id\u0027] \u003d\u003d"},{"line_number":357,"context_line":"                    self.properties[\u0027router_id\u0027]):"},{"line_number":358,"context_line":"                    # depend on routes with greater addresses to order"}],"source_content_type":"text/x-python","patch_set":21,"id":"AAAAT3%2F%2FqGg%3D","line":355,"updated":"2014-01-04 00:36:16.000000000","message":"As discussed previously, this is pointless because RouterRoute has a single-step creation process (it has not check_create_complete() function). So lines 352-369 should just be removed.","commit_id":"4657d8800cfb97fa79a0cfd3dac17cf5240f5898"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"d2942be473fee0dec05d4d0cc618e010fd0ad323","unresolved":false,"context_lines":[{"line_number":352,"context_line":"            # order routes to prevent a race condition from"},{"line_number":353,"context_line":"            # multiple routes updating the same router at the same time"},{"line_number":354,"context_line":"            routes \u003d {}"},{"line_number":355,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::RouterRoute\u0027) and"},{"line_number":356,"context_line":"                resource.properties[\u0027router_id\u0027] \u003d\u003d"},{"line_number":357,"context_line":"                    self.properties[\u0027router_id\u0027]):"},{"line_number":358,"context_line":"                    # depend on routes with greater addresses to order"}],"source_content_type":"text/x-python","patch_set":21,"id":"AAAAUH%2F%2F%2F9o%3D","line":355,"in_reply_to":"AAAAT3%2F%2FqGg%3D","updated":"2014-01-04 05:55:36.000000000","message":"Wouldn\u0027t the multi-engine support you referenced before create multiple non-dependent resources simultaneously?","commit_id":"4657d8800cfb97fa79a0cfd3dac17cf5240f5898"},{"author":{"_account_id":4257,"name":"Zane Bitter","email":"zbitter@redhat.com","username":"zaneb"},"change_message_id":"4627eafbb9e5893b72d62ed73a2487b2beaea20c","unresolved":false,"context_lines":[{"line_number":352,"context_line":"            # order routes to prevent a race condition from"},{"line_number":353,"context_line":"            # multiple routes updating the same router at the same time"},{"line_number":354,"context_line":"            routes \u003d {}"},{"line_number":355,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::RouterRoute\u0027) and"},{"line_number":356,"context_line":"                resource.properties[\u0027router_id\u0027] \u003d\u003d"},{"line_number":357,"context_line":"                    self.properties[\u0027router_id\u0027]):"},{"line_number":358,"context_line":"                    # depend on routes with greater addresses to order"}],"source_content_type":"text/x-python","patch_set":21,"id":"AAAAUH%2F%2Fllk%3D","line":355,"in_reply_to":"AAAAUH%2F%2F%2F9o%3D","updated":"2014-01-10 19:40:24.000000000","message":"No, each stack is managed by exactly one engine at a time.\n\nThere are multiple ways to break this with or without multi-engine support. You can create another stack in the same tenant containing Routes - that is racy. Or you can update the routes yourself using the Neutron API directly - that is also racy. But adding multiple routes in the same stack is not racy no matter how you dice it, and this is the only case that this code attempts to do something about (to no effect).","commit_id":"4657d8800cfb97fa79a0cfd3dac17cf5240f5898"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"d51ed81a356a6af0701562e4469b8451430a4c17","unresolved":false,"context_lines":[{"line_number":352,"context_line":"            # order routes to prevent a race condition from"},{"line_number":353,"context_line":"            # multiple routes updating the same router at the same time"},{"line_number":354,"context_line":"            routes \u003d {}"},{"line_number":355,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::RouterRoute\u0027) and"},{"line_number":356,"context_line":"                resource.properties[\u0027router_id\u0027] \u003d\u003d"},{"line_number":357,"context_line":"                    self.properties[\u0027router_id\u0027]):"},{"line_number":358,"context_line":"                    # depend on routes with greater addresses to order"}],"source_content_type":"text/x-python","patch_set":21,"id":"AAAAUH%2F%2Fkc8%3D","line":355,"in_reply_to":"AAAAUH%2F%2Fllk%3D","updated":"2014-01-10 22:44:13.000000000","message":"Ok, I will remove this component since multi-engine support doesn\u0027t divide up a single stack\u0027s resources.","commit_id":"4657d8800cfb97fa79a0cfd3dac17cf5240f5898"},{"author":{"_account_id":4257,"name":"Zane Bitter","email":"zbitter@redhat.com","username":"zaneb"},"change_message_id":"53c72ea5f27188e4402efdc4d5b5b358d6b662bd","unresolved":false,"context_lines":[{"line_number":369,"context_line":"                    break"},{"line_number":370,"context_line":"            # depend on any RouterInterface in this template with the same"},{"line_number":371,"context_line":"            # router_id as this router_id"},{"line_number":372,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::RouterInterface\u0027) and"},{"line_number":373,"context_line":"                resource.properties[\u0027router_id\u0027] \u003d\u003d"},{"line_number":374,"context_line":"                    self.properties[\u0027router_id\u0027]):"},{"line_number":375,"context_line":"                        deps +\u003d (self, resource)"}],"source_content_type":"text/x-python","patch_set":21,"id":"AAAAT3%2F%2FqGA%3D","line":372,"updated":"2014-01-04 00:36:16.000000000","message":"When this kind of thing is necessary, it\u0027s purely due to bad resource modelling. In this case, instead of a nexthop IP we should take a reference to either an instance, a port or a gateway. That way the dependencies will make themselves explicit in the template. AWS gets this right: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-route.html","commit_id":"4657d8800cfb97fa79a0cfd3dac17cf5240f5898"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"d2942be473fee0dec05d4d0cc618e010fd0ad323","unresolved":false,"context_lines":[{"line_number":369,"context_line":"                    break"},{"line_number":370,"context_line":"            # depend on any RouterInterface in this template with the same"},{"line_number":371,"context_line":"            # router_id as this router_id"},{"line_number":372,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::RouterInterface\u0027) and"},{"line_number":373,"context_line":"                resource.properties[\u0027router_id\u0027] \u003d\u003d"},{"line_number":374,"context_line":"                    self.properties[\u0027router_id\u0027]):"},{"line_number":375,"context_line":"                        deps +\u003d (self, resource)"}],"source_content_type":"text/x-python","patch_set":21,"id":"AAAAUH%2F%2F%2F9s%3D","line":372,"in_reply_to":"AAAAT3%2F%2FqGA%3D","updated":"2014-01-04 05:55:36.000000000","message":"Restricting to an instance, port, or gateway doesn\u0027t make sense in heat if that\u0027s not the expectation on the neutron side. We would have to implement a bunch of custom code in heat that would translate back to a nexthop IP from a gateway, a port, or an instance; the latter two of which can have many IP addresses, making the translation ambiguous. \n\nThe AWS model works well for them, but it\u0027s too restrictive for use-cases where the next-hop is not managed by OpenStack. For example, this could be a VPN termination box attached to an shared/external network. If there is disagreement that this should be supported by OpenStack, I would suggest that the removal of that flexibility should be advocated for with a patch to the neutron extension code rather than making the implementation inconsistent here.","commit_id":"4657d8800cfb97fa79a0cfd3dac17cf5240f5898"},{"author":{"_account_id":4257,"name":"Zane Bitter","email":"zbitter@redhat.com","username":"zaneb"},"change_message_id":"4627eafbb9e5893b72d62ed73a2487b2beaea20c","unresolved":false,"context_lines":[{"line_number":369,"context_line":"                    break"},{"line_number":370,"context_line":"            # depend on any RouterInterface in this template with the same"},{"line_number":371,"context_line":"            # router_id as this router_id"},{"line_number":372,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::RouterInterface\u0027) and"},{"line_number":373,"context_line":"                resource.properties[\u0027router_id\u0027] \u003d\u003d"},{"line_number":374,"context_line":"                    self.properties[\u0027router_id\u0027]):"},{"line_number":375,"context_line":"                        deps +\u003d (self, resource)"}],"source_content_type":"text/x-python","patch_set":21,"id":"AAAAUH%2F%2FlSc%3D","line":372,"in_reply_to":"AAAAUH%2F%2F%2F9s%3D","updated":"2014-01-10 19:40:24.000000000","message":"The \"Routing Table\" in Neutron is probably mis-named because it is actually more like a FIB than a RIB. It contains only routes that have already been selected, and has no method of selecting a route based on weights, administrative distance, that kind of thing.\n\nThe only thing of importance to the FIB is \"which interface should I route these packets out of, and which MAC address should I address them to?\" If the destination MAC has multiple IP addresses associated, it doesn\u0027t matter because the IP address of the nexthop doesn\u0027t enter into it as far as the router is concerned. I would have thought that e.g. a VPN termination would either be connected to the router with a port or be treated as a type of gateway, but if not then that can be added to the list of IDs we could accept.\n\nThe implementation as it stands breaks Heat\u0027s data model.","commit_id":"4657d8800cfb97fa79a0cfd3dac17cf5240f5898"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"2895ceff840926b77957aa4c157ba0c2ff00b135","unresolved":false,"context_lines":[{"line_number":369,"context_line":"                    break"},{"line_number":370,"context_line":"            # depend on any RouterInterface in this template with the same"},{"line_number":371,"context_line":"            # router_id as this router_id"},{"line_number":372,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::RouterInterface\u0027) and"},{"line_number":373,"context_line":"                resource.properties[\u0027router_id\u0027] \u003d\u003d"},{"line_number":374,"context_line":"                    self.properties[\u0027router_id\u0027]):"},{"line_number":375,"context_line":"                        deps +\u003d (self, resource)"}],"source_content_type":"text/x-python","patch_set":21,"id":"AAAAUH%2F%2FQcI%3D","line":372,"in_reply_to":"AAAAUH%2F%2FkN8%3D","updated":"2014-01-15 20:04:34.000000000","message":"\u003eRight, but at some point the Router is translating it back to an interface and a MAC which is unambiguous. The fact that it could have gone through any of a number of IP addresses along the way is neither here nor there to us.\n\nIt doesn\u0027t matter though because neutron expects nexthops as IP addresses, so we need to provide an IP address. We can\u0027t translate to an IP unambiguously, which is the crux of the problem.","commit_id":"4657d8800cfb97fa79a0cfd3dac17cf5240f5898"},{"author":{"_account_id":4257,"name":"Zane Bitter","email":"zbitter@redhat.com","username":"zaneb"},"change_message_id":"9f696861fb1ea15527510add6bc2b73e7937caaf","unresolved":false,"context_lines":[{"line_number":369,"context_line":"                    break"},{"line_number":370,"context_line":"            # depend on any RouterInterface in this template with the same"},{"line_number":371,"context_line":"            # router_id as this router_id"},{"line_number":372,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::RouterInterface\u0027) and"},{"line_number":373,"context_line":"                resource.properties[\u0027router_id\u0027] \u003d\u003d"},{"line_number":374,"context_line":"                    self.properties[\u0027router_id\u0027]):"},{"line_number":375,"context_line":"                        deps +\u003d (self, resource)"}],"source_content_type":"text/x-python","patch_set":21,"id":"AAAAUH%2F%2FkN8%3D","line":372,"in_reply_to":"AAAAUH%2F%2FkdM%3D","updated":"2014-01-14 23:55:14.000000000","message":"\u003e I don\u0027t think it is named that. It\u0027s just an \u0027extraroutes\u0027 table.\n\nGood point, so maybe we should name this resource ExtraRoute.\n\n\u003e We would need logic in heat to translate a port/instanceid/etc to an IP address for the neutron extension, which is the ambiguous translation I was referring to.\n\nRight, but at some point the Router is translating it back to an interface and a MAC which is unambiguous. The fact that it could have gone through any of a number of IP addresses along the way is neither here nor there to us.\n\n\u003e I understand that it\u0027s not a great fit because heat doesn\u0027t implicitly understand the dependencies between routes and connectivity, but how does it break it?\n\nHeat\u0027s data model is to model dependencies in the template. This means that everything works even when the resource definitions are spread throughout arbitrary trees of nested templates or, indeed, even outside Heat (or in unconnected templates). And this just doesn\u0027t - it only works if all of your resources are defined in one template.\n\n\u003e Also, even if I changed the patch to specify a heat resource as the next hop, this same logic to guarantee connectivity to the resource from the router would still be required. For example, if the next hop is an instanceid, an exception would still be raised if the instance was created but the router interface was not yet attached to that network.\n\nThen that sounds like the data model is broken somewhere else as well. I suspect we should deprecate RouterInterface and either allow a Port to be attached to a Router or not, but not allow it to be in some intermediate state where it will be attached to a Router but not yet. (We already had to do something similar with deprecating RouterGateway, and indeed the code in ll. 376--381 exists to handle that broken model until such time as we can eliminate it.)","commit_id":"4657d8800cfb97fa79a0cfd3dac17cf5240f5898"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"d51ed81a356a6af0701562e4469b8451430a4c17","unresolved":false,"context_lines":[{"line_number":369,"context_line":"                    break"},{"line_number":370,"context_line":"            # depend on any RouterInterface in this template with the same"},{"line_number":371,"context_line":"            # router_id as this router_id"},{"line_number":372,"context_line":"            if (resource.has_interface(\u0027OS::Neutron::RouterInterface\u0027) and"},{"line_number":373,"context_line":"                resource.properties[\u0027router_id\u0027] \u003d\u003d"},{"line_number":374,"context_line":"                    self.properties[\u0027router_id\u0027]):"},{"line_number":375,"context_line":"                        deps +\u003d (self, resource)"}],"source_content_type":"text/x-python","patch_set":21,"id":"AAAAUH%2F%2FkdM%3D","line":372,"in_reply_to":"AAAAUH%2F%2FlSc%3D","updated":"2014-01-10 22:44:13.000000000","message":"\u003eThe \"Routing Table\" in Neutron is probably mis-named because it is actually more like a FIB than a RIB.\n\nI don\u0027t think it is named that. It\u0027s just an \u0027extraroutes\u0027 table. It\u0027s up to the plugin that controls the underlying network to translate it into a FIB.\n\n\u003eIf the destination MAC has multiple IP addresses associated, it doesn\u0027t matter because the IP address of the nexthop doesn\u0027t enter into it as far as the router is concerned.\n\nUnfortunately that\u0027s not how the FIB is represented by the neutron extension though. We would need logic in heat to translate a port/instanceid/etc to an IP address for the neutron extension, which is the ambiguous translation I was referring to. \n\n\u003eThe implementation as it stands breaks Heat\u0027s data model.\n\nI understand that it\u0027s not a great fit because heat doesn\u0027t implicitly understand the dependencies between routes and connectivity, but how does it break it? \n\nAlso, even if I changed the patch to specify a heat resource as the next hop, this same logic to guarantee connectivity to the resource from the router would still be required. For example, if the next hop is an instanceid, an exception would still be raised if the instance was created but the router interface was not yet attached to that network.","commit_id":"4657d8800cfb97fa79a0cfd3dac17cf5240f5898"}]}
