@@ -75,6 +75,10 @@ async def bind_handle_to_claim(
75
75
76
76
# Loop through unbound instances to find best match
77
77
for resource_handle in cls .unbound_instances .values ():
78
+ # Skip unhealthy
79
+ if resource_handle .is_healthy == False :
80
+ continue
81
+
78
82
# Honor explicit pool requests
79
83
if resource_claim .resource_pool_name \
80
84
and resource_claim .resource_pool_name != resource_handle .resource_pool_name :
@@ -86,6 +90,16 @@ async def bind_handle_to_claim(
86
90
continue
87
91
88
92
diff_count = 0
93
+
94
+ # Prefer handles with known healthy status
95
+ if resource_handle .is_healthy == None :
96
+ diff_count += 0.1
97
+ # Prefer handles that are ready
98
+ if resource_handle .is_ready == False :
99
+ diff_count += 0.01
100
+ elif resource_handle .is_ready == None :
101
+ diff_count += 0.001
102
+
89
103
is_match = True
90
104
handle_resources = resource_handle .resources
91
105
if len (resource_claim_resources ) < len (handle_resources ):
@@ -131,7 +145,7 @@ async def bind_handle_to_claim(
131
145
matched_resource_handles .append ((diff_count , resource_handle ))
132
146
133
147
# Bind the oldest ResourceHandle with the smallest difference score
134
- matched_resource_handles .sort (key = lambda item : f"{ item [0 ]:09d } { item [1 ].creation_timestamp } " )
148
+ matched_resource_handles .sort (key = lambda item : f"{ item [0 ]:012.3f } { item [1 ].creation_timestamp } " )
135
149
for matched_resource_handle_item in matched_resource_handles :
136
150
matched_resource_handle = matched_resource_handle_item [1 ]
137
151
patch = [
@@ -597,13 +611,21 @@ def is_deleting(self) -> bool:
597
611
def is_from_resource_pool (self ) -> bool :
598
612
return 'resourcePool' in self .spec
599
613
614
+ @property
615
+ def is_healthy (self ) -> Optional [bool ]:
616
+ return self .status .get ('healthy' )
617
+
600
618
@property
601
619
def is_past_lifespan_end (self ) -> bool :
602
620
dt = self .lifespan_end_datetime
603
621
if not dt :
604
622
return False
605
623
return dt < datetime .now (timezone .utc )
606
624
625
+ @property
626
+ def is_ready (self ) -> Optional [bool ]:
627
+ return self .status .get ('ready' )
628
+
607
629
@property
608
630
def lifespan_end_datetime (self ) -> Any :
609
631
timestamp = self .lifespan_end_timestamp
@@ -1129,18 +1151,125 @@ async def update_status(self,
1129
1151
"path" : "/status" ,
1130
1152
"value" : {},
1131
1153
})
1154
+ if not 'resources' in self .status :
1155
+ patch .append ({
1156
+ "op" : "add" ,
1157
+ "path" : "/status/resources" ,
1158
+ "value" : [],
1159
+ })
1132
1160
1133
1161
resources = deepcopy (self .resources )
1134
1162
resource_states = await self .get_resource_states (logger = logger )
1135
1163
for idx , state in enumerate (resource_states ):
1136
1164
resources [idx ]['state' ] = state
1165
+ if len (self .status_resources ) < idx :
1166
+ patch .append ({
1167
+ "op" : "add" ,
1168
+ "path" : f"/status/resources/{ idx } " ,
1169
+ "value" : {},
1170
+ })
1137
1171
1138
- #for resource in resources:
1139
- # if
1140
- # await resourceprovider.ResourceProvider.get(resource['provider']['name'])
1172
+ overall_ready = True
1173
+ overall_healthy = True
1141
1174
1142
- # FIXME - add healthy
1143
- # FIXME - add ready
1175
+ for idx , resource in enumerate (resources ):
1176
+ if resource ['state' ]:
1177
+ resource_provider = await resourceprovider .ResourceProvider .get (resource ['provider' ]['name' ])
1178
+ resource_healthy = resource_provider .check_health (
1179
+ logger = logger ,
1180
+ resource_handle = self ,
1181
+ resource_state = resource ['state' ],
1182
+ )
1183
+ if resource_healthy :
1184
+ resource_ready = resource_provider .check_readiness (
1185
+ logger = logger ,
1186
+ resource_handle = self ,
1187
+ resource_state = resource ['state' ],
1188
+ )
1189
+ else :
1190
+ resource_ready = False
1191
+ else :
1192
+ resource_healthy = None
1193
+ resource_ready = False
1194
+
1195
+ # If the resource is not healthy then it is overall unhealthy.
1196
+ # If the resource health is unknown then he overall health is unknown unless it is unhealthy.
1197
+ if resource_healthy == False :
1198
+ overall_healthy = False
1199
+ elif resource_healthy == None :
1200
+ if overall_healthy :
1201
+ overall_healthy = None
1202
+
1203
+ if resource_ready == False :
1204
+ overall_ready = False
1205
+ elif resource_ready == None :
1206
+ if overall_ready :
1207
+ overall_ready = None
1208
+
1209
+ if len (self .status_resources ) <= idx :
1210
+ if resource_healthy != None :
1211
+ patch .append ({
1212
+ "op" : "add" ,
1213
+ "path" : f"/status/resources/{ idx } /healthy" ,
1214
+ "value" : resource_healthy ,
1215
+ })
1216
+ if resource_ready != None :
1217
+ patch .append ({
1218
+ "op" : "add" ,
1219
+ "path" : f"/status/resources/{ idx } /ready" ,
1220
+ "value" : resource_ready ,
1221
+ })
1222
+ else :
1223
+ if resource_healthy == None :
1224
+ if 'healthy' in self .status_resources [idx ]:
1225
+ patch .append ({
1226
+ "op" : "remove" ,
1227
+ "path" : f"/status/resources/{ idx } /healthy" ,
1228
+ })
1229
+ elif resource_healthy != self .status_resources [idx ].get ('healthy' ):
1230
+ patch .append ({
1231
+ "op" : "add" ,
1232
+ "path" : f"/status/resources/{ idx } /healthy" ,
1233
+ "value" : resource_healthy ,
1234
+ })
1235
+ if resource_ready == None :
1236
+ if 'ready' in self .status_resources [idx ]:
1237
+ patch .append ({
1238
+ "op" : "remove" ,
1239
+ "path" : f"/status/resources/{ idx } /ready" ,
1240
+ })
1241
+ elif resource_ready != self .status_resources [idx ].get ('ready' ):
1242
+ patch .append ({
1243
+ "op" : "add" ,
1244
+ "path" : f"/status/resources/{ idx } /ready" ,
1245
+ "value" : resource_ready ,
1246
+ })
1247
+
1248
+ if overall_healthy == None :
1249
+ if 'healthy' in self .status :
1250
+ patch .append ({
1251
+ "op" : "remove" ,
1252
+ "path" : f"/status/healthy" ,
1253
+ })
1254
+ elif overall_healthy != self .status .get ('healthy' ):
1255
+ patch .append ({
1256
+ "op" : "add" ,
1257
+ "path" : f"/status/healthy" ,
1258
+ "value" : overall_healthy ,
1259
+ })
1260
+
1261
+ if overall_ready == None :
1262
+ if 'ready' in self .status :
1263
+ patch .append ({
1264
+ "op" : "remove" ,
1265
+ "path" : f"/status/ready" ,
1266
+ })
1267
+ elif overall_ready != self .status .get ('ready' ):
1268
+ patch .append ({
1269
+ "op" : "add" ,
1270
+ "path" : f"/status/ready" ,
1271
+ "value" : overall_ready ,
1272
+ })
1144
1273
1145
1274
resource_provider = await self .get_resource_provider ()
1146
1275
if resource_provider .status_summary_template :
0 commit comments