def sync(self, driver=None):
        """
            Update the nodes based on the values returned from the driver
        """
        self.logger.debug("Sync Nodes")
        driver = driver or self.driver
        driver.sync()
        counter = 0
        self.groups = {}
        self.nodes_by_id = {}
        self.nodes_by_ip = {}
        self.azs = set()

        for group, ips in sorted(self.local_ips.items()):
            self.groups[group] = []

            # different groups can have the same IPs,
            # so we need to match to the same nodes
            for ip in ips:
                self.logger.debug("IP processing: %s", ip)
                # see if we have a matching node in the cached list of nodes
                node = self.nodes_by_ip.get(ip)
                if node is None:
                    # node is not in cached list (or the list is empty), check the clouddriver
                    node = driver.get_by_ip(ip)
                if node is None: #pragma: no cover
                    # apart from IPs, we will also get hostnames here
                    # for those, debug, otherwise info
                    try:
                        # validate that this is an IP or not
                        ipaddress.ip_address(ip)
                        self.logger.debug("Couldn't match IP to any cloud node: %s", ip)
                    except:
                        self.logger.debug("Couldn't match to any cloud node: %s", ip)
                    continue

                self.nodes_by_id[node.id] = node
                self.nodes_by_ip[ip] = node
                self.groups[group].append(node)
                node.groups.append(group)
                self.azs.add(node.az)

                self.logger.debug("Node added: %s", node)

                # just for easier identification, give them numbers
                node.no = counter
                counter += 1

            Update the nodes based on the values returned from the driver
        
powerfulseal/node/node_inventory.py