965 lines
36 KiB
Python
965 lines
36 KiB
Python
# 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.
|
|
|
|
from unittest import mock
|
|
|
|
from senlin.common import exception as exc
|
|
from senlin.profiles.os.nova import server
|
|
from senlin.tests.unit.common import base
|
|
from senlin.tests.unit.common import utils
|
|
|
|
spec = {
|
|
'type': 'os.nova.server',
|
|
'version': '1.0',
|
|
'properties': {
|
|
'context': {},
|
|
'auto_disk_config': True,
|
|
'availability_zone': 'FAKE_AZ',
|
|
'block_device_mapping': [{
|
|
'device_name': 'FAKE_NAME',
|
|
'volume_size': 1000,
|
|
}],
|
|
'flavor': 'FLAV',
|
|
'image': 'FAKE_IMAGE',
|
|
'key_name': 'FAKE_KEYNAME',
|
|
"metadata": {"meta var": "meta val"},
|
|
'name': 'FAKE_SERVER_NAME',
|
|
'networks': [{
|
|
'floating_ip': 'FAKE_FLOATING_IP',
|
|
'floating_network': 'FAKE_FLOATING_NET',
|
|
'security_groups': ['FAKE_SECURITY_GROUP'],
|
|
'port': 'FAKE_PORT',
|
|
'fixed_ip': 'FAKE_IP',
|
|
'network': 'FAKE_NET',
|
|
}],
|
|
'scheduler_hints': {
|
|
'same_host': 'HOST_ID',
|
|
},
|
|
}
|
|
}
|
|
|
|
|
|
class TestAvailabilityZoneValidation(base.SenlinTestCase):
|
|
|
|
scenarios = [
|
|
('validate:success', dict(
|
|
reason=None,
|
|
success=True,
|
|
validate_result=[['FAKE_AZ']],
|
|
result='FAKE_AZ',
|
|
exception=None,
|
|
message='')),
|
|
('validate:driver_failure', dict(
|
|
reason=None,
|
|
success=False,
|
|
validate_result=exc.InternalError(message='BANG.'),
|
|
result='FAKE_AZ',
|
|
exception=exc.InternalError,
|
|
message='BANG.')),
|
|
('validate:not_found', dict(
|
|
reason=None,
|
|
success=False,
|
|
validate_result=[[]],
|
|
result='FAKE_AZ',
|
|
exception=exc.InvalidSpec,
|
|
message=("The specified availability_zone 'FAKE_AZ' could "
|
|
"not be found"))),
|
|
('create:success', dict(
|
|
reason='create',
|
|
success=True,
|
|
validate_result=[['FAKE_AZ']],
|
|
result='FAKE_AZ',
|
|
exception=None,
|
|
message='')),
|
|
('create:driver_failure', dict(
|
|
reason='create',
|
|
success=False,
|
|
validate_result=exc.InternalError(message='BANG'),
|
|
result='FAKE_AZ',
|
|
exception=exc.EResourceCreation,
|
|
message='Failed in creating server: BANG.')),
|
|
('create:not_found', dict(
|
|
reason='create',
|
|
success=False,
|
|
validate_result=[[]],
|
|
result='FAKE_AZ',
|
|
exception=exc.EResourceCreation,
|
|
message=("Failed in creating server: The specified "
|
|
"availability_zone 'FAKE_AZ' could not be found.")))
|
|
]
|
|
|
|
def setUp(self):
|
|
super(TestAvailabilityZoneValidation, self).setUp()
|
|
|
|
self.cc = mock.Mock()
|
|
prof = server.ServerProfile('t', spec)
|
|
prof._computeclient = self.cc
|
|
self.profile = prof
|
|
|
|
def test_validation(self):
|
|
self.cc.validate_azs.side_effect = self.validate_result
|
|
node = mock.Mock(id='NODE_ID')
|
|
|
|
if self.success:
|
|
res = self.profile._validate_az(node, 'FAKE_AZ', self.reason)
|
|
self.assertEqual(self.result, res)
|
|
else:
|
|
ex = self.assertRaises(self.exception,
|
|
self.profile._validate_az,
|
|
node, 'FAKE_AZ', self.reason)
|
|
self.assertEqual(self.message, str(ex))
|
|
|
|
self.cc.validate_azs.assert_called_once_with(['FAKE_AZ'])
|
|
|
|
|
|
class TestFlavorValidation(base.SenlinTestCase):
|
|
|
|
scenarios = [
|
|
('validate:success', dict(
|
|
reason=None,
|
|
success=True,
|
|
validate_result=[mock.Mock(id='FID', is_disabled=False)],
|
|
result='FID',
|
|
exception=None,
|
|
message='')),
|
|
('validate:driver_failure', dict(
|
|
reason=None,
|
|
success=False,
|
|
validate_result=exc.InternalError(message='BANG.'),
|
|
result='FID',
|
|
exception=exc.InternalError,
|
|
message='BANG.')),
|
|
('validate:not_found', dict(
|
|
reason=None,
|
|
success=False,
|
|
validate_result=exc.InternalError(code=404, message='BANG.'),
|
|
result='FID',
|
|
exception=exc.InvalidSpec,
|
|
message="The specified flavor 'FLAVOR' could not be found.")),
|
|
('validate:disabled', dict(
|
|
reason=None,
|
|
success=False,
|
|
validate_result=[mock.Mock(id='FID', is_disabled=True)],
|
|
result='FID',
|
|
exception=exc.InvalidSpec,
|
|
message="The specified flavor 'FLAVOR' is disabled")),
|
|
('create:success', dict(
|
|
reason='create',
|
|
success=True,
|
|
validate_result=[mock.Mock(id='FID', is_disabled=False)],
|
|
result='FID',
|
|
exception=None,
|
|
message='')),
|
|
('create:driver_failure', dict(
|
|
reason='create',
|
|
success=False,
|
|
validate_result=exc.InternalError(message='BANG'),
|
|
result='FID',
|
|
exception=exc.EResourceCreation,
|
|
message='Failed in creating server: BANG.')),
|
|
('create:not_found', dict(
|
|
reason='create',
|
|
success=False,
|
|
validate_result=exc.InternalError(code=404, message='BANG'),
|
|
result='FID',
|
|
exception=exc.EResourceCreation,
|
|
message="Failed in creating server: BANG.")),
|
|
('create:disabled', dict(
|
|
reason='create',
|
|
success=False,
|
|
validate_result=[mock.Mock(id='FID', is_disabled=True)],
|
|
result='FID',
|
|
exception=exc.EResourceCreation,
|
|
message=("Failed in creating server: The specified flavor "
|
|
"'FLAVOR' is disabled."))),
|
|
('update:success', dict(
|
|
reason='update',
|
|
success=True,
|
|
validate_result=[mock.Mock(id='FID', is_disabled=False)],
|
|
result='FID',
|
|
exception=None,
|
|
message='')),
|
|
('update:driver_failure', dict(
|
|
reason='update',
|
|
success=False,
|
|
validate_result=exc.InternalError(message='BANG'),
|
|
result='FID',
|
|
exception=exc.EResourceUpdate,
|
|
message="Failed in updating server 'NOVA_ID': BANG.")),
|
|
('update:not_found', dict(
|
|
reason='update',
|
|
success=False,
|
|
validate_result=exc.InternalError(code=404, message='BANG'),
|
|
result='FID',
|
|
exception=exc.EResourceUpdate,
|
|
message="Failed in updating server 'NOVA_ID': BANG.")),
|
|
('update:disabled', dict(
|
|
reason='update',
|
|
success=False,
|
|
validate_result=[mock.Mock(id='FID', is_disabled=True)],
|
|
result='FID',
|
|
exception=exc.EResourceUpdate,
|
|
message=("Failed in updating server 'NOVA_ID': The specified "
|
|
"flavor 'FLAVOR' is disabled.")))
|
|
]
|
|
|
|
def setUp(self):
|
|
super(TestFlavorValidation, self).setUp()
|
|
|
|
self.cc = mock.Mock()
|
|
self.profile = server.ServerProfile('t', spec)
|
|
self.profile._computeclient = self.cc
|
|
|
|
def test_validation(self):
|
|
self.cc.flavor_find.side_effect = self.validate_result
|
|
node = mock.Mock(id='NODE_ID', physical_id='NOVA_ID')
|
|
flavor = 'FLAVOR'
|
|
|
|
if self.success:
|
|
res = self.profile._validate_flavor(node, flavor, self.reason)
|
|
self.assertIsNotNone(res)
|
|
self.assertEqual(self.result, res.id)
|
|
else:
|
|
ex = self.assertRaises(self.exception,
|
|
self.profile._validate_flavor,
|
|
node, flavor, self.reason)
|
|
self.assertEqual(self.message, str(ex))
|
|
|
|
self.cc.flavor_find.assert_called_once_with(flavor, False)
|
|
|
|
|
|
class TestImageValidation(base.SenlinTestCase):
|
|
|
|
scenarios = [
|
|
('validate:success', dict(
|
|
reason=None,
|
|
success=True,
|
|
validate_result=[mock.Mock(id='IMAGE_ID')],
|
|
result='IMAGE_ID',
|
|
exception=None,
|
|
message='')),
|
|
('validate:driver_failure', dict(
|
|
reason=None,
|
|
success=False,
|
|
validate_result=exc.InternalError(message='BANG.'),
|
|
result='FID',
|
|
exception=exc.InternalError,
|
|
message='BANG.')),
|
|
('validate:not_found', dict(
|
|
reason=None,
|
|
success=False,
|
|
validate_result=exc.InternalError(code=404, message='BANG.'),
|
|
result='FID',
|
|
exception=exc.InvalidSpec,
|
|
message="The specified image 'IMAGE' could not be found.")),
|
|
('create:success', dict(
|
|
reason='create',
|
|
success=True,
|
|
validate_result=[mock.Mock(id='IMAGE_ID')],
|
|
result='IMAGE_ID',
|
|
exception=None,
|
|
message='')),
|
|
('create:driver_failure', dict(
|
|
reason='create',
|
|
success=False,
|
|
validate_result=exc.InternalError(message='BANG'),
|
|
result='FID',
|
|
exception=exc.EResourceCreation,
|
|
message='Failed in creating server: BANG.')),
|
|
('create:not_found', dict(
|
|
reason='create',
|
|
success=False,
|
|
validate_result=exc.InternalError(code=404, message='BANG'),
|
|
result='FID',
|
|
exception=exc.EResourceCreation,
|
|
message="Failed in creating server: BANG.")),
|
|
('update:success', dict(
|
|
reason='update',
|
|
success=True,
|
|
validate_result=[mock.Mock(id='IMAGE_ID')],
|
|
result='IMAGE_ID',
|
|
exception=None,
|
|
message='')),
|
|
('update:driver_failure', dict(
|
|
reason='update',
|
|
success=False,
|
|
validate_result=exc.InternalError(message='BANG'),
|
|
result='FID',
|
|
exception=exc.EResourceUpdate,
|
|
message="Failed in updating server 'NOVA_ID': BANG.")),
|
|
('update:not_found', dict(
|
|
reason='update',
|
|
success=False,
|
|
validate_result=exc.InternalError(code=404, message='BANG'),
|
|
result='FID',
|
|
exception=exc.EResourceUpdate,
|
|
message="Failed in updating server 'NOVA_ID': BANG.")),
|
|
]
|
|
|
|
def setUp(self):
|
|
super(TestImageValidation, self).setUp()
|
|
|
|
self.cc = mock.Mock()
|
|
self.gc = mock.Mock()
|
|
self.profile = server.ServerProfile('t', spec)
|
|
self.profile._computeclient = self.cc
|
|
self.profile._glanceclient = self.gc
|
|
|
|
def test_validation(self):
|
|
self.gc.image_find.side_effect = self.validate_result
|
|
node = mock.Mock(id='NODE_ID', physical_id='NOVA_ID')
|
|
image = 'IMAGE'
|
|
|
|
if self.success:
|
|
res = self.profile._validate_image(node, image, self.reason)
|
|
self.assertIsNotNone(res)
|
|
self.assertEqual(self.result, res.id)
|
|
else:
|
|
ex = self.assertRaises(self.exception,
|
|
self.profile._validate_image,
|
|
node, image, self.reason)
|
|
self.assertEqual(self.message, str(ex))
|
|
|
|
self.gc.image_find.assert_called_once_with(image, False)
|
|
|
|
|
|
class TestVolumeValidation(base.SenlinTestCase):
|
|
|
|
scenarios = [
|
|
('validate:success', dict(
|
|
reason=None,
|
|
success=True,
|
|
validate_result=[mock.Mock(id='VOLUME_ID', status='available')],
|
|
result='VOLUME_ID',
|
|
exception=None,
|
|
message='')),
|
|
('validate:failure', dict(
|
|
reason=None,
|
|
success=False,
|
|
validate_result=[mock.Mock(id='VOLUME_ID', status='in-use')],
|
|
result='VOLUME_ID',
|
|
exception=exc.InvalidSpec,
|
|
message="The volume VOLUME should be in 'available' "
|
|
"status but is in 'in-use' status.")),
|
|
('validate:driver_failure', dict(
|
|
reason=None,
|
|
success=False,
|
|
validate_result=exc.InternalError(message='BANG.'),
|
|
result='FID',
|
|
exception=exc.InternalError,
|
|
message='BANG.')),
|
|
('validate:not_found', dict(
|
|
reason=None,
|
|
success=False,
|
|
validate_result=exc.InternalError(code=404, message='BANG.'),
|
|
result='FID',
|
|
exception=exc.InvalidSpec,
|
|
message="The specified volume 'VOLUME' could not be found.")),
|
|
('create:success', dict(
|
|
reason='create',
|
|
success=True,
|
|
validate_result=[mock.Mock(id='VOLUME_ID', status='available')],
|
|
result='VOLUME_ID',
|
|
exception=None,
|
|
message='')),
|
|
('create:driver_failure', dict(
|
|
reason='create',
|
|
success=False,
|
|
validate_result=exc.InternalError(message='BANG'),
|
|
result='FID',
|
|
exception=exc.EResourceCreation,
|
|
message='Failed in creating server: BANG.')),
|
|
('create:not_found', dict(
|
|
reason='create',
|
|
success=False,
|
|
validate_result=exc.InternalError(code=404, message='BANG'),
|
|
result='FID',
|
|
exception=exc.EResourceCreation,
|
|
message="Failed in creating server: BANG.")),
|
|
]
|
|
|
|
def setUp(self):
|
|
super(TestVolumeValidation, self).setUp()
|
|
bdm_v2 = [
|
|
{
|
|
'volume_size': 1,
|
|
'uuid': '6ce0be68',
|
|
'source_type': 'volume',
|
|
'destination_type': 'volume',
|
|
'boot_index': 0,
|
|
},
|
|
]
|
|
|
|
volume_spec = {
|
|
'type': 'os.nova.server',
|
|
'version': '1.0',
|
|
'properties': {
|
|
'flavor': 'FLAV',
|
|
'name': 'FAKE_SERVER_NAME',
|
|
'security_groups': ['HIGH_SECURITY_GROUP'],
|
|
'block_device_mapping_v2': bdm_v2,
|
|
}
|
|
}
|
|
|
|
self.vc = mock.Mock()
|
|
self.profile = server.ServerProfile('t', volume_spec)
|
|
self.profile._block_storageclient = self.vc
|
|
|
|
def test_validation(self):
|
|
self.vc.volume_get.side_effect = self.validate_result
|
|
node = mock.Mock(id='NODE_ID', physical_id='NOVA_ID')
|
|
volume = 'VOLUME'
|
|
|
|
if self.success:
|
|
res = self.profile._validate_volume(node, volume, self.reason)
|
|
self.assertIsNotNone(res)
|
|
self.assertEqual(self.result, res.id)
|
|
else:
|
|
ex = self.assertRaises(self.exception,
|
|
self.profile._validate_volume,
|
|
node, volume, self.reason)
|
|
self.assertEqual(self.message, str(ex))
|
|
|
|
self.vc.volume_get.assert_called_once_with(volume)
|
|
|
|
|
|
class TestKeypairValidation(base.SenlinTestCase):
|
|
|
|
scenarios = [
|
|
('validate:success', dict(
|
|
reason=None,
|
|
success=True,
|
|
validate_result=[mock.Mock(id='KEY_ID')],
|
|
result='KEY_ID',
|
|
exception=None,
|
|
message='')),
|
|
('validate:driver_failure', dict(
|
|
reason=None,
|
|
success=False,
|
|
validate_result=exc.InternalError(message='BANG.'),
|
|
result='FID',
|
|
exception=exc.InternalError,
|
|
message='BANG.')),
|
|
('validate:not_found', dict(
|
|
reason=None,
|
|
success=False,
|
|
validate_result=exc.InternalError(code=404, message='BANG.'),
|
|
result='FID',
|
|
exception=exc.InvalidSpec,
|
|
message="The specified key_name 'KEY' could not be found.")),
|
|
('create:success', dict(
|
|
reason='create',
|
|
success=True,
|
|
validate_result=[mock.Mock(id='IMAGE_ID')],
|
|
result='IMAGE_ID',
|
|
exception=None,
|
|
message='')),
|
|
('create:driver_failure', dict(
|
|
reason='create',
|
|
success=False,
|
|
validate_result=exc.InternalError(message='BANG'),
|
|
result='FID',
|
|
exception=exc.EResourceCreation,
|
|
message='Failed in creating server: BANG.')),
|
|
('create:not_found', dict(
|
|
reason='create',
|
|
success=False,
|
|
validate_result=exc.InternalError(code=404, message='BANG'),
|
|
result='FID',
|
|
exception=exc.EResourceCreation,
|
|
message="Failed in creating server: BANG.")),
|
|
('update:success', dict(
|
|
reason='update',
|
|
success=True,
|
|
validate_result=[mock.Mock(id='KEY_ID')],
|
|
result='KEY_ID',
|
|
exception=None,
|
|
message='')),
|
|
('update:driver_failure', dict(
|
|
reason='update',
|
|
success=False,
|
|
validate_result=exc.InternalError(message='BANG'),
|
|
result='FID',
|
|
exception=exc.EResourceUpdate,
|
|
message="Failed in updating server 'NOVA_ID': BANG.")),
|
|
('update:not_found', dict(
|
|
reason='update',
|
|
success=False,
|
|
validate_result=exc.InternalError(code=404, message='BANG'),
|
|
result='FID',
|
|
exception=exc.EResourceUpdate,
|
|
message="Failed in updating server 'NOVA_ID': BANG.")),
|
|
]
|
|
|
|
def setUp(self):
|
|
super(TestKeypairValidation, self).setUp()
|
|
|
|
self.cc = mock.Mock()
|
|
self.profile = server.ServerProfile('t', spec)
|
|
self.profile._computeclient = self.cc
|
|
|
|
def test_validation(self):
|
|
self.cc.keypair_find.side_effect = self.validate_result
|
|
node = mock.Mock(id='NODE_ID', physical_id='NOVA_ID')
|
|
key = 'KEY'
|
|
|
|
if self.success:
|
|
res = self.profile._validate_keypair(node, key, self.reason)
|
|
self.assertIsNotNone(res)
|
|
self.assertEqual(self.result, res.id)
|
|
else:
|
|
ex = self.assertRaises(self.exception,
|
|
self.profile._validate_keypair,
|
|
node, key, self.reason)
|
|
self.assertEqual(self.message, str(ex))
|
|
|
|
self.cc.keypair_find.assert_called_once_with(key, False)
|
|
|
|
|
|
class TestNetworkValidation(base.SenlinTestCase):
|
|
|
|
scenarios = [
|
|
('validate:net-n:port-n:fixed_ip-n:sgroups-n', dict(
|
|
reason=None,
|
|
success=True,
|
|
inputs={'port': 'PORT'},
|
|
net_result=[],
|
|
port_result=[mock.Mock(id='PORT_ID', status='DOWN')],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={'port': 'PORT_ID'},
|
|
exception=None,
|
|
message='')),
|
|
('validate:net-y:port-n:fixed_ip-n:sgroups-y', dict(
|
|
reason=None,
|
|
success=True,
|
|
inputs={'network': 'NET', 'security_groups': ['default']},
|
|
net_result=[mock.Mock(id='NET_ID')],
|
|
port_result=[],
|
|
sg_result=[mock.Mock(id='SG_ID')],
|
|
floating_result=[],
|
|
result={'network': 'NET_ID', 'security_groups': ['SG_ID']},
|
|
exception=None,
|
|
message='')),
|
|
('validate:net-y:port-n:fixed_ip-n:sgroups-n:floating_net-y', dict(
|
|
reason=None,
|
|
success=True,
|
|
inputs={'network': 'NET', 'floating_network': 'NET'},
|
|
net_result=[mock.Mock(id='NET_ID'), mock.Mock(id='NET_ID')],
|
|
port_result=[],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={'network': 'NET_ID', 'floating_network': 'NET_ID'},
|
|
exception=None,
|
|
message='')),
|
|
('validate:net-y:port-n:fixed_ip-n:floating_net-y:floating_ip-y', dict(
|
|
reason=None,
|
|
success=True,
|
|
inputs={'network': 'NET', 'floating_network': 'NET',
|
|
'floating_ip': 'FLOATINGIP'},
|
|
net_result=[mock.Mock(id='NET_ID'), mock.Mock(id='NET_ID')],
|
|
port_result=[],
|
|
sg_result=[],
|
|
floating_result=[mock.Mock(id='FLOATINGIP_ID', status='INACTIVE')],
|
|
result={'network': 'NET_ID', 'floating_network': 'NET_ID',
|
|
'floating_ip_id': 'FLOATINGIP_ID',
|
|
'floating_ip': 'FLOATINGIP'},
|
|
exception=None,
|
|
message='')),
|
|
('validate:net-y:port-n:fixed_ip-y:sgroups-n', dict(
|
|
reason=None,
|
|
success=True,
|
|
inputs={'network': 'NET', 'fixed_ip': 'FIXED_IP'},
|
|
net_result=[mock.Mock(id='NET_ID')],
|
|
port_result=[],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={'network': 'NET_ID', 'fixed_ip': 'FIXED_IP'},
|
|
exception=None,
|
|
message='')),
|
|
('validate:net-f:port-y:fixed_ip-n:sgroups-n', dict(
|
|
reason=None,
|
|
success=False,
|
|
inputs={'network': 'NET', 'port': 'PORT'},
|
|
net_result=[exc.InternalError(message='NET Failure')],
|
|
port_result=[],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={},
|
|
exception=exc.InvalidSpec,
|
|
message='NET Failure')),
|
|
('validate:net-n:port-f:fixed_ip-n', dict(
|
|
reason=None,
|
|
success=False,
|
|
inputs={'port': 'PORT'},
|
|
net_result=[],
|
|
port_result=[exc.InternalError(message='PORT Failure')],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={},
|
|
exception=exc.InvalidSpec,
|
|
message='PORT Failure')),
|
|
('validate:net-n:port-active:fixed_ip-n', dict(
|
|
reason=None,
|
|
success=False,
|
|
inputs={'port': 'PORT'},
|
|
net_result=[],
|
|
port_result=[mock.Mock(id='PORT_ID', status='ACTIVE')],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={},
|
|
exception=exc.InvalidSpec,
|
|
message='The status of the port PORT must be DOWN')),
|
|
('validate:net-n:port-y:fixed_ip-n:floating_net-n:floating_ip-y', dict(
|
|
reason=None,
|
|
success=False,
|
|
inputs={'port': 'PORT', 'floating_ip': 'FLOATINGIP'},
|
|
net_result=[],
|
|
port_result=[mock.Mock(id='PORT_ID', status='DOWN')],
|
|
sg_result=[],
|
|
floating_result=[mock.Mock(id='FLOATINGIP_ID', status='INACTIVE')],
|
|
result={},
|
|
exception=exc.InvalidSpec,
|
|
message='Must specify a network to create floating IP')),
|
|
('validate:net-n:port-y:fixed_ip-n:floating_ip-active', dict(
|
|
reason=None,
|
|
success=False,
|
|
inputs={'port': 'PORT', 'floating_network': 'NET',
|
|
'floating_ip': 'FLOATINGIP'},
|
|
net_result=[mock.Mock(id='NET_ID')],
|
|
port_result=[mock.Mock(id='PORT_ID', status='DOWN')],
|
|
sg_result=[],
|
|
floating_result=[mock.Mock(id='FLOATINGIP_ID', status='ACTIVE')],
|
|
result={},
|
|
exception=exc.InvalidSpec,
|
|
message='the floating IP FLOATINGIP has been used.')),
|
|
('validate:net-n:port-n:fixed_ip-n', dict(
|
|
reason=None,
|
|
success=False,
|
|
inputs={'fixed_ip': 'FIXED_IP'},
|
|
net_result=[],
|
|
port_result=[],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={},
|
|
exception=exc.InvalidSpec,
|
|
message="One of 'port' and 'network' must be provided")),
|
|
('validate:net-n:port-y:fixed_ip-y', dict(
|
|
reason=None,
|
|
success=False,
|
|
inputs={'port': 'PORT', 'fixed_ip': 'FIXED_IP'},
|
|
net_result=[],
|
|
port_result=[mock.Mock(id='PORT_ID', status='DOWN')],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={},
|
|
exception=exc.InvalidSpec,
|
|
message=("The 'port' property and the 'fixed_ip' property cannot "
|
|
"be specified at the same time"))),
|
|
('create:net-y:port-y:fixed_ip-n', dict(
|
|
reason='create',
|
|
success=True,
|
|
inputs={'network': 'NET', 'port': 'PORT'},
|
|
net_result=[mock.Mock(id='NET_ID')],
|
|
port_result=[mock.Mock(id='PORT_ID', status='DOWN')],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={'network': 'NET_ID', 'port': 'PORT_ID'},
|
|
exception=None,
|
|
message='')),
|
|
('create:net-y:port-n:fixed_ip-y', dict(
|
|
reason='create',
|
|
success=True,
|
|
inputs={'network': 'NET', 'fixed_ip': 'FIXED_IP'},
|
|
net_result=[mock.Mock(id='NET_ID')],
|
|
port_result=[],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={'network': 'NET_ID', 'fixed_ip': 'FIXED_IP'},
|
|
exception=None,
|
|
message='')),
|
|
('create:net-y:port-n:fixed_ip-n:sgroups-y', dict(
|
|
reason='create',
|
|
success=True,
|
|
inputs={'network': 'NET', 'security_groups': ['default']},
|
|
net_result=[mock.Mock(id='NET_ID')],
|
|
port_result=[],
|
|
sg_result=[mock.Mock(id='SG_ID')],
|
|
floating_result=[],
|
|
result={'network': 'NET_ID', 'security_groups': ['SG_ID']},
|
|
exception=None,
|
|
message='')),
|
|
('create:net-y:port-n:fixed_ip-n:sgroups-n:floating_net-y', dict(
|
|
reason=None,
|
|
success=True,
|
|
inputs={'network': 'NET', 'floating_network': 'NET'},
|
|
net_result=[mock.Mock(id='NET_ID'), mock.Mock(id='NET_ID')],
|
|
port_result=[],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={'network': 'NET_ID', 'floating_network': 'NET_ID'},
|
|
exception=None,
|
|
message='')),
|
|
('create:net-f:port-y:fixed_ip-n', dict(
|
|
reason='create',
|
|
success=False,
|
|
inputs={'network': 'NET', 'port': 'PORT'},
|
|
net_result=[exc.InternalError(message='NET Failure')],
|
|
port_result=[],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={},
|
|
exception=exc.EResourceCreation,
|
|
message='Failed in creating server: NET Failure.')),
|
|
('create:net-n:port-f:fixed_ip-n', dict(
|
|
reason='create',
|
|
success=False,
|
|
inputs={'port': 'PORT'},
|
|
net_result=[],
|
|
port_result=[exc.InternalError(message='PORT Failure')],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={},
|
|
exception=exc.EResourceCreation,
|
|
message='Failed in creating server: PORT Failure.')),
|
|
('create:net-n:port-active:fixed_ip-n', dict(
|
|
reason='create',
|
|
success=False,
|
|
inputs={'port': 'PORT'},
|
|
net_result=[],
|
|
port_result=[mock.Mock(id='PORT_ID', status='ACTIVE')],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={},
|
|
exception=exc.EResourceCreation,
|
|
message=('Failed in creating server: The status of the port PORT '
|
|
'must be DOWN.'))),
|
|
('create:net-n:port-n:fixed_ip-n', dict(
|
|
reason='create',
|
|
success=False,
|
|
inputs={'fixed_ip': 'FIXED_IP'},
|
|
net_result=[],
|
|
port_result=[],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={},
|
|
exception=exc.EResourceCreation,
|
|
message=("Failed in creating server: One of 'port' "
|
|
"and 'network' must be provided."))),
|
|
('create:net-n:port-y:fixed_ip-y', dict(
|
|
reason='create',
|
|
success=False,
|
|
inputs={'port': 'PORT', 'fixed_ip': 'FIXED_IP'},
|
|
net_result=[],
|
|
port_result=[mock.Mock(id='PORT_ID', status='DOWN')],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={},
|
|
exception=exc.EResourceCreation,
|
|
message=("Failed in creating server: The 'port' property and the "
|
|
"'fixed_ip' property cannot be specified at the same "
|
|
"time."))),
|
|
('update:net-y:port-y:fixed_ip-n', dict(
|
|
reason='update',
|
|
success=True,
|
|
inputs={'network': 'NET', 'port': 'PORT'},
|
|
net_result=[mock.Mock(id='NET_ID')],
|
|
port_result=[mock.Mock(id='PORT_ID', status='DOWN')],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={'network': 'NET_ID', 'port': 'PORT_ID'},
|
|
exception=None,
|
|
message='')),
|
|
('update:net-y:port-n:fixed_ip-y', dict(
|
|
reason='update',
|
|
success=True,
|
|
inputs={'network': 'NET', 'fixed_ip': 'FIXED_IP'},
|
|
net_result=[mock.Mock(id='NET_ID')],
|
|
port_result=[],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={'network': 'NET_ID',
|
|
'fixed_ip': 'FIXED_IP'},
|
|
exception=None,
|
|
message='')),
|
|
('update:net-y:port-n:fixed_ip-n:sgroups-y', dict(
|
|
reason='create',
|
|
success=True,
|
|
inputs={'network': 'NET', 'security_groups': ['default']},
|
|
net_result=[mock.Mock(id='NET_ID')],
|
|
port_result=[],
|
|
sg_result=[mock.Mock(id='SG_ID')],
|
|
floating_result=[],
|
|
result={'network': 'NET_ID', 'security_groups': ['SG_ID']},
|
|
exception=None,
|
|
message='')),
|
|
('update:net-y:port-n:fixed_ip-n:sgroups-n:floating_net-y', dict(
|
|
reason=None,
|
|
success=True,
|
|
inputs={'network': 'NET', 'floating_network': 'NET'},
|
|
net_result=[mock.Mock(id='NET_ID'), mock.Mock(id='NET_ID')],
|
|
port_result=[],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={'network': 'NET_ID', 'floating_network': 'NET_ID'},
|
|
exception=None,
|
|
message='')),
|
|
('update:net-f:port-y:fixed_ip-n', dict(
|
|
reason='update',
|
|
success=False,
|
|
inputs={'network': 'NET', 'port': 'PORT'},
|
|
net_result=[exc.InternalError(message='NET Failure')],
|
|
port_result=[],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={},
|
|
exception=exc.EResourceUpdate,
|
|
message="Failed in updating server 'NOVA_ID': NET Failure.")),
|
|
('update:net-n:port-f:fixed_ip-n', dict(
|
|
reason='update',
|
|
success=False,
|
|
inputs={'port': 'PORT'},
|
|
net_result=[],
|
|
port_result=[exc.InternalError(message='PORT Failure')],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={},
|
|
exception=exc.EResourceUpdate,
|
|
message="Failed in updating server 'NOVA_ID': PORT Failure.")),
|
|
('update:net-n:port-active:fixed_ip-n', dict(
|
|
reason='update',
|
|
success=False,
|
|
inputs={'port': 'PORT'},
|
|
net_result=[],
|
|
port_result=[mock.Mock(id='PORT_ID', status='ACTIVE')],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={},
|
|
exception=exc.EResourceUpdate,
|
|
message=("Failed in updating server 'NOVA_ID': The status of the "
|
|
"port PORT must be DOWN."))),
|
|
('update:net-n:port-n:fixed_ip-n', dict(
|
|
reason='update',
|
|
success=False,
|
|
inputs={'fixed_ip': 'FIXED_IP'},
|
|
net_result=[],
|
|
port_result=[],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={},
|
|
exception=exc.EResourceUpdate,
|
|
message=("Failed in updating server 'NOVA_ID': One of 'port' "
|
|
"and 'network' must be provided."))),
|
|
('update:net-n:port-y:fixed_ip-y', dict(
|
|
reason='update',
|
|
success=False,
|
|
inputs={'port': 'PORT', 'fixed_ip': 'FIXED_IP'},
|
|
net_result=[],
|
|
port_result=[mock.Mock(id='PORT_ID', status='DOWN')],
|
|
sg_result=[],
|
|
floating_result=[],
|
|
result={},
|
|
exception=exc.EResourceUpdate,
|
|
message=("Failed in updating server 'NOVA_ID': The 'port' "
|
|
"property and the 'fixed_ip' property cannot be "
|
|
"specified at the same time."))),
|
|
]
|
|
|
|
def setUp(self):
|
|
super(TestNetworkValidation, self).setUp()
|
|
|
|
self.nc = mock.Mock()
|
|
self.profile = server.ServerProfile('t', spec)
|
|
self.profile._networkclient = self.nc
|
|
|
|
def test_validation(self):
|
|
self.nc.network_get.side_effect = self.net_result
|
|
self.nc.port_find.side_effect = self.port_result
|
|
self.nc.security_group_find.side_effect = self.sg_result
|
|
self.nc.floatingip_find.side_effect = self.floating_result
|
|
obj = mock.Mock(physical_id='NOVA_ID')
|
|
|
|
if self.success:
|
|
res = self.profile._validate_network(obj, self.inputs, self.reason)
|
|
self.assertEqual(self.result, res)
|
|
else:
|
|
ex = self.assertRaises(self.exception,
|
|
self.profile._validate_network,
|
|
obj, self.inputs, self.reason)
|
|
self.assertEqual(self.message, str(ex))
|
|
|
|
if self.net_result:
|
|
self.nc.network_get.assert_called_with('NET')
|
|
if self.port_result:
|
|
self.nc.port_find.assert_called_once_with('PORT')
|
|
if self.sg_result:
|
|
self.nc.security_group_find.assert_called_once_with(
|
|
'default', project_id=None)
|
|
if self.floating_result:
|
|
self.nc.floatingip_find.assert_called_once_with('FLOATINGIP')
|
|
|
|
def test_validation_with_project_scope(self):
|
|
self.nc.network_get.side_effect = self.net_result
|
|
self.nc.port_find.side_effect = self.port_result
|
|
self.nc.security_group_find.side_effect = self.sg_result
|
|
self.nc.floatingip_find.side_effect = self.floating_result
|
|
obj = mock.Mock(physical_id='NOVA_ID')
|
|
|
|
self.profile.project_scope = True
|
|
self.profile.project = 'FAKE_PROJECT_ID'
|
|
|
|
if self.success:
|
|
res = self.profile._validate_network(obj, self.inputs, self.reason)
|
|
self.assertEqual(self.result, res)
|
|
else:
|
|
ex = self.assertRaises(self.exception,
|
|
self.profile._validate_network,
|
|
obj, self.inputs, self.reason)
|
|
self.assertEqual(self.message, str(ex))
|
|
|
|
if self.net_result:
|
|
self.nc.network_get.assert_called_with('NET')
|
|
if self.port_result:
|
|
self.nc.port_find.assert_called_once_with('PORT')
|
|
if self.sg_result:
|
|
self.nc.security_group_find.assert_called_once_with(
|
|
'default', project_id='FAKE_PROJECT_ID')
|
|
if self.floating_result:
|
|
self.nc.floatingip_find.assert_called_once_with('FLOATINGIP')
|
|
|
|
|
|
class TestNovaServerValidate(base.SenlinTestCase):
|
|
|
|
def setUp(self):
|
|
super(TestNovaServerValidate, self).setUp()
|
|
|
|
self.context = utils.dummy_context()
|
|
|
|
def test_do_validate_all_passed(self):
|
|
profile = server.ServerProfile('t', spec)
|
|
mock_az = self.patchobject(profile, '_validate_az')
|
|
mock_flavor = self.patchobject(profile, '_validate_flavor')
|
|
mock_image = self.patchobject(profile, '_validate_image')
|
|
mock_keypair = self.patchobject(profile, '_validate_keypair')
|
|
mock_network = self.patchobject(profile, '_validate_network')
|
|
obj = mock.Mock()
|
|
|
|
res = profile.do_validate(obj)
|
|
|
|
properties = spec['properties']
|
|
self.assertTrue(res)
|
|
mock_az.assert_called_once_with(obj, properties['availability_zone'])
|
|
mock_flavor.assert_called_once_with(obj, properties['flavor'])
|
|
mock_image.assert_called_once_with(obj, properties['image'])
|
|
mock_keypair.assert_called_once_with(obj, properties['key_name'])
|
|
mock_network.assert_called_once_with(obj, properties['networks'][0])
|