)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"ac16f2c1273189beb67103b81417513ea5dd7ac4","unresolved":false,"context_lines":[{"line_number":18,"context_line":""},{"line_number":19,"context_line":"or:"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":" compute_node \u003d ptree.find(cn.uuid)"},{"line_number":22,"context_line":" for cntree_provider in compute_node.all_by_uuid().values():"},{"line_number":23,"context_line":"     do_stuff_with(cntree_provider)"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"Change-Id: I994442830588ee37eda409370a07152903b2e817"},{"line_number":26,"context_line":"blueprint: nested-resource-providers"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"1f485f77_9d4eeebe","line":23,"range":{"start_line":21,"start_character":0,"end_line":23,"end_character":35},"updated":"2017-11-17 16:52:27.000000000","message":"I\u0027m not entirely convinced we will be using this pattern, but I\u0027ll go along with you for now...\n\nTo be clear, I definitely see the virt drivers doing this:\n\n compute_node \u003d ptree.find(cn.uuid)\n\nBut the thing that the virt drivers will be traversing will not really be the ProviderTree. Rather, the virt drivers (and GDM) will be traversing their *own* structures that store device, NUMA, and other information and then calling ProviderTree.find(), ProviderTree.new_child() and ProviderTree.update_inventory() accordingly.\n\nFor instance, the libvirt driver would be doing something like this for PCI devices:\n\n pci_devs \u003d self.get_pci_devices()\n for pci_dev in pci_devs:\n     # assume libvirt looks up via device address...\n     if not prov_tree.exists(pci_dev.address):\n         # create a new provider for PCI resources under the\n         # compute node provider\n         prov_tree.new_child(name\u003dpci_dev.address, parent_provider_uuid\u003dcn.uuid)\n     prov_tree.update_inventory(pci_dev.address, ...)\n\nIt\u0027s this part of your example:\n\n do_stuff_with(cntree_provider)\n\nthat is dangerous because all of the actions against a _Provider object are not thread-safe unless done via the ProviderTree interface. I\u0027m really considering reworking these interfaces to make them harder to misuse... :(","commit_id":"4df19ebf2994962e058a323ccb049ef3b6ab3a76"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"5ad7a4b32f40513efe3d126261df3f6a804e0ae0","unresolved":false,"context_lines":[{"line_number":18,"context_line":""},{"line_number":19,"context_line":"or:"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":" compute_node \u003d ptree.find(cn.uuid)"},{"line_number":22,"context_line":" for cntree_provider in compute_node.all_by_uuid().values():"},{"line_number":23,"context_line":"     do_stuff_with(cntree_provider)"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"Change-Id: I994442830588ee37eda409370a07152903b2e817"},{"line_number":26,"context_line":"blueprint: nested-resource-providers"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"1f485f77_b86c189c","line":23,"range":{"start_line":21,"start_character":0,"end_line":23,"end_character":35},"in_reply_to":"1f485f77_38402807","updated":"2017-11-17 17:07:54.000000000","message":"I know, and that\u0027s why I\u0027m considering reworking the ProviderTree interface to make it impossible to abuse in this way...","commit_id":"4df19ebf2994962e058a323ccb049ef3b6ab3a76"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c153f641653958344dc8bf7168377ce879410994","unresolved":false,"context_lines":[{"line_number":18,"context_line":""},{"line_number":19,"context_line":"or:"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":" compute_node \u003d ptree.find(cn.uuid)"},{"line_number":22,"context_line":" for cntree_provider in compute_node.all_by_uuid().values():"},{"line_number":23,"context_line":"     do_stuff_with(cntree_provider)"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"Change-Id: I994442830588ee37eda409370a07152903b2e817"},{"line_number":26,"context_line":"blueprint: nested-resource-providers"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"1f485f77_38402807","line":23,"range":{"start_line":21,"start_character":0,"end_line":23,"end_character":35},"in_reply_to":"1f485f77_386f08c6","updated":"2017-11-17 17:06:00.000000000","message":"But that\u0027s what find() returns??","commit_id":"4df19ebf2994962e058a323ccb049ef3b6ab3a76"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"990fbb184e0864f875ac3d1ca0fd90371b5965ca","unresolved":false,"context_lines":[{"line_number":18,"context_line":""},{"line_number":19,"context_line":"or:"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":" compute_node \u003d ptree.find(cn.uuid)"},{"line_number":22,"context_line":" for cntree_provider in compute_node.all_by_uuid().values():"},{"line_number":23,"context_line":"     do_stuff_with(cntree_provider)"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"Change-Id: I994442830588ee37eda409370a07152903b2e817"},{"line_number":26,"context_line":"blueprint: nested-resource-providers"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"1f485f77_386f08c6","line":23,"range":{"start_line":21,"start_character":0,"end_line":23,"end_character":35},"in_reply_to":"1f485f77_9d4eeebe","updated":"2017-11-17 16:58:59.000000000","message":"Incidentally, the reason why my original proposed code had a ProviderTree.uuid_set() method was so we would not return a dict of references to _Provider objects since those objects aren\u0027t safe to operate on in a thread-safe way.","commit_id":"4df19ebf2994962e058a323ccb049ef3b6ab3a76"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"3016038c63f9229ae603d5bc932eff15fad58f55","unresolved":false,"context_lines":[{"line_number":18,"context_line":""},{"line_number":19,"context_line":"or:"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":" compute_node \u003d ptree.find(cn.uuid)"},{"line_number":22,"context_line":" for cntree_provider in compute_node.all_by_uuid().values():"},{"line_number":23,"context_line":"     do_stuff_with(cntree_provider)"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"Change-Id: I994442830588ee37eda409370a07152903b2e817"},{"line_number":26,"context_line":"blueprint: nested-resource-providers"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"1f485f77_ed3c0f94","line":23,"range":{"start_line":21,"start_character":0,"end_line":23,"end_character":35},"in_reply_to":"1f485f77_b86c189c","updated":"2017-11-17 20:19:45.000000000","message":"Done","commit_id":"4df19ebf2994962e058a323ccb049ef3b6ab3a76"}],"nova/compute/provider_tree.py":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"0c9ed6a263232f319f0581fefa52b3231997f12e","unresolved":false,"context_lines":[{"line_number":65,"context_line":"        return None"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"    def __iter__(self):"},{"line_number":68,"context_line":"        \"\"\"Recurse, yielding every provider in this (sub)tree.\"\"\""},{"line_number":69,"context_line":"        yield self"},{"line_number":70,"context_line":"        for child in self.children.values():"},{"line_number":71,"context_line":"            for descendant in child:"}],"source_content_type":"text/x-python","patch_set":1,"id":"1f485f77_a0288796","line":68,"updated":"2017-11-16 14:47:52.000000000","message":"Turns out we actually have to *guarantee* that this yields tree nodes in a top-down order.  Doesn\u0027t matter if it\u0027s breadth- or depth-first, but we can\u0027t see any given node before we see its parent.\n\nI believe the current algorithm satisfies that constraint, but the docstring needs to be updated accordingly, and...","commit_id":"a40a38218d6f1473a61aaf9dbab1872a458810b9"},{"author":{"_account_id":25638,"name":"Naichuan Sun","email":"naichuan.sun@citrix.com","username":"naichuans"},"change_message_id":"6e949d5e6f4257fdbae42a446ce322ecbffd9045","unresolved":false,"context_lines":[{"line_number":48,"context_line":"        # dict of inventory records, keyed by resource class"},{"line_number":49,"context_line":"        self.inventory \u003d {}"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    def uuid_set(self):"},{"line_number":52,"context_line":"        \"\"\"Returns a set of UUIDs of this provider and all its descendants.\"\"\""},{"line_number":53,"context_line":"        ret \u003d set([self.uuid])"},{"line_number":54,"context_line":"        for child in self.children.values():"}],"source_content_type":"text/x-python","patch_set":5,"id":"ff82abbf_967e5517","line":51,"updated":"2017-11-23 09:22:09.000000000","message":"Hi, Eric. Why don\u0027t we do the traverse in class ProviderTree?\nIf we do it in _Provider, it would make me think the root node is a privileged node, it has the right to browse all the children nodes. Is it designed like that?","commit_id":"a58a7737e41422e1c6ca6e4831a8af1130ab6908"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"e83fd90afbd0e3eae82c8cf77283c4ff43a2d426","unresolved":false,"context_lines":[{"line_number":48,"context_line":"        # dict of inventory records, keyed by resource class"},{"line_number":49,"context_line":"        self.inventory \u003d {}"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    def uuid_set(self):"},{"line_number":52,"context_line":"        \"\"\"Returns a set of UUIDs of this provider and all its descendants.\"\"\""},{"line_number":53,"context_line":"        ret \u003d set([self.uuid])"},{"line_number":54,"context_line":"        for child in self.children.values():"}],"source_content_type":"text/x-python","patch_set":5,"id":"ff82abbf_98375be4","line":51,"in_reply_to":"ff82abbf_967e5517","updated":"2017-11-23 15:27:28.000000000","message":"We traverse the set of root nodes from the ProviderTree object (below). However, for a single resource provider node in the tree, Eric\u0027s made this convenience method to iterate over and return the UUIDs for just this provider and its children.\n\nI actually think this convenience method should be \"hidden\" by making it _uuid_set() to mark it as an internal function that should not be called. This should only be called by ProviderTree in its public uuid_set() method since that holds the tree lock and thus calls to this method on an individual node in the tree are thread-safe. It is *not* thread-safe for non-ProviderTree callers to call this method on the _Provider object nodes.","commit_id":"a58a7737e41422e1c6ca6e4831a8af1130ab6908"},{"author":{"_account_id":25638,"name":"Naichuan Sun","email":"naichuan.sun@citrix.com","username":"naichuans"},"change_message_id":"91be9bc9f5c4ab0dab93158aa820c850df99699d","unresolved":false,"context_lines":[{"line_number":48,"context_line":"        # dict of inventory records, keyed by resource class"},{"line_number":49,"context_line":"        self.inventory \u003d {}"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    def uuid_set(self):"},{"line_number":52,"context_line":"        \"\"\"Returns a set of UUIDs of this provider and all its descendants.\"\"\""},{"line_number":53,"context_line":"        ret \u003d set([self.uuid])"},{"line_number":54,"context_line":"        for child in self.children.values():"}],"source_content_type":"text/x-python","patch_set":5,"id":"ff82abbf_9509592d","line":51,"in_reply_to":"ff82abbf_98375be4","updated":"2017-11-24 02:00:54.000000000","message":"@Eric, suggest adding two functions like uuid_to_name() and name_to_uuid() in provider tree. Sometimes we need such kind of query, especially after you provide the uuid_set() API :)","commit_id":"a58a7737e41422e1c6ca6e4831a8af1130ab6908"},{"author":{"_account_id":25638,"name":"Naichuan Sun","email":"naichuan.sun@citrix.com","username":"naichuans"},"change_message_id":"235d228886415c073b3109910a095bd0db21b331","unresolved":false,"context_lines":[{"line_number":48,"context_line":"        # dict of inventory records, keyed by resource class"},{"line_number":49,"context_line":"        self.inventory \u003d {}"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    def uuid_set(self):"},{"line_number":52,"context_line":"        \"\"\"Returns a set of UUIDs of this provider and all its descendants.\"\"\""},{"line_number":53,"context_line":"        ret \u003d set([self.uuid])"},{"line_number":54,"context_line":"        for child in self.children.values():"}],"source_content_type":"text/x-python","patch_set":5,"id":"ff82abbf_da8ab019","line":51,"in_reply_to":"ff82abbf_98375be4","updated":"2017-11-24 01:26:14.000000000","message":"Thank you very much, @Jay. Just get a node\u0027s subtree through provider tree API looks more reasonable。","commit_id":"a58a7737e41422e1c6ca6e4831a8af1130ab6908"},{"author":{"_account_id":25638,"name":"Naichuan Sun","email":"naichuan.sun@citrix.com","username":"naichuans"},"change_message_id":"6e949d5e6f4257fdbae42a446ce322ecbffd9045","unresolved":false,"context_lines":[{"line_number":136,"context_line":"                p \u003d _Provider(cn.hypervisor_hostname, cn.uuid)"},{"line_number":137,"context_line":"                self.roots.append(p)"},{"line_number":138,"context_line":""},{"line_number":139,"context_line":"    def uuid_set(self):"},{"line_number":140,"context_line":"        \"\"\"Return a set of the UUIDs of all providers.\"\"\""},{"line_number":141,"context_line":"        ret \u003d set()"},{"line_number":142,"context_line":"        with self.lock:"}],"source_content_type":"text/x-python","patch_set":5,"id":"ff82abbf_331e7b70","line":139,"updated":"2017-11-23 09:22:09.000000000","message":"Hi, Eric. This function looks not so natural to me.\n _Provider.uuid_set() the name doesn\u0027t sound like a function which used to get the current node and its descendants uuids.","commit_id":"a58a7737e41422e1c6ca6e4831a8af1130ab6908"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"924880a05107b01ee664fc1365af5a6dd1c516c2","unresolved":false,"context_lines":[{"line_number":48,"context_line":"        # dict of inventory records, keyed by resource class"},{"line_number":49,"context_line":"        self.inventory \u003d {}"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    def uuid_set(self):"},{"line_number":52,"context_line":"        \"\"\"Returns a set of UUIDs of this provider and all its descendants.\"\"\""},{"line_number":53,"context_line":"        ret \u003d set([self.uuid])"},{"line_number":54,"context_line":"        for child in self.children.values():"}],"source_content_type":"text/x-python","patch_set":9,"id":"df87a7cf_d421704f","line":51,"range":{"start_line":51,"start_character":8,"end_line":51,"end_character":16},"updated":"2017-12-04 16:16:20.000000000","message":"did you want to make this _uuid_set() to \"hide\" it from potential callers?","commit_id":"7eff852ce5f54daf4aede622acce6fd059ad2bef"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"7d15a3d1652bbf60adc629c6176f549a8d23d40e","unresolved":false,"context_lines":[{"line_number":48,"context_line":"        # dict of inventory records, keyed by resource class"},{"line_number":49,"context_line":"        self.inventory \u003d {}"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    def uuid_set(self):"},{"line_number":52,"context_line":"        \"\"\"Returns a set of UUIDs of this provider and all its descendants.\"\"\""},{"line_number":53,"context_line":"        ret \u003d set([self.uuid])"},{"line_number":54,"context_line":"        for child in self.children.values():"}],"source_content_type":"text/x-python","patch_set":9,"id":"df87a7cf_f47354e6","line":51,"range":{"start_line":51,"start_character":8,"end_line":51,"end_character":16},"in_reply_to":"df87a7cf_d421704f","updated":"2017-12-04 16:29:23.000000000","message":"No, because the class is already private and (as of the previous change set in the series) inaccessible.  All the other methods in the class are marked public, so I saw no reason for this one to be otherwise.  (Also, my IDE complains gently if you access a private member of an object, which ProviderTree would be doing on L149/155.)","commit_id":"7eff852ce5f54daf4aede622acce6fd059ad2bef"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"7eb176cee51fb04e97a90f70ec86fd1a6781a215","unresolved":false,"context_lines":[{"line_number":48,"context_line":"        # dict of inventory records, keyed by resource class"},{"line_number":49,"context_line":"        self.inventory \u003d {}"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    def uuid_set(self):"},{"line_number":52,"context_line":"        \"\"\"Returns a set of UUIDs of this provider and all its descendants.\"\"\""},{"line_number":53,"context_line":"        ret \u003d set([self.uuid])"},{"line_number":54,"context_line":"        for child in self.children.values():"}],"source_content_type":"text/x-python","patch_set":9,"id":"df87a7cf_7ac96b76","line":51,"range":{"start_line":51,"start_character":8,"end_line":51,"end_character":16},"in_reply_to":"df87a7cf_f47354e6","updated":"2017-12-04 17:17:48.000000000","message":"ack.","commit_id":"7eff852ce5f54daf4aede622acce6fd059ad2bef"}],"nova/tests/unit/compute/test_provider_tree.py":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"0c9ed6a263232f319f0581fefa52b3231997f12e","unresolved":false,"context_lines":[{"line_number":70,"context_line":"        self.assertTrue(pt.exists(pf1_cell0.uuid))"},{"line_number":71,"context_line":"        self.assertTrue(pt.exists(\u0027pf1_cell0\u0027))"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"        # Now we\u0027ve got a 3-level tree - check the iterator again"},{"line_number":74,"context_line":"        self.assertEqual(set([cn1root, numa_cell0, pf1_cell0, numa_cell1]),"},{"line_number":75,"context_line":"                         set(p for p in cn1root))"},{"line_number":76,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"1f485f77_43067d1e","line":73,"updated":"2017-11-16 14:47:52.000000000","message":"...this test case needs to validate that ordering constraint.\n\nThe simple way would be to un-set()ify the expected \u0026 observed.  That\u0027s enforcing a tighter constraint than we actually need - but I think I can live with that.","commit_id":"a40a38218d6f1473a61aaf9dbab1872a458810b9"}]}
