'Extracts and returns a validated availability zone.
This function will extract the availability zone (if not provided) from
the snapshot or source_volume and then performs a set of validation
checks on the provided or extracted availability zone and then returns
the validated availability zone.'

def _extract_availability_zone(self, availability_zone, snapshot, source_volume, group):

    refresh_az = False
    if group:
        try:
            availability_zone = group['availability_zone']
        except (TypeError, KeyError):
            pass
    if (availability_zone is None):
        if snapshot:
            try:
                availability_zone = snapshot['volume']['availability_zone']
            except (TypeError, KeyError):
                pass
        if (source_volume and (availability_zone is None)):
            try:
                availability_zone = source_volume['availability_zone']
            except (TypeError, KeyError):
                pass
    if (availability_zone is None):
        if CONF.default_availability_zone:
            availability_zone = CONF.default_availability_zone
        else:
            availability_zone = CONF.storage_availability_zone
    if (availability_zone not in self.availability_zones):
        refresh_az = True
        if CONF.allow_availability_zone_fallback:
            original_az = availability_zone
            availability_zone = (CONF.default_availability_zone or CONF.storage_availability_zone)
            LOG.warning("Availability    zone    '%(s_az)s'    not    found,    falling    back    to    '%(s_fallback_az)s'.", {'s_az': original_az, 's_fallback_az': availability_zone})
        else:
            raise exception.InvalidAvailabilityZone(az=availability_zone)
    if CONF.cloned_volume_same_az:
        snap_az = None
        try:
            snap_az = snapshot['volume']['availability_zone']
        except (TypeError, KeyError):
            pass
        if (snap_az and (snap_az != availability_zone)):
            msg = _('Volume    must    be    in    the    same    availability    zone    as    the    snapshot')
            raise exception.InvalidInput(reason=msg)
        source_vol_az = None
        try:
            source_vol_az = source_volume['availability_zone']
        except (TypeError, KeyError):
            pass
        if (source_vol_az and (source_vol_az != availability_zone)):
            msg = _('Volume    must    be    in    the    same    availability    zone    as    the    source    volume')
            raise exception.InvalidInput(reason=msg)
    return (availability_zone, refresh_az)
