Merge "Complete move of baremetal machine tests"

This commit is contained in:
Zuul
2017-12-01 21:13:52 +00:00
committed by Gerrit Code Review
6 changed files with 804 additions and 60 deletions

View File

@@ -17,81 +17,94 @@
from openstack import task_manager
class MachineCreate(task_manager.Task):
def main(self, client):
return client.ironic_client.node.create(**self.args)
class IronicTask(task_manager.Task):
def __init__(self, client, **kwargs):
super(IronicTask, self).__init__(**kwargs)
self.client = client
class MachineDelete(task_manager.Task):
def main(self, client):
return client.ironic_client.node.delete(**self.args)
class MachineCreate(IronicTask):
def main(self):
return self.client.ironic_client.node.create(*self.args, **self.kwargs)
class MachinePatch(task_manager.Task):
def main(self, client):
return client.ironic_client.node.update(**self.args)
class MachineDelete(IronicTask):
def main(self):
return self.client.ironic_client.node.delete(*self.args, **self.kwargs)
class MachinePortGet(task_manager.Task):
def main(self, client):
return client.ironic_client.port.get(**self.args)
class MachinePatch(IronicTask):
def main(self):
return self.client.ironic_client.node.update(*self.args, **self.kwargs)
class MachinePortGetByAddress(task_manager.Task):
def main(self, client):
return client.ironic_client.port.get_by_address(**self.args)
class MachinePortGet(IronicTask):
def main(self):
return self.client.ironic_client.port.get(*self.args, **self.kwargs)
class MachinePortCreate(task_manager.Task):
def main(self, client):
return client.ironic_client.port.create(**self.args)
class MachinePortGetByAddress(IronicTask):
def main(self):
return self.client.ironic_client.port.get_by_address(
*self.args, **self.kwargs)
class MachinePortDelete(task_manager.Task):
def main(self, client):
return client.ironic_client.port.delete(**self.args)
class MachinePortCreate(IronicTask):
def main(self):
return self.client.ironic_client.port.create(*self.args, **self.kwargs)
class MachinePortList(task_manager.Task):
def main(self, client):
return client.ironic_client.port.list()
class MachinePortDelete(IronicTask):
def main(self):
return self.client.ironic_client.port.delete(*self.args, **self.kwargs)
class MachineNodeGet(task_manager.Task):
def main(self, client):
return client.ironic_client.node.get(**self.args)
class MachinePortList(IronicTask):
def main(self):
return self.client.ironic_client.port.list()
class MachineNodeList(task_manager.Task):
def main(self, client):
return client.ironic_client.node.list(**self.args)
class MachineNodeGet(IronicTask):
def main(self):
return self.client.ironic_client.node.get(*self.args, **self.kwargs)
class MachineNodePortList(task_manager.Task):
def main(self, client):
return client.ironic_client.node.list_ports(**self.args)
class MachineNodeList(IronicTask):
def main(self):
return self.client.ironic_client.node.list(*self.args, **self.kwargs)
class MachineNodeUpdate(task_manager.Task):
def main(self, client):
return client.ironic_client.node.update(**self.args)
class MachineNodePortList(IronicTask):
def main(self):
return self.client.ironic_client.node.list_ports(
*self.args, **self.kwargs)
class MachineNodeValidate(task_manager.Task):
def main(self, client):
return client.ironic_client.node.validate(**self.args)
class MachineNodeUpdate(IronicTask):
def main(self):
return self.client.ironic_client.node.update(*self.args, **self.kwargs)
class MachineSetMaintenance(task_manager.Task):
def main(self, client):
return client.ironic_client.node.set_maintenance(**self.args)
class MachineNodeValidate(IronicTask):
def main(self):
return self.client.ironic_client.node.validate(
*self.args, **self.kwargs)
class MachineSetPower(task_manager.Task):
def main(self, client):
return client.ironic_client.node.set_power_state(**self.args)
class MachineSetMaintenance(IronicTask):
def main(self):
return self.client.ironic_client.node.set_maintenance(
*self.args, **self.kwargs)
class MachineSetProvision(task_manager.Task):
def main(self, client):
return client.ironic_client.node.set_provision_state(**self.args)
class MachineSetPower(IronicTask):
def main(self):
return self.client.ironic_client.node.set_power_state(
*self.args, **self.kwargs)
class MachineSetProvision(IronicTask):
def main(self):
return self.client.ironic_client.node.set_provision_state(
*self.args, **self.kwargs)

View File

@@ -16,6 +16,7 @@ import jsonpatch
import munch
from openstack.cloud.exc import * # noqa
from openstack.cloud import meta
from openstack.cloud import openstackcloud
from openstack.cloud import _tasks
from openstack.cloud import _utils
@@ -35,27 +36,28 @@ class OperatorCloud(openstackcloud.OpenStackCloud):
def list_nics(self):
with _utils.shade_exceptions("Error fetching machine port list"):
return self.manager.submit_task(_tasks.MachinePortList())
return meta.obj_list_to_munch(
self.manager.submit_task(_tasks.MachinePortList(self)))
def list_nics_for_machine(self, uuid):
with _utils.shade_exceptions(
"Error fetching port list for node {node_id}".format(
node_id=uuid)):
return self.manager.submit_task(
_tasks.MachineNodePortList(node_id=uuid))
return meta.obj_list_to_munch(self.manager.submit_task(
_tasks.MachineNodePortList(self, node_id=uuid)))
def get_nic_by_mac(self, mac):
"""Get Machine by MAC address"""
# TODO(shade) Finish porting ironic to REST/sdk
# try:
# return self.manager.submit_task(
# _tasks.MachineNodePortGet(port_id=mac))
# _tasks.MachineNodePortGet(self, port_id=mac))
# except ironic_exceptions.ClientException:
# return None
def list_machines(self):
return self._normalize_machines(
self.manager.submit_task(_tasks.MachineNodeList()))
self.manager.submit_task(_tasks.MachineNodeList(self)))
def get_machine(self, name_or_id):
"""Get Machine by name or uuid
@@ -211,7 +213,7 @@ class OperatorCloud(openstackcloud.OpenStackCloud):
nic = self.manager.submit_task(
_tasks.MachinePortCreate(address=row['mac'],
node_uuid=machine['uuid']))
created_nics.append(nic.uuid)
created_nics.append(nic['uuid'])
except Exception as e:
self.log.debug("ironic NIC registration failed", exc_info=True)
@@ -277,7 +279,10 @@ class OperatorCloud(openstackcloud.OpenStackCloud):
machine = self.get_machine(machine['uuid'])
if (machine['reservation'] is None and
machine['provision_state'] is not 'enroll'):
# NOTE(TheJulia): In this case, the node has
# has moved on from the previous state and is
# likely not being verified, as no lock is
# present on the node.
self.node_set_provision_state(
machine['uuid'], 'provide')
machine = self.get_machine(machine['uuid'])
@@ -292,8 +297,10 @@ class OperatorCloud(openstackcloud.OpenStackCloud):
raise OpenStackCloudException(
"Machine encountered a failure: %s"
% machine['last_error'])
return machine
if not isinstance(machine, str):
return self._normalize_machine(machine)
else:
return machine
def unregister_machine(self, nics, uuid, wait=False, timeout=600):
"""Unregister Baremetal from Ironic

View File

@@ -248,6 +248,16 @@ def make_fake_machine(machine_name, machine_id=None):
id=machine_id,
name=machine_name))
def make_fake_port(address, node_id=None, port_id=None):
if not node_id:
node_id = uuid.uuid4().hex
if not port_id:
port_id = uuid.uuid4().hex
return meta.obj_to_munch(FakeMachinePort(
id=port_id,
address=address,
node_id=node_id))
class FakeFloatingIP(object):
def __init__(self, id, pool, ip, fixed_ip, instance_id):
@@ -346,7 +356,7 @@ class FakeVolumeSnapshot(object):
class FakeMachine(object):
def __init__(self, id, name=None, driver=None, driver_info=None,
chassis_uuid=None, instance_info=None, instance_uuid=None,
properties=None):
properties=None, reservation=None, last_error=None):
self.uuid = id
self.name = name
self.driver = driver
@@ -355,6 +365,8 @@ class FakeMachine(object):
self.instance_info = instance_info
self.instance_uuid = instance_uuid
self.properties = properties
self.reservation = reservation
self.last_error = last_error
class FakeMachinePort(object):

View File

@@ -34,6 +34,12 @@ class TestBaremetalNode(base.IronicTestCase):
self.skipTest("Ironic operations not supported yet")
self.fake_baremetal_node = fakes.make_fake_machine(
self.name, self.uuid)
# TODO(TheJulia): Some tests below have fake ports,
# since they are required in some processes. Lets refactor
# them at some point to use self.fake_baremetal_port.
self.fake_baremetal_port = fakes.make_fake_port(
'00:01:02:03:04:05',
node_id=self.uuid)
def test_list_machines(self):
fake_baremetal_two = fakes.make_fake_machine('two', str(uuid.uuid4()))
@@ -822,6 +828,542 @@ class TestBaremetalNode(base.IronicTestCase):
self.assertIsNone(return_value)
self.assert_calls()
def test_register_machine(self):
mac_address = '00:01:02:03:04:05'
nics = [{'mac': mac_address}]
node_uuid = self.fake_baremetal_node['uuid']
# TODO(TheJulia): There is a lot of duplication
# in testing creation. Surely this hsould be a helper
# or something. We should fix this, after we have
# ironicclient removed, as in the mean time visibility
# will be helpful.
node_to_post = {
'chassis_uuid': None,
'driver': None,
'driver_info': None,
'name': self.fake_baremetal_node['name'],
'properties': None,
'uuid': node_uuid}
self.fake_baremetal_node['provision_state'] = 'available'
if 'provision_state' in node_to_post:
node_to_post.pop('provision_state')
self.register_uris([
dict(
method='POST',
uri=self.get_mock_url(
resource='nodes'),
json=self.fake_baremetal_node,
validate=dict(json=node_to_post)),
dict(
method='POST',
uri=self.get_mock_url(
resource='ports'),
validate=dict(json={'address': mac_address,
'node_uuid': node_uuid}),
json=self.fake_baremetal_port),
])
return_value = self.op_cloud.register_machine(nics, **node_to_post)
self.assertDictEqual(self.fake_baremetal_node, return_value)
self.assert_calls()
# TODO(TheJulia): After we remove ironicclient,
# we need to de-duplicate these tests. Possibly
# a dedicated class, although we should do it then
# as we may find differences that need to be accounted
# for newer microversions.
def test_register_machine_enroll(self):
mac_address = '00:01:02:03:04:05'
nics = [{'mac': mac_address}]
node_uuid = self.fake_baremetal_node['uuid']
node_to_post = {
'chassis_uuid': None,
'driver': None,
'driver_info': None,
'name': self.fake_baremetal_node['name'],
'properties': None,
'uuid': node_uuid}
self.fake_baremetal_node['provision_state'] = 'enroll'
manageable_node = self.fake_baremetal_node.copy()
manageable_node['provision_state'] = 'manageable'
available_node = self.fake_baremetal_node.copy()
available_node['provision_state'] = 'available'
self.register_uris([
dict(
method='POST',
uri=self.get_mock_url(
resource='nodes'),
validate=dict(json=node_to_post),
json=self.fake_baremetal_node),
dict(
method='POST',
uri=self.get_mock_url(
resource='ports'),
validate=dict(json={'address': mac_address,
'node_uuid': node_uuid}),
json=self.fake_baremetal_port),
dict(
method='PUT',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid'],
'states', 'provision']),
validate=dict(json={'target': 'manage'})),
dict(
method='GET',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']]),
json=manageable_node),
dict(
method='GET',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']]),
json=manageable_node),
dict(
method='PUT',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid'],
'states', 'provision']),
validate=dict(json={'target': 'provide'})),
dict(
method='GET',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']]),
json=available_node),
dict(
method='GET',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']]),
json=available_node),
])
# NOTE(When we migrate to a newer microversion, this test
# may require revision. It was written for microversion
# ?1.13?, which accidently got reverted to 1.6 at one
# point during code being refactored soon after the
# change landed. Presently, with the lock at 1.6,
# this code is never used in the current code path.
return_value = self.op_cloud.register_machine(nics, **node_to_post)
self.assertDictEqual(available_node, return_value)
self.assert_calls()
def test_register_machine_enroll_wait(self):
mac_address = self.fake_baremetal_port
nics = [{'mac': mac_address}]
node_uuid = self.fake_baremetal_node['uuid']
node_to_post = {
'chassis_uuid': None,
'driver': None,
'driver_info': None,
'name': self.fake_baremetal_node['name'],
'properties': None,
'uuid': node_uuid}
self.fake_baremetal_node['provision_state'] = 'enroll'
manageable_node = self.fake_baremetal_node.copy()
manageable_node['provision_state'] = 'manageable'
available_node = self.fake_baremetal_node.copy()
available_node['provision_state'] = 'available'
self.register_uris([
dict(
method='POST',
uri=self.get_mock_url(
resource='nodes'),
validate=dict(json=node_to_post),
json=self.fake_baremetal_node),
dict(
method='POST',
uri=self.get_mock_url(
resource='ports'),
validate=dict(json={'address': mac_address,
'node_uuid': node_uuid}),
json=self.fake_baremetal_port),
dict(
method='GET',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']]),
json=self.fake_baremetal_node),
dict(
method='PUT',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid'],
'states', 'provision']),
validate=dict(json={'target': 'manage'})),
dict(
method='GET',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']]),
json=self.fake_baremetal_node),
dict(
method='GET',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']]),
json=manageable_node),
dict(
method='PUT',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid'],
'states', 'provision']),
validate=dict(json={'target': 'provide'})),
dict(
method='GET',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']]),
json=available_node),
dict(
method='GET',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']]),
json=available_node),
])
return_value = self.op_cloud.register_machine(nics, wait=True,
**node_to_post)
self.assertDictEqual(available_node, return_value)
self.assert_calls()
def test_register_machine_enroll_failure(self):
mac_address = '00:01:02:03:04:05'
nics = [{'mac': mac_address}]
node_uuid = self.fake_baremetal_node['uuid']
node_to_post = {
'chassis_uuid': None,
'driver': None,
'driver_info': None,
'name': self.fake_baremetal_node['name'],
'properties': None,
'uuid': node_uuid}
self.fake_baremetal_node['provision_state'] = 'enroll'
failed_node = self.fake_baremetal_node.copy()
failed_node['reservation'] = 'conductor0'
failed_node['provision_state'] = 'verifying'
failed_node['last_error'] = 'kaboom!'
self.register_uris([
dict(
method='POST',
uri=self.get_mock_url(
resource='nodes'),
json=self.fake_baremetal_node,
validate=dict(json=node_to_post)),
dict(
method='POST',
uri=self.get_mock_url(
resource='ports'),
validate=dict(json={'address': mac_address,
'node_uuid': node_uuid}),
json=self.fake_baremetal_port),
dict(
method='PUT',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid'],
'states', 'provision']),
validate=dict(json={'target': 'manage'})),
dict(
method='GET',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']]),
json=failed_node),
dict(
method='GET',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']]),
json=failed_node),
])
self.assertRaises(
exc.OpenStackCloudException,
self.op_cloud.register_machine,
nics,
**node_to_post)
self.assert_calls()
def test_register_machine_enroll_timeout(self):
mac_address = '00:01:02:03:04:05'
nics = [{'mac': mac_address}]
node_uuid = self.fake_baremetal_node['uuid']
node_to_post = {
'chassis_uuid': None,
'driver': None,
'driver_info': None,
'name': self.fake_baremetal_node['name'],
'properties': None,
'uuid': node_uuid}
self.fake_baremetal_node['provision_state'] = 'enroll'
busy_node = self.fake_baremetal_node.copy()
busy_node['reservation'] = 'conductor0'
busy_node['provision_state'] = 'verifying'
self.register_uris([
dict(
method='POST',
uri=self.get_mock_url(
resource='nodes'),
json=self.fake_baremetal_node,
validate=dict(json=node_to_post)),
dict(
method='POST',
uri=self.get_mock_url(
resource='ports'),
validate=dict(json={'address': mac_address,
'node_uuid': node_uuid}),
json=self.fake_baremetal_port),
dict(
method='PUT',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid'],
'states', 'provision']),
validate=dict(json={'target': 'manage'})),
dict(
method='GET',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']]),
json=self.fake_baremetal_node),
dict(
method='GET',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']]),
json=busy_node),
])
# NOTE(TheJulia): This test shortcircuits the timeout loop
# such that it executes only once. The very last returned
# state to the API is essentially a busy state that we
# want to block on until it has cleared.
self.assertRaises(
exc.OpenStackCloudException,
self.op_cloud.register_machine,
nics,
timeout=0.001,
lock_timeout=0.001,
**node_to_post)
self.assert_calls()
def test_register_machine_enroll_timeout_wait(self):
mac_address = '00:01:02:03:04:05'
nics = [{'mac': mac_address}]
node_uuid = self.fake_baremetal_node['uuid']
node_to_post = {
'chassis_uuid': None,
'driver': None,
'driver_info': None,
'name': self.fake_baremetal_node['name'],
'properties': None,
'uuid': node_uuid}
self.fake_baremetal_node['provision_state'] = 'enroll'
self.register_uris([
dict(
method='POST',
uri=self.get_mock_url(
resource='nodes'),
json=self.fake_baremetal_node,
validate=dict(json=node_to_post)),
dict(
method='POST',
uri=self.get_mock_url(
resource='ports'),
validate=dict(json={'address': mac_address,
'node_uuid': node_uuid}),
json=self.fake_baremetal_port),
dict(
method='GET',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']]),
json=self.fake_baremetal_node),
dict(
method='PUT',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid'],
'states', 'provision']),
validate=dict(json={'target': 'manage'})),
dict(
method='GET',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']]),
json=self.fake_baremetal_node),
])
self.assertRaises(
exc.OpenStackCloudException,
self.op_cloud.register_machine,
nics,
wait=True,
timeout=0.001,
**node_to_post)
self.assert_calls()
def test_register_machine_port_create_failed(self):
mac_address = '00:01:02:03:04:05'
nics = [{'mac': mac_address}]
node_uuid = self.fake_baremetal_node['uuid']
node_to_post = {
'chassis_uuid': None,
'driver': None,
'driver_info': None,
'name': self.fake_baremetal_node['name'],
'properties': None,
'uuid': node_uuid}
self.fake_baremetal_node['provision_state'] = 'available'
self.register_uris([
dict(
method='POST',
uri=self.get_mock_url(
resource='nodes'),
json=self.fake_baremetal_node,
validate=dict(json=node_to_post)),
dict(
method='POST',
uri=self.get_mock_url(
resource='ports'),
status_code=400,
json={'error': 'invalid'},
validate=dict(json={'address': mac_address,
'node_uuid': node_uuid})),
dict(
method='DELETE',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']])),
])
self.assertRaises(exc.OpenStackCloudException,
self.op_cloud.register_machine,
nics, **node_to_post)
self.assert_calls()
def test_unregister_machine(self):
mac_address = self.fake_baremetal_port['address']
nics = [{'mac': mac_address}]
port_uuid = self.fake_baremetal_port['uuid']
# NOTE(TheJulia): The two values below should be the same.
port_node_uuid = self.fake_baremetal_port['node_uuid']
port_url_address = 'detail?address=%s' % mac_address
self.fake_baremetal_node['provision_state'] = 'available'
self.register_uris([
dict(
method='GET',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']]),
json=self.fake_baremetal_node),
dict(
method='GET',
uri=self.get_mock_url(
resource='ports',
append=[port_url_address]),
json={'ports': [{'address': mac_address,
'node_uuid': port_node_uuid,
'uuid': port_uuid}]}),
dict(
method='DELETE',
uri=self.get_mock_url(
resource='ports',
append=[self.fake_baremetal_port['uuid']])),
dict(
method='DELETE',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']])),
])
self.op_cloud.unregister_machine(nics,
self.fake_baremetal_node['uuid'])
self.assert_calls()
def test_unregister_machine_timeout(self):
mac_address = self.fake_baremetal_port['address']
nics = [{'mac': mac_address}]
port_uuid = self.fake_baremetal_port['uuid']
port_node_uuid = self.fake_baremetal_port['node_uuid']
port_url_address = 'detail?address=%s' % mac_address
self.fake_baremetal_node['provision_state'] = 'available'
self.register_uris([
dict(
method='GET',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']]),
json=self.fake_baremetal_node),
dict(
method='GET',
uri=self.get_mock_url(
resource='ports',
append=[port_url_address]),
json={'ports': [{'address': mac_address,
'node_uuid': port_node_uuid,
'uuid': port_uuid}]}),
dict(
method='DELETE',
uri=self.get_mock_url(
resource='ports',
append=[self.fake_baremetal_port['uuid']])),
dict(
method='DELETE',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']])),
dict(
method='GET',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']]),
json=self.fake_baremetal_node),
])
self.assertRaises(
exc.OpenStackCloudException,
self.op_cloud.unregister_machine,
nics,
self.fake_baremetal_node['uuid'],
wait=True,
timeout=0.001)
self.assert_calls()
def test_unregister_machine_unavailable(self):
# This is a list of invalid states that the method
# should fail on.
invalid_states = ['active', 'cleaning', 'clean wait', 'clean failed']
mac_address = self.fake_baremetal_port['address']
nics = [{'mac': mac_address}]
url_list = []
for state in invalid_states:
self.fake_baremetal_node['provision_state'] = state
url_list.append(
dict(
method='GET',
uri=self.get_mock_url(
resource='nodes',
append=[self.fake_baremetal_node['uuid']]),
json=self.fake_baremetal_node))
self.register_uris(url_list)
for state in invalid_states:
self.assertRaises(
exc.OpenStackCloudException,
self.op_cloud.unregister_machine,
nics,
self.fake_baremetal_node['uuid'])
self.assert_calls()
def test_update_machine_patch_no_action(self):
self.register_uris([dict(
method='GET',

View File

@@ -374,8 +374,8 @@ class TestImage(BaseTestImage):
'X-Trans-Id': 'txbbb825960a3243b49a36f-005a0dadaedfw1',
'Content-Length': '1290170880',
'Last-Modified': 'Tue, 14 Apr 2015 18:29:01 GMT',
'X-Object-Meta-X-Shade-Sha256': fakes.NO_SHA256,
'X-Object-Meta-X-Shade-Md5': fakes.NO_MD5,
'X-Object-Meta-X-Sdk-Sha256': fakes.NO_SHA256,
'X-Object-Meta-X-Sdk-Md5': fakes.NO_MD5,
'Date': 'Thu, 16 Nov 2017 15:24:30 GMT',
'Accept-Ranges': 'bytes',
'Content-Type': 'application/octet-stream',

View File

@@ -0,0 +1,170 @@
# 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 mock
import munch
import testtools
import openstack
from openstack.cloud import exc
from openstack.cloud import meta
from openstack.config import cloud_config
from openstack.tests import fakes
from openstack.tests.unit import base
class TestOperatorCloud(base.RequestsMockTestCase):
def setUp(self):
super(TestOperatorCloud, self).setUp()
def test_operator_cloud(self):
self.assertIsInstance(self.op_cloud, openstack.OperatorCloud)
@mock.patch.object(openstack.OperatorCloud, 'ironic_client')
def test_list_nics(self, mock_client):
port1 = fakes.FakeMachinePort(1, "aa:bb:cc:dd", "node1")
port2 = fakes.FakeMachinePort(2, "dd:cc:bb:aa", "node2")
port_list = [port1, port2]
port_dict_list = meta.obj_list_to_munch(port_list)
mock_client.port.list.return_value = port_list
nics = self.op_cloud.list_nics()
self.assertTrue(mock_client.port.list.called)
self.assertEqual(port_dict_list, nics)
@mock.patch.object(openstack.OperatorCloud, 'ironic_client')
def test_list_nics_failure(self, mock_client):
mock_client.port.list.side_effect = Exception()
self.assertRaises(exc.OpenStackCloudException,
self.op_cloud.list_nics)
@mock.patch.object(openstack.OperatorCloud, 'ironic_client')
def test_list_nics_for_machine(self, mock_client):
mock_client.node.list_ports.return_value = []
self.op_cloud.list_nics_for_machine("123")
mock_client.node.list_ports.assert_called_with(node_id="123")
@mock.patch.object(openstack.OperatorCloud, 'ironic_client')
def test_list_nics_for_machine_failure(self, mock_client):
mock_client.node.list_ports.side_effect = Exception()
self.assertRaises(exc.OpenStackCloudException,
self.op_cloud.list_nics_for_machine, None)
@mock.patch.object(openstack.OpenStackCloud, '_image_client')
def test_get_image_name(self, mock_client):
fake_image = munch.Munch(
id='22',
name='22 name',
status='success')
mock_client.get.return_value = [fake_image]
self.assertEqual('22 name', self.op_cloud.get_image_name('22'))
self.assertEqual('22 name', self.op_cloud.get_image_name('22 name'))
@mock.patch.object(openstack.OpenStackCloud, '_image_client')
def test_get_image_id(self, mock_client):
fake_image = munch.Munch(
id='22',
name='22 name',
status='success')
mock_client.get.return_value = [fake_image]
self.assertEqual('22', self.op_cloud.get_image_id('22'))
self.assertEqual('22', self.op_cloud.get_image_id('22 name'))
@mock.patch.object(cloud_config.CloudConfig, 'get_endpoint')
def test_get_session_endpoint_provided(self, fake_get_endpoint):
fake_get_endpoint.return_value = 'http://fake.url'
self.assertEqual(
'http://fake.url', self.op_cloud.get_session_endpoint('image'))
@mock.patch.object(cloud_config.CloudConfig, 'get_session')
def test_get_session_endpoint_session(self, get_session_mock):
session_mock = mock.Mock()
session_mock.get_endpoint.return_value = 'http://fake.url'
get_session_mock.return_value = session_mock
self.assertEqual(
'http://fake.url', self.op_cloud.get_session_endpoint('image'))
@mock.patch.object(cloud_config.CloudConfig, 'get_session')
def test_get_session_endpoint_exception(self, get_session_mock):
class FakeException(Exception):
pass
def side_effect(*args, **kwargs):
raise FakeException("No service")
session_mock = mock.Mock()
session_mock.get_endpoint.side_effect = side_effect
get_session_mock.return_value = session_mock
self.op_cloud.name = 'testcloud'
self.op_cloud.region_name = 'testregion'
with testtools.ExpectedException(
exc.OpenStackCloudException,
"Error getting image endpoint on testcloud:testregion:"
" No service"):
self.op_cloud.get_session_endpoint("image")
@mock.patch.object(cloud_config.CloudConfig, 'get_session')
def test_get_session_endpoint_unavailable(self, get_session_mock):
session_mock = mock.Mock()
session_mock.get_endpoint.return_value = None
get_session_mock.return_value = session_mock
image_endpoint = self.op_cloud.get_session_endpoint("image")
self.assertIsNone(image_endpoint)
@mock.patch.object(cloud_config.CloudConfig, 'get_session')
def test_get_session_endpoint_identity(self, get_session_mock):
session_mock = mock.Mock()
get_session_mock.return_value = session_mock
self.op_cloud.get_session_endpoint('identity')
kwargs = dict(
interface='public', region_name='RegionOne',
service_name=None, service_type='identity')
session_mock.get_endpoint.assert_called_with(**kwargs)
@mock.patch.object(cloud_config.CloudConfig, 'get_session')
def test_has_service_no(self, get_session_mock):
session_mock = mock.Mock()
session_mock.get_endpoint.return_value = None
get_session_mock.return_value = session_mock
self.assertFalse(self.op_cloud.has_service("image"))
@mock.patch.object(cloud_config.CloudConfig, 'get_session')
def test_has_service_yes(self, get_session_mock):
session_mock = mock.Mock()
session_mock.get_endpoint.return_value = 'http://fake.url'
get_session_mock.return_value = session_mock
self.assertTrue(self.op_cloud.has_service("image"))
def test_list_hypervisors(self):
'''This test verifies that calling list_hypervisors results in a call
to nova client.'''
self.register_uris([
dict(method='GET',
uri=self.get_mock_url(
'compute', 'public', append=['os-hypervisors', 'detail']),
json={'hypervisors': [
fakes.make_fake_hypervisor('1', 'testserver1'),
fakes.make_fake_hypervisor('2', 'testserver2'),
]}),
])
r = self.op_cloud.list_hypervisors()
self.assertEqual(2, len(r))
self.assertEqual('testserver1', r[0]['hypervisor_hostname'])
self.assertEqual('testserver2', r[1]['hypervisor_hostname'])
self.assert_calls()