Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# Copyright (C) 2018 Bloomberg LP 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# <http://www.apache.org/licenses/LICENSE-2.0> 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14# 

15# Disable broad exception catch 

16# pylint: disable=broad-except 

17 

18 

19import asyncio 

20import logging 

21import threading 

22 

23from functools import partial 

24 

25import grpc 

26 

27from buildgrid._enums import LeaseState 

28from buildgrid._exceptions import BotError 

29 

30 

31class Tenant: 

32 

33 def __init__(self, lease): 

34 """Initialises a new :class:`Tenant`. 

35 

36 Args: 

37 lease (:class:`Lease`) : A new lease. 

38 

39 Raises: 

40 ValueError: If `lease` is not in a `PENDING` state. 

41 """ 

42 

43 if lease.state != LeaseState.PENDING.value: 

44 raise ValueError("Lease state not `PENDING`") 

45 

46 self._lease = lease 

47 self.__logger = logging.getLogger(__name__) 

48 self.__lease_cancelled = False 

49 self.__tenant_completed = False 

50 

51 @property 

52 def lease(self): 

53 """Returns the lease""" 

54 return self._lease 

55 

56 @property 

57 def tenant_completed(self): 

58 """Returns `True` if the work has completed or sucessfully stopped its work.""" 

59 return self.__tenant_completed 

60 

61 @property 

62 def lease_cancelled(self): 

63 """Returns `True` if the lease has been cancelled.""" 

64 return self.__lease_cancelled 

65 

66 def cancel_lease(self): 

67 """Cancel the lease.""" 

68 self.__lease_cancelled = True 

69 self.update_lease_state(LeaseState.CANCELLED) 

70 

71 def get_lease_state(self): 

72 """Returns the :class:`LeaseState`.""" 

73 return LeaseState(self._lease.state) 

74 

75 def update_lease_result(self, result): 

76 """Update the lease result. 

77 

78 Args: 

79 result (:class:`Any`) : The result of the lease.""" 

80 self._lease.result.CopyFrom(result) 

81 

82 def update_lease_state(self, state): 

83 """Update the lease state. 

84 

85 Args: 

86 state (:class:`LeaseState`) : State of the lease. 

87 """ 

88 self._lease.state = state.value 

89 

90 def update_lease_status(self, status): 

91 """Update the lease status. 

92 

93 Args: 

94 status (:class:`Status`) : Status of the lease. 

95 """ 

96 self._lease.status.CopyFrom(status) 

97 

98 async def run_work(self, work, context=None, executor=None): 

99 """Runs work. 

100 

101 Work is run in an executor. 

102 

103 Args: 

104 work (func) : Work to do. 

105 context (context) : Context for work. 

106 executor (:class:`ThreadPoolExecutor`) : Thread pool for work to run on. 

107 """ 

108 self.__logger.debug(f"Work created. Lease_id=[{self._lease.id}]") 

109 

110 loop = asyncio.get_event_loop() 

111 

112 try: 

113 event = threading.Event() 

114 lease = await loop.run_in_executor(executor, partial(work, self._lease, context, event)) 

115 

116 except asyncio.CancelledError: 

117 self.__logger.error(f"Lease cancelled: lease_id=[{self._lease.id}]") 

118 event.set() 

119 self.__tenant_completed = True 

120 # Propagate error to task wrapper 

121 raise 

122 

123 except grpc.RpcError as e: 

124 self.__logger.error(e) 

125 self.__tenant_completed = True 

126 raise 

127 

128 except BotError as e: 

129 if e.reason: 

130 self.__logger.error(e.reason) 

131 if str(e): 

132 self.__logger.error(e) 

133 if e.detail: 

134 self.__logger.error(e.detail) 

135 self.__tenant_completed = True 

136 raise 

137 

138 except Exception as e: 

139 self.__logger.error(e) 

140 self.__tenant_completed = True 

141 raise 

142 

143 self.__tenant_completed = True 

144 self.__logger.debug(f"Work completed: lease_id=[{lease.id}]") 

145 

146 return lease