)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"586dad17bde0f6def48e5e84a548919553499ea5","unresolved":false,"context_lines":[{"line_number":11,"context_line":"non-nested PCI devices (i.e. not SR-IOV PF/VF relationships), which are"},{"line_number":12,"context_line":"easy to reason about given that they are managed as a simple single"},{"line_number":13,"context_line":"whole unit that is allocated to a single consumer."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"Change-Id: I97a0584cf970ed19dbd0f47901f7d1e71bec5fbb"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"5a8bc5a2_03b617dc","line":14,"updated":"2016-09-22 14:15:31.000000000","message":"We should probably track this against a blueprint, some specless blueprint, I\u0027m not sure what that would be - resource-providers-ocata? Or some inventory blueprint for ocata (continued work that is).","commit_id":"63fc33b3f44be16a13e9cf176bcfe2d5bae3a374"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"f152d5486bd339fc886798e729e1d56533b87ad0","unresolved":false,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Adds tracking of generic PCI passthrough devices to the inventory"},{"line_number":10,"context_line":"handling in the scheduler reporting client. For now, we only handle"},{"line_number":11,"context_line":"non-nested PCI devices (i.e. not SR-IOV PF/VF relationships), which are"},{"line_number":12,"context_line":"easy to reason about given that they are managed as a simple single"},{"line_number":13,"context_line":"whole unit that is allocated to a single consumer."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"blueprint: inventory-allocation-ocata"},{"line_number":16,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":9,"id":"5a74a57a_54ac1c35","line":13,"range":{"start_line":11,"start_character":62,"end_line":13,"end_character":50},"updated":"2016-11-24 12:37:23.000000000","message":"As I understand it, the user requests a specific PCI alias in the flavor, like \"gold_gpu:1\" or \"silver_gpu:2\", so we would need to find a host with the correct alias and matching quantity.\n\nSurely we want to treat this more like ironic\u0027s dynamic resource classes, so we create a dynamic class for each PCI alias?\n\nI guess there are tags as well on the whitelist, that match the networks, so thats probably something very similar, but only really relevant for SR-IOV. So lets ignore that.\n\nPS I am looking here to remind me of the current state of things:\nhttp://docs.openstack.org/admin-guide/compute-pci-passthrough.html\nand here:\nhttps://github.com/openstack/nova/blob/aa7c3aef956fcbdfe1c31a27dc48f0ce524c8619/nova/pci/request.py#L148\n\nI suspect I am missing something, but how does a user attach a PCI device without using the alias in the flavor?","commit_id":"ec29ad8e277a41799a70cdcdba1af6fc273a9743"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"af883a32aefd94c707a60dc488e8dae80184673f","unresolved":false,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Adds tracking of generic PCI passthrough devices to the inventory"},{"line_number":10,"context_line":"handling in the scheduler reporting client. For now, we only handle"},{"line_number":11,"context_line":"non-nested PCI devices (i.e. not SR-IOV PF/VF relationships), which are"},{"line_number":12,"context_line":"easy to reason about given that they are managed as a simple single"},{"line_number":13,"context_line":"whole unit that is allocated to a single consumer."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"blueprint: inventory-allocation-ocata"},{"line_number":16,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":9,"id":"5a74a57a_d21e2e6f","line":13,"range":{"start_line":11,"start_character":62,"end_line":13,"end_character":50},"in_reply_to":"5a74a57a_54ac1c35","updated":"2016-11-28 00:12:09.000000000","message":"John, this code doesn\u0027t change anything at all about how a PCI device is attached to a flavor. This code only exists in the resource tracker. The scheduler report client simply relays the inventory/allocation information from the PciDeviceList object that is supplied to it by the resource tracker.","commit_id":"ec29ad8e277a41799a70cdcdba1af6fc273a9743"}],"nova/compute/resource_tracker.py":[{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"26895180ec79d41a9b685066dd980935d08c820c","unresolved":false,"context_lines":[{"line_number":432,"context_line":"            self._setup_pci_tracker(context, resources)"},{"line_number":433,"context_line":"            self.scheduler_client.update_compute_node_resource_stats("},{"line_number":434,"context_line":"                    self.compute_node,"},{"line_number":435,"context_line":"                    self.pci_tracker.pci_devs)"},{"line_number":436,"context_line":"            return"},{"line_number":437,"context_line":""},{"line_number":438,"context_line":"        # there was no local copy and none in the database"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a8bc5a2_56bb7675","line":435,"updated":"2016-09-28 10:57:08.000000000","message":"Not entirely germane to this change, so mostly just idly commenting: presumably we could cut some duped lines here (417-435) with a\n\n    self.compute_node \u003d self.compute_node or self._get_compute_node(context)","commit_id":"0c97e3e1c1699931f1dafc024b4979d0a057b03a"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"beef5b93c3894a62edf086af3edc3cc68f712f08","unresolved":false,"context_lines":[{"line_number":419,"context_line":"            self._setup_pci_tracker(context, resources)"},{"line_number":420,"context_line":"            self.scheduler_client.update_compute_node_resource_stats("},{"line_number":421,"context_line":"                    self.compute_node,"},{"line_number":422,"context_line":"                    self.pci_tracker.pci_devs)"},{"line_number":423,"context_line":"            return"},{"line_number":424,"context_line":""},{"line_number":425,"context_line":"        # now try to get the compute node record from the"}],"source_content_type":"text/x-python","patch_set":9,"id":"7a77a97e_ae7d0070","line":422,"range":{"start_line":422,"start_character":20,"end_line":422,"end_character":46},"updated":"2016-11-16 17:28:14.000000000","message":"I cringe when I see this sort of special snowflake handling, but to be honest, I don\u0027t see a better way, given the current design.","commit_id":"ec29ad8e277a41799a70cdcdba1af6fc273a9743"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"4057a33d814d7db7442aceedb5e39946f6cd9f39","unresolved":false,"context_lines":[{"line_number":419,"context_line":"            self._setup_pci_tracker(context, resources)"},{"line_number":420,"context_line":"            self.scheduler_client.update_compute_node_resource_stats("},{"line_number":421,"context_line":"                    self.compute_node,"},{"line_number":422,"context_line":"                    self.pci_tracker.pci_devs)"},{"line_number":423,"context_line":"            return"},{"line_number":424,"context_line":""},{"line_number":425,"context_line":"        # now try to get the compute node record from the"}],"source_content_type":"text/x-python","patch_set":9,"id":"7a77a97e_1992bd9e","line":422,"range":{"start_line":422,"start_character":20,"end_line":422,"end_character":46},"in_reply_to":"7a77a97e_ae7d0070","updated":"2016-11-16 18:53:30.000000000","message":"Yeah, agreed. Baby steps, but we\u0027re slowly getting there...","commit_id":"ec29ad8e277a41799a70cdcdba1af6fc273a9743"}],"nova/scheduler/client/report.py":[{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"31bf2eae150771ad8ddd41a3ebf5b43f6c9e961d","unresolved":false,"context_lines":[{"line_number":33,"context_line":"MEMORY_MB \u003d fields.ResourceClass.MEMORY_MB"},{"line_number":34,"context_line":"DISK_GB \u003d fields.ResourceClass.DISK_GB"},{"line_number":35,"context_line":"PCI_DEVICE \u003d fields.ResourceClass.PCI_DEVICE"},{"line_number":36,"context_line":"DEV_TYPE_STANDARD \u003d fields.PciDeviceType.STANDARD"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"def safe_connect(f):"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a8bc5a2_b0aa02d3","line":36,"range":{"start_line":36,"start_character":0,"end_line":36,"end_character":4},"updated":"2016-09-22 17:50:34.000000000","message":"Nit: I would prefer \u0027DEVICE_\u0027 instead of \u0027DEV_\u0027. I know the attribute is \u0027dev_type\u0027, but for a constant that is outside of the pci object context, spelling it out is clearer.","commit_id":"ccc6f65afea5d1edf8bbe9d5d27cb6c020dab8c4"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"0269dd46c0945288f2429b683c001d990a3593f5","unresolved":false,"context_lines":[{"line_number":33,"context_line":"MEMORY_MB \u003d fields.ResourceClass.MEMORY_MB"},{"line_number":34,"context_line":"DISK_GB \u003d fields.ResourceClass.DISK_GB"},{"line_number":35,"context_line":"PCI_DEVICE \u003d fields.ResourceClass.PCI_DEVICE"},{"line_number":36,"context_line":"DEV_TYPE_STANDARD \u003d fields.PciDeviceType.STANDARD"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"def safe_connect(f):"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a8bc5a2_c8a08346","line":36,"range":{"start_line":36,"start_character":0,"end_line":36,"end_character":4},"in_reply_to":"5a8bc5a2_b0aa02d3","updated":"2016-09-23 16:01:45.000000000","message":"Done","commit_id":"ccc6f65afea5d1edf8bbe9d5d27cb6c020dab8c4"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"31bf2eae150771ad8ddd41a3ebf5b43f6c9e961d","unresolved":false,"context_lines":[{"line_number":95,"context_line":"            \u0027allocation_ratio\u0027: compute_node.disk_allocation_ratio,"},{"line_number":96,"context_line":"        },"},{"line_number":97,"context_line":"    }"},{"line_number":98,"context_line":"    if len(pci_devices) \u003e 0:"},{"line_number":99,"context_line":"        result[PCI_DEVICE] \u003d {"},{"line_number":100,"context_line":"            \u0027total\u0027: len([d for d in pci_devices"},{"line_number":101,"context_line":"                          if d.dev_type \u003d\u003d DEV_TYPE_STANDARD]),"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a8bc5a2_50637e1a","line":98,"range":{"start_line":98,"start_character":4,"end_line":98,"end_character":28},"updated":"2016-09-22 17:50:34.000000000","message":"I really wish that o.vo defined __bool__/__nonzero__ so that this wouldn\u0027t be necessary. :(","commit_id":"ccc6f65afea5d1edf8bbe9d5d27cb6c020dab8c4"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"31bf2eae150771ad8ddd41a3ebf5b43f6c9e961d","unresolved":false,"context_lines":[{"line_number":360,"context_line":"        return True"},{"line_number":361,"context_line":""},{"line_number":362,"context_line":"    @safe_connect"},{"line_number":363,"context_line":"    def _update_inventory(self, compute_node, pci_devs):"},{"line_number":364,"context_line":"        inv_data \u003d _objects_to_inventory_dict(compute_node, pci_devs)"},{"line_number":365,"context_line":"        for attempt in (1, 2, 3):"},{"line_number":366,"context_line":"            if compute_node.uuid not in self._resource_providers:"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a8bc5a2_cd2290b9","line":363,"range":{"start_line":363,"start_character":8,"end_line":363,"end_character":55},"updated":"2016-09-22 17:50:34.000000000","message":"It seems inconsistent that the code changes above are moving from compute_node to a more generic resource_provider, but this and the next are becoming more specifically compute_node based. Maybe change the names of these methods to indicate that they are specific to compute_nodes?","commit_id":"ccc6f65afea5d1edf8bbe9d5d27cb6c020dab8c4"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"468c9618910240d2e745e5bd337d9d29956685b5","unresolved":false,"context_lines":[{"line_number":360,"context_line":"        return True"},{"line_number":361,"context_line":""},{"line_number":362,"context_line":"    @safe_connect"},{"line_number":363,"context_line":"    def _update_inventory(self, compute_node, pci_devs):"},{"line_number":364,"context_line":"        inv_data \u003d _objects_to_inventory_dict(compute_node, pci_devs)"},{"line_number":365,"context_line":"        for attempt in (1, 2, 3):"},{"line_number":366,"context_line":"            if compute_node.uuid not in self._resource_providers:"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a8bc5a2_cdcb2752","line":363,"range":{"start_line":363,"start_character":8,"end_line":363,"end_character":55},"in_reply_to":"5a8bc5a2_485ab350","updated":"2016-09-23 20:45:45.000000000","message":"I meant the update_resource_stats() method below, which takes a compute node.","commit_id":"ccc6f65afea5d1edf8bbe9d5d27cb6c020dab8c4"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"0269dd46c0945288f2429b683c001d990a3593f5","unresolved":false,"context_lines":[{"line_number":360,"context_line":"        return True"},{"line_number":361,"context_line":""},{"line_number":362,"context_line":"    @safe_connect"},{"line_number":363,"context_line":"    def _update_inventory(self, compute_node, pci_devs):"},{"line_number":364,"context_line":"        inv_data \u003d _objects_to_inventory_dict(compute_node, pci_devs)"},{"line_number":365,"context_line":"        for attempt in (1, 2, 3):"},{"line_number":366,"context_line":"            if compute_node.uuid not in self._resource_providers:"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a8bc5a2_485ab350","line":363,"range":{"start_line":363,"start_character":8,"end_line":363,"end_character":55},"in_reply_to":"5a8bc5a2_cd2290b9","updated":"2016-09-23 16:01:45.000000000","message":"I can change _update_inventory() to _update_compute_node_inventory(), but _update_inventory_attempt() is taking a generic dict of inventory information and should stay named that way.","commit_id":"ccc6f65afea5d1edf8bbe9d5d27cb6c020dab8c4"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"31bf2eae150771ad8ddd41a3ebf5b43f6c9e961d","unresolved":false,"context_lines":[{"line_number":390,"context_line":"              ComputeNode object."},{"line_number":391,"context_line":""},{"line_number":392,"context_line":"        :param compute_node: updated nova.objects.ComputeNode to report"},{"line_number":393,"context_line":"        :param pci_devices: `objects.PciDeviceLit` containing information about"},{"line_number":394,"context_line":"                            the compute host\u0027s PCI devices."},{"line_number":395,"context_line":"        \"\"\""},{"line_number":396,"context_line":"        compute_node.save()"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a8bc5a2_2d185484","line":393,"range":{"start_line":393,"start_character":37,"end_line":393,"end_character":49},"updated":"2016-09-22 17:50:34.000000000","message":"s/PciDeviceLit/PciDeviceList","commit_id":"ccc6f65afea5d1edf8bbe9d5d27cb6c020dab8c4"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"0269dd46c0945288f2429b683c001d990a3593f5","unresolved":false,"context_lines":[{"line_number":390,"context_line":"              ComputeNode object."},{"line_number":391,"context_line":""},{"line_number":392,"context_line":"        :param compute_node: updated nova.objects.ComputeNode to report"},{"line_number":393,"context_line":"        :param pci_devices: `objects.PciDeviceLit` containing information about"},{"line_number":394,"context_line":"                            the compute host\u0027s PCI devices."},{"line_number":395,"context_line":"        \"\"\""},{"line_number":396,"context_line":"        compute_node.save()"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a8bc5a2_a835f7f7","line":393,"range":{"start_line":393,"start_character":37,"end_line":393,"end_character":49},"in_reply_to":"5a8bc5a2_2d185484","updated":"2016-09-23 16:01:45.000000000","message":"Done","commit_id":"ccc6f65afea5d1edf8bbe9d5d27cb6c020dab8c4"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"26895180ec79d41a9b685066dd980935d08c820c","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"5a8bc5a2_aaae0ae5","updated":"2016-09-28 10:57:08.000000000","message":"The way you\u0027ve put this together is handy because it makes the clunkiness of the pci tracker stuff extra obvious for future cleanup.","commit_id":"0c97e3e1c1699931f1dafc024b4979d0a057b03a"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"2cfa9509e56a71ea42c7b8bf7a7dfc69caa9952e","unresolved":false,"context_lines":[{"line_number":279,"context_line":"        self._resource_providers[uuid] \u003d rp"},{"line_number":280,"context_line":"        return rp"},{"line_number":281,"context_line":""},{"line_number":282,"context_line":"    def _get_inventory(self, rp_uuid):"},{"line_number":283,"context_line":"        url \u003d \u0027/resource_providers/%s/inventories\u0027 % rp_uuid"},{"line_number":284,"context_line":"        result \u003d self.get(url)"},{"line_number":285,"context_line":"        if not result:"},{"line_number":286,"context_line":"            return {\u0027inventories\u0027: {}}"},{"line_number":287,"context_line":"        return result.json()"},{"line_number":288,"context_line":""},{"line_number":289,"context_line":"    def _update_inventory_attempt(self, rp_uuid, inv_data):"},{"line_number":290,"context_line":"        \"\"\"Update, if needed, the inventory records in the placement API using"},{"line_number":291,"context_line":"        the supplied inventory dict."},{"line_number":292,"context_line":""},{"line_number":293,"context_line":"        :param rp_uuid: UUID of the resource provider to update inventory for"},{"line_number":294,"context_line":"        :param inv_data: Dict, keyed by resource class, of inventory"},{"line_number":295,"context_line":"                         information"},{"line_number":296,"context_line":"        :returns: True if the inventory was updated (or did not need to be),"},{"line_number":297,"context_line":"                  False otherwise."},{"line_number":298,"context_line":"        \"\"\""},{"line_number":299,"context_line":"        curr \u003d self._get_inventory(rp_uuid)"},{"line_number":300,"context_line":""},{"line_number":301,"context_line":"        # Update our generation immediately, if possible. Even if there"},{"line_number":302,"context_line":"        # are no inventories we should always have a generation but let\u0027s"},{"line_number":303,"context_line":"        # be careful."},{"line_number":304,"context_line":"        server_gen \u003d curr.get(\u0027resource_provider_generation\u0027)"},{"line_number":305,"context_line":"        if server_gen:"},{"line_number":306,"context_line":"            my_rp \u003d self._resource_providers[rp_uuid]"},{"line_number":307,"context_line":"            if server_gen !\u003d my_rp.generation:"},{"line_number":308,"context_line":"                LOG.debug(\u0027Updating our resource provider generation \u0027"},{"line_number":309,"context_line":"                          \u0027from %(old)i to %(new)i for resource provider \u0027"},{"line_number":310,"context_line":"                          \u0027%(uuid)s\u0027,"},{"line_number":311,"context_line":"                          {\u0027old\u0027: my_rp.generation,"},{"line_number":312,"context_line":"                           \u0027new\u0027: server_gen,"},{"line_number":313,"context_line":"                           \u0027uuid\u0027: rp_uuid})"},{"line_number":314,"context_line":"            my_rp.generation \u003d server_gen"},{"line_number":315,"context_line":""},{"line_number":316,"context_line":"        # Check to see if we need to update placement\u0027s view"},{"line_number":317,"context_line":"        if inv_data \u003d\u003d curr.get(\u0027inventories\u0027, {}):"},{"line_number":318,"context_line":"            return True"},{"line_number":319,"context_line":""},{"line_number":320,"context_line":"        cur_rp_gen \u003d self._resource_providers[rp_uuid].generation"},{"line_number":321,"context_line":"        payload \u003d {"},{"line_number":322,"context_line":"            \u0027resource_provider_generation\u0027: cur_rp_gen,"},{"line_number":323,"context_line":"            \u0027inventories\u0027: inv_data,"},{"line_number":324,"context_line":"        }"},{"line_number":325,"context_line":"        url \u003d \u0027/resource_providers/%s/inventories\u0027 % rp_uuid"},{"line_number":326,"context_line":"        result \u003d self.put(url, payload)"},{"line_number":327,"context_line":"        if result.status_code \u003d\u003d 409:"},{"line_number":328,"context_line":"            LOG.info(_LI(\u0027Inventory update conflict for resource provider %s\u0027),"},{"line_number":329,"context_line":"                     rp_uuid)"},{"line_number":330,"context_line":"            # Invalidate our cache and re-fetch the resource provider"},{"line_number":331,"context_line":"            # to be sure to get the latest generation."},{"line_number":332,"context_line":"            del self._resource_providers[rp_uuid]"},{"line_number":333,"context_line":"            self._ensure_resource_provider(rp_uuid)"},{"line_number":334,"context_line":"            return False"},{"line_number":335,"context_line":"        elif not result:"},{"line_number":336,"context_line":"            LOG.warning(_LW(\u0027Failed to update inventory for resource provider \u0027"},{"line_number":337,"context_line":"                            \u0027%(uuid)s: %(status)i %(text)s\u0027),"},{"line_number":338,"context_line":"                        {\u0027uuid\u0027: rp_uuid,"},{"line_number":339,"context_line":"                         \u0027status\u0027: result.status_code,"},{"line_number":340,"context_line":"                         \u0027text\u0027: result.text})"},{"line_number":341,"context_line":"            return False"},{"line_number":342,"context_line":""},{"line_number":343,"context_line":"        if result.status_code !\u003d 200:"},{"line_number":344,"context_line":"            LOG.info("},{"line_number":345,"context_line":"                _LI(\u0027Received unexpected response code %(code)i while \u0027"},{"line_number":346,"context_line":"                    \u0027trying to update inventory for resource provider \u0027"},{"line_number":347,"context_line":"                    \u0027%(uuid)s: %(text)s\u0027),"},{"line_number":348,"context_line":"                {\u0027uuid\u0027: rp_uuid,"},{"line_number":349,"context_line":"                 \u0027code\u0027: result.status_code,"},{"line_number":350,"context_line":"                 \u0027text\u0027: result.text})"},{"line_number":351,"context_line":"            return False"},{"line_number":352,"context_line":""},{"line_number":353,"context_line":"        # Update our view of the generation for next time"},{"line_number":354,"context_line":"        updated_inventories_result \u003d result.json()"},{"line_number":355,"context_line":"        new_gen \u003d updated_inventories_result[\u0027resource_provider_generation\u0027]"},{"line_number":356,"context_line":""},{"line_number":357,"context_line":"        self._resource_providers[rp_uuid].generation \u003d new_gen"},{"line_number":358,"context_line":"        LOG.debug(\u0027Updated inventory for resource provider %s \u0027"},{"line_number":359,"context_line":"                  \u0027at generation %i\u0027, rp_uuid, new_gen)"},{"line_number":360,"context_line":"        return True"},{"line_number":361,"context_line":""},{"line_number":362,"context_line":"    @safe_connect"},{"line_number":363,"context_line":"    def _update_compute_node_inventory(self, compute_node, pci_devs):"}],"source_content_type":"text/x-python","patch_set":5,"id":"3a98d1f4_7f5c197d","line":360,"range":{"start_line":282,"start_character":0,"end_line":360,"end_character":19},"updated":"2016-10-03 13:59:23.000000000","message":"So all of this change is purely to take a rp_uuid instead of compute_node to these inner functions, right? Aside from the fact that it seems like personal preference to me, it\u0027s completely unrelated to the rest of this patch AFAICT. If so, can you split that out to another patch, separate from the functional meat here?","commit_id":"0c97e3e1c1699931f1dafc024b4979d0a057b03a"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"2e2ac070d50bddc7e142581764356c20d56cd91f","unresolved":false,"context_lines":[{"line_number":279,"context_line":"        self._resource_providers[uuid] \u003d rp"},{"line_number":280,"context_line":"        return rp"},{"line_number":281,"context_line":""},{"line_number":282,"context_line":"    def _get_inventory(self, rp_uuid):"},{"line_number":283,"context_line":"        url \u003d \u0027/resource_providers/%s/inventories\u0027 % rp_uuid"},{"line_number":284,"context_line":"        result \u003d self.get(url)"},{"line_number":285,"context_line":"        if not result:"},{"line_number":286,"context_line":"            return {\u0027inventories\u0027: {}}"},{"line_number":287,"context_line":"        return result.json()"},{"line_number":288,"context_line":""},{"line_number":289,"context_line":"    def _update_inventory_attempt(self, rp_uuid, inv_data):"},{"line_number":290,"context_line":"        \"\"\"Update, if needed, the inventory records in the placement API using"},{"line_number":291,"context_line":"        the supplied inventory dict."},{"line_number":292,"context_line":""},{"line_number":293,"context_line":"        :param rp_uuid: UUID of the resource provider to update inventory for"},{"line_number":294,"context_line":"        :param inv_data: Dict, keyed by resource class, of inventory"},{"line_number":295,"context_line":"                         information"},{"line_number":296,"context_line":"        :returns: True if the inventory was updated (or did not need to be),"},{"line_number":297,"context_line":"                  False otherwise."},{"line_number":298,"context_line":"        \"\"\""},{"line_number":299,"context_line":"        curr \u003d self._get_inventory(rp_uuid)"},{"line_number":300,"context_line":""},{"line_number":301,"context_line":"        # Update our generation immediately, if possible. Even if there"},{"line_number":302,"context_line":"        # are no inventories we should always have a generation but let\u0027s"},{"line_number":303,"context_line":"        # be careful."},{"line_number":304,"context_line":"        server_gen \u003d curr.get(\u0027resource_provider_generation\u0027)"},{"line_number":305,"context_line":"        if server_gen:"},{"line_number":306,"context_line":"            my_rp \u003d self._resource_providers[rp_uuid]"},{"line_number":307,"context_line":"            if server_gen !\u003d my_rp.generation:"},{"line_number":308,"context_line":"                LOG.debug(\u0027Updating our resource provider generation \u0027"},{"line_number":309,"context_line":"                          \u0027from %(old)i to %(new)i for resource provider \u0027"},{"line_number":310,"context_line":"                          \u0027%(uuid)s\u0027,"},{"line_number":311,"context_line":"                          {\u0027old\u0027: my_rp.generation,"},{"line_number":312,"context_line":"                           \u0027new\u0027: server_gen,"},{"line_number":313,"context_line":"                           \u0027uuid\u0027: rp_uuid})"},{"line_number":314,"context_line":"            my_rp.generation \u003d server_gen"},{"line_number":315,"context_line":""},{"line_number":316,"context_line":"        # Check to see if we need to update placement\u0027s view"},{"line_number":317,"context_line":"        if inv_data \u003d\u003d curr.get(\u0027inventories\u0027, {}):"},{"line_number":318,"context_line":"            return True"},{"line_number":319,"context_line":""},{"line_number":320,"context_line":"        cur_rp_gen \u003d self._resource_providers[rp_uuid].generation"},{"line_number":321,"context_line":"        payload \u003d {"},{"line_number":322,"context_line":"            \u0027resource_provider_generation\u0027: cur_rp_gen,"},{"line_number":323,"context_line":"            \u0027inventories\u0027: inv_data,"},{"line_number":324,"context_line":"        }"},{"line_number":325,"context_line":"        url \u003d \u0027/resource_providers/%s/inventories\u0027 % rp_uuid"},{"line_number":326,"context_line":"        result \u003d self.put(url, payload)"},{"line_number":327,"context_line":"        if result.status_code \u003d\u003d 409:"},{"line_number":328,"context_line":"            LOG.info(_LI(\u0027Inventory update conflict for resource provider %s\u0027),"},{"line_number":329,"context_line":"                     rp_uuid)"},{"line_number":330,"context_line":"            # Invalidate our cache and re-fetch the resource provider"},{"line_number":331,"context_line":"            # to be sure to get the latest generation."},{"line_number":332,"context_line":"            del self._resource_providers[rp_uuid]"},{"line_number":333,"context_line":"            self._ensure_resource_provider(rp_uuid)"},{"line_number":334,"context_line":"            return False"},{"line_number":335,"context_line":"        elif not result:"},{"line_number":336,"context_line":"            LOG.warning(_LW(\u0027Failed to update inventory for resource provider \u0027"},{"line_number":337,"context_line":"                            \u0027%(uuid)s: %(status)i %(text)s\u0027),"},{"line_number":338,"context_line":"                        {\u0027uuid\u0027: rp_uuid,"},{"line_number":339,"context_line":"                         \u0027status\u0027: result.status_code,"},{"line_number":340,"context_line":"                         \u0027text\u0027: result.text})"},{"line_number":341,"context_line":"            return False"},{"line_number":342,"context_line":""},{"line_number":343,"context_line":"        if result.status_code !\u003d 200:"},{"line_number":344,"context_line":"            LOG.info("},{"line_number":345,"context_line":"                _LI(\u0027Received unexpected response code %(code)i while \u0027"},{"line_number":346,"context_line":"                    \u0027trying to update inventory for resource provider \u0027"},{"line_number":347,"context_line":"                    \u0027%(uuid)s: %(text)s\u0027),"},{"line_number":348,"context_line":"                {\u0027uuid\u0027: rp_uuid,"},{"line_number":349,"context_line":"                 \u0027code\u0027: result.status_code,"},{"line_number":350,"context_line":"                 \u0027text\u0027: result.text})"},{"line_number":351,"context_line":"            return False"},{"line_number":352,"context_line":""},{"line_number":353,"context_line":"        # Update our view of the generation for next time"},{"line_number":354,"context_line":"        updated_inventories_result \u003d result.json()"},{"line_number":355,"context_line":"        new_gen \u003d updated_inventories_result[\u0027resource_provider_generation\u0027]"},{"line_number":356,"context_line":""},{"line_number":357,"context_line":"        self._resource_providers[rp_uuid].generation \u003d new_gen"},{"line_number":358,"context_line":"        LOG.debug(\u0027Updated inventory for resource provider %s \u0027"},{"line_number":359,"context_line":"                  \u0027at generation %i\u0027, rp_uuid, new_gen)"},{"line_number":360,"context_line":"        return True"},{"line_number":361,"context_line":""},{"line_number":362,"context_line":"    @safe_connect"},{"line_number":363,"context_line":"    def _update_compute_node_inventory(self, compute_node, pci_devs):"}],"source_content_type":"text/x-python","patch_set":5,"id":"3a98d1f4_080e68e4","line":360,"range":{"start_line":282,"start_character":0,"end_line":360,"end_character":19},"in_reply_to":"3a98d1f4_7f5c197d","updated":"2016-10-03 22:21:15.000000000","message":"It\u0027s not a preference; it\u0027s expanding the concept to handle resource providers other than compute nodes. But I agree that it\u0027s not strictly related, so I\u0027ll split it out.","commit_id":"0c97e3e1c1699931f1dafc024b4979d0a057b03a"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"f6bbee9fc0ea6013e5048f6be418033f4308ae5e","unresolved":false,"context_lines":[{"line_number":95,"context_line":"            \u0027allocation_ratio\u0027: compute_node.disk_allocation_ratio,"},{"line_number":96,"context_line":"        },"},{"line_number":97,"context_line":"    }"},{"line_number":98,"context_line":"    if len(pci_devices) \u003e 0:"},{"line_number":99,"context_line":"        result[PCI_DEVICE] \u003d {"},{"line_number":100,"context_line":"            \u0027total\u0027: len([d for d in pci_devices"},{"line_number":101,"context_line":"                          if d.dev_type \u003d\u003d DEVICE_TYPE_STANDARD]),"},{"line_number":102,"context_line":"            \u0027reserved\u0027: 0,"},{"line_number":103,"context_line":"            \u0027min_unit\u0027: 1,"},{"line_number":104,"context_line":"            \u0027max_unit\u0027: 1,"},{"line_number":105,"context_line":"            \u0027step_size\u0027: 1,"},{"line_number":106,"context_line":"            \u0027allocation_ratio\u0027: 1.0,"},{"line_number":107,"context_line":"        }"},{"line_number":108,"context_line":"    return result"},{"line_number":109,"context_line":""},{"line_number":110,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"5a74a57a_29c9555b","line":107,"range":{"start_line":98,"start_character":0,"end_line":107,"end_character":9},"updated":"2016-11-29 17:03:00.000000000","message":"Any reason to not always return this information?","commit_id":"ec29ad8e277a41799a70cdcdba1af6fc273a9743"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"ac3e0c829e809be2c5fcbec47936481936533d93","unresolved":false,"context_lines":[{"line_number":95,"context_line":"            \u0027allocation_ratio\u0027: compute_node.disk_allocation_ratio,"},{"line_number":96,"context_line":"        },"},{"line_number":97,"context_line":"    }"},{"line_number":98,"context_line":"    if len(pci_devices) \u003e 0:"},{"line_number":99,"context_line":"        result[PCI_DEVICE] \u003d {"},{"line_number":100,"context_line":"            \u0027total\u0027: len([d for d in pci_devices"},{"line_number":101,"context_line":"                          if d.dev_type \u003d\u003d DEVICE_TYPE_STANDARD]),"},{"line_number":102,"context_line":"            \u0027reserved\u0027: 0,"},{"line_number":103,"context_line":"            \u0027min_unit\u0027: 1,"},{"line_number":104,"context_line":"            \u0027max_unit\u0027: 1,"},{"line_number":105,"context_line":"            \u0027step_size\u0027: 1,"},{"line_number":106,"context_line":"            \u0027allocation_ratio\u0027: 1.0,"},{"line_number":107,"context_line":"        }"},{"line_number":108,"context_line":"    return result"},{"line_number":109,"context_line":""},{"line_number":110,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"5a74a57a_0402c06f","line":107,"range":{"start_line":98,"start_character":0,"end_line":107,"end_character":9},"in_reply_to":"5a74a57a_29c9555b","updated":"2016-11-29 17:16:44.000000000","message":"Yup, the reason we don\u0027t return this information is because the absence of a particular resource class in the result dict\u0027s keys is how we indicate that the provider contains no inventory of that resource class. It\u0027s also how InventoryList.find() works (it raises NotFound when an Inventory record with a requested resource class isn\u0027t in the InventoryList object.","commit_id":"ec29ad8e277a41799a70cdcdba1af6fc273a9743"}],"nova/tests/unit/compute/test_resource_tracker.py":[{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"f152d5486bd339fc886798e729e1d56533b87ad0","unresolved":false,"context_lines":[{"line_number":1244,"context_line":""},{"line_number":1245,"context_line":"        self._setup_rt()"},{"line_number":1246,"context_line":"        self.rt.compute_node \u003d copy.deepcopy(_COMPUTE_NODE_FIXTURES[0])"},{"line_number":1247,"context_line":"        mock_pci \u003d mock.MagicMock()"},{"line_number":1248,"context_line":"        mock_pci.pci_devs \u003d objects.PciDeviceList()"},{"line_number":1249,"context_line":"        pci_pool \u003d objects.PciDevicePoolList()"},{"line_number":1250,"context_line":"        mock_pci.stats.to_device_pools_obj.return_value \u003d pci_pool"}],"source_content_type":"text/x-python","patch_set":9,"id":"5a74a57a_744af8c6","line":1247,"range":{"start_line":1247,"start_character":24,"end_line":1247,"end_character":33},"updated":"2016-11-24 12:37:23.000000000","message":"Nit: feels like just Mock() would be enough here, but I could be missing something.","commit_id":"ec29ad8e277a41799a70cdcdba1af6fc273a9743"}],"nova/tests/unit/scheduler/client/test_report.py":[{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"26895180ec79d41a9b685066dd980935d08c820c","unresolved":false,"context_lines":[{"line_number":524,"context_line":"        pci_devs \u003d objects.PciDeviceList(objects\u003dpci_devs)"},{"line_number":525,"context_line":"        rp \u003d objects.ResourceProvider(uuid\u003duuid, name\u003d\u0027foo\u0027, generation\u003d42)"},{"line_number":526,"context_line":"        # Make sure the ResourceProvider exists for preventing to call the GET"},{"line_number":527,"context_line":"        # /r-p/{uuid} API"},{"line_number":528,"context_line":"        self.client._resource_providers[uuid] \u003d rp"},{"line_number":529,"context_line":""},{"line_number":530,"context_line":"        mock_get.return_value.json.return_value \u003d {"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a8bc5a2_cac6f648","line":527,"updated":"2016-09-28 10:57:08.000000000","message":"I was only able to figure out what this comment meant when I read the code it is commenting, which was a bit weirdly backwards. Instead of \"exists for preventing to call\" you might say \"is cached so there is no call to\" or something like.","commit_id":"0c97e3e1c1699931f1dafc024b4979d0a057b03a"}]}
