Merge "Make the TestResource a bit smarter"
This commit is contained in:
commit
66725065b6
@ -11,7 +11,10 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import datetime
|
||||
import eventlet
|
||||
from oslo_utils import timeutils
|
||||
import six
|
||||
|
||||
from heat.common.i18n import _
|
||||
from heat.engine import attributes
|
||||
@ -34,10 +37,19 @@ class TestResource(resource.Resource):
|
||||
|
||||
support_status = support.SupportStatus(version='2014.1')
|
||||
|
||||
PROPERTIES = (
|
||||
VALUE, UPDATE_REPLACE, FAIL, WAIT_SECS
|
||||
ACTION_TIMES = (
|
||||
CREATE_WAIT_SECS, UPDATE_WAIT_SECS, DELETE_WAIT_SECS
|
||||
) = (
|
||||
'value', 'update_replace', 'fail', 'wait_secs'
|
||||
'create', 'update', 'delete')
|
||||
|
||||
PROPERTIES = (
|
||||
VALUE, UPDATE_REPLACE, FAIL,
|
||||
CLIENT_NAME, ENTITY_NAME,
|
||||
WAIT_SECS, ACTION_WAIT_SECS
|
||||
) = (
|
||||
'value', 'update_replace', 'fail',
|
||||
'client_name', 'entity_name',
|
||||
'wait_secs', 'action_wait_secs'
|
||||
)
|
||||
|
||||
ATTRIBUTES = (
|
||||
@ -69,11 +81,47 @@ class TestResource(resource.Resource):
|
||||
),
|
||||
WAIT_SECS: properties.Schema(
|
||||
properties.Schema.NUMBER,
|
||||
_('Value which can be set for resource to wait after an action '
|
||||
'is performed.'),
|
||||
_('Seconds to wait after an action (-1 is infinite)'),
|
||||
update_allowed=True,
|
||||
default=0,
|
||||
),
|
||||
ACTION_WAIT_SECS: properties.Schema(
|
||||
properties.Schema.MAP,
|
||||
_('Options for simulating waiting.'),
|
||||
update_allowed=True,
|
||||
schema={
|
||||
CREATE_WAIT_SECS: properties.Schema(
|
||||
properties.Schema.NUMBER,
|
||||
_('Seconds to wait after a create. '
|
||||
'Defaults to the global wait_secs'),
|
||||
update_allowed=True,
|
||||
),
|
||||
UPDATE_WAIT_SECS: properties.Schema(
|
||||
properties.Schema.NUMBER,
|
||||
_('Seconds to wait after an update. '
|
||||
'Defaults to the global wait_secs'),
|
||||
update_allowed=True,
|
||||
),
|
||||
DELETE_WAIT_SECS: properties.Schema(
|
||||
properties.Schema.NUMBER,
|
||||
_('Seconds to wait after a delete. '
|
||||
'Defaults to the global wait_secs'),
|
||||
update_allowed=True,
|
||||
),
|
||||
}
|
||||
),
|
||||
CLIENT_NAME: properties.Schema(
|
||||
properties.Schema.STRING,
|
||||
_('Client to poll.'),
|
||||
default='',
|
||||
update_allowed=True
|
||||
),
|
||||
ENTITY_NAME: properties.Schema(
|
||||
properties.Schema.STRING,
|
||||
_('Client entity to poll.'),
|
||||
default='',
|
||||
update_allowed=True
|
||||
),
|
||||
}
|
||||
|
||||
attributes_schema = {
|
||||
@ -84,44 +132,88 @@ class TestResource(resource.Resource):
|
||||
),
|
||||
}
|
||||
|
||||
def _wait_secs(self):
|
||||
secs = None
|
||||
if self.properties[self.ACTION_WAIT_SECS]:
|
||||
secs = self.properties[self.ACTION_WAIT_SECS][self.action.lower()]
|
||||
if secs is None:
|
||||
secs = self.properties[self.WAIT_SECS]
|
||||
LOG.info('%s wait_secs:%s, action:%s' % (self.name, secs,
|
||||
self.action.lower()))
|
||||
return secs
|
||||
|
||||
def handle_create(self):
|
||||
value = self.properties.get(self.VALUE)
|
||||
fail_prop = self.properties.get(self.FAIL)
|
||||
sleep_secs = self.properties.get(self.WAIT_SECS)
|
||||
if not fail_prop:
|
||||
value = self.properties.get(self.VALUE)
|
||||
self.data_set('value', value, redact=False)
|
||||
self.resource_id_set(self.physical_resource_name())
|
||||
|
||||
self.data_set('value', value, redact=False)
|
||||
self.resource_id_set(self.physical_resource_name())
|
||||
|
||||
# sleep for specified time
|
||||
if sleep_secs:
|
||||
LOG.debug("Resource %s sleeping for %s seconds",
|
||||
self.name, sleep_secs)
|
||||
eventlet.sleep(sleep_secs)
|
||||
|
||||
# emulate failure
|
||||
if fail_prop:
|
||||
raise ValueError("Test Resource failed %s" % self.name)
|
||||
return timeutils.utcnow(), self._wait_secs()
|
||||
|
||||
def handle_update(self, json_snippet=None, tmpl_diff=None, prop_diff=None):
|
||||
self.properties = json_snippet.properties(self.properties_schema,
|
||||
self.context)
|
||||
value = prop_diff.get(self.VALUE)
|
||||
new_prop = json_snippet._properties
|
||||
if value:
|
||||
update_replace = new_prop.get(self.UPDATE_REPLACE, False)
|
||||
update_replace = self.properties[self.UPDATE_REPLACE]
|
||||
if update_replace:
|
||||
raise resource.UpdateReplace(self.name)
|
||||
else:
|
||||
fail_prop = new_prop.get(self.FAIL, False)
|
||||
sleep_secs = new_prop.get(self.WAIT_SECS, 0)
|
||||
# emulate failure
|
||||
if fail_prop:
|
||||
raise Exception("Test Resource failed %s", self.name)
|
||||
# update in place
|
||||
self.data_set('value', value, redact=False)
|
||||
fail_prop = self.properties[self.FAIL]
|
||||
if not fail_prop:
|
||||
# update in place
|
||||
self.data_set('value', value, redact=False)
|
||||
return timeutils.utcnow(), self._wait_secs()
|
||||
return timeutils.utcnow(), 0
|
||||
|
||||
if sleep_secs:
|
||||
LOG.debug("Update of Resource %s sleeping for %s seconds",
|
||||
self.name, sleep_secs)
|
||||
eventlet.sleep(sleep_secs)
|
||||
def handle_delete(self):
|
||||
return timeutils.utcnow(), self._wait_secs()
|
||||
|
||||
def check_create_complete(self, cookie):
|
||||
return self._check_status_complete(*cookie)
|
||||
|
||||
def check_update_complete(self, cookie):
|
||||
return self._check_status_complete(*cookie)
|
||||
|
||||
def check_delete_complete(self, cookie):
|
||||
return self._check_status_complete(*cookie)
|
||||
|
||||
def _check_status_complete(self, started_at, wait_secs):
|
||||
def simulated_effort():
|
||||
client_name = self.properties[self.CLIENT_NAME]
|
||||
self.entity = self.properties[self.ENTITY_NAME]
|
||||
if client_name and self.entity:
|
||||
# Allow the user to set the value to a real resource id.
|
||||
entity_id = self.data().get('value') or self.resource_id
|
||||
try:
|
||||
obj = getattr(self.client(name=client_name), self.entity)
|
||||
obj.get(entity_id)
|
||||
except Exception as exc:
|
||||
LOG.debug('%s.%s(%s) %s' % (client_name, self.entity,
|
||||
entity_id, six.text_type(exc)))
|
||||
else:
|
||||
# just sleep some more
|
||||
eventlet.sleep(1)
|
||||
|
||||
if isinstance(started_at, six.string_types):
|
||||
started_at = timeutils.parse_isotime(started_at)
|
||||
|
||||
started_at = timeutils.normalize_time(started_at)
|
||||
waited = timeutils.utcnow() - started_at
|
||||
LOG.info("Resource %s waited %s/%s seconds",
|
||||
self.name, waited, wait_secs)
|
||||
|
||||
# wait_secs < 0 is an infinite wait time.
|
||||
if wait_secs >= 0 and waited > datetime.timedelta(seconds=wait_secs):
|
||||
fail_prop = self.properties[self.FAIL]
|
||||
if fail_prop and self.action != self.DELETE:
|
||||
raise ValueError("Test Resource failed %s" % self.name)
|
||||
return True
|
||||
|
||||
simulated_effort()
|
||||
return False
|
||||
|
||||
def _resolve_attribute(self, name):
|
||||
if name == self.OUTPUT:
|
||||
|
@ -26,7 +26,10 @@ test_template_one_resource = {
|
||||
'value': 'Test1',
|
||||
'fail': False,
|
||||
'update_replace': False,
|
||||
'wait_secs': 0
|
||||
'wait_secs': 0,
|
||||
'action_wait_secs': {'create': 1},
|
||||
'client_name': 'nova',
|
||||
'entity_name': 'servers',
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -42,7 +45,8 @@ test_template_two_resource = {
|
||||
'value': 'Test1',
|
||||
'fail': False,
|
||||
'update_replace': False,
|
||||
'wait_secs': 0
|
||||
'wait_secs': 0,
|
||||
'action_wait_secs': {'update': 1}
|
||||
}
|
||||
},
|
||||
'test2': {
|
||||
|
Loading…
x
Reference in New Issue
Block a user