2014-01-07 17:55:02 -08:00
|
|
|
"""
|
|
|
|
Copyright 2013 Rackspace, Inc.
|
|
|
|
|
|
|
|
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 httmock
|
|
|
|
import json
|
|
|
|
import mock
|
|
|
|
import time
|
|
|
|
import unittest
|
|
|
|
|
2014-03-19 16:19:52 -07:00
|
|
|
from ironic_python_agent import errors
|
|
|
|
from ironic_python_agent import hardware
|
|
|
|
from ironic_python_agent import ironic_api_client
|
2014-01-07 17:55:02 -08:00
|
|
|
|
2014-03-19 16:19:52 -07:00
|
|
|
API_URL = 'http://agent-api.ironic.example.org/'
|
2014-01-07 17:55:02 -08:00
|
|
|
|
|
|
|
|
2014-03-19 16:19:52 -07:00
|
|
|
class TestBaseIronicPythonAgent(unittest.TestCase):
|
2014-01-07 17:55:02 -08:00
|
|
|
def setUp(self):
|
2014-03-19 16:19:52 -07:00
|
|
|
self.api_client = ironic_api_client.APIClient(API_URL)
|
2014-01-28 11:25:36 -08:00
|
|
|
self.hardware_info = [
|
|
|
|
hardware.HardwareInfo(hardware.HardwareType.MAC_ADDRESS,
|
2014-03-19 13:55:56 -07:00
|
|
|
'aa:bb:cc:dd:ee:ff'),
|
2014-01-28 11:25:36 -08:00
|
|
|
hardware.HardwareInfo(hardware.HardwareType.MAC_ADDRESS,
|
2014-03-19 13:55:56 -07:00
|
|
|
'ff:ee:dd:cc:bb:aa'),
|
2014-01-28 11:25:36 -08:00
|
|
|
]
|
2014-01-07 17:55:02 -08:00
|
|
|
|
|
|
|
def test_successful_heartbeat(self):
|
|
|
|
expected_heartbeat_before = time.time() + 120
|
|
|
|
response = httmock.response(status_code=204, headers={
|
|
|
|
'Heartbeat-Before': expected_heartbeat_before,
|
|
|
|
})
|
|
|
|
|
2014-01-08 14:32:44 -08:00
|
|
|
self.api_client.session.request = mock.Mock()
|
|
|
|
self.api_client.session.request.return_value = response
|
2014-01-07 17:55:02 -08:00
|
|
|
|
2014-03-19 11:14:45 -07:00
|
|
|
heartbeat_before = self.api_client.heartbeat(
|
2014-03-19 13:55:56 -07:00
|
|
|
uuid='deadbeef-dabb-ad00-b105-f00d00bab10c',
|
2014-03-19 14:01:49 -07:00
|
|
|
advertise_address=('192.0.2.1', '9999')
|
2014-03-19 11:14:45 -07:00
|
|
|
)
|
2014-01-07 17:55:02 -08:00
|
|
|
|
|
|
|
self.assertEqual(heartbeat_before, expected_heartbeat_before)
|
|
|
|
|
2014-03-19 13:55:56 -07:00
|
|
|
heartbeat_path = 'v1/nodes/deadbeef-dabb-ad00-b105-f00d00bab10c/' \
|
|
|
|
'vendor_passthru/heartbeat'
|
2014-01-08 14:32:44 -08:00
|
|
|
request_args = self.api_client.session.request.call_args[0]
|
2014-03-14 16:40:51 -07:00
|
|
|
self.assertEqual(request_args[0], 'POST')
|
2014-03-19 13:55:56 -07:00
|
|
|
self.assertEqual(request_args[1], API_URL + heartbeat_path)
|
2014-01-07 17:55:02 -08:00
|
|
|
|
2014-01-07 18:11:57 -08:00
|
|
|
def test_heartbeat_requests_exception(self):
|
2014-01-08 14:32:44 -08:00
|
|
|
self.api_client.session.request = mock.Mock()
|
|
|
|
self.api_client.session.request.side_effect = Exception('api is down!')
|
2014-01-07 18:11:57 -08:00
|
|
|
|
|
|
|
self.assertRaises(errors.HeartbeatError,
|
|
|
|
self.api_client.heartbeat,
|
2014-03-19 13:55:56 -07:00
|
|
|
uuid='deadbeef-dabb-ad00-b105-f00d00bab10c',
|
2014-03-19 14:01:49 -07:00
|
|
|
advertise_address=('192.0.2.1', '9999'))
|
2014-01-07 18:11:57 -08:00
|
|
|
|
|
|
|
def test_heartbeat_invalid_status_code(self):
|
|
|
|
response = httmock.response(status_code=404)
|
2014-01-08 14:32:44 -08:00
|
|
|
self.api_client.session.request = mock.Mock()
|
|
|
|
self.api_client.session.request.return_value = response
|
2014-01-07 18:11:57 -08:00
|
|
|
|
|
|
|
self.assertRaises(errors.HeartbeatError,
|
|
|
|
self.api_client.heartbeat,
|
2014-03-19 13:55:56 -07:00
|
|
|
uuid='deadbeef-dabb-ad00-b105-f00d00bab10c',
|
2014-03-19 14:01:49 -07:00
|
|
|
advertise_address=('192.0.2.1', '9999'))
|
2014-01-07 18:11:57 -08:00
|
|
|
|
|
|
|
def test_heartbeat_missing_heartbeat_before_header(self):
|
|
|
|
response = httmock.response(status_code=204)
|
2014-01-08 14:32:44 -08:00
|
|
|
self.api_client.session.request = mock.Mock()
|
|
|
|
self.api_client.session.request.return_value = response
|
2014-01-07 18:11:57 -08:00
|
|
|
|
|
|
|
self.assertRaises(errors.HeartbeatError,
|
|
|
|
self.api_client.heartbeat,
|
2014-03-19 13:55:56 -07:00
|
|
|
uuid='deadbeef-dabb-ad00-b105-f00d00bab10c',
|
2014-03-19 14:01:49 -07:00
|
|
|
advertise_address=('192.0.2.1', '9999'))
|
2014-01-07 18:11:57 -08:00
|
|
|
|
|
|
|
def test_heartbeat_invalid_heartbeat_before_header(self):
|
|
|
|
response = httmock.response(status_code=204, headers={
|
|
|
|
'Heartbeat-Before': 'tomorrow',
|
|
|
|
})
|
2014-01-08 14:32:44 -08:00
|
|
|
self.api_client.session.request = mock.Mock()
|
|
|
|
self.api_client.session.request.return_value = response
|
2014-01-07 18:11:57 -08:00
|
|
|
|
|
|
|
self.assertRaises(errors.HeartbeatError,
|
|
|
|
self.api_client.heartbeat,
|
2014-03-19 13:55:56 -07:00
|
|
|
uuid='deadbeef-dabb-ad00-b105-f00d00bab10c',
|
2014-03-19 14:01:49 -07:00
|
|
|
advertise_address=('192.0.2.1', '9999'))
|
2014-03-14 16:40:51 -07:00
|
|
|
|
2014-03-18 10:36:33 -07:00
|
|
|
def test_lookup_node(self):
|
2014-03-14 16:40:51 -07:00
|
|
|
response = httmock.response(status_code=200, content={
|
|
|
|
'node': {
|
2014-03-19 13:55:56 -07:00
|
|
|
'uuid': 'deadbeef-dabb-ad00-b105-f00d00bab10c'
|
2014-03-14 16:40:51 -07:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
self.api_client.session.request = mock.Mock()
|
|
|
|
self.api_client.session.request.return_value = response
|
|
|
|
|
2014-03-18 10:36:33 -07:00
|
|
|
self.api_client.lookup_node(
|
2014-03-14 16:40:51 -07:00
|
|
|
hardware_info=self.hardware_info,
|
|
|
|
)
|
|
|
|
|
|
|
|
request_args = self.api_client.session.request.call_args[0]
|
|
|
|
self.assertEqual(request_args[0], 'POST')
|
|
|
|
self.assertEqual(request_args[1], API_URL + 'v1/drivers/teeth/lookup')
|
|
|
|
|
|
|
|
data = self.api_client.session.request.call_args[1]['data']
|
|
|
|
content = json.loads(data)
|
|
|
|
self.assertEqual(content['hardware'], [
|
|
|
|
{
|
|
|
|
'type': 'mac_address',
|
2014-03-19 13:55:56 -07:00
|
|
|
'id': 'aa:bb:cc:dd:ee:ff',
|
2014-03-14 16:40:51 -07:00
|
|
|
},
|
|
|
|
{
|
|
|
|
'type': 'mac_address',
|
2014-03-19 13:55:56 -07:00
|
|
|
'id': 'ff:ee:dd:cc:bb:aa',
|
2014-03-14 16:40:51 -07:00
|
|
|
},
|
|
|
|
])
|
|
|
|
|
2014-03-18 10:36:33 -07:00
|
|
|
def test_lookup_node_bad_response_code(self):
|
2014-03-14 16:40:51 -07:00
|
|
|
response = httmock.response(status_code=400, content={
|
|
|
|
'node': {
|
2014-03-19 13:55:56 -07:00
|
|
|
'uuid': 'deadbeef-dabb-ad00-b105-f00d00bab10c'
|
2014-03-14 16:40:51 -07:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
self.api_client.session.request = mock.Mock()
|
|
|
|
self.api_client.session.request.return_value = response
|
|
|
|
|
2014-03-18 10:39:47 -07:00
|
|
|
self.assertRaises(errors.LookupNodeError,
|
2014-03-18 10:36:33 -07:00
|
|
|
self.api_client.lookup_node,
|
2014-01-28 11:25:36 -08:00
|
|
|
hardware_info=self.hardware_info,
|
2014-03-14 16:40:51 -07:00
|
|
|
)
|
|
|
|
|
2014-03-18 10:36:33 -07:00
|
|
|
def test_lookup_node_bad_response_data(self):
|
2014-03-14 16:45:22 -07:00
|
|
|
response = httmock.response(status_code=200, content='a')
|
2014-03-14 16:40:51 -07:00
|
|
|
|
|
|
|
self.api_client.session.request = mock.Mock()
|
|
|
|
self.api_client.session.request.return_value = response
|
|
|
|
|
2014-03-18 10:39:47 -07:00
|
|
|
self.assertRaises(errors.LookupNodeError,
|
2014-03-18 10:36:33 -07:00
|
|
|
self.api_client.lookup_node,
|
2014-03-18 12:45:36 -07:00
|
|
|
hardware_info=self.hardware_info
|
2014-03-14 16:40:51 -07:00
|
|
|
)
|
|
|
|
|
2014-03-18 10:36:33 -07:00
|
|
|
def test_lookup_node_bad_response_body(self):
|
2014-03-14 16:40:51 -07:00
|
|
|
response = httmock.response(status_code=200, content={
|
|
|
|
'node_node': 'also_not_node'
|
|
|
|
})
|
|
|
|
|
|
|
|
self.api_client.session.request = mock.Mock()
|
|
|
|
self.api_client.session.request.return_value = response
|
|
|
|
|
2014-03-18 10:39:47 -07:00
|
|
|
self.assertRaises(errors.LookupNodeError,
|
2014-03-18 10:36:33 -07:00
|
|
|
self.api_client.lookup_node,
|
2014-03-14 16:40:51 -07:00
|
|
|
hardware_info=self.hardware_info,
|
2014-03-14 16:45:22 -07:00
|
|
|
)
|