astara/astara/test/unit/test_tenant.py

296 lines
9.6 KiB
Python

# Copyright 2014 DreamHost, LLC
#
# Author: DreamHost, LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import uuid
import mock
import unittest2 as unittest
from six.moves import range
from astara import event
from astara import tenant
from astara.drivers import router
from astara import state
from astara.drivers import states
from astara.test.unit import fakes
class TestTenantResourceManager(unittest.TestCase):
def setUp(self):
super(TestTenantResourceManager, self).setUp()
self.fake_driver = fakes.fake_driver()
self.tenant_id = 'cfb48b9c-66f6-11e5-a7be-525400cfc326'
self.instance_mgr = \
mock.patch('astara.instance_manager.InstanceManager').start()
self.addCleanup(mock.patch.stopall)
self.notifier = mock.Mock()
self.deleter = mock.Mock()
self.trm = tenant.TenantResourceManager(
'1234',
delete_callback=self.deleter,
notify_callback=self.notifier,
queue_warning_threshold=10,
reboot_error_threshold=5,
)
self.ctx = mock.Mock()
def test_new_resource(self):
r = event.Resource(
tenant_id=self.tenant_id,
id='5678',
driver=router.Router.RESOURCE_NAME,
)
msg = event.Event(
resource=r,
crud=event.CREATE,
body={'key': 'value'},
)
sm = self.trm.get_state_machines(msg, self.ctx)[0]
self.assertEqual(sm.resource_id, '5678')
self.assertIn('5678', self.trm.state_machines)
def test_get_state_machine_no_resoruce_id(self):
r = event.Resource(
tenant_id=self.tenant_id,
id=None,
driver=router.Router.RESOURCE_NAME,
)
msg = event.Event(
resource=r,
crud=event.CREATE,
body={'key': 'value'},
)
self.assertRaises(tenant.InvalidIncomingMessage,
self.trm.get_state_machines, msg, self.ctx)
def test_all_resources(self):
for i in range(5):
rid = str(uuid.uuid4())
driver = fakes.fake_driver(rid)
sm = state.Automaton(
driver=driver,
worker_context=self.ctx,
resource_id=driver.id,
tenant_id=self.tenant_id,
delete_callback=None,
bandwidth_callback=None,
queue_warning_threshold=5,
reboot_error_threshold=5)
self.trm.state_machines[rid] = sm
r = event.Resource(
tenant_id=self.tenant_id,
id='*',
driver=router.Router.RESOURCE_NAME,
)
msg = event.Event(
resource=r,
crud=event.CREATE,
body={'key': 'value'},
)
sms = self.trm.get_state_machines(msg, self.ctx)
self.assertEqual(5, len(sms))
def test_errored_routers(self):
self.trm.state_machines.state_machines = {}
for i in range(5):
rid = str(uuid.uuid4())
driver = fakes.fake_driver(rid)
sm = state.Automaton(
driver=driver,
worker_context=self.ctx,
resource_id=i,
tenant_id=self.tenant_id,
delete_callback=None,
bandwidth_callback=None,
queue_warning_threshold=5,
reboot_error_threshold=5)
self.trm.state_machines[rid] = sm
# Replace the default mock with one that has 'state' set.
if i == 2:
status = states.ERROR
else:
status = states.UP
sm.instance = mock.Mock(state=status)
self.trm.state_machines.state_machines[str(i)] = sm
r = event.Resource(
tenant_id=self.tenant_id,
id='2',
driver=router.Router.RESOURCE_NAME,
)
msg = event.Event(
resource=r,
crud=event.CREATE,
body={'key': 'value'},
)
sms = self.trm.get_state_machines(msg, self.ctx)
self.assertEqual(1, len(sms))
self.assertEqual(2, sms[0].resource_id)
self.assertIs(self.trm.state_machines.state_machines['2'], sms[0])
def test_existing_resource(self):
r = event.Resource(
tenant_id=self.tenant_id,
id='5678',
driver=router.Router.RESOURCE_NAME,
)
msg = event.Event(
resource=r,
crud=event.CREATE,
body={'key': 'value'},
)
# First time creates...
sm1 = self.trm.get_state_machines(msg, self.ctx)[0]
# Second time should return the same objects...
sm2 = self.trm.get_state_machines(msg, self.ctx)[0]
self.assertIs(sm1, sm2)
self.assertIs(sm1._queue, sm2._queue)
def test_existing_resource_of_many(self):
sms = {}
for resource_id in ['5678', 'ABCD', 'EFGH']:
r = event.Resource(
tenant_id=self.tenant_id,
id=resource_id,
driver=router.Router.RESOURCE_NAME,
)
msg = event.Event(
resource=r,
crud=event.CREATE,
body={'key': 'value'},
)
# First time creates...
sm1 = self.trm.get_state_machines(msg, self.ctx)[0]
sms[resource_id] = sm1
# Second time should return the same objects...
r = event.Resource(
id='5678',
tenant_id=self.tenant_id,
driver=router.Router.RESOURCE_NAME,
)
msg = event.Event(
resource=r,
crud=event.CREATE,
body={'key': 'value'},
)
sm2 = self.trm.get_state_machines(msg, self.ctx)[0]
self.assertIs(sm2, sms['5678'])
def test_delete_resource(self):
r = event.Resource(
id='1234',
tenant_id=self.tenant_id,
driver=router.Router.RESOURCE_NAME,
)
self.trm.state_machines['1234'] = mock.Mock()
self.trm._delete_resource(r)
self.assertNotIn('1234', self.trm.state_machines)
self.assertTrue(self.deleter.called)
def test_delete_default_resource(self):
r = event.Resource(
id='1234',
tenant_id=self.tenant_id,
driver=router.Router.RESOURCE_NAME)
self.trm._default_resource_id = '1234'
self.trm.state_machines['1234'] = mock.Mock()
self.trm._delete_resource(r)
self.assertNotIn('1234', self.trm.state_machines)
self.assertIs(None, self.trm._default_resource_id)
def test_delete_not_default_resource(self):
r = event.Resource(
id='1234',
tenant_id=self.tenant_id,
driver=router.Router.RESOURCE_NAME)
self.trm._default_resource_id = 'abcd'
self.trm.state_machines['1234'] = mock.Mock()
self.trm._delete_resource(r)
self.assertEqual('abcd', self.trm._default_resource_id)
def test_no_update_deleted_resource(self):
r = event.Resource(
tenant_id='1234',
id='5678',
driver=router.Router.RESOURCE_NAME,
)
self.trm._default_resource_id = 'abcd'
self.trm.state_machines['5678'] = mock.Mock()
self.trm._delete_resource(r)
self.assertEqual(self.trm.state_machines.values(), [])
r = event.Resource(
tenant_id='1234',
id='5678',
driver=router.Router.RESOURCE_NAME,
)
msg = event.Event(
resource=r,
crud=event.CREATE,
body={'key': 'value'},
)
sms = self.trm.get_state_machines(msg, self.ctx)
self.assertEqual(sms, [])
self.assertIn('5678', self.trm.state_machines.deleted)
def test_deleter_callback(self):
r = event.Resource(
tenant_id='1234',
id='5678',
driver=router.Router.RESOURCE_NAME,
)
msg = event.Event(
resource=r,
crud=event.CREATE,
body={'key': 'value'},
)
sm = self.trm.get_state_machines(msg, self.ctx)[0]
self.assertIn('5678', self.trm.state_machines)
sm._do_delete()
self.assertNotIn('5678', self.trm.state_machines)
def test_report_bandwidth(self):
notifications = []
self.notifier.side_effect = notifications.append
self.trm._report_bandwidth(
'5678',
[{'name': 'a',
'value': 1,
},
{'name': 'b',
'value': 2,
}],
)
n = notifications[0]
self.assertEqual('1234', n['tenant_id'])
self.assertIn('5678', n['uuid'])
self.assertIn('timestamp', n)
self.assertEqual('astara.bandwidth.used', n['event_type'])
self.assertIn('a', n['payload'])
self.assertIn('b', n['payload'])
def test_get_state_machine_by_resource_id(self):
fake_sm = mock.Mock()
self.trm.state_machines['fake_resource_id'] = fake_sm
self.assertEqual(
self.trm.get_state_machine_by_resource_id('fake_resource_id'),
fake_sm
)