mirror of https://github.com/apache/cloudstack.git
api,server: allow configuring repetitive alerts (#11325)
* api,server: allow configuring repetitive alerts Fixes #6613 Introduces support for configuring additional alert types that can be published repeatedly, beyond the default set. Operators can now use the dynamic configuration `alert.allowed.repetitive.types` to specify a comma-separated list of alert type names that should be allowed for repetitive publication. Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com> * add tests Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com> * fix Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com> * test fix Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com> * allow repetition for custom alerts Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com> * remove refactoring Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com> --------- Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
This commit is contained in:
parent
8bea89a80b
commit
bb8e7d39e6
|
|
@ -24,18 +24,24 @@ import com.cloud.exception.InvalidParameterValueException;
|
|||
|
||||
public interface AlertService {
|
||||
public static class AlertType {
|
||||
private static Set<AlertType> defaultAlertTypes = new HashSet<AlertType>();
|
||||
private static final Set<AlertType> defaultAlertTypes = new HashSet<>();
|
||||
private final String name;
|
||||
private final short type;
|
||||
private final boolean repetitionAllowed;
|
||||
|
||||
private AlertType(short type, String name, boolean isDefault) {
|
||||
private AlertType(short type, String name, boolean isDefault, boolean repetitionAllowed) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.repetitionAllowed = repetitionAllowed;
|
||||
if (isDefault) {
|
||||
defaultAlertTypes.add(this);
|
||||
}
|
||||
}
|
||||
|
||||
private AlertType(short type, String name, boolean isDefault) {
|
||||
this(type, name, isDefault, false);
|
||||
}
|
||||
|
||||
public static final AlertType ALERT_TYPE_MEMORY = new AlertType(Capacity.CAPACITY_TYPE_MEMORY, "ALERT.MEMORY", true);
|
||||
public static final AlertType ALERT_TYPE_CPU = new AlertType(Capacity.CAPACITY_TYPE_CPU, "ALERT.CPU", true);
|
||||
public static final AlertType ALERT_TYPE_STORAGE = new AlertType(Capacity.CAPACITY_TYPE_STORAGE, "ALERT.STORAGE", true);
|
||||
|
|
@ -45,36 +51,36 @@ public interface AlertService {
|
|||
public static final AlertType ALERT_TYPE_VIRTUAL_NETWORK_IPV6_SUBNET = new AlertType(Capacity.CAPACITY_TYPE_VIRTUAL_NETWORK_IPV6_SUBNET, "ALERT.NETWORK.IPV6SUBNET", true);
|
||||
public static final AlertType ALERT_TYPE_PRIVATE_IP = new AlertType(Capacity.CAPACITY_TYPE_PRIVATE_IP, "ALERT.NETWORK.PRIVATEIP", true);
|
||||
public static final AlertType ALERT_TYPE_SECONDARY_STORAGE = new AlertType(Capacity.CAPACITY_TYPE_SECONDARY_STORAGE, "ALERT.STORAGE.SECONDARY", true);
|
||||
public static final AlertType ALERT_TYPE_HOST = new AlertType((short)7, "ALERT.COMPUTE.HOST", true);
|
||||
public static final AlertType ALERT_TYPE_USERVM = new AlertType((short)8, "ALERT.USERVM", true);
|
||||
public static final AlertType ALERT_TYPE_DOMAIN_ROUTER = new AlertType((short)9, "ALERT.SERVICE.DOMAINROUTER", true);
|
||||
public static final AlertType ALERT_TYPE_CONSOLE_PROXY = new AlertType((short)10, "ALERT.SERVICE.CONSOLEPROXY", true);
|
||||
public static final AlertType ALERT_TYPE_HOST = new AlertType((short)7, "ALERT.COMPUTE.HOST", true, true);
|
||||
public static final AlertType ALERT_TYPE_USERVM = new AlertType((short)8, "ALERT.USERVM", true, true);
|
||||
public static final AlertType ALERT_TYPE_DOMAIN_ROUTER = new AlertType((short)9, "ALERT.SERVICE.DOMAINROUTER", true, true);
|
||||
public static final AlertType ALERT_TYPE_CONSOLE_PROXY = new AlertType((short)10, "ALERT.SERVICE.CONSOLEPROXY", true, true);
|
||||
public static final AlertType ALERT_TYPE_ROUTING = new AlertType((short)11, "ALERT.NETWORK.ROUTING", true);
|
||||
public static final AlertType ALERT_TYPE_STORAGE_MISC = new AlertType((short)12, "ALERT.STORAGE.MISC", true);
|
||||
public static final AlertType ALERT_TYPE_STORAGE_MISC = new AlertType((short)12, "ALERT.STORAGE.MISC", true, true);
|
||||
public static final AlertType ALERT_TYPE_USAGE_SERVER = new AlertType((short)13, "ALERT.USAGE", true);
|
||||
public static final AlertType ALERT_TYPE_MANAGEMENT_NODE = new AlertType((short)14, "ALERT.MANAGEMENT", true);
|
||||
public static final AlertType ALERT_TYPE_MANAGEMENT_NODE = new AlertType((short)14, "ALERT.MANAGEMENT", true, true);
|
||||
public static final AlertType ALERT_TYPE_DOMAIN_ROUTER_MIGRATE = new AlertType((short)15, "ALERT.NETWORK.DOMAINROUTERMIGRATE", true);
|
||||
public static final AlertType ALERT_TYPE_CONSOLE_PROXY_MIGRATE = new AlertType((short)16, "ALERT.SERVICE.CONSOLEPROXYMIGRATE", true);
|
||||
public static final AlertType ALERT_TYPE_USERVM_MIGRATE = new AlertType((short)17, "ALERT.USERVM.MIGRATE", true);
|
||||
public static final AlertType ALERT_TYPE_VLAN = new AlertType((short)18, "ALERT.NETWORK.VLAN", true);
|
||||
public static final AlertType ALERT_TYPE_SSVM = new AlertType((short)19, "ALERT.SERVICE.SSVM", true);
|
||||
public static final AlertType ALERT_TYPE_SSVM = new AlertType((short)19, "ALERT.SERVICE.SSVM", true, true);
|
||||
public static final AlertType ALERT_TYPE_USAGE_SERVER_RESULT = new AlertType((short)20, "ALERT.USAGE.RESULT", true);
|
||||
public static final AlertType ALERT_TYPE_STORAGE_DELETE = new AlertType((short)21, "ALERT.STORAGE.DELETE", true);
|
||||
public static final AlertType ALERT_TYPE_UPDATE_RESOURCE_COUNT = new AlertType((short)22, "ALERT.RESOURCE.COUNT", true);
|
||||
public static final AlertType ALERT_TYPE_USAGE_SANITY_RESULT = new AlertType((short)23, "ALERT.USAGE.SANITY", true);
|
||||
public static final AlertType ALERT_TYPE_DIRECT_ATTACHED_PUBLIC_IP = new AlertType((short)24, "ALERT.NETWORK.DIRECTPUBLICIP", true);
|
||||
public static final AlertType ALERT_TYPE_LOCAL_STORAGE = new AlertType((short)25, "ALERT.STORAGE.LOCAL", true);
|
||||
public static final AlertType ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED = new AlertType((short)26, "ALERT.RESOURCE.EXCEED", true);
|
||||
public static final AlertType ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED = new AlertType((short)26, "ALERT.RESOURCE.EXCEED", true, true);
|
||||
public static final AlertType ALERT_TYPE_SYNC = new AlertType((short)27, "ALERT.TYPE.SYNC", true);
|
||||
public static final AlertType ALERT_TYPE_UPLOAD_FAILED = new AlertType((short)28, "ALERT.UPLOAD.FAILED", true);
|
||||
public static final AlertType ALERT_TYPE_OOBM_AUTH_ERROR = new AlertType((short)29, "ALERT.OOBM.AUTHERROR", true);
|
||||
public static final AlertType ALERT_TYPE_HA_ACTION = new AlertType((short)30, "ALERT.HA.ACTION", true);
|
||||
public static final AlertType ALERT_TYPE_CA_CERT = new AlertType((short)31, "ALERT.CA.CERT", true);
|
||||
public static final AlertType ALERT_TYPE_UPLOAD_FAILED = new AlertType((short)28, "ALERT.UPLOAD.FAILED", true, true);
|
||||
public static final AlertType ALERT_TYPE_OOBM_AUTH_ERROR = new AlertType((short)29, "ALERT.OOBM.AUTHERROR", true, true);
|
||||
public static final AlertType ALERT_TYPE_HA_ACTION = new AlertType((short)30, "ALERT.HA.ACTION", true, true);
|
||||
public static final AlertType ALERT_TYPE_CA_CERT = new AlertType((short)31, "ALERT.CA.CERT", true, true);
|
||||
public static final AlertType ALERT_TYPE_VM_SNAPSHOT = new AlertType((short)32, "ALERT.VM.SNAPSHOT", true);
|
||||
public static final AlertType ALERT_TYPE_VR_PUBLIC_IFACE_MTU = new AlertType((short)33, "ALERT.VR.PUBLIC.IFACE.MTU", true);
|
||||
public static final AlertType ALERT_TYPE_VR_PRIVATE_IFACE_MTU = new AlertType((short)34, "ALERT.VR.PRIVATE.IFACE.MTU", true);
|
||||
public static final AlertType ALERT_TYPE_EXTENSION_PATH_NOT_READY = new AlertType((short)33, "ALERT.TYPE.EXTENSION.PATH.NOT.READY", true);
|
||||
public static final AlertType ALERT_TYPE_VPN_GATEWAY_OBSOLETE_PARAMETERS = new AlertType((short)34, "ALERT.S2S.VPN.GATEWAY.OBSOLETE.PARAMETERS", true);
|
||||
public static final AlertType ALERT_TYPE_EXTENSION_PATH_NOT_READY = new AlertType((short)33, "ALERT.TYPE.EXTENSION.PATH.NOT.READY", true, true);
|
||||
public static final AlertType ALERT_TYPE_VPN_GATEWAY_OBSOLETE_PARAMETERS = new AlertType((short)34, "ALERT.S2S.VPN.GATEWAY.OBSOLETE.PARAMETERS", true, true);
|
||||
public static final AlertType ALERT_TYPE_BACKUP_STORAGE = new AlertType(Capacity.CAPACITY_TYPE_BACKUP_STORAGE, "ALERT.STORAGE.BACKUP", true);
|
||||
public static final AlertType ALERT_TYPE_OBJECT_STORAGE = new AlertType(Capacity.CAPACITY_TYPE_OBJECT_STORAGE, "ALERT.STORAGE.OBJECT", true);
|
||||
|
||||
|
|
@ -86,6 +92,10 @@ public interface AlertService {
|
|||
return name;
|
||||
}
|
||||
|
||||
public boolean isRepetitionAllowed() {
|
||||
return repetitionAllowed;
|
||||
}
|
||||
|
||||
private static AlertType getAlertType(short type) {
|
||||
for (AlertType alertType : defaultAlertTypes) {
|
||||
if (alertType.getType() == type) {
|
||||
|
|
@ -109,7 +119,7 @@ public interface AlertService {
|
|||
if (defaultAlert != null && !defaultAlert.getName().equalsIgnoreCase(name)) {
|
||||
throw new InvalidParameterValueException("There is a default alert having type " + type + " and name " + defaultAlert.getName());
|
||||
} else {
|
||||
return new AlertType(type, name, false);
|
||||
return new AlertType(type, name, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -503,6 +503,7 @@ public class ApiConstants {
|
|||
public static final String RECONNECT = "reconnect";
|
||||
public static final String RECOVER = "recover";
|
||||
public static final String REPAIR = "repair";
|
||||
public static final String REPETITION_ALLOWED = "repetitionallowed";
|
||||
public static final String REQUIRES_HVM = "requireshvm";
|
||||
public static final String RESOURCES = "resources";
|
||||
public static final String RESOURCE_COUNT = "resourcecount";
|
||||
|
|
|
|||
|
|
@ -16,7 +16,10 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.api.command.admin.resource;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.cloudstack.alert.AlertService;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
|
|
@ -24,9 +27,7 @@ import org.apache.cloudstack.api.response.AlertResponse;
|
|||
import org.apache.cloudstack.api.response.AlertTypeResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "listAlertTypes", description = "Lists all alerts types", responseObject = AlertResponse.class,
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
|
|
@ -43,7 +44,8 @@ public class ListAlertTypesCmd extends BaseCmd {
|
|||
ListResponse<AlertTypeResponse> response = new ListResponse<>();
|
||||
List<AlertTypeResponse> typeResponseList = new ArrayList<>();
|
||||
for (AlertService.AlertType alertType : result) {
|
||||
AlertTypeResponse alertResponse = new AlertTypeResponse(alertType.getType(), alertType.getName());
|
||||
AlertTypeResponse alertResponse = new AlertTypeResponse(alertType.getType(), alertType.getName(),
|
||||
alertType.isRepetitionAllowed());
|
||||
alertResponse.setObjectName("alerttype");
|
||||
typeResponseList.add(alertResponse);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,11 +16,12 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.api.response;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class AlertTypeResponse extends BaseResponse {
|
||||
|
||||
@SerializedName("alerttypeid")
|
||||
|
|
@ -31,6 +32,10 @@ public class AlertTypeResponse extends BaseResponse {
|
|||
@Param(description = "description of alert type")
|
||||
private String name;
|
||||
|
||||
@SerializedName(ApiConstants.REPETITION_ALLOWED)
|
||||
@Param(description = "Whether repetitive alerts allowed for the alert type", since = "4.22.0")
|
||||
private boolean repetitionAllowed = true;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
|
@ -47,9 +52,10 @@ public class AlertTypeResponse extends BaseResponse {
|
|||
this.alertType = alertType;
|
||||
}
|
||||
|
||||
public AlertTypeResponse(short alertType, String name) {
|
||||
public AlertTypeResponse(short alertType, String name, boolean repetitionAllowed) {
|
||||
this.alertType = alertType;
|
||||
this.name = name;
|
||||
this.repetitionAllowed = repetitionAllowed;
|
||||
setObjectName("alerttype");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,10 @@ public interface AlertManager extends Manager, AlertService {
|
|||
"Percentage (as a value between 0 and 1) of guest network IPv6 subnet utilization above which alerts will be sent.",
|
||||
true);
|
||||
|
||||
ConfigKey<String> AllowedRepetitiveAlertTypes = new ConfigKey<>(ConfigKey.CATEGORY_ALERT, String.class,
|
||||
"alert.allowed.repetitive.types", "",
|
||||
"Comma-separated list of alert types (by name) that can be sent multiple times", true);
|
||||
|
||||
void clearAlert(AlertType alertType, long dataCenterId, long podId);
|
||||
|
||||
void recalculateCapacity();
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ package com.cloud.alert;
|
|||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
|
@ -37,15 +36,12 @@ import javax.inject.Inject;
|
|||
import javax.mail.MessagingException;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.dc.Pod;
|
||||
import com.cloud.org.Cluster;
|
||||
|
||||
import org.apache.cloudstack.backup.BackupManager;
|
||||
import org.apache.cloudstack.framework.config.ConfigDepot;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.Configurable;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.framework.messagebus.MessageBus;
|
||||
import org.apache.cloudstack.managed.context.ManagedContextTimerTask;
|
||||
import org.apache.cloudstack.storage.datastore.db.ObjectStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
|
|
@ -54,6 +50,7 @@ import org.apache.cloudstack.utils.mailing.MailAddress;
|
|||
import org.apache.cloudstack.utils.mailing.SMTPMailProperties;
|
||||
import org.apache.cloudstack.utils.mailing.SMTPMailSender;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
|
@ -70,9 +67,11 @@ import com.cloud.capacity.dao.CapacityDaoImpl.SummedCapacity;
|
|||
import com.cloud.configuration.Config;
|
||||
import com.cloud.configuration.ConfigurationManager;
|
||||
import com.cloud.dc.ClusterVO;
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.dc.DataCenter.NetworkType;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.HostPodVO;
|
||||
import com.cloud.dc.Pod;
|
||||
import com.cloud.dc.Vlan.VlanType;
|
||||
import com.cloud.dc.dao.ClusterDao;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
|
|
@ -86,10 +85,12 @@ import com.cloud.host.HostVO;
|
|||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.network.Ipv6Service;
|
||||
import com.cloud.network.dao.IPAddressDao;
|
||||
import com.cloud.org.Cluster;
|
||||
import com.cloud.org.Grouping.AllocationState;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.storage.StorageManager;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.Ternary;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
import com.cloud.utils.concurrency.NamedThreadFactory;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
|
@ -100,21 +101,6 @@ import com.cloud.utils.db.TransactionStatus;
|
|||
public class AlertManagerImpl extends ManagerBase implements AlertManager, Configurable {
|
||||
protected Logger logger = LogManager.getLogger(AlertManagerImpl.class.getName());
|
||||
|
||||
public static final List<AlertType> ALERTS = Arrays.asList(AlertType.ALERT_TYPE_HOST
|
||||
, AlertType.ALERT_TYPE_USERVM
|
||||
, AlertType.ALERT_TYPE_DOMAIN_ROUTER
|
||||
, AlertType.ALERT_TYPE_CONSOLE_PROXY
|
||||
, AlertType.ALERT_TYPE_SSVM
|
||||
, AlertType.ALERT_TYPE_STORAGE_MISC
|
||||
, AlertType.ALERT_TYPE_MANAGEMENT_NODE
|
||||
, AlertType.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED
|
||||
, AlertType.ALERT_TYPE_UPLOAD_FAILED
|
||||
, AlertType.ALERT_TYPE_OOBM_AUTH_ERROR
|
||||
, AlertType.ALERT_TYPE_HA_ACTION
|
||||
, AlertType.ALERT_TYPE_CA_CERT
|
||||
, AlertType.ALERT_TYPE_EXTENSION_PATH_NOT_READY
|
||||
, AlertType.ALERT_TYPE_VPN_GATEWAY_OBSOLETE_PARAMETERS);
|
||||
|
||||
private static final long INITIAL_CAPACITY_CHECK_DELAY = 30L * 1000L; // Thirty seconds expressed in milliseconds.
|
||||
|
||||
private static final DecimalFormat DfPct = new DecimalFormat("###.##");
|
||||
|
|
@ -156,6 +142,8 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager, Confi
|
|||
Ipv6Service ipv6Service;
|
||||
@Inject
|
||||
HostDao hostDao;
|
||||
@Inject
|
||||
MessageBus messageBus;
|
||||
|
||||
private Timer _timer = null;
|
||||
private long _capacityCheckPeriod = 60L * 60L * 1000L; // One hour by default.
|
||||
|
|
@ -175,6 +163,8 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager, Confi
|
|||
protected String[] recipients = null;
|
||||
protected String senderAddress = null;
|
||||
|
||||
private final List<String> allowedRepetitiveAlertTypeNames = new ArrayList<>();
|
||||
|
||||
public AlertManagerImpl() {
|
||||
_executor = Executors.newCachedThreadPool(new NamedThreadFactory("Email-Alerts-Sender"));
|
||||
}
|
||||
|
|
@ -254,12 +244,32 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager, Confi
|
|||
_capacityCheckPeriod = Long.parseLong(Config.CapacityCheckPeriod.getDefaultValue());
|
||||
}
|
||||
}
|
||||
initMessageBusListener();
|
||||
setupRepetitiveAlertTypes();
|
||||
|
||||
_timer = new Timer("CapacityChecker");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void setupRepetitiveAlertTypes() {
|
||||
allowedRepetitiveAlertTypeNames.clear();
|
||||
String allowedRepetitiveAlertsStr = AllowedRepetitiveAlertTypes.value();
|
||||
logger.trace("Allowed repetitive alert types specified by {}: {} ", AllowedRepetitiveAlertTypes.key(),
|
||||
allowedRepetitiveAlertsStr);
|
||||
if (StringUtils.isBlank(allowedRepetitiveAlertsStr)) {
|
||||
return;
|
||||
}
|
||||
String[] allowedRepetitiveAlertTypesArray = allowedRepetitiveAlertsStr.split(",");
|
||||
for (String allowedTypeName : allowedRepetitiveAlertTypesArray) {
|
||||
if (StringUtils.isBlank(allowedTypeName)) {
|
||||
continue;
|
||||
}
|
||||
allowedRepetitiveAlertTypeNames.add(allowedTypeName.toLowerCase());
|
||||
}
|
||||
logger.trace("{} alert types specified for repetitive alerts", allowedRepetitiveAlertTypeNames.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
_timer.schedule(new CapacityChecker(), INITIAL_CAPACITY_CHECK_DELAY, _capacityCheckPeriod);
|
||||
|
|
@ -850,11 +860,11 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager, Confi
|
|||
|
||||
@Nullable
|
||||
private AlertVO getAlertForTrivialAlertType(AlertType alertType, long dataCenterId, Long podId, Long clusterId) {
|
||||
AlertVO alert = null;
|
||||
if (!ALERTS.contains(alertType)) {
|
||||
alert = _alertDao.getLastAlert(alertType.getType(), dataCenterId, podId, clusterId);
|
||||
if (alertType.isRepetitionAllowed() || (StringUtils.isNotBlank(alertType.getName()) &&
|
||||
allowedRepetitiveAlertTypeNames.contains(alertType.getName().toLowerCase()))) {
|
||||
return null;
|
||||
}
|
||||
return alert;
|
||||
return _alertDao.getLastAlert(alertType.getType(), dataCenterId, podId, clusterId);
|
||||
}
|
||||
|
||||
protected void sendMessage(SMTPMailProperties mailProps) {
|
||||
|
|
@ -883,7 +893,7 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager, Confi
|
|||
@Override
|
||||
public ConfigKey<?>[] getConfigKeys() {
|
||||
return new ConfigKey<?>[] {CPUCapacityThreshold, MemoryCapacityThreshold, StorageAllocatedCapacityThreshold, StorageCapacityThreshold, AlertSmtpEnabledSecurityProtocols,
|
||||
AlertSmtpUseStartTLS, Ipv6SubnetCapacityThreshold, AlertSmtpUseAuth};
|
||||
AlertSmtpUseStartTLS, Ipv6SubnetCapacityThreshold, AlertSmtpUseAuth, AllowedRepetitiveAlertTypes};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -897,4 +907,16 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager, Confi
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void initMessageBusListener() {
|
||||
messageBus.subscribe(EventTypes.EVENT_CONFIGURATION_VALUE_EDIT, (senderAddress, subject, args) -> {
|
||||
Ternary<String, ConfigKey.Scope, Long> updatedSetting = (Ternary<String, ConfigKey.Scope, Long>) args;
|
||||
String updatedSettingName = updatedSetting.first();
|
||||
if (!AllowedRepetitiveAlertTypes.key().equals(updatedSettingName)) {
|
||||
return;
|
||||
}
|
||||
setupRepetitiveAlertTypes();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,12 @@
|
|||
// under the License.
|
||||
package com.cloud.alert;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
|
@ -25,7 +31,10 @@ import javax.mail.MessagingException;
|
|||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.cloudstack.backup.BackupManager;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.framework.messagebus.MessageBus;
|
||||
import org.apache.cloudstack.framework.messagebus.MessageSubscriber;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
import org.apache.cloudstack.utils.mailing.SMTPMailSender;
|
||||
|
|
@ -40,6 +49,7 @@ import org.mockito.Mock;
|
|||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import com.cloud.alert.dao.AlertDao;
|
||||
import com.cloud.capacity.Capacity;
|
||||
|
|
@ -52,16 +62,12 @@ import com.cloud.dc.HostPodVO;
|
|||
import com.cloud.dc.dao.ClusterDao;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.dc.dao.HostPodDao;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.storage.StorageManager;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import com.cloud.utils.Ternary;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AlertManagerImplTest {
|
||||
|
|
@ -112,6 +118,9 @@ public class AlertManagerImplTest {
|
|||
@Mock
|
||||
ConfigurationDao configDao;
|
||||
|
||||
@Mock
|
||||
MessageBus messageBus;
|
||||
|
||||
private final String[] recipients = new String[]{"test@test.com"};
|
||||
private final String senderAddress = "sender@test.com";
|
||||
|
||||
|
|
@ -268,4 +277,81 @@ public class AlertManagerImplTest {
|
|||
assertEquals("Available backup storage space is low, total: 200.0 MB, used: 180.0 MB (90%)", capturedAlert.getContent());
|
||||
assertEquals(AlertManager.AlertType.ALERT_TYPE_BACKUP_STORAGE.getType(), capturedAlert.getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initMessageBusListenerSubscribesToConfigurationEditEvent() {
|
||||
MessageBus messageBusMock = Mockito.mock(MessageBus.class);
|
||||
alertManagerImplMock.messageBus = messageBusMock;
|
||||
alertManagerImplMock.initMessageBusListener();
|
||||
Mockito.verify(messageBusMock).subscribe(Mockito.eq(EventTypes.EVENT_CONFIGURATION_VALUE_EDIT), Mockito.any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initMessageBusListenerTriggersSetupRepetitiveAlertTypesOnAllowedKeyEdit() {
|
||||
MessageBus messageBusMock = Mockito.mock(MessageBus.class);
|
||||
alertManagerImplMock.messageBus = messageBusMock;
|
||||
alertManagerImplMock.initMessageBusListener();
|
||||
ArgumentCaptor<MessageSubscriber> captor = ArgumentCaptor.forClass(MessageSubscriber.class);
|
||||
Mockito.verify(messageBusMock).subscribe(Mockito.eq(EventTypes.EVENT_CONFIGURATION_VALUE_EDIT), captor.capture());
|
||||
Ternary<String, ConfigKey.Scope, Long> args = new Ternary<>(AlertManager.AllowedRepetitiveAlertTypes.key(), ConfigKey.Scope.Global, 1L);
|
||||
captor.getValue().onPublishMessage(null, null, args);
|
||||
Mockito.verify(alertManagerImplMock).setupRepetitiveAlertTypes();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initMessageBusListenerDoesNotTriggerSetupRepetitiveAlertTypesOnOtherKeyEdit() {
|
||||
MessageBus messageBusMock = Mockito.mock(MessageBus.class);
|
||||
alertManagerImplMock.messageBus = messageBusMock;
|
||||
alertManagerImplMock.initMessageBusListener();
|
||||
ArgumentCaptor<MessageSubscriber> captor = ArgumentCaptor.forClass(MessageSubscriber.class);
|
||||
Mockito.verify(messageBusMock).subscribe(Mockito.eq(EventTypes.EVENT_CONFIGURATION_VALUE_EDIT), captor.capture());
|
||||
Ternary<String, ConfigKey.Scope, Long> args = new Ternary<>("some.other.key", ConfigKey.Scope.Global, 1L);
|
||||
captor.getValue().onPublishMessage(null, null, args);
|
||||
Mockito.verify(alertManagerImplMock, Mockito.never()).setupRepetitiveAlertTypes();
|
||||
}
|
||||
|
||||
private void mockAllowedRepetitiveAlertTypesConfigKey(String value) {
|
||||
ReflectionTestUtils.setField(AlertManager.AllowedRepetitiveAlertTypes, "_defaultValue", value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setupRepetitiveAlertTypesParsesValidAlertTypesCorrectly() {
|
||||
mockAllowedRepetitiveAlertTypesConfigKey(AlertManager.AlertType.ALERT_TYPE_CPU.getName() + "," + AlertManager.AlertType.ALERT_TYPE_MEMORY.getName());
|
||||
alertManagerImplMock.setupRepetitiveAlertTypes();
|
||||
List<String> expectedTypes = (List<String>)ReflectionTestUtils.getField(alertManagerImplMock, "allowedRepetitiveAlertTypeNames");
|
||||
Assert.assertNotNull(expectedTypes);
|
||||
Assert.assertEquals(2, expectedTypes.size());
|
||||
Assert.assertTrue(expectedTypes.contains(AlertManager.AlertType.ALERT_TYPE_CPU.getName().toLowerCase()));
|
||||
Assert.assertTrue(expectedTypes.contains(AlertManager.AlertType.ALERT_TYPE_MEMORY.getName().toLowerCase()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setupRepetitiveAlertTypesHandlesEmptyConfigValue() {
|
||||
mockAllowedRepetitiveAlertTypesConfigKey("");
|
||||
alertManagerImplMock.setupRepetitiveAlertTypes();
|
||||
List<String> expectedTypes = (List<String>)ReflectionTestUtils.getField(alertManagerImplMock, "allowedRepetitiveAlertTypeNames");
|
||||
Assert.assertNotNull(expectedTypes);
|
||||
Assert.assertTrue(expectedTypes.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setupRepetitiveAlertTypesIgnoresCustomAlertTypes() {
|
||||
String customAlertTypeName = "CUSTOM_ALERT_TYPE";
|
||||
mockAllowedRepetitiveAlertTypesConfigKey(AlertManager.AlertType.ALERT_TYPE_CPU.getName() + "," + customAlertTypeName);
|
||||
alertManagerImplMock.setupRepetitiveAlertTypes();
|
||||
List<String> expectedTypes = (List<String>)ReflectionTestUtils.getField(alertManagerImplMock, "allowedRepetitiveAlertTypeNames");
|
||||
Assert.assertNotNull(expectedTypes);
|
||||
Assert.assertEquals(2, expectedTypes.size());
|
||||
Assert.assertTrue(expectedTypes.contains(AlertManager.AlertType.ALERT_TYPE_CPU.getName().toLowerCase()));
|
||||
Assert.assertTrue(expectedTypes.contains(customAlertTypeName.toLowerCase()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setupRepetitiveAlertTypesHandlesNullConfigValue() {
|
||||
mockAllowedRepetitiveAlertTypesConfigKey(null);
|
||||
alertManagerImplMock.setupRepetitiveAlertTypes();
|
||||
List<String> expectedTypes = (List<String>)ReflectionTestUtils.getField(alertManagerImplMock, "allowedRepetitiveAlertTypeNames");
|
||||
Assert.assertNotNull(expectedTypes);
|
||||
Assert.assertTrue(expectedTypes.isEmpty());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue