summaryrefslogtreecommitdiff
path: root/daemons/lvmdbusd/job.py
blob: 1158370c2fd8da3fa26699477adadf6c9360e792 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# 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 .utils import job_obj_path_generate
from . import cfg
from .cfg import JOB_INTERFACE
import dbus
import threading
from . import background


# noinspection PyPep8Naming
class JobState(object):
	def __init__(self, request=None):
		self.rlock = threading.RLock()

		self._percent = 0
		self._complete = False
		self._request = request
		self._cond = threading.Condition(self.rlock)
		self._ec = 0
		self._stderr = ''

		# This is an lvm command that is just taking too long and doesn't
		# support background operation
		if self._request:
			# Faking the percentage when we don't have one
			self._percent = 1

	@property
	def Percent(self):
		with self.rlock:
			return self._percent

	@Percent.setter
	def Percent(self, value):
		with self.rlock:
			self._percent = value

	@property
	def Complete(self):
		with self.rlock:
			if self._request:
				self._complete = self._request.is_done()

			return self._complete

	@Complete.setter
	def Complete(self, value):
		with self.rlock:
			self._complete = value
			self._percent = 100
			self._cond.notify_all()

	@property
	def GetError(self):
		with self.rlock:
			if self.Complete:
				if self._request:
					(rc, error) = self._request.get_errors()
					return (rc, str(error))
				else:
					return (self._ec, self._stderr)
			else:
				return (-1, 'Job is not complete!')

	def set_result(self, ec, msg):
		with self.rlock:
			self.Complete = True
			self._ec = ec
			self._stderr = msg

	def dtor(self):
		with self.rlock:
			self._request = None

	def Wait(self, timeout):
		try:
			with self._cond:
				# Check to see if we are done, before we wait
				if not self.Complete:
					if timeout != -1:
						self._cond.wait(timeout)
					else:
						self._cond.wait()
				return self.Complete
		except RuntimeError:
			return False

	@property
	def Result(self):
		with self.rlock:
			if self._request:
				return self._request.result()
			return '/'


# noinspection PyPep8Naming
class Job(AutomatedProperties):
	_Percent_meta = ('d', JOB_INTERFACE)
	_Complete_meta = ('b', JOB_INTERFACE)
	_Result_meta = ('o', JOB_INTERFACE)
	_GetError_meta = ('(is)', JOB_INTERFACE)

	def __init__(self, request, job_state=None):
		super(Job, self).__init__(job_obj_path_generate())
		self.set_interface(JOB_INTERFACE)

		if job_state:
			self.state = job_state
		else:
			self.state = JobState(request)

	@property
	def Percent(self):
		return dbus.Double(float(self.state.Percent))

	@Percent.setter
	def Percent(self, value):
		self.state.Percent = value

	@property
	def Complete(self):
		return dbus.Boolean(self.state.Complete)

	@Complete.setter
	def Complete(self, value):
		self.state.Complete = value

	@property
	def GetError(self):
		return dbus.Struct(self.state.GetError, signature="(is)")

	def set_result(self, ec, msg):
		self.state.set_result(ec, msg)

	@dbus.service.method(dbus_interface=JOB_INTERFACE)
	def Remove(self):
		if self.state.Complete:
			cfg.om.remove_object(self, True)
			self.state.dtor()
		else:
			raise dbus.exceptions.DBusException(
				JOB_INTERFACE, 'Job is not complete!')

	@dbus.service.method(dbus_interface=JOB_INTERFACE,
							in_signature='i',
							out_signature='b',
							async_callbacks=('cb', 'cbe'))
	def Wait(self, timeout, cb, cbe):
		background.add_wait(self, timeout, cb, cbe)

	@property
	def Result(self):
		return dbus.ObjectPath(self.state.Result)

	@property
	def lvm_id(self):
		return str(id(self))

	@property
	def Uuid(self):
		import uuid
		return uuid.uuid1()