)]}'
{"doc/source/specs/nb_api_refactor.rst":[{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"63e82625730e9081bb1453284e08d65977b0d945","unresolved":false,"context_lines":[{"line_number":96,"context_line":""},{"line_number":97,"context_line":"::"},{"line_number":98,"context_line":""},{"line_number":99,"context_line":"    self.nb_api.get_resource(\u0027lport\u0027).create(...)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"Pros:"}],"source_content_type":"text/x-rst","patch_set":5,"id":"ba5201f7_1e6bc71f","line":99,"range":{"start_line":99,"start_character":4,"end_line":99,"end_character":49},"updated":"2017-01-02 14:53:03.000000000","message":"I think this is kind of redundant now, once we decided to go for model objects with typed fields. \n\nWhat CRUD originally was written to do, is take keywork arguments, compose a dictionary and write it to the database. This approach does not enforce schema validity, so I think we should change it. Given a model instance, we can create/update/delete it just by knowing its type:\n\n def create(self, model_obj):\n     model_obj.validate()\n     val \u003d jsonutils.dumps(model_obj.to_struct())\n     write_to_db(model_obj.table_name, val)\n\nUpdate is very similar, we\u0027ll just have to make sure we\u0027re overwriting only specified fields.\n\nI think it would be simpler to reduce NB API to following functions:\n\n nb_api.create(Model(id\u003d...,field1\u003d...))\n nb_api.update(Model(id\u003d...,field2\u003d...))\n nb_api.delete(Model(id\u003d...))\n nb_api.get(Model(id\u003d...))\n\nThen all the operations on the models (e.g. assoc floating ip) happen on the model directly, and updated through the NB api:\n\n  fip.assoc_lport(lport)\n  nb_api.update(fip)\n\nAlso, for convenience we can add extra constructors to each model we create Neutron requests:\n\n @classmethod\n def from_neutron_context(cls, ctx):\n     return cls(\n         id\u003dctx.current.get(\u0027id\u0027),\n         topic\u003dctx.current.get(\u0027tenant_id\u0027),\n         ....\n     )\n\n\nThat way our mech driver and service plugins become simpler:\n\n def create_network_postcommit(self, ctx):\n     self.nb_api.create(Lswitch.from_neutron_ctx(ctx))","commit_id":"fd213061f0fadfc5c2714273055d6a74d9e2f0dd"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"bc186bcaa917df063ad9bf377cd660c58301ec94","unresolved":false,"context_lines":[{"line_number":96,"context_line":""},{"line_number":97,"context_line":"::"},{"line_number":98,"context_line":""},{"line_number":99,"context_line":"    self.nb_api.get_resource(\u0027lport\u0027).create(...)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"Pros:"}],"source_content_type":"text/x-rst","patch_set":5,"id":"ba5201f7_d78075f9","line":99,"range":{"start_line":99,"start_character":4,"end_line":99,"end_character":49},"in_reply_to":"ba5201f7_0db678f8","updated":"2017-01-09 08:17:55.000000000","message":"@Hong Hui Xiao\n1. For [1] we\u0027ll have to let each model a way to specialize the create/update/delete/get/get_all calls, a-la CRUD helper proposed before.\n\n2. I am not familiar enough with the contexts, but I don\u0027t thinks its a big issue, we either create a method for each or just skip it and convert in-line inside mech_driver.","commit_id":"fd213061f0fadfc5c2714273055d6a74d9e2f0dd"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"e04933fd6a0c4e3e7ef008bf63496c7b86660213","unresolved":false,"context_lines":[{"line_number":96,"context_line":""},{"line_number":97,"context_line":"::"},{"line_number":98,"context_line":""},{"line_number":99,"context_line":"    self.nb_api.get_resource(\u0027lport\u0027).create(...)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"Pros:"}],"source_content_type":"text/x-rst","patch_set":5,"id":"ba5201f7_af43a7ad","line":99,"range":{"start_line":99,"start_character":4,"end_line":99,"end_character":49},"in_reply_to":"ba5201f7_1e6bc71f","updated":"2017-01-08 15:29:11.000000000","message":"This direction looks good in my opinion, considering the evolution this spec has passed.\n\n@xiaohhui, you had some issues with a similar direction in the past. Is this direction all right, or do you have some concerns?","commit_id":"fd213061f0fadfc5c2714273055d6a74d9e2f0dd"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"c5ebe68d1be60256c4fdab077fdd91ec8510537b","unresolved":false,"context_lines":[{"line_number":96,"context_line":""},{"line_number":97,"context_line":"::"},{"line_number":98,"context_line":""},{"line_number":99,"context_line":"    self.nb_api.get_resource(\u0027lport\u0027).create(...)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"Pros:"}],"source_content_type":"text/x-rst","patch_set":5,"id":"ba5201f7_0db678f8","line":99,"range":{"start_line":99,"start_character":4,"end_line":99,"end_character":49},"in_reply_to":"ba5201f7_af43a7ad","updated":"2017-01-09 02:20:23.000000000","message":"I am more than OK with this direction. The original way that I had issues with proposes something like \"self.nb_api.floatingip.update\". I just don\u0027t like the middle `floatingip`. This direction seems finding another way out , removes the hardcode `floatingip` and abstracts the essence of nb db operations. \n\nA couple of things that I think deserve some attention:\n\n1. How would you take care of the special case like [1]?\n\n2. The context in ml2 mech driver and in service plugin is not the same thing. The former context is instance of subclass of neutron.plugin.ml2.MechanismDriverContext, while the latter context is instance of neutron.context.Context. \nThe from_neutron_ctx method might not apply to latter one.\n\n[1] https://github.com/openstack/dragonflow/blob/1fdc89d0ce7c8c6422eb79519c346fced6328a9e/dragonflow/db/api_nb.py#L465-L467","commit_id":"fd213061f0fadfc5c2714273055d6a74d9e2f0dd"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"d2211b5c33a94b68ab28692c2f8b6ca8dd6dc3c2","unresolved":false,"context_lines":[{"line_number":133,"context_line":""},{"line_number":134,"context_line":"    @register_model"},{"line_number":135,"context_line":"    @construct_nb_db_model("},{"line_number":136,"context_line":"        indexes\u003dNamespace(id\u003d\u0027id),"},{"line_number":137,"context_line":"        events\u003d(\u0027create\u0027, \u0027update\u0027, \u0027delete\u0027),"},{"line_number":138,"context_line":"        nb_crud\u003d\u003cCRUD Helper\u003e,"},{"line_number":139,"context_line":"    )"}],"source_content_type":"text/x-rst","patch_set":5,"id":"da4df55a_8f5644cc","line":136,"range":{"start_line":136,"start_character":32,"end_line":136,"end_character":34},"updated":"2016-12-27 01:30:42.000000000","message":"missing quotation mark？","commit_id":"fd213061f0fadfc5c2714273055d6a74d9e2f0dd"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"96b327b007517ec502bcb1713a852e2e1b105ed4","unresolved":false,"context_lines":[{"line_number":131,"context_line":""},{"line_number":132,"context_line":"::"},{"line_number":133,"context_line":""},{"line_number":134,"context_line":"    @register_model"},{"line_number":135,"context_line":"    @construct_nb_db_model("},{"line_number":136,"context_line":"        indexes\u003dNamespace(id\u003d\u0027id),"},{"line_number":137,"context_line":"        events\u003d(\u0027create\u0027, \u0027update\u0027, \u0027delete\u0027),"},{"line_number":138,"context_line":"        nb_crud\u003d\u003cCRUD Helper\u003e,"},{"line_number":139,"context_line":"    )"},{"line_number":140,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":141,"context_line":"        # Fields"},{"line_number":142,"context_line":"        \u003cModelField1\u003e \u003d jsonmodels.StringField()"},{"line_number":143,"context_line":"        \u003cModelReferenceField1\u003e \u003d jsonmodels.RefField()"},{"line_number":144,"context_line":""},{"line_number":145,"context_line":"        # Additional methods, if necessary, e.g. lports external fields"},{"line_number":146,"context_line":""},{"line_number":147,"context_line":"\u003cModelBaseClass\u003e will be a base class all models inherit."},{"line_number":148,"context_line":""}],"source_content_type":"text/x-rst","patch_set":5,"id":"da4df55a_5bf50b55","line":145,"range":{"start_line":134,"start_character":0,"end_line":145,"end_character":71},"updated":"2016-12-26 13:56:44.000000000","message":"Some basic implementation and usage ca be seen here.\nhttps://review.openstack.org/#/c/414984/","commit_id":"fd213061f0fadfc5c2714273055d6a74d9e2f0dd"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"b7ada0356e131789c31dc4645baaaafa12eeddb8","unresolved":false,"context_lines":[{"line_number":176,"context_line":"methods: `create`, `get`, `update`, and `delete`. A \u003cModelMixin\u003e may override"},{"line_number":177,"context_line":"this field to provide a CRUD helper with additional methods."},{"line_number":178,"context_line":""},{"line_number":179,"context_line":"The mnodel class itself will hold the list of fields available on the object."},{"line_number":180,"context_line":"getter functions can be generated automatically, in the form of"},{"line_number":181,"context_line":"`get_\u003cfieldname\u003e` for every defined field, unless such a method already"},{"line_number":182,"context_line":"exists. The type of the field, as well as any additonal metadata, can be"}],"source_content_type":"text/x-rst","patch_set":5,"id":"da4df55a_b54d2840","line":179,"range":{"start_line":179,"start_character":4,"end_line":179,"end_character":10},"updated":"2016-12-26 12:40:16.000000000","message":"model","commit_id":"fd213061f0fadfc5c2714273055d6a74d9e2f0dd"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"b7ada0356e131789c31dc4645baaaafa12eeddb8","unresolved":false,"context_lines":[{"line_number":178,"context_line":""},{"line_number":179,"context_line":"The mnodel class itself will hold the list of fields available on the object."},{"line_number":180,"context_line":"getter functions can be generated automatically, in the form of"},{"line_number":181,"context_line":"`get_\u003cfieldname\u003e` for every defined field, unless such a method already"},{"line_number":182,"context_line":"exists. The type of the field, as well as any additonal metadata, can be"},{"line_number":183,"context_line":"specified during field definition. e.g. to specify an IP field, specify"},{"line_number":184,"context_line":"`ipv4 \u003d models.IPv4Field()`."}],"source_content_type":"text/x-rst","patch_set":5,"id":"da4df55a_f5e330a2","line":181,"range":{"start_line":181,"start_character":0,"end_line":181,"end_character":17},"updated":"2016-12-26 12:40:16.000000000","message":"jsonmodels provides each field as property with relevant setters that perform valdation, do we really need the getters?","commit_id":"fd213061f0fadfc5c2714273055d6a74d9e2f0dd"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"910a53ad2fd474c283335b770476bfbdb3d97e59","unresolved":false,"context_lines":[{"line_number":178,"context_line":""},{"line_number":179,"context_line":"The mnodel class itself will hold the list of fields available on the object."},{"line_number":180,"context_line":"getter functions can be generated automatically, in the form of"},{"line_number":181,"context_line":"`get_\u003cfieldname\u003e` for every defined field, unless such a method already"},{"line_number":182,"context_line":"exists. The type of the field, as well as any additonal metadata, can be"},{"line_number":183,"context_line":"specified during field definition. e.g. to specify an IP field, specify"},{"line_number":184,"context_line":"`ipv4 \u003d models.IPv4Field()`."}],"source_content_type":"text/x-rst","patch_set":5,"id":"da4df55a_9044b21b","line":181,"range":{"start_line":181,"start_character":0,"end_line":181,"end_character":17},"in_reply_to":"da4df55a_f5e330a2","updated":"2016-12-26 13:06:37.000000000","message":"No. We can do without.","commit_id":"fd213061f0fadfc5c2714273055d6a74d9e2f0dd"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"b7ada0356e131789c31dc4645baaaafa12eeddb8","unresolved":false,"context_lines":[{"line_number":192,"context_line":""},{"line_number":193,"context_line":"::"},{"line_number":194,"context_line":""},{"line_number":195,"context_line":"    network \u003d models.RefField(model\u003d\u0027Network\u0027)"},{"line_number":196,"context_line":""},{"line_number":197,"context_line":"In another example, networks reference their subnets and contain the subnet"},{"line_number":198,"context_line":"object. Therefore, the subnet definition within the network will be:"}],"source_content_type":"text/x-rst","patch_set":5,"id":"da4df55a_b5e9a8e8","line":195,"range":{"start_line":195,"start_character":4,"end_line":195,"end_character":46},"updated":"2016-12-26 12:40:16.000000000","message":"Do we want to define references by anything other than id index? The index will be used to access NB DB so I think it is a fair assumption (at least for now) that it will be the index we\u0027ll use.\n\nIt will save us from defining a language used to map the inline info to a key, which could be a bit awkward...","commit_id":"fd213061f0fadfc5c2714273055d6a74d9e2f0dd"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"910a53ad2fd474c283335b770476bfbdb3d97e59","unresolved":false,"context_lines":[{"line_number":192,"context_line":""},{"line_number":193,"context_line":"::"},{"line_number":194,"context_line":""},{"line_number":195,"context_line":"    network \u003d models.RefField(model\u003d\u0027Network\u0027)"},{"line_number":196,"context_line":""},{"line_number":197,"context_line":"In another example, networks reference their subnets and contain the subnet"},{"line_number":198,"context_line":"object. Therefore, the subnet definition within the network will be:"}],"source_content_type":"text/x-rst","patch_set":5,"id":"da4df55a_905bd2f5","line":195,"range":{"start_line":195,"start_character":4,"end_line":195,"end_character":46},"in_reply_to":"da4df55a_b5e9a8e8","updated":"2016-12-26 13:06:37.000000000","message":"Reference by ID only seems good enough. Not need to support other fields.","commit_id":"fd213061f0fadfc5c2714273055d6a74d9e2f0dd"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"d2211b5c33a94b68ab28692c2f8b6ca8dd6dc3c2","unresolved":false,"context_lines":[{"line_number":350,"context_line":"  The automatic migration code will generate files to be placed"},{"line_number":351,"context_line":"  in dragonflow.migration. They will use the timestamp of code"},{"line_number":352,"context_line":"  generation. The generation will review the differences between the"},{"line_number":353,"context_line":"  object before and after the change (retrieved using git magic), and"},{"line_number":354,"context_line":"  generate the script to migrate. A developer will have to review the"},{"line_number":355,"context_line":"  result to verify there are not errors."},{"line_number":356,"context_line":""},{"line_number":357,"context_line":"* Configuration file options (Can be done in parallel)"}],"source_content_type":"text/x-rst","patch_set":5,"id":"da4df55a_efd0b0f8","line":354,"range":{"start_line":353,"start_character":38,"end_line":354,"end_character":32},"updated":"2016-12-27 01:30:42.000000000","message":"Do you mean automatically generate the script form migration? How would that happen?","commit_id":"fd213061f0fadfc5c2714273055d6a74d9e2f0dd"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"c5ebe68d1be60256c4fdab077fdd91ec8510537b","unresolved":false,"context_lines":[{"line_number":350,"context_line":"  The automatic migration code will generate files to be placed"},{"line_number":351,"context_line":"  in dragonflow.migration. They will use the timestamp of code"},{"line_number":352,"context_line":"  generation. The generation will review the differences between the"},{"line_number":353,"context_line":"  object before and after the change (retrieved using git magic), and"},{"line_number":354,"context_line":"  generate the script to migrate. A developer will have to review the"},{"line_number":355,"context_line":"  result to verify there are not errors."},{"line_number":356,"context_line":""},{"line_number":357,"context_line":"* Configuration file options (Can be done in parallel)"}],"source_content_type":"text/x-rst","patch_set":5,"id":"ba5201f7_8d99887b","line":354,"range":{"start_line":353,"start_character":38,"end_line":354,"end_character":32},"in_reply_to":"da4df55a_6cc4c05e","updated":"2017-01-09 02:20:23.000000000","message":"I just don\u0027t know the tool will do the job automatically without maintenance, or will do the job with careful maintenance. e.g. how would the tool take care the default value of the new attribute? Take unique_key as example, its default value needs to be allocated from nb db. I think we need add additional code for that kind of migration.","commit_id":"fd213061f0fadfc5c2714273055d6a74d9e2f0dd"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"efc2f4df5d0b80d33f7cf3302897ce57d472ac51","unresolved":false,"context_lines":[{"line_number":350,"context_line":"  The automatic migration code will generate files to be placed"},{"line_number":351,"context_line":"  in dragonflow.migration. They will use the timestamp of code"},{"line_number":352,"context_line":"  generation. The generation will review the differences between the"},{"line_number":353,"context_line":"  object before and after the change (retrieved using git magic), and"},{"line_number":354,"context_line":"  generate the script to migrate. A developer will have to review the"},{"line_number":355,"context_line":"  result to verify there are not errors."},{"line_number":356,"context_line":""},{"line_number":357,"context_line":"* Configuration file options (Can be done in parallel)"}],"source_content_type":"text/x-rst","patch_set":5,"id":"da4df55a_6cc4c05e","line":354,"range":{"start_line":353,"start_character":38,"end_line":354,"end_character":32},"in_reply_to":"da4df55a_8f89e377","updated":"2016-12-27 12:25:13.000000000","message":"@xiaohhui, not sure I understood what you mean, but mostly I meant a tool that will take the current patch\u0027s models, the previous commit\u0027s models, compare them, and generate a migration script.\n\n@nick-ma, not a necessity, but I think it would help greatly with there was something that will generate the migration script, and the developer only needs to tweak it to work.","commit_id":"fd213061f0fadfc5c2714273055d6a74d9e2f0dd"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"b41b1c6b59460dc27a01365f29699b1add57ef21","unresolved":false,"context_lines":[{"line_number":350,"context_line":"  The automatic migration code will generate files to be placed"},{"line_number":351,"context_line":"  in dragonflow.migration. They will use the timestamp of code"},{"line_number":352,"context_line":"  generation. The generation will review the differences between the"},{"line_number":353,"context_line":"  object before and after the change (retrieved using git magic), and"},{"line_number":354,"context_line":"  generate the script to migrate. A developer will have to review the"},{"line_number":355,"context_line":"  result to verify there are not errors."},{"line_number":356,"context_line":""},{"line_number":357,"context_line":"* Configuration file options (Can be done in parallel)"}],"source_content_type":"text/x-rst","patch_set":5,"id":"da4df55a_8f89e377","line":354,"range":{"start_line":353,"start_character":38,"end_line":354,"end_character":32},"in_reply_to":"da4df55a_efd0b0f8","updated":"2016-12-27 02:08:09.000000000","message":"I also doubt the necessity. Could you elaborate it?","commit_id":"fd213061f0fadfc5c2714273055d6a74d9e2f0dd"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"b41b1c6b59460dc27a01365f29699b1add57ef21","unresolved":false,"context_lines":[{"line_number":359,"context_line":"References"},{"line_number":360,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":361,"context_line":""},{"line_number":362,"context_line":".. [1] https://github.com/beregond/jsonmodels"}],"source_content_type":"text/x-rst","patch_set":5,"id":"da4df55a_af7a2775","line":362,"updated":"2016-12-27 02:08:09.000000000","message":"is this library in openstack requirements? it seems not well maintained.","commit_id":"fd213061f0fadfc5c2714273055d6a74d9e2f0dd"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"efc2f4df5d0b80d33f7cf3302897ce57d472ac51","unresolved":false,"context_lines":[{"line_number":359,"context_line":"References"},{"line_number":360,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":361,"context_line":""},{"line_number":362,"context_line":".. [1] https://github.com/beregond/jsonmodels"}],"source_content_type":"text/x-rst","patch_set":5,"id":"da4df55a_ec851007","line":362,"in_reply_to":"da4df55a_af7a2775","updated":"2016-12-27 12:25:13.000000000","message":"It isn\u0027t yet. @dimak is trying to add it here: https://review.openstack.org/#/c/415164/ . We\u0027ll see what the infra guys say. Since we couldn\u0027t find any other matching alternatives (all other alternatives were database-backed), and we don\u0027t want to write it from scratch, and if the maintenance is the only issue, we could take over the project (or create a fork).","commit_id":"fd213061f0fadfc5c2714273055d6a74d9e2f0dd"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"07eaf8201f2bccdb30cb12ea2d760fc3876d0fbe","unresolved":false,"context_lines":[{"line_number":102,"context_line":""},{"line_number":103,"context_line":"Each method will receive a model instance. It will use the data in the model"},{"line_number":104,"context_line":"to update the database (`id` for `get` and `delete`, other fields for `create`"},{"line_number":105,"context_line":"and `update`)."},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"A model will be able to extend these operations using metadata defined upon"},{"line_number":108,"context_line":"model definition (see below)."}],"source_content_type":"text/x-rst","patch_set":6,"id":"ba5201f7_ab67cdb5","line":105,"range":{"start_line":105,"start_character":12,"end_line":105,"end_character":13},"updated":"2017-01-10 13:18:50.000000000","message":"no arguments for get_all?","commit_id":"a25a32608a515e454a11ea3212aca1b1dbf5c9e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"cdd77f9175517d535c40d1dfdedf78134ad7f320","unresolved":false,"context_lines":[{"line_number":102,"context_line":""},{"line_number":103,"context_line":"Each method will receive a model instance. It will use the data in the model"},{"line_number":104,"context_line":"to update the database (`id` for `get` and `delete`, other fields for `create`"},{"line_number":105,"context_line":"and `update`)."},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"A model will be able to extend these operations using metadata defined upon"},{"line_number":108,"context_line":"model definition (see below)."}],"source_content_type":"text/x-rst","patch_set":6,"id":"ba5201f7_684b202c","line":105,"range":{"start_line":105,"start_character":12,"end_line":105,"end_character":13},"in_reply_to":"ba5201f7_ab67cdb5","updated":"2017-01-10 16:07:20.000000000","message":"get_all must get an argument to know from which table to read. Will add next spin.","commit_id":"a25a32608a515e454a11ea3212aca1b1dbf5c9e8"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"6bf10ee10624bba7fec7137883d71907107d83c1","unresolved":false,"context_lines":[{"line_number":160,"context_line":"    @construct_nb_db_model("},{"line_number":161,"context_line":"        indexes\u003dNamespace(id\u003d\u0027id\u0027),"},{"line_number":162,"context_line":"        events\u003d(\u0027create\u0027, \u0027update\u0027, \u0027delete\u0027),"},{"line_number":163,"context_line":"        nb_create\u003d\u003cCreate command\u003e,"},{"line_number":164,"context_line":"        nb_get\u003d\u003cGet command\u003e,"},{"line_number":165,"context_line":"        nb_update\u003d\u003cUpdate command\u003e,"},{"line_number":166,"context_line":"        nb_delete\u003d\u003cDelete command\u003e,"},{"line_number":167,"context_line":"    )"},{"line_number":168,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":169,"context_line":"        # Fields"}],"source_content_type":"text/x-rst","patch_set":6,"id":"ba5201f7_dacaee4e","line":166,"range":{"start_line":163,"start_character":0,"end_line":166,"end_character":35},"updated":"2017-01-11 09:08:38.000000000","message":"I\u0027m not sure if this better than defining a CRUD type and overriding the specific methods but I don\u0027t have a strong opinion for either.","commit_id":"a25a32608a515e454a11ea3212aca1b1dbf5c9e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"5afe989b2b5f37299b50f484947ad3413aaed87c","unresolved":false,"context_lines":[{"line_number":160,"context_line":"    @construct_nb_db_model("},{"line_number":161,"context_line":"        indexes\u003dNamespace(id\u003d\u0027id\u0027),"},{"line_number":162,"context_line":"        events\u003d(\u0027create\u0027, \u0027update\u0027, \u0027delete\u0027),"},{"line_number":163,"context_line":"        nb_create\u003d\u003cCreate command\u003e,"},{"line_number":164,"context_line":"        nb_get\u003d\u003cGet command\u003e,"},{"line_number":165,"context_line":"        nb_update\u003d\u003cUpdate command\u003e,"},{"line_number":166,"context_line":"        nb_delete\u003d\u003cDelete command\u003e,"},{"line_number":167,"context_line":"    )"},{"line_number":168,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":169,"context_line":"        # Fields"}],"source_content_type":"text/x-rst","patch_set":6,"id":"7a3c09a3_c1b3bee7","line":166,"range":{"start_line":163,"start_character":0,"end_line":166,"end_character":35},"in_reply_to":"7a3c09a3_be27d710","updated":"2017-01-17 08:18:33.000000000","message":"+1","commit_id":"a25a32608a515e454a11ea3212aca1b1dbf5c9e8"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"ad613e8ca4842763c568e6d77f4c1b8e7b8a202a","unresolved":false,"context_lines":[{"line_number":160,"context_line":"    @construct_nb_db_model("},{"line_number":161,"context_line":"        indexes\u003dNamespace(id\u003d\u0027id\u0027),"},{"line_number":162,"context_line":"        events\u003d(\u0027create\u0027, \u0027update\u0027, \u0027delete\u0027),"},{"line_number":163,"context_line":"        nb_create\u003d\u003cCreate command\u003e,"},{"line_number":164,"context_line":"        nb_get\u003d\u003cGet command\u003e,"},{"line_number":165,"context_line":"        nb_update\u003d\u003cUpdate command\u003e,"},{"line_number":166,"context_line":"        nb_delete\u003d\u003cDelete command\u003e,"},{"line_number":167,"context_line":"    )"},{"line_number":168,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":169,"context_line":"        # Fields"}],"source_content_type":"text/x-rst","patch_set":6,"id":"7a3c09a3_be27d710","line":166,"range":{"start_line":163,"start_character":0,"end_line":166,"end_character":35},"in_reply_to":"ba5201f7_dacaee4e","updated":"2017-01-16 15:36:53.000000000","message":"In fact I think we should avoid this customizated CRUD layer altogether.\n\nAfter playing a bit with mixins, I realized it is very confusing to have the create() code as part of the CRUD layer. Consider the following scenario:\n\nhttp://i.imgur.com/5ArjGRL.png\n\nWe want to create a new NewModel in the database, and we have to use a CRUD object for that.  The CRUD object for NewModel is CRUD1 inherited from ModelBase (since its the leftmost), but CRUD1 doesn\u0027t necessarily takes care of fields in Mixin1.\n\nCRUD1 and CRUD2 are not necessarily in descendant-ancestor relationship, so we cannot just choose one that fits both (consider we have 3 possible CRUDs to choose from).  \n\nI suggest we go with a single set of CRUD operations for all models (in NB api), and allow several hook-points for all each model augment its behavior.\n\nFor example:\n\n def create(self, obj):\n     obj.on_create_pre()\n     data \u003d obj.serialize()\n     self.db.create_key(obj.id, data)\n     self.publisher.send_event(obj.id, data)\n\nHere we add an entry point for our model object to initialize itself upon creation.\n\nOn model end, each model/mixin can override it do its stuff and pass the control to the next in line:\n\n def on_create_pre(self):\n     self.take_care_of_some_fields()\n     super(OurMixin, self).on_create_pre()\n\nThis way, the descendant-ancestor relationship exists due to model\u0027s own class hierarchy, and each class only has to take care of field manipulation, as serialization and database access happen in NorthBound API (plus we get rid of extra classes :). Additionally, the order of hook function calls is subject to python\u0027s MRO, so it is well documents and somewhat intuitive.","commit_id":"a25a32608a515e454a11ea3212aca1b1dbf5c9e8"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"07eaf8201f2bccdb30cb12ea2d760fc3876d0fbe","unresolved":false,"context_lines":[{"line_number":222,"context_line":""},{"line_number":223,"context_line":"    subnet \u003d models.NestedField(model\u003d\u0027Subnet\u0027)"},{"line_number":224,"context_line":""},{"line_number":225,"context_line":"In this example, we assume exactly one subnet per network."},{"line_number":226,"context_line":""},{"line_number":227,"context_line":"In both cases, when referencing the field, it will look as though the field"},{"line_number":228,"context_line":"is nested within the parent model. If only the id field is accessed in a"}],"source_content_type":"text/x-rst","patch_set":6,"id":"ba5201f7_ae46fb4c","line":225,"range":{"start_line":225,"start_character":34,"end_line":225,"end_character":57},"updated":"2017-01-10 13:18:50.000000000","message":"with IPv6 supported, there will be at least 2 subnets per network","commit_id":"a25a32608a515e454a11ea3212aca1b1dbf5c9e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"cdd77f9175517d535c40d1dfdedf78134ad7f320","unresolved":false,"context_lines":[{"line_number":222,"context_line":""},{"line_number":223,"context_line":"    subnet \u003d models.NestedField(model\u003d\u0027Subnet\u0027)"},{"line_number":224,"context_line":""},{"line_number":225,"context_line":"In this example, we assume exactly one subnet per network."},{"line_number":226,"context_line":""},{"line_number":227,"context_line":"In both cases, when referencing the field, it will look as though the field"},{"line_number":228,"context_line":"is nested within the parent model. If only the id field is accessed in a"}],"source_content_type":"text/x-rst","patch_set":6,"id":"ba5201f7_285838fa","line":225,"range":{"start_line":225,"start_character":34,"end_line":225,"end_character":57},"in_reply_to":"ba5201f7_ae46fb4c","updated":"2017-01-10 16:07:20.000000000","message":"Yes. This is just an example to show the specific use case of RefField and NestedField.","commit_id":"a25a32608a515e454a11ea3212aca1b1dbf5c9e8"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"07eaf8201f2bccdb30cb12ea2d760fc3876d0fbe","unresolved":false,"context_lines":[{"line_number":351,"context_line":""},{"line_number":352,"context_line":"* Remove legacy API"},{"line_number":353,"context_line":""},{"line_number":354,"context_line":"* Configuration file options (Can be done in parallel)"},{"line_number":355,"context_line":""},{"line_number":356,"context_line":"References"},{"line_number":357,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":6,"id":"ba5201f7_8e03f7b7","line":354,"range":{"start_line":354,"start_character":2,"end_line":354,"end_character":29},"updated":"2017-01-10 13:18:50.000000000","message":"This was not mentioned before. Can you elaborate about the impact?","commit_id":"a25a32608a515e454a11ea3212aca1b1dbf5c9e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"cdd77f9175517d535c40d1dfdedf78134ad7f320","unresolved":false,"context_lines":[{"line_number":351,"context_line":""},{"line_number":352,"context_line":"* Remove legacy API"},{"line_number":353,"context_line":""},{"line_number":354,"context_line":"* Configuration file options (Can be done in parallel)"},{"line_number":355,"context_line":""},{"line_number":356,"context_line":"References"},{"line_number":357,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":6,"id":"ba5201f7_28267868","line":354,"range":{"start_line":354,"start_character":2,"end_line":354,"end_character":29},"in_reply_to":"ba5201f7_8e03f7b7","updated":"2017-01-10 16:07:20.000000000","message":"Out-of-tree models are placed in an out-of-tree module. That module needs to be imported. This is the configuration option. Will add next spin.","commit_id":"a25a32608a515e454a11ea3212aca1b1dbf5c9e8"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"be4666cb1c5d8cc3c00a5dc90c9a8b43e676deee","unresolved":false,"context_lines":[{"line_number":184,"context_line":"\u003cCRUD hooks\u003e are optional method definitions that will be called upon CRUD"},{"line_number":185,"context_line":"operations performed in NbApi, e.g."},{"line_number":186,"context_line":""},{"line_number":187,"context_line":" * `on_create_pre` - Called on the object before its being inserted for the"},{"line_number":188,"context_line":"   first time into the database, for example allocating a unique key."},{"line_number":189,"context_line":""},{"line_number":190,"context_line":" * `on_update_pre` - Called on the object each time it is updated, can be used"}],"source_content_type":"text/x-rst","patch_set":7,"id":"5a3905b3_efdb027a","line":187,"range":{"start_line":187,"start_character":4,"end_line":187,"end_character":17},"updated":"2017-01-24 03:46:22.000000000","message":"is on_create_prehook more readable? if we have pre function, is it necessary to add post function?","commit_id":"f94972a2211199389a14b9685a9dd87e60a87e1c"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"4788b300d851a15b4c75403e48d23740a64cf6a9","unresolved":false,"context_lines":[{"line_number":184,"context_line":"\u003cCRUD hooks\u003e are optional method definitions that will be called upon CRUD"},{"line_number":185,"context_line":"operations performed in NbApi, e.g."},{"line_number":186,"context_line":""},{"line_number":187,"context_line":" * `on_create_pre` - Called on the object before its being inserted for the"},{"line_number":188,"context_line":"   first time into the database, for example allocating a unique key."},{"line_number":189,"context_line":""},{"line_number":190,"context_line":" * `on_update_pre` - Called on the object each time it is updated, can be used"}],"source_content_type":"text/x-rst","patch_set":7,"id":"3a461143_ac03a30c","line":187,"range":{"start_line":187,"start_character":4,"end_line":187,"end_character":17},"in_reply_to":"5a3905b3_efdb027a","updated":"2017-01-25 12:49:48.000000000","message":"About the naming I don\u0027t have a strong opinion. On the other question I think we don\u0027t have to decide what hooks we need in the scope of the spec because it will be a lot of guessing.\n\nWe should port all our models and add required hooks as we go. Once we\u0027re done and know all the cases (hook-points) needed we can reason about adding other ones, or maybe merging existing ones where possible.","commit_id":"f94972a2211199389a14b9685a9dd87e60a87e1c"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"be4666cb1c5d8cc3c00a5dc90c9a8b43e676deee","unresolved":false,"context_lines":[{"line_number":187,"context_line":" * `on_create_pre` - Called on the object before its being inserted for the"},{"line_number":188,"context_line":"   first time into the database, for example allocating a unique key."},{"line_number":189,"context_line":""},{"line_number":190,"context_line":" * `on_update_pre` - Called on the object each time it is updated, can be used"},{"line_number":191,"context_line":"   for example to generate a new version or trigger updates on other objects."},{"line_number":192,"context_line":""},{"line_number":193,"context_line":"Since those hooks are methods on objects themselves, we can use super() to"}],"source_content_type":"text/x-rst","patch_set":7,"id":"5a3905b3_0fe76e40","line":190,"range":{"start_line":190,"start_character":4,"end_line":190,"end_character":17},"updated":"2017-01-24 03:46:22.000000000","message":"ditto","commit_id":"f94972a2211199389a14b9685a9dd87e60a87e1c"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"cd18cb4742d512f3eb4665be1ec2cac6e028c526","unresolved":false,"context_lines":[{"line_number":87,"context_line":"* Dragonflow upgrade scenario, i.e. replacing an existing Dragonflow"},{"line_number":88,"context_line":"  implementation with a newer version"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"* *Please add anything I missed.*"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"Proposed Change"},{"line_number":93,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":8,"id":"3a461143_d1d474be","line":90,"updated":"2017-01-29 08:05:40.000000000","message":"I think this line can be removed","commit_id":"57d87b6780bae5d6728a94d8504af5c2d94a81fd"}],"doc/source/specs/nb_api_refactor_spec.rst":[{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"5dbc62973e70560038a2204b7ce57b0ba7320804","unresolved":false,"context_lines":[{"line_number":29,"context_line":""},{"line_number":30,"context_line":"  * Dynamic adding of events to applications (e.g. CRUD on lport, routers)"},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"* Dynamic registration of new models (for new features)"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"* Native Dragonflow API (e.g. REST)"},{"line_number":35,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_59960c4d","line":32,"range":{"start_line":32,"start_character":2,"end_line":32,"end_character":9},"updated":"2016-12-14 06:32:30.000000000","message":"please elaborate more on what you mean by \u0027dynamic\u0027","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"6d2b26be2abfe57ccf08f5a6bb3f8581048db363","unresolved":false,"context_lines":[{"line_number":29,"context_line":""},{"line_number":30,"context_line":"  * Dynamic adding of events to applications (e.g. CRUD on lport, routers)"},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"* Dynamic registration of new models (for new features)"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"* Native Dragonflow API (e.g. REST)"},{"line_number":35,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_5165cfb2","line":32,"range":{"start_line":32,"start_character":2,"end_line":32,"end_character":9},"in_reply_to":"1a6eadb0_59960c4d","updated":"2016-12-15 02:06:26.000000000","message":"+1 kind of magic ;-)","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"5dbc62973e70560038a2204b7ce57b0ba7320804","unresolved":false,"context_lines":[{"line_number":38,"context_line":""},{"line_number":39,"context_line":"Currently the northbound API (and southbound API) is written in a hard-coded"},{"line_number":40,"context_line":"manner which makes adding new models difficult. It requires modifications of"},{"line_number":41,"context_line":"many files, and the modification usually include modified code."},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"We would like to find a new mechanism, with the following requirements:"},{"line_number":44,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_597d2c1b","line":41,"range":{"start_line":41,"start_character":16,"end_line":41,"end_character":62},"updated":"2016-12-14 06:32:30.000000000","message":"this is the result of the modification, not the problem :-)","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"6311d26d19d296f2b368d1e4c527033267218289","unresolved":false,"context_lines":[{"line_number":38,"context_line":""},{"line_number":39,"context_line":"Currently the northbound API (and southbound API) is written in a hard-coded"},{"line_number":40,"context_line":"manner which makes adding new models difficult. It requires modifications of"},{"line_number":41,"context_line":"many files, and the modification usually include modified code."},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"We would like to find a new mechanism, with the following requirements:"},{"line_number":44,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_4cb00c44","line":41,"range":{"start_line":41,"start_character":16,"end_line":41,"end_character":62},"in_reply_to":"1a6eadb0_597d2c1b","updated":"2016-12-14 06:53:43.000000000","message":"Yes, evening writing always worked out well :)\n\nWill fix to: \u0027the modification usually includes duplicated code\u0027","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"5dbc62973e70560038a2204b7ce57b0ba7320804","unresolved":false,"context_lines":[{"line_number":39,"context_line":"Currently the northbound API (and southbound API) is written in a hard-coded"},{"line_number":40,"context_line":"manner which makes adding new models difficult. It requires modifications of"},{"line_number":41,"context_line":"many files, and the modification usually include modified code."},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"We would like to find a new mechanism, with the following requirements:"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"* Simple, readable code structure"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_39487087","line":42,"updated":"2016-12-14 06:32:30.000000000","message":"Another problem it is not easy to split new App development between developers due to the current implementation","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"5dbc62973e70560038a2204b7ce57b0ba7320804","unresolved":false,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":"* No hard-coding or tight coupling"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"* Support to easily add new models"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"* Within that, support for dynamic model registration (which may be done in future, or as an implementation of this spec)"},{"line_number":56,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_199ad463","line":53,"range":{"start_line":53,"start_character":2,"end_line":53,"end_character":34},"updated":"2016-12-14 06:32:30.000000000","message":"i.e. extendability","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"5dbc62973e70560038a2204b7ce57b0ba7320804","unresolved":false,"context_lines":[{"line_number":52,"context_line":""},{"line_number":53,"context_line":"* Support to easily add new models"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"* Within that, support for dynamic model registration (which may be done in future, or as an implementation of this spec)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"* Simplify support for new external APIs"},{"line_number":58,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_f9b998cc","line":55,"range":{"start_line":55,"start_character":27,"end_line":55,"end_character":34},"updated":"2016-12-14 06:32:30.000000000","message":"please explain what \u0027dynamic\u0027 means here","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"6d2b26be2abfe57ccf08f5a6bb3f8581048db363","unresolved":false,"context_lines":[{"line_number":52,"context_line":""},{"line_number":53,"context_line":"* Support to easily add new models"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"* Within that, support for dynamic model registration (which may be done in future, or as an implementation of this spec)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"* Simplify support for new external APIs"},{"line_number":58,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_d11f1f06","line":55,"range":{"start_line":55,"start_character":27,"end_line":55,"end_character":34},"in_reply_to":"1a6eadb0_2cf750f6","updated":"2016-12-15 02:06:26.000000000","message":"You can add the explanation to the context.","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"cefd06b4a7c6be05fb764a80f17965c6f75df50d","unresolved":false,"context_lines":[{"line_number":52,"context_line":""},{"line_number":53,"context_line":"* Support to easily add new models"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"* Within that, support for dynamic model registration (which may be done in future, or as an implementation of this spec)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"* Simplify support for new external APIs"},{"line_number":58,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_7739d1a3","line":55,"range":{"start_line":55,"start_character":27,"end_line":55,"end_character":34},"in_reply_to":"1a6eadb0_d11f1f06","updated":"2016-12-15 09:22:46.000000000","message":"Will do.","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"6311d26d19d296f2b368d1e4c527033267218289","unresolved":false,"context_lines":[{"line_number":52,"context_line":""},{"line_number":53,"context_line":"* Support to easily add new models"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"* Within that, support for dynamic model registration (which may be done in future, or as an implementation of this spec)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"* Simplify support for new external APIs"},{"line_number":58,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_2cf750f6","line":55,"range":{"start_line":55,"start_character":27,"end_line":55,"end_character":34},"in_reply_to":"1a6eadb0_f9b998cc","updated":"2016-12-14 06:53:43.000000000","message":"In this case, the thought is that models would be able to register themselves. A client developer only defines a model (maybe also call a registration function similar to the way configuration options register), and it exists in the NbApi and DbStore.","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"5dbc62973e70560038a2204b7ce57b0ba7320804","unresolved":false,"context_lines":[{"line_number":54,"context_line":""},{"line_number":55,"context_line":"* Within that, support for dynamic model registration (which may be done in future, or as an implementation of this spec)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"* Simplify support for new external APIs"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"* Support search and indexing operations in DB store (e.g. ports by chassis, local ports, remote ports)"},{"line_number":60,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_79c6684a","line":57,"range":{"start_line":57,"start_character":2,"end_line":57,"end_character":40},"updated":"2016-12-14 06:32:30.000000000","message":"please elaborate more","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"6311d26d19d296f2b368d1e4c527033267218289","unresolved":false,"context_lines":[{"line_number":54,"context_line":""},{"line_number":55,"context_line":"* Within that, support for dynamic model registration (which may be done in future, or as an implementation of this spec)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"* Simplify support for new external APIs"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"* Support search and indexing operations in DB store (e.g. ports by chassis, local ports, remote ports)"},{"line_number":60,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_cc37bcae","line":57,"range":{"start_line":57,"start_character":2,"end_line":57,"end_character":40},"in_reply_to":"1a6eadb0_79c6684a","updated":"2016-12-14 06:53:43.000000000","message":"Native API, Gluon, etc., will need to interface with NbApi. In theory, we should prepare the code so that this won\u0027t be too difficult.","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"5dbc62973e70560038a2204b7ce57b0ba7320804","unresolved":false,"context_lines":[{"line_number":60,"context_line":""},{"line_number":61,"context_line":"* Support special NB API operations (e.g. adding/removing router interfaces, adding/removing secgroup rules)"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"* Simple, localised changes when adding new models (e.g. for TAPaaS, FWaaS, SFC)"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"* Similar API for NBApi and DBStore (mostly for simplicity, readibility)"},{"line_number":66,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_f9e0b8ce","line":63,"range":{"start_line":63,"start_character":44,"end_line":63,"end_character":50},"updated":"2016-12-14 06:32:30.000000000","message":"it this case it looks more like adding new service models, maybe worth to emphasize it","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"6311d26d19d296f2b368d1e4c527033267218289","unresolved":false,"context_lines":[{"line_number":60,"context_line":""},{"line_number":61,"context_line":"* Support special NB API operations (e.g. adding/removing router interfaces, adding/removing secgroup rules)"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"* Simple, localised changes when adding new models (e.g. for TAPaaS, FWaaS, SFC)"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"* Similar API for NBApi and DBStore (mostly for simplicity, readibility)"},{"line_number":66,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_6c47881d","line":63,"range":{"start_line":63,"start_character":44,"end_line":63,"end_character":50},"in_reply_to":"1a6eadb0_f9e0b8ce","updated":"2016-12-14 06:53:43.000000000","message":"Yes, and yes (since the concept of \u0027service\u0027 models doesn\u0027t actually exist in Dragonflow)","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"b08329165f6e7d92cfc5a61cf3a1130e12937cdd","unresolved":false,"context_lines":[{"line_number":64,"context_line":""},{"line_number":65,"context_line":"* Similar API for NBApi and DBStore (mostly for simplicity, readibility)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"* *Please add anything I missed.*"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"Proposed Change"},{"line_number":70,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_d092f84a","line":67,"range":{"start_line":67,"start_character":0,"end_line":67,"end_character":33},"updated":"2016-12-14 01:39:11.000000000","message":"Uniform way to the calls in db_store and nb_api. I am thinking of supporting multi-tenants scenario(admin context, rbac). I hope the applications might only need to tell which resource and id they want. So that the applications don\u0027t need to make special call to db_store, if db_store returns None, make another special call to nb_api.","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"5dbc62973e70560038a2204b7ce57b0ba7320804","unresolved":false,"context_lines":[{"line_number":64,"context_line":""},{"line_number":65,"context_line":"* Similar API for NBApi and DBStore (mostly for simplicity, readibility)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"* *Please add anything I missed.*"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"Proposed Change"},{"line_number":70,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_b94560b4","line":67,"range":{"start_line":67,"start_character":0,"end_line":67,"end_character":33},"in_reply_to":"1a6eadb0_d092f84a","updated":"2016-12-14 06:32:30.000000000","message":"+1","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"5dbc62973e70560038a2204b7ce57b0ba7320804","unresolved":false,"context_lines":[{"line_number":65,"context_line":"* Similar API for NBApi and DBStore (mostly for simplicity, readibility)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"* *Please add anything I missed.*"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"Proposed Change"},{"line_number":70,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_b91c80c2","line":68,"updated":"2016-12-14 06:32:30.000000000","message":"Another requirements may be for the db-cli that should be extendable too  when new/dynamic models are added.","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"f6be99b19e2878c549302d02a061c9f9d0616d38","unresolved":false,"context_lines":[{"line_number":65,"context_line":"* Similar API for NBApi and DBStore (mostly for simplicity, readibility)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"* *Please add anything I missed.*"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"Proposed Change"},{"line_number":70,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_eeec6391","line":68,"in_reply_to":"1a6eadb0_02fb38c2","updated":"2016-12-14 10:55:03.000000000","message":"This partially addresses what I raised here. But \u0027upgrade\u0027 as an entire DF system flow should be considered as well","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"cefd06b4a7c6be05fb764a80f17965c6f75df50d","unresolved":false,"context_lines":[{"line_number":65,"context_line":"* Similar API for NBApi and DBStore (mostly for simplicity, readibility)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"* *Please add anything I missed.*"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"Proposed Change"},{"line_number":70,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_f76fa128","line":68,"in_reply_to":"1a6eadb0_318a131c","updated":"2016-12-15 09:22:46.000000000","message":"That would be very cool :)","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"8217569c3695dbef2fef7d7c20822c83eb390ccc","unresolved":false,"context_lines":[{"line_number":65,"context_line":"* Similar API for NBApi and DBStore (mostly for simplicity, readibility)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"* *Please add anything I missed.*"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"Proposed Change"},{"line_number":70,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_02fb38c2","line":68,"in_reply_to":"1a6eadb0_4cf9ec7f","updated":"2016-12-14 09:37:47.000000000","message":"\u003e Also need to refer to the upgrade scenario\n\nThis is handled here: https://review.openstack.org/#/c/401210 .","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"30c12617ee79658440fc27cba29dd1fb20746491","unresolved":false,"context_lines":[{"line_number":65,"context_line":"* Similar API for NBApi and DBStore (mostly for simplicity, readibility)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"* *Please add anything I missed.*"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"Proposed Change"},{"line_number":70,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_4cf9ec7f","line":68,"in_reply_to":"1a6eadb0_b91c80c2","updated":"2016-12-14 07:01:01.000000000","message":"Also need to refer to the upgrade scenario","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"6d2b26be2abfe57ccf08f5a6bb3f8581048db363","unresolved":false,"context_lines":[{"line_number":65,"context_line":"* Similar API for NBApi and DBStore (mostly for simplicity, readibility)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"* *Please add anything I missed.*"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"Proposed Change"},{"line_number":70,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_318a131c","line":68,"in_reply_to":"1a6eadb0_eeec6391","updated":"2016-12-15 02:06:26.000000000","message":"maybe we can make db-cli as a new sub-project, like python-dfclient? when we add dragonflow restful api in the future, we can expand this project to achieve a standard os-cli implementation.","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"5dbc62973e70560038a2204b7ce57b0ba7320804","unresolved":false,"context_lines":[{"line_number":74,"context_line":"Option 1"},{"line_number":75,"context_line":"--------"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"Have objects as attributes on nbapi and dbstore. Calling a method is as follows:"},{"line_number":78,"context_line":""},{"line_number":79,"context_line":"::"},{"line_number":80,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_398790d8","line":77,"range":{"start_line":77,"start_character":5,"end_line":77,"end_character":12},"updated":"2016-12-14 06:32:30.000000000","message":"like resources?","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"6311d26d19d296f2b368d1e4c527033267218289","unresolved":false,"context_lines":[{"line_number":74,"context_line":"Option 1"},{"line_number":75,"context_line":"--------"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"Have objects as attributes on nbapi and dbstore. Calling a method is as follows:"},{"line_number":78,"context_line":""},{"line_number":79,"context_line":"::"},{"line_number":80,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_8c56a4d0","line":77,"range":{"start_line":77,"start_character":5,"end_line":77,"end_character":12},"in_reply_to":"1a6eadb0_398790d8","updated":"2016-12-14 06:53:43.000000000","message":"Yes","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"5dbc62973e70560038a2204b7ce57b0ba7320804","unresolved":false,"context_lines":[{"line_number":85,"context_line":"    * Every object can provide its own methods when needed"},{"line_number":86,"context_line":"Cons:"},{"line_number":87,"context_line":"    * Manual registration for every model"},{"line_number":88,"context_line":"    * Namespace pollution"},{"line_number":89,"context_line":"    * Need to know attribute name of model (Can\u0027t use model\u0027s tablename const)"},{"line_number":90,"context_line":""},{"line_number":91,"context_line":"Option 2"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_d9605c38","line":88,"range":{"start_line":88,"start_character":6,"end_line":88,"end_character":25},"updated":"2016-12-14 06:32:30.000000000","message":"what do you mean by this?","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"6311d26d19d296f2b368d1e4c527033267218289","unresolved":false,"context_lines":[{"line_number":85,"context_line":"    * Every object can provide its own methods when needed"},{"line_number":86,"context_line":"Cons:"},{"line_number":87,"context_line":"    * Manual registration for every model"},{"line_number":88,"context_line":"    * Namespace pollution"},{"line_number":89,"context_line":"    * Need to know attribute name of model (Can\u0027t use model\u0027s tablename const)"},{"line_number":90,"context_line":""},{"line_number":91,"context_line":"Option 2"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_8c6dc49a","line":88,"range":{"start_line":88,"start_character":6,"end_line":88,"end_character":25},"in_reply_to":"1a6eadb0_d9605c38","updated":"2016-12-14 06:53:43.000000000","message":"e.g. NbApi has a publisher attribute. There is also a publisher model/resource. So the existing publisher attribute has to be renamed or moved.","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"5dbc62973e70560038a2204b7ce57b0ba7320804","unresolved":false,"context_lines":[{"line_number":86,"context_line":"Cons:"},{"line_number":87,"context_line":"    * Manual registration for every model"},{"line_number":88,"context_line":"    * Namespace pollution"},{"line_number":89,"context_line":"    * Need to know attribute name of model (Can\u0027t use model\u0027s tablename const)"},{"line_number":90,"context_line":""},{"line_number":91,"context_line":"Option 2"},{"line_number":92,"context_line":"--------"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_7950285f","line":89,"range":{"start_line":89,"start_character":6,"end_line":89,"end_character":78},"updated":"2016-12-14 06:32:30.000000000","message":"why knowing model is worse than knowing tablename?","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"6311d26d19d296f2b368d1e4c527033267218289","unresolved":false,"context_lines":[{"line_number":86,"context_line":"Cons:"},{"line_number":87,"context_line":"    * Manual registration for every model"},{"line_number":88,"context_line":"    * Namespace pollution"},{"line_number":89,"context_line":"    * Need to know attribute name of model (Can\u0027t use model\u0027s tablename const)"},{"line_number":90,"context_line":""},{"line_number":91,"context_line":"Option 2"},{"line_number":92,"context_line":"--------"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_ecbd58d8","line":89,"range":{"start_line":89,"start_character":6,"end_line":89,"end_character":78},"in_reply_to":"1a6eadb0_7950285f","updated":"2016-12-14 06:53:43.000000000","message":"A client developer needs to know that the LogicalPort model (resource) has the attribute name lport on NbApi. And it could easily have been e.g. lports, or logical_port. We will need a convention to map them, and the client developer will need to know the table name, not just the model.\n\nTo use the table name const, one has to write:\ngetattr(self.nb_api, \u003ctable name const\u003e), which defeats one of the purposes of this solution.","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":20287,"name":"hujie","email":"mike.hu@huawei.com","username":"hujie"},"change_message_id":"7092ae90a15c1bc9b0e3cf6af3584a3f9bf804c4","unresolved":false,"context_lines":[{"line_number":103,"context_line":"Cons:"},{"line_number":104,"context_line":"    * Every method type has to be placed on nb_api/db_store. Therefore, add_lrouter_port will exist on nb_api, but will only be relevant for lrouters."},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"Option 3"},{"line_number":107,"context_line":"--------"},{"line_number":108,"context_line":""},{"line_number":109,"context_line":"(My favorite)"},{"line_number":110,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_4f8abec0","line":107,"range":{"start_line":106,"start_character":0,"end_line":107,"end_character":8},"updated":"2016-12-14 07:52:40.000000000","message":"I think this is the best solution in these three:)","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"2ea97eda56473e909969526d6f8c3b7775197be5","unresolved":false,"context_lines":[{"line_number":103,"context_line":"Cons:"},{"line_number":104,"context_line":"    * Every method type has to be placed on nb_api/db_store. Therefore, add_lrouter_port will exist on nb_api, but will only be relevant for lrouters."},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"Option 3"},{"line_number":107,"context_line":"--------"},{"line_number":108,"context_line":""},{"line_number":109,"context_line":"(My favorite)"},{"line_number":110,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_655f960e","line":107,"range":{"start_line":106,"start_character":0,"end_line":107,"end_character":8},"in_reply_to":"1a6eadb0_4f8abec0","updated":"2016-12-14 10:03:11.000000000","message":"I think this and option 2 are quite similar in the way they work, this is a bit nicer because model name and the actual parameters are placed in different parentheses.","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":23235,"name":"Lihi Wishnitzer","email":"lihiwish@gmail.com","username":"lihiwish"},"change_message_id":"d66453eb248c36190004e69a168573aa3b11c64b","unresolved":false,"context_lines":[{"line_number":103,"context_line":"Cons:"},{"line_number":104,"context_line":"    * Every method type has to be placed on nb_api/db_store. Therefore, add_lrouter_port will exist on nb_api, but will only be relevant for lrouters."},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"Option 3"},{"line_number":107,"context_line":"--------"},{"line_number":108,"context_line":""},{"line_number":109,"context_line":"(My favorite)"},{"line_number":110,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_45752896","line":107,"range":{"start_line":106,"start_character":0,"end_line":107,"end_character":8},"in_reply_to":"1a6eadb0_655f960e","updated":"2016-12-14 15:25:25.000000000","message":"I agree. This seems like the better option","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"6d2b26be2abfe57ccf08f5a6bb3f8581048db363","unresolved":false,"context_lines":[{"line_number":113,"context_line":""},{"line_number":114,"context_line":"::"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"    self.nb_api.get_resource(\u0027lport\u0027).create(...)"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"Pros:"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_91ea07ab","line":116,"range":{"start_line":116,"start_character":3,"end_line":116,"end_character":49},"updated":"2016-12-15 02:06:26.000000000","message":"+1","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"b08329165f6e7d92cfc5a61cf3a1130e12937cdd","unresolved":false,"context_lines":[{"line_number":113,"context_line":""},{"line_number":114,"context_line":"::"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"    self.nb_api.get_resource(\u0027lport\u0027).create(...)"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"Pros:"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_13139a0e","line":116,"updated":"2016-12-14 01:39:11.000000000","message":"I like this option. You have pointed out the pros. And the cons seems to be less pain.","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":20287,"name":"hujie","email":"mike.hu@huawei.com","username":"hujie"},"change_message_id":"7092ae90a15c1bc9b0e3cf6af3584a3f9bf804c4","unresolved":false,"context_lines":[{"line_number":113,"context_line":""},{"line_number":114,"context_line":"::"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"    self.nb_api.get_resource(\u0027lport\u0027).create(...)"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"Pros:"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_4a146c43","line":116,"range":{"start_line":116,"start_character":16,"end_line":116,"end_character":28},"updated":"2016-12-14 07:52:40.000000000","message":"So nb_api and db_store just need to provide their own get_resource method and remove all the current crud code, right?","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":20297,"name":"duankebo","email":"duankebo@huawei.com","username":"duankebo"},"change_message_id":"3828734b89a934a311b8d5d1945b9342919d3642","unresolved":false,"context_lines":[{"line_number":113,"context_line":""},{"line_number":114,"context_line":"::"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"    self.nb_api.get_resource(\u0027lport\u0027).create(...)"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"Pros:"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_5cbfdffa","line":116,"in_reply_to":"1a6eadb0_13139a0e","updated":"2016-12-14 03:21:55.000000000","message":"+1\nbtw: I suggest we should be very cautious to do refectory like this, for it effects lots of components.","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"8217569c3695dbef2fef7d7c20822c83eb390ccc","unresolved":false,"context_lines":[{"line_number":113,"context_line":""},{"line_number":114,"context_line":"::"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"    self.nb_api.get_resource(\u0027lport\u0027).create(...)"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"Pros:"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_8283c855","line":116,"range":{"start_line":116,"start_character":16,"end_line":116,"end_character":28},"in_reply_to":"1a6eadb0_4a146c43","updated":"2016-12-14 09:37:47.000000000","message":"That\u0027s the general idea, yes. But we have to see exactly how this will be provided,","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"6311d26d19d296f2b368d1e4c527033267218289","unresolved":false,"context_lines":[{"line_number":113,"context_line":""},{"line_number":114,"context_line":"::"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"    self.nb_api.get_resource(\u0027lport\u0027).create(...)"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"Pros:"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_cca17cab","line":116,"in_reply_to":"1a6eadb0_5cbfdffa","updated":"2016-12-14 06:53:43.000000000","message":"See line 109 :)\n\n@duankebo, this is how we ended up needing a spec in the first place.","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"5dbc62973e70560038a2204b7ce57b0ba7320804","unresolved":false,"context_lines":[{"line_number":120,"context_line":"    * Every object can provide its own methods when needed"},{"line_number":121,"context_line":"    * Table name constant on model can be used"},{"line_number":122,"context_line":"    * Model registration can be automatic, and models can provide their own \u0027CRUD helper\u0027"},{"line_number":123,"context_line":"    * synactic sugars such as nb_api.create can be used for well-known operations (e.g. create, get, update, delete)"},{"line_number":124,"context_line":"Cons:"},{"line_number":125,"context_line":"    * Very long line to do a single operation"},{"line_number":126,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_d9bcdc6e","line":123,"range":{"start_line":123,"start_character":6,"end_line":123,"end_character":14},"updated":"2016-12-14 06:32:30.000000000","message":"syntactic","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"5dbc62973e70560038a2204b7ce57b0ba7320804","unresolved":false,"context_lines":[{"line_number":122,"context_line":"    * Model registration can be automatic, and models can provide their own \u0027CRUD helper\u0027"},{"line_number":123,"context_line":"    * synactic sugars such as nb_api.create can be used for well-known operations (e.g. create, get, update, delete)"},{"line_number":124,"context_line":"Cons:"},{"line_number":125,"context_line":"    * Very long line to do a single operation"},{"line_number":126,"context_line":""},{"line_number":127,"context_line":"This model can be used to promote dynamic registration: Upon import,"},{"line_number":128,"context_line":"the model registres itself to a global store, providing a CRUD Object"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_d963fc18","line":125,"range":{"start_line":125,"start_character":6,"end_line":125,"end_character":45},"updated":"2016-12-14 06:32:30.000000000","message":"performance wise?","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"6311d26d19d296f2b368d1e4c527033267218289","unresolved":false,"context_lines":[{"line_number":122,"context_line":"    * Model registration can be automatic, and models can provide their own \u0027CRUD helper\u0027"},{"line_number":123,"context_line":"    * synactic sugars such as nb_api.create can be used for well-known operations (e.g. create, get, update, delete)"},{"line_number":124,"context_line":"Cons:"},{"line_number":125,"context_line":"    * Very long line to do a single operation"},{"line_number":126,"context_line":""},{"line_number":127,"context_line":"This model can be used to promote dynamic registration: Upon import,"},{"line_number":128,"context_line":"the model registres itself to a global store, providing a CRUD Object"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_6cca2870","line":125,"range":{"start_line":125,"start_character":6,"end_line":125,"end_character":45},"in_reply_to":"1a6eadb0_d963fc18","updated":"2016-12-14 06:53:43.000000000","message":"We\u0027re writing in python. If we want performance, this is the least of our problems :)","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":20287,"name":"hujie","email":"mike.hu@huawei.com","username":"hujie"},"change_message_id":"7092ae90a15c1bc9b0e3cf6af3584a3f9bf804c4","unresolved":false,"context_lines":[{"line_number":130,"context_line":"additional functionality where needed. Basic functions are then provided"},{"line_number":131,"context_line":"by the NBApi/DBStore, for the actual read/write to the NBDB and cache."},{"line_number":132,"context_line":""},{"line_number":133,"context_line":"Need to think on how to add support for cache searching and indexing."},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"References"},{"line_number":136,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_2aaf3095","line":133,"range":{"start_line":133,"start_character":40,"end_line":133,"end_character":68},"updated":"2016-12-14 07:52:40.000000000","message":"Maybe we need a new CacheManager module.","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"8217569c3695dbef2fef7d7c20822c83eb390ccc","unresolved":false,"context_lines":[{"line_number":130,"context_line":"additional functionality where needed. Basic functions are then provided"},{"line_number":131,"context_line":"by the NBApi/DBStore, for the actual read/write to the NBDB and cache."},{"line_number":132,"context_line":""},{"line_number":133,"context_line":"Need to think on how to add support for cache searching and indexing."},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"References"},{"line_number":136,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_825f48e4","line":133,"range":{"start_line":133,"start_character":40,"end_line":133,"end_character":68},"in_reply_to":"1a6eadb0_2aaf3095","updated":"2016-12-14 09:37:47.000000000","message":"Very possible. We need to see how much logic is planned to go into DBStore, and then see what has to/can be/should be moved out.","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"1ed926fa589867bfcc2524a8e9441e88d06573f5","unresolved":false,"context_lines":[{"line_number":130,"context_line":"additional functionality where needed. Basic functions are then provided"},{"line_number":131,"context_line":"by the NBApi/DBStore, for the actual read/write to the NBDB and cache."},{"line_number":132,"context_line":""},{"line_number":133,"context_line":"Need to think on how to add support for cache searching and indexing."},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"References"},{"line_number":136,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_e19c435f","line":133,"range":{"start_line":133,"start_character":40,"end_line":133,"end_character":68},"in_reply_to":"1a6eadb0_825f48e4","updated":"2016-12-15 08:24:42.000000000","message":"Maybe there is any external code we can use instead that has querying capabilities (like SqlAlchemy or Django\u0027s QuerySet over in-memory sqlite3)","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"2ea97eda56473e909969526d6f8c3b7775197be5","unresolved":false,"context_lines":[{"line_number":131,"context_line":"by the NBApi/DBStore, for the actual read/write to the NBDB and cache."},{"line_number":132,"context_line":""},{"line_number":133,"context_line":"Need to think on how to add support for cache searching and indexing."},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"References"},{"line_number":136,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":137,"context_line":"None"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_c5130a65","line":134,"updated":"2016-12-14 10:03:11.000000000","message":"One thing I think this spec skips upon is the code separation part, which is a major issue right now because adding a model requires changes all over the code.\n\nIf we pick either option 2 or 3, we can take the knowledge of specific CRUD objects away from NbAPI/DbStore, and only have a very simple function (e.g. for option 3):\n\n def get_resource(self, model):\n     return model.crud_nb_api(self)\n\nAnd have each Db model define 2 attributes, one for NbAPI crud class and one for DbStore CRUD:\n\n class SomeModel(NbDbObject):\n     crud_nb_api \u003d SomeCrudNbApi\n     crud_db_store \u003d SomeCrudDbStore\n     ...\n\nThose CRUD classes can be in their own module, or located beside the models, or even as nested classes (which makes some sense because the crud class is specific to the model itself)\n\nThis way, the knowledge of how the object is operated on is placed into its class, and NbApi/DbStore don\u0027t need to handle any part of it. If the object requires any special treatment, we can specialize its relevant crud class. In case we don\u0027t have any special treatment, we don\u0027t have to specify a thing since it will be inherited from the parent class.","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"cefd06b4a7c6be05fb764a80f17965c6f75df50d","unresolved":false,"context_lines":[{"line_number":131,"context_line":"by the NBApi/DBStore, for the actual read/write to the NBDB and cache."},{"line_number":132,"context_line":""},{"line_number":133,"context_line":"Need to think on how to add support for cache searching and indexing."},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"References"},{"line_number":136,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":137,"context_line":"None"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_77f0f167","line":134,"in_reply_to":"1a6eadb0_57007e01","updated":"2016-12-15 09:22:46.000000000","message":"+1","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":23235,"name":"Lihi Wishnitzer","email":"lihiwish@gmail.com","username":"lihiwish"},"change_message_id":"d66453eb248c36190004e69a168573aa3b11c64b","unresolved":false,"context_lines":[{"line_number":131,"context_line":"by the NBApi/DBStore, for the actual read/write to the NBDB and cache."},{"line_number":132,"context_line":""},{"line_number":133,"context_line":"Need to think on how to add support for cache searching and indexing."},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"References"},{"line_number":136,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":137,"context_line":"None"}],"source_content_type":"text/x-rst","patch_set":1,"id":"1a6eadb0_57007e01","line":134,"in_reply_to":"1a6eadb0_c5130a65","updated":"2016-12-14 15:25:25.000000000","message":"+1","commit_id":"c125ba10f0b05ac965c941634c9fb894d4a80e4d"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"54ce9e71c868cffb5dbac34997885596d968cfb5","unresolved":false,"context_lines":[{"line_number":4,"context_line":""},{"line_number":5,"context_line":" http://creativecommons.org/licenses/by/3.0/legalcode"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":8,"context_line":"North Bound Code Refactor"},{"line_number":9,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":10,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_abe1d49c","line":7,"range":{"start_line":7,"start_character":23,"end_line":7,"end_character":25},"updated":"2016-12-19 02:08:08.000000000","message":"format?","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"54ce9e71c868cffb5dbac34997885596d968cfb5","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":8,"context_line":"North Bound Code Refactor"},{"line_number":9,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"In this (informal) spec we will discuss the North Bound API, and how we want it to look."},{"line_number":12,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_cbec5095","line":9,"range":{"start_line":9,"start_character":23,"end_line":9,"end_character":25},"updated":"2016-12-19 02:08:08.000000000","message":"ditto","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"f1027510b3e2e65f282d5db931ea742ced6277e6","unresolved":false,"context_lines":[{"line_number":106,"context_line":""},{"line_number":107,"context_line":"This model can be used to promote dynamic registration: Upon import,"},{"line_number":108,"context_line":"the model registres itself to a global store, providing a CRUD Object"},{"line_number":109,"context_line":"for NBApi and a CRUDObject for DBStore.  These CRUD objects can include"},{"line_number":110,"context_line":"additional functionality where needed. Basic functions are then provided"},{"line_number":111,"context_line":"by the NBApi/DBStore, for the actual read/write to the NBDB and cache."},{"line_number":112,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_2616db55","line":109,"range":{"start_line":109,"start_character":16,"end_line":109,"end_character":26},"updated":"2016-12-19 03:20:34.000000000","message":"CRUD Object?","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"f1027510b3e2e65f282d5db931ea742ced6277e6","unresolved":false,"context_lines":[{"line_number":107,"context_line":"This model can be used to promote dynamic registration: Upon import,"},{"line_number":108,"context_line":"the model registres itself to a global store, providing a CRUD Object"},{"line_number":109,"context_line":"for NBApi and a CRUDObject for DBStore.  These CRUD objects can include"},{"line_number":110,"context_line":"additional functionality where needed. Basic functions are then provided"},{"line_number":111,"context_line":"by the NBApi/DBStore, for the actual read/write to the NBDB and cache."},{"line_number":112,"context_line":""},{"line_number":113,"context_line":"Model Definition"}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_610fdd2e","line":110,"updated":"2016-12-19 03:20:34.000000000","message":"The common functionality will be maintained in a common class, for example a CRUD base class, right?","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"4edd75f9918e4483d52552775430dd869f464725","unresolved":false,"context_lines":[{"line_number":107,"context_line":"This model can be used to promote dynamic registration: Upon import,"},{"line_number":108,"context_line":"the model registres itself to a global store, providing a CRUD Object"},{"line_number":109,"context_line":"for NBApi and a CRUDObject for DBStore.  These CRUD objects can include"},{"line_number":110,"context_line":"additional functionality where needed. Basic functions are then provided"},{"line_number":111,"context_line":"by the NBApi/DBStore, for the actual read/write to the NBDB and cache."},{"line_number":112,"context_line":""},{"line_number":113,"context_line":"Model Definition"}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_8836d9e5","line":110,"in_reply_to":"1a6eadb0_610fdd2e","updated":"2016-12-19 04:59:38.000000000","message":"Yes. Will add.","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"f1027510b3e2e65f282d5db931ea742ced6277e6","unresolved":false,"context_lines":[{"line_number":119,"context_line":""},{"line_number":120,"context_line":"    @register_model"},{"line_number":121,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":122,"context_line":"        # If different from what\u0027s provided by the mixins"},{"line_number":123,"context_line":"        crud_nb_api \u003d \u003cCRUD Helper\u003e"},{"line_number":124,"context_line":"        # Events definition will go here"},{"line_number":125,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_41dca174","line":122,"range":{"start_line":122,"start_character":10,"end_line":122,"end_character":22},"updated":"2016-12-19 03:20:34.000000000","message":"reword?","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"4edd75f9918e4483d52552775430dd869f464725","unresolved":false,"context_lines":[{"line_number":119,"context_line":""},{"line_number":120,"context_line":"    @register_model"},{"line_number":121,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":122,"context_line":"        # If different from what\u0027s provided by the mixins"},{"line_number":123,"context_line":"        crud_nb_api \u003d \u003cCRUD Helper\u003e"},{"line_number":124,"context_line":"        # Events definition will go here"},{"line_number":125,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_c830d1eb","line":122,"range":{"start_line":122,"start_character":10,"end_line":122,"end_character":22},"in_reply_to":"1a6eadb0_41dca174","updated":"2016-12-19 04:59:38.000000000","message":"I\u0027ll remove. It\u0027s explained below anyway.","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"2b87722ab82268de37f9082a7718f4b62348a173","unresolved":false,"context_lines":[{"line_number":126,"context_line":"        indexes \u003d [\u0027\u003c"},{"line_number":127,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"\u003cModelBaseClass\u003e will be a base class all mdoels inherit."},{"line_number":130,"context_line":""},{"line_number":131,"context_line":"Models will be registered via the `register_model` method. This method can be"},{"line_number":132,"context_line":"used as a decorator, or called directly with the model."}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_5709b0dc","line":129,"range":{"start_line":129,"start_character":42,"end_line":129,"end_character":48},"updated":"2016-12-19 11:36:08.000000000","message":"typo","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"f1027510b3e2e65f282d5db931ea742ced6277e6","unresolved":false,"context_lines":[{"line_number":129,"context_line":"\u003cModelBaseClass\u003e will be a base class all mdoels inherit."},{"line_number":130,"context_line":""},{"line_number":131,"context_line":"Models will be registered via the `register_model` method. This method can be"},{"line_number":132,"context_line":"used as a decorator, or called directly with the model."},{"line_number":133,"context_line":""},{"line_number":134,"context_line":"\u003cModelMixins\u003e can be used to add additional recurring features to the model."},{"line_number":135,"context_line":"For instance, a unique key."}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_c19991d2","line":132,"range":{"start_line":132,"start_character":20,"end_line":132,"end_character":54},"updated":"2016-12-19 03:20:34.000000000","message":"I found it is hard to register a class in its static code. In static code of the class, the class object has not been created by interpreter yet. Maybe using a decorator is more appropriate.","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"4edd75f9918e4483d52552775430dd869f464725","unresolved":false,"context_lines":[{"line_number":129,"context_line":"\u003cModelBaseClass\u003e will be a base class all mdoels inherit."},{"line_number":130,"context_line":""},{"line_number":131,"context_line":"Models will be registered via the `register_model` method. This method can be"},{"line_number":132,"context_line":"used as a decorator, or called directly with the model."},{"line_number":133,"context_line":""},{"line_number":134,"context_line":"\u003cModelMixins\u003e can be used to add additional recurring features to the model."},{"line_number":135,"context_line":"For instance, a unique key."}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_e872edaf","line":132,"range":{"start_line":132,"start_character":20,"end_line":132,"end_character":54},"in_reply_to":"1a6eadb0_c19991d2","updated":"2016-12-19 04:59:38.000000000","message":"Yes. I gave it some thought too. External modules will have to add themselves to a configuration file to be loaded. I\u0027ll add that info.\n\nThe same function can be used both as decorator and registration function, so I don\u0027t think there is a lot of overhead here.","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"2b87722ab82268de37f9082a7718f4b62348a173","unresolved":false,"context_lines":[{"line_number":134,"context_line":"\u003cModelMixins\u003e can be used to add additional recurring features to the model."},{"line_number":135,"context_line":"For instance, a unique key."},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"The class field `crud_nb_api` will hold a getter for a CRUD helper object."},{"line_number":138,"context_line":"The CRUD helper object will contain create, get, update, and delete methods, as"},{"line_number":139,"context_line":"well as any other methods provided by the model (e.g. associate and"},{"line_number":140,"context_line":"disassociate floating IPs)."},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"The getter received an instance of the NB API, so that it will be able to"},{"line_number":143,"context_line":"interact with the database driver. It may be any callable accepting exactly"},{"line_number":144,"context_line":"one parameter."},{"line_number":145,"context_line":""},{"line_number":146,"context_line":"Nb Api\u0027s new `get_resource` method will call \u003cModel\u003e\u0027s `crud_nb_api` with"},{"line_number":147,"context_line":"itself as the only parameter."},{"line_number":148,"context_line":""},{"line_number":149,"context_line":"\u003cModelBaseClass\u003e will hold a basic CRUD helper, providing the four basic CRUD"},{"line_number":150,"context_line":"methods: `create`, `get`, `update`, and `delete`. A \u003cModelMixin\u003e may override"},{"line_number":151,"context_line":"this field to provide a CRUD helper with additional methods."},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"The class field `crud_cache` will hold a getter for a DB Store helper object."},{"line_number":154,"context_line":"The DB Store helper object will container create, get, update, and delete"}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_b794c444","line":151,"range":{"start_line":137,"start_character":0,"end_line":151,"end_character":60},"updated":"2016-12-19 11:36:08.000000000","message":"pseudocode can be helpful here","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"f1027510b3e2e65f282d5db931ea742ced6277e6","unresolved":false,"context_lines":[{"line_number":150,"context_line":"methods: `create`, `get`, `update`, and `delete`. A \u003cModelMixin\u003e may override"},{"line_number":151,"context_line":"this field to provide a CRUD helper with additional methods."},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"The class field `crud_cache` will hold a getter for a DB Store helper object."},{"line_number":154,"context_line":"The DB Store helper object will container create, get, update, and delete"},{"line_number":155,"context_line":"methods, as well as indexing and searching information {TODO: How?}"},{"line_number":156,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_c1cef1b6","line":153,"range":{"start_line":153,"start_character":17,"end_line":153,"end_character":27},"updated":"2016-12-19 03:20:34.000000000","message":"This field is not mentioned in above example.","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"4edd75f9918e4483d52552775430dd869f464725","unresolved":false,"context_lines":[{"line_number":150,"context_line":"methods: `create`, `get`, `update`, and `delete`. A \u003cModelMixin\u003e may override"},{"line_number":151,"context_line":"this field to provide a CRUD helper with additional methods."},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"The class field `crud_cache` will hold a getter for a DB Store helper object."},{"line_number":154,"context_line":"The DB Store helper object will container create, get, update, and delete"},{"line_number":155,"context_line":"methods, as well as indexing and searching information {TODO: How?}"},{"line_number":156,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_6867bdea","line":153,"range":{"start_line":153,"start_character":17,"end_line":153,"end_character":27},"in_reply_to":"1a6eadb0_c1cef1b6","updated":"2016-12-19 04:59:38.000000000","message":"Yes. It\u0027s from an earlier draft. Will reword.","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"f1027510b3e2e65f282d5db931ea742ced6277e6","unresolved":false,"context_lines":[{"line_number":151,"context_line":"this field to provide a CRUD helper with additional methods."},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"The class field `crud_cache` will hold a getter for a DB Store helper object."},{"line_number":154,"context_line":"The DB Store helper object will container create, get, update, and delete"},{"line_number":155,"context_line":"methods, as well as indexing and searching information {TODO: How?}"},{"line_number":156,"context_line":""},{"line_number":157,"context_line":"To support dynamic definition of events, i.e. to allow each model to define its"}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_61d99d83","line":154,"range":{"start_line":154,"start_character":32,"end_line":154,"end_character":41},"updated":"2016-12-19 03:20:34.000000000","message":"contain?","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"2b87722ab82268de37f9082a7718f4b62348a173","unresolved":false,"context_lines":[{"line_number":158,"context_line":"events, there will be an `events` class field. It will be defined in greater"},{"line_number":159,"context_line":"detail upon southbound refactor."},{"line_number":160,"context_line":""},{"line_number":161,"context_line":"The class field `fields` will hold a list of fields available on the object."},{"line_number":162,"context_line":"getter functions can be generated automatically, in the form of"},{"line_number":163,"context_line":"`get_\u003cfieldname\u003e` for every field in `fields`, unless such a method already"},{"line_number":164,"context_line":"exists. The representation of the field is transparent to the model definition,"}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_1773b84e","line":161,"range":{"start_line":161,"start_character":17,"end_line":161,"end_character":23},"updated":"2016-12-19 11:36:08.000000000","message":"what about type of the field and validation ?","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"f1027510b3e2e65f282d5db931ea742ced6277e6","unresolved":false,"context_lines":[{"line_number":173,"context_line":""},{"line_number":174,"context_line":"::"},{"line_number":175,"context_line":""},{"line_number":176,"context_line":"    def create(self, table_name, **columns):"},{"line_number":177,"context_line":"        resource \u003d self.get_resource(table_name)"},{"line_number":178,"context_line":"        crud_nb_api \u003d resource.crud_nb_api(self)"},{"line_number":179,"context_line":"        return crud_nb_api.create(columns)"},{"line_number":180,"context_line":""},{"line_number":181,"context_line":"Searching and Indexing"},{"line_number":182,"context_line":"----------------------"}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_816b1985","line":179,"range":{"start_line":176,"start_character":0,"end_line":179,"end_character":42},"updated":"2016-12-19 03:20:34.000000000","message":"Will this be necessary if we already have this\n\n self.nb_api.get_resource(\u0027lport\u0027).create(...)","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"4edd75f9918e4483d52552775430dd869f464725","unresolved":false,"context_lines":[{"line_number":173,"context_line":""},{"line_number":174,"context_line":"::"},{"line_number":175,"context_line":""},{"line_number":176,"context_line":"    def create(self, table_name, **columns):"},{"line_number":177,"context_line":"        resource \u003d self.get_resource(table_name)"},{"line_number":178,"context_line":"        crud_nb_api \u003d resource.crud_nb_api(self)"},{"line_number":179,"context_line":"        return crud_nb_api.create(columns)"},{"line_number":180,"context_line":""},{"line_number":181,"context_line":"Searching and Indexing"},{"line_number":182,"context_line":"----------------------"}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_e8e74d44","line":179,"range":{"start_line":176,"start_character":0,"end_line":179,"end_character":42},"in_reply_to":"1a6eadb0_816b1985","updated":"2016-12-19 04:59:38.000000000","message":"No. It\u0027s there as a syntactic sugar (of sorts) to make the calling code a bit simpler/shorter in the common case.","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"2b87722ab82268de37f9082a7718f4b62348a173","unresolved":false,"context_lines":[{"line_number":204,"context_line":""},{"line_number":205,"context_line":"For these requirements, it is enough to define on a model the fields by which"},{"line_number":206,"context_line":"it will be filtered. The internal DB store implementation will index the cached"},{"line_number":207,"context_line":"instances by these fields (even if they are nested), and upon request use thse"},{"line_number":208,"context_line":"fields to extract the relevant instance."},{"line_number":209,"context_line":""},{"line_number":210,"context_line":"Guiding Example"}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_37dc3418","line":207,"range":{"start_line":207,"start_character":74,"end_line":207,"end_character":78},"updated":"2016-12-19 11:36:08.000000000","message":"typo","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"54ce9e71c868cffb5dbac34997885596d968cfb5","unresolved":false,"context_lines":[{"line_number":223,"context_line":"Proposed Implementation"},{"line_number":224,"context_line":"~~~~~~~~~~~~~~~~~~~~~~~"},{"line_number":225,"context_line":""},{"line_number":226,"context_line":"The DB Store will have, for each model, a map from instance\u0027s `id` to"},{"line_number":227,"context_line":"its object. For each direct indexing field (e.g. `topic` in the example"},{"line_number":228,"context_line":"above), the DB Store will hold a map from the indexed field to a list"},{"line_number":229,"context_line":"of objects with that field\u0027s value. Since the objects are stored by"}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_0bb5687d","line":226,"range":{"start_line":226,"start_character":4,"end_line":226,"end_character":12},"updated":"2016-12-19 02:08:08.000000000","message":"Could we take advantage of sqlite in-memory db to construct our db store?\nhttps://sqlite.org/inmemorydb.html\nAs a result, we can easily CRUD our db store and do indexing as well.","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"4edd75f9918e4483d52552775430dd869f464725","unresolved":false,"context_lines":[{"line_number":223,"context_line":"Proposed Implementation"},{"line_number":224,"context_line":"~~~~~~~~~~~~~~~~~~~~~~~"},{"line_number":225,"context_line":""},{"line_number":226,"context_line":"The DB Store will have, for each model, a map from instance\u0027s `id` to"},{"line_number":227,"context_line":"its object. For each direct indexing field (e.g. `topic` in the example"},{"line_number":228,"context_line":"above), the DB Store will hold a map from the indexed field to a list"},{"line_number":229,"context_line":"of objects with that field\u0027s value. Since the objects are stored by"}],"source_content_type":"text/x-rst","patch_set":2,"id":"1a6eadb0_68c33d8b","line":226,"range":{"start_line":226,"start_character":4,"end_line":226,"end_character":12},"in_reply_to":"1a6eadb0_0bb5687d","updated":"2016-12-19 04:59:38.000000000","message":"I considered that. But sqlite stores information as strings, and in this case I want to store objects. I guess I could serialise and de-serialise the objects upon read and write, but I am not sure that would make things better.\n\nAs I mention below, the implementation can be changed. Maybe we can write both and compare performance (e.g. using Rally)?","commit_id":"6731b65476e496c5357978e777bbec6f7f207853"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"cfa2fd2855658800e7d2c1c2627aae9e212f8dc8","unresolved":false,"context_lines":[{"line_number":108,"context_line":"    * Very long line to do a single operation"},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"This model can be used to promote dynamic registration: Upon import,"},{"line_number":111,"context_line":"the model registres itself to a global store, providing a CRUD Object"},{"line_number":112,"context_line":"for NBApi and a CRUD Object for DBStore."},{"line_number":113,"context_line":""},{"line_number":114,"context_line":"CRUD objects can include additional functionality where needed. Basic"}],"source_content_type":"text/x-rst","patch_set":3,"id":"1a6eadb0_c44a7555","line":111,"range":{"start_line":111,"start_character":10,"end_line":111,"end_character":19},"updated":"2016-12-19 09:56:02.000000000","message":"registers","commit_id":"84fb80403186debb9ad975fdd1b51e0628c23c1a"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"cfa2fd2855658800e7d2c1c2627aae9e212f8dc8","unresolved":false,"context_lines":[{"line_number":130,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":131,"context_line":"        # If different from what\u0027s provided by the mixins"},{"line_number":132,"context_line":"        crud_nb_api \u003d \u003cCRUD Helper\u003e"},{"line_number":133,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"},{"line_number":134,"context_line":"        nested \u003d [\u0027\u003cNestedModel1\u003e\u0027, ...]"},{"line_number":135,"context_line":"        indexes \u003d [\u0027\u003cIndexedField1\u003e\u0027, ...]"},{"line_number":136,"context_line":"        # Events definition will go here"}],"source_content_type":"text/x-rst","patch_set":3,"id":"1a6eadb0_84679de9","line":133,"range":{"start_line":133,"start_character":8,"end_line":133,"end_character":65},"updated":"2016-12-19 09:56:02.000000000","message":"Implementation wise, needs to collect fields from all the ancestor classes, right?","commit_id":"84fb80403186debb9ad975fdd1b51e0628c23c1a"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"6360533d2add584a13a59ad37e79de2882fc1025","unresolved":false,"context_lines":[{"line_number":130,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":131,"context_line":"        # If different from what\u0027s provided by the mixins"},{"line_number":132,"context_line":"        crud_nb_api \u003d \u003cCRUD Helper\u003e"},{"line_number":133,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"},{"line_number":134,"context_line":"        nested \u003d [\u0027\u003cNestedModel1\u003e\u0027, ...]"},{"line_number":135,"context_line":"        indexes \u003d [\u0027\u003cIndexedField1\u003e\u0027, ...]"},{"line_number":136,"context_line":"        # Events definition will go here"}],"source_content_type":"text/x-rst","patch_set":3,"id":"1a6eadb0_da5a4550","line":133,"range":{"start_line":133,"start_character":8,"end_line":133,"end_character":65},"in_reply_to":"1a6eadb0_84679de9","updated":"2016-12-19 12:09:10.000000000","message":"Yes.","commit_id":"84fb80403186debb9ad975fdd1b51e0628c23c1a"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"054108110bc6e7634dcddc19c1f841841179c072","unresolved":false,"context_lines":[{"line_number":136,"context_line":"        # Events definition will go here"},{"line_number":137,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":138,"context_line":""},{"line_number":139,"context_line":"\u003cModelBaseClass\u003e will be a base class all mdoels inherit."},{"line_number":140,"context_line":""},{"line_number":141,"context_line":"Models will be registered via the `register_model` method. This method can be"},{"line_number":142,"context_line":"used as a decorator, or called directly with the model."}],"source_content_type":"text/x-rst","patch_set":3,"id":"1a6eadb0_3f025570","line":139,"range":{"start_line":139,"start_character":42,"end_line":139,"end_character":48},"updated":"2016-12-19 08:11:33.000000000","message":"models","commit_id":"84fb80403186debb9ad975fdd1b51e0628c23c1a"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"cfa2fd2855658800e7d2c1c2627aae9e212f8dc8","unresolved":false,"context_lines":[{"line_number":152,"context_line":"well as any other methods provided by the model (e.g. associate and"},{"line_number":153,"context_line":"disassociate floating IPs)."},{"line_number":154,"context_line":""},{"line_number":155,"context_line":"The getter received an instance of the NB API, so that it will be able to"},{"line_number":156,"context_line":"interact with the database driver. It may be any callable accepting exactly"},{"line_number":157,"context_line":"one parameter."},{"line_number":158,"context_line":""}],"source_content_type":"text/x-rst","patch_set":3,"id":"1a6eadb0_c48fd573","line":155,"range":{"start_line":155,"start_character":0,"end_line":155,"end_character":10},"updated":"2016-12-19 09:56:02.000000000","message":"Getter of what?","commit_id":"84fb80403186debb9ad975fdd1b51e0628c23c1a"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"054108110bc6e7634dcddc19c1f841841179c072","unresolved":false,"context_lines":[{"line_number":164,"context_line":"this field to provide a CRUD helper with additional methods."},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"The class field `fields` will hold a list of fields available on the object."},{"line_number":167,"context_line":"getter functions can be generated automatically, in the form of"},{"line_number":168,"context_line":"`get_\u003cfieldname\u003e` for every field in `fields`, unless such a method already"},{"line_number":169,"context_line":"exists. The representation of the field is transparent to the model definition,"},{"line_number":170,"context_line":"provided it can natively be serialised using e.g. jsonutils or msgpack."},{"line_number":171,"context_line":""}],"source_content_type":"text/x-rst","patch_set":3,"id":"1a6eadb0_7ffe8d39","line":168,"range":{"start_line":167,"start_character":49,"end_line":168,"end_character":18},"updated":"2016-12-19 08:11:33.000000000","message":"what if we want to rename fields between the code and their existing name in the nb db or wrap the result in a new type?","commit_id":"84fb80403186debb9ad975fdd1b51e0628c23c1a"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"3445fa769630467795932b7cf399514883e6019a","unresolved":false,"context_lines":[{"line_number":164,"context_line":"this field to provide a CRUD helper with additional methods."},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"The class field `fields` will hold a list of fields available on the object."},{"line_number":167,"context_line":"getter functions can be generated automatically, in the form of"},{"line_number":168,"context_line":"`get_\u003cfieldname\u003e` for every field in `fields`, unless such a method already"},{"line_number":169,"context_line":"exists. The representation of the field is transparent to the model definition,"},{"line_number":170,"context_line":"provided it can natively be serialised using e.g. jsonutils or msgpack."},{"line_number":171,"context_line":""}],"source_content_type":"text/x-rst","patch_set":3,"id":"1a6eadb0_3aa34351","line":168,"range":{"start_line":167,"start_character":49,"end_line":168,"end_character":18},"in_reply_to":"1a6eadb0_7ffe8d39","updated":"2016-12-19 08:28:37.000000000","message":"\u003e The class can be extended with additional or overriding methods, if necessary. (Line 191)\n\nThis way, a method with a new name, or overriding the logic by adding an adaptor, can be used.","commit_id":"84fb80403186debb9ad975fdd1b51e0628c23c1a"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"cfa2fd2855658800e7d2c1c2627aae9e212f8dc8","unresolved":false,"context_lines":[{"line_number":169,"context_line":"exists. The representation of the field is transparent to the model definition,"},{"line_number":170,"context_line":"provided it can natively be serialised using e.g. jsonutils or msgpack."},{"line_number":171,"context_line":""},{"line_number":172,"context_line":"The class field `nested` will hold a dictionary of field name to model class."},{"line_number":173,"context_line":"The meaning here is that the field value will be an instance of that model."},{"line_number":174,"context_line":"This allows resources to contain other resources, e.g. routers and their ports,"},{"line_number":175,"context_line":"or security groups and their rules. This will also allow splitting nested"},{"line_number":176,"context_line":"resources into separate NB tables, if desired."},{"line_number":177,"context_line":""},{"line_number":178,"context_line":"Nested resources are \u0027owned\u0027 by their parents. Therefore, this relationship is"},{"line_number":179,"context_line":"only suitable for a 1-to-1 or 1-to-many relation.  many-to-many relations"}],"source_content_type":"text/x-rst","patch_set":3,"id":"1a6eadb0_a4cad96c","line":176,"range":{"start_line":172,"start_character":0,"end_line":176,"end_character":46},"updated":"2016-12-19 09:56:02.000000000","message":"Any way to signify if the nested field is singular or plural?","commit_id":"84fb80403186debb9ad975fdd1b51e0628c23c1a"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"9911ff9034cc474cb56099e62914baa75688ae16","unresolved":false,"context_lines":[{"line_number":169,"context_line":"exists. The representation of the field is transparent to the model definition,"},{"line_number":170,"context_line":"provided it can natively be serialised using e.g. jsonutils or msgpack."},{"line_number":171,"context_line":""},{"line_number":172,"context_line":"The class field `nested` will hold a dictionary of field name to model class."},{"line_number":173,"context_line":"The meaning here is that the field value will be an instance of that model."},{"line_number":174,"context_line":"This allows resources to contain other resources, e.g. routers and their ports,"},{"line_number":175,"context_line":"or security groups and their rules. This will also allow splitting nested"},{"line_number":176,"context_line":"resources into separate NB tables, if desired."},{"line_number":177,"context_line":""},{"line_number":178,"context_line":"Nested resources are \u0027owned\u0027 by their parents. Therefore, this relationship is"},{"line_number":179,"context_line":"only suitable for a 1-to-1 or 1-to-many relation.  many-to-many relations"}],"source_content_type":"text/x-rst","patch_set":3,"id":"1a6eadb0_abf7fdf3","line":176,"range":{"start_line":172,"start_character":0,"end_line":176,"end_character":46},"in_reply_to":"1a6eadb0_5d2aaf7f","updated":"2016-12-19 12:56:46.000000000","message":"If I have a singular object in my model.\n\nConsider lrouter.external_gw which can be more than dictionary, we can wrap it in some class with nicer getters.","commit_id":"84fb80403186debb9ad975fdd1b51e0628c23c1a"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"6360533d2add584a13a59ad37e79de2882fc1025","unresolved":false,"context_lines":[{"line_number":169,"context_line":"exists. The representation of the field is transparent to the model definition,"},{"line_number":170,"context_line":"provided it can natively be serialised using e.g. jsonutils or msgpack."},{"line_number":171,"context_line":""},{"line_number":172,"context_line":"The class field `nested` will hold a dictionary of field name to model class."},{"line_number":173,"context_line":"The meaning here is that the field value will be an instance of that model."},{"line_number":174,"context_line":"This allows resources to contain other resources, e.g. routers and their ports,"},{"line_number":175,"context_line":"or security groups and their rules. This will also allow splitting nested"},{"line_number":176,"context_line":"resources into separate NB tables, if desired."},{"line_number":177,"context_line":""},{"line_number":178,"context_line":"Nested resources are \u0027owned\u0027 by their parents. Therefore, this relationship is"},{"line_number":179,"context_line":"only suitable for a 1-to-1 or 1-to-many relation.  many-to-many relations"}],"source_content_type":"text/x-rst","patch_set":3,"id":"1a6eadb0_5d2aaf7f","line":176,"range":{"start_line":172,"start_character":0,"end_line":176,"end_character":46},"in_reply_to":"1a6eadb0_a4cad96c","updated":"2016-12-19 12:09:10.000000000","message":"No. I figured it will always be plural. Where do you think the distinction is important?","commit_id":"84fb80403186debb9ad975fdd1b51e0628c23c1a"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"054108110bc6e7634dcddc19c1f841841179c072","unresolved":false,"context_lines":[{"line_number":179,"context_line":"only suitable for a 1-to-1 or 1-to-many relation.  many-to-many relations"},{"line_number":180,"context_line":"cannot be used here."},{"line_number":181,"context_line":""},{"line_number":182,"context_line":"The class field `indexes` will provided the indexes that should be constructed"},{"line_number":183,"context_line":"around the model. This is to facilitate lookup by field value or filtering. An"},{"line_number":184,"context_line":"indexed field will allow looking up models that have a specific value in that"},{"line_number":185,"context_line":"field."},{"line_number":186,"context_line":""},{"line_number":187,"context_line":"To support dynamic definition of events, i.e. to allow each model to define its"},{"line_number":188,"context_line":"events, there will be an `events` class field. It will be defined in greater"}],"source_content_type":"text/x-rst","patch_set":3,"id":"1a6eadb0_ff4d3d9a","line":185,"range":{"start_line":182,"start_character":0,"end_line":185,"end_character":6},"updated":"2016-12-19 08:11:33.000000000","message":"What about indexing nested objects, a la\n\n lrouter.lport.id","commit_id":"84fb80403186debb9ad975fdd1b51e0628c23c1a"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"cfa2fd2855658800e7d2c1c2627aae9e212f8dc8","unresolved":false,"context_lines":[{"line_number":179,"context_line":"only suitable for a 1-to-1 or 1-to-many relation.  many-to-many relations"},{"line_number":180,"context_line":"cannot be used here."},{"line_number":181,"context_line":""},{"line_number":182,"context_line":"The class field `indexes` will provided the indexes that should be constructed"},{"line_number":183,"context_line":"around the model. This is to facilitate lookup by field value or filtering. An"},{"line_number":184,"context_line":"indexed field will allow looking up models that have a specific value in that"},{"line_number":185,"context_line":"field."},{"line_number":186,"context_line":""},{"line_number":187,"context_line":"To support dynamic definition of events, i.e. to allow each model to define its"},{"line_number":188,"context_line":"events, there will be an `events` class field. It will be defined in greater"}],"source_content_type":"text/x-rst","patch_set":3,"id":"1a6eadb0_c457d524","line":185,"range":{"start_line":182,"start_character":0,"end_line":185,"end_character":6},"in_reply_to":"1a6eadb0_fabf0b5e","updated":"2016-12-19 09:56:02.000000000","message":"+1","commit_id":"84fb80403186debb9ad975fdd1b51e0628c23c1a"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"3445fa769630467795932b7cf399514883e6019a","unresolved":false,"context_lines":[{"line_number":179,"context_line":"only suitable for a 1-to-1 or 1-to-many relation.  many-to-many relations"},{"line_number":180,"context_line":"cannot be used here."},{"line_number":181,"context_line":""},{"line_number":182,"context_line":"The class field `indexes` will provided the indexes that should be constructed"},{"line_number":183,"context_line":"around the model. This is to facilitate lookup by field value or filtering. An"},{"line_number":184,"context_line":"indexed field will allow looking up models that have a specific value in that"},{"line_number":185,"context_line":"field."},{"line_number":186,"context_line":""},{"line_number":187,"context_line":"To support dynamic definition of events, i.e. to allow each model to define its"},{"line_number":188,"context_line":"events, there will be an `events` class field. It will be defined in greater"}],"source_content_type":"text/x-rst","patch_set":3,"id":"1a6eadb0_fabf0b5e","line":185,"range":{"start_line":182,"start_character":0,"end_line":185,"end_character":6},"in_reply_to":"1a6eadb0_ff4d3d9a","updated":"2016-12-19 08:28:37.000000000","message":"Yes, should be supported. Mentioned in section \u0027Searching and Indexing\u0027","commit_id":"84fb80403186debb9ad975fdd1b51e0628c23c1a"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"cfa2fd2855658800e7d2c1c2627aae9e212f8dc8","unresolved":false,"context_lines":[{"line_number":185,"context_line":"field."},{"line_number":186,"context_line":""},{"line_number":187,"context_line":"To support dynamic definition of events, i.e. to allow each model to define its"},{"line_number":188,"context_line":"events, there will be an `events` class field. It will be defined in greater"},{"line_number":189,"context_line":"detail upon southbound refactor."},{"line_number":190,"context_line":""},{"line_number":191,"context_line":"The class can be extended with additional or overriding methods, if necessary."},{"line_number":192,"context_line":""}],"source_content_type":"text/x-rst","patch_set":3,"id":"1a6eadb0_27e16bd1","line":189,"range":{"start_line":188,"start_character":47,"end_line":189,"end_character":32},"updated":"2016-12-19 09:56:02.000000000","message":"Do we plan to replace [1] with code in which local controller registers its own methods?\n\n  api_nb.register_event(\n      floatingip_created, \n      models.Floatingip.events.created\n  )\n\n[1] https://github.com/openstack/dragonflow/blob/master/dragonflow/db/api_nb.py#L199","commit_id":"84fb80403186debb9ad975fdd1b51e0628c23c1a"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"6360533d2add584a13a59ad37e79de2882fc1025","unresolved":false,"context_lines":[{"line_number":185,"context_line":"field."},{"line_number":186,"context_line":""},{"line_number":187,"context_line":"To support dynamic definition of events, i.e. to allow each model to define its"},{"line_number":188,"context_line":"events, there will be an `events` class field. It will be defined in greater"},{"line_number":189,"context_line":"detail upon southbound refactor."},{"line_number":190,"context_line":""},{"line_number":191,"context_line":"The class can be extended with additional or overriding methods, if necessary."},{"line_number":192,"context_line":""}],"source_content_type":"text/x-rst","patch_set":3,"id":"1a6eadb0_fd8ffb72","line":189,"range":{"start_line":188,"start_character":47,"end_line":189,"end_character":32},"in_reply_to":"1a6eadb0_27e16bd1","updated":"2016-12-19 12:09:10.000000000","message":"Yes. That\u0027s the plan for the southbound refactor.","commit_id":"84fb80403186debb9ad975fdd1b51e0628c23c1a"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"cfa2fd2855658800e7d2c1c2627aae9e212f8dc8","unresolved":false,"context_lines":[{"line_number":196,"context_line":"the resource\u0027s `crud_nb_api`. An example implementation will be:"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":"::"},{"line_number":199,"context_line":""},{"line_number":200,"context_line":"    def create(self, table_name, **columns):"},{"line_number":201,"context_line":"        resource \u003d self.get_resource(table_name)"},{"line_number":202,"context_line":"        crud_nb_api \u003d resource.crud_nb_api(self)"},{"line_number":203,"context_line":"        return crud_nb_api.create(columns)"},{"line_number":204,"context_line":""},{"line_number":205,"context_line":"An automatic migration script can review the difference between models, and"},{"line_number":206,"context_line":"create the relevant migration code. This should also facilitate upgrading"}],"source_content_type":"text/x-rst","patch_set":3,"id":"1a6eadb0_04dc6d17","line":203,"range":{"start_line":199,"start_character":0,"end_line":203,"end_character":42},"updated":"2016-12-19 09:56:02.000000000","message":"A slightly different idea to what is proposed in crud helper, but maybe we can have the CRUD object work on already constructed objects?\n\n resource \u003d self.get_resource(table_name)\n obj \u003d resource.from_dict(columns)\n crud_nb_api \u003d resource.crud_nb_api(self)\n return crud_nb_api.create(obj)    # This sets ID on the object\n\nSame can be done for update, which simplifies CRUD helper a bit.","commit_id":"84fb80403186debb9ad975fdd1b51e0628c23c1a"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"6360533d2add584a13a59ad37e79de2882fc1025","unresolved":false,"context_lines":[{"line_number":196,"context_line":"the resource\u0027s `crud_nb_api`. An example implementation will be:"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":"::"},{"line_number":199,"context_line":""},{"line_number":200,"context_line":"    def create(self, table_name, **columns):"},{"line_number":201,"context_line":"        resource \u003d self.get_resource(table_name)"},{"line_number":202,"context_line":"        crud_nb_api \u003d resource.crud_nb_api(self)"},{"line_number":203,"context_line":"        return crud_nb_api.create(columns)"},{"line_number":204,"context_line":""},{"line_number":205,"context_line":"An automatic migration script can review the difference between models, and"},{"line_number":206,"context_line":"create the relevant migration code. This should also facilitate upgrading"}],"source_content_type":"text/x-rst","patch_set":3,"id":"1a6eadb0_3d5df3ec","line":203,"range":{"start_line":199,"start_character":0,"end_line":203,"end_character":42},"in_reply_to":"1a6eadb0_04dc6d17","updated":"2016-12-19 12:09:10.000000000","message":"Possible, but how do you know if a field value wasn\u0027t provided? a **kwargs dictionary has this ability built-in. For this, the feature has to be build into the object (which will probably be backed by a dict anyway)","commit_id":"84fb80403186debb9ad975fdd1b51e0628c23c1a"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"9911ff9034cc474cb56099e62914baa75688ae16","unresolved":false,"context_lines":[{"line_number":196,"context_line":"the resource\u0027s `crud_nb_api`. An example implementation will be:"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":"::"},{"line_number":199,"context_line":""},{"line_number":200,"context_line":"    def create(self, table_name, **columns):"},{"line_number":201,"context_line":"        resource \u003d self.get_resource(table_name)"},{"line_number":202,"context_line":"        crud_nb_api \u003d resource.crud_nb_api(self)"},{"line_number":203,"context_line":"        return crud_nb_api.create(columns)"},{"line_number":204,"context_line":""},{"line_number":205,"context_line":"An automatic migration script can review the difference between models, and"},{"line_number":206,"context_line":"create the relevant migration code. This should also facilitate upgrading"}],"source_content_type":"text/x-rst","patch_set":3,"id":"1a6eadb0_8b0ec1e3","line":203,"range":{"start_line":199,"start_character":0,"end_line":203,"end_character":42},"in_reply_to":"1a6eadb0_3d5df3ec","updated":"2016-12-19 12:56:46.000000000","message":"Since we\u0027re serializing all our data anyway now, update requires get+deserialize, we can just create the object:\n\n   obj \u003d crud.get(id)\n   obj.update(**kwargs)\n   crud.update(obj)","commit_id":"84fb80403186debb9ad975fdd1b51e0628c23c1a"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"a477713f2d971ad01d6601fc728d75503987be65","unresolved":false,"context_lines":[{"line_number":29,"context_line":""},{"line_number":30,"context_line":"  * Dynamic adding of events to applications (e.g. CRUD on lport, routers)"},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"  * Application manager which chains and orders applications according to their"},{"line_number":33,"context_line":"    dependencies."},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"* Allow new models to register their NB API and DB Store functionality."},{"line_number":36,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_4471dca7","line":33,"range":{"start_line":32,"start_character":0,"end_line":33,"end_character":17},"updated":"2016-12-20 02:34:48.000000000","message":"I thought most apps should be independent, and decoupled with each other.","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"bd4608016254ac289f10e649e43236f94e86f7bc","unresolved":false,"context_lines":[{"line_number":29,"context_line":""},{"line_number":30,"context_line":"  * Dynamic adding of events to applications (e.g. CRUD on lport, routers)"},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"  * Application manager which chains and orders applications according to their"},{"line_number":33,"context_line":"    dependencies."},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"* Allow new models to register their NB API and DB Store functionality."},{"line_number":36,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_10347af9","line":33,"range":{"start_line":32,"start_character":0,"end_line":33,"end_character":17},"in_reply_to":"1a6eadb0_4471dca7","updated":"2016-12-20 04:12:47.000000000","message":"Yes and no. It is reasonable to assume that some applications will gather information (e.g. classification, connection tracking), and some apps will act upon that information (e.g. Security groups and sNAT on connection tracking)\n\nThis sort of design questions are the reason NB and SB refactor are done separately.","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20287,"name":"hujie","email":"mike.hu@huawei.com","username":"hujie"},"change_message_id":"724ab45636916f9a93e95ea50e9e88a5b235b58d","unresolved":false,"context_lines":[{"line_number":78,"context_line":""},{"line_number":79,"context_line":"* Similar API for NBApi and DBStore (mostly for simplicity, readibility)"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"* Uniform call to NbApi\u0027s and DBStore\u0027s get. e.g. to allow a call to DBStore\u0027s"},{"line_number":82,"context_line":"  get to fall through to NbApi if the object doesn\u0027t exist in the DBStore."},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"* Dragonflow specific CLI. Including integration of relevant bits into"},{"line_number":85,"context_line":"  openstack pythonclient."}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_83bf37fa","line":82,"range":{"start_line":81,"start_character":2,"end_line":82,"end_character":74},"updated":"2016-12-23 15:40:18.000000000","message":"I think we should implement this situation carefully and try to avoid to fetch data again when can not find in db store, as we already have the selective topology and db consistent logic, we should reduce the pressure of df db and provide less chance for system attacker.","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"eab127b689d82126d1c9c9c505021f759eab7dd8","unresolved":false,"context_lines":[{"line_number":78,"context_line":""},{"line_number":79,"context_line":"* Similar API for NBApi and DBStore (mostly for simplicity, readibility)"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"* Uniform call to NbApi\u0027s and DBStore\u0027s get. e.g. to allow a call to DBStore\u0027s"},{"line_number":82,"context_line":"  get to fall through to NbApi if the object doesn\u0027t exist in the DBStore."},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"* Dragonflow specific CLI. Including integration of relevant bits into"},{"line_number":85,"context_line":"  openstack pythonclient."}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_769afc64","line":82,"range":{"start_line":81,"start_character":2,"end_line":82,"end_character":74},"in_reply_to":"da4df55a_83bf37fa","updated":"2016-12-25 10:06:50.000000000","message":"Not sure how an attack is feasible, could you please provide more info?\n\nThe db_store/cache is on the controller side, which is not accessible to users/possible attackers, only trusted sources. Additionally, we don\u0027t know to which tenant an object belongs based on its id (which may be all we have).","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20287,"name":"hujie","email":"mike.hu@huawei.com","username":"hujie"},"change_message_id":"724ab45636916f9a93e95ea50e9e88a5b235b58d","unresolved":false,"context_lines":[{"line_number":108,"context_line":"    * Very long line to do a single operation"},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"This model can be used to promote dynamic registration: Upon import,"},{"line_number":111,"context_line":"the model registres itself to a global store, providing a CRUD Object"},{"line_number":112,"context_line":"for NBApi and a CRUD Object for DBStore."},{"line_number":113,"context_line":""},{"line_number":114,"context_line":"CRUD objects can include additional functionality where needed. Basic"}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_23876bd8","line":111,"range":{"start_line":111,"start_character":10,"end_line":111,"end_character":19},"updated":"2016-12-23 15:40:18.000000000","message":"registries","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"ccef3cfd3712070a07253310607b34608aabbddd","unresolved":false,"context_lines":[{"line_number":108,"context_line":"    * Very long line to do a single operation"},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"This model can be used to promote dynamic registration: Upon import,"},{"line_number":111,"context_line":"the model registres itself to a global store, providing a CRUD Object"},{"line_number":112,"context_line":"for NBApi and a CRUD Object for DBStore."},{"line_number":113,"context_line":""},{"line_number":114,"context_line":"CRUD objects can include additional functionality where needed. Basic"}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_5993694f","line":111,"range":{"start_line":111,"start_character":10,"end_line":111,"end_character":19},"in_reply_to":"da4df55a_23876bd8","updated":"2016-12-26 12:16:01.000000000","message":"Done","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20287,"name":"hujie","email":"mike.hu@huawei.com","username":"hujie"},"change_message_id":"724ab45636916f9a93e95ea50e9e88a5b235b58d","unresolved":false,"context_lines":[{"line_number":116,"context_line":"read/write to the NBDB and cache."},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"These CRUD objects will have a base class all CRUD objects are expected to"},{"line_number":119,"context_line":"extend. The Db Store CRUD object will be provided by Db Store code, and is"},{"line_number":120,"context_line":"not expected to be extended by model developers."},{"line_number":121,"context_line":""},{"line_number":122,"context_line":"Model Definition"},{"line_number":123,"context_line":"----------------"}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_16f707f6","line":120,"range":{"start_line":119,"start_character":7,"end_line":120,"end_character":48},"updated":"2016-12-23 15:40:18.000000000","message":"why only mentioned the db store crud object could not be extended, what about nb_api?","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"eab127b689d82126d1c9c9c505021f759eab7dd8","unresolved":false,"context_lines":[{"line_number":116,"context_line":"read/write to the NBDB and cache."},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"These CRUD objects will have a base class all CRUD objects are expected to"},{"line_number":119,"context_line":"extend. The Db Store CRUD object will be provided by Db Store code, and is"},{"line_number":120,"context_line":"not expected to be extended by model developers."},{"line_number":121,"context_line":""},{"line_number":122,"context_line":"Model Definition"},{"line_number":123,"context_line":"----------------"}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_f6aeec83","line":120,"range":{"start_line":119,"start_character":7,"end_line":120,"end_character":48},"in_reply_to":"da4df55a_16f707f6","updated":"2016-12-25 10:06:50.000000000","message":"The NB API CRuD object is expected to be extended. e.g. associate/disassociate floating IP. The db store object is automatically generated by the model\u0027s indexes, as they are provided.","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20287,"name":"hujie","email":"mike.hu@huawei.com","username":"hujie"},"change_message_id":"724ab45636916f9a93e95ea50e9e88a5b235b58d","unresolved":false,"context_lines":[{"line_number":131,"context_line":"        crud_nb_api \u003d \u003cCRUD Helper\u003e"},{"line_number":132,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"},{"line_number":133,"context_line":"        nested \u003d [\u0027\u003cNestedModel1\u003e\u0027, ...]"},{"line_number":134,"context_line":"        indexes \u003d [\u0027\u003cIndexedField1\u003e\u0027, ...]"},{"line_number":135,"context_line":"        # Events definition will go here"},{"line_number":136,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":137,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_193f38d7","line":134,"range":{"start_line":134,"start_character":8,"end_line":134,"end_character":42},"updated":"2016-12-23 15:40:18.000000000","message":"I could not image how to use Model.indexed to fetch the corresponding data, could you pls give a example, thx:)","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"eab127b689d82126d1c9c9c505021f759eab7dd8","unresolved":false,"context_lines":[{"line_number":131,"context_line":"        crud_nb_api \u003d \u003cCRUD Helper\u003e"},{"line_number":132,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"},{"line_number":133,"context_line":"        nested \u003d [\u0027\u003cNestedModel1\u003e\u0027, ...]"},{"line_number":134,"context_line":"        indexes \u003d [\u0027\u003cIndexedField1\u003e\u0027, ...]"},{"line_number":135,"context_line":"        # Events definition will go here"},{"line_number":136,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":137,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_76b11ce1","line":134,"range":{"start_line":134,"start_character":8,"end_line":134,"end_character":42},"in_reply_to":"da4df55a_193f38d7","updated":"2016-12-25 10:06:50.000000000","message":"Example available at section \u0027Searching and Indexing\u0027. Say a LogicalPort has a reference to chassis, and we say that there is an index: chassis (or chassis.id). Then the DB store will offer a method to search by that index, e.g. db_store.get(\u0027LogicalPort\u0027, \u003cchassis_id\u003e, \u0027chassis\u0027)","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20287,"name":"hujie","email":"mike.hu@huawei.com","username":"hujie"},"change_message_id":"724ab45636916f9a93e95ea50e9e88a5b235b58d","unresolved":false,"context_lines":[{"line_number":132,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"},{"line_number":133,"context_line":"        nested \u003d [\u0027\u003cNestedModel1\u003e\u0027, ...]"},{"line_number":134,"context_line":"        indexes \u003d [\u0027\u003cIndexedField1\u003e\u0027, ...]"},{"line_number":135,"context_line":"        # Events definition will go here"},{"line_number":136,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"\u003cModelBaseClass\u003e will be a base class all models inherit."}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_d402d708","line":135,"range":{"start_line":135,"start_character":10,"end_line":135,"end_character":40},"updated":"2016-12-23 15:40:18.000000000","message":"Are the events consist of create/update/delete??","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"eab127b689d82126d1c9c9c505021f759eab7dd8","unresolved":false,"context_lines":[{"line_number":132,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"},{"line_number":133,"context_line":"        nested \u003d [\u0027\u003cNestedModel1\u003e\u0027, ...]"},{"line_number":134,"context_line":"        indexes \u003d [\u0027\u003cIndexedField1\u003e\u0027, ...]"},{"line_number":135,"context_line":"        # Events definition will go here"},{"line_number":136,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"\u003cModelBaseClass\u003e will be a base class all models inherit."}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_b6cb8452","line":135,"range":{"start_line":135,"start_character":10,"end_line":135,"end_character":40},"in_reply_to":"da4df55a_d402d708","updated":"2016-12-25 10:06:50.000000000","message":"As a minimum, yes. Some objects may have additional events (e.g. associate/disassociate floating ip).","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"4dac58f3a9267e00d6a4fdfc04997d0424ec8392","unresolved":false,"context_lines":[{"line_number":126,"context_line":""},{"line_number":127,"context_line":"::"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"    @register_model"},{"line_number":130,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":131,"context_line":"        crud_nb_api \u003d \u003cCRUD Helper\u003e"},{"line_number":132,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"},{"line_number":133,"context_line":"        nested \u003d [\u0027\u003cNestedModel1\u003e\u0027, ...]"},{"line_number":134,"context_line":"        indexes \u003d [\u0027\u003cIndexedField1\u003e\u0027, ...]"},{"line_number":135,"context_line":"        # Events definition will go here"},{"line_number":136,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"\u003cModelBaseClass\u003e will be a base class all models inherit."},{"line_number":139,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_f5cfa653","line":136,"range":{"start_line":129,"start_character":0,"end_line":136,"end_character":75},"updated":"2016-12-21 11:12:58.000000000","message":"As we discussed in the channel, we should eliminate nested fields attribute and have a single fields attribute to hold all the required information.\n\nTo add all the extra info we can create a Field class that will hold details:\n\n class SomeModel(BaseModel):\n     fields \u003d [\n         Field(\u0027timestamp\u0027, type\u003dparse_from_datetime),\n         Field(\u0027nested_list_of_ints\u0027, plural\u003d\u0027list\u0027),\n         ...\n     ]\n\nAnd also allow strings we will automatically convert to Field objects with sane defaults (implicit type, singular...)\n\nI also propose avoid having both type and plural arguments. I think we can get away with just having type\u003d argument that will work as follows:\n\n* For singular objects of type Type, specify type\u003dType\n* For sequences/sets of objects of Type, specify type\u003d[Type] or type\u003d{Type}\n* For dictionaries from KeyType to ValueType specify: type\u003d{KeyType: ValueType}","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"796057d3c38931169b0f169b85744d5bf9f2cf08","unresolved":false,"context_lines":[{"line_number":126,"context_line":""},{"line_number":127,"context_line":"::"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"    @register_model"},{"line_number":130,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":131,"context_line":"        crud_nb_api \u003d \u003cCRUD Helper\u003e"},{"line_number":132,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"},{"line_number":133,"context_line":"        nested \u003d [\u0027\u003cNestedModel1\u003e\u0027, ...]"},{"line_number":134,"context_line":"        indexes \u003d [\u0027\u003cIndexedField1\u003e\u0027, ...]"},{"line_number":135,"context_line":"        # Events definition will go here"},{"line_number":136,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"\u003cModelBaseClass\u003e will be a base class all models inherit."},{"line_number":139,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_a56d4d34","line":136,"range":{"start_line":129,"start_character":0,"end_line":136,"end_character":75},"in_reply_to":"1a6eadb0_0f8ecb78","updated":"2016-12-22 19:50:06.000000000","message":"After some research, I think jsonmodels [1] package offers the tools we need for building our models. We can use it to define model classes with typed fields, and the package constructs objects that can be turned into python dicts and also enforces field types (which we currently don\u0027t do).\n\nAnother thing, we currently have some relations between our models, either by composition (lrouter ports) or by reference (lport\u0027s lswitch). I think it would be nice if we write our code in such way that traversing the relations is seamless. In case of members it is already so, in case of references, we can eagerly or lazily fetch the object on the other end (using nb api if its not present)\n\nOne other thing we neglected is the index definition, if we\u0027ll go for jsonmodels we can specify indicies as sequences of Field instances, \n\n\n[1] https://github.com/beregond/jsonmodels","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"c8af3dca46b4f7e19097197a3afa7489987fd453","unresolved":false,"context_lines":[{"line_number":126,"context_line":""},{"line_number":127,"context_line":"::"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"    @register_model"},{"line_number":130,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":131,"context_line":"        crud_nb_api \u003d \u003cCRUD Helper\u003e"},{"line_number":132,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"},{"line_number":133,"context_line":"        nested \u003d [\u0027\u003cNestedModel1\u003e\u0027, ...]"},{"line_number":134,"context_line":"        indexes \u003d [\u0027\u003cIndexedField1\u003e\u0027, ...]"},{"line_number":135,"context_line":"        # Events definition will go here"},{"line_number":136,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"\u003cModelBaseClass\u003e will be a base class all models inherit."},{"line_number":139,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_bee98bb9","line":136,"range":{"start_line":129,"start_character":0,"end_line":136,"end_character":75},"in_reply_to":"1a6eadb0_bea7cb09","updated":"2016-12-21 11:57:01.000000000","message":"I don\u0027t think it is very different than inferring list type from plural\u003d\u0027list\u0027.\n\nAfter all, we\u0027ll have to support just 3 cases (or 4 if we want to support sets which don\u0027t really translate into JSON), and this can be done quite easily.\n\nI wanted to unify the 2 properties because it makes the most sense to me. The field type is really List\u003cElementType\u003e (sorry if templates make you cry)","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"5b21c6d00330db9b22a5af76e83ee233c0c704ec","unresolved":false,"context_lines":[{"line_number":126,"context_line":""},{"line_number":127,"context_line":"::"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"    @register_model"},{"line_number":130,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":131,"context_line":"        crud_nb_api \u003d \u003cCRUD Helper\u003e"},{"line_number":132,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"},{"line_number":133,"context_line":"        nested \u003d [\u0027\u003cNestedModel1\u003e\u0027, ...]"},{"line_number":134,"context_line":"        indexes \u003d [\u0027\u003cIndexedField1\u003e\u0027, ...]"},{"line_number":135,"context_line":"        # Events definition will go here"},{"line_number":136,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"\u003cModelBaseClass\u003e will be a base class all models inherit."},{"line_number":139,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_0f8ecb78","line":136,"range":{"start_line":129,"start_character":0,"end_line":136,"end_character":75},"in_reply_to":"1a6eadb0_bee98bb9","updated":"2016-12-21 12:40:47.000000000","message":"I second Omer on having explicit way to specify both type and plural args","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"3ca9800034fd0b17f820e7eb007ab1494872520c","unresolved":false,"context_lines":[{"line_number":126,"context_line":""},{"line_number":127,"context_line":"::"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"    @register_model"},{"line_number":130,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":131,"context_line":"        crud_nb_api \u003d \u003cCRUD Helper\u003e"},{"line_number":132,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"},{"line_number":133,"context_line":"        nested \u003d [\u0027\u003cNestedModel1\u003e\u0027, ...]"},{"line_number":134,"context_line":"        indexes \u003d [\u0027\u003cIndexedField1\u003e\u0027, ...]"},{"line_number":135,"context_line":"        # Events definition will go here"},{"line_number":136,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"\u003cModelBaseClass\u003e will be a base class all models inherit."},{"line_number":139,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_bea7cb09","line":136,"range":{"start_line":129,"start_character":0,"end_line":136,"end_character":75},"in_reply_to":"1a6eadb0_f5cfa653","updated":"2016-12-21 11:48:23.000000000","message":"I like it, with a caveat: I prefer to explicitly have both type_ and plural arguments. I think it will be easier to be given the types, rather than inferring them.","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"eab127b689d82126d1c9c9c505021f759eab7dd8","unresolved":false,"context_lines":[{"line_number":126,"context_line":""},{"line_number":127,"context_line":"::"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"    @register_model"},{"line_number":130,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":131,"context_line":"        crud_nb_api \u003d \u003cCRUD Helper\u003e"},{"line_number":132,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"},{"line_number":133,"context_line":"        nested \u003d [\u0027\u003cNestedModel1\u003e\u0027, ...]"},{"line_number":134,"context_line":"        indexes \u003d [\u0027\u003cIndexedField1\u003e\u0027, ...]"},{"line_number":135,"context_line":"        # Events definition will go here"},{"line_number":136,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"\u003cModelBaseClass\u003e will be a base class all models inherit."},{"line_number":139,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_f6c50c3c","line":136,"range":{"start_line":129,"start_character":0,"end_line":136,"end_character":75},"in_reply_to":"da4df55a_1373824e","updated":"2016-12-25 10:06:50.000000000","message":"+1","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"ccef3cfd3712070a07253310607b34608aabbddd","unresolved":false,"context_lines":[{"line_number":126,"context_line":""},{"line_number":127,"context_line":"::"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"    @register_model"},{"line_number":130,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":131,"context_line":"        crud_nb_api \u003d \u003cCRUD Helper\u003e"},{"line_number":132,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"},{"line_number":133,"context_line":"        nested \u003d [\u0027\u003cNestedModel1\u003e\u0027, ...]"},{"line_number":134,"context_line":"        indexes \u003d [\u0027\u003cIndexedField1\u003e\u0027, ...]"},{"line_number":135,"context_line":"        # Events definition will go here"},{"line_number":136,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"\u003cModelBaseClass\u003e will be a base class all models inherit."},{"line_number":139,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_26083591","line":136,"range":{"start_line":129,"start_character":0,"end_line":136,"end_character":75},"in_reply_to":"da4df55a_3278778f","updated":"2016-12-26 12:16:01.000000000","message":"Working on it :)","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"d9ee75935e633788439609699237426ce03d15f7","unresolved":false,"context_lines":[{"line_number":126,"context_line":""},{"line_number":127,"context_line":"::"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"    @register_model"},{"line_number":130,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":131,"context_line":"        crud_nb_api \u003d \u003cCRUD Helper\u003e"},{"line_number":132,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"},{"line_number":133,"context_line":"        nested \u003d [\u0027\u003cNestedModel1\u003e\u0027, ...]"},{"line_number":134,"context_line":"        indexes \u003d [\u0027\u003cIndexedField1\u003e\u0027, ...]"},{"line_number":135,"context_line":"        # Events definition will go here"},{"line_number":136,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"\u003cModelBaseClass\u003e will be a base class all models inherit."},{"line_number":139,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_3278778f","line":136,"range":{"start_line":129,"start_character":0,"end_line":136,"end_character":75},"in_reply_to":"da4df55a_7cb1fbe0","updated":"2016-12-26 05:42:48.000000000","message":"Can you please update this spec with finalized proposal? It is a bit difficult to review and comment through the comments","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"c1826c280f62c9cc3610ce5467431ca8a161710d","unresolved":false,"context_lines":[{"line_number":126,"context_line":""},{"line_number":127,"context_line":"::"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"    @register_model"},{"line_number":130,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":131,"context_line":"        crud_nb_api \u003d \u003cCRUD Helper\u003e"},{"line_number":132,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"},{"line_number":133,"context_line":"        nested \u003d [\u0027\u003cNestedModel1\u003e\u0027, ...]"},{"line_number":134,"context_line":"        indexes \u003d [\u0027\u003cIndexedField1\u003e\u0027, ...]"},{"line_number":135,"context_line":"        # Events definition will go here"},{"line_number":136,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"\u003cModelBaseClass\u003e will be a base class all models inherit."},{"line_number":139,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_1373824e","line":136,"range":{"start_line":129,"start_character":0,"end_line":136,"end_character":75},"in_reply_to":"da4df55a_a56d4d34","updated":"2016-12-25 07:20:46.000000000","message":"I like the proposed jsonmodels package. It looks quite mature and provides the functionality we discussed in scope of this spec. In addition it allows an easy way to validate the models and it will be a requirement once we add NB API to DF.","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"a84ae8dfe70ad0456634271e776ae3b94ee8591b","unresolved":false,"context_lines":[{"line_number":126,"context_line":""},{"line_number":127,"context_line":"::"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"    @register_model"},{"line_number":130,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":131,"context_line":"        crud_nb_api \u003d \u003cCRUD Helper\u003e"},{"line_number":132,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"},{"line_number":133,"context_line":"        nested \u003d [\u0027\u003cNestedModel1\u003e\u0027, ...]"},{"line_number":134,"context_line":"        indexes \u003d [\u0027\u003cIndexedField1\u003e\u0027, ...]"},{"line_number":135,"context_line":"        # Events definition will go here"},{"line_number":136,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"\u003cModelBaseClass\u003e will be a base class all models inherit."},{"line_number":139,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_7cb1fbe0","line":136,"range":{"start_line":129,"start_character":0,"end_line":136,"end_character":75},"in_reply_to":"da4df55a_bc42833c","updated":"2016-12-25 16:45:49.000000000","message":"Another idea with the code example above, we can skip the metadata class altogather, and change the construct decorator to accept arguments:\n\n @construct_nb_db_model(\n     indexes\u003dNamespace(id\u003d\u0027id\u0027),\n     events\u003d(\u0027created\u0027, \u0027updated\u0027, \u0027deleted\u0027),\n     nb_crud\u003dBaseNbCRUD,\n )\n class BaseModel(jsonmodels.models.Base):\n     id \u003d fields.StringType(required\u003dTrue)\n\nWith any/all arguments can be ommited","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"f665b9181423d686ff97d70c1829ca7379f4ec77","unresolved":false,"context_lines":[{"line_number":126,"context_line":""},{"line_number":127,"context_line":"::"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"    @register_model"},{"line_number":130,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":131,"context_line":"        crud_nb_api \u003d \u003cCRUD Helper\u003e"},{"line_number":132,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"},{"line_number":133,"context_line":"        nested \u003d [\u0027\u003cNestedModel1\u003e\u0027, ...]"},{"line_number":134,"context_line":"        indexes \u003d [\u0027\u003cIndexedField1\u003e\u0027, ...]"},{"line_number":135,"context_line":"        # Events definition will go here"},{"line_number":136,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"\u003cModelBaseClass\u003e will be a base class all models inherit."},{"line_number":139,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_bc42833c","line":136,"range":{"start_line":129,"start_character":0,"end_line":136,"end_character":75},"in_reply_to":"da4df55a_dc0f472c","updated":"2016-12-25 15:39:59.000000000","message":"Additionally, events defined on the models would generate several of methods each, e.g. for \u0027created\u0027:\n\n Model.register_created(callback)\n Model.unregister_created(callback)\n Model.emit_created(*args, **kwargs)\n\nWhere emit function would call all of the registered callbacks with the arguments passed to it.","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"ee800651d3d9a1032d1de355a585877eb54c9746","unresolved":false,"context_lines":[{"line_number":126,"context_line":""},{"line_number":127,"context_line":"::"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"    @register_model"},{"line_number":130,"context_line":"    class \u003cModel\u003e(\u003cModelBaseClass\u003e, \u003cModelMixins\u003e):"},{"line_number":131,"context_line":"        crud_nb_api \u003d \u003cCRUD Helper\u003e"},{"line_number":132,"context_line":"        fields \u003d [\u0027\u003cModelField1\u003e\u0027, \u0027\u003cModelReferenceField1\u003e\u0027, ...]"},{"line_number":133,"context_line":"        nested \u003d [\u0027\u003cNestedModel1\u003e\u0027, ...]"},{"line_number":134,"context_line":"        indexes \u003d [\u0027\u003cIndexedField1\u003e\u0027, ...]"},{"line_number":135,"context_line":"        # Events definition will go here"},{"line_number":136,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"\u003cModelBaseClass\u003e will be a base class all models inherit."},{"line_number":139,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_dc0f472c","line":136,"range":{"start_line":129,"start_character":0,"end_line":136,"end_character":75},"in_reply_to":"da4df55a_f6c50c3c","updated":"2016-12-25 15:27:51.000000000","message":"After long discussions with Omer, we wanted to propose the following points for the refactor:\n\nUsing jsonmodels [1] gives us a lot of flexibility and saves us the time to define our own model definition code.\n\nTypical models definition will look the following:\n\n # A type to define model metadata, the indexes we want, events and etc...\n # All names below are suggestions only\n Metadata \u003d collections.nametuple(\u0027Metadata\u0027, (\u0027indexes\u0027, \u0027events\u0027, \u0027nb_crud\u0027)) \n\n\n # (a)\n base_metadata \u003d Metadata(\n     indexes\u003dNamespace(id\u003d\u0027id\u0027),\n     events\u003d(\u0027created\u0027, \u0027updated\u0027, \u0027deleted\u0027),\n     nb_crud\u003dBaseNbCRUD,\n )\n\n @construct_nb_db_model(base_metadata)  # (b)\n class BaseModel(jsonmodels.models.Base):\n     id \u003d fields.StringType(required\u003dTrue)\n\n \n # (c)\n derived_metadata \u003d Metadata(\n     indexes\u003dNamespace(index1\u003d\u0027field1\u0027, index2\u003d(\u0027field2\u0027, \u0027field3\u0027),\n     events\u003d(\u0027resuscitated\u0027,)\n )\n\n \n @register_nb_db_model  # (d)\n @construct_nb_db_model(derived_metadata)\n class DerivedWithMetadataModel(BaseModel):\n     table_name \u003d \u0027derived_with_md\u0027\n\n     field1 \u003d fields.IntType()\n     field2 \u003d fields.StringField()\n     field3 \u003d fields.StringField()\n\n\n @register_nb_db_model\n @construct_nb_db_model  # (e)\n class DerivedWithoutMetadataModel(BaseModel):\n     table_name \u003d \u0027derived_without_md\u0027\n\n     ref_to_base \u003d fields.Ref(BaseModel[, index\u003d\u0027id\u0027])  # (f)\n\n\nAs the code above presents, each model is a definition of its fields, the extra information, such as indexes and events is defined externally in a metadata object (see a). This allows us to avoid taking up any possible field name. Each such model has to be constructed with some behind the scene code, using construct_nb_db_model (see b) decorator, whose role includes:\n\n* Constructing the correct metadata object, that combines all the events and indexes of the class and its ancestors (see c), if name conflict occurs, the metadata of the type that comes first in MRO takes precedence.\n* Adding get_metadata() method that returns the constructed metadata.\n* Constructing the code for events, registeration methods, emit methods, unregistration methods, etc\n* More stuff we might need in the future that augment the model class or instances.\n\nOmitting the parameter to the aforementioned decorator will use the metadata constructed for the parent class (see e). register_nb_db_model decorator registers the model into a lookup by table name (see d) as it already happend in [2]\n\nLastly, we\u0027ll extend jsonmodels field types to include references between models. In the example below we\u0027ll be able to store in our database:\n\n {\n     ...\n     \u0027ref_to_base\u0027: \u0027id1\u0027,\n }\n\nand when we get an object of the above kind, we\u0027ll be able to access the ref_to_base as it it ware full base object:\n\n base_id \u003d d.ref_to_base.id\n\nThis retrieval will be done behind the scenes, to allow this, we\u0027ll need to tell the reference definition what index we should use, i.e. what info we have in our model and how do we use it to find the original object (using DbStore and NbApi)\n\nLastly, to allow each model with reference field automatic fetching, we\u0027ll have to make DbStore globally accessible (accross the process), a singleton or some other way.\n\n[1] http://jsonmodels.readthedocs.io/\n[2] https://review.openstack.org/#/c/410645/","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20287,"name":"hujie","email":"mike.hu@huawei.com","username":"hujie"},"change_message_id":"724ab45636916f9a93e95ea50e9e88a5b235b58d","unresolved":false,"context_lines":[{"line_number":135,"context_line":"        # Events definition will go here"},{"line_number":136,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"\u003cModelBaseClass\u003e will be a base class all models inherit."},{"line_number":139,"context_line":""},{"line_number":140,"context_line":"Models will be registered via the `register_model` method. This method can be"},{"line_number":141,"context_line":"used as a decorator, or called directly with the model."}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_191018a8","line":138,"range":{"start_line":138,"start_character":0,"end_line":138,"end_character":16},"updated":"2016-12-23 15:40:18.000000000","message":"will it contain the common attributes?","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"eab127b689d82126d1c9c9c505021f759eab7dd8","unresolved":false,"context_lines":[{"line_number":135,"context_line":"        # Events definition will go here"},{"line_number":136,"context_line":"        ... # Additional methods, if necessary, e.g. lports external fields"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"\u003cModelBaseClass\u003e will be a base class all models inherit."},{"line_number":139,"context_line":""},{"line_number":140,"context_line":"Models will be registered via the `register_model` method. This method can be"},{"line_number":141,"context_line":"used as a decorator, or called directly with the model."}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_16c1b02e","line":138,"range":{"start_line":138,"start_character":0,"end_line":138,"end_character":16},"in_reply_to":"da4df55a_191018a8","updated":"2016-12-25 10:06:50.000000000","message":"Yes.","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"fcf8c922bd68abd523498ef03409a1d2cd48c600","unresolved":false,"context_lines":[{"line_number":196,"context_line":""},{"line_number":197,"context_line":"The class can be extended with additional or overriding methods, if necessary."},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"Optionally, Nb Api will have four methods: `create`, `get`, `update`,"},{"line_number":200,"context_line":"and `delete`, receiving a table name, and the parameters to the relevant"},{"line_number":201,"context_line":"method. These will be facility methods calling the relevant function on"},{"line_number":202,"context_line":"the resource\u0027s `crud_nb_api`. An example implementation will be:"}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_c30046ae","line":199,"range":{"start_line":199,"start_character":68,"end_line":199,"end_character":69},"updated":"2016-12-21 03:13:06.000000000","message":"extra comma","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"eab127b689d82126d1c9c9c505021f759eab7dd8","unresolved":false,"context_lines":[{"line_number":196,"context_line":""},{"line_number":197,"context_line":"The class can be extended with additional or overriding methods, if necessary."},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"Optionally, Nb Api will have four methods: `create`, `get`, `update`,"},{"line_number":200,"context_line":"and `delete`, receiving a table name, and the parameters to the relevant"},{"line_number":201,"context_line":"method. These will be facility methods calling the relevant function on"},{"line_number":202,"context_line":"the resource\u0027s `crud_nb_api`. An example implementation will be:"}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_76e83cb5","line":199,"range":{"start_line":199,"start_character":68,"end_line":199,"end_character":69},"in_reply_to":"1a6eadb0_c30046ae","updated":"2016-12-25 10:06:50.000000000","message":"oxford comma :)","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"a477713f2d971ad01d6601fc728d75503987be65","unresolved":false,"context_lines":[{"line_number":203,"context_line":""},{"line_number":204,"context_line":"::"},{"line_number":205,"context_line":""},{"line_number":206,"context_line":"    def create(self, table_name, **columns):"},{"line_number":207,"context_line":"        resource \u003d self.get_resource(table_name)"},{"line_number":208,"context_line":"        crud_nb_api \u003d resource.crud_nb_api(self)"},{"line_number":209,"context_line":"        return crud_nb_api.create(columns)"},{"line_number":210,"context_line":""},{"line_number":211,"context_line":"An automatic migration script can review the difference between models, and"},{"line_number":212,"context_line":"create the relevant migration code. This should also facilitate upgrading"}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_4fb3b5e9","line":209,"range":{"start_line":206,"start_character":0,"end_line":209,"end_character":42},"updated":"2016-12-20 02:34:48.000000000","message":"Do we need to provide 2 approaches for developer to CRUD nb db objects?","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"bd4608016254ac289f10e649e43236f94e86f7bc","unresolved":false,"context_lines":[{"line_number":203,"context_line":""},{"line_number":204,"context_line":"::"},{"line_number":205,"context_line":""},{"line_number":206,"context_line":"    def create(self, table_name, **columns):"},{"line_number":207,"context_line":"        resource \u003d self.get_resource(table_name)"},{"line_number":208,"context_line":"        crud_nb_api \u003d resource.crud_nb_api(self)"},{"line_number":209,"context_line":"        return crud_nb_api.create(columns)"},{"line_number":210,"context_line":""},{"line_number":211,"context_line":"An automatic migration script can review the difference between models, and"},{"line_number":212,"context_line":"create the relevant migration code. This should also facilitate upgrading"}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_d02a0290","line":209,"range":{"start_line":206,"start_character":0,"end_line":209,"end_character":42},"in_reply_to":"1a6eadb0_4fb3b5e9","updated":"2016-12-20 04:12:47.000000000","message":"No. We don\u0027t. Unless someone upvotes this sub-feature, I\u0027ll remove it.","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"fcf8c922bd68abd523498ef03409a1d2cd48c600","unresolved":false,"context_lines":[{"line_number":203,"context_line":""},{"line_number":204,"context_line":"::"},{"line_number":205,"context_line":""},{"line_number":206,"context_line":"    def create(self, table_name, **columns):"},{"line_number":207,"context_line":"        resource \u003d self.get_resource(table_name)"},{"line_number":208,"context_line":"        crud_nb_api \u003d resource.crud_nb_api(self)"},{"line_number":209,"context_line":"        return crud_nb_api.create(columns)"},{"line_number":210,"context_line":""},{"line_number":211,"context_line":"An automatic migration script can review the difference between models, and"},{"line_number":212,"context_line":"create the relevant migration code. This should also facilitate upgrading"}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_e3fd42b2","line":209,"range":{"start_line":206,"start_character":0,"end_line":209,"end_character":42},"in_reply_to":"1a6eadb0_84412f3c","updated":"2016-12-21 03:13:06.000000000","message":"I think @dimak want to put the details of objects outside the nb_api crud helper(if I understand correctly).\n\nIf we are going to provide \"self.nb_api.get_resource(\u0027lport\u0027).create(...)\", I think we have to put the details inside the crud helper. We might not want the user to construct the object first, and then apply the object to nb api crud methods.","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"36911c297efc48ebae4f0a71e317408ec788465a","unresolved":false,"context_lines":[{"line_number":203,"context_line":""},{"line_number":204,"context_line":"::"},{"line_number":205,"context_line":""},{"line_number":206,"context_line":"    def create(self, table_name, **columns):"},{"line_number":207,"context_line":"        resource \u003d self.get_resource(table_name)"},{"line_number":208,"context_line":"        crud_nb_api \u003d resource.crud_nb_api(self)"},{"line_number":209,"context_line":"        return crud_nb_api.create(columns)"},{"line_number":210,"context_line":""},{"line_number":211,"context_line":"An automatic migration script can review the difference between models, and"},{"line_number":212,"context_line":"create the relevant migration code. This should also facilitate upgrading"}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_84412f3c","line":209,"range":{"start_line":206,"start_character":0,"end_line":209,"end_character":42},"in_reply_to":"1a6eadb0_d02a0290","updated":"2016-12-20 04:14:10.000000000","message":"Please also note @dimak\u0027s comments here from PS3 (line 203). I would like additional opinions.","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20287,"name":"hujie","email":"mike.hu@huawei.com","username":"hujie"},"change_message_id":"724ab45636916f9a93e95ea50e9e88a5b235b58d","unresolved":false,"context_lines":[{"line_number":203,"context_line":""},{"line_number":204,"context_line":"::"},{"line_number":205,"context_line":""},{"line_number":206,"context_line":"    def create(self, table_name, **columns):"},{"line_number":207,"context_line":"        resource \u003d self.get_resource(table_name)"},{"line_number":208,"context_line":"        crud_nb_api \u003d resource.crud_nb_api(self)"},{"line_number":209,"context_line":"        return crud_nb_api.create(columns)"},{"line_number":210,"context_line":""},{"line_number":211,"context_line":"An automatic migration script can review the difference between models, and"},{"line_number":212,"context_line":"create the relevant migration code. This should also facilitate upgrading"}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_b95e2ce7","line":209,"range":{"start_line":206,"start_character":0,"end_line":209,"end_character":42},"in_reply_to":"1a6eadb0_e3fd42b2","updated":"2016-12-23 15:40:18.000000000","message":"I think the previous solution is enough, this could be ignored currently","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"eab127b689d82126d1c9c9c505021f759eab7dd8","unresolved":false,"context_lines":[{"line_number":203,"context_line":""},{"line_number":204,"context_line":"::"},{"line_number":205,"context_line":""},{"line_number":206,"context_line":"    def create(self, table_name, **columns):"},{"line_number":207,"context_line":"        resource \u003d self.get_resource(table_name)"},{"line_number":208,"context_line":"        crud_nb_api \u003d resource.crud_nb_api(self)"},{"line_number":209,"context_line":"        return crud_nb_api.create(columns)"},{"line_number":210,"context_line":""},{"line_number":211,"context_line":"An automatic migration script can review the difference between models, and"},{"line_number":212,"context_line":"create the relevant migration code. This should also facilitate upgrading"}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_f6dc2c14","line":209,"range":{"start_line":206,"start_character":0,"end_line":209,"end_character":42},"in_reply_to":"da4df55a_b95e2ce7","updated":"2016-12-25 10:06:50.000000000","message":"We\u0027re going to need a CRUD Helper if we want to extend it with additional methods.\n\nI was also hoping for some opinions on the objects vs. field\u003dvalue API of the crud helper.","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"a477713f2d971ad01d6601fc728d75503987be65","unresolved":false,"context_lines":[{"line_number":250,"context_line":""},{"line_number":251,"context_line":"2. MAC"},{"line_number":252,"context_line":""},{"line_number":253,"context_line":"The `crud_cache` class field will need the following indexing information:"},{"line_number":254,"context_line":"`topic`, and `ports.mac`. The `crud_cache` implementation will index the"},{"line_number":255,"context_line":"`topic` and nested `mac` fields automatically."},{"line_number":256,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_e4c66815","line":253,"range":{"start_line":253,"start_character":5,"end_line":253,"end_character":15},"updated":"2016-12-20 02:34:48.000000000","message":"This class field was not introduced above.","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"bd4608016254ac289f10e649e43236f94e86f7bc","unresolved":false,"context_lines":[{"line_number":250,"context_line":""},{"line_number":251,"context_line":"2. MAC"},{"line_number":252,"context_line":""},{"line_number":253,"context_line":"The `crud_cache` class field will need the following indexing information:"},{"line_number":254,"context_line":"`topic`, and `ports.mac`. The `crud_cache` implementation will index the"},{"line_number":255,"context_line":"`topic` and nested `mac` fields automatically."},{"line_number":256,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_f017fe51","line":253,"range":{"start_line":253,"start_character":5,"end_line":253,"end_character":15},"in_reply_to":"1a6eadb0_e4c66815","updated":"2016-12-20 04:12:47.000000000","message":"Will fix.","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"a477713f2d971ad01d6601fc728d75503987be65","unresolved":false,"context_lines":[{"line_number":251,"context_line":"2. MAC"},{"line_number":252,"context_line":""},{"line_number":253,"context_line":"The `crud_cache` class field will need the following indexing information:"},{"line_number":254,"context_line":"`topic`, and `ports.mac`. The `crud_cache` implementation will index the"},{"line_number":255,"context_line":"`topic` and nested `mac` fields automatically."},{"line_number":256,"context_line":""},{"line_number":257,"context_line":"Proposed Implementation"}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_44eb9c78","line":254,"range":{"start_line":254,"start_character":7,"end_line":254,"end_character":8},"updated":"2016-12-20 02:34:48.000000000","message":"extra comma?","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"bd4608016254ac289f10e649e43236f94e86f7bc","unresolved":false,"context_lines":[{"line_number":251,"context_line":"2. MAC"},{"line_number":252,"context_line":""},{"line_number":253,"context_line":"The `crud_cache` class field will need the following indexing information:"},{"line_number":254,"context_line":"`topic`, and `ports.mac`. The `crud_cache` implementation will index the"},{"line_number":255,"context_line":"`topic` and nested `mac` fields automatically."},{"line_number":256,"context_line":""},{"line_number":257,"context_line":"Proposed Implementation"}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_700cce42","line":254,"range":{"start_line":254,"start_character":7,"end_line":254,"end_character":8},"in_reply_to":"1a6eadb0_44eb9c78","updated":"2016-12-20 04:12:47.000000000","message":"Will fix.","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"b33e3813fb5e881432ab439d9eeef48ff1bb627a","unresolved":false,"context_lines":[{"line_number":251,"context_line":"2. MAC"},{"line_number":252,"context_line":""},{"line_number":253,"context_line":"The `crud_cache` class field will need the following indexing information:"},{"line_number":254,"context_line":"`topic`, and `ports.mac`. The `crud_cache` implementation will index the"},{"line_number":255,"context_line":"`topic` and nested `mac` fields automatically."},{"line_number":256,"context_line":""},{"line_number":257,"context_line":"Proposed Implementation"}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_b8900850","line":254,"range":{"start_line":254,"start_character":7,"end_line":254,"end_character":8},"in_reply_to":"1a6eadb0_700cce42","updated":"2016-12-20 06:47:59.000000000","message":"Serial comma :)","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"a477713f2d971ad01d6601fc728d75503987be65","unresolved":false,"context_lines":[{"line_number":257,"context_line":"Proposed Implementation"},{"line_number":258,"context_line":"~~~~~~~~~~~~~~~~~~~~~~~"},{"line_number":259,"context_line":""},{"line_number":260,"context_line":"The DB Store will have, for each model, a map from instance\u0027s `id` to"},{"line_number":261,"context_line":"its object. For each direct indexing field (e.g. `topic` in the example"},{"line_number":262,"context_line":"above), the DB Store will hold a map from the indexed field to a list"},{"line_number":263,"context_line":"of objects with that field\u0027s value. Since the objects are stored by"},{"line_number":264,"context_line":"reference, there will be no object duplication between the maps."},{"line_number":265,"context_line":""},{"line_number":266,"context_line":"For nested field indexing (e.g. `ports.mac` above), there will be a map between"},{"line_number":267,"context_line":"the field to all the objects with that nested field value. If the intermediate"}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_6f3f9125","line":264,"range":{"start_line":260,"start_character":0,"end_line":264,"end_character":64},"updated":"2016-12-20 02:34:48.000000000","message":"I like the idea here, we can use a common, simple code to build the relationship between models(which might be complicating)","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20287,"name":"hujie","email":"mike.hu@huawei.com","username":"hujie"},"change_message_id":"724ab45636916f9a93e95ea50e9e88a5b235b58d","unresolved":false,"context_lines":[{"line_number":257,"context_line":"Proposed Implementation"},{"line_number":258,"context_line":"~~~~~~~~~~~~~~~~~~~~~~~"},{"line_number":259,"context_line":""},{"line_number":260,"context_line":"The DB Store will have, for each model, a map from instance\u0027s `id` to"},{"line_number":261,"context_line":"its object. For each direct indexing field (e.g. `topic` in the example"},{"line_number":262,"context_line":"above), the DB Store will hold a map from the indexed field to a list"},{"line_number":263,"context_line":"of objects with that field\u0027s value. Since the objects are stored by"},{"line_number":264,"context_line":"reference, there will be no object duplication between the maps."},{"line_number":265,"context_line":""},{"line_number":266,"context_line":"For nested field indexing (e.g. `ports.mac` above), there will be a map between"},{"line_number":267,"context_line":"the field to all the objects with that nested field value. If the intermediate"}],"source_content_type":"text/x-rst","patch_set":4,"id":"da4df55a_593d40ba","line":264,"range":{"start_line":260,"start_character":0,"end_line":264,"end_character":64},"in_reply_to":"1a6eadb0_13047f7c","updated":"2016-12-23 15:40:18.000000000","message":"+1","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"b33e3813fb5e881432ab439d9eeef48ff1bb627a","unresolved":false,"context_lines":[{"line_number":257,"context_line":"Proposed Implementation"},{"line_number":258,"context_line":"~~~~~~~~~~~~~~~~~~~~~~~"},{"line_number":259,"context_line":""},{"line_number":260,"context_line":"The DB Store will have, for each model, a map from instance\u0027s `id` to"},{"line_number":261,"context_line":"its object. For each direct indexing field (e.g. `topic` in the example"},{"line_number":262,"context_line":"above), the DB Store will hold a map from the indexed field to a list"},{"line_number":263,"context_line":"of objects with that field\u0027s value. Since the objects are stored by"},{"line_number":264,"context_line":"reference, there will be no object duplication between the maps."},{"line_number":265,"context_line":""},{"line_number":266,"context_line":"For nested field indexing (e.g. `ports.mac` above), there will be a map between"},{"line_number":267,"context_line":"the field to all the objects with that nested field value. If the intermediate"}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_f871a045","line":264,"range":{"start_line":260,"start_character":0,"end_line":264,"end_character":64},"in_reply_to":"1a6eadb0_6f3f9125","updated":"2016-12-20 06:47:59.000000000","message":"Does such indexing cover all the lookups we do in DbStore today?","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"991c9b4c7658a0a61c8e7da0adc7c566d5f1ec9a","unresolved":false,"context_lines":[{"line_number":257,"context_line":"Proposed Implementation"},{"line_number":258,"context_line":"~~~~~~~~~~~~~~~~~~~~~~~"},{"line_number":259,"context_line":""},{"line_number":260,"context_line":"The DB Store will have, for each model, a map from instance\u0027s `id` to"},{"line_number":261,"context_line":"its object. For each direct indexing field (e.g. `topic` in the example"},{"line_number":262,"context_line":"above), the DB Store will hold a map from the indexed field to a list"},{"line_number":263,"context_line":"of objects with that field\u0027s value. Since the objects are stored by"},{"line_number":264,"context_line":"reference, there will be no object duplication between the maps."},{"line_number":265,"context_line":""},{"line_number":266,"context_line":"For nested field indexing (e.g. `ports.mac` above), there will be a map between"},{"line_number":267,"context_line":"the field to all the objects with that nested field value. If the intermediate"}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_13047f7c","line":264,"range":{"start_line":260,"start_character":0,"end_line":264,"end_character":64},"in_reply_to":"1a6eadb0_f871a045","updated":"2016-12-20 07:20:23.000000000","message":"I think so, yes.","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"a477713f2d971ad01d6601fc728d75503987be65","unresolved":false,"context_lines":[{"line_number":301,"context_line":""},{"line_number":302,"context_line":"* Remove legacy API"},{"line_number":303,"context_line":""},{"line_number":304,"context_line":"* Automatic migration code (Can be done in parallel)"},{"line_number":305,"context_line":""},{"line_number":306,"context_line":"* Configuration file options (Can be done in parallel)"},{"line_number":307,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_8f35cddc","line":304,"range":{"start_line":304,"start_character":1,"end_line":304,"end_character":52},"updated":"2016-12-20 02:34:48.000000000","message":"Do you mention this patch here?\n\nhttps://review.openstack.org/#/c/401210/","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"b33e3813fb5e881432ab439d9eeef48ff1bb627a","unresolved":false,"context_lines":[{"line_number":301,"context_line":""},{"line_number":302,"context_line":"* Remove legacy API"},{"line_number":303,"context_line":""},{"line_number":304,"context_line":"* Automatic migration code (Can be done in parallel)"},{"line_number":305,"context_line":""},{"line_number":306,"context_line":"* Configuration file options (Can be done in parallel)"},{"line_number":307,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_b89e4852","line":304,"range":{"start_line":304,"start_character":1,"end_line":304,"end_character":52},"in_reply_to":"1a6eadb0_0426ffb9","updated":"2016-12-20 06:47:59.000000000","message":"A short info on how that will be done?","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"bd4608016254ac289f10e649e43236f94e86f7bc","unresolved":false,"context_lines":[{"line_number":301,"context_line":""},{"line_number":302,"context_line":"* Remove legacy API"},{"line_number":303,"context_line":""},{"line_number":304,"context_line":"* Automatic migration code (Can be done in parallel)"},{"line_number":305,"context_line":""},{"line_number":306,"context_line":"* Configuration file options (Can be done in parallel)"},{"line_number":307,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_0426ffb9","line":304,"range":{"start_line":304,"start_character":1,"end_line":304,"end_character":52},"in_reply_to":"1a6eadb0_8f35cddc","updated":"2016-12-20 04:12:47.000000000","message":"I\u0027ll add that. Actually this patch is a requirement (I assumed it would pass). This bullet is actually writing the migration scripts used by this patch automatically.","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"991c9b4c7658a0a61c8e7da0adc7c566d5f1ec9a","unresolved":false,"context_lines":[{"line_number":301,"context_line":""},{"line_number":302,"context_line":"* Remove legacy API"},{"line_number":303,"context_line":""},{"line_number":304,"context_line":"* Automatic migration code (Can be done in parallel)"},{"line_number":305,"context_line":""},{"line_number":306,"context_line":"* Configuration file options (Can be done in parallel)"},{"line_number":307,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"1a6eadb0_730f7388","line":304,"range":{"start_line":304,"start_character":1,"end_line":304,"end_character":52},"in_reply_to":"1a6eadb0_b89e4852","updated":"2016-12-20 07:20:23.000000000","message":"Will add. Will probably look like this:\n\nThe automatic migration code will generate files to be placed in dragonflow.migration. They will use the timestamp of code generation. The generation will review the differences between the object before and after the change (retrieved using git magic), and generate the script to migrate. A developer will have to review the result to verify there are not errors.","commit_id":"c466fbb3938a7d27b08ae5d58202bd9cd39163e8"}]}
