def test__victims_by_profile_age_oldest(self, mock_filter): good_nodes = [ mock.Mock(id='N11', profile_created_at=110), mock.Mock(id='N15', profile_created_at=150), mock.Mock(id='N12', profile_created_at=120), mock.Mock(id='N13', profile_created_at=130), mock.Mock(id='N14', profile_created_at=140), ] mock_filter.return_value = (['N1', 'N2'], good_nodes) nodes = mock.Mock() res = su.nodes_by_profile_age(nodes, 1) self.assertEqual(['N1'], res) res = su.nodes_by_profile_age(nodes, 2) self.assertEqual(['N1', 'N2'], res) res = su.nodes_by_profile_age(nodes, 5) self.assertEqual(['N1', 'N2', 'N11', 'N12', 'N13'], res)
def test__victims_by_profile_age_oldest(self, mock_filter): good_nodes = [ mock.Mock(id='N11', rt={'profile': mock.Mock(created_at=110)}), mock.Mock(id='N15', rt={'profile': mock.Mock(created_at=150)}), mock.Mock(id='N12', rt={'profile': mock.Mock(created_at=120)}), mock.Mock(id='N13', rt={'profile': mock.Mock(created_at=130)}), mock.Mock(id='N14', rt={'profile': mock.Mock(created_at=140)}), ] mock_filter.return_value = (['N1', 'N2'], good_nodes) nodes = mock.Mock() res = su.nodes_by_profile_age(nodes, 1) self.assertEqual(['N1'], res) res = su.nodes_by_profile_age(nodes, 2) self.assertEqual(['N1', 'N2'], res) res = su.nodes_by_profile_age(nodes, 5) self.assertEqual(['N1', 'N2', 'N11', 'N12', 'N13'], res)
def _victims_by_zones(self, cluster, zones): victims = [] for zone in sorted(zones.keys()): count = zones[zone] nodes = cluster.nodes_by_zone(zone) if self.criteria == self.RANDOM: candidates = scaleutils.nodes_by_random(nodes, count) elif self.criteria == self.OLDEST_PROFILE_FIRST: candidates = scaleutils.nodes_by_profile_age(nodes, count) elif self.criteria == self.OLDEST_FIRST: candidates = scaleutils.nodes_by_age(nodes, count, True) else: candidates = scaleutils.nodes_by_age(nodes, count, False) victims.extend(candidates) return victims
def _victims_by_regions(self, cluster, regions): victims = [] for region in sorted(regions.keys()): count = regions[region] nodes = cluster.nodes_by_region(region) if self.criteria == self.RANDOM: candidates = scaleutils.nodes_by_random(nodes, count) elif self.criteria == self.OLDEST_PROFILE_FIRST: candidates = scaleutils.nodes_by_profile_age(nodes, count) elif self.criteria == self.OLDEST_FIRST: candidates = scaleutils.nodes_by_age(nodes, count, True) else: candidates = scaleutils.nodes_by_age(nodes, count, False) victims.extend(candidates) return victims
def pre_op(self, cluster_id, action): """Choose victims that can be deleted. :param cluster_id: ID of the cluster to be handled. :param action: The action object that triggered this policy. """ victims = action.inputs.get('candidates', []) if len(victims) > 0: self._update_action(action, victims) return db_cluster = None regions = None zones = None deletion = action.data.get('deletion', {}) if deletion: # there are policy decisions count = deletion['count'] regions = deletion.get('regions', None) zones = deletion.get('zones', None) # No policy decision, check action itself: SCALE_IN elif action.action == consts.CLUSTER_SCALE_IN: count = action.inputs.get('count', 1) # No policy decision, check action itself: RESIZE else: db_cluster = db_api.cluster_get(action.context, cluster_id) scaleutils.parse_resize_params(action, db_cluster) if 'deletion' not in action.data: return count = action.data['deletion']['count'] cluster = cluster_mod.Cluster.load(action.context, cluster=db_cluster, cluster_id=cluster_id) # Cross-region if regions: victims = self._victims_by_regions(cluster, regions) self._update_action(action, victims) return # Cross-AZ if zones: victims = self._victims_by_zones(cluster, zones) self._update_action(action, victims) return if count > len(cluster.nodes): count = len(cluster.nodes) if self.criteria == self.RANDOM: victims = scaleutils.nodes_by_random(cluster.nodes, count) elif self.criteria == self.OLDEST_PROFILE_FIRST: victims = scaleutils.nodes_by_profile_age(cluster.nodes, count) elif self.criteria == self.OLDEST_FIRST: victims = scaleutils.nodes_by_age(cluster.nodes, count, True) else: victims = scaleutils.nodes_by_age(cluster.nodes, count, False) self._update_action(action, victims) return
def pre_op(self, cluster_id, action): """Choose victims that can be deleted. :param cluster_id: ID of the cluster to be handled. :param action: The action object that triggered this policy. """ victims = action.inputs.get('candidates', []) if len(victims) > 0: self._update_action(action, victims) return if action.action == consts.NODE_DELETE: self._update_action(action, [action.node.id]) return db_cluster = None regions = None zones = None deletion = action.data.get('deletion', {}) if deletion: # there are policy decisions count = deletion['count'] regions = deletion.get('regions', None) zones = deletion.get('zones', None) # No policy decision, check action itself: SCALE_IN elif action.action == consts.CLUSTER_SCALE_IN: count = action.inputs.get('count', 1) # No policy decision, check action itself: RESIZE else: db_cluster = co.Cluster.get(action.context, cluster_id) current = no.Node.count_by_cluster(action.context, cluster_id) res, reason = scaleutils.parse_resize_params(action, db_cluster, current) if res == base.CHECK_ERROR: action.data['status'] = base.CHECK_ERROR action.data['reason'] = reason LOG.error(reason) return if 'deletion' not in action.data: return count = action.data['deletion']['count'] cluster = cm.Cluster.load(action.context, dbcluster=db_cluster, cluster_id=cluster_id) # Cross-region if regions: victims = self._victims_by_regions(cluster, regions) self._update_action(action, victims) return # Cross-AZ if zones: victims = self._victims_by_zones(cluster, zones) self._update_action(action, victims) return if count > len(cluster.nodes): count = len(cluster.nodes) if self.criteria == self.RANDOM: victims = scaleutils.nodes_by_random(cluster.nodes, count) elif self.criteria == self.OLDEST_PROFILE_FIRST: victims = scaleutils.nodes_by_profile_age(cluster.nodes, count) elif self.criteria == self.OLDEST_FIRST: victims = scaleutils.nodes_by_age(cluster.nodes, count, True) else: victims = scaleutils.nodes_by_age(cluster.nodes, count, False) self._update_action(action, victims) return
def pre_op(self, cluster_id, action): """Choose victims that can be deleted. :param cluster_id: ID of the cluster to be handled. :param action: The action object that triggered this policy. """ victims = action.inputs.get('candidates', []) if len(victims) > 0: self._update_action(action, victims) return if action.action == consts.NODE_DELETE: self._update_action(action, [action.entity.id]) return cluster = action.entity regions = None zones = None hooks_data = self.hooks action.data.update({'status': base.CHECK_OK, 'reason': _('lifecycle hook parameters saved'), 'hooks': hooks_data}) action.store(action.context) deletion = action.data.get('deletion', {}) if deletion: # there are policy decisions count = deletion['count'] regions = deletion.get('regions', None) zones = deletion.get('zones', None) # No policy decision, check action itself: SCALE_IN elif action.action == consts.CLUSTER_SCALE_IN: count = action.inputs.get('count', 1) # No policy decision, check action itself: RESIZE else: current = len(cluster.nodes) res, reason = su.parse_resize_params(action, cluster, current) if res == base.CHECK_ERROR: action.data['status'] = base.CHECK_ERROR action.data['reason'] = reason LOG.error(reason) return if 'deletion' not in action.data: return count = action.data['deletion']['count'] # Cross-region if regions: victims = self._victims_by_regions(cluster, regions) self._update_action(action, victims) return # Cross-AZ if zones: victims = self._victims_by_zones(cluster, zones) self._update_action(action, victims) return if count > len(cluster.nodes): count = len(cluster.nodes) if self.criteria == self.RANDOM: victims = su.nodes_by_random(cluster.nodes, count) elif self.criteria == self.OLDEST_PROFILE_FIRST: victims = su.nodes_by_profile_age(cluster.nodes, count) elif self.criteria == self.OLDEST_FIRST: victims = su.nodes_by_age(cluster.nodes, count, True) else: victims = su.nodes_by_age(cluster.nodes, count, False) self._update_action(action, victims) return