15
15
import datetime
16
16
import sys
17
17
import time
18
- import ast
18
+ import json
19
19
import threading
20
+ from leaderelectionrecord import LeaderElectionRecord
20
21
import logging
22
+
21
23
logging .basicConfig (level = logging .INFO )
22
24
23
25
@@ -35,16 +37,6 @@ def __init__(self, election_config):
35
37
# Latest update time of the lock
36
38
self .observed_time_milliseconds = 0
37
39
38
-
39
- # Annotation used in the lock object
40
- def leaderelector_record (self , election_config , now ):
41
- return {
42
- "holderIdentity" : str (election_config .lock .identity ),
43
- "leaseDurationSeconds" : str (election_config .lease_duration ),
44
- "acquireTime" : str (now ),
45
- "renewTime" : str (now )
46
- }
47
-
48
40
# Point of entry to Leader election
49
41
def run (self ):
50
42
# Try to create/ acquire a lock
@@ -77,13 +69,13 @@ def renew_loop(self):
77
69
logging .info ("Leader has entered renew loop and will try to update lease continuously" )
78
70
79
71
retry_period = self .election_config .retry_period
80
- renew_deadline = self .election_config .renew_deadline * 1000
72
+ renew_deadline = self .election_config .renew_deadline * 1000
81
73
82
74
while True :
83
- timeout = int (time .time ()* 1000 ) + renew_deadline
75
+ timeout = int (time .time () * 1000 ) + renew_deadline
84
76
succeeded = False
85
77
86
- while int (time .time ()* 1000 ) < timeout :
78
+ while int (time .time () * 1000 ) < timeout :
87
79
succeeded = self .try_acquire_or_renew ()
88
80
89
81
if succeeded :
@@ -101,82 +93,76 @@ def try_acquire_or_renew(self):
101
93
now = datetime .datetime .now ()
102
94
103
95
# Check if lock is created
104
- lock_status , lock_response , lock_record = self .election_config .lock .get (self .election_config .lock .name ,
105
- self .election_config .lock .namespace )
96
+ lock_status , old_election_record = self .election_config .lock .get (self .election_config .lock .name ,
97
+ self .election_config .lock .namespace )
106
98
107
99
# create a default Election record for this candidate
108
- leader_election_record = self .leaderelector_record (self .election_config , now )
100
+ leader_election_record = LeaderElectionRecord (self .election_config .lock .identity ,
101
+ str (self .election_config .lease_duration ), str (now ), str (now ))
109
102
110
103
# A lock is not created with that name, try to create one
111
104
if not lock_status :
112
- if ast .literal_eval (lock_response .body )['code' ] != 404 :
113
- logging .info ("Error retrieving resource lock {} as {}" .format (self .election_config .lock .name , lock_response .reason ))
105
+ if json .loads (old_election_record .body )['code' ] != 404 :
106
+ logging .info ("Error retrieving resource lock {} as {}" .format (self .election_config .lock .name ,
107
+ old_election_record .reason ))
114
108
return False
115
109
116
-
117
- logging .info ("{} is trying to create a lock" .format (leader_election_record ['holderIdentity' ]))
118
- create_status , create_response = self .election_config .lock .create (name = self .election_config .lock .name ,
119
- namespace = self .election_config .lock .namespace ,
120
- election_record = leader_election_record )
110
+ logging .info ("{} is trying to create a lock" .format (leader_election_record .holder_identity ))
111
+ create_status = self .election_config .lock .create (name = self .election_config .lock .name ,
112
+ namespace = self .election_config .lock .namespace ,
113
+ election_record = leader_election_record )
121
114
122
115
if create_status is False :
116
+ logging .info ("{} Failed to create lock" .format (leader_election_record .holder_identity ))
123
117
return False
124
118
125
119
self .observed_record = leader_election_record
126
120
self .observed_time_milliseconds = int (time .time () * 1000 )
127
121
return True
128
122
129
123
# A lock exists with that name
130
- # Validate lock_record
131
- if lock_record is None :
124
+ # Validate old_election_record
125
+ if old_election_record is None :
132
126
# try to update lock with proper annotation and election record
133
- return self .update_lock (lock_response , leader_election_record )
134
-
135
- # check for any key, value errors in the record
136
- try :
137
- old_election_record = ast .literal_eval (lock_record )
138
- if (old_election_record ['holderIdentity' ] == '' or old_election_record ['leaseDurationSeconds' ] == ''
139
- or old_election_record ['acquireTime' ] == '' or old_election_record ['renewTime' ] == '' ):
140
- # try to update lock with proper annotation and election record
141
- return self .update_lock (lock_response , leader_election_record )
142
- except :
143
- # try to update lock with proper annotation and election record
144
- return self .update_lock (lock_response , leader_election_record )
127
+ return self .update_lock (leader_election_record )
145
128
129
+ if (old_election_record .holder_identity is None or old_election_record .lease_duration is None
130
+ or old_election_record .acquire_time is None or old_election_record .renew_time is None ):
131
+ # try to update lock with proper annotation and election record
132
+ return self .update_lock (leader_election_record )
146
133
147
134
# Report transitions
148
- if self .observed_record and self .observed_record [ 'holderIdentity' ] != old_election_record [ 'holderIdentity' ] :
149
- logging .info ("Leader has switched to {}" .format (old_election_record [ 'holderIdentity' ] ))
135
+ if self .observed_record and self .observed_record . holder_identity != old_election_record . holder_identity :
136
+ logging .info ("Leader has switched to {}" .format (old_election_record . holder_identity ))
150
137
151
- if old_election_record != self .observed_record :
138
+ if self . observed_record is None or old_election_record . __dict__ != self .observed_record . __dict__ :
152
139
self .observed_record = old_election_record
153
140
self .observed_time_milliseconds = int (time .time () * 1000 )
154
141
155
142
# If This candidate is not the leader and lease duration is yet to finish
156
- if (str ( self .election_config .lock .identity ) != self .observed_record [ 'holderIdentity' ]
157
- and self .observed_time_milliseconds + self .election_config .lease_duration * 1000 > int (now .timestamp ()* 1000 )):
158
- logging .info ("yet to finish lease_duration, lease held by {} and has not expired" .format (old_election_record [ 'holderIdentity' ] ))
143
+ if (self .election_config .lock .identity != self .observed_record . holder_identity
144
+ and self .observed_time_milliseconds + self .election_config .lease_duration * 1000 > int (now .timestamp () * 1000 )):
145
+ logging .info ("yet to finish lease_duration, lease held by {} and has not expired" .format (old_election_record . holder_identity ))
159
146
return False
160
147
161
148
# If this candidate is the Leader
162
- if str ( self .election_config .lock .identity ) == self .observed_record [ 'holderIdentity' ] :
163
- # Leader sets acquireTime
164
- leader_election_record [ 'acquireTime' ] = self .observed_record [ 'acquireTime' ]
149
+ if self .election_config .lock .identity == self .observed_record . holder_identity :
150
+ # Leader updates renewTime, but keeps acquire_time unchanged
151
+ leader_election_record . acquire_time = self .observed_record . acquire_time
165
152
166
- return self .update_lock (lock_response , leader_election_record )
153
+ return self .update_lock (leader_election_record )
167
154
168
- def update_lock (self , lock_response , leader_election_record ):
155
+ def update_lock (self , leader_election_record ):
169
156
# Update object with latest election record
170
- update_status , update_response = self .election_config .lock .update (self .election_config .lock .name ,
171
- self .election_config .lock .namespace ,
172
- lock_response , leader_election_record )
157
+ update_status = self .election_config .lock .update (self .election_config .lock .name ,
158
+ self .election_config .lock .namespace ,
159
+ leader_election_record )
173
160
174
161
if update_status is False :
175
- logging .info ("{} failed to acquire lease" .format (leader_election_record [ 'holderIdentity' ] ))
162
+ logging .info ("{} failed to acquire lease" .format (leader_election_record . holder_identity ))
176
163
return False
177
164
178
165
self .observed_record = leader_election_record
179
166
self .observed_time_milliseconds = int (time .time () * 1000 )
180
- logging .info ("leader {} has successfully acquired lease" .format (leader_election_record [ 'holderIdentity' ] ))
167
+ logging .info ("leader {} has successfully acquired lease" .format (leader_election_record . holder_identity ))
181
168
return True
182
-
0 commit comments