'Failover a volume.
:param vol: the volume object
:param failover: flag to indicate failover or failback -- bool
:param extra_specs: the extra specifications
:returns: model_update -- dict'

def _failover_volume(self, vol, failover, extra_specs):

    loc = vol.provider_location
    rep_data = vol.replication_driver_data
    try:
        name = ast.literal_eval(loc)
        replication_keybindings = ast.literal_eval(rep_data)
        try:
            array = name['array']
        except KeyError:
            array = name['keybindings']['SystemName'].split('+')[1].strip('-')
        device_id = self._find_device_on_array(vol, {utils.ARRAY: array})
        (target_device, remote_array, rdf_group, local_vol_state, pair_state) = self.get_remote_target_device(array, vol, device_id)
        self._sync_check(array, device_id, vol.name, extra_specs)
        self.provision.failover_volume(array, device_id, rdf_group, extra_specs, local_vol_state, failover)
        if failover:
            new_status = REPLICATION_FAILOVER
        else:
            new_status = REPLICATION_ENABLED
        loc = six.text_type(replication_keybindings)
        rep_data = six.text_type(name)
    except Exception as ex:
        msg = 'Failed    to    failover    volume    %(volume_id)s.    Error:    %(error)s.'
        LOG.error(msg, {'volume_id': vol.id, 'error': ex})
        new_status = FAILOVER_ERROR
    model_update = {'volume_id': vol.id, 'updates': {'replication_status': new_status, 'replication_driver_data': rep_data, 'provider_location': loc}}
    return model_update
