def handle_update(self, json_snippet, tmpl_diff, prop_diff): """ If Properties has changed, update self.properties, so we get the new values during any subsequent adjustment. """ if tmpl_diff: # parse update policy if 'UpdatePolicy' in tmpl_diff: self.update_policy = Properties(self.update_policy_schema, json_snippet.get( 'UpdatePolicy', {}), parent_name=self.name, context=self.context) if prop_diff: self.properties = Properties(self.properties_schema, json_snippet.get('Properties', {}), function.resolve, self.name, self.context) # Replace instances first if launch configuration has changed self._try_rolling_update(prop_diff) # Get the current capacity, we may need to adjust if # Size has changed if self.SIZE in prop_diff: inst_list = self.get_instances() if len(inst_list) != self.properties[self.SIZE]: self.resize(self.properties[self.SIZE])
def handle_update(self, json_snippet, tmpl_diff, prop_diff): """ If Properties has changed, update self.properties, so we get the new values during any subsequent adjustment. """ if tmpl_diff: # parse update policy if 'UpdatePolicy' in tmpl_diff: self.update_policy = Properties(self.update_policy_schema, json_snippet.get( 'UpdatePolicy', {}), parent_name=self.name, context=self.context) if prop_diff: self.properties = Properties(self.properties_schema, json_snippet.get('Properties', {}), self.stack.resolve_runtime_data, self.name, self.context) # Replace instances first if launch configuration has changed if (self.update_policy[self.ROLLING_UPDATE] and self.LAUNCH_CONFIGURATION_NAME in prop_diff): policy = self.update_policy[self.ROLLING_UPDATE] self._replace(policy[self.MIN_INSTANCES_IN_SERVICE], policy[self.MAX_BATCH_SIZE], policy[self.PAUSE_TIME]) # Get the current capacity, we may need to adjust if # Size has changed if self.SIZE in prop_diff: inst_list = self.get_instances() if len(inst_list) != self.properties[self.SIZE]: self.resize(self.properties[self.SIZE])
def handle_update(self, json_snippet, tmpl_diff, prop_diff): """ If Properties has changed, update self.properties, so we get the new values during any subsequent adjustment. """ if tmpl_diff: # parse update policy if 'UpdatePolicy' in tmpl_diff: self.update_policy = Properties(self.update_policy_schema, json_snippet.get( 'UpdatePolicy', {}), parent_name=self.name) if prop_diff: self.properties = Properties(self.properties_schema, json_snippet.get('Properties', {}), self.stack.resolve_runtime_data, self.name) # Get the current capacity, we may need to adjust if # Size has changed if 'Size' in prop_diff: inst_list = self.get_instances() if len(inst_list) != int(self.properties['Size']): self.resize(int(self.properties['Size']))
def handle_update(self, json_snippet, tmpl_diff, prop_diff): """ If Properties has changed, update self.properties, so we get the new values during any subsequent adjustment. """ if tmpl_diff: # parse update policy if 'UpdatePolicy' in tmpl_diff: self.update_policy = Properties(self.update_policy_schema, json_snippet.get( 'UpdatePolicy', {}), parent_name=self.name) if prop_diff: self.properties = Properties(self.properties_schema, json_snippet.get('Properties', {}), self.stack.resolve_runtime_data, self.name) # Replace instances first if launch configuration has changed if (self.update_policy['RollingUpdate'] and 'LaunchConfigurationName' in prop_diff): policy = self.update_policy['RollingUpdate'] self._replace(int(policy['MinInstancesInService']), int(policy['MaxBatchSize']), policy['PauseTime']) # Get the current capacity, we may need to adjust if # Size has changed if 'Size' in prop_diff: inst_list = self.get_instances() if len(inst_list) != int(self.properties['Size']): self.resize(int(self.properties['Size']))
def handle_update(self, json_snippet): try: self.update_template_diff(json_snippet) except NotImplementedError: logger.error("Could not update %s, invalid key" % self.name) return self.UPDATE_REPLACE try: prop_diff = self.update_template_diff_properties(json_snippet) except NotImplementedError: logger.error("Could not update %s, invalid Property" % self.name) return self.UPDATE_REPLACE # If Properties has changed, update self.properties, so we # get the new values during any subsequent adjustment if prop_diff: self.properties = Properties(self.properties_schema, json_snippet.get('Properties', {}), self.stack.resolve_runtime_data, self.name) loader = watchrule.WatchRule.load wr = loader(self.context, watch_name=self.physical_resource_name()) wr.rule = self.parsed_template('Properties') wr.store() return self.UPDATE_COMPLETE
def __init__(self, name, json_snippet, stack): if '/' in name: raise ValueError(_('Resource name may not contain "/"')) self.stack = stack self.context = stack.context self.name = name self.json_snippet = json_snippet self.t = stack.resolve_static_data(json_snippet) self.cached_t = None self.properties = Properties(self.properties_schema, self.t.get('Properties', {}), self.stack.resolve_runtime_data, self.name) resource = db_api.resource_get_by_name_and_stack( self.context, name, stack.id) if resource: self.resource_id = resource.nova_instance self.state = resource.state self.state_description = resource.state_description self.id = resource.id else: self.resource_id = None self.state = None self.state_description = '' self.id = None
def update(self, json_snippet=None): ''' update the resource. Subclasses should provide a handle_update() method to customise update, the base-class handle_update will fail by default. ''' assert json_snippet is not None, 'Must specify update json snippet' if self.state in (self.CREATE_IN_PROGRESS, self.UPDATE_IN_PROGRESS): raise exception.ResourceFailure( Exception('Resource update already requested')) logger.info('updating %s' % str(self)) try: self.state_set(self.UPDATE_IN_PROGRESS) properties = Properties(self.properties_schema, json_snippet.get('Properties', {}), self.stack.resolve_runtime_data, self.name) properties.validate() tmpl_diff = self.update_template_diff(json_snippet) prop_diff = self.update_template_diff_properties(json_snippet) if callable(getattr(self, 'handle_update', None)): result = self.handle_update(json_snippet, tmpl_diff, prop_diff) except UpdateReplace: logger.debug("Resource %s update requires replacement" % self.name) raise except Exception as ex: logger.exception('update %s : %s' % (str(self), str(ex))) failure = exception.ResourceFailure(ex) self.state_set(self.UPDATE_FAILED, str(failure)) raise failure else: self.t = self.stack.resolve_static_data(json_snippet) self.state_set(self.UPDATE_COMPLETE)
def validate(self): """Validate any of the provided params.""" res = super(CloudLoadBalancer, self).validate() if res: return res if self.properties.get(self.HALF_CLOSED): if not (self.properties[self.PROTOCOL] == 'TCP' or self.properties[self.PROTOCOL] == 'TCP_CLIENT_FIRST'): return { 'Error': 'The %s property is only available for the TCP or ' 'TCP_CLIENT_FIRST protocols' % self.HALF_CLOSED } #health_monitor connect and http types require completely different #schema if self.properties.get(self.HEALTH_MONITOR): health_monitor = \ self._remove_none(self.properties[self.HEALTH_MONITOR]) schema = self._health_monitor_schema if health_monitor[self.HEALTH_MONITOR_TYPE] == 'CONNECT': schema = dict((k, v) for k, v in schema.items() if k in self._HEALTH_MONITOR_CONNECT_KEYS) try: Properties(schema, health_monitor, function.resolve, self.name).validate() except exception.StackValidationFailed as svf: return {'Error': str(svf)}
def update(self, json_snippet=None): ''' update the resource. Subclasses should provide a handle_update() method to customise update, the base-class handle_update will fail by default. ''' if self.state in (self.CREATE_IN_PROGRESS, self.UPDATE_IN_PROGRESS): return 'Resource update already requested' if not json_snippet: return 'Must specify json snippet for resource update!' logger.info('updating %s' % str(self)) result = self.UPDATE_NOT_IMPLEMENTED try: self.state_set(self.UPDATE_IN_PROGRESS) properties = Properties(self.properties_schema, json_snippet.get('Properties', {}), self.stack.resolve_runtime_data, self.name) properties.validate() if callable(getattr(self, 'handle_update', None)): result = self.handle_update(json_snippet) except Exception as ex: logger.exception('update %s : %s' % (str(self), str(ex))) self.state_set(self.UPDATE_FAILED, str(ex)) return str(ex) or "Error : %s" % type(ex) else: # If resource was updated (with or without interruption), # then we set the resource to UPDATE_COMPLETE if not result == self.UPDATE_REPLACE: self.t = self.stack.resolve_static_data(json_snippet) self.state_set(self.UPDATE_COMPLETE) return result
def create(self): ''' Create the resource. Subclasses should provide a handle_create() method to customise creation. ''' if self.state in (self.CREATE_IN_PROGRESS, self.CREATE_COMPLETE): return 'Resource creation already requested' logger.info('creating %s' % str(self)) # Re-resolve the template, since if the resource Ref's # the AWS::StackId pseudo parameter, it will change after # the parser.Stack is stored (which is after the resources # are __init__'d, but before they are create()'d) self.t = self.stack.resolve_static_data(self.json_snippet) self.properties = Properties(self.properties_schema, self.t.get('Properties', {}), self.stack.resolve_runtime_data, self.name) try: self.properties.validate() self.state_set(self.CREATE_IN_PROGRESS) create_data = None if callable(getattr(self, 'handle_create', None)): create_data = self.handle_create() while not self.check_active(create_data): eventlet.sleep(1) except greenlet.GreenletExit: raise except Exception as ex: logger.exception('create %s', str(self)) self.state_set(self.CREATE_FAILED, str(ex)) return str(ex) or "Error : %s" % type(ex) else: self.state_set(self.CREATE_COMPLETE)
def handle_update(self, json_snippet): try: tmpl_diff = self.update_template_diff(json_snippet) except NotImplementedError: logger.error("Could not update %s, invalid key" % self.name) return self.UPDATE_REPLACE try: prop_diff = self.update_template_diff_properties(json_snippet) except NotImplementedError: logger.error("Could not update %s, invalid Property" % self.name) return self.UPDATE_REPLACE # If Properties has changed, update self.properties, so we # get the new values during any subsequent adjustment if prop_diff: self.properties = Properties(self.properties_schema, json_snippet.get('Properties', {}), self.stack.resolve_runtime_data, self.name) # Get the current capacity, we may need to adjust if # Size has changed if 'Size' in prop_diff: inst_list = [] if self.resource_id is not None: inst_list = sorted(self.resource_id.split(',')) if len(inst_list) != int(self.properties['Size']): self.resize(int(self.properties['Size']), raise_on_error=True) self._wait_for_activation() return self.UPDATE_COMPLETE
def __init__(self, name, json_snippet, stack): if '/' in name: raise ValueError(_('Resource name may not contain "/"')) self.stack = stack self.context = stack.context self.name = name self.json_snippet = json_snippet self.t = stack.resolve_static_data(json_snippet) self.properties = Properties(self.properties_schema, self.t.get('Properties', {}), self._resolve_runtime_data, self.name) self.attributes = Attributes(self.name, self.attributes_schema, self._resolve_attribute) resource = db_api.resource_get_by_name_and_stack( self.context, name, stack.id) if resource: self.resource_id = resource.nova_instance self.action = resource.action self.status = resource.status self.status_reason = resource.status_reason self.id = resource.id self.data = resource.data else: self.resource_id = None # if the stack is being deleted, assume we've already been deleted if stack.action == stack.DELETE: self.action = self.DELETE else: self.action = self.INIT self.status = self.COMPLETE self.status_reason = '' self.id = None self.data = []
def handle_update(self, json_snippet, tmpl_diff, prop_diff): # If Properties has changed, update self.properties, so we # get the new values during any subsequent adjustment if prop_diff: self.properties = Properties(self.properties_schema, json_snippet.get('Properties', {}), self.stack.resolve_runtime_data, self.name) # Get the current capacity, we may need to adjust if # MinSize or MaxSize has changed inst_list = [] if self.resource_id is not None: inst_list = sorted(self.resource_id.split(',')) capacity = len(inst_list) # Figure out if an adjustment is required new_capacity = None if 'MinSize' in prop_diff: if capacity < int(self.properties['MinSize']): new_capacity = int(self.properties['MinSize']) if 'MaxSize' in prop_diff: if capacity > int(self.properties['MaxSize']): new_capacity = int(self.properties['MaxSize']) if 'DesiredCapacity' in prop_diff: if self.properties['DesiredCapacity']: new_capacity = int(self.properties['DesiredCapacity']) if new_capacity is not None: creator = self._adjust(new_capacity) self._wait_for_activation(creator)
def reparse(self): self.t = self.stack.resolve_static_data(self.json_snippet) self.properties = Properties(self.properties_schema, self.t.get('Properties', {}), self._resolve_runtime_data, self.name, self.context)
def handle_update(self, json_snippet, tmpl_diff, prop_diff): """ If Properties has changed, update self.properties, so we get the new values during any subsequent adjustment. """ if prop_diff: self.properties = Properties(self.properties_schema, json_snippet.get('Properties', {}), self.stack.resolve_runtime_data, self.name) # Get the current capacity, we may need to adjust if # MinSize or MaxSize has changed capacity = len(self.get_instances()) # Figure out if an adjustment is required new_capacity = None if 'MinSize' in prop_diff: if capacity < int(self.properties['MinSize']): new_capacity = int(self.properties['MinSize']) if 'MaxSize' in prop_diff: if capacity > int(self.properties['MaxSize']): new_capacity = int(self.properties['MaxSize']) if 'DesiredCapacity' in prop_diff: if self.properties['DesiredCapacity']: new_capacity = int(self.properties['DesiredCapacity']) if new_capacity is not None: self.adjust(new_capacity, adjustment_type='ExactCapacity')
def handle_update(self, json_snippet, tmpl_diff, prop_diff): # If Properties has changed, update self.properties, so we # get the new values during any subsequent adjustment if prop_diff: self.properties = Properties(self.properties_schema, json_snippet.get('Properties', {}), self.stack.resolve_runtime_data, self.name)
def handle_update(self, json_snippet, tmpl_diff, prop_diff): """ If Properties has changed, update self.properties, so we get the new values during any subsequent adjustment. """ if tmpl_diff: # parse update policy if 'UpdatePolicy' in tmpl_diff: self.update_policy = Properties(self.update_policy_schema, json_snippet.get( 'UpdatePolicy', {}), parent_name=self.name, context=self.context) if prop_diff: self.properties = Properties(self.properties_schema, json_snippet.get('Properties', {}), self.stack.resolve_runtime_data, self.name, self.context) # Replace instances first if launch configuration has changed if (self.update_policy[self.ROLLING_UPDATE] and self.LAUNCH_CONFIGURATION_NAME in prop_diff): policy = self.update_policy[self.ROLLING_UPDATE] self._replace(policy[self.MIN_INSTANCES_IN_SERVICE], policy[self.MAX_BATCH_SIZE], policy[self.PAUSE_TIME]) # Get the current capacity, we may need to adjust if # MinSize or MaxSize has changed capacity = len(self.get_instances()) # Figure out if an adjustment is required new_capacity = None if self.MIN_SIZE in prop_diff: if capacity < self.properties[self.MIN_SIZE]: new_capacity = self.properties[self.MIN_SIZE] if self.MAX_SIZE in prop_diff: if capacity > self.properties[self.MAX_SIZE]: new_capacity = self.properties[self.MAX_SIZE] if self.DESIRED_CAPACITY in prop_diff: if self.properties[self.DESIRED_CAPACITY]: new_capacity = self.properties[self.DESIRED_CAPACITY] if new_capacity is not None: self.adjust(new_capacity, adjustment_type=EXACT_CAPACITY)
def validate(self): """ Validate any of the provided params """ res = super(CloudLoadBalancer, self).validate() if res: return res if self.properties.get('halfClosed'): if not (self.properties['protocol'] == 'TCP' or self.properties['protocol'] == 'TCP_CLIENT_FIRST'): return { 'Error': 'The halfClosed property is only available for the ' 'TCP or TCP_CLIENT_FIRST protocols' } #health_monitor connect and http types require completely different #schema if self.properties.get('healthMonitor'): health_monitor = \ self._remove_none(self.properties['healthMonitor']) if health_monitor['type'] == 'CONNECT': schema = CloudLoadBalancer.health_monitor_connect_schema else: schema = CloudLoadBalancer.health_monitor_http_schema try: Properties(schema, health_monitor, self.stack.resolve_runtime_data, self.name).validate() except exception.StackValidationFailed as svf: return {'Error': str(svf)} if self.properties.get('sslTermination'): ssl_termination = self._remove_none( self.properties['sslTermination']) if ssl_termination['enabled']: try: Properties( CloudLoadBalancer.ssl_termination_enabled_schema, ssl_termination, self.stack.resolve_runtime_data, self.name).validate() except exception.StackValidationFailed as svf: return {'Error': str(svf)}
def update(self, after, before=None, prev_resource=None): ''' update the resource. Subclasses should provide a handle_update() method to customise update, the base-class handle_update will fail by default. ''' action = self.UPDATE (cur_class_def, cur_ver) = self.implementation_signature() prev_ver = cur_ver if prev_resource is not None: (prev_class_def, prev_ver) = prev_resource.implementation_signature() if prev_class_def != cur_class_def: raise UpdateReplace(self.name) if before is None: before = self.parsed_template() if prev_ver == cur_ver and before == after: return if (self.action, self.status) in ((self.CREATE, self.IN_PROGRESS), (self.UPDATE, self.IN_PROGRESS), (self.ADOPT, self.IN_PROGRESS)): exc = Exception(_('Resource update already requested')) raise exception.ResourceFailure(exc, self, action) logger.info('updating %s' % str(self)) try: self.updated_time = datetime.utcnow() self.state_set(action, self.IN_PROGRESS) properties = Properties(self.properties_schema, after.get('Properties', {}), self._resolve_runtime_data, self.name, self.context) properties.validate() tmpl_diff = self.update_template_diff(after, before) prop_diff = self.update_template_diff_properties(after, before) if callable(getattr(self, 'handle_update', None)): handle_data = self.handle_update(after, tmpl_diff, prop_diff) yield if callable(getattr(self, 'check_update_complete', None)): while not self.check_update_complete(handle_data): yield except UpdateReplace: with excutils.save_and_reraise_exception(): logger.debug(_("Resource %s update requires replacement") % self.name) except Exception as ex: logger.exception('update %s : %s' % (str(self), str(ex))) failure = exception.ResourceFailure(ex, self, action) self.state_set(action, self.FAILED, str(failure)) raise failure else: self.json_snippet = copy.deepcopy(after) self.reparse() self.state_set(action, self.COMPLETE)
def handle_update(self, json_snippet, tmpl_diff, prop_diff): """ If Properties has changed, update self.properties, so we get the new values during any subsequent adjustment. """ if tmpl_diff: # parse update policy if 'UpdatePolicy' in tmpl_diff: self.update_policy = Properties(self.update_policy_schema, json_snippet.get( 'UpdatePolicy', {}), parent_name=self.name, context=self.context) if prop_diff: self.properties = Properties(self.properties_schema, json_snippet.get('Properties', {}), self.stack.resolve_runtime_data, self.name, self.context) # Replace instances first if launch configuration has changed if (self.update_policy['AutoScalingRollingUpdate'] and 'LaunchConfigurationName' in prop_diff): policy = self.update_policy['AutoScalingRollingUpdate'] self._replace(int(policy['MinInstancesInService']), int(policy['MaxBatchSize']), policy['PauseTime']) # Get the current capacity, we may need to adjust if # MinSize or MaxSize has changed capacity = len(self.get_instances()) # Figure out if an adjustment is required new_capacity = None if self.MIN_SIZE in prop_diff: if capacity < int(self.properties[self.MIN_SIZE]): new_capacity = int(self.properties[self.MIN_SIZE]) if self.MAX_SIZE in prop_diff: if capacity > int(self.properties[self.MAX_SIZE]): new_capacity = int(self.properties[self.MAX_SIZE]) if self.DESIRED_CAPACITY in prop_diff: if self.properties[self.DESIRED_CAPACITY]: new_capacity = int(self.properties[self.DESIRED_CAPACITY]) if new_capacity is not None: self.adjust(new_capacity, adjustment_type='ExactCapacity')
def handle_update(self, json_snippet, tmpl_diff, prop_diff): """ If Properties has changed, update self.properties, so we get the new values during any subsequent adjustment. """ if prop_diff: self.properties = Properties(self.properties_schema, json_snippet.get('Properties', {}), function.resolve, self.name, self.context)
def __init__(self, name, json_snippet, stack): """ UpdatePolicy is currently only specific to InstanceGroup and AutoScalingGroup. Therefore, init is overridden to parse for the UpdatePolicy. """ super(InstanceGroup, self).__init__(name, json_snippet, stack) self.update_policy = Properties(self.update_policy_schema, self.t.get('UpdatePolicy', {}), parent_name=self.name)
def prepare_update_properties(self, json_snippet): ''' Removes any properties which are not update_allowed, then processes as for prepare_properties. ''' p = Properties(self.properties_schema, json_snippet.get('Properties', {}), self._resolve_runtime_data, self.name, self.context) props = dict((k, v) for k, v in p.items() if p.props.get(k).schema.update_allowed) return props
def handle_update(self, json_snippet, tmpl_diff, prop_diff): """ If Properties has changed, update self.properties, so we get the new values during any subsequent adjustment. """ if tmpl_diff: # parse update policy if 'UpdatePolicy' in tmpl_diff: self.update_policy = Properties(self.update_policy_schema, json_snippet.get( 'UpdatePolicy', {}), parent_name=self.name, context=self.context) if prop_diff: self.properties = Properties(self.properties_schema, json_snippet.get('Properties', {}), function.resolve, self.name, self.context) # Replace instances first if launch configuration has changed self._try_rolling_update(prop_diff) # Get the current capacity, we may need to adjust if # MinSize or MaxSize has changed capacity = len(self.get_instances()) # Figure out if an adjustment is required new_capacity = None if self.MIN_SIZE in prop_diff: if capacity < self.properties[self.MIN_SIZE]: new_capacity = self.properties[self.MIN_SIZE] if self.MAX_SIZE in prop_diff: if capacity > self.properties[self.MAX_SIZE]: new_capacity = self.properties[self.MAX_SIZE] if self.DESIRED_CAPACITY in prop_diff: if self.properties[self.DESIRED_CAPACITY] is not None: new_capacity = self.properties[self.DESIRED_CAPACITY] if new_capacity is not None: self.adjust(new_capacity, adjustment_type=EXACT_CAPACITY)
def handle_update(self, json_snippet, tmpl_diff, prop_diff): # Nested stack template may be changed even if the prop_diff is empty. self.properties = Properties(self.properties_schema, json_snippet.get('Properties', {}), self.stack.resolve_runtime_data, self.name) template_data = urlfetch.get(self.properties[PROP_TEMPLATE_URL]) template = template_format.parse(template_data) self.update_with_template(template, self.properties[PROP_PARAMETERS], self.properties[PROP_TIMEOUT_MINS])
def handle_update(self, json_snippet, tmpl_diff, prop_diff): # If Properties has changed, update self.properties, so we # get the new values during any subsequent adjustment if prop_diff: self.properties = Properties(self.properties_schema, json_snippet.get('Properties', {}), function.resolve, self.name, self.context) loader = watchrule.WatchRule.load wr = loader(self.context, watch_name=self.physical_resource_name()) wr.rule = self.parsed_template('Properties') wr.store()
def test_stack_validate(self): stack_name = 'service_create_test_validate' stack = get_wordpress_stack(stack_name, self.ctx) setup_mocks(self.m, stack) template = dict(stack.t) template['Parameters']['KeyName']['Default'] = 'test' resource = stack['WebServer'] self.m.ReplayAll() resource.properties = Properties(resource.properties_schema, { 'ImageId': 'foo', 'KeyName': 'test', 'InstanceType': 'm1.large' }) stack.validate() resource.properties = Properties(resource.properties_schema, { 'KeyName': 'test', 'InstanceType': 'm1.large' }) self.assertRaises(exception.StackValidationFailed, stack.validate)
def create(self): ''' Create the resource. Subclasses should provide a handle_create() method to customise creation. ''' assert self.state is None, 'Resource create requested in invalid state' logger.info('creating %s' % str(self)) # Re-resolve the template, since if the resource Ref's # the AWS::StackId pseudo parameter, it will change after # the parser.Stack is stored (which is after the resources # are __init__'d, but before they are create()'d) self.t = self.stack.resolve_static_data(self.json_snippet) self.properties = Properties(self.properties_schema, self.t.get('Properties', {}), self.stack.resolve_runtime_data, self.name) try: self.properties.validate() self.state_set(self.CREATE_IN_PROGRESS) create_data = None if callable(getattr(self, 'handle_create', None)): create_data = self.handle_create() yield while not self.check_create_complete(create_data): yield except greenlet.GreenletExit: # Older versions of greenlet erroneously had GreenletExit inherit # from Exception instead of BaseException with excutils.save_and_reraise_exception(): try: self.state_set(self.CREATE_FAILED, 'Creation aborted') except Exception: logger.exception('Error marking resource as failed') except Exception as ex: logger.exception('create %s', str(self)) failure = exception.ResourceFailure(ex) self.state_set(self.CREATE_FAILED, str(failure)) raise failure except: with excutils.save_and_reraise_exception(): try: self.state_set(self.CREATE_FAILED, 'Creation aborted') except Exception: logger.exception('Error marking resource as failed') else: self.state_set(self.CREATE_COMPLETE)
def handle_update(self, json_snippet): try: tmpl_diff = self.update_template_diff(json_snippet) except NotImplementedError: logger.error("Could not update %s, invalid key" % self.name) return self.UPDATE_REPLACE try: prop_diff = self.update_template_diff_properties(json_snippet) except NotImplementedError: logger.error("Could not update %s, invalid Property" % self.name) return self.UPDATE_REPLACE # If Properties has changed, update self.properties, so we # get the new values during any subsequent adjustment if prop_diff: self.properties = Properties(self.properties_schema, json_snippet.get('Properties', {}), self.stack.resolve_runtime_data, self.name) # Get the current capacity, we may need to adjust if # MinSize or MaxSize has changed inst_list = [] if self.resource_id is not None: inst_list = sorted(self.resource_id.split(',')) capacity = len(inst_list) # Figure out if an adjustment is required new_capacity = None if 'MinSize' in prop_diff: if capacity < int(self.properties['MinSize']): new_capacity = int(self.properties['MinSize']) if 'MaxSize' in prop_diff: if capacity > int(self.properties['MaxSize']): new_capacity = int(self.properties['MaxSize']) if 'DesiredCapacity' in prop_diff: if self.properties['DesiredCapacity']: new_capacity = int(self.properties['DesiredCapacity']) if new_capacity is not None: self._adjust(new_capacity) self._wait_for_activation() return self.UPDATE_COMPLETE
def prepare_update_properties(self, json_snippet): ''' Prepares the property values so that they can be passed directly to the Neutron update call. Removes any properties which are not update_allowed, then processes as for prepare_properties. ''' p = Properties(self.properties_schema, json_snippet.get('Properties', {}), self._resolve_runtime_data, self.name, self.context) update_props = dict((k, v) for k, v in p.items() if p.props.get(k).schema.update_allowed) props = self.prepare_properties(update_props, self.physical_resource_name()) return props