@@ -200,13 +200,14 @@ func TestFilterRequestedDestinationStep_Run(t *testing.T) {
200200 expectErr : false ,
201201 },
202202 {
203- name : "Filter by multiple aggregates" ,
203+ name : "Filter by multiple aggregates with OR syntax (comma-separated) " ,
204204 request : api.ExternalSchedulerRequest {
205205 Spec : api.NovaObject [api.NovaSpec ]{
206206 Data : api.NovaSpec {
207207 RequestedDestination : & api.NovaObject [api.NovaRequestedDestination ]{
208208 Data : api.NovaRequestedDestination {
209- Aggregates : []string {"aggregate1" , "aggregate3" },
209+ // "aggregate1,aggregate3" means host must be in aggregate1 OR aggregate3
210+ Aggregates : []string {"aggregate1,aggregate3" },
210211 },
211212 },
212213 },
@@ -241,12 +242,13 @@ func TestFilterRequestedDestinationStep_Run(t *testing.T) {
241242 expectErr : false ,
242243 },
243244 {
244- name : "Filter by aggregates - hosts in both spec and status " ,
245+ name : "Filter by multiple aggregates with AND logic " ,
245246 request : api.ExternalSchedulerRequest {
246247 Spec : api.NovaObject [api.NovaSpec ]{
247248 Data : api.NovaSpec {
248249 RequestedDestination : & api.NovaObject [api.NovaRequestedDestination ]{
249250 Data : api.NovaRequestedDestination {
251+ // ["aggregate1", "aggregate2"] means host must be in aggregate1 AND aggregate2
250252 Aggregates : []string {"aggregate1" , "aggregate2" },
251253 },
252254 },
@@ -258,6 +260,85 @@ func TestFilterRequestedDestinationStep_Run(t *testing.T) {
258260 {ComputeHost : "host3" },
259261 },
260262 },
263+ hypervisors : []hv1.Hypervisor {
264+ {
265+ ObjectMeta : metav1.ObjectMeta {Name : "host1" },
266+ Status : hv1.HypervisorStatus {Aggregates : []hv1.Aggregate {{UUID : "aggregate1" }}},
267+ },
268+ {
269+ ObjectMeta : metav1.ObjectMeta {Name : "host2" },
270+ Status : hv1.HypervisorStatus {Aggregates : []hv1.Aggregate {{UUID : "aggregate1" }, {UUID : "aggregate2" }}},
271+ },
272+ {
273+ ObjectMeta : metav1.ObjectMeta {Name : "host3" },
274+ Status : hv1.HypervisorStatus {Aggregates : []hv1.Aggregate {{UUID : "aggregate2" }}},
275+ },
276+ },
277+ expectedHosts : []string {"host2" },
278+ filteredHosts : []string {"host1" , "host3" },
279+ expectErr : false ,
280+ },
281+ {
282+ name : "Filter by mixed AND/OR aggregates" ,
283+ request : api.ExternalSchedulerRequest {
284+ Spec : api.NovaObject [api.NovaSpec ]{
285+ Data : api.NovaSpec {
286+ RequestedDestination : & api.NovaObject [api.NovaRequestedDestination ]{
287+ Data : api.NovaRequestedDestination {
288+ // Host must be in (aggregate1 OR aggregate2) AND aggregate3
289+ Aggregates : []string {"aggregate1,aggregate2" , "aggregate3" },
290+ },
291+ },
292+ },
293+ },
294+ Hosts : []api.ExternalSchedulerHost {
295+ {ComputeHost : "host1" },
296+ {ComputeHost : "host2" },
297+ {ComputeHost : "host3" },
298+ {ComputeHost : "host4" },
299+ },
300+ },
301+ hypervisors : []hv1.Hypervisor {
302+ {
303+ ObjectMeta : metav1.ObjectMeta {Name : "host1" },
304+ Status : hv1.HypervisorStatus {Aggregates : []hv1.Aggregate {{UUID : "aggregate1" }, {UUID : "aggregate3" }}},
305+ },
306+ {
307+ ObjectMeta : metav1.ObjectMeta {Name : "host2" },
308+ Status : hv1.HypervisorStatus {Aggregates : []hv1.Aggregate {{UUID : "aggregate2" }, {UUID : "aggregate3" }}},
309+ },
310+ {
311+ ObjectMeta : metav1.ObjectMeta {Name : "host3" },
312+ Status : hv1.HypervisorStatus {Aggregates : []hv1.Aggregate {{UUID : "aggregate1" }}},
313+ },
314+ {
315+ ObjectMeta : metav1.ObjectMeta {Name : "host4" },
316+ Status : hv1.HypervisorStatus {Aggregates : []hv1.Aggregate {{UUID : "aggregate3" }}},
317+ },
318+ },
319+ expectedHosts : []string {"host1" , "host2" },
320+ filteredHosts : []string {"host3" , "host4" },
321+ expectErr : false ,
322+ },
323+ {
324+ name : "Filter by aggregates with OR syntax - hosts in both spec and status" ,
325+ request : api.ExternalSchedulerRequest {
326+ Spec : api.NovaObject [api.NovaSpec ]{
327+ Data : api.NovaSpec {
328+ RequestedDestination : & api.NovaObject [api.NovaRequestedDestination ]{
329+ Data : api.NovaRequestedDestination {
330+ // "aggregate1,aggregate2" means host must be in aggregate1 OR aggregate2
331+ Aggregates : []string {"aggregate1,aggregate2" },
332+ },
333+ },
334+ },
335+ },
336+ Hosts : []api.ExternalSchedulerHost {
337+ {ComputeHost : "host1" },
338+ {ComputeHost : "host2" },
339+ {ComputeHost : "host3" },
340+ },
341+ },
261342 hypervisors : []hv1.Hypervisor {
262343 {
263344 ObjectMeta : metav1.ObjectMeta {Name : "host1" },
0 commit comments