From 61754cd987a54de53a742bf7475336b3938e0de9 Mon Sep 17 00:00:00 2001 From: Anshul Gangwar Date: Wed, 6 Mar 2013 15:09:56 +0530 Subject: [PATCH 01/13] CLOUDSTACK-680: Feature SNMP Alerts support in CloudStack Signed-off-by: Anshul Gangwar Signed-off-by: Sateesh Chodapuneedi --- client/pom.xml | 5 + client/tomcatconf/log4j-cloud.xml.in | 25 +++ core/src/com/cloud/alert/AlertManager.java | 41 ++-- plugins/alert-handlers/snmp-alerts/pom.xml | 45 ++++ .../alert/snmp/CsSnmpConstants.java | 45 ++++ .../alert/snmp/SnmpEnhancedPatternLayout.java | 107 +++++++++ .../cloudstack/alert/snmp/SnmpHelper.java | 106 +++++++++ .../alert/snmp/SnmpTrapAppender.java | 207 ++++++++++++++++++ .../cloudstack/alert/snmp/SnmpTrapInfo.java | 90 ++++++++ .../snmp/SnmpEnhancedPatternLayoutTest.java | 90 ++++++++ .../alert/snmp/SnmpTrapAppenderTest.java | 86 ++++++++ plugins/pom.xml | 1 + .../src/com/cloud/alert/AlertManagerImpl.java | 6 + .../cloud/usage/UsageAlertManagerImpl.java | 13 +- 14 files changed, 843 insertions(+), 24 deletions(-) create mode 100644 plugins/alert-handlers/snmp-alerts/pom.xml create mode 100644 plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/CsSnmpConstants.java create mode 100644 plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpEnhancedPatternLayout.java create mode 100644 plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpHelper.java create mode 100644 plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpTrapAppender.java create mode 100644 plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpTrapInfo.java create mode 100644 plugins/alert-handlers/snmp-alerts/test/org/apache/cloudstack/alert/snmp/SnmpEnhancedPatternLayoutTest.java create mode 100644 plugins/alert-handlers/snmp-alerts/test/org/apache/cloudstack/alert/snmp/SnmpTrapAppenderTest.java diff --git a/client/pom.xml b/client/pom.xml index cda6ab8b4e7..ecf232be7ac 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -65,6 +65,11 @@ cloud-plugin-network-nvp ${project.version} + + org.apache.cloudstack + cloud-plugin-snmp-alerts + ${project.version} + org.apache.cloudstack cloud-plugin-network-ovs diff --git a/client/tomcatconf/log4j-cloud.xml.in b/client/tomcatconf/log4j-cloud.xml.in index 086669376aa..ce4079f9c96 100755 --- a/client/tomcatconf/log4j-cloud.xml.in +++ b/client/tomcatconf/log4j-cloud.xml.in @@ -74,6 +74,20 @@ under the License. + + + + + + + + + + + + + + @@ -142,6 +156,17 @@ under the License. + + + + + + + + + + + diff --git a/core/src/com/cloud/alert/AlertManager.java b/core/src/com/cloud/alert/AlertManager.java index a24e18c8373..b6d005a5f21 100755 --- a/core/src/com/cloud/alert/AlertManager.java +++ b/core/src/com/cloud/alert/AlertManager.java @@ -27,26 +27,27 @@ public interface AlertManager extends Manager { public static final short ALERT_TYPE_VIRTUAL_NETWORK_PUBLIC_IP = CapacityVO.CAPACITY_TYPE_VIRTUAL_NETWORK_PUBLIC_IP; public static final short ALERT_TYPE_PRIVATE_IP = CapacityVO.CAPACITY_TYPE_PRIVATE_IP; public static final short ALERT_TYPE_SECONDARY_STORAGE = CapacityVO.CAPACITY_TYPE_SECONDARY_STORAGE; - public static final short ALERT_TYPE_HOST = 6; - public static final short ALERT_TYPE_USERVM = 7; - public static final short ALERT_TYPE_DOMAIN_ROUTER = 8; - public static final short ALERT_TYPE_CONSOLE_PROXY = 9; - public static final short ALERT_TYPE_ROUTING = 10; // lost connection to default route (to the gateway) - public static final short ALERT_TYPE_STORAGE_MISC = 11; // lost connection to default route (to the gateway) - public static final short ALERT_TYPE_USAGE_SERVER = 12; // lost connection to default route (to the gateway) - public static final short ALERT_TYPE_MANAGMENT_NODE = 13; // lost connection to default route (to the gateway) - public static final short ALERT_TYPE_DOMAIN_ROUTER_MIGRATE = 14; - public static final short ALERT_TYPE_CONSOLE_PROXY_MIGRATE = 15; - public static final short ALERT_TYPE_USERVM_MIGRATE = 16; - public static final short ALERT_TYPE_VLAN = 17; - public static final short ALERT_TYPE_SSVM = 18; - public static final short ALERT_TYPE_USAGE_SERVER_RESULT = 19; // Usage job result - public static final short ALERT_TYPE_STORAGE_DELETE = 20; - public static final short ALERT_TYPE_UPDATE_RESOURCE_COUNT = 21; // Generated when we fail to update the resource count - public static final short ALERT_TYPE_USAGE_SANITY_RESULT = 22; - public static final short ALERT_TYPE_DIRECT_ATTACHED_PUBLIC_IP = 23; - public static final short ALERT_TYPE_LOCAL_STORAGE = 24; - public static final short ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED = 25; // Generated when the resource limit exceeds the limit. Currently used for recurring snapshots only + public static final short ALERT_TYPE_HOST = 7; + public static final short ALERT_TYPE_USERVM = 8; + public static final short ALERT_TYPE_DOMAIN_ROUTER = 9; + public static final short ALERT_TYPE_CONSOLE_PROXY = 10; + public static final short ALERT_TYPE_ROUTING = 11; // lost connection to default route (to the gateway) + public static final short ALERT_TYPE_STORAGE_MISC = 12; // lost connection to default route (to the gateway) + public static final short ALERT_TYPE_USAGE_SERVER = 13; // lost connection to default route (to the gateway) + public static final short ALERT_TYPE_MANAGMENT_NODE = 14; // lost connection to default route (to the gateway) + public static final short ALERT_TYPE_DOMAIN_ROUTER_MIGRATE = 15; + public static final short ALERT_TYPE_CONSOLE_PROXY_MIGRATE = 16; + public static final short ALERT_TYPE_USERVM_MIGRATE = 17; + public static final short ALERT_TYPE_VLAN = 18; + public static final short ALERT_TYPE_SSVM = 19; + public static final short ALERT_TYPE_USAGE_SERVER_RESULT = 20; // Usage job result + public static final short ALERT_TYPE_STORAGE_DELETE = 21; + public static final short ALERT_TYPE_UPDATE_RESOURCE_COUNT = 22; // Generated when we fail to update the resource + // count + public static final short ALERT_TYPE_USAGE_SANITY_RESULT = 23; + public static final short ALERT_TYPE_DIRECT_ATTACHED_PUBLIC_IP = 24; + public static final short ALERT_TYPE_LOCAL_STORAGE = 25; + public static final short ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED = 26; // Generated when the resource limit exceeds the limit. Currently used for recurring snapshots only void clearAlert(short alertType, long dataCenterId, long podId); diff --git a/plugins/alert-handlers/snmp-alerts/pom.xml b/plugins/alert-handlers/snmp-alerts/pom.xml new file mode 100644 index 00000000000..b5cebf31b7a --- /dev/null +++ b/plugins/alert-handlers/snmp-alerts/pom.xml @@ -0,0 +1,45 @@ + + + + cloudstack-plugins + org.apache.cloudstack + 4.2.0-SNAPSHOT + ../../pom.xml + + 4.0.0 + Apache CloudStack Plugin - SNMP Alerts + cloud-plugin-snmp-alerts + + + + org.apache.servicemix.bundles + org.apache.servicemix.bundles.snmp4j + 2.1.0_1 + + + log4j + log4j + ${cs.log4j.version} + + + + diff --git a/plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/CsSnmpConstants.java b/plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/CsSnmpConstants.java new file mode 100644 index 00000000000..36970a958fd --- /dev/null +++ b/plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/CsSnmpConstants.java @@ -0,0 +1,45 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License + +package org.apache.cloudstack.alert.snmp; + +/** + *

+ * IMPORTANT + *

+ * These OIDs are based on CS-ROOT-MIB MIB file. If there is any change in MIB file + * then that should be reflected in this file also * + *

+ * suffix 2 due to conflict with SnmpConstants class of snmp4j + */ +public class CsSnmpConstants { + public static final String CLOUDSTACK = "1.3.6.1.4.1.18060.15"; + + public static final String OBJECTS_PREFIX = CLOUDSTACK + ".1.1."; + + public static final String TRAPS_PREFIX = CLOUDSTACK + ".1.2.0."; + + public static final String DATA_CENTER_ID = OBJECTS_PREFIX + 1; + + public static final String POD_ID = OBJECTS_PREFIX + 2; + + public static final String CLUSTER_ID = OBJECTS_PREFIX + 3; + + public static final String MESSAGE = OBJECTS_PREFIX + 4; + + public static final String GENERATION_TIME = OBJECTS_PREFIX + 5; +} \ No newline at end of file diff --git a/plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpEnhancedPatternLayout.java b/plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpEnhancedPatternLayout.java new file mode 100644 index 00000000000..67420915607 --- /dev/null +++ b/plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpEnhancedPatternLayout.java @@ -0,0 +1,107 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License + +package org.apache.cloudstack.alert.snmp; + +import org.apache.log4j.EnhancedPatternLayout; +import org.apache.log4j.spi.LoggingEvent; + +import java.util.Date; +import java.util.StringTokenizer; + +public class SnmpEnhancedPatternLayout extends EnhancedPatternLayout { + private String _pairDelimiter = "//"; + private String _keyValueDelimiter = "::"; + + private static final int LENGTH_OF_STRING_MESSAGE_AND_KEY_VALUE_DELIMITER = 9; + private static final int LENGTH_OF_STRING_MESSAGE = 8; + + public String getKeyValueDelimeter() { + return _keyValueDelimiter; + } + + public void setKeyValueDelimiter(String keyValueDelimiter) { + this._keyValueDelimiter = keyValueDelimiter; + } + + public String getPairDelimiter() { + return _pairDelimiter; + } + + public void setPairDelimiter(String pairDelimiter) { + this._pairDelimiter = pairDelimiter; + } + + public SnmpTrapInfo parseEvent(LoggingEvent event) { + SnmpTrapInfo snmpTrapInfo = null; + + final String message = event.getRenderedMessage(); + if (message.contains("alertType") && message.contains("message")) { + snmpTrapInfo = new SnmpTrapInfo(); + final StringTokenizer messageSplitter = new StringTokenizer(message, _pairDelimiter); + while (messageSplitter.hasMoreTokens()) { + final String pairToken = messageSplitter.nextToken(); + final StringTokenizer pairSplitter = new StringTokenizer(pairToken, _keyValueDelimiter); + String keyToken; + String valueToken; + + if (pairSplitter.hasMoreTokens()) { + keyToken = pairSplitter.nextToken().trim(); + } else { + break; + } + + if (pairSplitter.hasMoreTokens()) { + valueToken = pairSplitter.nextToken().trim(); + } else { + break; + } + + if (keyToken.equalsIgnoreCase("alertType") && !valueToken.equalsIgnoreCase("null")) { + snmpTrapInfo.setAlertType(Short.parseShort(valueToken)); + } else if (keyToken.equalsIgnoreCase("dataCenterId") && !valueToken.equalsIgnoreCase("null")) { + snmpTrapInfo.setDataCenterId(Long.parseLong(valueToken)); + } else if (keyToken.equalsIgnoreCase("podId") && !valueToken.equalsIgnoreCase("null")) { + snmpTrapInfo.setPodId(Long.parseLong(valueToken)); + } else if (keyToken.equalsIgnoreCase("clusterId") && !valueToken.equalsIgnoreCase("null")) { + snmpTrapInfo.setClusterId(Long.parseLong(valueToken)); + } else if (keyToken.equalsIgnoreCase("message") && !valueToken.equalsIgnoreCase("null")) { + snmpTrapInfo.setMessage(getSnmpMessage(message)); + } + } + + snmpTrapInfo.setGenerationTime(new Date(event.getTimeStamp())); + } + return snmpTrapInfo; + } + + private String getSnmpMessage(String message) { + int lastIndexOfKeyValueDelimiter = message.lastIndexOf(_keyValueDelimiter); + int lastIndexOfMessageInString = message.lastIndexOf("message"); + + if (lastIndexOfKeyValueDelimiter - lastIndexOfMessageInString <= + LENGTH_OF_STRING_MESSAGE_AND_KEY_VALUE_DELIMITER) { + return message.substring(lastIndexOfKeyValueDelimiter + _keyValueDelimiter.length()).trim(); + } else if (lastIndexOfMessageInString < lastIndexOfKeyValueDelimiter) { + return message.substring( + lastIndexOfMessageInString + _keyValueDelimiter.length() + LENGTH_OF_STRING_MESSAGE).trim(); + } + + return message.substring(message.lastIndexOf("message" + _keyValueDelimiter) + + LENGTH_OF_STRING_MESSAGE_AND_KEY_VALUE_DELIMITER).trim(); + } +} \ No newline at end of file diff --git a/plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpHelper.java b/plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpHelper.java new file mode 100644 index 00000000000..4bee94bd9d0 --- /dev/null +++ b/plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpHelper.java @@ -0,0 +1,106 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License + +package org.apache.cloudstack.alert.snmp; + +import com.cloud.utils.exception.CloudRuntimeException; +import org.snmp4j.CommunityTarget; +import org.snmp4j.PDU; +import org.snmp4j.Snmp; +import org.snmp4j.mp.SnmpConstants; +import org.snmp4j.smi.OID; +import org.snmp4j.smi.OctetString; +import org.snmp4j.smi.UdpAddress; +import org.snmp4j.smi.UnsignedInteger32; +import org.snmp4j.smi.VariableBinding; +import org.snmp4j.transport.DefaultUdpTransportMapping; + +import java.io.IOException; + +public class SnmpHelper { + private Snmp _snmp; + private CommunityTarget _target; + + public SnmpHelper(String address, String community) { + _target = new CommunityTarget(); + _target.setCommunity(new OctetString(community)); + _target.setVersion(SnmpConstants.version2c); + _target.setAddress(new UdpAddress(address)); + try { + _snmp = new Snmp(new DefaultUdpTransportMapping()); + } catch (IOException e) { + _snmp = null; + throw new CloudRuntimeException(" Error in crearting snmp object, " + e.getMessage()); + } + } + + public void sendSnmpTrap(SnmpTrapInfo snmpTrapInfo) { + try { + if (_snmp != null) { + _snmp.send(createPDU(snmpTrapInfo), _target, null, null); + } + } catch (IOException e) { + throw new CloudRuntimeException(" Error in sending SNMP Trap, " + e.getMessage()); + } + } + + private PDU createPDU(SnmpTrapInfo snmpTrapInfo) { + PDU trap = new PDU(); + trap.setType(PDU.TRAP); + + int alertType = snmpTrapInfo.getAlertType() + 1; + if (alertType > 0) { + trap.add(new VariableBinding(SnmpConstants.snmpTrapOID, getOID(CsSnmpConstants.TRAPS_PREFIX + alertType))); + if (snmpTrapInfo.getDataCenterId() != 0) { + trap.add(new VariableBinding(getOID(CsSnmpConstants.DATA_CENTER_ID), + new UnsignedInteger32(snmpTrapInfo.getDataCenterId()))); + } + + if (snmpTrapInfo.getPodId() != 0) { + trap.add(new VariableBinding(getOID(CsSnmpConstants.POD_ID), new UnsignedInteger32(snmpTrapInfo + .getPodId()))); + } + + if (snmpTrapInfo.getClusterId() != 0) { + trap.add(new VariableBinding(getOID(CsSnmpConstants.CLUSTER_ID), new UnsignedInteger32(snmpTrapInfo + .getClusterId()))); + } + + if (snmpTrapInfo.getMessage() != null) { + trap.add(new VariableBinding(getOID(CsSnmpConstants.MESSAGE), new OctetString(snmpTrapInfo.getMessage + ()))); + } else { + throw new CloudRuntimeException(" What is the use of alert without message "); + } + + if (snmpTrapInfo.getGenerationTime() != null) { + trap.add(new VariableBinding(getOID(CsSnmpConstants.GENERATION_TIME), + new OctetString(snmpTrapInfo.getGenerationTime().toString()))); + } else { + trap.add(new VariableBinding(getOID(CsSnmpConstants.GENERATION_TIME))); + } + } else { + throw new CloudRuntimeException(" Invalid alert Type "); + } + + return trap; + } + + private OID getOID(String oidString) { + return new OID(oidString); + } +} \ No newline at end of file diff --git a/plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpTrapAppender.java b/plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpTrapAppender.java new file mode 100644 index 00000000000..eaa4a132b7e --- /dev/null +++ b/plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpTrapAppender.java @@ -0,0 +1,207 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License + +package org.apache.cloudstack.alert.snmp; + +import com.cloud.utils.net.NetUtils; +import org.apache.log4j.AppenderSkeleton; +import org.apache.log4j.spi.ErrorCode; +import org.apache.log4j.spi.LoggingEvent; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +public class SnmpTrapAppender extends AppenderSkeleton { + private String _delimiter = ","; + private String _snmpManagerIpAddresses; + private String _snmpManagerPorts; + private String _snmpManagerCommunities; + + private String _oldSnmpManagerIpAddresses = null; + private String _oldSnmpManagerPorts = null; + private String _oldSnmpManagerCommunities = null; + + private List _ipAddresses = null; + private List _communities = null; + private List _ports = null; + + List _snmpHelpers = new ArrayList(); + + @Override + protected void append(LoggingEvent event) { + SnmpEnhancedPatternLayout snmpEnhancedPatternLayout; + + if (getLayout() == null) { + errorHandler.error("No layout set for the Appender named [" + getName() + ']', null, + ErrorCode.MISSING_LAYOUT); + return; + } + + if (getLayout() instanceof SnmpEnhancedPatternLayout) { + snmpEnhancedPatternLayout = (SnmpEnhancedPatternLayout) getLayout(); + } else { + return; + } + + if (!isAsSevereAsThreshold(event.getLevel())) { + return; + } + + SnmpTrapInfo snmpTrapInfo = snmpEnhancedPatternLayout.parseEvent(event); + + if (snmpTrapInfo != null && !_snmpHelpers.isEmpty()) { + for (SnmpHelper helper : _snmpHelpers) { + try { + helper.sendSnmpTrap(snmpTrapInfo); + } catch (Exception e) { + errorHandler.error(e.getMessage()); + } + } + } + } + + void setSnmpHelpers() { + if (_snmpManagerIpAddresses == null || _snmpManagerIpAddresses.trim().isEmpty() || _snmpManagerCommunities == + null || _snmpManagerCommunities.trim().isEmpty() || _snmpManagerPorts == null || + _snmpManagerPorts.trim().isEmpty()) { + reset(); + return; + } + + if (_oldSnmpManagerIpAddresses != null && _oldSnmpManagerIpAddresses.equals(_snmpManagerIpAddresses) && + _oldSnmpManagerCommunities.equals(_snmpManagerCommunities) && + _oldSnmpManagerPorts.equals(_snmpManagerPorts)) { + return; + } + + _oldSnmpManagerIpAddresses = _snmpManagerIpAddresses; + _oldSnmpManagerPorts = _snmpManagerPorts; + _oldSnmpManagerCommunities = _snmpManagerCommunities; + + _ipAddresses = parse(_snmpManagerIpAddresses); + _communities = parse(_snmpManagerCommunities); + _ports = parse(_snmpManagerPorts); + + if (!(_ipAddresses.size() == _communities.size() && _ipAddresses.size() == _ports.size())) { + reset(); + errorHandler.error(" size of ip addresses , communities, " + "and ports list doesn't match, " + + "setting all to null"); + return; + } + + if (!validateIpAddresses() || !validatePorts()) { + reset(); + errorHandler.error(" Invalid format for the IP Addresses or Ports parameter "); + return; + } + + String address; + + for (int i = 0; i < _ipAddresses.size(); i++) { + address = _ipAddresses.get(i) + "/" + _ports.get(i); + try { + _snmpHelpers.add(new SnmpHelper(address, _communities.get(i))); + } catch (Exception e) { + errorHandler.error(e.getMessage()); + } + } + } + + private void reset() { + _ipAddresses = null; + _communities = null; + _ports = null; + _snmpHelpers.clear(); + } + + @Override + public void close() { + if (!closed) closed = true; + } + + @Override + public boolean requiresLayout() { + return true; + } + + private List parse(String str) { + List result = new ArrayList(); + + final StringTokenizer tokenizer = new StringTokenizer(str, _delimiter); + while (tokenizer.hasMoreTokens()) { + result.add(tokenizer.nextToken().trim()); + } + return result; + } + + private boolean validatePorts() { + for (String port : _ports) { + if (!NetUtils.isValidPort(port)) { + return false; + } + } + return true; + } + + private boolean validateIpAddresses() { + for (String ipAddress : _ipAddresses) { + if (ipAddress.trim().equalsIgnoreCase("localhost")) { + continue; + } + if (!NetUtils.isValidIp(ipAddress)) { + return false; + } + } + return true; + } + + public String getSnmpManagerIpAddresses() { + return _snmpManagerIpAddresses; + } + + public void setSnmpManagerIpAddresses(String snmpManagerIpAddresses) { + this._snmpManagerIpAddresses = snmpManagerIpAddresses; + setSnmpHelpers(); + } + + public String getSnmpManagerPorts() { + return _snmpManagerPorts; + } + + public void setSnmpManagerPorts(String snmpManagerPorts) { + this._snmpManagerPorts = snmpManagerPorts; + setSnmpHelpers(); + } + + public String getSnmpManagerCommunities() { + return _snmpManagerCommunities; + } + + public void setSnmpManagerCommunities(String snmpManagerCommunities) { + this._snmpManagerCommunities = snmpManagerCommunities; + setSnmpHelpers(); + } + + public String getDelimiter() { + return _delimiter; + } + + public void setDelimiter(String delimiter) { + this._delimiter = delimiter; + } +} \ No newline at end of file diff --git a/plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpTrapInfo.java b/plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpTrapInfo.java new file mode 100644 index 00000000000..71bfee02cb6 --- /dev/null +++ b/plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpTrapInfo.java @@ -0,0 +1,90 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License + +package org.apache.cloudstack.alert.snmp; + +import java.util.Date; + +public class SnmpTrapInfo { + private String message; + private long podId; + private long dataCenterId; + private long clusterId; + private Date generationTime; + private short alertType; + + public SnmpTrapInfo() { + } + + public SnmpTrapInfo(short alertType, long dataCenterId, long podId, long clusterId, String message, + Date generationTime) { + this.podId = podId; + this.alertType = alertType; + this.clusterId = clusterId; + this.dataCenterId = dataCenterId; + this.generationTime = generationTime; + this.message = message; + } + + public short getAlertType() { + return alertType; + } + + public void setAlertType(short alertType) { + this.alertType = alertType; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public long getPodId() { + return podId; + } + + public void setPodId(long podId) { + this.podId = podId; + } + + public long getDataCenterId() { + return dataCenterId; + } + + public void setDataCenterId(long dataCenterId) { + this.dataCenterId = dataCenterId; + } + + public long getClusterId() { + return clusterId; + } + + public void setClusterId(long clusterId) { + this.clusterId = clusterId; + } + + public Date getGenerationTime() { + return generationTime; + } + + public void setGenerationTime(Date generationTime) { + this.generationTime = generationTime; + } +} \ No newline at end of file diff --git a/plugins/alert-handlers/snmp-alerts/test/org/apache/cloudstack/alert/snmp/SnmpEnhancedPatternLayoutTest.java b/plugins/alert-handlers/snmp-alerts/test/org/apache/cloudstack/alert/snmp/SnmpEnhancedPatternLayoutTest.java new file mode 100644 index 00000000000..b903a1e18b9 --- /dev/null +++ b/plugins/alert-handlers/snmp-alerts/test/org/apache/cloudstack/alert/snmp/SnmpEnhancedPatternLayoutTest.java @@ -0,0 +1,90 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License + +package org.apache.cloudstack.alert.snmp; + +import org.apache.log4j.spi.LoggingEvent; +import org.junit.Before; +import org.junit.Test; + +import javax.naming.ConfigurationException; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class SnmpEnhancedPatternLayoutTest { + SnmpEnhancedPatternLayout _snmpEnhancedPatternLayout = new SnmpEnhancedPatternLayout(); + + @Before + public void setUp() throws ConfigurationException { + _snmpEnhancedPatternLayout.setKeyValueDelimiter("::"); + _snmpEnhancedPatternLayout.setPairDelimiter("//"); + } + + @Test + public void parseAlertTest() { + LoggingEvent event = mock(LoggingEvent.class); + setMessage(" alertType:: 14 // dataCenterId:: 1 // podId:: 1 // " + "clusterId:: null // message:: Management" + + " network CIDR is not configured originally. Set it default to 10.102.192.0/22", event); + SnmpTrapInfo info = _snmpEnhancedPatternLayout.parseEvent(event); + commonAssertions(info, "Management network CIDR is not configured originally. Set it default to 10.102.192" + + ".0/22"); + } + + @Test + public void ParseAlertWithPairDelimeterInMessageTest() { + LoggingEvent event = mock(LoggingEvent.class); + setMessage(" alertType:: 14 // dataCenterId:: 1 // podId:: 1 // " + "clusterId:: null // message:: Management" + + " //network CIDR is not configured originally. Set it default to 10.102.192.0/22", event); + SnmpTrapInfo info = _snmpEnhancedPatternLayout.parseEvent(event); + commonAssertions(info, "Management //network CIDR is not configured originally. Set it default to 10.102.192" + + ".0/22"); + } + + @Test + public void ParseAlertWithKeyValueDelimeterInMessageTest() { + LoggingEvent event = mock(LoggingEvent.class); + setMessage(" alertType:: 14 // dataCenterId:: 1 // podId:: 1 // " + "clusterId:: null // message:: Management" + + " ::network CIDR is not configured originally. Set it default to 10.102.192.0/22", event); + SnmpTrapInfo info = _snmpEnhancedPatternLayout.parseEvent(event); + commonAssertions(info, "Management ::network CIDR is not configured originally. Set it default to 10.102.192" + + ".0/22"); + } + + @Test + public void parseRandomTest() { + LoggingEvent event = mock(LoggingEvent.class); + when(event.getRenderedMessage()).thenReturn("Problem clearing email alert"); + assertNull(" Null value was expected ", _snmpEnhancedPatternLayout.parseEvent(event)); + } + + private void commonAssertions(SnmpTrapInfo info, String message) { + assertEquals(" alert type not as expected ", 14, info.getAlertType()); + assertEquals(" data center id not as expected ", 1, info.getDataCenterId()); + assertEquals(" pod id os not as expected ", 1, info.getPodId()); + assertEquals(" cluster id is not as expected ", 0, info.getClusterId()); + assertNotNull(" generation time is set to null", info.getGenerationTime()); + assertEquals(" message is not as expected ", message, info.getMessage()); + } + + private void setMessage(String message, LoggingEvent event) { + when(event.getRenderedMessage()).thenReturn(message); + } +} \ No newline at end of file diff --git a/plugins/alert-handlers/snmp-alerts/test/org/apache/cloudstack/alert/snmp/SnmpTrapAppenderTest.java b/plugins/alert-handlers/snmp-alerts/test/org/apache/cloudstack/alert/snmp/SnmpTrapAppenderTest.java new file mode 100644 index 00000000000..2a65d90acc2 --- /dev/null +++ b/plugins/alert-handlers/snmp-alerts/test/org/apache/cloudstack/alert/snmp/SnmpTrapAppenderTest.java @@ -0,0 +1,86 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License + +package org.apache.cloudstack.alert.snmp; + +import org.apache.log4j.spi.LoggingEvent; +import org.junit.Test; +import org.mockito.Mock; + +import java.util.List; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; +import static org.mockito.Mockito.mock; + +public class SnmpTrapAppenderTest { + SnmpTrapAppender _appender = new SnmpTrapAppender(); + LoggingEvent _event = mock(LoggingEvent.class); + SnmpEnhancedPatternLayout _snmpEnhancedPatternLayout = mock(SnmpEnhancedPatternLayout.class); + @Mock + List snmpHelpers; + + @Test + public void appendTest() { + _appender.setSnmpManagerIpAddresses("10.1.1.1,10.1.1.2"); + _appender.setSnmpManagerPorts("162,164"); + _appender.setSnmpManagerCommunities("public,snmp"); + + _appender.setSnmpHelpers(); + assertEquals(" error snmpHelper list size not as expected ", _appender._snmpHelpers.size(), 2); + } + + @Test + public void InvalidInputTest() { + _appender.setSnmpManagerIpAddresses("10.1.1.1,10.1.1.2"); + _appender.setSnmpManagerPorts("162,164"); + _appender.setSnmpManagerCommunities("public"); + + _appender.setSnmpHelpers(); + assertTrue(" list was expected to be empty", _appender._snmpHelpers.isEmpty()); + } + + @Test + public void InvalidIpInputTest() { + _appender.setSnmpManagerIpAddresses("10.1.1,10.1.1.2"); + _appender.setSnmpManagerPorts("162,164"); + _appender.setSnmpManagerCommunities("public,snmp"); + + _appender.setSnmpHelpers(); + assertTrue(" list was expected to be empty", _appender._snmpHelpers.isEmpty()); + } + + @Test + public void InvalidPortInputTest() { + _appender.setSnmpManagerIpAddresses("10.1.1,10.1.1.2"); + _appender.setSnmpManagerPorts("162,164897489978"); + _appender.setSnmpManagerCommunities("public,snmp"); + + _appender.setSnmpHelpers(); + assertTrue(" list was expected to be empty", _appender._snmpHelpers.isEmpty()); + } + + @Test + public void mismatchListLengthInputTest() { + _appender.setSnmpManagerIpAddresses("10.1.1"); + _appender.setSnmpManagerPorts("162,164"); + _appender.setSnmpManagerCommunities("public,snmp"); + + _appender.setSnmpHelpers(); + assertTrue(" list was expected to be empty", _appender._snmpHelpers.isEmpty()); + } +} \ No newline at end of file diff --git a/plugins/pom.xml b/plugins/pom.xml index 88f617b4560..5d31a72ee91 100755 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -57,6 +57,7 @@ network-elements/dns-notifier storage/image/s3 storage/volume/solidfire + alert-handlers/snmp-alerts diff --git a/server/src/com/cloud/alert/AlertManagerImpl.java b/server/src/com/cloud/alert/AlertManagerImpl.java index f8a8fd8b1b9..a45482fd4ef 100755 --- a/server/src/com/cloud/alert/AlertManagerImpl.java +++ b/server/src/com/cloud/alert/AlertManagerImpl.java @@ -84,6 +84,7 @@ import com.sun.mail.smtp.SMTPTransport; @Local(value={AlertManager.class}) public class AlertManagerImpl extends ManagerBase implements AlertManager { private static final Logger s_logger = Logger.getLogger(AlertManagerImpl.class.getName()); + private static final Logger s_alertsLogger = Logger.getLogger("org.apache.cloudstack.alerts"); private static final long INITIAL_CAPACITY_CHECK_DELAY = 30L * 1000L; // thirty seconds expressed in milliseconds @@ -256,6 +257,9 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager { try { if (_emailAlert != null) { _emailAlert.sendAlert(alertType, dataCenterId, podId, null, subject, body); + } else { + s_alertsLogger.warn(" alertType:: " + alertType + " // dataCenterId:: " + dataCenterId + " // podId:: " + + podId + " // clusterId:: " + null + " // message:: " + subject ); } } catch (Exception ex) { s_logger.error("Problem sending email alert", ex); @@ -789,6 +793,8 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager { // TODO: make sure this handles SSL transport (useAuth is true) and regular public void sendAlert(short alertType, long dataCenterId, Long podId, Long clusterId, String subject, String content) throws MessagingException, UnsupportedEncodingException { + s_alertsLogger.warn(" alertType:: " + alertType + " // dataCenterId:: " + dataCenterId + " // podId:: " + + podId + " // clusterId:: " + null + " // message:: " + subject); AlertVO alert = null; if ((alertType != AlertManager.ALERT_TYPE_HOST) && (alertType != AlertManager.ALERT_TYPE_USERVM) && diff --git a/usage/src/com/cloud/usage/UsageAlertManagerImpl.java b/usage/src/com/cloud/usage/UsageAlertManagerImpl.java index a0765b2b272..dc918b83b6d 100644 --- a/usage/src/com/cloud/usage/UsageAlertManagerImpl.java +++ b/usage/src/com/cloud/usage/UsageAlertManagerImpl.java @@ -50,11 +50,12 @@ import com.sun.mail.smtp.SMTPTransport; @Local(value={AlertManager.class}) public class UsageAlertManagerImpl extends ManagerBase implements AlertManager { private static final Logger s_logger = Logger.getLogger(UsageAlertManagerImpl.class.getName()); + private static final Logger s_alertsLogger = Logger.getLogger("org.apache.cloudstack.alerts"); private EmailAlert _emailAlert; @Inject private AlertDao _alertDao; @Inject private ConfigurationDao _configDao; - + @Override public boolean configure(String name, Map params) throws ConfigurationException { Map configs = _configDao.getConfiguration("management-server", params); @@ -101,6 +102,9 @@ public class UsageAlertManagerImpl extends ManagerBase implements AlertManager { try { if (_emailAlert != null) { _emailAlert.sendAlert(alertType, dataCenterId, podId, subject, body); + } else { + s_alertsLogger.warn(" alertType:: " + alertType + " // dataCenterId:: " + dataCenterId + " // podId:: " + + podId + " // clusterId:: " + null + " // message:: " + subject ); } } catch (Exception ex) { s_logger.error("Problem sending email alert", ex); @@ -171,18 +175,19 @@ public class UsageAlertManagerImpl extends ManagerBase implements AlertManager { // TODO: make sure this handles SSL transport (useAuth is true) and regular public void sendAlert(short alertType, long dataCenterId, Long podId, String subject, String content) throws MessagingException, UnsupportedEncodingException { + s_alertsLogger.warn(" alertType:: " + alertType + " // dataCenterId:: " + dataCenterId + " // podId:: " + + podId + " // clusterId:: " + null + " // message:: " + subject); AlertVO alert = null; - if ((alertType != AlertManager.ALERT_TYPE_HOST) && (alertType != AlertManager.ALERT_TYPE_USERVM) && (alertType != AlertManager.ALERT_TYPE_DOMAIN_ROUTER) && (alertType != AlertManager.ALERT_TYPE_CONSOLE_PROXY) && - (alertType != AlertManager.ALERT_TYPE_SSVM) && + (alertType != AlertManager.ALERT_TYPE_SSVM) && (alertType != AlertManager.ALERT_TYPE_STORAGE_MISC) && (alertType != AlertManager.ALERT_TYPE_MANAGMENT_NODE)) { alert = _alertDao.getLastAlert(alertType, dataCenterId, podId); } - + if (alert == null) { // set up a new alert AlertVO newAlert = new AlertVO(); From 6ba0ef1a17e70d64894f7f9b1d5baa886aab651c Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Mon, 18 Mar 2013 18:15:59 +0530 Subject: [PATCH 02/13] Removing the test tooltip from Pingpath variable --- ui/scripts/ui-custom/healthCheck.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/scripts/ui-custom/healthCheck.js b/ui/scripts/ui-custom/healthCheck.js index c4c84e5236b..ebb7e5a8903 100644 --- a/ui/scripts/ui-custom/healthCheck.js +++ b/ui/scripts/ui-custom/healthCheck.js @@ -73,7 +73,7 @@ form: { title: '', fields:{ - pingpath: {label: 'Ping Path', docID:'helpAccountUsername' , validation: {required: false}, defaultValue: pingpath1} + pingpath: {label: 'Ping Path', validation: {required: false}, defaultValue: pingpath1} } } }); From 2b05f546b7b882e61d54a653a8c5069be22b1be2 Mon Sep 17 00:00:00 2001 From: Min Chen Date: Fri, 15 Mar 2013 16:28:46 -0700 Subject: [PATCH 03/13] CLOUDSTACK-1690: Remove region_id from sql insert statement for inserting "system" and "admin" account and user in MS startup due to recent region feature change. --- .../cloud/server/ConfigurationServerImpl.java | 30 +++++++------------ 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index 8c665ad1eee..3b0ec0f943b 100755 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -106,10 +106,7 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; import com.cloud.utils.script.Script; import com.cloud.uuididentity.dao.IdentityDao; -import org.apache.cloudstack.region.RegionVO; -import org.apache.cloudstack.region.dao.RegionDao; -import org.apache.commons.codec.binary.Base64; -import org.apache.log4j.Logger; + @Component public class ConfigurationServerImpl extends ManagerBase implements ConfigurationServer { @@ -152,7 +149,7 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio public void persistDefaultValues() throws InternalErrorException { fixupScriptFileAttribute(); - + // Create system user and admin user saveUser(); @@ -337,23 +334,20 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio @DB protected void saveUser() { - int region_id = _configDao.getRegionId(); // insert system account - String insertSql = "INSERT INTO `cloud`.`account` (id, uuid, account_name, type, domain_id, region_id) VALUES (1, UUID(), 'system', '1', '1', ?)"; + String insertSql = "INSERT INTO `cloud`.`account` (id, uuid, account_name, type, domain_id) VALUES (1, UUID(), 'system', '1', '1')"; Transaction txn = Transaction.currentTxn(); try { PreparedStatement stmt = txn.prepareAutoCloseStatement(insertSql); - stmt.setInt(1, region_id); stmt.executeUpdate(); } catch (SQLException ex) { } // insert system user - insertSql = "INSERT INTO `cloud`.`user` (id, uuid, username, password, account_id, firstname, lastname, created, region_id)" + - " VALUES (1, UUID(), 'system', RAND(), 1, 'system', 'cloud', now(), ?)"; + insertSql = "INSERT INTO `cloud`.`user` (id, uuid, username, password, account_id, firstname, lastname, created)" + + " VALUES (1, UUID(), 'system', RAND(), 1, 'system', 'cloud', now())"; txn = Transaction.currentTxn(); try { PreparedStatement stmt = txn.prepareAutoCloseStatement(insertSql); - stmt.setInt(1, region_id); stmt.executeUpdate(); } catch (SQLException ex) { } @@ -366,23 +360,21 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio String lastname = "cloud"; // create an account for the admin user first - insertSql = "INSERT INTO `cloud`.`account` (id, uuid, account_name, type, domain_id, region_id) VALUES (" + id + ", UUID(), '" + username + "', '1', '1', ?)"; + insertSql = "INSERT INTO `cloud`.`account` (id, uuid, account_name, type, domain_id) VALUES (" + id + ", UUID(), '" + username + "', '1', '1')"; txn = Transaction.currentTxn(); try { PreparedStatement stmt = txn.prepareAutoCloseStatement(insertSql); - stmt.setInt(1, region_id); stmt.executeUpdate(); } catch (SQLException ex) { } // now insert the user - insertSql = "INSERT INTO `cloud`.`user` (id, uuid, username, password, account_id, firstname, lastname, created, state, region_id) " + - "VALUES (" + id + ", UUID(), '" + username + "', RAND(), 2, '" + firstname + "','" + lastname + "',now(), 'disabled', ?)"; + insertSql = "INSERT INTO `cloud`.`user` (id, uuid, username, password, account_id, firstname, lastname, created, state) " + + "VALUES (" + id + ", UUID(), '" + username + "', RAND(), 2, '" + firstname + "','" + lastname + "',now(), 'disabled')"; txn = Transaction.currentTxn(); try { PreparedStatement stmt = txn.prepareAutoCloseStatement(insertSql); - stmt.setInt(1, region_id); stmt.executeUpdate(); } catch (SQLException ex) { } @@ -708,15 +700,15 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio } } - + private void fixupScriptFileAttribute() { - // TODO : this is a hacking fix to workaround that executable bit is not preserved in WAR package + // TODO : this is a hacking fix to workaround that executable bit is not preserved in WAR package String scriptPath = Script.findScript("", "scripts/vm/systemvm/injectkeys.sh"); if(scriptPath != null) { File file = new File(scriptPath); if(!file.canExecute()) { s_logger.info("Some of the shell script files may not have executable bit set. Fixup..."); - + String cmd = "chmod ugo+x " + scriptPath; s_logger.info("Executing " + cmd); String result = Script.runSimpleBashScript(cmd); From d9b85e397d10f2291058ff972094decd8fc4ad7d Mon Sep 17 00:00:00 2001 From: Prachi Damle Date: Mon, 18 Mar 2013 12:03:57 -0700 Subject: [PATCH 04/13] CLOUDSTACK-1706 Failed to deploy VM with error "cannot find DeployPlannerSelector" Changes: - Regular plugin/adapter components should usually be loaded at run level RUNLEVEL_COMPONENT(5) - HypervisorVmPlannerSelector was at level 0, while configurationServer at level 2 - causing config to be not loaded for the HypervisorVmPlannerSelector --- .../src/com/cloud/deploy/HypervisorVmPlannerSelector.java | 8 ++++++++ utils/src/com/cloud/utils/component/AdapterBase.java | 4 +++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/server/src/com/cloud/deploy/HypervisorVmPlannerSelector.java b/server/src/com/cloud/deploy/HypervisorVmPlannerSelector.java index 8b2a1441151..0f454cdb582 100755 --- a/server/src/com/cloud/deploy/HypervisorVmPlannerSelector.java +++ b/server/src/com/cloud/deploy/HypervisorVmPlannerSelector.java @@ -18,12 +18,16 @@ package com.cloud.deploy; import javax.ejb.Local; +import org.apache.log4j.Logger; + import com.cloud.deploy.DeploymentPlanner.AllocationAlgorithm; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.vm.UserVmVO; @Local(value = {DeployPlannerSelector.class}) public class HypervisorVmPlannerSelector extends AbstractDeployPlannerSelector { + private static final Logger s_logger = Logger.getLogger(HypervisorVmPlannerSelector.class); + @Override public String selectPlanner(UserVmVO vm) { if (vm.getHypervisorType() != HypervisorType.BareMetal) { @@ -38,6 +42,10 @@ public class HypervisorVmPlannerSelector extends AbstractDeployPlannerSelector { || _allocationAlgorithm.equals(AllocationAlgorithm.userconcentratedpod_firstfit.toString())) { return "UserConcentratedPodPlanner"; } + } else { + if (s_logger.isDebugEnabled()) { + s_logger.debug("The allocation algorithm is null, cannot select the planner"); + } } } diff --git a/utils/src/com/cloud/utils/component/AdapterBase.java b/utils/src/com/cloud/utils/component/AdapterBase.java index a8f4f468090..ea5e9611ab6 100644 --- a/utils/src/com/cloud/utils/component/AdapterBase.java +++ b/utils/src/com/cloud/utils/component/AdapterBase.java @@ -22,8 +22,10 @@ import java.util.List; public class AdapterBase extends ComponentLifecycleBase implements Adapter { public AdapterBase() { + // set default run level for adapter components + setRunLevel(ComponentLifecycle.RUN_LEVEL_COMPONENT); } - + public static T getAdapterByName(List adapters, String name) { for(T adapter : adapters) { if(adapter.getName() != null && adapter.getName().equalsIgnoreCase(name)) From fb94b72213bf96f2878b90260067f61629c6a956 Mon Sep 17 00:00:00 2001 From: Kelven Yang Date: Mon, 18 Mar 2013 18:05:09 -0700 Subject: [PATCH 05/13] CLOUDSTACK-1568,CLOUDSTACK-1664: Fix ActionEvent interception and optimize @DB lookup with caching --- .../cloud/event/ActionEventInterceptor.java | 15 +++- .../ConsoleProxyHttpHandlerHelper.java | 14 ++- .../component/ComponentMethodProxyCache.java | 90 +++++++++++++++++++ .../component/SpringComponentScanUtils.java | 1 - .../utils/db/TransactionContextBuilder.java | 14 ++- 5 files changed, 119 insertions(+), 15 deletions(-) create mode 100644 utils/src/com/cloud/utils/component/ComponentMethodProxyCache.java diff --git a/server/src/com/cloud/event/ActionEventInterceptor.java b/server/src/com/cloud/event/ActionEventInterceptor.java index fb89498ffce..a6c2565510e 100644 --- a/server/src/com/cloud/event/ActionEventInterceptor.java +++ b/server/src/com/cloud/event/ActionEventInterceptor.java @@ -19,22 +19,29 @@ package com.cloud.event; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; +import org.apache.log4j.Logger; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.reflect.MethodSignature; import com.cloud.user.UserContext; +import com.cloud.utils.component.ComponentMethodProxyCache; public class ActionEventInterceptor { + private static final Logger s_logger = Logger.getLogger(ActionEventInterceptor.class); public ActionEventInterceptor() { } public Object AroundAnyMethod(ProceedingJoinPoint call) throws Throwable { MethodSignature methodSignature = (MethodSignature)call.getSignature(); - Method targetMethod = methodSignature.getMethod(); - if(needToIntercept(targetMethod)) { + + // Note: AOP for ActionEvent is triggered annotation, no need to check the annotation on method again + Method targetMethod = ComponentMethodProxyCache.getTargetMethod( + methodSignature.getMethod(), call.getTarget()); + + if(targetMethod != null) { EventVO event = interceptStart(targetMethod); - + boolean success = true; Object ret = null; try { @@ -49,6 +56,8 @@ public class ActionEventInterceptor { } } return ret; + } else { + s_logger.error("Unable to find the proxied method behind. Method: " + methodSignature.getMethod().getName()); } return call.proceed(); } diff --git a/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxyHttpHandlerHelper.java b/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxyHttpHandlerHelper.java index 6815b0d43bc..297e71118ad 100644 --- a/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxyHttpHandlerHelper.java +++ b/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxyHttpHandlerHelper.java @@ -53,7 +53,7 @@ public class ConsoleProxyHttpHandlerHelper { ConsoleProxyClientParam param = encryptor.decryptObject(ConsoleProxyClientParam.class, map.get("token")); // make sure we get information from token only - map.clear(); + guardUserInput(map); if(param != null) { if(param.getClientHostAddress() != null) map.put("host", param.getClientHostAddress()); @@ -72,9 +72,19 @@ public class ConsoleProxyHttpHandlerHelper { } } else { // we no longer accept information from parameter other than token - map.clear(); + guardUserInput(map); } return map; } + + private static void guardUserInput(Map map) { + map.remove("host"); + map.remove("port"); + map.remove("tag"); + map.remove("sid"); + map.remove("consoleurl"); + map.remove("sessionref"); + map.remove("ticket"); + } } diff --git a/utils/src/com/cloud/utils/component/ComponentMethodProxyCache.java b/utils/src/com/cloud/utils/component/ComponentMethodProxyCache.java new file mode 100644 index 00000000000..ea3b68573cf --- /dev/null +++ b/utils/src/com/cloud/utils/component/ComponentMethodProxyCache.java @@ -0,0 +1,90 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package com.cloud.utils.component; + +import java.lang.ref.WeakReference; +import java.lang.reflect.Method; +import java.util.WeakHashMap; + +public class ComponentMethodProxyCache { + + private static WeakHashMap> s_cache = new WeakHashMap>(); + + public ComponentMethodProxyCache() { + } + + public static Method getTargetMethod(Method method, Object target) { + synchronized(s_cache) { + WeakReference targetMethod = s_cache.get(new TargetKey(method, target)); + if(targetMethod != null && targetMethod.get() != null) + return targetMethod.get(); + + Class clazz = target.getClass(); + for(Method m : clazz.getMethods()) { + if(isMethodMatched(method, m)) { + s_cache.put(new TargetKey(method, target), new WeakReference(m)); + return m; + } + } + + return method; + } + } + + private static boolean isMethodMatched(Method m1, Method m2) { + if(!m1.getName().equals(m2.getName())) + return false; + + Class[] params1 = m1.getParameterTypes(); + Class[] params2 = m2.getParameterTypes(); + + if(params1.length != params2.length) + return false; + + for(int i = 0; i < params1.length; i++) { + if(!params1[i].isAssignableFrom(params2[i])) + return false; + } + + return true; + } + + public static class TargetKey { + Method _method; + Object _target; + + public TargetKey(Method method, Object target) { + _method = method; + _target = target; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof TargetKey)) + return false; + + // for target object, we just check the reference + return _method.equals(((TargetKey)obj)._method) && + _target == ((TargetKey)obj)._target; + } + + public int hashCode() { + return _target.hashCode() ^ _target.hashCode(); + } + } +} diff --git a/utils/src/com/cloud/utils/component/SpringComponentScanUtils.java b/utils/src/com/cloud/utils/component/SpringComponentScanUtils.java index fda11b74609..9a85c79fa80 100644 --- a/utils/src/com/cloud/utils/component/SpringComponentScanUtils.java +++ b/utils/src/com/cloud/utils/component/SpringComponentScanUtils.java @@ -38,5 +38,4 @@ public class SpringComponentScanUtils { } return false; } - } diff --git a/utils/src/com/cloud/utils/db/TransactionContextBuilder.java b/utils/src/com/cloud/utils/db/TransactionContextBuilder.java index e03b25f912d..7ca33ab5f5d 100644 --- a/utils/src/com/cloud/utils/db/TransactionContextBuilder.java +++ b/utils/src/com/cloud/utils/db/TransactionContextBuilder.java @@ -22,9 +22,10 @@ import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.apache.log4j.Logger; import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.Signature; import org.aspectj.lang.reflect.MethodSignature; +import com.cloud.utils.component.ComponentMethodProxyCache; + public class TransactionContextBuilder implements MethodInterceptor { private static final Logger s_logger = Logger.getLogger(TransactionContextBuilder.class); public TransactionContextBuilder() { @@ -72,14 +73,9 @@ public class TransactionContextBuilder implements MethodInterceptor { Class clazz = method.getDeclaringClass(); if(clazz.isInterface()) { clazz = target.getClass(); - for(Method m : clazz.getMethods()) { - // it is supposed that we need to check against type arguments, - // this can be simplified by just checking method name - if(m.getName().equals(method.getName())) { - if(m.getAnnotation(DB.class) != null) - return true; - } - } + Method targetMethod = ComponentMethodProxyCache.getTargetMethod(method, target); + if(targetMethod != null && targetMethod.getAnnotation(DB.class) != null) + return true; } do { From beb15af0f267c59b7e070d279e1df960701b6cf6 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Tue, 19 Mar 2013 12:21:19 +0530 Subject: [PATCH 06/13] CLOUDSTACK-1720: Add upgrade paths from 4.0.x to 4.2.0 Signed-off-by: Rohit Yadav --- server/src/com/cloud/upgrade/DatabaseUpgradeChecker.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/src/com/cloud/upgrade/DatabaseUpgradeChecker.java b/server/src/com/cloud/upgrade/DatabaseUpgradeChecker.java index 5bd749fe842..8f9be0f5d57 100755 --- a/server/src/com/cloud/upgrade/DatabaseUpgradeChecker.java +++ b/server/src/com/cloud/upgrade/DatabaseUpgradeChecker.java @@ -162,6 +162,10 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker { _upgradeMap.put("4.0.0", new DbUpgrade[] { new Upgrade40to41(), new Upgrade410to420() }); + _upgradeMap.put("4.0.1", new DbUpgrade[] { new Upgrade40to41(), new Upgrade410to420() }); + + _upgradeMap.put("4.0.2", new DbUpgrade[] { new Upgrade40to41(), new Upgrade410to420() }); + _upgradeMap.put("4.1.0", new DbUpgrade[] { new Upgrade410to420() }); } From 19d1a30360750df280e46e1da5cf138625243852 Mon Sep 17 00:00:00 2001 From: Pranav Saxena Date: Tue, 19 Mar 2013 15:35:31 +0530 Subject: [PATCH 07/13] Dv switch UI space removal changes --- ui/scripts/system.js | 4 ++-- ui/scripts/zoneWizard.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 4d529aeb04e..c0a5d141700 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -7597,7 +7597,7 @@ if(vSwitchEnabled) { - items.push({ id:" nexusdvs" , description: "Cisco Nexus 1000v Distributed Virtual Switch"}); + items.push({ id:"nexusdvs" , description: "Cisco Nexus 1000v Distributed Virtual Switch"}); items.push({id: "vmwaresvs", description: "VMware vNetwork Standard Virtual Switch"}); items.push({id: "vmwaredvs", description: "VMware vNetwork Distributed Virtual Switch"}); @@ -7610,7 +7610,7 @@ else{ items.push({id: "vmwaredvs", description: "VMware vNetwork Distributed Virtual Switch"}); items.push({id: "vmwaresvs", description: "VMware vNetwork Standard Virtual Switch"}); - items.push({ id:" nexusdvs" , description: "Cisco Nexus 1000v Distributed Virtual Switch"}); + items.push({ id:"nexusdvs" , description: "Cisco Nexus 1000v Distributed Virtual Switch"}); } args.response.success({data: items}); diff --git a/ui/scripts/zoneWizard.js b/ui/scripts/zoneWizard.js index 47932664927..5108c5c0c3b 100755 --- a/ui/scripts/zoneWizard.js +++ b/ui/scripts/zoneWizard.js @@ -897,7 +897,7 @@ if(vSwitchEnabled) { - items.push({ id:" nexusdvs" , description: "Cisco Nexus 1000v Distributed Virtual Switch"}); + items.push({ id:"nexusdvs" , description: "Cisco Nexus 1000v Distributed Virtual Switch"}); items.push({id: "vmwaresvs", description: "VMware vNetwork Standard Virtual Switch"}); items.push({id: "vmwaredvs", description: "VMware vNetwork Distributed Virtual Switch"}); @@ -909,9 +909,9 @@ // items.push({id: " ", description: " "}); else{ - items.push({id: "vmwaredvs", description: "VMware vNetwork Distributed Virtual Switch"}); - items.push({id: "vmwaresvs", description: "VMware vNetwork Standard Virtual Switch"}); - items.push({ id:" nexusdvs" , description: "Cisco Nexus 1000v Distributed Virtual Switch"}); + items.push({id:"vmwaredvs", description: "VMware vNetwork Distributed Virtual Switch"}); + items.push({ id: "vmwaresvs", description: "VMware vNetwork Standard Virtual Switch"}); + items.push({ id:"nexusdvs" , description: "Cisco Nexus 1000v Distributed Virtual Switch"}); } args.response.success({data: items}); From 93bc669a0e2fdfc5860e72113e7a51866c93ab2c Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Tue, 19 Mar 2013 15:34:20 +0530 Subject: [PATCH 08/13] cli: Pass config file by value in cloudmonkey's config Signed-off-by: Rohit Yadav --- tools/cli/cloudmonkey/config.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tools/cli/cloudmonkey/config.py b/tools/cli/cloudmonkey/config.py index 6a5feab8d12..4a4aa99cdc8 100644 --- a/tools/cli/cloudmonkey/config.py +++ b/tools/cli/cloudmonkey/config.py @@ -19,6 +19,12 @@ # Use following rules for versioning: # - __version__ = "4.1.0-0" +__description__ = "Command Line Interface for Apache CloudStack" +__maintainer__ = "Rohit Yadav" +__maintaineremail__ = "bhaisaab@apache.org" +__project__ = "The Apache CloudStack Team" +__projectemail__ = "cloudstack-dev@incubator.apache.org" +__projecturl__ = "http://incubator.apache.org/cloudstack" try: import os @@ -36,14 +42,14 @@ iterable_type = ['set', 'list', 'object'] config_dir = expanduser('~/.cloudmonkey') config_file = expanduser(config_dir + '/config') -cache_file = expanduser(config_dir + '/cache') # cloudmonkey config fields -config_fields = {'core': {}, 'ui': {}, 'server': {}, 'user': {}} +config_fields = {'core': {}, 'server': {}, 'user': {}, 'ui': {}} # core config_fields['core']['asyncblock'] = 'true' config_fields['core']['paramcompletion'] = 'false' +config_fields['core']['cache_file'] = expanduser(config_dir + '/cache') config_fields['core']['history_file'] = expanduser(config_dir + '/history') config_fields['core']['log_file'] = expanduser(config_dir + '/log') @@ -64,8 +70,8 @@ config_fields['user']['apikey'] = '' config_fields['user']['secretkey'] = '' -def write_config(get_attr, first_time=False): - global config_fields, config_file +def write_config(get_attr, config_file, first_time=False): + global config_fields config = ConfigParser() for section in config_fields.keys(): config.add_section(section) @@ -79,8 +85,8 @@ def write_config(get_attr, first_time=False): return config -def read_config(get_attr, set_attr): - global config_fields, config_dir, config_file +def read_config(get_attr, set_attr, config_file): + global config_fields, config_dir if not os.path.exists(config_dir): os.makedirs(config_dir) @@ -95,7 +101,7 @@ def read_config(get_attr, set_attr): except IOError, e: print "Error: config_file not found", e else: - config = write_config(get_attr, True) + config = write_config(get_attr, config_file, True) print "Welcome! Using `set` configure the necessary settings:" print " ".join(sorted(config_options)) print "Config file:", config_file From e28aa09f01fcaf6abd806ab94d962563e1fba6c2 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Tue, 19 Mar 2013 15:47:51 +0530 Subject: [PATCH 09/13] cli: cachemaker should import config and not the field Signed-off-by: Rohit Yadav --- tools/cli/cloudmonkey/cachemaker.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/cli/cloudmonkey/cachemaker.py b/tools/cli/cloudmonkey/cachemaker.py index 42a077ad928..8ac123caa4b 100644 --- a/tools/cli/cloudmonkey/cachemaker.py +++ b/tools/cli/cloudmonkey/cachemaker.py @@ -21,7 +21,7 @@ try: import os import types - from config import cache_file + from config import config_fields except ImportError, e: import sys print "ImportError", e @@ -168,6 +168,7 @@ def main(json_file): f.close() if __name__ == "__main__": + cache_file = config_fields['core']['cache_file'] print "[cachemaker] Pre-caching using user's cloudmonkey cache", cache_file if os.path.exists(cache_file): main(cache_file) From 4421f2bb60ea44a6b28593eb7e0254d5108919ff Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Tue, 19 Mar 2013 15:49:42 +0530 Subject: [PATCH 10/13] CLOUDSTACK-1708: Let cloudmonkey accept cfg passed in cmd line The patch adds feature in cloudmonkey to have multiple profiles by passing custom cfg file to set custom profile in both interactive shell and cmd line tool use cases. Signed-off-by: Rohit Yadav --- tools/cli/cloudmonkey/cloudmonkey.py | 47 +++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/tools/cli/cloudmonkey/cloudmonkey.py b/tools/cli/cloudmonkey/cloudmonkey.py index 25422412613..f88632d828c 100644 --- a/tools/cli/cloudmonkey/cloudmonkey.py +++ b/tools/cli/cloudmonkey/cloudmonkey.py @@ -29,8 +29,9 @@ try: import types from cachemaker import loadcache, savecache, monkeycache, splitverbsubject - from config import __version__, cache_file - from config import read_config, write_config + from config import __version__, __description__, __projecturl__ + from config import read_config, write_config, config_file + from optparse import OptionParser from prettytable import PrettyTable from printer import monkeyprint from requester import monkeyrequest @@ -63,13 +64,14 @@ class CloudMonkeyShell(cmd.Cmd, object): intro = ("☁ Apache CloudStack 🐵 cloudmonkey " + __version__ + ". Type help or ? to list commands.\n") ruler = "=" - cache_file = cache_file config_options = [] verbs = [] - def __init__(self, pname): + def __init__(self, pname, cfile): self.program_name = pname - self.config_options = read_config(self.get_attr, self.set_attr) + self.config_file = cfile + self.config_options = read_config(self.get_attr, self.set_attr, + self.config_file) self.loadcache() self.prompt = self.prompt.strip() + " " # Cosmetic fix for prompt @@ -364,7 +366,7 @@ class CloudMonkeyShell(cmd.Cmd, object): key, value = (args[0], args[2]) setattr(self, key, value) # keys and attributes should have same names self.prompt = self.prompt.strip() + " " # prompt fix - write_config(self.get_attr) + write_config(self.get_attr, self.config_file) def complete_set(self, text, line, begidx, endidx): mline = line.partition(" ")[2] @@ -458,10 +460,39 @@ class CloudMonkeyShell(cmd.Cmd, object): return self.do_EOF(args) +class MonkeyParser(OptionParser): + def format_help(self, formatter=None): + if formatter is None: + formatter = self.formatter + result = [] + if self.usage: + result.append("Usage: cloudmonkey [options] [cmds] [params]\n\n") + if self.description: + result.append(self.format_description(formatter) + "\n") + result.append(self.format_option_help(formatter)) + result.append("\nTry cloudmonkey [help|?]\n") + return "".join(result) + + def main(): - shell = CloudMonkeyShell(sys.argv[0]) + parser = MonkeyParser() + parser.add_option("-c", "--config-file", + dest="cfile", default=config_file, + help="config file for cloudmonkey", metavar="FILE") + parser.add_option("-v", "--version", + action="store_true", dest="version", default=False, + help="prints cloudmonkey version information") + + (options, args) = parser.parse_args() + print 'args', args + print 'options', options + if options.version: + print "cloudmonkey", __version__ + print __description__, "(%s)" % __projecturl__ + + shell = CloudMonkeyShell(sys.argv[0], options.cfile) if len(sys.argv) > 1: - shell.onecmd(' '.join(sys.argv[1:])) + shell.onecmd(' '.join(args)) else: shell.cmdloop() From 19a290500e17765a67eddc0d61769e483ee3d7f7 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Tue, 19 Mar 2013 15:52:03 +0530 Subject: [PATCH 11/13] cli: Import project info from config in setup.py, fix debug msgs Signed-off-by: Rohit Yadav lsdfjk Signed-off-by: Rohit Yadav --- tools/cli/cloudmonkey/__init__.py | 4 +++- tools/cli/cloudmonkey/cloudmonkey.py | 2 -- tools/cli/setup.py | 34 +++++++++++++--------------- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/tools/cli/cloudmonkey/__init__.py b/tools/cli/cloudmonkey/__init__.py index e4c4e6d24f1..cf689e79480 100644 --- a/tools/cli/cloudmonkey/__init__.py +++ b/tools/cli/cloudmonkey/__init__.py @@ -16,6 +16,8 @@ # under the License. try: - from config import __version__ + from config import __version__, __description__ + from config import __maintainer__, __maintaineremail__ + from config import __project__, __projecturl__, __projectemail__ except ImportError, e: print e diff --git a/tools/cli/cloudmonkey/cloudmonkey.py b/tools/cli/cloudmonkey/cloudmonkey.py index f88632d828c..f750c3afa8d 100644 --- a/tools/cli/cloudmonkey/cloudmonkey.py +++ b/tools/cli/cloudmonkey/cloudmonkey.py @@ -484,8 +484,6 @@ def main(): help="prints cloudmonkey version information") (options, args) = parser.parse_args() - print 'args', args - print 'options', options if options.version: print "cloudmonkey", __version__ print __description__, "(%s)" % __projecturl__ diff --git a/tools/cli/setup.py b/tools/cli/setup.py index 9624115ed5f..4c7b2978b2f 100644 --- a/tools/cli/setup.py +++ b/tools/cli/setup.py @@ -22,13 +22,9 @@ except ImportError: use_setuptools() from setuptools import setup, find_packages -from cloudmonkey import __version__ - -name = 'cloudmonkey' -version = __version__ -requires = ['Pygments>=1.5', - 'prettytable>=0.6', - ] +from cloudmonkey import __version__, __description__ +from cloudmonkey import __maintainer__, __maintaineremail__ +from cloudmonkey import __project__, __projecturl__, __projectemail__ try: import readline @@ -36,20 +32,22 @@ except ImportError: requires.append('readline') setup( - name = name, - version = version, - author = "The Apache CloudStack Team", - author_email = "cloudstack-dev@incubator.apache.org", - maintainer = "Rohit Yadav", - maintainer_email = "bhaisaab@apache.org", - url = "http://incubator.apache.org/cloudstack", - description = "Command Line Interface for Apache CloudStack", - long_description = "cloudmonkey is a command line interface for Apache " - "CloudStack powered by CloudStack Marvin", + name = 'cloudmonkey', + version = __version__, + author = __project__, + author_email = __projectemail__, + maintainer = __maintainer__, + maintainer_email = __maintaineremail__, + url = __projecturl__, + description = __description__, + long_description = "cloudmonkey is a CLI for Apache CloudStack", platforms = ("Any",), license = 'ASL 2.0', packages = find_packages(), - install_requires = requires, + install_requires = [ + 'Pygments>=1.5', + 'prettytable>=0.6', + ], include_package_data = True, zip_safe = False, classifiers = [ From c02ab3f4d7a502eadca76026bdeeec40f00ca8ee Mon Sep 17 00:00:00 2001 From: Anshul Gangwar Date: Tue, 19 Mar 2013 16:08:11 +0530 Subject: [PATCH 12/13] CLOUDSTACK-1723:Fix for dashboard alerts --- ui/scripts/sharedFunctions.js | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js index ad26b34196e..8bcdff91574 100644 --- a/ui/scripts/sharedFunctions.js +++ b/ui/scripts/sharedFunctions.js @@ -400,20 +400,28 @@ cloudStack.converters = { case 4 : return _l('label.public.ips'); case 5 : return _l('label.management.ips'); case 6 : return _l('label.secondary.storage'); - case 7 : return _l('label.vlan'); - case 8 : return _l('label.direct.ips'); - case 9 : return _l('label.local.storage'); + case 7 : return _l('label.host'); + case 9 : return _l('label.domain.router'); + case 10 : return _l('label.console.proxy'); - // These are old values -- can be removed in the future - case 10 : return "Routing Host"; - case 11 : return "Storage"; - case 12 : return "Usage Server"; - case 13 : return "Management Server"; - case 14 : return "Domain Router"; - case 15 : return "Console Proxy"; - case 16 : return "User VM"; - case 17 : return "VLAN"; - case 18 : return "Secondary Storage VM"; + // These are old values -- can be removed in the future + case 8 : return "User VM"; + case 11 : return "Routing Host"; + case 12 : return "Storage"; + case 13 : return "Usage Server"; + case 14 : return "Management Server"; + case 15 : return "Domain Router"; + case 16 : return "Console Proxy"; + case 17 : return "User VM"; + case 18 : return "VLAN"; + case 19 : return "Secondary Storage VM"; + case 20 : return "Usage Server"; + case 21 : return "Storage"; + case 22 : return "Update Resource Count"; + case 23 : return "Usage Sanity Result"; + case 24 : return "Direct Attached Public IP"; + case 25 : return "Local Storage"; + case 26 : return "Resource Limit Exceeded"; } }, convertByType: function(alertCode, value) { From 217ebf20a62006c999505ff1535a7bbf908b7763 Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Tue, 19 Mar 2013 14:24:12 +0530 Subject: [PATCH 13/13] CLOUDSTACK-1717, CLOUDSTACK-1718: Corrected RemoveRegion response. Removed /api in Local region end_point --- .../cloudstack/api/command/admin/region/RemoveRegionCmd.java | 2 +- setup/db/db/schema-40to410.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/src/org/apache/cloudstack/api/command/admin/region/RemoveRegionCmd.java b/api/src/org/apache/cloudstack/api/command/admin/region/RemoveRegionCmd.java index 79c34d0690f..d2b696d2b6b 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/region/RemoveRegionCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/region/RemoveRegionCmd.java @@ -33,7 +33,7 @@ import com.cloud.user.Account; @APICommand(name = "removeRegion", description="Removes specified region", responseObject=SuccessResponse.class) public class RemoveRegionCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(RemoveRegionCmd.class.getName()); - private static final String s_name = "updateregionresponse"; + private static final String s_name = "removeregionresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/setup/db/db/schema-40to410.sql b/setup/db/db/schema-40to410.sql index 865fbd3181c..0f316a5acdd 100644 --- a/setup/db/db/schema-40to410.sql +++ b/setup/db/db/schema-40to410.sql @@ -261,7 +261,7 @@ CREATE TABLE `cloud`.`region` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -INSERT INTO `cloud`.`region` values ('1','Local','http://localhost:8080/client/api'); +INSERT INTO `cloud`.`region` values ('1','Local','http://localhost:8080/client'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Account Defaults', 'DEFAULT', 'management-server', 'max.account.cpus', '40', 'The default maximum number of cpu cores that can be used for an account');