Add check for specified image in create request

We should make sure the image exists before sending it to
Ironic.

Change-Id: I8ff6aec53186c3ecbb9b7bd06e3bcd3fe35ef913
This commit is contained in:
Zhenguo Niu 2016-11-23 16:27:05 +08:00
parent 80983ab56b
commit 948e0f5758
7 changed files with 266 additions and 22 deletions

View File

@ -88,7 +88,10 @@ function configure_nimble {
iniset ${NIMBLE_CONF_FILE} ironic api_endpoint "${KEYSTONE_AUTH_PROTOCOL}://${SERVICE_HOST}:${IRONIC_SERVICE_PORT}"
# Setup neutron section
iniset ${NIMBLE_CONF_FILE} neutron url "${NIMBLE_SERVICE_PROTOCOL}://${SERVICE_HOST}:${NEUTRON_SERVICE_PORT}"
iniset ${NIMBLE_CONF_FILE} neutron url "${NEUTRON_SERVICE_PROTOCOL}://${SERVICE_HOST}:${NEUTRON_SERVICE_PORT}"
# Setup glance section
iniset ${NIMBLE_CONF_FILE} glance glance_api_servers "${GLANCE_SERVICE_PROTOCOL}://${SERVICE_HOST}:${GLANCE_SERVICE_PORT}"
# Setup keystone section
iniset ${NIMBLE_CONF_FILE} keystone region_name ${REGION_NAME}

View File

@ -168,7 +168,7 @@
#rpc_zmq_bind_address = *
# MatchMaker driver. (string value)
# Allowed values: redis, dummy
# Allowed values: redis, sentinel, dummy
# Deprecated group/name - [DEFAULT]/rpc_zmq_matchmaker
#rpc_zmq_matchmaker = redis
@ -191,13 +191,15 @@
# Deprecated group/name - [DEFAULT]/rpc_zmq_host
#rpc_zmq_host = localhost
# Seconds to wait before a cast expires (TTL). The default
# value of -1 specifies an infinite linger period. The value
# of 0 specifies no linger period. Pending messages shall be
# discarded immediately when the socket is closed. Only
# supported by impl_zmq. (integer value)
# Number of seconds to wait before all pending messages will
# be sent after closing a socket. The default value of -1
# specifies an infinite linger period. The value of 0
# specifies no linger period. Pending messages shall be
# discarded immediately when the socket is closed. Positive
# values specify an upper bound for the linger period.
# (integer value)
# Deprecated group/name - [DEFAULT]/rpc_cast_timeout
#rpc_cast_timeout = -1
#zmq_linger = -1
# The default number of seconds that poll should wait. Poll
# raises timeout exception when timeout expired. (integer
@ -253,7 +255,73 @@
# False means to keep queue and messages even if server is
# disconnected, when the server appears we send all
# accumulated messages to it. (boolean value)
#zmq_immediate = false
#zmq_immediate = true
# Enable/disable TCP keepalive (KA) mechanism. The default
# value of -1 (or any other negative value) means to skip any
# overrides and leave it to OS default; 0 and 1 (or any other
# positive value) mean to disable and enable the option
# respectively. (integer value)
#zmq_tcp_keepalive = -1
# The duration between two keepalive transmissions in idle
# condition. The unit is platform dependent, for example,
# seconds in Linux, milliseconds in Windows etc. The default
# value of -1 (or any other negative value and 0) means to
# skip any overrides and leave it to OS default. (integer
# value)
#zmq_tcp_keepalive_idle = -1
# The number of retransmissions to be carried out before
# declaring that remote end is not available. The default
# value of -1 (or any other negative value and 0) means to
# skip any overrides and leave it to OS default. (integer
# value)
#zmq_tcp_keepalive_cnt = -1
# The duration between two successive keepalive
# retransmissions, if acknowledgement to the previous
# keepalive transmission is not received. The unit is platform
# dependent, for example, seconds in Linux, milliseconds in
# Windows etc. The default value of -1 (or any other negative
# value and 0) means to skip any overrides and leave it to OS
# default. (integer value)
#zmq_tcp_keepalive_intvl = -1
# Maximum number of (green) threads to work concurrently.
# (integer value)
#rpc_thread_pool_size = 100
# Expiration timeout in seconds of a sent/received message
# after which it is not tracked anymore by a client/server.
# (integer value)
#rpc_message_ttl = 300
# Wait for message acknowledgements from receivers. This
# mechanism works only via proxy without PUB/SUB. (boolean
# value)
#rpc_use_acks = false
# Number of seconds to wait for an ack from a cast/call. After
# each retry attempt this timeout is multiplied by some
# specified multiplier. (integer value)
#rpc_ack_timeout_base = 15
# Number to multiply base ack timeout by after each retry
# attempt. (integer value)
#rpc_ack_timeout_multiplier = 2
# Default number of message sending attempts in case of any
# problems occurred: positive value N means at most N retries,
# 0 means no retries, None or -1 (or any other negative
# values) mean to retry forever. This option is used only if
# acknowledgments are enabled. (integer value)
#rpc_retry_attempts = 3
# List of publisher hosts SubConsumer can subscribe on. This
# option has higher priority then the default publishers list
# taken from the matchmaker. (list value)
#subscribe_on =
# Size of executor thread pool. (integer value)
# Deprecated group/name - [DEFAULT]/rpc_thread_pool_size
@ -571,6 +639,34 @@
# seconds. (integer value)
#sync_node_resource_interval = 60
# Default scheduler driver to use (string value)
#scheduler_driver = nimble.engine.scheduler.filter_scheduler.FilterScheduler
[glance]
#
# From nimble
#
# A list of the glance api servers available to nimble. Prefix
# with https:// for SSL-based glance API servers. Format is
# [hostname|IP]:port. (list value)
#glance_api_servers = <None>
# Allow to perform insecure SSL (https) requests to glance.
# (boolean value)
#glance_api_insecure = false
# Number of retries when downloading an image from glance.
# (integer value)
#glance_num_retries = 0
# Optional path to a CA certificate bundle to be used to
# validate the SSL certificate served by glance. It is used
# when glance_api_insecure is set to False. (string value)
#glance_cafile = <None>
[ironic]
@ -919,6 +1015,19 @@
# Minimum value: 1
#notify_server_credit = 100
# Send messages of this type pre-settled.
# Pre-settled messages will not receive acknowledgement
# from the peer. Note well: pre-settled messages may be
# silently discarded if the delivery fails.
# Permitted values:
# 'rpc-call' - send RPC Calls pre-settled
# 'rpc-reply'- send RPC Replies pre-settled
# 'rpc-cast' - Send RPC Casts pre-settled
# 'notify' - Send Notifications pre-settled
# (multi valued)
#pre_settled = rpc-cast
#pre_settled = rpc-reply
[oslo_messaging_notifications]
@ -1046,6 +1155,7 @@
#rabbit_password = guest
# The RabbitMQ login method. (string value)
# Allowed values: PLAIN, AMQPLAIN, RABBIT-CR-DEMO
# Deprecated group/name - [DEFAULT]/rabbit_login_method
#rabbit_login_method = AMQPLAIN
@ -1166,6 +1276,12 @@
# connections are closed on acquire. (integer value)
#pool_stale = 60
# Default serialization mechanism for
# serializing/deserializing outgoing/incoming messages (string
# value)
# Allowed values: json, msgpack
#default_serializer_type = json
# Persist notification messages. (boolean value)
#notification_persistence = false
@ -1236,7 +1352,7 @@
#rpc_zmq_bind_address = *
# MatchMaker driver. (string value)
# Allowed values: redis, dummy
# Allowed values: redis, sentinel, dummy
# Deprecated group/name - [DEFAULT]/rpc_zmq_matchmaker
#rpc_zmq_matchmaker = redis
@ -1259,13 +1375,15 @@
# Deprecated group/name - [DEFAULT]/rpc_zmq_host
#rpc_zmq_host = localhost
# Seconds to wait before a cast expires (TTL). The default
# value of -1 specifies an infinite linger period. The value
# of 0 specifies no linger period. Pending messages shall be
# discarded immediately when the socket is closed. Only
# supported by impl_zmq. (integer value)
# Number of seconds to wait before all pending messages will
# be sent after closing a socket. The default value of -1
# specifies an infinite linger period. The value of 0
# specifies no linger period. Pending messages shall be
# discarded immediately when the socket is closed. Positive
# values specify an upper bound for the linger period.
# (integer value)
# Deprecated group/name - [DEFAULT]/rpc_cast_timeout
#rpc_cast_timeout = -1
#zmq_linger = -1
# The default number of seconds that poll should wait. Poll
# raises timeout exception when timeout expired. (integer
@ -1321,7 +1439,73 @@
# False means to keep queue and messages even if server is
# disconnected, when the server appears we send all
# accumulated messages to it. (boolean value)
#zmq_immediate = false
#zmq_immediate = true
# Enable/disable TCP keepalive (KA) mechanism. The default
# value of -1 (or any other negative value) means to skip any
# overrides and leave it to OS default; 0 and 1 (or any other
# positive value) mean to disable and enable the option
# respectively. (integer value)
#zmq_tcp_keepalive = -1
# The duration between two keepalive transmissions in idle
# condition. The unit is platform dependent, for example,
# seconds in Linux, milliseconds in Windows etc. The default
# value of -1 (or any other negative value and 0) means to
# skip any overrides and leave it to OS default. (integer
# value)
#zmq_tcp_keepalive_idle = -1
# The number of retransmissions to be carried out before
# declaring that remote end is not available. The default
# value of -1 (or any other negative value and 0) means to
# skip any overrides and leave it to OS default. (integer
# value)
#zmq_tcp_keepalive_cnt = -1
# The duration between two successive keepalive
# retransmissions, if acknowledgement to the previous
# keepalive transmission is not received. The unit is platform
# dependent, for example, seconds in Linux, milliseconds in
# Windows etc. The default value of -1 (or any other negative
# value and 0) means to skip any overrides and leave it to OS
# default. (integer value)
#zmq_tcp_keepalive_intvl = -1
# Maximum number of (green) threads to work concurrently.
# (integer value)
#rpc_thread_pool_size = 100
# Expiration timeout in seconds of a sent/received message
# after which it is not tracked anymore by a client/server.
# (integer value)
#rpc_message_ttl = 300
# Wait for message acknowledgements from receivers. This
# mechanism works only via proxy without PUB/SUB. (boolean
# value)
#rpc_use_acks = false
# Number of seconds to wait for an ack from a cast/call. After
# each retry attempt this timeout is multiplied by some
# specified multiplier. (integer value)
#rpc_ack_timeout_base = 15
# Number to multiply base ack timeout by after each retry
# attempt. (integer value)
#rpc_ack_timeout_multiplier = 2
# Default number of message sending attempts in case of any
# problems occurred: positive value N means at most N retries,
# 0 means no retries, None or -1 (or any other negative
# values) mean to retry forever. This option is used only if
# acknowledgments are enabled. (integer value)
#rpc_retry_attempts = 3
# List of publisher hosts SubConsumer can subscribe on. This
# option has higher priority then the default publishers list
# taken from the matchmaker. (list value)
#subscribe_on =
[oslo_policy]
@ -1330,7 +1514,7 @@
# From oslo.policy
#
# The JSON file that defines policies. (string value)
# The file that defines policies. (string value)
# Deprecated group/name - [DEFAULT]/policy_file
#policy_file = policy.json
@ -1349,6 +1533,39 @@
#policy_dirs = policy.d
[scheduler]
#
# From nimble
#
# Default scheduler driver to use (string value)
#scheduler_driver = nimble.engine.scheduler.filter_scheduler.FilterScheduler
# The scheduler node manager class to use (string value)
#scheduler_node_manager = nimble.engine.scheduler.node_manager.NodeManager
# Maximum number of attempts to schedule a node (integer
# value)
#scheduler_max_attempts = 3
# Absolute path to scheduler configuration JSON file. (string
# value)
#scheduler_json_config_location =
# Which filter class names to use for filtering nodes when not
# specified in the request. (list value)
#scheduler_default_filters = AvailabilityZoneFilter,InstanceTypeFilter,CapabilitiesFilter
# Which weigher class names to use for weighing nodes. (list
# value)
#scheduler_default_weighers =
# Which handler to use for selecting the node after weighing
# (string value)
#scheduler_weight_handler = nimble.engine.scheduler.weights.OrderedNodeWeightHandler
[ssl]
#

View File

@ -369,6 +369,7 @@ class InstanceController(rest.RestController):
requested_networks = instance.pop('networks', None)
instance_type_uuid = instance.get('instance_type_uuid')
image_uuid = instance.get('image_uuid')
try:
instance_type = objects.InstanceType.get(pecan.request.context,
@ -377,7 +378,7 @@ class InstanceController(rest.RestController):
instance = self.engine_api.create(
pecan.request.context,
instance_type,
image_uuid=instance.get('image_uuid'),
image_uuid=image_uuid,
name=instance.get('name'),
description=instance.get('description'),
availability_zone=instance.get('availability_zone'),
@ -388,6 +389,14 @@ class InstanceController(rest.RestController):
instance_type_uuid)
raise wsme.exc.ClientSideError(
msg, status_code=http_client.BAD_REQUEST)
except exception.ImageNotFound:
msg = (_("Requested image %s could not be found") % image_uuid)
raise wsme.exc.ClientSideError(
msg, status_code=http_client.BAD_REQUEST)
except exception.GlanceConnectionFailed:
msg = _("Error contacting with glance server")
raise wsme.exc.ClientSideError(
msg, status_code=http_client.BAD_REQUEST)
# Set the HTTP Location Header
pecan.response.location = link.build_url('instance', instance.uuid)

View File

@ -21,6 +21,7 @@ from nimble.common.i18n import _
opts = [
cfg.ListOpt('glance_api_servers',
required=True,
help=_('A list of the glance api servers available to nimble. '
'Prefix with https:// for SSL-based glance API '
'servers. Format is [hostname|IP]:port.')),

View File

@ -19,6 +19,7 @@ from oslo_log import log
from nimble.engine import rpcapi
from nimble.engine import status
from nimble import image
from nimble import objects
LOG = log.getLogger(__name__)
@ -27,10 +28,14 @@ LOG = log.getLogger(__name__)
class API(object):
"""API for interacting with the engine manager."""
def __init__(self, **kwargs):
def __init__(self, image_api=None, **kwargs):
super(API, self).__init__(**kwargs)
self.image_api = image_api or image.API()
self.engine_rpcapi = rpcapi.EngineAPI()
def _get_image(self, context, image_uuid):
return self.image_api.get(context, image_uuid)
def _validate_and_build_base_options(self, context, instance_type,
image_uuid, name, description,
availability_zone, extra):
@ -65,6 +70,10 @@ class API(object):
requested_networks):
"""Verify all the input parameters"""
# Verify the specified image exists
if image_uuid:
self._get_image(context, image_uuid)
base_options = self._validate_and_build_base_options(
context, instance_type, image_uuid, name, description,
availability_zone, extra)

View File

@ -69,6 +69,7 @@ class TestCase(base.BaseTestCase):
self.set_defaults(connection="sqlite://",
sqlite_synchronous=False,
group='database')
CONF.set_override('glance_api_servers', 'fake-glance', 'glance')
nimble_config.parse_args([], default_config_files=[])
def config(self, **kw):

View File

@ -80,8 +80,10 @@ class ComputeAPIUnitTest(base.DbTestCase):
@mock.patch.object(engine_rpcapi.EngineAPI, 'create_instance')
@mock.patch('nimble.engine.api.API._provision_instances')
@mock.patch('nimble.engine.api.API._get_image')
@mock.patch('nimble.engine.api.API._validate_and_build_base_options')
def test_create(self, mock_validate, mock_provision, mock_create):
def test_create(self, mock_validate, mock_get_image,
mock_provision, mock_create):
instance_type = self._create_instance_type()
base_options = {'image_uuid': 'fake-uuid',
@ -94,6 +96,7 @@ class ComputeAPIUnitTest(base.DbTestCase):
'extra': {'k1', 'v1'},
'availability_zone': None}
mock_validate.return_value = base_options
mock_get_image.side_effect = None
mock_create.return_value = mock.MagicMock()
self.engine_api.create(
@ -111,3 +114,4 @@ class ComputeAPIUnitTest(base.DbTestCase):
'fake-descritpion', 'test_az', {'k1', 'v1'})
mock_provision.assert_called_once_with(self.context, base_options)
self.assertTrue(mock_create.called)
self.assertTrue(mock_get_image.called)