Compare commits

..

5 Commits

Author SHA1 Message Date
Thierry Carrez
837e658999 Move queue declaration to project level
This moves the watcher queue declaration from the pipeline level
(where it is no longer valid) to the project level.

https: //lists.openstack.org/pipermail/openstack-discuss/2022-May/028603.html
Change-Id: I06923abb00f7eecd59587f44cd1f6a069e88a9fc
(cherry picked from commit 6003322711)
2023-08-19 07:30:59 +00:00
limin0801
70a24cb009 Watcher API supports strategy name when creating audit template
when directly using the `curl` command to create audit template,
strategy name can be accepted.

Closes-Bug: #1884174

Change-Id: I7c0ca760a7fa414faca03c5293df34a84aad6fac
(cherry picked from commit 3f7a508a2e)
2020-07-10 01:16:19 +00:00
Zuul
69a9e4bee4 Merge "Compatible with old scope format" into stable/train 2020-06-19 07:53:37 +00:00
licanwei
8ef9d14a54 Check if scope is None
if scope is None, don't create data model

Change-Id: Icf611966c9b0a3882615d778ee6c72a8da73841d
Closed-Bug: #1881920
(cherry picked from commit 9f0138e1cf)
2020-06-19 01:46:37 +00:00
licanwei
4422878ec7 Compatible with old scope format
Scope format changed from old to new after bp cdm-scoping.

old format:
  - availability_zones:
    - name: nova
  - host_aggregates:
    - id: 1
    - name: agg
  - exclude:
    - compute_nodes:
      - name: w012

new format:
- compute:
  - availability_zones:
    - name: nova
  - host_aggregates:
    - id: 1
    - name: agg
  - exclude:
    - compute_nodes:
      - name: w012

Change-Id: I2b5cd4d1cee19f5588e4d2185eb074343fff1187
Closed-Bug: #1882049
(cherry picked from commit 4a1915bec4)
2020-06-11 02:16:04 +00:00
7 changed files with 109 additions and 7 deletions

View File

@@ -1,4 +1,5 @@
- project: - project:
queue: watcher
templates: templates:
- check-requirements - check-requirements
- openstack-cover-jobs - openstack-cover-jobs
@@ -17,7 +18,6 @@
- watcher-tls-test - watcher-tls-test
- watcher-tempest-functional-ipv6-only - watcher-tempest-functional-ipv6-only
gate: gate:
queue: watcher
jobs: jobs:
- watcher-tempest-functional - watcher-tempest-functional
- watcher-tempest-functional-ipv6-only - watcher-tempest-functional-ipv6-only

View File

@@ -138,6 +138,9 @@ class AuditTemplatePostType(wtypes.Base):
raise exception.InvalidGoal(goal=audit_template.goal) raise exception.InvalidGoal(goal=audit_template.goal)
if audit_template.scope: if audit_template.scope:
keys = [list(s)[0] for s in audit_template.scope]
if keys[0] not in ('compute', 'storage'):
audit_template.scope = [dict(compute=audit_template.scope)]
common_utils.Draft4Validator( common_utils.Draft4Validator(
AuditTemplatePostType._build_schema() AuditTemplatePostType._build_schema()
).validate(audit_template.scope) ).validate(audit_template.scope)
@@ -158,18 +161,23 @@ class AuditTemplatePostType(wtypes.Base):
"included and excluded together")) "included and excluded together"))
if audit_template.strategy: if audit_template.strategy:
available_strategies = objects.Strategy.list( try:
AuditTemplatePostType._ctx) if (common_utils.is_uuid_like(audit_template.strategy) or
available_strategies_map = { common_utils.is_int_like(audit_template.strategy)):
s.uuid: s for s in available_strategies} strategy = objects.Strategy.get(
if audit_template.strategy not in available_strategies_map: AuditTemplatePostType._ctx, audit_template.strategy)
else:
strategy = objects.Strategy.get_by_name(
AuditTemplatePostType._ctx, audit_template.strategy)
except Exception:
raise exception.InvalidStrategy( raise exception.InvalidStrategy(
strategy=audit_template.strategy) strategy=audit_template.strategy)
strategy = available_strategies_map[audit_template.strategy]
# Check that the strategy we indicate is actually related to the # Check that the strategy we indicate is actually related to the
# specified goal # specified goal
if strategy.goal_id != goal.id: if strategy.goal_id != goal.id:
available_strategies = objects.Strategy.list(
AuditTemplatePostType._ctx)
choices = ["'%s' (%s)" % (s.uuid, s.name) choices = ["'%s' (%s)" % (s.uuid, s.name)
for s in available_strategies] for s in available_strategies]
raise exception.InvalidStrategy( raise exception.InvalidStrategy(

View File

@@ -152,6 +152,9 @@ class CinderClusterDataModelCollector(base.BaseClusterDataModelCollector):
if self._audit_scope_handler is None: if self._audit_scope_handler is None:
LOG.debug("No audit, Don't Build storage data model") LOG.debug("No audit, Don't Build storage data model")
return return
if self._data_model_scope is None:
LOG.debug("No audit scope, Don't Build storage data model")
return
builder = CinderModelBuilder(self.osc) builder = CinderModelBuilder(self.osc)
return builder.execute(self._data_model_scope) return builder.execute(self._data_model_scope)

View File

@@ -63,6 +63,9 @@ class BaremetalClusterDataModelCollector(base.BaseClusterDataModelCollector):
if self._audit_scope_handler is None: if self._audit_scope_handler is None:
LOG.debug("No audit, Don't Build Baremetal data model") LOG.debug("No audit, Don't Build Baremetal data model")
return return
if self._data_model_scope is None:
LOG.debug("No audit scope, Don't Build Baremetal data model")
return
builder = BareMetalModelBuilder(self.osc) builder = BareMetalModelBuilder(self.osc)
return builder.execute(self._data_model_scope) return builder.execute(self._data_model_scope)

View File

@@ -181,6 +181,9 @@ class NovaClusterDataModelCollector(base.BaseClusterDataModelCollector):
if self._audit_scope_handler is None: if self._audit_scope_handler is None:
LOG.debug("No audit, Don't Build compute data model") LOG.debug("No audit, Don't Build compute data model")
return return
if self._data_model_scope is None:
LOG.debug("No audit scope, Don't Build compute data model")
return
builder = NovaModelBuilder(self.osc) builder = NovaModelBuilder(self.osc)
return builder.execute(self._data_model_scope) return builder.execute(self._data_model_scope)

View File

@@ -555,6 +555,35 @@ class TestPost(FunctionalTestWithSetup):
response.json['created_at']).replace(tzinfo=None) response.json['created_at']).replace(tzinfo=None)
self.assertEqual(test_time, return_created_at) self.assertEqual(test_time, return_created_at)
@mock.patch.object(timeutils, 'utcnow')
def test_create_audit_template_with_strategy_name(self, mock_utcnow):
audit_template_dict = post_get_test_audit_template(
goal=self.fake_goal1.uuid,
strategy=self.fake_strategy1.name)
test_time = datetime.datetime(2000, 1, 1, 0, 0)
mock_utcnow.return_value = test_time
response = self.post_json('/audit_templates', audit_template_dict)
self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int)
# Check location header
self.assertIsNotNone(response.location)
expected_location = \
'/v1/audit_templates/%s' % response.json['uuid']
self.assertEqual(urlparse.urlparse(response.location).path,
expected_location)
self.assertTrue(utils.is_uuid_like(response.json['uuid']))
self.assertNotIn('updated_at', response.json.keys)
self.assertNotIn('deleted_at', response.json.keys)
self.assertEqual(self.fake_goal1.uuid, response.json['goal_uuid'])
self.assertEqual(self.fake_strategy1.uuid,
response.json['strategy_uuid'])
self.assertEqual(self.fake_strategy1.name,
response.json['strategy_name'])
return_created_at = timeutils.parse_isotime(
response.json['created_at']).replace(tzinfo=None)
self.assertEqual(test_time, return_created_at)
def test_create_audit_template_validation_with_aggregates(self): def test_create_audit_template_validation_with_aggregates(self):
scope = [{'compute': [{'host_aggregates': [{'id': '*'}]}, scope = [{'compute': [{'host_aggregates': [{'id': '*'}]},
{'availability_zones': [{'name': 'AZ1'}, {'availability_zones': [{'name': 'AZ1'},
@@ -663,6 +692,26 @@ class TestPost(FunctionalTestWithSetup):
self.assertEqual(400, response.status_int) self.assertEqual(400, response.status_int)
assert not cn_mock.called assert not cn_mock.called
def test_create_audit_template_with_old_scope(self):
scope = [{'host_aggregates': [{'id': '*'}]},
{'availability_zones': [{'name': 'AZ1'},
{'name': 'AZ2'}]},
{'exclude': [
{'instances': [
{'uuid': 'INSTANCE_1'},
{'uuid': 'INSTANCE_2'}]},
{'compute_nodes': [
{'name': 'Node_1'},
{'name': 'Node_2'}]},
]}
]
audit_template_dict = post_get_test_audit_template(
goal=self.fake_goal1.uuid,
strategy=self.fake_strategy1.uuid, scope=scope)
response = self.post_json('/audit_templates',
audit_template_dict)
self.assertEqual(201, response.status_int)
class TestDelete(api_base.FunctionalTest): class TestDelete(api_base.FunctionalTest):

View File

@@ -17,6 +17,9 @@
import mock import mock
from watcher.decision_engine.model.collector import base from watcher.decision_engine.model.collector import base
from watcher.decision_engine.model.collector import cinder
from watcher.decision_engine.model.collector import ironic
from watcher.decision_engine.model.collector import nova
from watcher.decision_engine.model import model_root from watcher.decision_engine.model import model_root
from watcher.tests import base as test_base from watcher.tests import base as test_base
@@ -55,3 +58,36 @@ class TestClusterDataModelCollector(test_base.TestCase):
self.assertIsNot( self.assertIsNot(
collector.cluster_data_model, collector.cluster_data_model,
collector.get_latest_cluster_data_model()) collector.get_latest_cluster_data_model())
class TestComputeDataModelCollector(test_base.TestCase):
def test_model_scope_is_none(self):
m_config = mock.Mock()
collector = nova.NovaClusterDataModelCollector(config=m_config)
collector._audit_scope_handler = mock.Mock()
collector._data_model_scope = None
self.assertIsNone(collector.execute())
class TestStorageDataModelCollector(test_base.TestCase):
def test_model_scope_is_none(self):
m_config = mock.Mock()
collector = cinder.CinderClusterDataModelCollector(config=m_config)
collector._audit_scope_handler = mock.Mock()
collector._data_model_scope = None
self.assertIsNone(collector.execute())
class TestBareMetalDataModelCollector(test_base.TestCase):
def test_model_scope_is_none(self):
m_config = mock.Mock()
collector = ironic.BaremetalClusterDataModelCollector(config=m_config)
collector._audit_scope_handler = mock.Mock()
collector._data_model_scope = None
self.assertIsNone(collector.execute())