Пример #1
0
    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])
Пример #2
0
    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])
Пример #3
0
    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']))
Пример #4
0
    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']))
Пример #5
0
    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
Пример #6
0
    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
Пример #7
0
    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)
Пример #8
0
    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)}
Пример #9
0
    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
Пример #10
0
    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)
Пример #11
0
    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
Пример #12
0
    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 = []
Пример #13
0
    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)
Пример #14
0
 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)
Пример #15
0
    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')
Пример #16
0
 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)
Пример #17
0
    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)
Пример #18
0
    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)}
Пример #19
0
    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)
Пример #20
0
    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')
Пример #21
0
 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)
Пример #22
0
 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)
Пример #23
0
 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
Пример #24
0
    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)
Пример #25
0
    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])
Пример #26
0
    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()
Пример #27
0
    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)
Пример #28
0
    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)
Пример #29
0
    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
Пример #30
0
    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