You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by jo...@apache.org on 2014/08/27 14:52:00 UTC
[1/2] AMBARI-7021 - Alerts: Create Group and Target REST Endpoints
(jonathanhurley)
Repository: ambari
Updated Branches:
refs/heads/branch-alerts-dev 6ba11a2a9 -> 4a4644b88
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertTargetResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertTargetResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertTargetResourceProviderTest.java
new file mode 100644
index 0000000..982dd4b
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertTargetResourceProviderTest.java
@@ -0,0 +1,290 @@
+/**
+ * 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.ambari.server.controller.internal;
+
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.createStrictMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.resetToStrict;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PredicateBuilder;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.metadata.ActionMetadata;
+import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.orm.dao.AlertDispatchDAO;
+import org.apache.ambari.server.orm.entities.AlertTargetEntity;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.alert.TargetType;
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.inject.Binder;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.util.Modules;
+
+/**
+ * {@link AlertTargetResourceProvider} tests.
+ */
+public class AlertTargetResourceProviderTest {
+
+ private static final Long ALERT_TARGET_ID = Long.valueOf(28);
+ private static final String ALERT_TARGET_NAME = "The Administrators";
+ private static final String ALERT_TARGET_DESC = "Admins and Others";
+ private static final String ALERT_TARGET_TYPE = TargetType.EMAIL.name();
+
+ private AlertDispatchDAO m_dao;
+ private Injector m_injector;
+
+ @Before
+ public void before() {
+ m_dao = createStrictMock(AlertDispatchDAO.class);
+
+ m_injector = Guice.createInjector(Modules.override(
+ new InMemoryDefaultTestModule()).with(new MockModule()));
+
+ AlertTargetResourceProvider.init(m_injector);
+ }
+
+ /**
+ * @throws Exception
+ */
+ @Test
+ public void testGetResourcesNoPredicate() throws Exception {
+ Request request = PropertyHelper.getReadRequest(
+ AlertTargetResourceProvider.ALERT_TARGET_DESCRIPTION,
+ AlertTargetResourceProvider.ALERT_TARGET_ID,
+ AlertTargetResourceProvider.ALERT_TARGET_NAME,
+ AlertTargetResourceProvider.ALERT_TARGET_NOTIFICATION_TYPE);
+
+ expect(m_dao.findAllTargets()).andReturn(getMockEntities());
+ replay(m_dao);
+
+ AmbariManagementController amc = createMock(AmbariManagementController.class);
+ AlertTargetResourceProvider provider = createProvider(amc);
+ Set<Resource> results = provider.getResources(request, null);
+
+ assertEquals(1, results.size());
+
+ Resource r = results.iterator().next();
+ Assert.assertEquals(ALERT_TARGET_NAME,
+ r.getPropertyValue(AlertTargetResourceProvider.ALERT_TARGET_NAME));
+
+ verify(m_dao);
+ }
+
+ /**
+ * @throws Exception
+ */
+ @Test
+ public void testGetSingleResource() throws Exception {
+ Request request = PropertyHelper.getReadRequest(
+ AlertTargetResourceProvider.ALERT_TARGET_DESCRIPTION,
+ AlertTargetResourceProvider.ALERT_TARGET_ID,
+ AlertTargetResourceProvider.ALERT_TARGET_NAME,
+ AlertTargetResourceProvider.ALERT_TARGET_NOTIFICATION_TYPE);
+
+ AmbariManagementController amc = createMock(AmbariManagementController.class);
+
+ Predicate predicate = new PredicateBuilder().property(
+ AlertTargetResourceProvider.ALERT_TARGET_ID).equals(
+ ALERT_TARGET_ID.toString()).toPredicate();
+
+ expect(m_dao.findTargetById(ALERT_TARGET_ID.longValue())).andReturn(
+ getMockEntities().get(0));
+
+ replay(amc, m_dao);
+
+ AlertTargetResourceProvider provider = createProvider(amc);
+ Set<Resource> results = provider.getResources(request, predicate);
+
+ assertEquals(1, results.size());
+
+ Resource r = results.iterator().next();
+ Assert.assertEquals(ALERT_TARGET_ID,
+ r.getPropertyValue(AlertTargetResourceProvider.ALERT_TARGET_ID));
+
+ Assert.assertEquals(ALERT_TARGET_NAME,
+ r.getPropertyValue(AlertTargetResourceProvider.ALERT_TARGET_NAME));
+
+ verify(amc, m_dao);
+ }
+
+ /**
+ * @throws Exception
+ */
+ @Test
+ public void testCreateResources() throws Exception {
+ AmbariManagementController amc = createMock(AmbariManagementController.class);
+ Capture<List<AlertTargetEntity>> listCapture = new Capture<List<AlertTargetEntity>>();
+
+ m_dao.createTargets(capture(listCapture));
+ expectLastCall();
+
+ replay(amc, m_dao);
+
+ AlertTargetResourceProvider provider = createProvider(amc);
+ Map<String, Object> requestProps = new HashMap<String, Object>();
+ requestProps.put(AlertTargetResourceProvider.ALERT_TARGET_NAME,
+ ALERT_TARGET_NAME);
+
+ requestProps.put(AlertTargetResourceProvider.ALERT_TARGET_DESCRIPTION,
+ ALERT_TARGET_DESC);
+
+ requestProps.put(
+ AlertTargetResourceProvider.ALERT_TARGET_NOTIFICATION_TYPE,
+ ALERT_TARGET_TYPE);
+
+ Request request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), null);
+ provider.createResources(request);
+
+ Assert.assertTrue(listCapture.hasCaptured());
+ AlertTargetEntity entity = listCapture.getValue().get(0);
+ Assert.assertNotNull(entity);
+
+ Assert.assertEquals(ALERT_TARGET_NAME, entity.getTargetName());
+ Assert.assertEquals(ALERT_TARGET_DESC, entity.getDescription());
+ Assert.assertEquals(ALERT_TARGET_TYPE, entity.getNotificationType());
+
+ verify(amc, m_dao);
+ }
+
+ /**
+ * @throws Exception
+ */
+ @Test
+ public void testUpdateResources() throws Exception {
+ }
+
+ /**
+ * @throws Exception
+ */
+ @Test
+ public void testDeleteResources() throws Exception {
+ AmbariManagementController amc = createMock(AmbariManagementController.class);
+ Capture<AlertTargetEntity> entityCapture = new Capture<AlertTargetEntity>();
+ Capture<List<AlertTargetEntity>> listCapture = new Capture<List<AlertTargetEntity>>();
+
+ m_dao.createTargets(capture(listCapture));
+ expectLastCall();
+
+ replay(amc, m_dao);
+
+ AlertTargetResourceProvider provider = createProvider(amc);
+
+ Map<String, Object> requestProps = new HashMap<String, Object>();
+ requestProps.put(AlertTargetResourceProvider.ALERT_TARGET_NAME,
+ ALERT_TARGET_NAME);
+
+ requestProps.put(AlertTargetResourceProvider.ALERT_TARGET_DESCRIPTION,
+ ALERT_TARGET_DESC);
+
+ requestProps.put(
+ AlertTargetResourceProvider.ALERT_TARGET_NOTIFICATION_TYPE,
+ ALERT_TARGET_TYPE);
+
+ Request request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), null);
+ provider.createResources(request);
+
+ Assert.assertTrue(listCapture.hasCaptured());
+ AlertTargetEntity entity = listCapture.getValue().get(0);
+ Assert.assertNotNull(entity);
+
+ Predicate p = new PredicateBuilder().property(
+ AlertTargetResourceProvider.ALERT_TARGET_ID).equals(
+ ALERT_TARGET_ID.toString()).toPredicate();
+
+ // everything is mocked, there is no DB
+ entity.setTargetId(ALERT_TARGET_ID);
+
+ resetToStrict(m_dao);
+ expect(m_dao.findTargetById(ALERT_TARGET_ID.longValue())).andReturn(entity).anyTimes();
+ m_dao.remove(capture(entityCapture));
+ expectLastCall();
+ replay(m_dao);
+
+ provider.deleteResources(p);
+
+ AlertTargetEntity entity1 = entityCapture.getValue();
+ Assert.assertEquals(ALERT_TARGET_ID, entity1.getTargetId());
+
+ verify(amc, m_dao);
+ }
+
+ /**
+ * @param amc
+ * @return
+ */
+ private AlertTargetResourceProvider createProvider(
+ AmbariManagementController amc) {
+ return new AlertTargetResourceProvider(
+ PropertyHelper.getPropertyIds(Resource.Type.AlertTarget),
+ PropertyHelper.getKeyPropertyIds(Resource.Type.AlertTarget), amc);
+ }
+
+ /**
+ * @return
+ */
+ private List<AlertTargetEntity> getMockEntities() throws Exception {
+ AlertTargetEntity entity = new AlertTargetEntity();
+ entity.setTargetId(ALERT_TARGET_ID);
+ entity.setDescription(ALERT_TARGET_DESC);
+ entity.setTargetName(ALERT_TARGET_NAME);
+ entity.setNotificationType(TargetType.EMAIL.name());
+ return Arrays.asList(entity);
+ }
+
+ /**
+ *
+ */
+ private class MockModule implements Module {
+ /**
+ *
+ */
+ @Override
+ public void configure(Binder binder) {
+ binder.bind(AlertDispatchDAO.class).toInstance(m_dao);
+ binder.bind(Clusters.class).toInstance(
+ EasyMock.createNiceMock(Clusters.class));
+ binder.bind(Cluster.class).toInstance(
+ EasyMock.createNiceMock(Cluster.class));
+ binder.bind(ActionMetadata.class);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/test/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostTest.java
index c0bdaa2..d7c8c54 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostTest.java
@@ -105,12 +105,12 @@ public class ServiceComponentHostTest {
metaInfo.init();
clusters.mapHostToCluster("h1","C1");
}
-
+
private void setOsFamily(Host host, String osFamily, String osVersion) {
Map<String, String> hostAttributes = new HashMap<String, String>(2);
hostAttributes.put("os_family", osFamily);
hostAttributes.put("os_release_version", osVersion);
-
+
host.setHostAttributes(hostAttributes);
}
@@ -118,15 +118,16 @@ public class ServiceComponentHostTest {
public void teardown() {
injector.getInstance(PersistService.class).stop();
}
-
+
private ServiceComponentHost createNewServiceComponentHost(
String svc,
String svcComponent,
String hostName, boolean isClient) throws AmbariException{
Cluster c = clusters.getCluster("C1");
-
+
return createNewServiceComponentHost(c, svc, svcComponent, hostName);
}
+
private ServiceComponentHost createNewServiceComponentHost(
Cluster c,
String svc,
@@ -156,18 +157,22 @@ public class ServiceComponentHostTest {
ServiceComponentHost impl = serviceComponentHostFactory.createNew(
sc, hostName);
+
impl.persist();
- Assert.assertEquals(State.INIT,
- impl.getState());
- Assert.assertEquals(State.INIT,
- impl.getDesiredState());
+
+ Assert.assertEquals(State.INIT, impl.getState());
+ Assert.assertEquals(State.INIT, impl.getDesiredState());
Assert.assertEquals(c.getClusterName(), impl.getClusterName());
Assert.assertEquals(c.getClusterId(), impl.getClusterId());
Assert.assertEquals(s.getName(), impl.getServiceName());
Assert.assertEquals(sc.getName(), impl.getServiceComponentName());
Assert.assertEquals(hostName, impl.getHostName());
+
+ Assert.assertNotNull(c.getServiceComponentHosts(hostName));
+
Assert.assertFalse(
impl.getDesiredStackVersion().getStackId().isEmpty());
+
Assert.assertTrue(impl.getStackVersion().getStackId().isEmpty());
return impl;
@@ -264,7 +269,7 @@ public class ServiceComponentHostTest {
ServiceComponentHostEvent installEvent2 = createEvent(impl, ++timestamp,
startEventType);
-
+
boolean exceptionThrown = false;
LOG.info("Transitioning from " + impl.getState() + " " + installEvent2.getType());
try {
@@ -503,7 +508,7 @@ public class ServiceComponentHostTest {
Assert.assertEquals("HDP-1.1.0",
sch.getDesiredStackVersion().getStackId());
}
-
+
@Test
public void testActualConfigs() throws Exception {
ServiceComponentHost sch =
@@ -520,25 +525,25 @@ public class ServiceComponentHostTest {
configGroup.persist();
cluster.addConfigGroup(configGroup);
-
+
Map<String, Map<String,String>> actual =
new HashMap<String, Map<String, String>>() {{
put("global", new HashMap<String,String>() {{ put("tag", "version1"); }});
put("core-site", new HashMap<String,String>() {{ put("tag", "version1");
put(configGroup.getId().toString(), "version2"); }});
}};
-
+
sch.updateActualConfigs(actual);
-
+
Map<String, HostConfig> confirm = sch.getActualConfigs();
-
+
Assert.assertEquals(2, confirm.size());
Assert.assertTrue(confirm.containsKey("global"));
Assert.assertTrue(confirm.containsKey("core-site"));
Assert.assertEquals(1, confirm.get("core-site").getConfigGroupOverrides().size());
}
-
+
@Test
public void testConvertToResponse() throws AmbariException {
ServiceComponentHost sch =
@@ -555,7 +560,7 @@ public class ServiceComponentHostTest {
Assert.assertEquals(State.INSTALLED.toString(), r.getDesiredState());
Assert.assertEquals(State.INSTALLING.toString(), r.getLiveState());
Assert.assertEquals("HDP-1.0.0", r.getStackVersion());
-
+
Assert.assertFalse(r.isStaleConfig());
// TODO check configs
@@ -615,62 +620,61 @@ public class ServiceComponentHostTest {
impl.getState());
}
- @Test
- public void TestDisableInVariousStates() throws AmbariException,
- InvalidStateTransitionException {
- ServiceComponentHost sch =
- createNewServiceComponentHost("HDFS", "DATANODE", "h1", false);
- ServiceComponentHostImpl impl = (ServiceComponentHostImpl) sch;
-
- // Test valid states in which host component can be disabled
- long timestamp = 0;
- HashSet<State> validStates = new HashSet<State>();
- validStates.add(State.INSTALLED);
- validStates.add(State.INSTALL_FAILED);
- validStates.add(State.UNKNOWN);
- validStates.add(State.DISABLED);
- for (State state : validStates)
- {
- sch.setState(state);
- ServiceComponentHostEvent disableEvent = createEvent(
- impl, ++timestamp, ServiceComponentHostEventType.HOST_SVCCOMP_DISABLE);
- impl.handleEvent(disableEvent);
- // TODO: At present operation timestamps are not getting updated.
- Assert.assertEquals(-1, impl.getLastOpStartTime());
- Assert.assertEquals(-1, impl.getLastOpLastUpdateTime());
- Assert.assertEquals(-1, impl.getLastOpEndTime());
- Assert.assertEquals(State.DISABLED, impl.getState());
- }
-
- // Test invalid states in which host component cannot be disabled
- HashSet<State> invalidStates = new HashSet<State>();
- invalidStates.add(State.INIT);
- invalidStates.add(State.INSTALLING);
- invalidStates.add(State.STARTING);
- invalidStates.add(State.STARTED);
- invalidStates.add(State.STOPPING);
- invalidStates.add(State.UNINSTALLING);
- invalidStates.add(State.UNINSTALLED);
- invalidStates.add(State.UPGRADING);
-
- for(State state : invalidStates)
- {
- sch.setState(state);
- ServiceComponentHostEvent disableEvent = createEvent(
- impl, ++timestamp, ServiceComponentHostEventType.HOST_SVCCOMP_DISABLE);
- boolean exceptionThrown = false;
- try {
- impl.handleEvent(disableEvent);
- } catch (Exception e) {
- exceptionThrown = true;
- }
- Assert.assertTrue("Exception not thrown on invalid event", exceptionThrown);
- // TODO: At present operation timestamps are not getting updated.
- Assert.assertEquals(-1, impl.getLastOpStartTime());
- Assert.assertEquals(-1, impl.getLastOpLastUpdateTime());
- Assert.assertEquals(-1, impl.getLastOpEndTime());
- }
- }
+ @Test
+ public void testDisableInVariousStates() throws AmbariException,
+ InvalidStateTransitionException {
+ ServiceComponentHost sch = createNewServiceComponentHost("HDFS",
+ "DATANODE", "h1", false);
+ ServiceComponentHostImpl impl = (ServiceComponentHostImpl) sch;
+
+ // Test valid states in which host component can be disabled
+ long timestamp = 0;
+ HashSet<State> validStates = new HashSet<State>();
+ validStates.add(State.INSTALLED);
+ validStates.add(State.INSTALL_FAILED);
+ validStates.add(State.UNKNOWN);
+ validStates.add(State.DISABLED);
+ for (State state : validStates) {
+ sch.setState(state);
+ ServiceComponentHostEvent disableEvent = createEvent(impl, ++timestamp,
+ ServiceComponentHostEventType.HOST_SVCCOMP_DISABLE);
+ impl.handleEvent(disableEvent);
+ // TODO: At present operation timestamps are not getting updated.
+ Assert.assertEquals(-1, impl.getLastOpStartTime());
+ Assert.assertEquals(-1, impl.getLastOpLastUpdateTime());
+ Assert.assertEquals(-1, impl.getLastOpEndTime());
+ Assert.assertEquals(State.DISABLED, impl.getState());
+ }
+
+ // Test invalid states in which host component cannot be disabled
+ HashSet<State> invalidStates = new HashSet<State>();
+ invalidStates.add(State.INIT);
+ invalidStates.add(State.INSTALLING);
+ invalidStates.add(State.STARTING);
+ invalidStates.add(State.STARTED);
+ invalidStates.add(State.STOPPING);
+ invalidStates.add(State.UNINSTALLING);
+ invalidStates.add(State.UNINSTALLED);
+ invalidStates.add(State.UPGRADING);
+
+ for (State state : invalidStates) {
+ sch.setState(state);
+ ServiceComponentHostEvent disableEvent = createEvent(impl, ++timestamp,
+ ServiceComponentHostEventType.HOST_SVCCOMP_DISABLE);
+ boolean exceptionThrown = false;
+ try {
+ impl.handleEvent(disableEvent);
+ } catch (Exception e) {
+ exceptionThrown = true;
+ }
+ Assert.assertTrue("Exception not thrown on invalid event",
+ exceptionThrown);
+ // TODO: At present operation timestamps are not getting updated.
+ Assert.assertEquals(-1, impl.getLastOpStartTime());
+ Assert.assertEquals(-1, impl.getLastOpLastUpdateTime());
+ Assert.assertEquals(-1, impl.getLastOpEndTime());
+ }
+ }
@Test
public void testCanBeRemoved() throws Exception{
@@ -688,13 +692,13 @@ public class ServiceComponentHostTest {
}
}
}
-
+
@Test
public void testStaleConfigs() throws Exception {
String stackVersion="HDP-2.0.6";
String clusterName = "c2";
String hostName = "h3";
-
+
clusters.addCluster(clusterName);
clusters.addHost(hostName);
setOsFamily(clusters.getHost(hostName), "redhat", "5.9");
@@ -702,14 +706,14 @@ public class ServiceComponentHostTest {
clusters.getCluster(clusterName).setDesiredStackVersion(
new StackId(stackVersion));
metaInfo.init();
- clusters.mapHostToCluster(hostName, clusterName);
-
+ clusters.mapHostToCluster(hostName, clusterName);
+
Cluster cluster = clusters.getCluster(clusterName);
-
+
ServiceComponentHost sch1 = createNewServiceComponentHost(cluster, "HDFS", "NAMENODE", hostName);
ServiceComponentHost sch2 = createNewServiceComponentHost(cluster, "HDFS", "DATANODE", hostName);
ServiceComponentHost sch3 = createNewServiceComponentHost(cluster, "MAPREDUCE2", "HISTORYSERVER", hostName);
-
+
sch1.setDesiredState(State.INSTALLED);
sch1.setState(State.INSTALLING);
sch1.setStackVersion(new StackId(stackVersion));
@@ -717,10 +721,10 @@ public class ServiceComponentHostTest {
sch2.setDesiredState(State.INSTALLED);
sch2.setState(State.INSTALLING);
sch2.setStackVersion(new StackId(stackVersion));
-
+
sch3.setDesiredState(State.INSTALLED);
sch3.setState(State.INSTALLING);
- sch3.setStackVersion(new StackId(stackVersion));
+ sch3.setStackVersion(new StackId(stackVersion));
Assert.assertFalse(sch1.convertToResponse().isStaleConfig());
Assert.assertFalse(sch2.convertToResponse().isStaleConfig());
@@ -735,7 +739,7 @@ public class ServiceComponentHostTest {
Map<String, Map<String, String>> actual = new HashMap<String, Map<String, String>>() {{
put("global", new HashMap<String,String>() {{ put("tag", "version1"); }});
}};
-
+
sch1.updateActualConfigs(actual);
sch2.updateActualConfigs(actual);
sch3.updateActualConfigs(actual);
@@ -746,7 +750,7 @@ public class ServiceComponentHostTest {
// HDP-x/HDFS does not define type 'foo', so changes do not count to stale
Assert.assertFalse(sch1.convertToResponse().isStaleConfig());
Assert.assertFalse(sch2.convertToResponse().isStaleConfig());
-
+
makeConfig(cluster, "hdfs-site", "version1",
new HashMap<String,String>() {{ put("a", "b"); }}, new HashMap<String, Map<String,String>>());
@@ -755,7 +759,7 @@ public class ServiceComponentHostTest {
Assert.assertTrue(sch2.convertToResponse().isStaleConfig());
actual.put("hdfs-site", new HashMap<String, String>() {{ put ("tag", "version1"); }});
-
+
sch1.updateActualConfigs(actual);
// previous value from cache
Assert.assertTrue(sch1.convertToResponse().isStaleConfig());
@@ -765,7 +769,7 @@ public class ServiceComponentHostTest {
// HDP-x/HDFS/hdfs-site up to date, only for sch1
Assert.assertFalse(sch1.convertToResponse().isStaleConfig());
Assert.assertTrue(sch2.convertToResponse().isStaleConfig());
-
+
sch2.updateActualConfigs(actual);
// previous value from cache
Assert.assertTrue(sch2.convertToResponse().isStaleConfig());
@@ -775,15 +779,15 @@ public class ServiceComponentHostTest {
// HDP-x/HDFS/hdfs-site up to date for both
Assert.assertFalse(sch1.convertToResponse().isStaleConfig());
Assert.assertFalse(sch2.convertToResponse().isStaleConfig());
-
+
makeConfig(cluster, "hdfs-site", "version2",
- new HashMap<String, String>() {{ put("dfs.journalnode.http-address", "http://foo"); }},
+ new HashMap<String, String>() {{ put("dfs.journalnode.http-address", "http://foo"); }},
new HashMap<String, Map<String,String>>());
// HDP-x/HDFS/hdfs-site updated to changed property
Assert.assertTrue(sch1.convertToResponse().isStaleConfig());
Assert.assertTrue(sch2.convertToResponse().isStaleConfig());
-
+
actual.get("hdfs-site").put("tag", "version2");
sch1.updateActualConfigs(actual);
sch2.updateActualConfigs(actual);
@@ -794,13 +798,13 @@ public class ServiceComponentHostTest {
// HDP-x/HDFS/hdfs-site updated to changed property
Assert.assertFalse(sch1.convertToResponse().isStaleConfig());
Assert.assertFalse(sch2.convertToResponse().isStaleConfig());
-
+
// make a host override
final Host host = clusters.getHostsForCluster(cluster.getClusterName()).get(hostName);
Assert.assertNotNull(host);
-
+
final Config c = configFactory.createNew(cluster, "hdfs-site",
- new HashMap<String, String>() {{ put("dfs.journalnode.http-address", "http://goo"); }},
+ new HashMap<String, String>() {{ put("dfs.journalnode.http-address", "http://goo"); }},
new HashMap<String, Map<String,String>>());
c.setTag("version3");
c.persist();
@@ -811,11 +815,11 @@ public class ServiceComponentHostTest {
new HashMap<String, Host>() {{ put("h3", host); }});
configGroup.persist();
cluster.addConfigGroup(configGroup);
-
+
// HDP-x/HDFS/hdfs-site updated host to changed property
Assert.assertTrue(sch1.convertToResponse().isStaleConfig());
Assert.assertTrue(sch2.convertToResponse().isStaleConfig());
-
+
actual.get("hdfs-site").put(configGroup.getId().toString(), "version3");
sch2.updateActualConfigs(actual);
// previous value from cache
@@ -826,7 +830,7 @@ public class ServiceComponentHostTest {
// HDP-x/HDFS/hdfs-site updated host to changed property
Assert.assertTrue(sch1.convertToResponse().isStaleConfig());
Assert.assertFalse(sch2.convertToResponse().isStaleConfig());
-
+
sch1.updateActualConfigs(actual);
// previous value from cache
Assert.assertTrue(sch1.convertToResponse().isStaleConfig());
@@ -836,7 +840,7 @@ public class ServiceComponentHostTest {
// HDP-x/HDFS/hdfs-site updated host to changed property
Assert.assertFalse(sch1.convertToResponse().isStaleConfig());
Assert.assertFalse(sch2.convertToResponse().isStaleConfig());
-
+
// change 'global' property only affecting global/HDFS
makeConfig(cluster, "global", "version2",
new HashMap<String,String>() {{
@@ -844,7 +848,7 @@ public class ServiceComponentHostTest {
put("dfs_namenode_name_dir", "/foo3"); // HDFS only
put("mapred_log_dir_prefix", "/foo2"); // MR2 only
}}, new HashMap<String, Map<String,String>>());
-
+
Assert.assertTrue(sch1.convertToResponse().isStaleConfig());
Assert.assertTrue(sch2.convertToResponse().isStaleConfig());
Assert.assertFalse(sch3.convertToResponse().isStaleConfig());
@@ -867,7 +871,7 @@ public class ServiceComponentHostTest {
sch1.updateActualConfigs(actual);
final Config c1 = configFactory.createNew(cluster, "core-site",
- new HashMap<String, String>() {{ put("fs.trash.interval", "400"); }},
+ new HashMap<String, String>() {{ put("fs.trash.interval", "400"); }},
new HashMap<String, Map<String,String>>());
c1.setTag("version2");
c1.persist();
@@ -912,13 +916,13 @@ public class ServiceComponentHostTest {
sch3.setRestartRequired(false);
Assert.assertFalse(sch3.convertToResponse().isStaleConfig());
}
-
+
@Test
public void testStaleConfigsAttributes() throws Exception {
String stackVersion="HDP-2.0.6";
String clusterName = "c2";
String hostName = "h3";
-
+
clusters.addCluster(clusterName);
clusters.addHost(hostName);
setOsFamily(clusters.getHost(hostName), "redhat", "5.9");
@@ -926,14 +930,14 @@ public class ServiceComponentHostTest {
clusters.getCluster(clusterName).setDesiredStackVersion(
new StackId(stackVersion));
metaInfo.init();
- clusters.mapHostToCluster(hostName, clusterName);
-
+ clusters.mapHostToCluster(hostName, clusterName);
+
Cluster cluster = clusters.getCluster(clusterName);
-
+
ServiceComponentHost sch1 = createNewServiceComponentHost(cluster, "HDFS", "NAMENODE", hostName);
ServiceComponentHost sch2 = createNewServiceComponentHost(cluster, "HDFS", "DATANODE", hostName);
ServiceComponentHost sch3 = createNewServiceComponentHost(cluster, "MAPREDUCE2", "HISTORYSERVER", hostName);
-
+
sch1.setDesiredState(State.INSTALLED);
sch1.setState(State.INSTALLING);
sch1.setStackVersion(new StackId(stackVersion));
@@ -941,10 +945,10 @@ public class ServiceComponentHostTest {
sch2.setDesiredState(State.INSTALLED);
sch2.setState(State.INSTALLING);
sch2.setStackVersion(new StackId(stackVersion));
-
+
sch3.setDesiredState(State.INSTALLED);
sch3.setState(State.INSTALLING);
- sch3.setStackVersion(new StackId(stackVersion));
+ sch3.setStackVersion(new StackId(stackVersion));
Assert.assertFalse(sch1.convertToResponse().isStaleConfig());
Assert.assertFalse(sch2.convertToResponse().isStaleConfig());
@@ -963,7 +967,7 @@ public class ServiceComponentHostTest {
put("global", new HashMap<String,String>() {{ put("tag", "version1"); }});
put("hdfs-site", new HashMap<String,String>() {{ put("tag", "version1"); }});
}};
-
+
sch1.updateActualConfigs(actual);
sch2.updateActualConfigs(actual);
sch3.updateActualConfigs(actual);
@@ -972,7 +976,7 @@ public class ServiceComponentHostTest {
new HashMap<String,String>() {{ put("a", "c"); }},new HashMap<String, Map<String,String>>(){{
put("final", new HashMap<String, String>(){{
put("a", "true");
- }});
+ }});
}});
// HDP-x/HDFS does not define type 'foo', so changes do not count to stale
Assert.assertFalse(sch1.convertToResponse().isStaleConfig());
@@ -985,7 +989,7 @@ public class ServiceComponentHostTest {
sch3.setRestartRequired(false);
sch3.updateActualConfigs(actual);
Assert.assertFalse(sch3.convertToResponse().isStaleConfig());
-
+
// Now add config-attributes
Map<String, Map<String, String>> c1PropAttributes = new HashMap<String, Map<String,String>>();
c1PropAttributes.put("final", new HashMap<String, String>());
@@ -1000,7 +1004,7 @@ public class ServiceComponentHostTest {
Assert.assertTrue(sch1.convertToResponse().isStaleConfig());
Assert.assertTrue(sch2.convertToResponse().isStaleConfig());
Assert.assertFalse(sch3.convertToResponse().isStaleConfig());
-
+
// Now change config-attributes
Map<String, Map<String, String>> c2PropAttributes = new HashMap<String, Map<String,String>>();
c2PropAttributes.put("final", new HashMap<String, String>());
@@ -1015,7 +1019,7 @@ public class ServiceComponentHostTest {
Assert.assertTrue(sch1.convertToResponse().isStaleConfig());
Assert.assertTrue(sch2.convertToResponse().isStaleConfig());
Assert.assertFalse(sch3.convertToResponse().isStaleConfig());
-
+
// Now change config-attributes
makeConfig(cluster, "hdfs-site", "version4",
new HashMap<String,String>() {{
@@ -1043,13 +1047,13 @@ public class ServiceComponentHostTest {
cluster.addConfig(config);
cluster.addDesiredConfig("user", config);
}
-
+
@Test
public void testMaintenance() throws Exception {
String stackVersion="HDP-2.0.6";
String clusterName = "c2";
String hostName = "h3";
-
+
clusters.addCluster(clusterName);
clusters.addHost(hostName);
setOsFamily(clusters.getHost(hostName), "redhat", "5.9");
@@ -1057,10 +1061,10 @@ public class ServiceComponentHostTest {
clusters.getCluster(clusterName).setDesiredStackVersion(
new StackId(stackVersion));
metaInfo.init();
- clusters.mapHostToCluster(hostName, clusterName);
-
+ clusters.mapHostToCluster(hostName, clusterName);
+
Cluster cluster = clusters.getCluster(clusterName);
-
+
ServiceComponentHost sch1 = createNewServiceComponentHost(cluster, "HDFS", "NAMENODE", hostName);
ServiceComponentHost sch2 = createNewServiceComponentHost(cluster, "HDFS", "DATANODE", hostName);
ServiceComponentHost sch3 = createNewServiceComponentHost(cluster, "MAPREDUCE2", "HISTORYSERVER", hostName);
@@ -1070,20 +1074,20 @@ public class ServiceComponentHostTest {
pk.setComponentName(sch1.getServiceComponentName());
pk.setServiceName(sch1.getServiceName());
pk.setHostName(hostName);
-
+
HostComponentDesiredStateDAO dao = injector.getInstance(HostComponentDesiredStateDAO.class);
HostComponentDesiredStateEntity entity = dao.findByPK(pk);
Assert.assertEquals(MaintenanceState.OFF, entity.getMaintenanceState());
Assert.assertEquals(MaintenanceState.OFF, sch1.getMaintenanceState());
-
+
sch1.setMaintenanceState(MaintenanceState.ON);
Assert.assertEquals(MaintenanceState.ON, sch1.getMaintenanceState());
-
+
entity = dao.findByPK(pk);
Assert.assertEquals(MaintenanceState.ON, entity.getMaintenanceState());
}
-
-
+
+
}
[2/2] git commit: AMBARI-7021 - Alerts: Create Group and Target REST
Endpoints (jonathanhurley)
Posted by jo...@apache.org.
AMBARI-7021 - Alerts: Create Group and Target REST Endpoints (jonathanhurley)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/4a4644b8
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/4a4644b8
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/4a4644b8
Branch: refs/heads/branch-alerts-dev
Commit: 4a4644b882c9a0d39b249db5a106f7075cb0c93d
Parents: 6ba11a2
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Tue Aug 26 14:21:31 2014 -0400
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Wed Aug 27 08:51:49 2014 -0400
----------------------------------------------------------------------
.../python/ambari_agent/alerts/base_alert.py | 4 +-
.../python/ambari_agent/alerts/port_alert.py | 11 +-
.../ambari/server/agent/HeartBeatHandler.java | 16 +-
.../resources/AlertGroupResourceDefinition.java | 50 +++
.../AlertTargetResourceDefinition.java | 50 +++
.../resources/ResourceInstanceFactoryImpl.java | 8 +
.../server/api/services/AlertGroupService.java | 111 ++++++
.../server/api/services/AlertTargetService.java | 96 ++++++
.../server/api/services/ClusterService.java | 66 +++-
.../ambari/server/controller/AmbariServer.java | 4 +
.../AbstractControllerResourceProvider.java | 10 +-
.../internal/AlertGroupResourceProvider.java | 268 +++++++++++++++
.../internal/AlertTargetResourceProvider.java | 258 ++++++++++++++
.../ambari/server/controller/spi/Resource.java | 13 +-
.../ambari/server/orm/dao/AlertDispatchDAO.java | 78 +++--
.../ambari/server/state/alert/AlertGroup.java | 124 +++++++
.../ambari/server/state/alert/AlertTarget.java | 123 +++++++
.../ambari/server/state/alert/TargetType.java | 37 ++
.../svccomphost/ServiceComponentHostImpl.java | 2 +
.../src/main/resources/key_properties.json | 7 +
.../src/main/resources/properties.json | 18 +-
.../AlertGroupResourceProviderTest.java | 335 +++++++++++++++++++
.../AlertTargetResourceProviderTest.java | 290 ++++++++++++++++
.../svccomphost/ServiceComponentHostTest.java | 242 +++++++-------
24 files changed, 2045 insertions(+), 176 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-agent/src/main/python/ambari_agent/alerts/base_alert.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/ambari_agent/alerts/base_alert.py b/ambari-agent/src/main/python/ambari_agent/alerts/base_alert.py
index 07987d9..88c7f92 100644
--- a/ambari-agent/src/main/python/ambari_agent/alerts/base_alert.py
+++ b/ambari-agent/src/main/python/ambari_agent/alerts/base_alert.py
@@ -34,7 +34,7 @@ class BaseAlert(object):
self.alert_meta = alert_meta
self.alert_source_meta = alert_source_meta
self.cluster = ''
- self.hostname = ''
+ self.hostName = ''
self._lookup_keys = []
@@ -54,7 +54,7 @@ class BaseAlert(object):
def set_cluster(self, cluster, host):
''' sets cluster information for the alert '''
self.cluster = cluster
- self.hostname = host
+ self.hostName = host
def collect(self):
''' method used for collection. defers to _collect() '''
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-agent/src/main/python/ambari_agent/alerts/port_alert.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/ambari_agent/alerts/port_alert.py b/ambari-agent/src/main/python/ambari_agent/alerts/port_alert.py
index d06d1f4..eaf744a 100644
--- a/ambari-agent/src/main/python/ambari_agent/alerts/port_alert.py
+++ b/ambari-agent/src/main/python/ambari_agent/alerts/port_alert.py
@@ -22,7 +22,6 @@ import logging
import re
import socket
import time
-import traceback
from alerts.base_alert import BaseAlert
from resource_management.libraries.functions.get_port_from_url import get_port_from_url
@@ -40,7 +39,7 @@ class PortAlert(BaseAlert):
def _collect(self):
urivalue = self._lookup_property_value(self.uri)
- host = get_host_from_url(urivalue)
+ host = get_host_from_url(self, urivalue)
port = self.port
try:
@@ -76,9 +75,9 @@ Tested on the following cases:
"hdfs://192.168.54.3/foo/bar"
"ftp://192.168.54.4:7842/foo/bar"
'''
-def get_host_from_url(uri):
+def get_host_from_url(self, uri):
# RFC3986, Appendix B
- parts = re.findall('^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?' , uri)
+ parts = re.findall('^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?', uri)
# index of parts
# scheme = 1
@@ -96,6 +95,10 @@ def get_host_from_url(uri):
host_and_port = parts[0][3]
if -1 == host_and_port.find(':'):
+ # if no : then it might only be a port; if it's a port, return this host
+ if host_and_port.isdigit():
+ return self.hostName
+
return host_and_port
else:
return host_and_port.split(':')[0]
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
index dca3bd9..d0d5a13 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
@@ -229,11 +229,13 @@ public class HeartBeatHandler {
protected void calculateHostAlerts(HeartBeat heartbeat, String hostname)
throws AmbariException {
- if (heartbeat != null && hostname != null) {
- for (Cluster cluster : clusterFsm.getClustersForHost(hostname)) {
- cluster.addAlerts(heartbeat.getNodeStatus().getAlerts());
- }
- }
+ if (null == hostname || null == heartbeat) {
+ return;
+ }
+
+ for (Cluster cluster : clusterFsm.getClustersForHost(hostname)) {
+ cluster.addAlerts(heartbeat.getNodeStatus().getAlerts());
+ }
}
protected void processHostStatus(HeartBeat heartbeat, String hostname) throws AmbariException {
@@ -710,7 +712,7 @@ public class HeartBeatHandler {
response.setResponseStatus(RegistrationStatus.OK);
// force the registering agent host to receive its list of alert definitions
- List<AlertDefinitionCommand> alertDefinitionCommands = getAlertDefinitionCommands(hostname);
+ List<AlertDefinitionCommand> alertDefinitionCommands = getRegistrationAlertDefinitionCommands(hostname);
response.setAlertDefinitionCommands(alertDefinitionCommands);
Long requestId = 0L;
@@ -787,7 +789,7 @@ public class HeartBeatHandler {
* @return
* @throws AmbariException
*/
- private List<AlertDefinitionCommand> getAlertDefinitionCommands(
+ private List<AlertDefinitionCommand> getRegistrationAlertDefinitionCommands(
String hostname) throws AmbariException {
Set<Cluster> hostClusters = clusterFsm.getClustersForHost(hostname);
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertGroupResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertGroupResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertGroupResourceDefinition.java
new file mode 100644
index 0000000..67e5d60
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertGroupResourceDefinition.java
@@ -0,0 +1,50 @@
+/**
+ * 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.ambari.server.api.resources;
+
+import org.apache.ambari.server.controller.spi.Resource;
+
+/**
+ * The {@link AlertGroupResourceDefinition} class is used to register alert
+ * groups to be returned via the REST API.
+ */
+public class AlertGroupResourceDefinition extends BaseResourceDefinition {
+
+ /**
+ * Constructor.
+ */
+ public AlertGroupResourceDefinition() {
+ super(Resource.Type.AlertGroup);
+ }
+
+ /**
+ *
+ */
+ @Override
+ public String getPluralName() {
+ return "alert_groups";
+ }
+
+ /**
+ *
+ */
+ @Override
+ public String getSingularName() {
+ return "alert_group";
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertTargetResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertTargetResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertTargetResourceDefinition.java
new file mode 100644
index 0000000..bc0d81d
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertTargetResourceDefinition.java
@@ -0,0 +1,50 @@
+/**
+ * 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.ambari.server.api.resources;
+
+import org.apache.ambari.server.controller.spi.Resource;
+
+/**
+ * The {@link AlertTargetResourceDefinition} class is used to register alert
+ * targets to be returned via the REST API.
+ */
+public class AlertTargetResourceDefinition extends BaseResourceDefinition {
+
+ /**
+ * Constructor.
+ */
+ public AlertTargetResourceDefinition() {
+ super(Resource.Type.AlertTarget);
+ }
+
+ /**
+ *
+ */
+ @Override
+ public String getPluralName() {
+ return "alert_targets";
+ }
+
+ /**
+ *
+ */
+ @Override
+ public String getSingularName() {
+ return "alert_target";
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
index 13fff1d..7faf365 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
@@ -251,6 +251,14 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
resourceDefinition = new AlertDefResourceDefinition();
break;
+ case AlertGroup:
+ resourceDefinition = new AlertGroupResourceDefinition();
+ break;
+
+ case AlertTarget:
+ resourceDefinition = new AlertTargetResourceDefinition();
+ break;
+
case AmbariPrivilege:
resourceDefinition = new PrivilegeResourceDefinition(Resource.Type.AmbariPrivilege);
break;
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/main/java/org/apache/ambari/server/api/services/AlertGroupService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AlertGroupService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AlertGroupService.java
new file mode 100644
index 0000000..c2e5048
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AlertGroupService.java
@@ -0,0 +1,111 @@
+/**
+ * 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.ambari.server.api.services;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.state.alert.AlertGroup;
+
+/**
+ * The {@link AlertGroupService} handles CRUD operations for a cluster's alert
+ * groups.
+ */
+public class AlertGroupService extends BaseService {
+
+ /**
+ * Cluster name for cluster-based requests
+ */
+ private String m_clusterName = null;
+
+ /**
+ * Constructor.
+ *
+ * @param clusterName
+ */
+ AlertGroupService(String clusterName) {
+ m_clusterName = clusterName;
+ }
+
+ @GET
+ @Produces("text/plain")
+ public Response getGroups(String body, @Context HttpHeaders headers,
+ @Context UriInfo ui) {
+ return handleRequest(headers, body, ui, Request.Type.GET,
+ createAlertGroupResource(m_clusterName, null));
+ }
+
+ @GET
+ @Produces("text/plain")
+ @Path("{groupId}")
+ public Response getGroup(String body, @Context HttpHeaders headers,
+ @Context UriInfo ui, @PathParam("groupId") Long groupId) {
+ return handleRequest(headers, body, ui, Request.Type.GET,
+ createAlertGroupResource(m_clusterName, groupId));
+ }
+
+ @POST
+ @Produces("text/plain")
+ public Response createGroup(String body, @Context HttpHeaders headers,
+ @Context UriInfo ui) {
+ return handleRequest(headers, body, ui, Request.Type.POST,
+ createAlertGroupResource(m_clusterName, null));
+ }
+
+ @DELETE
+ @Produces("text/plain")
+ @Path("{groupId}")
+ public Response deleteGroup(String body, @Context HttpHeaders headers,
+ @Context UriInfo ui, @PathParam("groupId") Long groupId) {
+ return handleRequest(headers, body, ui, Request.Type.DELETE,
+ createAlertGroupResource(m_clusterName, groupId));
+ }
+
+ /**
+ * Create a request capturing the group ID and resource type for an
+ * {@link AlertGroup}.
+ *
+ * @param groupId
+ * the unique ID of the group to create the query for (not
+ * {@code null}).
+ * @return the instance of the query.
+ */
+ private ResourceInstance createAlertGroupResource(String clusterName,
+ Long groupId) {
+
+ Map<Resource.Type, String> mapIds = new HashMap<Resource.Type, String>();
+ mapIds.put(Resource.Type.Cluster, m_clusterName);
+ mapIds.put(Resource.Type.AlertGroup,
+ null == groupId ? null : groupId.toString());
+
+ return createResource(Resource.Type.AlertGroup, mapIds);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/main/java/org/apache/ambari/server/api/services/AlertTargetService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AlertTargetService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AlertTargetService.java
new file mode 100644
index 0000000..86281b3
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AlertTargetService.java
@@ -0,0 +1,96 @@
+/**
+ * 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.ambari.server.api.services;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.state.alert.AlertTarget;
+
+/**
+ * The {@link AlertTargetService} handles CRUD operation requests for alert
+ * targets.
+ */
+@Path("/alert_targets/")
+public class AlertTargetService extends BaseService {
+
+ @GET
+ @Produces("text/plain")
+ public Response getTargets(String body, @Context HttpHeaders headers,
+ @Context UriInfo ui) {
+ return handleRequest(headers, body, ui, Request.Type.GET,
+ createAlertTargetResource(null));
+ }
+
+ @GET
+ @Produces("text/plain")
+ @Path("{targetId}")
+ public Response getTargets(String body, @Context HttpHeaders headers,
+ @Context UriInfo ui, @PathParam("targetId") Long targetId) {
+ return handleRequest(headers, body, ui, Request.Type.GET,
+ createAlertTargetResource(targetId));
+ }
+
+ @POST
+ @Produces("text/plain")
+ public Response createTarget(String body, @Context HttpHeaders headers,
+ @Context UriInfo ui) {
+ return handleRequest(headers, body, ui, Request.Type.POST,
+ createAlertTargetResource(null));
+ }
+
+ @DELETE
+ @Produces("text/plain")
+ @Path("{targetId}")
+ public Response deleteTarget(String body, @Context HttpHeaders headers,
+ @Context UriInfo ui, @PathParam("targetId") Long targetId) {
+ return handleRequest(headers, body, ui, Request.Type.DELETE,
+ createAlertTargetResource(targetId));
+ }
+
+ /**
+ * Create a request capturing the target ID and resource type for an
+ * {@link AlertTarget}.
+ *
+ * @param targetId
+ * the unique ID of the target to create the query for (not
+ * {@code null}).
+ * @return the instance of the query.
+ */
+ private ResourceInstance createAlertTargetResource(Long targetId) {
+ Map<Resource.Type, String> mapIds = new HashMap<Resource.Type, String>();
+
+ mapIds.put(Resource.Type.AlertTarget,
+ null == targetId ? null : targetId.toString());
+
+ return createResource(Resource.Type.AlertTarget, mapIds);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
index 8043b3f..3f1ce36 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
@@ -18,15 +18,26 @@
package org.apache.ambari.server.api.services;
+import java.util.Collections;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
import org.apache.ambari.server.api.resources.ResourceInstance;
import org.apache.ambari.server.controller.AmbariServer;
import org.apache.ambari.server.controller.spi.Resource;
import org.apache.ambari.server.state.Clusters;
-import javax.ws.rs.*;
-import javax.ws.rs.core.*;
-import java.util.Collections;
-
/**
* Service responsible for cluster resource requests.
@@ -46,7 +57,7 @@ public class ClusterService extends BaseService {
* Construct a ClusterService.
*/
public ClusterService() {
- this.clusters = AmbariServer.getController().getClusters();
+ clusters = AmbariServer.getController().getClusters();
}
/**
@@ -187,7 +198,7 @@ public class ClusterService extends BaseService {
hasPermission(Request.Type.valueOf(request.getMethod()), clusterName);
return new ServiceService(clusterName);
}
-
+
/**
* Gets the configurations sub-resource.
*
@@ -295,7 +306,7 @@ public class ClusterService extends BaseService {
hasPermission(Request.Type.valueOf(request.getMethod()), clusterName);
return new RequestScheduleService(clusterName);
}
-
+
/**
* Gets the alert definition service
*
@@ -313,12 +324,32 @@ public class ClusterService extends BaseService {
}
/**
+ * Gets the alert group service.
+ *
+ * @param request
+ * the request.
+ * @param clusterName
+ * the cluster name.
+ * @return the alert group service.
+ */
+ @Path("{clusterName}/alert_groups")
+ public AlertGroupService getAlertGroups(
+ @Context javax.ws.rs.core.Request request,
+ @PathParam("clusterName") String clusterName) {
+
+ hasPermission(Request.Type.valueOf(request.getMethod()), clusterName);
+ return new AlertGroupService(clusterName);
+ }
+
+ /**
* Gets the privilege service
*
- * @param request the request
- * @param clusterName the cluster name
+ * @param request
+ * the request
+ * @param clusterName
+ * the cluster name
*
- * @return the privileges service
+ * @return the privileges service
*/
@Path("{clusterName}/privileges")
public PrivilegeService getPrivilegeService(@Context javax.ws.rs.core.Request request, @PathParam ("clusterName") String clusterName) {
@@ -343,14 +374,17 @@ public class ClusterService extends BaseService {
}
/**
- * Determine whether or not the access specified by the given request type
- * is permitted for the current user on the cluster resource identified by
- * the given cluster name.
+ * Determine whether or not the access specified by the given request type is
+ * permitted for the current user on the cluster resource identified by the
+ * given cluster name.
*
- * @param requestType the request method type
- * @param clusterName the name of the cluster resource
+ * @param requestType
+ * the request method type
+ * @param clusterName
+ * the name of the cluster resource
*
- * @throws WebApplicationException if access is forbidden
+ * @throws WebApplicationException
+ * if access is forbidden
*/
private void hasPermission(Request.Type requestType, String clusterName) throws WebApplicationException {
if (!clusters.checkPermission(clusterName, requestType == Request.Type.GET)) {
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index 21c9d80..c75a7bb 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -46,6 +46,8 @@ import org.apache.ambari.server.configuration.ComponentSSLConfiguration;
import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.controller.internal.AbstractControllerResourceProvider;
import org.apache.ambari.server.controller.internal.AlertDefinitionResourceProvider;
+import org.apache.ambari.server.controller.internal.AlertGroupResourceProvider;
+import org.apache.ambari.server.controller.internal.AlertTargetResourceProvider;
import org.apache.ambari.server.controller.internal.AmbariPrivilegeResourceProvider;
import org.apache.ambari.server.controller.internal.BlueprintResourceProvider;
import org.apache.ambari.server.controller.internal.ClusterPrivilegeResourceProvider;
@@ -538,6 +540,8 @@ public class AmbariServer {
StackDependencyResourceProvider.init(ambariMetaInfo);
ClusterResourceProvider.init(injector.getInstance(BlueprintDAO.class), ambariMetaInfo, injector.getInstance(ConfigHelper.class));
AlertDefinitionResourceProvider.init(injector);
+ AlertGroupResourceProvider.init(injector);
+ AlertTargetResourceProvider.init(injector);
PermissionResourceProvider.init(injector.getInstance(PermissionDAO.class));
ViewPermissionResourceProvider.init(injector.getInstance(PermissionDAO.class));
PrivilegeResourceProvider.init(injector.getInstance(PrivilegeDAO.class), injector.getInstance(UserDAO.class),
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
index 71ddc8d..c10d300 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
@@ -18,15 +18,15 @@
package org.apache.ambari.server.controller.internal;
+import java.util.Map;
+import java.util.Set;
+
import org.apache.ambari.server.controller.AmbariManagementController;
import org.apache.ambari.server.controller.ResourceProviderFactory;
import org.apache.ambari.server.controller.spi.Resource;
import org.apache.ambari.server.controller.spi.ResourceProvider;
import org.apache.ambari.server.controller.utilities.ClusterControllerHelper;
-import java.util.Map;
-import java.util.Set;
-
/**
* Abstract resource provider implementation that maps to an Ambari management controller.
*/
@@ -149,6 +149,10 @@ public abstract class AbstractControllerResourceProvider extends AbstractResourc
return new ValidationResourceProvider(propertyIds, keyPropertyIds, managementController);
case AlertDefinition:
return new AlertDefinitionResourceProvider(propertyIds, keyPropertyIds, managementController);
+ case AlertGroup:
+ return new AlertGroupResourceProvider(propertyIds, keyPropertyIds, managementController);
+ case AlertTarget:
+ return new AlertTargetResourceProvider(propertyIds, keyPropertyIds, managementController);
case Controller:
return new ControllerResourceProvider(propertyIds, keyPropertyIds, managementController);
case ClientConfig:
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertGroupResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertGroupResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertGroupResourceProvider.java
new file mode 100644
index 0000000..f14e76f
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertGroupResourceProvider.java
@@ -0,0 +1,268 @@
+/**
+ * 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.ambari.server.controller.internal;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.Resource.Type;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.orm.dao.AlertDispatchDAO;
+import org.apache.ambari.server.orm.entities.AlertGroupEntity;
+import org.apache.ambari.server.orm.entities.AlertTargetEntity;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.alert.AlertGroup;
+import org.apache.commons.lang.StringUtils;
+
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+
+/**
+ * The {@link AlertGroupResourceProvider} class deals with managing the CRUD
+ * operations for {@link AlertGroup}, including property coercion to and from
+ * {@link AlertGroupEntity}.
+ */
+public class AlertGroupResourceProvider extends
+ AbstractControllerResourceProvider {
+
+ protected static final String ALERT_GROUP = "AlertGroup";
+ protected static final String ALERT_GROUP_ID = "AlertGroup/id";
+ protected static final String ALERT_GROUP_CLUSTER_NAME = "AlertGroup/cluster_name";
+ protected static final String ALERT_GROUP_NAME = "AlertGroup/name";
+ protected static final String ALERT_GROUP_DEFAULT = "AlertGroup/default";
+ protected static final String ALERT_GROUP_DEFINITIONS = "AlertGroup/definitions";
+ protected static final String ALERT_GROUP_TARGETS = "AlertGroup/targets";
+
+ private static final Set<String> PK_PROPERTY_IDS = new HashSet<String>(
+ Arrays.asList(ALERT_GROUP_ID, ALERT_GROUP_CLUSTER_NAME));
+
+ /**
+ * Group DAO
+ */
+ @Inject
+ private static AlertDispatchDAO s_dao;
+
+ /**
+ * Initializes the injectable members of this class with the specified
+ * injector.
+ *
+ * @param injector
+ * the injector (not {@code null}).
+ */
+ @Inject
+ public static void init(Injector injector) {
+ s_dao = injector.getInstance(AlertDispatchDAO.class);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param propertyIds
+ * @param keyPropertyIds
+ * @param managementController
+ */
+ AlertGroupResourceProvider(Set<String> propertyIds,
+ Map<Type, String> keyPropertyIds,
+ AmbariManagementController managementController) {
+ super(propertyIds, keyPropertyIds, managementController);
+ }
+
+ @Override
+ public RequestStatus createResources(final Request request)
+ throws SystemException,
+ UnsupportedPropertyException, ResourceAlreadyExistsException,
+ NoSuchParentResourceException {
+
+ createResources(new Command<Void>() {
+ @Override
+ public Void invoke() throws AmbariException {
+ createAlertGroups(request.getProperties());
+ return null;
+ }
+ });
+
+ notifyCreate(Resource.Type.AlertGroup, request);
+ return getRequestStatus(null);
+ }
+
+ @Override
+ public Set<Resource> getResources(Request request, Predicate predicate)
+ throws SystemException, UnsupportedPropertyException,
+ NoSuchResourceException, NoSuchParentResourceException {
+
+ Set<Resource> results = new HashSet<Resource>();
+ Set<String> requestPropertyIds = getRequestPropertyIds(request, predicate);
+
+ for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
+ String clusterName = (String) propertyMap.get(ALERT_GROUP_CLUSTER_NAME);
+
+ if (null == clusterName || clusterName.isEmpty()) {
+ throw new IllegalArgumentException("The cluster name is required when retrieving alert groups");
+ }
+
+ String id = (String) propertyMap.get(ALERT_GROUP_ID);
+ if (null != id) {
+ AlertGroupEntity entity = s_dao.findGroupById(Long.parseLong(id));
+ if (null != entity) {
+ results.add(toResource(false, clusterName, entity, requestPropertyIds));
+ }
+ } else {
+ Cluster cluster = null;
+
+ try {
+ cluster = getManagementController().getClusters().getCluster(clusterName);
+ } catch (AmbariException ae) {
+ throw new NoSuchResourceException("Parent Cluster resource doesn't exist", ae);
+ }
+
+ List<AlertGroupEntity> entities = s_dao.findAllGroups(cluster.getClusterId());
+
+ for (AlertGroupEntity entity : entities) {
+ results.add(toResource(true, clusterName, entity, requestPropertyIds));
+ }
+ }
+ }
+
+ return results;
+ }
+
+ @Override
+ public RequestStatus updateResources(Request request, Predicate predicate)
+ throws SystemException, UnsupportedPropertyException,
+ NoSuchResourceException, NoSuchParentResourceException {
+
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public RequestStatus deleteResources(Predicate predicate)
+ throws SystemException, UnsupportedPropertyException,
+ NoSuchResourceException, NoSuchParentResourceException {
+
+ Set<Resource> resources = getResources(new RequestImpl(null, null, null,
+ null), predicate);
+
+ Set<Long> groupIds = new HashSet<Long>();
+
+ for (final Resource resource : resources) {
+ Long id = (Long) resource.getPropertyValue(ALERT_GROUP_ID);
+ groupIds.add(id);
+ }
+
+ for (Long groupId : groupIds) {
+ LOG.info("Deleting alert target {}", groupId);
+
+ final AlertGroupEntity entity = s_dao.findGroupById(groupId.longValue());
+
+ modifyResources(new Command<Void>() {
+ @Override
+ public Void invoke() throws AmbariException {
+ s_dao.remove(entity);
+ return null;
+ }
+ });
+ }
+
+ notifyDelete(Resource.Type.AlertGroup, predicate);
+ return getRequestStatus(null);
+ }
+
+ @Override
+ protected Set<String> getPKPropertyIds() {
+ return PK_PROPERTY_IDS;
+ }
+
+ /**
+ * Create and persist {@link AlertTargetEntity} from the map of properties.
+ *
+ * @param requestMaps
+ * @throws AmbariException
+ */
+ private void createAlertGroups(Set<Map<String, Object>> requestMaps)
+ throws AmbariException {
+
+ List<AlertGroupEntity> entities = new ArrayList<AlertGroupEntity>();
+ for (Map<String, Object> requestMap : requestMaps) {
+ AlertGroupEntity entity = new AlertGroupEntity();
+
+ String name = (String) requestMap.get(ALERT_GROUP_NAME);
+ String clusterName = (String) requestMap.get(ALERT_GROUP_CLUSTER_NAME);
+
+ if (StringUtils.isEmpty(name)) {
+ throw new IllegalArgumentException(
+ "The name of the alert group is required.");
+ }
+
+ if (StringUtils.isEmpty(clusterName)) {
+ throw new IllegalArgumentException(
+ "The name of the cluster is required when creating an alert group.");
+ }
+
+ Cluster cluster = getManagementController().getClusters().getCluster(
+ clusterName);
+
+ entity.setClusterId(cluster.getClusterId());
+ entity.setDefault(false);
+ entity.setGroupName(name);
+
+ entities.add(entity);
+ }
+
+ s_dao.createGroups(entities);
+ }
+
+ /**
+ * Convert the given {@link AlertGroupEntity} to a {@link Resource}.
+ *
+ * @param isCollection
+ * {@code true} if the resource is part of a collection.
+ * @param entity
+ * the entity to convert.
+ * @param requestedIds
+ * the properties that were requested or {@code null} for all.
+ * @return the resource representation of the entity (never {@code null}).
+ */
+ private Resource toResource(boolean isCollection, String clusterName,
+ AlertGroupEntity entity,
+ Set<String> requestedIds) {
+
+ Resource resource = new ResourceImpl(Resource.Type.AlertGroup);
+ resource.setProperty(ALERT_GROUP_ID, entity.getGroupId());
+ resource.setProperty(ALERT_GROUP_NAME, entity.getGroupName());
+ resource.setProperty(ALERT_GROUP_CLUSTER_NAME, clusterName);
+
+ setResourceProperty(resource, ALERT_GROUP_DEFAULT,
+ entity.isDefault(), requestedIds);
+
+ return resource;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertTargetResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertTargetResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertTargetResourceProvider.java
new file mode 100644
index 0000000..e00f60f
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertTargetResourceProvider.java
@@ -0,0 +1,258 @@
+/**
+ * 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.ambari.server.controller.internal;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.Resource.Type;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.orm.dao.AlertDispatchDAO;
+import org.apache.ambari.server.orm.entities.AlertTargetEntity;
+import org.apache.ambari.server.state.alert.AlertTarget;
+import org.apache.commons.lang.StringUtils;
+
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+
+/**
+ * The {@link AlertTargetResourceProvider} class deals with managing the CRUD
+ * operations for {@link AlertTarget}, including property coercion to and from
+ * {@link AlertTargetEntity}.
+ */
+public class AlertTargetResourceProvider extends
+ AbstractControllerResourceProvider {
+
+ protected static final String ALERT_TARGET = "AlertTarget";
+ protected static final String ALERT_TARGET_ID = "AlertTarget/id";
+ protected static final String ALERT_TARGET_NAME = "AlertTarget/name";
+ protected static final String ALERT_TARGET_DESCRIPTION = "AlertTarget/description";
+ protected static final String ALERT_TARGET_NOTIFICATION_TYPE = "AlertTarget/notification_type";
+ protected static final String ALERT_TARGET_PROPERTIES = "AlertTarget/properties";
+ protected static final String ALERT_TARGET_GROUPS = "AlertTarget/groups";
+
+ private static final Set<String> PK_PROPERTY_IDS = new HashSet<String>(
+ Arrays.asList(ALERT_TARGET_ID, ALERT_TARGET_NAME));
+
+ /**
+ * Target DAO
+ */
+ @Inject
+ private static AlertDispatchDAO s_dao;
+
+ /**
+ * Initializes the injectable members of this class with the specified
+ * injector.
+ *
+ * @param injector
+ * the injector (not {@code null}).
+ */
+ @Inject
+ public static void init(Injector injector) {
+ s_dao = injector.getInstance(AlertDispatchDAO.class);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param propertyIds
+ * @param keyPropertyIds
+ * @param managementController
+ */
+ AlertTargetResourceProvider(Set<String> propertyIds,
+ Map<Type, String> keyPropertyIds,
+ AmbariManagementController managementController) {
+ super(propertyIds, keyPropertyIds, managementController);
+ }
+
+ @Override
+ public RequestStatus createResources(final Request request)
+ throws SystemException,
+ UnsupportedPropertyException, ResourceAlreadyExistsException,
+ NoSuchParentResourceException {
+
+ createResources(new Command<Void>() {
+ @Override
+ public Void invoke() throws AmbariException {
+ createAlertTargets(request.getProperties());
+ return null;
+ }
+ });
+
+ notifyCreate(Resource.Type.AlertTarget, request);
+ return getRequestStatus(null);
+ }
+
+ @Override
+ public Set<Resource> getResources(Request request, Predicate predicate)
+ throws SystemException, UnsupportedPropertyException,
+ NoSuchResourceException, NoSuchParentResourceException {
+
+ Set<Resource> results = new HashSet<Resource>();
+ Set<String> requestPropertyIds = getRequestPropertyIds(request, predicate);
+
+ if( null == predicate ){
+ List<AlertTargetEntity> entities = s_dao.findAllTargets();
+ for (AlertTargetEntity entity : entities) {
+ results.add(toResource(true, entity, requestPropertyIds));
+ }
+ } else {
+ for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
+ String id = (String) propertyMap.get(ALERT_TARGET_ID);
+ if (null == id) {
+ continue;
+ }
+
+ AlertTargetEntity entity = s_dao.findTargetById(Long.parseLong(id));
+ if (null != entity) {
+ results.add(toResource(false, entity, requestPropertyIds));
+ }
+ }
+ }
+
+ return results;
+ }
+
+ @Override
+ public RequestStatus updateResources(Request request, Predicate predicate)
+ throws SystemException, UnsupportedPropertyException,
+ NoSuchResourceException, NoSuchParentResourceException {
+
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public RequestStatus deleteResources(Predicate predicate)
+ throws SystemException, UnsupportedPropertyException,
+ NoSuchResourceException, NoSuchParentResourceException {
+
+ Set<Resource> resources = getResources(new RequestImpl(null, null, null,
+ null), predicate);
+
+ Set<Long> targetIds = new HashSet<Long>();
+
+ for (final Resource resource : resources) {
+ Long id = (Long) resource.getPropertyValue(ALERT_TARGET_ID);
+ targetIds.add(id);
+ }
+
+ for (Long targetId : targetIds) {
+ LOG.info("Deleting alert target {}", targetId);
+
+ final AlertTargetEntity entity = s_dao.findTargetById(targetId.longValue());
+
+ modifyResources(new Command<Void>() {
+ @Override
+ public Void invoke() throws AmbariException {
+ s_dao.remove(entity);
+ return null;
+ }
+ });
+ }
+
+ notifyDelete(Resource.Type.AlertTarget, predicate);
+ return getRequestStatus(null);
+ }
+
+ @Override
+ protected Set<String> getPKPropertyIds() {
+ return PK_PROPERTY_IDS;
+ }
+
+ /**
+ * Create and persist {@link AlertTargetEntity} from the map of properties.
+ *
+ * @param requestMaps
+ * @throws AmbariException
+ */
+ private void createAlertTargets(Set<Map<String, Object>> requestMaps)
+ throws AmbariException {
+ List<AlertTargetEntity> entities = new ArrayList<AlertTargetEntity>();
+ for (Map<String, Object> requestMap : requestMaps) {
+ AlertTargetEntity entity = new AlertTargetEntity();
+
+ String name = (String) requestMap.get(ALERT_TARGET_NAME);
+ String description = (String) requestMap.get(ALERT_TARGET_DESCRIPTION);
+ String notificationType = (String) requestMap.get(ALERT_TARGET_NOTIFICATION_TYPE);
+ String properties = (String) requestMap.get(ALERT_TARGET_PROPERTIES);
+
+ if (StringUtils.isEmpty(name)) {
+ throw new IllegalArgumentException(
+ "The name of the alert target is required.");
+ }
+
+ if (StringUtils.isEmpty(notificationType)) {
+ throw new IllegalArgumentException(
+ "The type of the alert target is required.");
+ }
+
+ entity.setDescription(description);
+ entity.setNotificationType(notificationType);
+ entity.setProperties(properties);
+ entity.setTargetName(name);
+
+ entities.add(entity);
+ }
+
+ s_dao.createTargets(entities);
+ }
+
+ /**
+ * Convert the given {@link AlertTargetEntity} to a {@link Resource}.
+ *
+ * @param isCollection
+ * {@code true} if the resource is part of a collection.
+ * @param entity
+ * the entity to convert.
+ * @param requestedIds
+ * the properties that were requested or {@code null} for all.
+ * @return the resource representation of the entity (never {@code null}).
+ */
+ private Resource toResource(boolean isCollection, AlertTargetEntity entity,
+ Set<String> requestedIds) {
+
+ Resource resource = new ResourceImpl(Resource.Type.AlertTarget);
+ resource.setProperty(ALERT_TARGET_ID, entity.getTargetId());
+ resource.setProperty(ALERT_TARGET_NAME, entity.getTargetName());
+
+ setResourceProperty(resource, ALERT_TARGET_DESCRIPTION,
+ entity.getDescription(), requestedIds);
+
+ setResourceProperty(resource, ALERT_TARGET_NOTIFICATION_TYPE,
+ entity.getNotificationType(), requestedIds);
+
+ setResourceProperty(resource, ALERT_TARGET_PROPERTIES,
+ entity.getProperties(), requestedIds);
+
+ return resource;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
index b10b4bc..3114809 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
@@ -115,6 +115,8 @@ public interface Resource {
HostComponentProcess,
Permission,
AlertDefinition,
+ AlertGroup,
+ AlertTarget,
AmbariPrivilege,
ClusterPrivilege,
ViewPrivilege,
@@ -196,6 +198,8 @@ public interface Resource {
public static final Type HostComponentProcess = InternalType.HostComponentProcess.getType();
public static final Type Permission = InternalType.Permission.getType();
public static final Type AlertDefinition = InternalType.AlertDefinition.getType();
+ public static final Type AlertGroup = InternalType.AlertGroup.getType();
+ public static final Type AlertTarget = InternalType.AlertTarget.getType();
public static final Type AmbariPrivilege = InternalType.AmbariPrivilege.getType();
public static final Type ClusterPrivilege = InternalType.ClusterPrivilege.getType();
public static final Type ViewPrivilege = InternalType.ViewPrivilege.getType();
@@ -315,8 +319,13 @@ public interface Resource {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (this == o) {
+ return true;
+ }
+
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
Type type = (Type) o;
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java
index 2871e62..dfbe747 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java
@@ -51,7 +51,7 @@ public class AlertDispatchDAO {
/**
* Gets an alert group with the specified ID.
- *
+ *
* @param groupId
* the ID of the group to retrieve.
* @return the group or {@code null} if none exists.
@@ -62,7 +62,7 @@ public class AlertDispatchDAO {
/**
* Gets an alert target with the specified ID.
- *
+ *
* @param targetId
* the ID of the target to retrieve.
* @return the target or {@code null} if none exists.
@@ -73,7 +73,7 @@ public class AlertDispatchDAO {
/**
* Gets a notification with the specified ID.
- *
+ *
* @param noticeId
* the ID of the notification to retrieve.
* @return the notification or {@code null} if none exists.
@@ -85,7 +85,7 @@ public class AlertDispatchDAO {
/**
* Gets an alert group with the specified name across all clusters. Alert
* group names are unique within a cluster.
- *
+ *
* @param groupName
* the name of the group (not {@code null}).
* @return the alert group or {@code null} if none exists.
@@ -102,7 +102,7 @@ public class AlertDispatchDAO {
/**
* Gets an alert group with the specified name for the given cluster. Alert
* group names are unique within a cluster.
- *
+ *
* @param clusterId
* the ID of the cluster.
* @param groupName
@@ -122,7 +122,7 @@ public class AlertDispatchDAO {
/**
* Gets an alert target with the specified name. Alert target names are unique
* across all clusters.
- *
+ *
* @param targetName
* the name of the target (not {@code null}).
* @return the alert target or {@code null} if none exists.
@@ -138,7 +138,7 @@ public class AlertDispatchDAO {
/**
* Gets all alert groups stored in the database across all clusters.
- *
+ *
* @return all alert groups or empty list if none exist (never {@code null}).
*/
public List<AlertGroupEntity> findAllGroups() {
@@ -150,7 +150,7 @@ public class AlertDispatchDAO {
/**
* Gets all alert groups stored in the database for the specified cluster.
- *
+ *
* @return all alert groups in the specified cluster or empty list if none
* exist (never {@code null}).
*/
@@ -165,7 +165,7 @@ public class AlertDispatchDAO {
/**
* Gets all alert targets stored in the database.
- *
+ *
* @return all alert targets or empty list if none exist (never {@code null}).
*/
public List<AlertTargetEntity> findAllTargets() {
@@ -177,7 +177,7 @@ public class AlertDispatchDAO {
/**
* Gets all alert notifications stored in the database.
- *
+ *
* @return all alert notifications or empty list if none exist (never
* {@code null}).
*/
@@ -189,6 +189,23 @@ public class AlertDispatchDAO {
}
/**
+ * Persists new alert groups.
+ *
+ * @param entities
+ * the groups to persist (not {@code null}).
+ */
+ @Transactional
+ public void createGroups(List<AlertGroupEntity> entities) {
+ if (null == entities) {
+ return;
+ }
+
+ for (AlertGroupEntity entity : entities) {
+ create(entity);
+ }
+ }
+
+ /**
* Persists a new alert group.
*
* @param alertGroup
@@ -201,7 +218,7 @@ public class AlertDispatchDAO {
/**
* Refresh the state of the alert group from the database.
- *
+ *
* @param alertGroup
* the group to refresh (not {@code null}).
*/
@@ -212,7 +229,7 @@ public class AlertDispatchDAO {
/**
* Merge the speicified alert group with the existing group in the database.
- *
+ *
* @param alertGroup
* the group to merge (not {@code null}).
* @return the updated group with merged content (never {@code null}).
@@ -224,7 +241,7 @@ public class AlertDispatchDAO {
/**
* Removes the specified alert group from the database.
- *
+ *
* @param alertGroup
* the group to remove.
*/
@@ -234,8 +251,25 @@ public class AlertDispatchDAO {
}
/**
+ * Persists new alert targets.
+ *
+ * @param entities
+ * the targets to persist (not {@code null}).
+ */
+ @Transactional
+ public void createTargets(List<AlertTargetEntity> entities) {
+ if (null == entities) {
+ return;
+ }
+
+ for (AlertTargetEntity entity : entities) {
+ create(entity);
+ }
+ }
+
+ /**
* Persists a new alert target.
- *
+ *
* @param alertTarget
* the target to persist (not {@code null}).
*/
@@ -246,7 +280,7 @@ public class AlertDispatchDAO {
/**
* Refresh the state of the alert target from the database.
- *
+ *
* @param alertTarget
* the target to refresh (not {@code null}).
*/
@@ -257,7 +291,7 @@ public class AlertDispatchDAO {
/**
* Merge the speicified alert target with the existing target in the database.
- *
+ *
* @param alertTarget
* the target to merge (not {@code null}).
* @return the updated target with merged content (never {@code null}).
@@ -269,7 +303,7 @@ public class AlertDispatchDAO {
/**
* Removes the specified alert target from the database.
- *
+ *
* @param alertTarget
* the target to remove.
*/
@@ -280,7 +314,7 @@ public class AlertDispatchDAO {
/**
* Persists a new notification.
- *
+ *
* @param alertNotice
* the notification to persist (not {@code null}).
*/
@@ -291,7 +325,7 @@ public class AlertDispatchDAO {
/**
* Refresh the state of the notification from the database.
- *
+ *
* @param alertNotice
* the notification to refresh (not {@code null}).
*/
@@ -302,7 +336,7 @@ public class AlertDispatchDAO {
/**
* Merge the specified notification with the existing target in the database.
- *
+ *
* @param alertNotice
* the notification to merge (not {@code null}).
* @return the updated notification with merged content (never {@code null}).
@@ -314,7 +348,7 @@ public class AlertDispatchDAO {
/**
* Removes the specified notification from the database.
- *
+ *
* @param alertNotice
* the notification to remove.
*/
@@ -327,7 +361,7 @@ public class AlertDispatchDAO {
* Removes notifications for the specified alert definition ID. This will
* invoke {@link EntityManager#clear()} when completed since the JPQL
* statement will remove entries without going through the EM.
- *
+ *
* @param definitionId
* the ID of the definition to remove.
*/
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertGroup.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertGroup.java b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertGroup.java
new file mode 100644
index 0000000..659efa9
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertGroup.java
@@ -0,0 +1,124 @@
+/**
+ * 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.ambari.server.state.alert;
+
+import java.util.List;
+
+/**
+ * The {@link AlertGroup} class represents a grouping of {@link AlertDefinition}
+ * instances as well as the targets that will be invoked when an alert is
+ * triggered.
+ */
+public class AlertGroup {
+ private String m_id;
+ private String m_name;
+ private String m_clusterName;
+ private boolean m_isDefault;
+ private List<AlertDefinition> m_definitions;
+ private List<AlertTarget> m_targets;
+
+ /**
+ * @return the id
+ */
+ public String getId() {
+ return m_id;
+ }
+
+ /**
+ * @param id
+ * the id to set
+ */
+ public void setId(String id) {
+ m_id = id;
+ }
+
+ /**
+ * @return the name
+ */
+ public String getName() {
+ return m_name;
+ }
+
+ /**
+ * @param name
+ * the name to set
+ */
+ public void setName(String name) {
+ m_name = name;
+ }
+
+ /**
+ * @return the clusterName
+ */
+ public String getClusterName() {
+ return m_clusterName;
+ }
+
+ /**
+ * @param clusterName
+ * the clusterName to set
+ */
+ public void setClusterName(String clusterName) {
+ m_clusterName = clusterName;
+ }
+
+ /**
+ * @return the isDefault
+ */
+ public boolean isDefault() {
+ return m_isDefault;
+ }
+
+ /**
+ * @param isDefault
+ * the isDefault to set
+ */
+ public void setDefault(boolean isDefault) {
+ m_isDefault = isDefault;
+ }
+
+ /**
+ * @return the definitions
+ */
+ public List<AlertDefinition> getDefinitions() {
+ return m_definitions;
+ }
+
+ /**
+ * @param definitions
+ * the definitions to set
+ */
+ public void setDefinitions(List<AlertDefinition> definitions) {
+ m_definitions = definitions;
+ }
+
+ /**
+ * @return the targets
+ */
+ public List<AlertTarget> getTargets() {
+ return m_targets;
+ }
+
+ /**
+ * @param targets
+ * the targets to set
+ */
+ public void setTargets(List<AlertTarget> targets) {
+ m_targets = targets;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertTarget.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertTarget.java b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertTarget.java
new file mode 100644
index 0000000..21e83d9
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertTarget.java
@@ -0,0 +1,123 @@
+/**
+ * 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.ambari.server.state.alert;
+
+import java.util.List;
+
+/**
+ * The {@link AlertTarget} class represents a dispatch mechanism and audience
+ * that will receive information about alerts int he system.
+ */
+public class AlertTarget {
+ private String m_id;
+ private String m_name;
+ private String m_description;
+ private String m_notificationType;
+ private String m_properties;
+ private List<AlertGroup> m_groups;
+
+ /**
+ * @return the id
+ */
+ public String getId() {
+ return m_id;
+ }
+
+ /**
+ * @param id
+ * the id to set
+ */
+ public void setId(String id) {
+ m_id = id;
+ }
+
+ /**
+ * @return the name
+ */
+ public String getName() {
+ return m_name;
+ }
+
+ /**
+ * @param name
+ * the name to set
+ */
+ public void setName(String name) {
+ m_name = name;
+ }
+
+ /**
+ * @return the description
+ */
+ public String getDescription() {
+ return m_description;
+ }
+
+ /**
+ * @param description
+ * the description to set
+ */
+ public void setDescription(String description) {
+ m_description = description;
+ }
+
+ /**
+ * @return the notificationType
+ */
+ public String getNotificationType() {
+ return m_notificationType;
+ }
+
+ /**
+ * @param notificationType
+ * the notificationType to set
+ */
+ public void setNotificationType(String notificationType) {
+ m_notificationType = notificationType;
+ }
+
+ /**
+ * @return the properties
+ */
+ public String getProperties() {
+ return m_properties;
+ }
+
+ /**
+ * @param properties
+ * the properties to set
+ */
+ public void setProperties(String properties) {
+ m_properties = properties;
+ }
+
+ /**
+ * @return the groups
+ */
+ public List<AlertGroup> getGroups() {
+ return m_groups;
+ }
+
+ /**
+ * @param groups
+ * the groups to set
+ */
+ public void setGroups(List<AlertGroup> groups) {
+ m_groups = groups;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/main/java/org/apache/ambari/server/state/alert/TargetType.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/TargetType.java b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/TargetType.java
new file mode 100644
index 0000000..e2564cc
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/TargetType.java
@@ -0,0 +1,37 @@
+/**
+ * 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.ambari.server.state.alert;
+
+import org.apache.ambari.server.orm.dao.AlertsDAO;
+
+/**
+ * The {@link TargetType} enumeration is used to represent the built-in target
+ * dispatch mechanisms that are supported internally. {@link AlertTarget}
+ * instances may have other custom target types that are not listed here.
+ */
+public enum TargetType {
+ /**
+ * Alerts will be distributed via email.
+ */
+ EMAIL,
+
+ /**
+ * {@link AlertsDAO} will be distributed via SNMP.
+ */
+ SNMP;
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
index cc5bb5b..75265b7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
@@ -555,6 +555,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
impl.alertDefinitionHash.invalidate(impl.getClusterName(), hostName);
impl.alertDefinitionHash.enqueueAgentCommands(impl.getClusterName(),
Collections.singleton(hostName));
+
+ impl.updateLastOpInfo(event.getType(), event.getOpTimestamp());
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/main/resources/key_properties.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/key_properties.json b/ambari-server/src/main/resources/key_properties.json
index 06ebb61..3007fee 100644
--- a/ambari-server/src/main/resources/key_properties.json
+++ b/ambari-server/src/main/resources/key_properties.json
@@ -149,6 +149,13 @@
"Cluster": "AlertDefinition/cluster_name",
"AlertDefinition": "AlertDefinition/id"
},
+ "AlertTarget": {
+ "AlertTarget": "AlertTarget/id"
+ },
+ "AlertGroup": {
+ "Cluster": "AlertGroup/cluster_name",
+ "AlertGroup": "AlertGroup/id"
+ },
"Controller": {
"Controller": "Controllers/name"
},
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/main/resources/properties.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/properties.json b/ambari-server/src/main/resources/properties.json
index bc2ad22..9574aa9 100644
--- a/ambari-server/src/main/resources/properties.json
+++ b/ambari-server/src/main/resources/properties.json
@@ -425,7 +425,23 @@
"AlertDefinition/enabled",
"AlertDefinition/scope",
"AlertDefinition/source"
- ],
+ ],
+ "AlertGroup": [
+ "AlertGroup/id",
+ "AlertGroup/name",
+ "AlertGroup/cluster_name",
+ "AlertGroup/default",
+ "AlertGroup/definitions",
+ "AlertGroup/targets"
+ ],
+ "AlertTarget": [
+ "AlertTarget/id",
+ "AlertTarget/name",
+ "AlertTarget/description",
+ "AlertTarget/notification_type",
+ "AlertTarget/properties",
+ "AlertTarget/groups"
+ ],
"Controller":[
"Controllers/name",
"LDAP/configured",
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a4644b8/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertGroupResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertGroupResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertGroupResourceProviderTest.java
new file mode 100644
index 0000000..c9428b7
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertGroupResourceProviderTest.java
@@ -0,0 +1,335 @@
+/**
+ * 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.ambari.server.controller.internal;
+
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.createStrictMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.resetToStrict;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PredicateBuilder;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.metadata.ActionMetadata;
+import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.orm.dao.AlertDispatchDAO;
+import org.apache.ambari.server.orm.entities.AlertGroupEntity;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.inject.Binder;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.util.Modules;
+
+/**
+ * {@link AlertGroupResourceProvider} tests.
+ */
+public class AlertGroupResourceProviderTest {
+
+ private static final Long ALERT_GROUP_ID = Long.valueOf(28);
+ private static final String ALERT_GROUP_NAME = "Important Alerts";
+ private static final long ALERT_GROUP_CLUSTER_ID = 1L;
+ private static final String ALERT_GROUP_CLUSTER_NAME = "c1";
+
+ private AlertDispatchDAO m_dao;
+ private Injector m_injector;
+
+ @Before
+ public void before() {
+ m_dao = createStrictMock(AlertDispatchDAO.class);
+
+ m_injector = Guice.createInjector(Modules.override(
+ new InMemoryDefaultTestModule()).with(new MockModule()));
+
+ AlertGroupResourceProvider.init(m_injector);
+ }
+
+ /**
+ * @throws Exception
+ */
+ @Test
+ public void testGetResourcesNoPredicate() throws Exception {
+ AlertGroupResourceProvider provider = createProvider(null);
+
+ Request request = PropertyHelper.getReadRequest("AlertGroup/cluster_name",
+ "AlertGroup/id");
+
+ Set<Resource> results = provider.getResources(request, null);
+
+ assertEquals(0, results.size());
+ }
+
+ /**
+ * @throws Exception
+ */
+ @Test
+ public void testGetResourcesClusterPredicate() throws Exception {
+ Request request = PropertyHelper.getReadRequest(
+ AlertGroupResourceProvider.ALERT_GROUP_ID,
+ AlertGroupResourceProvider.ALERT_GROUP_NAME,
+ AlertGroupResourceProvider.ALERT_GROUP_CLUSTER_NAME,
+ AlertGroupResourceProvider.ALERT_GROUP_DEFAULT);
+
+ AmbariManagementController amc = createMock(AmbariManagementController.class);
+ Clusters clusters = createMock(Clusters.class);
+ Cluster cluster = createMock(Cluster.class);
+ expect(amc.getClusters()).andReturn(clusters).atLeastOnce();
+ expect(clusters.getCluster((String) anyObject())).andReturn(cluster).atLeastOnce();
+ expect(cluster.getClusterId()).andReturn(Long.valueOf(1)).anyTimes();
+
+ Predicate predicate = new PredicateBuilder().property(
+ AlertGroupResourceProvider.ALERT_GROUP_CLUSTER_NAME).equals("c1").toPredicate();
+
+ expect(m_dao.findAllGroups(ALERT_GROUP_CLUSTER_ID)).andReturn(
+ getMockEntities());
+
+ replay(amc, clusters, cluster, m_dao);
+
+ AlertGroupResourceProvider provider = createProvider(amc);
+ Set<Resource> results = provider.getResources(request, predicate);
+
+ assertEquals(1, results.size());
+
+ Resource r = results.iterator().next();
+
+ Assert.assertEquals(ALERT_GROUP_NAME,
+ r.getPropertyValue(AlertGroupResourceProvider.ALERT_GROUP_NAME));
+
+ Assert.assertEquals(ALERT_GROUP_ID,
+ r.getPropertyValue(AlertGroupResourceProvider.ALERT_GROUP_ID));
+
+ Assert.assertEquals(ALERT_GROUP_CLUSTER_NAME,
+ r.getPropertyValue(AlertGroupResourceProvider.ALERT_GROUP_CLUSTER_NAME));
+
+ verify(amc, clusters, cluster, m_dao);
+ }
+
+ /**
+ * @throws Exception
+ */
+ @Test
+ public void testGetSingleResource() throws Exception {
+ Request request = PropertyHelper.getReadRequest(
+ AlertGroupResourceProvider.ALERT_GROUP_ID,
+ AlertGroupResourceProvider.ALERT_GROUP_NAME,
+ AlertGroupResourceProvider.ALERT_GROUP_CLUSTER_NAME,
+ AlertGroupResourceProvider.ALERT_GROUP_DEFAULT);
+
+ AmbariManagementController amc = createMock(AmbariManagementController.class);
+
+ Predicate predicate = new PredicateBuilder().property(
+ AlertGroupResourceProvider.ALERT_GROUP_CLUSTER_NAME).equals(
+ ALERT_GROUP_CLUSTER_NAME).and().property(
+ AlertGroupResourceProvider.ALERT_GROUP_ID).equals(
+ ALERT_GROUP_ID.toString()).toPredicate();
+
+ expect(m_dao.findGroupById(ALERT_GROUP_ID.longValue())).andReturn(
+ getMockEntities().get(0));
+
+ replay(amc, m_dao);
+
+ AlertGroupResourceProvider provider = createProvider(amc);
+ Set<Resource> results = provider.getResources(request, predicate);
+
+ assertEquals(1, results.size());
+
+ Resource r = results.iterator().next();
+
+ Assert.assertEquals(ALERT_GROUP_NAME,
+ r.getPropertyValue(AlertGroupResourceProvider.ALERT_GROUP_NAME));
+
+ Assert.assertEquals(ALERT_GROUP_ID,
+ r.getPropertyValue(AlertGroupResourceProvider.ALERT_GROUP_ID));
+
+ Assert.assertEquals(ALERT_GROUP_CLUSTER_NAME,
+ r.getPropertyValue(AlertGroupResourceProvider.ALERT_GROUP_CLUSTER_NAME));
+
+ verify(amc, m_dao);
+ }
+
+ /**
+ * @throws Exception
+ */
+ @Test
+ public void testCreateResources() throws Exception {
+ AmbariManagementController amc = createMock(AmbariManagementController.class);
+ Clusters clusters = createMock(Clusters.class);
+ Cluster cluster = createMock(Cluster.class);
+ expect(amc.getClusters()).andReturn(clusters).atLeastOnce();
+ expect(clusters.getCluster((String) anyObject())).andReturn(cluster).atLeastOnce();
+ expect(cluster.getClusterId()).andReturn(Long.valueOf(1)).anyTimes();
+
+ Capture<List<AlertGroupEntity>> listCapture = new Capture<List<AlertGroupEntity>>();
+
+ m_dao.createGroups(capture(listCapture));
+ expectLastCall();
+
+ replay(amc, clusters, cluster, m_dao);
+
+ AlertGroupResourceProvider provider = createProvider(amc);
+ Map<String, Object> requestProps = new HashMap<String, Object>();
+ requestProps.put(AlertGroupResourceProvider.ALERT_GROUP_NAME,
+ ALERT_GROUP_NAME);
+
+ requestProps.put(AlertGroupResourceProvider.ALERT_GROUP_CLUSTER_NAME,
+ ALERT_GROUP_CLUSTER_NAME);
+
+ Request request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), null);
+ provider.createResources(request);
+
+ Assert.assertTrue(listCapture.hasCaptured());
+ AlertGroupEntity entity = listCapture.getValue().get(0);
+ Assert.assertNotNull(entity);
+
+ Assert.assertEquals(ALERT_GROUP_NAME, entity.getGroupName());
+ Assert.assertEquals(ALERT_GROUP_CLUSTER_ID,
+ entity.getClusterId().longValue());
+
+ verify(amc, clusters, cluster, m_dao);
+ }
+
+ /**
+ * @throws Exception
+ */
+ @Test
+ public void testUpdateResources() throws Exception {
+ }
+
+ /**
+ * @throws Exception
+ */
+ @Test
+ public void testDeleteResources() throws Exception {
+ AmbariManagementController amc = createMock(AmbariManagementController.class);
+ Clusters clusters = createMock(Clusters.class);
+ Cluster cluster = createMock(Cluster.class);
+ expect(amc.getClusters()).andReturn(clusters).atLeastOnce();
+ expect(clusters.getCluster((String) anyObject())).andReturn(cluster).atLeastOnce();
+ expect(cluster.getClusterId()).andReturn(Long.valueOf(1)).anyTimes();
+
+ Capture<AlertGroupEntity> entityCapture = new Capture<AlertGroupEntity>();
+ Capture<List<AlertGroupEntity>> listCapture = new Capture<List<AlertGroupEntity>>();
+
+ m_dao.createGroups(capture(listCapture));
+ expectLastCall();
+
+ replay(amc, clusters, cluster, m_dao);
+
+ AlertGroupResourceProvider provider = createProvider(amc);
+
+ Map<String, Object> requestProps = new HashMap<String, Object>();
+ requestProps.put(AlertGroupResourceProvider.ALERT_GROUP_NAME,
+ ALERT_GROUP_NAME);
+
+ requestProps.put(AlertGroupResourceProvider.ALERT_GROUP_CLUSTER_NAME,
+ ALERT_GROUP_CLUSTER_NAME);
+
+ Request request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), null);
+ provider.createResources(request);
+
+ Assert.assertTrue(listCapture.hasCaptured());
+ AlertGroupEntity entity = listCapture.getValue().get(0);
+ Assert.assertNotNull(entity);
+
+ Predicate predicate = new PredicateBuilder().property(
+ AlertGroupResourceProvider.ALERT_GROUP_CLUSTER_NAME).equals(
+ ALERT_GROUP_CLUSTER_NAME).and().property(
+ AlertGroupResourceProvider.ALERT_GROUP_ID).equals(
+ ALERT_GROUP_ID.toString()).toPredicate();
+
+ // everything is mocked, there is no DB
+ entity.setGroupId(ALERT_GROUP_ID);
+
+ resetToStrict(m_dao);
+ expect(m_dao.findGroupById(ALERT_GROUP_ID.longValue())).andReturn(entity).anyTimes();
+ m_dao.remove(capture(entityCapture));
+ expectLastCall();
+ replay(m_dao);
+
+ provider.deleteResources(predicate);
+
+ AlertGroupEntity entity1 = entityCapture.getValue();
+ Assert.assertEquals(ALERT_GROUP_ID, entity1.getGroupId());
+
+ verify(amc, clusters, cluster, m_dao);
+ }
+
+ /**
+ * @param amc
+ * @return
+ */
+ private AlertGroupResourceProvider createProvider(
+ AmbariManagementController amc) {
+ return new AlertGroupResourceProvider(
+ PropertyHelper.getPropertyIds(Resource.Type.AlertGroup),
+ PropertyHelper.getKeyPropertyIds(Resource.Type.AlertGroup), amc);
+ }
+
+ /**
+ * @return
+ */
+ private List<AlertGroupEntity> getMockEntities() throws Exception {
+ AlertGroupEntity entity = new AlertGroupEntity();
+ entity.setGroupId(ALERT_GROUP_ID);
+ entity.setGroupName(ALERT_GROUP_NAME);
+ entity.setClusterId(ALERT_GROUP_CLUSTER_ID);
+ entity.setDefault(false);
+ return Arrays.asList(entity);
+ }
+
+ /**
+ *
+ */
+ private class MockModule implements Module {
+ /**
+ *
+ */
+ @Override
+ public void configure(Binder binder) {
+ binder.bind(AlertDispatchDAO.class).toInstance(m_dao);
+ binder.bind(Clusters.class).toInstance(
+ EasyMock.createNiceMock(Clusters.class));
+ binder.bind(Cluster.class).toInstance(
+ EasyMock.createNiceMock(Cluster.class));
+ binder.bind(ActionMetadata.class);
+ }
+ }
+}