From 756a3b86f381c50d47e8c88268f20e3e60caa5da Mon Sep 17 00:00:00 2001
From: Masahito Muroi <muroi.masahito@lab.ntt.co.jp>
Date: Mon, 24 Jul 2017 12:28:00 +0900
Subject: [PATCH] Add instance reservation filtering in BlazarFilter

BlazarFilter needs to pass a host if the scheduling request is
related to the new instance reservation feature.

This patch adds filtering rules for the new instance reservation
feature.

Partially implements: blueprint new-instance-reservation
Change-Id: Ifb61a3f858f13a84b7a841068d13da7c56fda3af
---
 blazarnova/scheduler/filters/blazar_filter.py | 12 ++++++++++++
 .../scheduler/filters/test_blazar_filter.py   | 19 ++++++++++++++++++-
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/blazarnova/scheduler/filters/blazar_filter.py b/blazarnova/scheduler/filters/blazar_filter.py
index 5e5cb5b..4769dba 100644
--- a/blazarnova/scheduler/filters/blazar_filter.py
+++ b/blazarnova/scheduler/filters/blazar_filter.py
@@ -24,6 +24,8 @@ from oslo_log import log as logging
 
 LOG = logging.getLogger(__name__)
 
+FLAVOR_EXTRA_SPEC = "aggregate_instance_extra_specs:reservation"
+
 opts = [
     cfg.StrOpt('aggregate_freepool_name',
                default='freepool',
@@ -121,6 +123,16 @@ class BlazarFilter(filters.BaseHostFilter):
             return self.host_reservation_request(host_state, spec_obj,
                                                  requested_pools)
 
+        # the request is instance reservation
+        if FLAVOR_EXTRA_SPEC in spec_obj.flavor.extra_specs.keys():
+            # Scheduling requests for instance reservation are processed by
+            # other Nova filters: AggregateInstanceExtraSpecsFilter,
+            # AggregateMultiTenancyIsolation, and
+            # ServerGroupAntiAffinityFilter. What BlazarFilter needs to
+            # do is just pass the host if the request has an instance
+            # reservation key.
+            return True
+
         if self.fetch_blazar_pools(host_state):
             # Host is in a blazar pool and non reservation request
             LOG.info(_("In a user pool or in the freepool"))
diff --git a/blazarnova/tests/scheduler/filters/test_blazar_filter.py b/blazarnova/tests/scheduler/filters/test_blazar_filter.py
index 31be9bd..a06fcec 100644
--- a/blazarnova/tests/scheduler/filters/test_blazar_filter.py
+++ b/blazarnova/tests/scheduler/filters/test_blazar_filter.py
@@ -19,6 +19,8 @@ from nova.tests.unit.scheduler import fakes
 from nova.virt import fake
 from oslo_config import cfg
 
+FLAVOR_EXTRA_SPEC = "aggregate_instance_extra_specs:reservation"
+
 
 class BlazarFilterTestCase(test.TestCase):
     """Filter test case.
@@ -41,7 +43,8 @@ class BlazarFilterTestCase(test.TestCase):
         # And a base spec_obj
         self.spec_obj = objects.RequestSpec(
             project_id='fakepj',
-            scheduler_hints={}
+            scheduler_hints={},
+            flavor=objects.Flavor(flavorid='flavor-id1', extra_specs={})
         )
 
     def test_blazar_filter_no_pool_available_requested(self):
@@ -267,3 +270,17 @@ class BlazarFilterTestCase(test.TestCase):
 
         # Then the host shall pass
         self.assertTrue(self.host.passes)
+
+    def test_instance_reservation_requested(self):
+
+        # A host is not in any aggregate
+        self.host.aggregates = []
+
+        # And instance-reservation-id1 is requested by an instance
+        self.spec_obj.flavor.extra_specs = {
+            FLAVOR_EXTRA_SPEC: 'instance-reservation-id1'}
+        self.spec_obj.flavor.flavorid = 'instance-reservation-id1'
+
+        self.host.passes = self.f.host_passes(self.host, self.spec_obj)
+
+        self.assertTrue(self.host.passes)