# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from .automatedproperties import AutomatedProperties

from . import utils
from .utils import vg_obj_path_generate
import dbus
from . import cmdhandler
from . import cfg
from .cfg import LV_INTERFACE, THIN_POOL_INTERFACE, SNAPSHOT_INTERFACE, \
	LV_COMMON_INTERFACE, CACHE_POOL_INTERFACE, LV_CACHED
from .request import RequestEntry
from .utils import n, n32
from .loader import common
from .state import State
from . import background
from .utils import round_size
from .job import JobState


# Try and build a key for a LV, so that we sort the LVs with least dependencies
# first.  This may be error prone because of the flexibility LVM
# provides and what you can stack.
def get_key(i):

	name = i['lv_name']
	parent = i['lv_parent']
	pool = i['pool_lv']
	a1 = ""
	a2 = ""

	if name[0] == '[':
		a1 = '#'

	# We have a parent
	if parent:
		# Check if parent is hidden
		if parent[0] == '[':
			a2 = '##'
		else:
			a2 = '#'

	# If a LV has a pool, then it should be sorted/loaded after the pool
	# lv, unless it's a hidden too, then after other hidden, but before visible
	if pool:
		if pool[0] != '[':
			a2 += '~'
		else:
			a1 = '$' + a1

	return "%s%s%s" % (a1, a2, name)


# noinspection PyUnusedLocal
def lvs_state_retrieve(selection, cache_refresh=True):
	rc = []

	if cache_refresh:
		cfg.db.refresh()

	# When building up the model, it's best to process LVs with the least
	# dependencies to those that are dependant upon other LVs.  Otherwise, when
	# we are trying to gather information we could be in a position where we
	# don't have information available yet.
	lvs = sorted(cfg.db.fetch_lvs(selection), key=get_key)

	for l in lvs:
		rc.append(LvState(
			l['lv_uuid'], l['lv_name'],
			l['lv_path'], n(l['lv_size']),
			l['vg_name'],
			l['vg_uuid'], l['pool_lv_uuid'],
			l['pool_lv'], l['origin_uuid'], l['origin'],
			n32(l['data_percent']), l['lv_attr'],
			l['lv_tags'], l['lv_active'], l['data_lv'],
			l['metadata_lv'], l['segtype'], l['lv_role'],
			l['lv_layout']))
	return rc


def load_lvs(lv_name=None, object_path=None, refresh=False, emit_signal=False,
				cache_refresh=True):
	# noinspection PyUnresolvedReferences
	return common(
		lvs_state_retrieve,
		(LvCommon, Lv, LvThinPool, LvSnapShot),
		lv_name, object_path, refresh, emit_signal, cache_refresh)


# noinspection PyPep8Naming,PyUnresolvedReferences,PyUnusedLocal
class LvState(State):
	@staticmethod
	def _pv_devices(uuid):
		rc = []
		for pv in sorted(cfg.db.lv_contained_pv(uuid)):
			(pv_uuid, pv_name, pv_segs) = pv
			pv_obj = cfg.om.get_object_path_by_uuid_lvm_id(
				pv_uuid, pv_name, gen_new=False)
			rc.append((pv_obj, pv_segs))

		return dbus.Array(rc, signature="(oa(tts))")

	def vg_name_lookup(self):
		return cfg.om.get_object_by_path(self.Vg).Name

	@property
	def lvm_id(self):
		return "%s/%s" % (self.vg_name_lookup(), self.Name)

	def identifiers(self):
		return (self.Uuid, self.lvm_id)

	def _get_hidden_lv(self):
		rc = dbus.Array([], "o")

		vg_name = self.vg_name_lookup()

		for l in cfg.db.hidden_lvs(self.Uuid):
			full_name = "%s/%s" % (vg_name, l[1])
			op = cfg.om.get_object_path_by_uuid_lvm_id(
				l[0], full_name, gen_new=False)
			assert op
			rc.append(op)
		return rc

	def __init__(self, Uuid, Name, Path, SizeBytes,
			vg_name, vg_uuid, pool_lv_uuid, PoolLv,
			origin_uuid, OriginLv, DataPercent, Attr, Tags, active,
			data_lv, metadata_lv, segtypes, role, layout):
		utils.init_class_from_arguments(self)

		# The segtypes is possibly an array with potentially dupes or a single
		# value
		self._segs = dbus.Array([], signature='s')
		if not isinstance(segtypes, list):
			self._segs.append(segtypes)
		else:
			self._segs.extend(set(segtypes))

		self.Vg = cfg.om.get_object_path_by_uuid_lvm_id(
			vg_uuid, vg_name, vg_obj_path_generate)

		self.Devices = LvState._pv_devices(self.Uuid)

		if PoolLv:
			gen = utils.lv_object_path_method(Name, (Attr, layout, role))

			self.PoolLv = cfg.om.get_object_path_by_uuid_lvm_id(
				pool_lv_uuid, '%s/%s' % (vg_name, PoolLv),
				gen)
		else:
			self.PoolLv = '/'

		if OriginLv:
			self.OriginLv = \
				cfg.om.get_object_path_by_uuid_lvm_id(
					origin_uuid, '%s/%s' % (vg_name, OriginLv),
					vg_obj_path_generate)
		else:
			self.OriginLv = '/'

		self.HiddenLvs = self._get_hidden_lv()

	@property
	def SegType(self):
		return self._segs

	def _object_path_create(self):
		return utils.lv_object_path_method(
			self.Name, (self.Attr, self.layout, self.role))

	def _object_type_create(self):
		if self.Attr[0] == 't':
			return LvThinPool
		elif self.Attr[0] == 'C':
			if 'pool' in self.layout:
				return LvCachePool
			else:
				return LvCacheLv
		elif self.Name[0] == '[':
			return LvCommon
		elif self.OriginLv != '/':
			return LvSnapShot
		else:
			return Lv

	def create_dbus_object(self, path):
		if not path:
			path = cfg.om.get_object_path_by_uuid_lvm_id(
				self.Uuid, self.lvm_id, self._object_path_create())

		obj_ctor = self._object_type_create()
		return obj_ctor(path, self)

	def creation_signature(self):
		klass = self._object_type_create()
		path_method = self._object_path_create()
		return (klass, path_method)


# noinspection PyPep8Naming
@utils.dbus_property(LV_COMMON_INTERFACE, 'Uuid', 's')
@utils.dbus_property(LV_COMMON_INTERFACE, 'Name', 's')
@utils.dbus_property(LV_COMMON_INTERFACE, 'Path', 's')
@utils.dbus_property(LV_COMMON_INTERFACE, 'SizeBytes', 't')
@utils.dbus_property(LV_COMMON_INTERFACE, 'DataPercent', 'u')
@utils.dbus_property(LV_COMMON_INTERFACE, 'SegType', 'as')
@utils.dbus_property(LV_COMMON_INTERFACE, 'Vg', 'o')
@utils.dbus_property(LV_COMMON_INTERFACE, 'OriginLv', 'o')
@utils.dbus_property(LV_COMMON_INTERFACE, 'PoolLv', 'o')
@utils.dbus_property(LV_COMMON_INTERFACE, 'Devices', "a(oa(tts))")
@utils.dbus_property(LV_COMMON_INTERFACE, 'HiddenLvs', "ao")
class LvCommon(AutomatedProperties):
	_Tags_meta = ("as", LV_COMMON_INTERFACE)
	_Roles_meta = ("as", LV_COMMON_INTERFACE)
	_IsThinVolume_meta = ("b", LV_COMMON_INTERFACE)
	_IsThinPool_meta = ("b", LV_COMMON_INTERFACE)
	_Active_meta = ("b", LV_COMMON_INTERFACE)
	_VolumeType_meta = ("(ss)", LV_COMMON_INTERFACE)
	_Permissions_meta = ("(ss)", LV_COMMON_INTERFACE)
	_AllocationPolicy_meta = ("(ss)", LV_COMMON_INTERFACE)
	_State_meta = ("(ss)", LV_COMMON_INTERFACE)
	_TargetType_meta = ("(ss)", LV_COMMON_INTERFACE)
	_Health_meta = ("(ss)", LV_COMMON_INTERFACE)
	_FixedMinor_meta = ('b', LV_COMMON_INTERFACE)
	_ZeroBlocks_meta = ('b', LV_COMMON_INTERFACE)
	_SkipActivation_meta = ('b', LV_COMMON_INTERFACE)

	# noinspection PyUnusedLocal,PyPep8Naming
	def __init__(self, object_path, object_state):
		super(LvCommon, self).__init__(object_path, lvs_state_retrieve)
		self.set_interface(LV_COMMON_INTERFACE)
		self.state = object_state

	@property
	def VolumeType(self):
		type_map = {'C': 'Cache', 'm': 'mirrored',
					'M': 'Mirrored without initial sync', 'o': 'origin',
					'O': 'Origin with merging snapshot', 'r': 'raid',
					'R': 'Raid without initial sync', 's': 'snapshot',
					'S': 'merging Snapshot', 'p': 'pvmove',
					'v': 'virtual', 'i': 'mirror  or  raid  image',
					'I': 'mirror or raid Image out-of-sync',
					'l': 'mirror log device', 'c': 'under conversion',
					'V': 'thin Volume', 't': 'thin pool', 'T': 'Thin pool data',
					'e': 'raid or pool metadata or pool metadata spare',
					'-': 'Unspecified'}
		return (self.state.Attr[0], type_map[self.state.Attr[0]])

	@property
	def Permissions(self):
		type_map = {'w': 'writable', 'r': 'read-only',
					'R': 'Read-only activation of non-read-only volume',
					'-': 'Unspecified'}
		return (self.state.Attr[1], type_map[self.state.Attr[1]])

	@property
	def AllocationPolicy(self):
		type_map = {'a': 'anywhere', 'A': 'anywhere locked',
					'c': 'contiguous', 'C': 'contiguous locked',
					'i': 'inherited', 'I': 'inherited locked',
					'l': 'cling', 'L': 'cling locked',
					'n': 'normal', 'N': 'normal locked', '-': 'Unspecified'}
		return (self.state.Attr[2], type_map[self.state.Attr[2]])

	@property
	def FixedMinor(self):
		return self.state.Attr[3] == 'm'

	@property
	def State(self):
		type_map = {'a': 'active', 's': 'suspended', 'I': 'Invalid snapshot',
					'S': 'invalid Suspended snapshot',
					'm': 'snapshot merge failed',
					'M': 'suspended snapshot (M)erge failed',
					'd': 'mapped device present without  tables',
					'i': 'mapped device present with inactive table',
					'X': 'unknown', '-': 'Unspecified'}
		return (self.state.Attr[4], type_map[self.state.Attr[4]])

	@property
	def TargetType(self):
		type_map = {'C': 'Cache', 'm': 'mirror', 'r': 'raid',
					's': 'snapshot', 't': 'thin', 'u': 'unknown',
					'v': 'virtual', '-': 'Unspecified'}
		return (self.state.Attr[6], type_map[self.state.Attr[6]])

	@property
	def ZeroBlocks(self):
		return self.state.Attr[7] == 'z'

	@property
	def Health(self):
		type_map = {'p': 'partial', 'r': 'refresh',
					'm': 'mismatches', 'w': 'writemostly',
					'X': 'X unknown', '-': 'Unspecified'}
		return (self.state.Attr[8], type_map[self.state.Attr[8]])

	@property
	def SkipActivation(self):
		return self.state.Attr[9] == 'k'

	def vg_name_lookup(self):
		return self.state.vg_name_lookup()

	def lv_full_name(self):
		return "%s/%s" % (self.state.vg_name_lookup(), self.state.Name)

	@property
	def identifiers(self):
		return self.state.identifiers

	@property
	def Tags(self):
		return utils.parse_tags(self.state.Tags)

	@property
	def Roles(self):
		return utils.parse_tags(self.state.role)

	@property
	def lvm_id(self):
		return self.state.lvm_id

	@property
	def IsThinVolume(self):
		return self.state.Attr[0] == 'V'

	@property
	def IsThinPool(self):
		return self.state.Attr[0] == 't'

	@property
	def Active(self):
		return self.state.active == "active"

	@dbus.service.method(
		dbus_interface=LV_COMMON_INTERFACE,
		in_signature='ia{sv}',
		out_signature='o')
	def _Future(self, tmo, open_options):
		raise dbus.exceptions.DBusException(LV_COMMON_INTERFACE, 'Do not use!')


# noinspection PyPep8Naming
class Lv(LvCommon):
	def _fetch_hidden(self, name):

		# The name is vg/name
		full_name = "%s/%s" % (self.vg_name_lookup(), name)
		return cfg.om.get_object_path_by_lvm_id(full_name)

	def _get_data_meta(self):

		# Get the data
		return (self._fetch_hidden(self.state.data_lv),
				self._fetch_hidden(self.state.metadata_lv))

	# noinspection PyUnusedLocal,PyPep8Naming
	def __init__(self, object_path, object_state):
		super(Lv, self).__init__(object_path, object_state)
		self.set_interface(LV_INTERFACE)
		self.state = object_state

	@staticmethod
	def _remove(lv_uuid, lv_name, remove_options):
		# Make sure we have a dbus object representing it
		dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)

		if dbo:
			# Remove the LV, if successful then remove from the model
			rc, out, err = cmdhandler.lv_remove(lv_name, remove_options)

			if rc == 0:
				cfg.om.remove_object(dbo, True)
				cfg.load()
			else:
				# Need to work on error handling, need consistent
				raise dbus.exceptions.DBusException(
					LV_INTERFACE,
					'Exit code %s, stderr = %s' % (str(rc), err))
		else:
			raise dbus.exceptions.DBusException(
				LV_INTERFACE,
				'LV with uuid %s and name %s not present!' %
				(lv_uuid, lv_name))
		return '/'

	@dbus.service.method(
		dbus_interface=LV_INTERFACE,
		in_signature='ia{sv}',
		out_signature='o',
		async_callbacks=('cb', 'cbe'))
	def Remove(self, tmo, remove_options, cb, cbe):
		r = RequestEntry(
			tmo, Lv._remove,
			(self.Uuid, self.lvm_id, remove_options),
			cb, cbe, False)
		cfg.worker_q.put(r)

	@staticmethod
	def _rename(lv_uuid, lv_name, new_name, rename_options):
		# Make sure we have a dbus object representing it
		dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)

		if dbo:
			# Rename the logical volume
			rc, out, err = cmdhandler.lv_rename(lv_name, new_name,
												rename_options)
			if rc == 0:
				cfg.load()
			else:
				# Need to work on error handling, need consistent
				raise dbus.exceptions.DBusException(
					LV_INTERFACE,
					'Exit code %s, stderr = %s' % (str(rc), err))
		else:
			raise dbus.exceptions.DBusException(
				LV_INTERFACE,
				'LV with uuid %s and name %s not present!' %
				(lv_uuid, lv_name))
		return '/'

	@dbus.service.method(
		dbus_interface=LV_INTERFACE,
		in_signature='sia{sv}',
		out_signature='o',
		async_callbacks=('cb', 'cbe'))
	def Rename(self, name, tmo, rename_options, cb, cbe):
		utils.validate_lv_name(LV_INTERFACE, self.vg_name_lookup(), name)

		r = RequestEntry(
			tmo, Lv._rename,
			(self.Uuid, self.lvm_id, name, rename_options),
			cb, cbe, False)
		cfg.worker_q.put(r)

	@dbus.service.method(
		dbus_interface=LV_INTERFACE,
		in_signature='o(tt)a(ott)ia{sv}',
		out_signature='o',
		async_callbacks=('cb', 'cbe'))
	def Move(self, pv_src_obj, pv_source_range,
				pv_dests_and_ranges,
				tmo, move_options, cb, cbe):

		job_state = JobState()

		r = RequestEntry(
				tmo, background.move,
				(LV_INTERFACE, self.lvm_id, pv_src_obj, pv_source_range,
				pv_dests_and_ranges, move_options, job_state), cb, cbe, False,
				job_state)

		cfg.worker_q.put(r)

	@staticmethod
	def _snap_shot(lv_uuid, lv_name, name, optional_size,
			snapshot_options):
		# Make sure we have a dbus object representing it
		dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)

		if dbo:
			# If you specify a size you get a 'thick' snapshot even if
			# it is a thin lv
			if not dbo.IsThinVolume:
				if optional_size == 0:
					space = dbo.SizeBytes / 80
					remainder = space % 512
					optional_size = space + 512 - remainder

			rc, out, err = cmdhandler.vg_lv_snapshot(
				lv_name, snapshot_options, name, optional_size)
			if rc == 0:
				return_path = '/'
				full_name = "%s/%s" % (dbo.vg_name_lookup(), name)
				lvs = load_lvs([full_name], emit_signal=True)[0]
				for l in lvs:
					return_path = l.dbus_object_path()

				# Refresh self and all included PVs
				cfg.load(cache_refresh=False)
				return return_path
			else:
				raise dbus.exceptions.DBusException(
					LV_INTERFACE,
					'Exit code %s, stderr = %s' % (str(rc), err))
		else:
			raise dbus.exceptions.DBusException(
				LV_INTERFACE,
				'LV with uuid %s and name %s not present!' %
				(lv_uuid, lv_name))

	@dbus.service.method(
		dbus_interface=LV_INTERFACE,
		in_signature='stia{sv}',
		out_signature='(oo)',
		async_callbacks=('cb', 'cbe'))
	def Snapshot(self, name, optional_size, tmo,
			snapshot_options, cb, cbe):

		utils.validate_lv_name(LV_INTERFACE, self.vg_name_lookup(), name)

		r = RequestEntry(
			tmo, Lv._snap_shot,
			(self.Uuid, self.lvm_id, name,
			optional_size, snapshot_options), cb, cbe)
		cfg.worker_q.put(r)

	@staticmethod
	def _resize(lv_uuid, lv_name, new_size_bytes, pv_dests_and_ranges,
				resize_options):
		# Make sure we have a dbus object representing it
		pv_dests = []
		dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)

		if dbo:
			# If we have PVs, verify them
			if len(pv_dests_and_ranges):
				for pr in pv_dests_and_ranges:
					pv_dbus_obj = cfg.om.get_object_by_path(pr[0])
					if not pv_dbus_obj:
						raise dbus.exceptions.DBusException(
							LV_INTERFACE,
							'PV Destination (%s) not found' % pr[0])

					pv_dests.append((pv_dbus_obj.lvm_id, pr[1], pr[2]))

			size_change = new_size_bytes - dbo.SizeBytes

			rc, out, err = cmdhandler.lv_resize(dbo.lvm_id, size_change,
												pv_dests, resize_options)

			if rc == 0:
				# Refresh what's changed
				cfg.load()
				return "/"
			else:
				raise dbus.exceptions.DBusException(
					LV_INTERFACE,
					'Exit code %s, stderr = %s' % (str(rc), err))
		else:
			raise dbus.exceptions.DBusException(
				LV_INTERFACE,
				'LV with uuid %s and name %s not present!' %
				(lv_uuid, lv_name))

	@dbus.service.method(
		dbus_interface=LV_INTERFACE,
		in_signature='ta(ott)ia{sv}',
		out_signature='o',
		async_callbacks=('cb', 'cbe'))
	def Resize(self, new_size_bytes, pv_dests_and_ranges, tmo,
			resize_options, cb, cbe):
		"""
		Resize a LV
		:param new_size_bytes: The requested final size in bytes
		:param pv_dests_and_ranges: An array of pv object paths and src &
									dst. segment ranges
		:param tmo: -1 to wait forever, 0 to return job immediately, else
					number of seconds to wait for operation to complete
					before getting a job
		:param resize_options: key/value hash of options
		:param cb:  Used by framework not client facing API
		:param cbe: Used by framework not client facing API
		:return: '/' if complete, else job object path
		"""
		r = RequestEntry(
			tmo, Lv._resize,
			(self.Uuid, self.lvm_id, round_size(new_size_bytes),
			pv_dests_and_ranges,
			resize_options), cb, cbe, return_tuple=False)
		cfg.worker_q.put(r)

	@staticmethod
	def _lv_activate_deactivate(uuid, lv_name, activate, control_flags,
								options):
		# Make sure we have a dbus object representing it
		dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, lv_name)

		if dbo:
			rc, out, err = cmdhandler.activate_deactivate(
				'lvchange', lv_name, activate, control_flags, options)
			if rc == 0:
				dbo.refresh()
				return '/'
			else:
				raise dbus.exceptions.DBusException(
					LV_INTERFACE,
					'Exit code %s, stderr = %s' % (str(rc), err))
		else:
			raise dbus.exceptions.DBusException(
				LV_INTERFACE,
				'LV with uuid %s and name %s not present!' %
				(uuid, lv_name))

	@dbus.service.method(
		dbus_interface=LV_INTERFACE,
		in_signature='tia{sv}',
		out_signature='o',
		async_callbacks=('cb', 'cbe'))
	def Activate(self, control_flags, tmo, activate_options, cb, cbe):
		r = RequestEntry(
			tmo, Lv._lv_activate_deactivate,
			(self.state.Uuid, self.state.lvm_id, True,
			control_flags, activate_options),
			cb, cbe, return_tuple=False)
		cfg.worker_q.put(r)

	# noinspection PyProtectedMember
	@dbus.service.method(
		dbus_interface=LV_INTERFACE,
		in_signature='tia{sv}',
		out_signature='o',
		async_callbacks=('cb', 'cbe'))
	def Deactivate(self, control_flags, tmo, activate_options, cb, cbe):
		r = RequestEntry(
			tmo, Lv._lv_activate_deactivate,
			(self.state.Uuid, self.state.lvm_id, False,
			control_flags, activate_options),
			cb, cbe, return_tuple=False)
		cfg.worker_q.put(r)

	@staticmethod
	def _add_rm_tags(uuid, lv_name, tags_add, tags_del, tag_options):
		# Make sure we have a dbus object representing it
		dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, lv_name)

		if dbo:

			rc, out, err = cmdhandler.lv_tag(
				lv_name, tags_add, tags_del, tag_options)
			if rc == 0:
				dbo.refresh()
				return '/'
			else:
				raise dbus.exceptions.DBusException(
					LV_INTERFACE,
					'Exit code %s, stderr = %s' % (str(rc), err))

		else:
			raise dbus.exceptions.DBusException(
				LV_INTERFACE,
				'LV with uuid %s and name %s not present!' %
				(uuid, lv_name))

	@dbus.service.method(
		dbus_interface=LV_INTERFACE,
		in_signature='asia{sv}',
		out_signature='o',
		async_callbacks=('cb', 'cbe'))
	def TagsAdd(self, tags, tmo, tag_options, cb, cbe):

		for t in tags:
			utils.validate_tag(LV_INTERFACE, t)

		r = RequestEntry(
			tmo, Lv._add_rm_tags,
			(self.state.Uuid, self.state.lvm_id,
			tags, None, tag_options),
			cb, cbe, return_tuple=False)
		cfg.worker_q.put(r)

	@dbus.service.method(
		dbus_interface=LV_INTERFACE,
		in_signature='asia{sv}',
		out_signature='o',
		async_callbacks=('cb', 'cbe'))
	def TagsDel(self, tags, tmo, tag_options, cb, cbe):

		for t in tags:
			utils.validate_tag(LV_INTERFACE, t)

		r = RequestEntry(
			tmo, Lv._add_rm_tags,
			(self.state.Uuid, self.state.lvm_id,
			None, tags, tag_options),
			cb, cbe, return_tuple=False)
		cfg.worker_q.put(r)


# noinspection PyPep8Naming
class LvThinPool(Lv):
	_DataLv_meta = ("o", THIN_POOL_INTERFACE)
	_MetaDataLv_meta = ("o", THIN_POOL_INTERFACE)

	def __init__(self, object_path, object_state):
		super(LvThinPool, self).__init__(object_path, object_state)
		self.set_interface(THIN_POOL_INTERFACE)
		self._data_lv, self._metadata_lv = self._get_data_meta()

	@property
	def DataLv(self):
		return self._data_lv

	@property
	def MetaDataLv(self):
		return self._metadata_lv

	@staticmethod
	def _lv_create(lv_uuid, lv_name, name, size_bytes, create_options):
		# Make sure we have a dbus object representing it
		dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)

		lv_created = '/'

		if dbo:
			rc, out, err = cmdhandler.lv_lv_create(
				lv_name, create_options, name, size_bytes)
			if rc == 0:
				full_name = "%s/%s" % (dbo.vg_name_lookup(), name)
				lvs = load_lvs([full_name], emit_signal=True)[0]
				for l in lvs:
					lv_created = l.dbus_object_path()
			else:
				raise dbus.exceptions.DBusException(
					LV_INTERFACE,
					'Exit code %s, stderr = %s' % (str(rc), err))
		else:
			raise dbus.exceptions.DBusException(
				LV_INTERFACE,
				'LV with uuid %s and name %s not present!' %
				(lv_uuid, lv_name))
		return lv_created

	@dbus.service.method(
		dbus_interface=THIN_POOL_INTERFACE,
		in_signature='stia{sv}',
		out_signature='(oo)',
		async_callbacks=('cb', 'cbe'))
	def LvCreate(self, name, size_bytes, tmo, create_options, cb, cbe):
		utils.validate_lv_name(THIN_POOL_INTERFACE, self.vg_name_lookup(), name)

		r = RequestEntry(
			tmo, LvThinPool._lv_create,
			(self.Uuid, self.lvm_id, name,
			round_size(size_bytes), create_options), cb, cbe)
		cfg.worker_q.put(r)


# noinspection PyPep8Naming
class LvCachePool(Lv):
	_DataLv_meta = ("o", CACHE_POOL_INTERFACE)
	_MetaDataLv_meta = ("o", CACHE_POOL_INTERFACE)

	def __init__(self, object_path, object_state):
		super(LvCachePool, self).__init__(object_path, object_state)
		self.set_interface(CACHE_POOL_INTERFACE)
		self._data_lv, self._metadata_lv = self._get_data_meta()

	@property
	def DataLv(self):
		return self._data_lv

	@property
	def MetaDataLv(self):
		return self._metadata_lv

	@staticmethod
	def _cache_lv(lv_uuid, lv_name, lv_object_path, cache_options):

		# Make sure we have a dbus object representing cache pool
		dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)

		# Make sure we have dbus object representing lv to cache
		lv_to_cache = cfg.om.get_object_by_path(lv_object_path)

		if dbo and lv_to_cache:
			fcn = lv_to_cache.lv_full_name()
			rc, out, err = cmdhandler.lv_cache_lv(
				dbo.lv_full_name(), fcn, cache_options)
			if rc == 0:
				# When we cache an LV, the cache pool and the lv that is getting
				# cached need to be removed from the object manager and
				# re-created as their interfaces have changed!
				cfg.om.remove_object(dbo, emit_signal=True)
				cfg.om.remove_object(lv_to_cache, emit_signal=True)
				cfg.load()

				lv_converted = cfg.om.get_object_path_by_lvm_id(fcn)

			else:
				raise dbus.exceptions.DBusException(
					LV_INTERFACE,
					'Exit code %s, stderr = %s' % (str(rc), err))
		else:
			msg = ""
			if not dbo:
				dbo += 'CachePool LV with uuid %s and name %s not present!' % \
					(lv_uuid, lv_name)

			if not lv_to_cache:
				dbo += 'LV to cache with object path %s not present!' % \
					(lv_object_path)

			raise dbus.exceptions.DBusException(LV_INTERFACE, msg)
		return lv_converted

	@dbus.service.method(
		dbus_interface=CACHE_POOL_INTERFACE,
		in_signature='oia{sv}',
		out_signature='(oo)',
		async_callbacks=('cb', 'cbe'))
	def CacheLv(self, lv_object, tmo, cache_options, cb, cbe):
		r = RequestEntry(
			tmo, LvCachePool._cache_lv,
			(self.Uuid, self.lvm_id, lv_object,
			cache_options), cb, cbe)
		cfg.worker_q.put(r)


# noinspection PyPep8Naming
class LvCacheLv(Lv):
	_CachePool_meta = ("o", LV_CACHED)

	def __init__(self, object_path, object_state):
		super(LvCacheLv, self).__init__(object_path, object_state)
		self.set_interface(LV_CACHED)

	@property
	def CachePool(self):
		return self.state.PoolLv

	@staticmethod
	def _detach_lv(lv_uuid, lv_name, detach_options, destroy_cache):
		# Make sure we have a dbus object representing cache pool
		dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)

		if dbo:

			# Get current cache name
			cache_pool = cfg.om.get_object_by_path(dbo.CachePool)

			rc, out, err = cmdhandler.lv_detach_cache(
				dbo.lv_full_name(), detach_options, destroy_cache)
			if rc == 0:
				# The cache pool gets removed as hidden and put back to
				# visible, so lets delete
				cfg.om.remove_object(cache_pool, emit_signal=True)
				cfg.om.remove_object(dbo, emit_signal=True)
				cfg.load()

				uncached_lv_path = cfg.om.get_object_path_by_lvm_id(lv_name)
			else:
				raise dbus.exceptions.DBusException(
					LV_INTERFACE,
					'Exit code %s, stderr = %s' % (str(rc), err))
		else:
			raise dbus.exceptions.DBusException(
				LV_INTERFACE,
				'LV with uuid %s and name %s not present!' %
				(lv_uuid, lv_name))
		return uncached_lv_path

	@dbus.service.method(
		dbus_interface=LV_CACHED,
		in_signature='bia{sv}',
		out_signature='(oo)',
		async_callbacks=('cb', 'cbe'))
	def DetachCachePool(self, destroy_cache, tmo, detach_options, cb, cbe):
		r = RequestEntry(
			tmo, LvCacheLv._detach_lv,
			(self.Uuid, self.lvm_id, detach_options,
			destroy_cache), cb, cbe)
		cfg.worker_q.put(r)


# noinspection PyPep8Naming
class LvSnapShot(Lv):
	def __init__(self, object_path, object_state):
		super(LvSnapShot, self).__init__(object_path, object_state)
		self.set_interface(SNAPSHOT_INTERFACE)

	@dbus.service.method(
		dbus_interface=SNAPSHOT_INTERFACE,
		in_signature='ia{sv}',
		out_signature='o',
		async_callbacks=('cb', 'cbe'))
	def Merge(self, tmo, merge_options, cb, cbe):
		job_state = JobState()

		r = RequestEntry(tmo, background.merge,
							(SNAPSHOT_INTERFACE, self.Uuid, self.lvm_id,
							merge_options, job_state), cb, cbe, False,
							job_state)
		cfg.worker_q.put(r)
