[rhq] modules/enterprise modules/integration-tests
by Heiko W. Rupp
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricSchedule.java | 5 ++---
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/MetricsTest.java | 10 ++++------
2 files changed, 6 insertions(+), 9 deletions(-)
New commits:
commit aff60a50e9e04238a3693b9335647cea6a25ed5f
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Mon Jun 3 16:59:19 2013 +0200
BZ 963691 - return scheduleId as int.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricSchedule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricSchedule.java
index 2d012c9..9d21d9f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricSchedule.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricSchedule.java
@@ -68,9 +68,8 @@ public class MetricSchedule {
}
@ApiProperty("The id of the schedule")
- @XmlID
- public String getScheduleId() {
- return ""+scheduleId;
+ public int getScheduleId() {
+ return scheduleId;
}
public void setScheduleId(int scheduleId) {
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/MetricsTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/MetricsTest.java
index bb7288d..6928299 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/MetricsTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/MetricsTest.java
@@ -37,7 +37,6 @@ import org.rhq.modules.integrationTests.restApi.d.MDataPoint;
import org.rhq.modules.integrationTests.restApi.d.Schedule;
import static com.jayway.restassured.RestAssured.given;
-import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
@@ -45,7 +44,6 @@ import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.Matchers.emptyIterable;
import static org.hamcrest.Matchers.isOneOf;
import static org.hamcrest.Matchers.iterableWithSize;
-import static org.junit.matchers.JUnitMatchers.hasItems;
/**
* Test stuff related to metrics
@@ -90,7 +88,7 @@ public class MetricsTest extends AbstractBase {
.pathParam("id", numericScheduleId)
.expect()
.statusCode(200)
- .body("scheduleId", containsString("" + numericScheduleId))
+ .body("scheduleId", is(numericScheduleId))
.header("ETag",notNullValue())
// .body("links", hasItems("edit", "metric", "resource")) TODO
.log().everything()
@@ -107,7 +105,7 @@ public class MetricsTest extends AbstractBase {
.pathParam("id", numericScheduleId)
.expect()
.statusCode(200)
- .body("scheduleId", containsString("" + numericScheduleId))
+ .body("scheduleId", is( numericScheduleId))
.when()
.get("/metric/schedule/{id}");
@@ -132,7 +130,7 @@ public class MetricsTest extends AbstractBase {
.pathParam("id", numericScheduleId)
.expect()
.statusCode(200)
- .body("scheduleId", containsString("" + numericScheduleId))
+ .body("scheduleId", is( numericScheduleId))
.header("ETag", notNullValue())
// .body("links.rel", hasItems("edit", "metric", "resource")) TODO
.log().ifError()
@@ -164,7 +162,7 @@ public class MetricsTest extends AbstractBase {
.queryParam("enabledOnly", false)
.expect()
.statusCode(200)
- .body("scheduleId", hasItem("" + numericScheduleId))
+ .body("scheduleId", hasItem( numericScheduleId))
.body("scheduleName", hasItem(scheduleName))
.log().everything()
.when()
10 years, 11 months
[rhq] 2 commits - modules/enterprise modules/integration-tests
by Heiko W. Rupp
modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java | 51 ++++++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java | 20 ++
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java | 73 +++++++++-
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/Resource.java | 18 ++
6 files changed, 161 insertions(+), 5 deletions(-)
New commits:
commit 581a5b03422cb55dc88551b52231b048acb43f60
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Mon Jun 3 16:17:57 2013 +0200
BZ 966381 - allow to import servers and update resources.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
index 224ab3f..62a85ca 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
@@ -274,6 +274,8 @@ public class AbstractRestBean {
rwt.setTypeId(resourceType.getId());
rwt.setPluginName(resourceType.getPlugin());
rwt.setStatus(res.getInventoryStatus().name());
+ rwt.setLocation(res.getLocation());
+ rwt.setDescription(res.getDescription());
Resource parent = res.getParentResource();
if (parent != null) {
rwt.setParentId(parent.getId());
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 332dfbc..3ee8f19 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -63,6 +63,7 @@ import javax.ws.rs.core.UriInfo;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiError;
+import com.wordnik.swagger.annotations.ApiErrors;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
@@ -96,6 +97,7 @@ import org.rhq.core.domain.util.PageOrdering;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.alert.AlertManagerLocal;
import org.rhq.enterprise.server.core.AgentManagerLocal;
+import org.rhq.enterprise.server.discovery.DiscoveryBossLocal;
import org.rhq.enterprise.server.measurement.AvailabilityManagerLocal;
import org.rhq.enterprise.server.resource.ResourceAlreadyExistsException;
import org.rhq.enterprise.server.resource.ResourceFactoryManagerLocal;
@@ -136,6 +138,8 @@ public class ResourceHandlerBean extends AbstractRestBean {
AgentManagerLocal agentMgr;
@EJB
ResourceFactoryManagerLocal resourceFactory;
+ @EJB
+ DiscoveryBossLocal discoveryBoss;
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
private EntityManager entityManager;
@@ -174,6 +178,50 @@ public class ResourceHandlerBean extends AbstractRestBean {
return builder.build();
}
+ @PUT
+ @Path("/{id:\\d+}")
+ @ApiOperation(value = "Update a single resource (name, description, location) that is committed or import "+
+ "a resource that is new. To do the latter you need to PUT the resource retrieved with a COMMITTED state",
+ responseClass = "ResourceWithType")
+ @ApiErrors({
+ @ApiError(code = 404, reason = NO_RESOURCE_FOR_ID),
+ @ApiError(code = 406, reason = "Tried to update a resource that is not COMMITTED")
+ })
+ public Response updateResource(@ApiParam("Id of the resource to import") @PathParam("id") int resourceId,
+ @ApiParam("Resource to update" ) ResourceWithType resourceWithType,
+ @Context UriInfo uriInfo) {
+
+ Resource res = fetchResource(resourceId);
+
+ if (res.getInventoryStatus()==InventoryStatus.NEW && res.getResourceType().getCategory()!=ResourceCategory.SERVICE && resourceWithType.getStatus().equalsIgnoreCase("COMMITTED")) {
+ // Import
+ discoveryBoss.importResources(caller,new int[] { resourceId});
+
+ res = fetchResource(resourceId);
+
+ ResourceWithType outWithType = fillRWT(res,uriInfo);
+
+ return Response.ok(outWithType).build();
+ }
+
+ // Import was handled above, so we require committed state now
+ if (res.getInventoryStatus()!=InventoryStatus.COMMITTED) {
+ throw new BadArgumentException("Can only update resources in committed state");
+ }
+
+ // No import, so update some of the allowed items
+ Resource in = new Resource(res.getId());
+ in.setName(resourceWithType.getResourceName());
+ in.setDescription(resourceWithType.getDescription());
+ in.setLocation(resourceWithType.getLocation());
+ Resource out = resMgr.updateResource(caller,in);
+
+ ResourceWithType outWithType = fillRWT(out,uriInfo);
+
+ return Response.ok(outWithType).build();
+
+ }
+
@GET @GZIP
@Path("/")
@ApiError(code = 406, reason = "The passed inventory status was invalid")
@@ -189,7 +237,6 @@ public class ResourceHandlerBean extends AbstractRestBean {
ResourceCriteria criteria = new ResourceCriteria();
criteria.addSortName(PageOrdering.ASC);
- criteria.addSortId(PageOrdering.ASC);
if (!status.toLowerCase().equals("all")) {
try {
criteria.addFilterInventoryStatus(InventoryStatus.valueOf(status.toUpperCase()));
@@ -270,7 +317,7 @@ public class ResourceHandlerBean extends AbstractRestBean {
} else {
if (mediaType.equals(wrappedCollectionJsonType)) {
- wrapForPaging(builder,uriInfo,resources,rwtList);
+ wrapForPaging(builder, uriInfo, resources, rwtList);
} else {
GenericEntity<List<ResourceWithType>> list = new GenericEntity<List<ResourceWithType>>(rwtList) {
};
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
index 8273737..f802f35 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
@@ -47,6 +47,8 @@ public class ResourceWithType {
String status;
List<Link> links = new ArrayList<Link>();
private String ancestry;
+ private String location;
+ private String description;
public ResourceWithType() {
}
@@ -156,4 +158,22 @@ public class ResourceWithType {
", ancestry='" + ancestry + '\'' +
'}';
}
+
+ @ApiProperty("The location of the resource (e.g. data center / rack")
+ public String getLocation() {
+ return location;
+ }
+
+ public void setLocation(String location) {
+ this.location = location;
+ }
+
+ @ApiProperty("A description of the resource")
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
}
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
index 6b78fe7..852f802 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
@@ -456,7 +456,7 @@ public class ResourcesTest extends AbstractBase {
.expect()
.statusCode(201)
.log().everything()
- .body("resourceId",instanceOf(Number.class))
+ .body("resourceId", instanceOf(Number.class))
.when()
.post("/resource/platforms");
@@ -511,6 +511,60 @@ public class ResourcesTest extends AbstractBase {
}
@Test
+ public void testCreateUpdateRemovePlatform() throws Exception {
+
+ Resource resource = new Resource();
+ resource.setResourceName("dummy-test");
+ resource.setTypeName("Linux");
+
+ Response response =
+ given()
+ .header(acceptXml)
+ .contentType(ContentType.JSON)
+ .body(resource)
+ .expect()
+ .statusCode(201)
+ .log().ifError()
+ .when()
+ .post("/resource/platforms");
+
+ int platformId=0;
+ try {
+ XmlPath xmlPath = response.xmlPath();
+ Node resource1 = xmlPath.get("resource");
+ Node platformIdNode = resource1.get("resourceId");
+ platformId = Integer.parseInt(platformIdNode.value());
+
+ // Now update the description
+ resource.setDescription("li la lu");
+ resource.setLocation("Datacenter 1");
+ resource.setResourceName("DummY");
+
+ given()
+ .pathParam("id",platformId)
+ .body(resource)
+ .contentType(ContentType.JSON)
+ .header(acceptJson)
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .body("location",is("Datacenter 1"))
+ .body("description",is("li la lu"))
+ .body("resourceName",is("DummY"))
+ .when()
+ .put("/resource/{id}");
+
+ } finally {
+ given()
+ .pathParam("id", platformId)
+ .expect()
+ .statusCode(HttpStatus.SC_NO_CONTENT)
+ .when()
+ .delete("/resource/{id}");
+ }
+ }
+
+ @Test
public void testCreatePlatformUpdateAvailabilityAndRemove() throws Exception {
Resource resource = new Resource();
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/Resource.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/Resource.java
index f060101..5eb33d2 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/Resource.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/Resource.java
@@ -37,6 +37,8 @@ public class Resource {
int typeId;
List<Map> links;
String ancestry;
+ String location;
+ String description;
public Resource() {
}
@@ -112,4 +114,20 @@ public class Resource {
public void setStatus(String status) {
this.status = status;
}
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getLocation() {
+ return location;
+ }
+
+ public void setLocation(String location) {
+ this.location = location;
+ }
}
commit bdd1e0055764d9c6127f8f02b004f940553c3b9f
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Mon Jun 3 12:56:20 2013 +0200
Allow to use the .jsonw prefix to request the application/vnd.rhq.wrapped+json type
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml b/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
index f336c60..164707f 100644
--- a/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
@@ -7,7 +7,7 @@
<context-param>
<param-name>resteasy.media.type.mappings</param-name>
<param-value>html : text/html, json : application/json, xml : application/xml, csv : text/csv, txt: text/plain,
- yaml: application/yaml
+ yaml: application/yaml, jsonw: application/vnd.rhq.wrapped+json
</param-value>
</context-param>
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
index 900ab10..6b78fe7 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
@@ -33,7 +33,6 @@ import com.jayway.restassured.path.json.JsonPath;
import com.jayway.restassured.path.xml.XmlPath;
import com.jayway.restassured.path.xml.element.Node;
import com.jayway.restassured.response.Response;
-import com.jayway.restassured.response.ResponseBody;
import org.apache.http.HttpStatus;
import org.junit.Test;
@@ -344,6 +343,22 @@ public class ResourcesTest extends AbstractBase {
}
@Test
+ public void testGetResourcesWithPagingAndWrappingByExtension() throws Exception {
+
+ given()
+ .queryParam("page", 1)
+ .queryParam("ps", 2) // Unusually small to provoke having more than 1 page
+ .queryParam("category", "service")
+ .expect()
+ .statusCode(200)
+ .log().everything()
+ .body("pageSize",is(2))
+ .body("currentPage",is(1))
+ .when()
+ .get("/resource.jsonw");
+ }
+
+ @Test
public void testGetPlatformsWithPaging() throws Exception {
given()
10 years, 11 months
[rhq] modules/plugins
by Thomas Segismont
modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
New commits:
commit c860e6ebb29c99a399471e610e6c2772ffb66d64
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Mon Jun 3 09:50:35 2013 +0200
Bug 865634 - Add more metrics to AS7 plugin
New commit: enable traits by default
diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index 7213acd..7e9270d 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -8885,8 +8885,8 @@
</c:group>
</plugin-configuration>
- <metric property="virtual-host" dataType="trait" displayName="Virtual Host" description="the virtual host this webapp is deployed to"/>
- <metric property="context-root" dataType="trait" displayName="Context Root" description="the context root of this webapp"/>
+ <metric property="virtual-host" dataType="trait" defaultOn="true" displayName="Virtual Host" description="the virtual host this webapp is deployed to"/>
+ <metric property="context-root" dataType="trait" defaultOn="true" displayName="Context Root" description="the context root of this webapp"/>
<metric property="responseTime"
dataType="calltime" defaultOn="false" units="milliseconds" destinationType="URL"
description="the minimum, maximum, and average response times for requests serviced by this webapp"/>
10 years, 11 months
[rhq] modules/plugins
by John Sanda
modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/CassandraNodeComponent.java | 15 +++++---
modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java | 18 ++++++++++
2 files changed, 28 insertions(+), 5 deletions(-)
New commits:
commit 1231cc220f34fc804e17f99156138973b8a0c6e1
Author: John Sanda <jsanda(a)redhat.com>
Date: Sun Jun 2 23:39:35 2013 -0400
adding support to update seeds property in addNodeMaintenance resource operation
There is an issue in how the yaml document is serialized. It fails to parse.
I am relying on the Cassandra config classes for reading/writing the yaml
config file; so, we may have to explore an alternative approach. Cassandra
reads but does not write the yaml file, and we are having problems with
how the file is being written.
diff --git a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/CassandraNodeComponent.java b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/CassandraNodeComponent.java
index b756f10..9bfb1b0 100644
--- a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/CassandraNodeComponent.java
+++ b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/CassandraNodeComponent.java
@@ -234,12 +234,8 @@ public class CassandraNodeComponent extends JMXServerComponent<ResourceComponent
}
protected OperationResult updateSeedsList(Configuration params) {
- List<String> addresses = new ArrayList<String>();
PropertyList list = params.getList("seedsList");
- for (Property property : list.getList()) {
- PropertySimple simple = (PropertySimple) property;
- addresses.add(simple.getStringValue());
- }
+ List<String> addresses = getAddresses(list);
OperationResult result = new OperationResult();
try {
@@ -252,6 +248,15 @@ public class CassandraNodeComponent extends JMXServerComponent<ResourceComponent
return result;
}
+ protected List<String> getAddresses(PropertyList seedsList) {
+ List<String> addresses = new ArrayList<String>();
+ for (Property property : seedsList.getList()) {
+ PropertySimple simple = (PropertySimple) property;
+ addresses.add(simple.getStringValue());
+ }
+ return addresses;
+ }
+
protected void updateSeedsList(List<String> addresses) throws IOException {
ResourceContext<?> context = getResourceContext();
Configuration pluginConfig = context.getPluginConfiguration();
diff --git a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java
index 88b76c1..a6b5e48 100644
--- a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java
+++ b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java
@@ -25,6 +25,8 @@
package org.rhq.plugins.storage;
+import java.util.List;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.mc4j.ems.connection.EmsConnection;
@@ -99,6 +101,22 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper
resultsList.add(toPropertyMap(opResult));
// update seeds list...
+ List<String> addresses = getAddresses(params.getList("seedsList"));
+ try {
+ opResult = new OpResult();
+ opResult.operation = "Update seeds list";
+ updateSeedsList(addresses);
+ opResult.succeeded = true;
+ } catch (Exception e) {
+ log.error("An error occurred while updating the seeds lists for " + getResourceContext().getResourceKey(),
+ e);
+ opResult.succeeded = false;
+
+ Throwable rootCause = ThrowableUtil.getRootCause(e);
+ opResult.details = "An error occurred while updating the seeds list: " +
+ ThrowableUtil.getStackAsString(rootCause);
+ }
+ resultsList.add(toPropertyMap(opResult));
resultConfig.put(resultsList);
10 years, 11 months
[rhq] modules/plugins
by John Sanda
modules/plugins/cassandra/pom.xml | 5
modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/CassandraNodeComponent.java | 77 ++++++++++
modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml | 10 +
modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java | 2
modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml | 8 +
5 files changed, 102 insertions(+)
New commits:
commit d25eb453afc3ba1a06fa2d47b2129d7c0d4592ce
Author: John Sanda <jsanda(a)redhat.com>
Date: Sun Jun 2 22:15:24 2013 -0400
initial commit for resource operation to update seeds property in cassandra.yaml
Updating the seeds property is one of the tasks that needs to be performed when
a node is added to or removed from the cluster. Since this is a generally useful
operation, I have added it to the base, cassandra plugin.
diff --git a/modules/plugins/cassandra/pom.xml b/modules/plugins/cassandra/pom.xml
index 79cbe0f..4a938d0 100644
--- a/modules/plugins/cassandra/pom.xml
+++ b/modules/plugins/cassandra/pom.xml
@@ -30,6 +30,11 @@
<version>1.0.5-M3-p1</version>
</dependency>
<dependency>
+ <groupId>org.apache.cassandra</groupId>
+ <artifactId>cassandra-all</artifactId>
+ <version>${cassandra.version}</version>
+ </dependency>
+ <dependency>
<groupId>${project.groupId}</groupId>
<artifactId>rhq-core-domain</artifactId>
<version>${project.version}</version>
diff --git a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/CassandraNodeComponent.java b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/CassandraNodeComponent.java
index a1636e7..b756f10 100644
--- a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/CassandraNodeComponent.java
+++ b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/CassandraNodeComponent.java
@@ -28,19 +28,34 @@ import static org.rhq.core.domain.measurement.AvailabilityType.UP;
import static org.rhq.core.system.OperatingSystemType.WINDOWS;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Cluster.Builder;
import com.datastax.driver.core.Session;
+import org.apache.cassandra.config.Config;
+import org.apache.cassandra.config.SeedProviderDef;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.sigar.SigarException;
import org.mc4j.ems.connection.EmsConnection;
import org.mc4j.ems.connection.bean.EmsBean;
import org.mc4j.ems.connection.bean.operation.EmsOperation;
+import org.yaml.snakeyaml.DumperOptions;
+import org.yaml.snakeyaml.TypeDescription;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.representer.Representer;
import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.Property;
+import org.rhq.core.domain.configuration.PropertyList;
+import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
import org.rhq.core.pluginapi.inventory.ResourceContext;
@@ -52,6 +67,7 @@ import org.rhq.core.system.ProcessExecutionResults;
import org.rhq.core.system.ProcessInfo;
import org.rhq.core.system.ProcessInfo.ProcessInfoSnapshot;
import org.rhq.core.system.SystemInfo;
+import org.rhq.core.util.StringUtil;
import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.plugins.jmx.JMXServerComponent;
@@ -137,6 +153,8 @@ public class CassandraNodeComponent extends JMXServerComponent<ResourceComponent
return startNode();
} else if (name.equals("restart")) {
return restartNode();
+ } else if (name.equals("updateSeedsList")) {
+ return updateSeedsList(parameters);
}
return null;
@@ -215,6 +233,65 @@ public class CassandraNodeComponent extends JMXServerComponent<ResourceComponent
return result;
}
+ protected OperationResult updateSeedsList(Configuration params) {
+ List<String> addresses = new ArrayList<String>();
+ PropertyList list = params.getList("seedsList");
+ for (Property property : list.getList()) {
+ PropertySimple simple = (PropertySimple) property;
+ addresses.add(simple.getStringValue());
+ }
+
+ OperationResult result = new OperationResult();
+ try {
+ updateSeedsList(addresses);
+ } catch (Exception e) {
+ log.error("An error occurred while updating the seeds list property", e);
+ Throwable rootCause = ThrowableUtil.getRootCause(e);
+ result.setErrorMessage(ThrowableUtil.getStackAsString(rootCause));
+ }
+ return result;
+ }
+
+ protected void updateSeedsList(List<String> addresses) throws IOException {
+ ResourceContext<?> context = getResourceContext();
+ Configuration pluginConfig = context.getPluginConfiguration();
+
+ String yamlProp = pluginConfig.getSimpleValue("yamlConfiguration");
+ if (yamlProp == null || yamlProp.isEmpty()) {
+ throw new IllegalStateException("Plugin configuration property [yamlConfiguration] is undefined. This " +
+ "property must specify be set and specify the location of cassandra.yaml in order to complete " +
+ "this operation");
+ }
+
+ File yamlFile = new File(yamlProp);
+ if (!yamlFile.exists()) {
+ throw new IllegalStateException("Plug configuration property [yamlConfiguration] has as its value a " +
+ "non-existent file.");
+ }
+
+ org.yaml.snakeyaml.constructor.Constructor constructor = new org.yaml.snakeyaml.constructor.Constructor(Config.class);
+ TypeDescription seedDesc = new TypeDescription(SeedProviderDef.class);
+ seedDesc.putMapPropertyType("parameters", String.class, String.class);
+ constructor.addTypeDescription(seedDesc);
+
+ DumperOptions options = new DumperOptions();
+ options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
+
+ Yaml yaml = new Yaml(constructor, new Representer(), options);
+ Config conf = (Config)yaml.load(new FileInputStream(yamlFile));
+
+ SeedProviderDef seedProviderDef = conf.seed_provider;
+ seedProviderDef.parameters.put("seeds", StringUtil.listToString(addresses));
+ Map<String, String> params = seedProviderDef.parameters;
+
+ // remove the original file
+ // TODO create a backup first in case something goes wrong so we can rollback
+ yamlFile.delete();
+ FileWriter writer = new FileWriter(yamlFile);
+ yaml.dump(conf, writer);
+ writer.close();
+ }
+
private String getStartScript() {
ResourceContext<?> context = getResourceContext();
SystemInfo systemInfo = context.getSystemInformation();
diff --git a/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml
index 8dfc156..8ec0c6d 100644
--- a/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml
@@ -61,17 +61,27 @@
<c:simple-property name="shutdownResult" description="Shutdown the Cassandra daemon"/>
</results>
</operation>
+
<operation name="start" description="Starts the Cassandra daemon">
<results>
<c:simple-property name="startResult" description="Start the Cassandra daemon"/>
</results>
</operation>
+
<operation name="restart" description="Restarts the Cassandra daemon">
<results>
<c:simple-property name="startResult" description="Restart the Cassandra daemon"/>
</results>
</operation>
+ <operation name="updateSeedsList" description="Updatess the node's seeds property in cassandra.yaml">
+ <parameters>
+ <c:list-property name="seedsList">
+ <c:simple-property name="seed" type="string"/>
+ </c:list-property>
+ </parameters>
+ </operation>
+
<server name="Cassandra Server JVM"
sourcePlugin="JMX" sourceType="JMX Server"
discovery="org.rhq.plugins.jmx.EmbeddedJMXServerDiscoveryComponent"
diff --git a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java
index 2accf4a..88b76c1 100644
--- a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java
+++ b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java
@@ -98,6 +98,8 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper
}
resultsList.add(toPropertyMap(opResult));
+ // update seeds list...
+
resultConfig.put(resultsList);
if (hasErrors) {
diff --git a/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml
index 21b4c6d..2457b0c 100644
--- a/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml
@@ -81,6 +81,14 @@
</results>
</operation>
+ <operation name="updateSeedsList" description="Updatess the node's seeds property in cassandra.yaml">
+ <parameters>
+ <c:list-property name="seedsList">
+ <c:simple-property name="seed" type="string"/>
+ </c:list-property>
+ </parameters>
+ </operation>
+
<server name="Cassandra Server JVM"
sourcePlugin="JMX" sourceType="JMX Server"
discovery="org.rhq.plugins.jmx.EmbeddedJMXServerDiscoveryComponent"
10 years, 11 months
[rhq] etc/scripts
by Jiri Kremser
etc/scripts/rhqctl-completion.sh | 69 +++++++++++++++++++++++++++++++++++++++
1 file changed, 69 insertions(+)
New commits:
commit cc2a48436952f7fe8ee2443a7c6b6bc5291e5daa
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Mon Jun 3 01:00:40 2013 +0200
Bash completion script for rhqctl command.
diff --git a/etc/scripts/rhqctl-completion.sh b/etc/scripts/rhqctl-completion.sh
new file mode 100755
index 0000000..73891d9
--- /dev/null
+++ b/etc/scripts/rhqctl-completion.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+
+# completion function for rhqctl command
+# to auto load this script move this script to /etc/bash_completion.d/
+
+_rhqctl() {
+ local cur prev opts agentServerStorage storageInstallSubopts agentInstallSubopts serverInstallSubopts first
+ COMPREPLY=()
+
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
+ opts="console install start status stop"
+ agentServerStorage="--agent --server --storage"
+ storageInstallSubopts=" --storage-config --storage-dir "
+ agentInstallSubopts=" --agent-config --agent-dir --agent-security-token "
+ serverInstallSubopts=" --server-config "
+
+ if [[ "${COMP_LINE}" =~ ^rhqctl[[:space:]]*$ ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ fi
+
+ first="${COMP_WORDS[1]}"
+
+ if [[ "x${first}" == "xstart" ]] || [[ "x${first}" == "xstop" ]] || [[ "x${first}" == "xstatus" ]] || [[ "x${first}" == "xconsole" ]] ; then
+ COMPREPLY=( $(compgen -W "${agentServerStorage}" -- ${cur}) )
+ return 0
+ elif [[ "x${first}" == "xinstall" ]] ; then
+ second="${COMP_WORDS[2]}"
+ if [[ "x$second" == "x" ]] ; then
+ COMPREPLY=( $(compgen -W "${agentServerStorage}" -- ${cur}) )
+ return 0
+ fi
+
+ if [[ "x${second}" == "x--server" ]] ; then
+ if [[ "${serverInstallSubopts}" == *" ${prev} "* ]] ; then
+ # complete path
+ COMPREPLY=( $( ls -1 | grep ^${cur} ) )
+ return 0
+ fi
+ COMPREPLY=( $(compgen -W "${serverInstallSubopts}" -- ${cur}) )
+ return 0
+ elif [[ "x${second}" == "x--agent" ]] ; then
+ if [[ "${agentInstallSubopts}" == *" ${prev} "* ]] ; then
+ # complete path
+ COMPREPLY=( $( ls -1 | grep ^${cur} ) )
+ return 0
+ fi
+ COMPREPLY=( $(compgen -W "${agentInstallSubopts}" -- ${cur}) )
+ return 0
+ elif [[ "x${second}" == "x--storage" ]] ; then
+ if [[ "${storageInstallSubopts}" == *" ${prev} "* ]] ; then
+ # complete path
+ COMPREPLY=( $( ls -1 | grep ^${cur} ) )
+ return 0
+ fi
+ COMPREPLY=( $(compgen -W "${storageInstallSubopts}" -- ${cur}) )
+ return 0
+ fi
+ COMPREPLY=( $(compgen -W "${agentServerStorage}" -- ${cur}) )
+ return 0
+ # fallback
+ elif [[ "${cur}" == * ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ fi
+}
+
+complete -F _rhqctl rhqctl
10 years, 11 months
[rhq] modules/plugins
by John Sanda
modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java | 29 ++++++----
modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml | 7 ++
2 files changed, 25 insertions(+), 11 deletions(-)
New commits:
commit bdf0702de70e18e20b3a27c047aee81a39c90ffa
Author: John Sanda <jsanda(a)redhat.com>
Date: Sun Jun 2 10:16:10 2013 -0400
fix typo in ks name and add initial support for params in addNodeMaintenance
The parameter list includes a flag for running repair. We also want to run
cleanup after a new node joins the cluster, but we only need to run repair
when we also change the replication_factor.
diff --git a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java
index 9672a37..2accf4a 100644
--- a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java
+++ b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java
@@ -46,20 +46,22 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper
private Log log = LogFactory.getLog(StorageNodeComponent.class);
- private static final String SYSTEM_AUTH_KEYSPACE = " system_auth";
+ private static final String SYSTEM_AUTH_KEYSPACE = "system_auth";
private static final String RHQ_KEYSPACE = "rhq";
@Override
public OperationResult invokeOperation(String name, Configuration parameters) throws Exception {
if (name.equals("addNodeMaintenance")) {
- return nodeAdded();
+ return nodeAdded(parameters);
} else {
return super.invokeOperation(name, parameters);
}
}
- private OperationResult nodeAdded() {
+ private OperationResult nodeAdded(Configuration params) {
+ boolean runRepair = params.getSimple("runRepair").getBooleanValue();
+
EmsConnection emsConnection = getEmsConnection();
KeyspaceService keyspaceService = new KeyspaceService(emsConnection);
boolean hasErrors = false;
@@ -67,11 +69,14 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper
Configuration resultConfig = result.getComplexResults();
PropertyList resultsList = new PropertyList("results");
- OpResult opResult = repairKeyspace(keyspaceService, SYSTEM_AUTH_KEYSPACE);
- if (!opResult.succeeded) {
- hasErrors = true;
+ OpResult opResult = null;
+ if (runRepair) {
+ opResult = repairKeyspace(keyspaceService, SYSTEM_AUTH_KEYSPACE);
+ if (!opResult.succeeded) {
+ hasErrors = true;
+ }
+ resultsList.add(toPropertyMap(opResult));
}
- resultsList.add(toPropertyMap(opResult));
opResult = cleanupKeyspace(keyspaceService, SYSTEM_AUTH_KEYSPACE);
if (!opResult.succeeded) {
@@ -79,11 +84,13 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper
}
resultsList.add(toPropertyMap(opResult));
- opResult = repairKeyspace(keyspaceService, RHQ_KEYSPACE);
- if (!opResult.succeeded) {
- hasErrors = true;
+ if (runRepair) {
+ opResult = repairKeyspace(keyspaceService, RHQ_KEYSPACE);
+ if (!opResult.succeeded) {
+ hasErrors = true;
+ }
+ resultsList.add(toPropertyMap(opResult));
}
- resultsList.add(toPropertyMap(opResult));
opResult = cleanupKeyspace(keyspaceService, RHQ_KEYSPACE);
if (!opResult.succeeded) {
diff --git a/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml
index 11c56c6..21b4c6d 100644
--- a/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml
@@ -63,6 +63,13 @@
</operation>
<operation name="addNodeMaintenance">
+ <parameters>
+ <c:simple-property name="runRepair" type="boolean" default="true"/>
+ <c:simple-property name="updateSeedsList" type="boolean" default="true"/>
+ <c:list-property name="seedsList">
+ <c:simple-property name="seed" type="string"/>
+ </c:list-property>
+ </parameters>
<results>
<c:list-property name="results">
<c:map-property name="resultsMap">
10 years, 11 months
[rhq] modules/plugins
by John Sanda
modules/plugins/rhq-storage/pom.xml | 2
modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java | 167 ++++++++++
modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml | 113 ++++++
3 files changed, 278 insertions(+), 4 deletions(-)
New commits:
commit 7ed79ce3c8ae87d81d09793c9149b9eac3522923
Author: John Sanda <jsanda(a)redhat.com>
Date: Sun Jun 2 07:40:29 2013 -0400
Initial commit for StorageNodeComponent and new addNodeMaintenance operation
So far addNodeMaintenance does the following,
* runs repair on system_auth keyspace
* run cleanup on system_auth keyspace
* run repair on rhq keyspace
* run cleanup on rhq keysapce
Since I could not add an operation to existing resource type definition that we
are extending, I had to copy the top-level type definition from the cassandra
plugin.
diff --git a/modules/plugins/rhq-storage/pom.xml b/modules/plugins/rhq-storage/pom.xml
index 4a88e0f..e3b3282 100644
--- a/modules/plugins/rhq-storage/pom.xml
+++ b/modules/plugins/rhq-storage/pom.xml
@@ -27,7 +27,7 @@
<groupId>${rhq.groupId}</groupId>
<artifactId>rhq-cassandra-plugin</artifactId>
<version>${project.version}</version>
- <scope>provided</scope>
+ <!--<scope>provided</scope>-->
</dependency>
<dependency>
diff --git a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java
new file mode 100644
index 0000000..9672a37
--- /dev/null
+++ b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java
@@ -0,0 +1,167 @@
+/*
+ *
+ * * RHQ Management Platform
+ * * Copyright (C) 2005-2012 Red Hat, Inc.
+ * * All rights reserved.
+ * *
+ * * This program is free software; you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License, version 2, as
+ * * published by the Free Software Foundation, and/or the GNU Lesser
+ * * General Public License, version 2.1, also as published by the Free
+ * * Software Foundation.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License and the GNU Lesser General Public License
+ * * for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * and the GNU Lesser General Public License along with this program;
+ * * if not, write to the Free Software Foundation, Inc.,
+ * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+package org.rhq.plugins.storage;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.mc4j.ems.connection.EmsConnection;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertyList;
+import org.rhq.core.domain.configuration.PropertyMap;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.pluginapi.operation.OperationFacet;
+import org.rhq.core.pluginapi.operation.OperationResult;
+import org.rhq.core.util.exception.ThrowableUtil;
+import org.rhq.plugins.cassandra.CassandraNodeComponent;
+import org.rhq.plugins.cassandra.util.KeyspaceService;
+
+/**
+ * @author John Sanda
+ */
+public class StorageNodeComponent extends CassandraNodeComponent implements OperationFacet {
+
+ private Log log = LogFactory.getLog(StorageNodeComponent.class);
+
+ private static final String SYSTEM_AUTH_KEYSPACE = " system_auth";
+
+ private static final String RHQ_KEYSPACE = "rhq";
+
+ @Override
+ public OperationResult invokeOperation(String name, Configuration parameters) throws Exception {
+ if (name.equals("addNodeMaintenance")) {
+ return nodeAdded();
+ } else {
+ return super.invokeOperation(name, parameters);
+ }
+ }
+
+ private OperationResult nodeAdded() {
+ EmsConnection emsConnection = getEmsConnection();
+ KeyspaceService keyspaceService = new KeyspaceService(emsConnection);
+ boolean hasErrors = false;
+ OperationResult result = new OperationResult();
+ Configuration resultConfig = result.getComplexResults();
+ PropertyList resultsList = new PropertyList("results");
+
+ OpResult opResult = repairKeyspace(keyspaceService, SYSTEM_AUTH_KEYSPACE);
+ if (!opResult.succeeded) {
+ hasErrors = true;
+ }
+ resultsList.add(toPropertyMap(opResult));
+
+ opResult = cleanupKeyspace(keyspaceService, SYSTEM_AUTH_KEYSPACE);
+ if (!opResult.succeeded) {
+ hasErrors = true;
+ }
+ resultsList.add(toPropertyMap(opResult));
+
+ opResult = repairKeyspace(keyspaceService, RHQ_KEYSPACE);
+ if (!opResult.succeeded) {
+ hasErrors = true;
+ }
+ resultsList.add(toPropertyMap(opResult));
+
+ opResult = cleanupKeyspace(keyspaceService, RHQ_KEYSPACE);
+ if (!opResult.succeeded) {
+ hasErrors = true;
+ }
+ resultsList.add(toPropertyMap(opResult));
+
+ resultConfig.put(resultsList);
+
+ if (hasErrors) {
+ result.setErrorMessage("One or more tasks failed to complete successfully.");
+ }
+ return result;
+ }
+
+ private OpResult repairKeyspace(KeyspaceService keyspaceService, String keyspace) {
+ OpResult result = new OpResult();
+ result.operation = "repair " + keyspace + " keyspace";
+ try {
+ if (log.isDebugEnabled()) {
+ log.debug("Running repair on " + keyspace + " keyspace");
+ }
+ long start = System.currentTimeMillis();
+ keyspaceService.repairPrimaryRange(keyspace);
+ long end = System.currentTimeMillis();
+ if (log.isDebugEnabled()) {
+ log.debug("Finsihed repair on " + keyspace + " keyspace in " + (end - start) + " ms");
+ }
+ result.succeeded = true;
+ } catch (Exception e) {
+ log.error("An error occurred while running repair on " + keyspace, e);
+ Throwable rootCause = ThrowableUtil.getRootCause(e);
+
+ result.succeeded = false;
+ result.details = "An error occurred while running repair: " + ThrowableUtil.getStackAsString(rootCause);
+ }
+ return result;
+ }
+
+ private OpResult cleanupKeyspace(KeyspaceService keyspaceService, String keyspace) {
+ OpResult result = new OpResult();
+ result.operation = "cleanup " + keyspace + " keyspace";
+
+ long start;
+ long end;
+ if (log.isDebugEnabled()) {
+ log.debug("Running cleanup on " + keyspace + " keyspace");
+ }
+ start = System.currentTimeMillis();
+ try {
+ keyspaceService.cleanup(keyspace);
+ end = System.currentTimeMillis();
+ if (log.isDebugEnabled()) {
+ log.debug("Finished cleanup on " + keyspace + " keyspace in " + (end - start) + " ms");
+ }
+ result.succeeded = true;
+ } catch (Exception e) {
+ log.error("An error occurred while running cleanup on " + keyspace + " keyspace", e);
+ Throwable rootCause = ThrowableUtil.getRootCause(e);
+
+ result.succeeded = false;
+ result.details = "An error occurred while running cleanup: " + ThrowableUtil.getStackAsString(rootCause);
+ }
+ return result;
+ }
+
+ private PropertyMap toPropertyMap(OpResult opResult) {
+ PropertyMap map = new PropertyMap("resultsMap");
+ map.put(new PropertySimple("task", opResult.operation));
+ map.put(new PropertySimple("succeeded", opResult.succeeded));
+ map.put(new PropertySimple("details", opResult.details));
+
+ return map;
+ }
+
+ private static class OpResult {
+ String operation;
+ boolean succeeded;
+ String details;
+ }
+}
diff --git a/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml
index 0d015ff..11c56c6 100644
--- a/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml
@@ -11,10 +11,117 @@
<server
name="RHQ Storage Node"
discovery="StorageNodeDiscoveryComponent"
- class="org.rhq.plugins.cassandra.CassandraNodeComponent"
- description="RHQ Storage Node" sourcePlugin="Cassandra" sourceType="Cassandra Node">
+ class="StorageNodeComponent"
+ description="RHQ Storage Node">
- </server>
+ <subcategories>
+ <subcategory name="Client Request Metrics" description="Client Request Metrics"/>
+ <subcategory name="Server Request Metrics" description="Server Request Metrics"/>
+ <subcategory name="Internal Server Metrics" description="Internal Server Metrics"/>
+ <subcategory name="Database Management Services" description="Database Management Services"/>
+ <subcategory name="Network Services" description="Network Services"/>
+ </subcategories>
+
+ <plugin-configuration>
+ <c:simple-property name="connectorAddress" displayName="Manager URL" default="service:jmx:rmi:///jndi/rmi://localhost:7199/jmxrmi"
+ description="The RMI URL with which to connect to the Cassandra node (e.g. service:jmx:rmi:///jndi/rmi://localhost:7199/jmxrmi)."/>
+ <c:simple-property name="type" readOnly="true" default="org.mc4j.ems.connection.support.metadata.J2SE5ConnectionTypeDescriptor"
+ description="The type used to establish the EMS connection to the Cassandra node."/>
+ <c:simple-property name="username" default="cassandra" required="true" description="The login username"/>
+ <c:simple-property name="password" default="cassandra" required="true" type="password" description="The login password"/>
+ <c:simple-property name="baseDir" displayName="Base Directory" description="The base directory from which the Cassandra Daemon was launched." required="false"/>
+ <c:simple-property name="yamlConfiguration" displayName="YAML Configuration File" description="YAML Configuration File"/>
+ <c:simple-property name="nativeTransportPort" description="The port on which Cassandra listens for CQL client connections." default="9042" type="integer"/>
+ <c:simple-property name="host" description="The host on which cassandra listens to CQL client connections" default="localhost"/>
+ <c:simple-property name="clusterName" description="Cluster name" default="localhost"/>
+ <c:simple-property name="authenticator" required="true" default="org.apache.cassandra.auth.AllowAllAuthenticator" description="Cassandra client authenticator">
+ <c:property-options>
+ <c:option name="org.apache.cassandra.auth.AllowAllAuthenticator" value="org.apache.cassandra.auth.AllowAllAuthenticator"/>
+ <c:option name="org.apache.cassandra.auth.PasswordAuthenticator" value="org.apache.cassandra.auth.PasswordAuthenticator"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="commandLine" required="false" type="string" description="the command line of the JVM at the time it was discovered - only used by JVMs with type Local; if the command line of the JVM changes, this property's value will need to be updated accordingly in order for RHQ to connect to the JVM"/>
+ </plugin-configuration>
+
+ <process-scan name="CassandraDaemon" query="process|basename|match=^java.*,arg|org.apache.cassandra.service.CassandraDaemon|match=.*"/>
+
+ <operation name="shutdown" description="Shuts down the Cassandra daemon">
+ <results>
+ <c:simple-property name="shutdownResult" description="Shutdown the Cassandra daemon"/>
+ </results>
+ </operation>
+
+ <operation name="start" description="Starts the Cassandra daemon">
+ <results>
+ <c:simple-property name="startResult" description="Start the Cassandra daemon"/>
+ </results>
+ </operation>
+ <operation name="restart" description="Restarts the Cassandra daemon">
+ <results>
+ <c:simple-property name="startResult" description="Restart the Cassandra daemon"/>
+ </results>
+ </operation>
+
+ <operation name="addNodeMaintenance">
+ <results>
+ <c:list-property name="results">
+ <c:map-property name="resultsMap">
+ <c:simple-property name="task" type="string"/>
+ <c:simple-property name="succeeded" type="boolean"/>
+ <c:simple-property name="details" type="string"/>
+ </c:map-property>
+ </c:list-property>
+ </results>
+ </operation>
+
+ <server name="Cassandra Server JVM"
+ sourcePlugin="JMX" sourceType="JMX Server"
+ discovery="org.rhq.plugins.jmx.EmbeddedJMXServerDiscoveryComponent"
+ class="org.rhq.plugins.jmx.EmbeddedJMXServerComponent"
+ description="The JVM of the Cassandra node"
+ singleton="true">
+
+ <plugin-configuration>
+ <c:simple-property name="type" type="string" default="PARENT" readOnly="true" description="The EMS connection type for this JVM (cannot be modified)"/>
+ </plugin-configuration>
+ </server>
+
+ <service name="StorageProxy" sourcePlugin="Cassandra" sourceType="StorageProxy" singleton="true"/>
+
+ <service name="StorageService" sourcePlugin="Cassandra" sourceType="StorageService" singleton="true"/>
+
+ <service name="CommitLog" sourcePlugin="Cassandra" sourceType="CommitLog" singleton="true"/>
+
+ <service name="ReadTimeouts" sourcePlugin="Cassandra" sourceType="ReadTimeouts" singleton="true"/>
+
+ <service name="ReadUnavailables" sourcePlugin="Cassandra" sourceType="ReadUnavailables" singleton="true"/>
+ <service name="WriteTimeouts" sourcePlugin="Cassandra" sourceType="WriteTimeouts" singleton="true"/>
+ <service name="WriteUnavailables" sourcePlugin="Cassandra" sourceType="WriteUnavailables" singleton="true"/>
+
+ <service name="CompactionManager" sourcePlugin="Cassandra" sourceType="CompactionManager" singleton="true"/>
+
+ <service name="CacheService" sourcePlugin="Cassandra" sourceType="CacheService" singleton="true"/>
+
+ <service name="ConfigurableStages" sourcePlugin="Cassandra" sourceType="ConfigurableStages" singleton="true"/>
+
+ <service name="EnabledStages" sourcePlugin="Cassandra" sourceType="EnabledStages" singleton="true"/>
+
+ <service name="ConfigurableInternalServerMetrics" sourcePlugin="Cassandra" sourceType="ConfigurableInternalServerMetrics"
+ singleton="true"/>
+
+ <service name="EnabledInternalServerMetrics" sourcePlugin="Cassandra" sourceType="EnabledInternalServerMetrics"
+ singleton="true"/>
+
+ <service name="FailureDetector" sourcePlugin="Cassandra" sourceType="FailureDetector" singleton="true"/>
+
+ <service name="Gossiper" sourcePlugin="Cassandra" sourceType="Gossiper" singleton="true"/>
+
+ <service name="StreamingService" sourcePlugin="Cassandra" sourceType="StreamingService" singleton="true"/>
+
+ <service name="MessagingService" sourcePlugin="Cassandra" sourceType="MessagingService" singleton="true"/>
+
+ <service name="Keyspace" sourcePlugin="Cassandra" sourceType="Keyspace"/>
+ </server>
</plugin>
10 years, 11 months
[rhq] 3 commits - modules/plugins
by John Sanda
modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/KeyspaceComponent.java | 62 ++++-
modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/util/KeyspaceService.java | 109 ++++++++++
modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml | 6
3 files changed, 161 insertions(+), 16 deletions(-)
New commits:
commit 389c78721f61b3704404cbdb6a2a03bff22785ef
Author: John Sanda <jsanda(a)redhat.com>
Date: Sat Jun 1 22:52:20 2013 -0400
more refactoring to get the correct logic in KeyspaceService
diff --git a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/KeyspaceComponent.java b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/KeyspaceComponent.java
index ea5f55f..81a9388 100644
--- a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/KeyspaceComponent.java
+++ b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/KeyspaceComponent.java
@@ -144,14 +144,17 @@ public class KeyspaceComponent implements ResourceComponent<ResourceComponent<?>
return failedOperation;
}
- public OperationResult repairKeyspace() {
+ public OperationResult repairKeyspace(String... columnFamilies) {
KeyspaceService keyspaceService = new KeyspaceService(getEmsConnection());
String keyspace = context.getResourceKey();
+ if (columnFamilies == null) {
+ columnFamilies = new String[] {};
+ }
log.info("Executing repair on keyspace [" + keyspace + "]");
long start = System.currentTimeMillis();
- keyspaceService.repair(keyspace);
+ keyspaceService.repair(keyspace, columnFamilies);
long end = System.currentTimeMillis();
log.info("Finished repair on keyspace [" + keyspace + "] in " + (end - start) + " ms");
@@ -172,13 +175,17 @@ public class KeyspaceComponent implements ResourceComponent<ResourceComponent<?>
return new OperationResult();
}
- public OperationResult compactKeyspace() {
+ public OperationResult compactKeyspace(String... columnFamilies) {
KeyspaceService keyspaceService = new KeyspaceService(getEmsConnection());
+
String keyspace = context.getResourceKey();
+ if (columnFamilies == null) {
+ columnFamilies = new String[] {};
+ }
log.info("Executing compaction on keyspace [" + keyspace + "]");
long start = System.currentTimeMillis();
- keyspaceService.compact(keyspace);
+ keyspaceService.compact(keyspace, columnFamilies);
long end = System.currentTimeMillis();
log.info("Finished compaction on keysapce [" + keyspace + "] in " + (end - start) + " ms");
diff --git a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/util/KeyspaceService.java b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/util/KeyspaceService.java
index 9bd0716..5dda8be 100644
--- a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/util/KeyspaceService.java
+++ b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/util/KeyspaceService.java
@@ -44,26 +44,30 @@ public class KeyspaceService {
public static final String COMPACT_OPERATION = "forceTableCompaction";
+ public static final String SNAPSHOT_OPERATION = "takeSnapshot";
+
+ public static final String CF_SNAPSHOT_OPERATION = "takeColumnFamilySnapshot";
+
private EmsConnection emsConnection;
public KeyspaceService(EmsConnection emsConnection) {
this.emsConnection = emsConnection;
}
- public void repair(String keyspace) {
+ public void repair(String keyspace, String... columnFamilies) {
EmsBean emsBean = loadBean(STORAGE_SERVICE_BEAN);
EmsOperation operation = emsBean.getOperation(REPAIR_OPERATION, String.class, boolean.class,
boolean.class, String[].class);
- operation.invoke(keyspace, new String[] {});
+ operation.invoke(keyspace, true, true, columnFamilies);
}
- public void repairPrimaryRange(String keyspace) {
+ public void repairPrimaryRange(String keyspace, String... columnFamilies) {
EmsBean emsBean = loadBean(KeyspaceService.STORAGE_SERVICE_BEAN);
EmsOperation operation = emsBean.getOperation(REPAIR_PRIMARY_RANGE, String.class, boolean.class, boolean.class,
String[].class);
- operation.invoke(keyspace);
+ operation.invoke(keyspace, true, true, columnFamilies);
}
public void cleanup(String keyspace) {
@@ -73,11 +77,18 @@ public class KeyspaceService {
operation.invoke(keyspace, new String[] {});
}
- public void compact(String keyspace) {
+ public void compact(String keyspace, String... columnFamilies) {
EmsBean emsBean = loadBean(STORAGE_SERVICE_BEAN);
EmsOperation operation = emsBean.getOperation(COMPACT_OPERATION, String.class, String[].class);
- operation.invoke(keyspace, new String[] {});
+ operation.invoke(keyspace, columnFamilies);
+ }
+
+ public void takeSnapshot(String keyspace, String snapshotName) {
+ EmsBean emsBean = loadBean(STORAGE_SERVICE_BEAN);
+ EmsOperation operation = emsBean.getOperation(SNAPSHOT_OPERATION, String.class, String[].class);
+
+ operation.invoke(snapshotName, new String[] {keyspace});
}
private EmsBean loadBean(String objectName) {
commit 4e086fd5d1f5698c9af43eab0ec00d9797655216
Author: John Sanda <jsanda(a)redhat.com>
Date: Sat Jun 1 20:44:45 2013 -0400
inital commit for KeyspaceService
Extracting some of the logic in KeyspaceComponent into KeyspaceService because
it is needed in the storage plugin as well for kicking off tasks when nodes are
added to or removed from the cluster.
diff --git a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/KeyspaceComponent.java b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/KeyspaceComponent.java
index f0369c8..ea5f55f 100644
--- a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/KeyspaceComponent.java
+++ b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/KeyspaceComponent.java
@@ -55,6 +55,7 @@ import org.rhq.core.pluginapi.inventory.ResourceComponent;
import org.rhq.core.pluginapi.inventory.ResourceContext;
import org.rhq.core.pluginapi.operation.OperationFacet;
import org.rhq.core.pluginapi.operation.OperationResult;
+import org.rhq.plugins.cassandra.util.KeyspaceService;
import org.rhq.plugins.jmx.JMXComponent;
/**
@@ -65,12 +66,6 @@ public class KeyspaceComponent implements ResourceComponent<ResourceComponent<?>
private final Log log = LogFactory.getLog(KeyspaceComponent.class);
- private static final String STORAGE_SERVICE_BEAN = "org.apache.cassandra.db:type=StorageService";
-
- private static final String COMPACT_OPERATION = "forceTableCompaction";
- private static final String REPAIR_OPERATION = "forceTableRepair";
- private static final String CLEANUP_OPERATION = "forceTableCleanup";
-
private ResourceContext<ResourceComponent<?>> context;
@Override
@@ -149,19 +144,14 @@ public class KeyspaceComponent implements ResourceComponent<ResourceComponent<?>
return failedOperation;
}
- public OperationResult repairKeyspace(String... columnFamilies) {
- EmsBean emsBean = loadBean(STORAGE_SERVICE_BEAN);
- EmsOperation operation = emsBean.getOperation(REPAIR_OPERATION, String.class, boolean.class, boolean.class,
- String[].class);
+ public OperationResult repairKeyspace() {
+ KeyspaceService keyspaceService = new KeyspaceService(getEmsConnection());
String keyspace = context.getResourceKey();
- if (columnFamilies == null) {
- columnFamilies = new String[]{};
- }
log.info("Executing repair on keyspace [" + keyspace + "]");
long start = System.currentTimeMillis();
- operation.invoke(keyspace, true, true, columnFamilies);
+ keyspaceService.repair(keyspace);
long end = System.currentTimeMillis();
log.info("Finished repair on keyspace [" + keyspace + "] in " + (end - start) + " ms");
@@ -169,16 +159,12 @@ public class KeyspaceComponent implements ResourceComponent<ResourceComponent<?>
}
public OperationResult cleanup() {
- EmsBean emsBean = loadBean(STORAGE_SERVICE_BEAN);
- EmsOperation operation = emsBean.getOperation(CLEANUP_OPERATION, String.class, String[].class);
-
+ KeyspaceService keyspaceService = new KeyspaceService(getEmsConnection());
String keyspace = context.getResourceKey();
- operation.invoke(keyspace, new String[]{});
-
log.info("Executing cleanup on keyspace [" + keyspace + "]");
long start = System.currentTimeMillis();
- operation.invoke(keyspace, new String[]{});
+ keyspaceService.cleanup(keyspace);
long end = System.currentTimeMillis();
log.info("Finished cleanup on keyspace [" + keyspace + "] in " + (end - start) + " ms");
@@ -186,20 +172,14 @@ public class KeyspaceComponent implements ResourceComponent<ResourceComponent<?>
return new OperationResult();
}
- public OperationResult compactKeyspace(String... columnFamilies) {
- EmsBean emsBean = loadBean(STORAGE_SERVICE_BEAN);
- EmsOperation operation = emsBean.getOperation(COMPACT_OPERATION, String.class, String[].class);
-
+ public OperationResult compactKeyspace() {
+ KeyspaceService keyspaceService = new KeyspaceService(getEmsConnection());
String keyspace = context.getResourceKey();
- if (columnFamilies == null) {
- columnFamilies = new String[]{};
- }
log.info("Executing compaction on keyspace [" + keyspace + "]");
long start = System.currentTimeMillis();
- operation.invoke(keyspace, new String[]{});
+ keyspaceService.compact(keyspace);
long end = System.currentTimeMillis();
-
log.info("Finished compaction on keysapce [" + keyspace + "] in " + (end - start) + " ms");
return new OperationResult();
@@ -215,7 +195,7 @@ public class KeyspaceComponent implements ResourceComponent<ResourceComponent<?>
log.info("Taking snapshot of keyspace [" + keyspace + "]");
log.info("Snapshot name set to [" + snapshotName + "]");
long start = System.currentTimeMillis();
- EmsBean emsBean = loadBean(STORAGE_SERVICE_BEAN);
+ EmsBean emsBean = loadBean(KeyspaceService.STORAGE_SERVICE_BEAN);
if (columnFamilies == null || columnFamilies.length == 0) {
EmsOperation operation = emsBean.getOperation("takeSnapshot", String.class, String[].class);
operation.invoke(snapshotName, new String[]{keyspace});
@@ -238,7 +218,7 @@ public class KeyspaceComponent implements ResourceComponent<ResourceComponent<?>
}
public PropertyList getKeySpaceDataFileLocations() {
- EmsBean emsBean = loadBean(STORAGE_SERVICE_BEAN);
+ EmsBean emsBean = loadBean(KeyspaceService.STORAGE_SERVICE_BEAN);
EmsAttribute attribute = emsBean.getAttribute("AllDataFileLocations");
PropertyList list = new PropertyList("keyspaceFileLocations");
@@ -255,7 +235,7 @@ public class KeyspaceComponent implements ResourceComponent<ResourceComponent<?>
}
public PropertySimple getCommitLogProperty() {
- EmsBean emsBean = loadBean(STORAGE_SERVICE_BEAN);
+ EmsBean emsBean = loadBean(KeyspaceService.STORAGE_SERVICE_BEAN);
EmsAttribute attribute = emsBean.getAttribute("CommitLogLocation");
return new PropertySimple("CommitLogLocation", attribute.refresh());
}
diff --git a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/util/KeyspaceService.java b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/util/KeyspaceService.java
new file mode 100644
index 0000000..9bd0716
--- /dev/null
+++ b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/util/KeyspaceService.java
@@ -0,0 +1,98 @@
+/*
+ *
+ * * RHQ Management Platform
+ * * Copyright (C) 2005-2012 Red Hat, Inc.
+ * * All rights reserved.
+ * *
+ * * This program is free software; you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License, version 2, as
+ * * published by the Free Software Foundation, and/or the GNU Lesser
+ * * General Public License, version 2.1, also as published by the Free
+ * * Software Foundation.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License and the GNU Lesser General Public License
+ * * for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * and the GNU Lesser General Public License along with this program;
+ * * if not, write to the Free Software Foundation, Inc.,
+ * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+package org.rhq.plugins.cassandra.util;
+
+import org.mc4j.ems.connection.EmsConnection;
+import org.mc4j.ems.connection.bean.EmsBean;
+import org.mc4j.ems.connection.bean.operation.EmsOperation;
+
+/**
+ * @author John Sanda
+ */
+public class KeyspaceService {
+
+ public static final String STORAGE_SERVICE_BEAN = "org.apache.cassandra.db:type=StorageService";
+
+ public static final String REPAIR_OPERATION = "forceTableRepair";
+
+ public static final String REPAIR_PRIMARY_RANGE = "forceTableRepairPrimaryRange";
+
+ public static final String CLEANUP_OPERATION = "forceTableCleanup";
+
+ public static final String COMPACT_OPERATION = "forceTableCompaction";
+
+ private EmsConnection emsConnection;
+
+ public KeyspaceService(EmsConnection emsConnection) {
+ this.emsConnection = emsConnection;
+ }
+
+ public void repair(String keyspace) {
+ EmsBean emsBean = loadBean(STORAGE_SERVICE_BEAN);
+ EmsOperation operation = emsBean.getOperation(REPAIR_OPERATION, String.class, boolean.class,
+ boolean.class, String[].class);
+
+ operation.invoke(keyspace, new String[] {});
+ }
+
+ public void repairPrimaryRange(String keyspace) {
+ EmsBean emsBean = loadBean(KeyspaceService.STORAGE_SERVICE_BEAN);
+ EmsOperation operation = emsBean.getOperation(REPAIR_PRIMARY_RANGE, String.class, boolean.class, boolean.class,
+ String[].class);
+
+ operation.invoke(keyspace);
+ }
+
+ public void cleanup(String keyspace) {
+ EmsBean emsBean = loadBean(STORAGE_SERVICE_BEAN);
+ EmsOperation operation = emsBean.getOperation(CLEANUP_OPERATION, String.class, String[].class);
+
+ operation.invoke(keyspace, new String[] {});
+ }
+
+ public void compact(String keyspace) {
+ EmsBean emsBean = loadBean(STORAGE_SERVICE_BEAN);
+ EmsOperation operation = emsBean.getOperation(COMPACT_OPERATION, String.class, String[].class);
+
+ operation.invoke(keyspace, new String[] {});
+ }
+
+ private EmsBean loadBean(String objectName) {
+ EmsBean bean = emsConnection.getBean(objectName);
+ if (bean == null) {
+ // In some cases, this resource component may have been discovered by some means other than querying its
+ // parent's EMSConnection (e.g. ApplicationDiscoveryComponent uses a filesystem to discover EARs and
+ // WARs that are not yet deployed). In such cases, getBean() will return null, since EMS won't have the
+ // bean in its cache. To cover such cases, make an attempt to query the underlying MBeanServer for the
+ // bean before giving up.
+ emsConnection.queryBeans(objectName);
+ bean = emsConnection.getBean(objectName);
+ }
+
+ return bean;
+ }
+
+}
commit f6d23afafed53f61598aa97c2c2df2760274b3bf
Author: John Sanda <jsanda(a)redhat.com>
Date: Sat Jun 1 07:44:39 2013 -0400
adding cleanup operation and some logging
diff --git a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/KeyspaceComponent.java b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/KeyspaceComponent.java
index 2f2591a..f0369c8 100644
--- a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/KeyspaceComponent.java
+++ b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/KeyspaceComponent.java
@@ -36,6 +36,8 @@ import com.datastax.driver.core.Row;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.querybuilder.QueryBuilder;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.mc4j.ems.connection.EmsConnection;
import org.mc4j.ems.connection.bean.EmsBean;
import org.mc4j.ems.connection.bean.attribute.EmsAttribute;
@@ -61,10 +63,13 @@ import org.rhq.plugins.jmx.JMXComponent;
public class KeyspaceComponent implements ResourceComponent<ResourceComponent<?>>, ConfigurationFacet,
JMXComponent<ResourceComponent<?>>, OperationFacet {
+ private final Log log = LogFactory.getLog(KeyspaceComponent.class);
+
private static final String STORAGE_SERVICE_BEAN = "org.apache.cassandra.db:type=StorageService";
private static final String COMPACT_OPERATION = "forceTableCompaction";
private static final String REPAIR_OPERATION = "forceTableRepair";
+ private static final String CLEANUP_OPERATION = "forceTableCleanup";
private ResourceContext<ResourceComponent<?>> context;
@@ -134,6 +139,8 @@ public class KeyspaceComponent implements ResourceComponent<ResourceComponent<?>
return compactKeyspace();
} else if (name.equals("takeSnapshot")) {
return takeSnapshot(parameters);
+ } else if (name.equals("cleanup")) {
+ return cleanup();
}
OperationResult failedOperation = new OperationResult();
@@ -149,9 +156,32 @@ public class KeyspaceComponent implements ResourceComponent<ResourceComponent<?>
String keyspace = context.getResourceKey();
if (columnFamilies == null) {
- columnFamilies = new String[] {};
+ columnFamilies = new String[]{};
}
+
+ log.info("Executing repair on keyspace [" + keyspace + "]");
+ long start = System.currentTimeMillis();
operation.invoke(keyspace, true, true, columnFamilies);
+ long end = System.currentTimeMillis();
+ log.info("Finished repair on keyspace [" + keyspace + "] in " + (end - start) + " ms");
+
+ return new OperationResult();
+ }
+
+ public OperationResult cleanup() {
+ EmsBean emsBean = loadBean(STORAGE_SERVICE_BEAN);
+ EmsOperation operation = emsBean.getOperation(CLEANUP_OPERATION, String.class, String[].class);
+
+ String keyspace = context.getResourceKey();
+ operation.invoke(keyspace, new String[]{});
+
+
+ log.info("Executing cleanup on keyspace [" + keyspace + "]");
+ long start = System.currentTimeMillis();
+ operation.invoke(keyspace, new String[]{});
+ long end = System.currentTimeMillis();
+
+ log.info("Finished cleanup on keyspace [" + keyspace + "] in " + (end - start) + " ms");
return new OperationResult();
}
@@ -162,9 +192,15 @@ public class KeyspaceComponent implements ResourceComponent<ResourceComponent<?>
String keyspace = context.getResourceKey();
if (columnFamilies == null) {
- columnFamilies = new String[] {};
+ columnFamilies = new String[]{};
}
- operation.invoke(keyspace, new String[] {});
+
+ log.info("Executing compaction on keyspace [" + keyspace + "]");
+ long start = System.currentTimeMillis();
+ operation.invoke(keyspace, new String[]{});
+ long end = System.currentTimeMillis();
+
+ log.info("Finished compaction on keysapce [" + keyspace + "] in " + (end - start) + " ms");
return new OperationResult();
}
@@ -176,19 +212,28 @@ public class KeyspaceComponent implements ResourceComponent<ResourceComponent<?>
snapshotName = System.currentTimeMillis() + "";
}
+ log.info("Taking snapshot of keyspace [" + keyspace + "]");
+ log.info("Snapshot name set to [" + snapshotName + "]");
+ long start = System.currentTimeMillis();
EmsBean emsBean = loadBean(STORAGE_SERVICE_BEAN);
if (columnFamilies == null || columnFamilies.length == 0) {
EmsOperation operation = emsBean.getOperation("takeSnapshot", String.class, String[].class);
- operation.invoke(snapshotName, new String[] { keyspace });
+ operation.invoke(snapshotName, new String[]{keyspace});
} else {
EmsOperation operation = emsBean.getOperation("takeColumnFamilySnapshot", String.class, String.class,
String.class);
for (String columnFamily : columnFamilies) {
+ if (log.isDebugEnabled()) {
+ log.debug("Taking snapshot of column family [" + columnFamily + "]");
+ }
operation.invoke(keyspace, columnFamily, snapshotName);
}
}
+ long end = System.currentTimeMillis();
+ log.info("Finished taking snapshot of keyspace [" + keyspace + "] in " + (end - start) + " ms");
+
return new OperationResult();
}
diff --git a/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml
index 752c72a..8dfc156 100644
--- a/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml
@@ -649,7 +649,11 @@
deletes, it is important to run regularly scheduled repairs to ensure that deleted data gets purged.
The frequency that this should be run should be less than the gc_grace_period for each column family.
This runs a repair on all column families in this keyspace." />
- <operation name="compact" displayName="Compact Keyspace"
+ <operation name="cleanup" displayName="Clean Keyspace"
+ description="Goes through each SSTable file on disk fore each column family and removes keys
+ (i.e., rows) that the node does not own. This should be performed as a routine maintenance task on
+ existing nodes when new nodes are added to the cluster."/>
+ <operation name="compact" displayName="Compact Keyspace"
description="Forces major compaction of the keyspace. Though major compaction can free disk space
used during runtime it temporarily doubles disk space usage and is I/O and CPU intensive. Once you
run a major compaction, automatic minor compactions are no longer triggered frequently forcing you to
10 years, 11 months