Checks the integrity of the container map. This means, that
        * every shared container (instance name) and attached volume should only exist once (can be deactivated);
        * every container declared as `used` needs to have at least a shared volume or a host bind;
        * every host bind declared under `binds` needs to be shared from the host;
        * every volume alias used in `attached` and `binds` needs to be associated with a path in `volumes`;
        * every container referred to in `links` needs to be defined;
        * every container named in `extended` is available.

        :param check_duplicates: Check for duplicate attached volumes.
        :type check_duplicates: bool

def check_integrity(self, check_duplicates=True):
        """
        Checks the integrity of the container map. This means, that
        * every shared container (instance name) and attached volume should only exist once (can be deactivated);
        * every container declared as `used` needs to have at least a shared volume or a host bind;
        * every host bind declared under `binds` needs to be shared from the host;
        * every volume alias used in `attached` and `binds` needs to be associated with a path in `volumes`;
        * every container referred to in `links` needs to be defined;
        * every container named in `extended` is available.

        :param check_duplicates: Check for duplicate attached volumes.
        :type check_duplicates: bool
        """
        def _get_instance_names(c_name, instances):
            if instances:
                return ['{0}.{1}'.format(c_name, instance) for instance in instances]
            return [c_name]

        def _get_container_items(c_name, c_config):
            instance_names = _get_instance_names(c_name, c_config.instances)
            group_ref_names = instance_names[:]
            if c_config.instances:
                group_ref_names.append(c_name)
            shared = instance_names[:] if c_config.shares or c_config.binds or c_config.uses else []
            bind = [b.name for b in c_config.binds if isinstance(b, SharedVolume)]
            link = [l.container for l in c_config.links]
            uses = [u.name for u in c_config.uses]
            networks = [n.network_name for n in c_config.networks if n.network_name not in DEFAULT_PRESET_NETWORKS]
            network_mode = c_config.network_mode
            if isinstance(network_mode, tuple):
                if network_mode[1]:
                    net_containers = ['{0[0]}.{0[1]}'.format(network_mode)]
                else:
                    net_containers = [network_mode[0]]
            else:
                net_containers = []
            if self.use_attached_parent_name:
                attaches = [(c_name, a.name) for a in c_config.attaches]
            else:
                attaches = [a.name for a in c_config.attaches]
            attaches_with_path = [a.name for a in c_config.attaches
                                  if isinstance(a, UsedVolume)]
            return (instance_names, group_ref_names, uses, attaches, attaches_with_path, shared, bind, link, networks,
                    net_containers)

        self.clean()
        (all_instances, all_grouprefs, all_used, all_attached, all_attached_default, all_shared, all_binds, all_links,
         all_networks, all_net_containers) = zip(*[
            _get_container_items(k, v) for k, v in self.get_extended_map()
         ])
        if self.use_attached_parent_name:
            all_attached_names = tuple('{0}.{1}'.format(c_name, a)
                                       for c_name, a in itertools.chain.from_iterable(all_attached))
        else:
            all_attached_names = tuple(itertools.chain.from_iterable(all_attached))

        ref_set = set(itertools.chain.from_iterable(all_grouprefs))
        group_set = set(self.groups.keys())
        ambiguous_names = group_set & ref_set
        if ambiguous_names:
            ambiguous_str = ', '.join(ambiguous_names)
            raise MapIntegrityError("Names are used both for container configurations (or instances) and for container "
                                    "groups: {0}.".format(ambiguous_str))
        group_referenced = set(itertools.chain.from_iterable(self.groups.values()))
        missing_refs = group_referenced - ref_set
        if missing_refs:
            missing_ref_str = ', '.join(missing_refs)
            raise MapIntegrityError("Container configurations or certain instances are referenced by groups, but are "
                                    "not defined: {0}.".format(missing_ref_str))
        volume_shared = tuple(itertools.chain.from_iterable(all_shared)) + all_attached_names
        if check_duplicates:
            duplicated = [name for name, count in six.iteritems(Counter(volume_shared)) if count > 1]
            if duplicated:
                dup_str = ', '.join(duplicated)
                raise MapIntegrityError("Duplicated attached volumes found with name(s): {0}.".format(dup_str))
        used_set = set(itertools.chain.from_iterable(all_used))
        shared_set = set(volume_shared)
        missing_shares = used_set - shared_set
        if missing_shares:
            missing_share_str = ', '.join(missing_shares)
            raise MapIntegrityError("No shared or attached volumes found for used volume(s): "
                                    "{0}.".format(missing_share_str))
        binds_set = set(itertools.chain.from_iterable(all_binds))
        host_set = set(self.host.keys())
        missing_binds = binds_set - host_set
        if missing_binds:
            missing_mapped_str = ', '.join(missing_binds)
            raise MapIntegrityError("No host share found for mapped volume(s): {0}.".format(missing_mapped_str))
        if self.use_attached_parent_name:
            volume_set = binds_set.union(a[1] for a in itertools.chain.from_iterable(all_attached))
        else:
            volume_set = binds_set.union(all_attached_names)
        named_set = set(self.volumes.keys()).union(itertools.chain.from_iterable(all_attached_default))
        missing_names = volume_set - named_set
        if missing_names:
            missing_names_str = ', '.join(missing_names)
            raise MapIntegrityError("No volume name-path-assignments found for volume(s): "
                                    "{0}.".format(missing_names_str))
        instance_set = set(itertools.chain.from_iterable(all_instances))
        linked_set = set(itertools.chain.from_iterable(all_links))
        missing_links = linked_set - instance_set
        if missing_links:
            missing_links_str = ', '.join(missing_links)
            raise MapIntegrityError("No container instance found for link(s): {0}.".format(missing_links_str))
        used_network_set = set(itertools.chain.from_iterable(all_networks))
        used_net_container_set = set(itertools.chain.from_iterable(all_net_containers))
        available_network_set = set(self.networks.keys())
        missing_networks = used_network_set - available_network_set
        if missing_networks:
            missing_networks_str = ', '.join(missing_networks)
            raise MapIntegrityError("No network configuration found for the following network reference(s): "
                                    "{0}".format(missing_networks_str))
        missing_net_containers = used_net_container_set - instance_set
        if missing_net_containers:
            missing_net_cnt_str = ', '.join(missing_net_containers)
            raise MapIntegrityError("No container instance found for the following network mode reference(s): "
                                    "{0}".format(missing_net_cnt_str))