Sahina Bose has uploaded a new change for review.

Change subject: restapi: Support for gluster hooks added
......................................................................

restapi: Support for gluster hooks added

Added API for managing gluster hooks.
 - api/cluster/{id}/glusterhooks
   lists all gluster hooks in the cluster
 - api/cluster/{id}/glusterhooks/{id}
   show details of a gluster hook
   actions supported:
        - enable
        - disable
        - add
        - update
        - remove

Change-Id: Ibf9c0299977448e0b50feeed6e38a015c60b86fd
Signed-off-by: Sahina Bose <[email protected]>
---
M 
backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java
M 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/ClusterResource.java
A 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/gluster/GlusterHookResource.java
A 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/gluster/GlusterHooksResource.java
M 
backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd
M 
backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml
M 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterResource.java
M 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClustersResource.java
A 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/gluster/BackendGlusterHookResource.java
A 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/gluster/BackendGlusterHooksResource.java
M 
backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/AbstractBackendCollectionResourceTest.java
A 
backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/gluster/BackendGlusterHooksResourceTest.java
A 
backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/GlusterHookMapper.java
13 files changed, 826 insertions(+), 11 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/12/16512/1

diff --git 
a/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java
 
b/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java
index 8c33f3b..e31fdaa 100644
--- 
a/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java
+++ 
b/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java
@@ -40,6 +40,7 @@
 import org.ovirt.engine.api.model.Event;
 import org.ovirt.engine.api.model.File;
 import org.ovirt.engine.api.model.GlusterBrick;
+import org.ovirt.engine.api.model.GlusterHook;
 import org.ovirt.engine.api.model.GlusterVolume;
 import org.ovirt.engine.api.model.Group;
 import org.ovirt.engine.api.model.Hook;
@@ -146,6 +147,8 @@
 import org.ovirt.engine.api.resource.VmsResource;
 import org.ovirt.engine.api.resource.gluster.GlusterBrickResource;
 import org.ovirt.engine.api.resource.gluster.GlusterBricksResource;
+import org.ovirt.engine.api.resource.gluster.GlusterHookResource;
+import org.ovirt.engine.api.resource.gluster.GlusterHooksResource;
 import org.ovirt.engine.api.resource.gluster.GlusterVolumeResource;
 import org.ovirt.engine.api.resource.gluster.GlusterVolumesResource;
 
@@ -314,6 +317,9 @@
         map = new ParentToCollectionMap(GlusterBrickResource.class, 
GlusterBricksResource.class, GlusterVolume.class);
         TYPES.put(GlusterBrick.class, map);
 
+        map = new ParentToCollectionMap(GlusterHookResource.class, 
GlusterHooksResource.class, Cluster.class);
+        TYPES.put(GlusterHook.class, map);
+
         map = new ParentToCollectionMap(CapabiliyResource.class, 
CapabilitiesResource.class);
         TYPES.put(VersionCaps.class, map);
     }
diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/ClusterResource.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/ClusterResource.java
index 48d38a0..47d271d 100644
--- 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/ClusterResource.java
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/ClusterResource.java
@@ -20,6 +20,7 @@
 import javax.ws.rs.Produces;
 
 import org.ovirt.engine.api.model.Cluster;
+import org.ovirt.engine.api.resource.gluster.GlusterHooksResource;
 import org.ovirt.engine.api.resource.gluster.GlusterVolumesResource;
 
 
@@ -34,4 +35,7 @@
 
     @Path("glustervolumes")
     public GlusterVolumesResource getGlusterVolumesResource();
+
+    @Path("glusterhooks")
+    public GlusterHooksResource getGlusterHooksResource();
 }
diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/gluster/GlusterHookResource.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/gluster/GlusterHookResource.java
new file mode 100644
index 0000000..e12104f
--- /dev/null
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/gluster/GlusterHookResource.java
@@ -0,0 +1,65 @@
+package org.ovirt.engine.api.resource.gluster;
+
+import javax.ws.rs.Consumes;
+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.Response;
+
+import org.jboss.resteasy.annotations.providers.jaxb.Formatted;
+import org.ovirt.engine.api.model.Action;
+import org.ovirt.engine.api.model.Actionable;
+import org.ovirt.engine.api.model.GlusterHook;
+import org.ovirt.engine.api.resource.ActionResource;
+import org.ovirt.engine.api.resource.ApiMediaType;
+
+/**
+ * Resource interface for the "clusters/{cluster_id}/glusterhooks/{hook_id}" 
resource
+ */
+@Produces({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML })
+public interface GlusterHookResource {
+    @GET
+    @Formatted
+    public GlusterHook get();
+
+    @Path("{action: (enable|disable|add|update|remove)}/{oid}")
+    public ActionResource getActionSubresource(@PathParam("action") String 
action, @PathParam("oid") String oid);
+
+    @POST
+    @Formatted
+    @Consumes({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML })
+    @Actionable
+    @Path("enable")
+    public Response enable(Action action);
+
+    @POST
+    @Formatted
+    @Consumes({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML })
+    @Actionable
+    @Path("disable")
+    public Response disable(Action action);
+
+    @POST
+    @Formatted
+    @Consumes({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML })
+    @Actionable
+    @Path("add")
+    public Response add(Action action);
+
+    @POST
+    @Formatted
+    @Consumes({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML })
+    @Actionable
+    @Path("update")
+    public Response update(Action action);
+
+    @POST
+    @Formatted
+    @Consumes({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML })
+    @Actionable
+    @Path("remove")
+    public Response remove(Action action);
+
+}
diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/gluster/GlusterHooksResource.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/gluster/GlusterHooksResource.java
new file mode 100644
index 0000000..d468023
--- /dev/null
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/gluster/GlusterHooksResource.java
@@ -0,0 +1,35 @@
+/**
+ *
+ */
+package org.ovirt.engine.api.resource.gluster;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+
+import org.jboss.resteasy.annotations.providers.jaxb.Formatted;
+import org.ovirt.engine.api.model.GlusterHooks;
+import org.ovirt.engine.api.resource.ApiMediaType;
+
+/**
+ * Resource interface for the "clusters/{cluster_id}/glusterhooks" resource
+ */
+@Produces({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML })
+public interface GlusterHooksResource {
+    @GET
+    @Formatted
+    public GlusterHooks list();
+
+
+    /**
+     * Sub-resource locator method, returns individual GlusterHookResource on 
which the remainder of the URI is
+     * dispatched.
+     *
+     * @param name
+     *            the GlusterHook name
+     * @return matching subresource if found
+     */
+    @Path("{hook_id}")
+    public GlusterHookResource getGlusterHookSubResource(@PathParam("hook_id") 
String id);
+}
diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd
 
b/backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd
index 108bca9..559047a 100644
--- 
a/backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd
@@ -137,6 +137,7 @@
     <xs:sequence>
       <xs:element name="grace_period" type="GracePeriod" minOccurs="0"/>
       <!-- for StorageDomain VM migrate action -->
+      <!-- also used for Gluster hook update to choose server to update from 
-->
       <xs:element name="host" type="Host" minOccurs="0"/>
       <!-- for host NIC attach action -->
       <xs:element name="network" type="Network" minOccurs="0"/>
@@ -3135,6 +3136,123 @@
     </xs:complexContent>
   </xs:complexType>
 
+
+  <xs:element name="gluster_stages" type="GlusterStages"/>
+  <xs:complexType name="GlusterStages">
+    <xs:sequence>
+      <xs:element name="gluster_stage" type="xs:string" minOccurs="0" 
maxOccurs="unbounded">
+        <xs:annotation>
+          <xs:appinfo>
+            <jaxb:property name="GlusterStage"/>
+          </xs:appinfo>
+        </xs:annotation>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
+  
+  <xs:element name="hook_status" type="HookStatus"/>
+  <xs:complexType name="HookStatus">
+    <xs:sequence>
+      <xs:element name="hook_status" type="xs:string" minOccurs="0" 
maxOccurs="unbounded">
+        <xs:annotation>
+          <xs:appinfo>
+            <jaxb:property name="GlusterHookStatus"/>
+          </xs:appinfo>
+        </xs:annotation>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
+  
+  <xs:element name="content_types" type="ContentTypes"/>
+  <xs:complexType name="ContentTypes">
+    <xs:sequence>
+      <xs:element name="content_type" type="xs:string" minOccurs="0" 
maxOccurs="unbounded">
+        <xs:annotation>
+          <xs:appinfo>
+            <jaxb:property name="HookContentType"/>
+          </xs:appinfo>
+        </xs:annotation>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
+  
+  <xs:element name="server_hooks" type="GlusterServerHooks" />
+  <xs:complexType name="GlusterServerHooks">
+    <xs:complexContent>
+      <xs:extension base="BaseResources">
+        <xs:sequence>
+          <xs:annotation>
+            <xs:appinfo>
+              <jaxb:property name="GlusterServerHooks"/>
+            </xs:appinfo>
+          </xs:annotation>
+          <xs:element ref="server_hook" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  
+  <xs:element name="server_hook" type="GlusterServerHook"/>
+  <xs:complexType name="GlusterServerHook">
+    <xs:annotation>
+      <xs:appinfo>
+         <jaxb:class name="GlusterServerHook"/>
+      </xs:appinfo>
+    </xs:annotation>
+    <xs:complexContent>
+      <xs:extension base="BaseResource">
+        <xs:sequence>
+          <xs:element ref="host" minOccurs="0" maxOccurs="1"/>
+          <xs:element ref="content_types" minOccurs="0" maxOccurs="1" />
+          <xs:element ref="hook_status" minOccurs="0" maxOccurs="1"/>
+          <xs:element name="checksum" type="xs:string" minOccurs="0" 
maxOccurs="1"/>
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  
+  <xs:element name="gluster_hook" type="GlusterHook"/>
+  <xs:complexType name="GlusterHook">
+    <xs:annotation>
+      <xs:appinfo>
+         <jaxb:class name="GlusterHook"/>
+      </xs:appinfo>
+    </xs:annotation>
+    <xs:complexContent>
+      <xs:extension base="BaseResource">
+        <xs:sequence>
+          <xs:element ref="cluster" minOccurs="0" maxOccurs="1"/>
+          <xs:element name="gluster_command" type="xs:string" minOccurs="0" 
maxOccurs="1"/>
+          <xs:element name="gluster_stage" type="xs:string" minOccurs="0" 
maxOccurs="1"/>
+          <xs:element name="content_type" type="xs:string" minOccurs="0" 
maxOccurs="1"/>
+          <xs:element name="checksum" type="xs:string" minOccurs="0" 
maxOccurs="1"/>
+          <xs:element name="content" type="xs:string" minOccurs="0" 
maxOccurs="1"/>
+          <xs:element name="conflict_status" type="xs:unsignedShort" 
minOccurs="0" maxOccurs="1"/>
+          <xs:element name="conflicts" type="xs:string" minOccurs="0" 
maxOccurs="1"/>
+          <xs:element name="hook_status" type="xs:string" minOccurs="0" 
maxOccurs="1"/>
+          <xs:element ref="server_hooks" minOccurs="0" maxOccurs="1"/>
+         </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  
+ 
+  <xs:element name="glusterhooks" type="GlusterHooks" />
+  <xs:complexType name="GlusterHooks">
+    <xs:complexContent>
+      <xs:extension base="BaseResources">
+        <xs:sequence>
+          <xs:annotation>
+            <xs:appinfo>
+              <jaxb:property name="GlusterHooks"/>
+            </xs:appinfo>
+          </xs:annotation>
+          <xs:element ref="gluster_hook" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  
   <xs:element name="pm_proxies" type="PmProxies"/>
   <xs:complexType name="PmProxies">
     <xs:sequence>
diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml
 
b/backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml
index dbb0ad2..3df5950 100644
--- 
a/backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml
@@ -3176,3 +3176,73 @@
       Content-Type: {value: application/xml|json, required: true}
       Expect: {value: 201-created, required: false}
       Correlation-Id: {value: 'any string', required: false}
+- name: /api/clusters/{cluster:id}/glusterhooks|rel=get
+  request:
+    body:
+      parameterType: null
+      signatures: []
+    urlparams: {}
+    headers: {}
+- name: /api/clusters/{cluster:id}/glusterhooks/{glusterhook:id}|rel=get
+  request:
+    body:
+      parameterType: null
+      signatures: []
+    urlparams: {}
+    headers: {}
+- name: 
/api/clusters/{cluster:id}/glusterhooks/{glusterhook:id}/enable|rel=enable
+  request:
+    body:
+      parameterType: Action
+      signatures:
+      - mandatoryArguments: {}
+        optionalArguments: {}
+    urlparams: {}
+    headers:
+      Content-Type: {value: application/xml|json, required: true}
+      Correlation-Id: {value: 'any string', required: false}
+- name: 
/api/clusters/{cluster:id}/glusterhooks/{glusterhook:id}/disable|rel=disable
+  request:
+    body:
+      parameterType: Action
+      signatures:
+      - mandatoryArguments: {}
+        optionalArguments: {}
+    urlparams: {}
+    headers:
+      Content-Type: {value: application/xml|json, required: true}
+      Correlation-Id: {value: 'any string', required: false}
+- name: /api/clusters/{cluster:id}/glusterhooks/{glusterhook:id}/add|rel=add
+  request:
+    body:
+      parameterType: Action
+      signatures:
+      - mandatoryArguments: {}
+        optionalArguments: {}
+    urlparams: {}
+    headers:
+      Content-Type: {value: application/xml|json, required: true}
+      Correlation-Id: {value: 'any string', required: false}
+- name: 
/api/clusters/{cluster:id}/glusterhooks/{glusterhook:id}/update|rel=update
+  request:
+    body:
+      parameterType: Action
+      signatures:
+      - mandatoryArguments: {}
+        optionalArguments: {host.id: 'xs:string', host.name: 'xs:string'}
+    urlparams: {}
+    headers:
+      Content-Type: {value: application/xml|json, required: true}
+      Correlation-Id: {value: 'any string', required: false}
+- name: 
/api/clusters/{cluster:id}/glusterhooks/{glusterhook:id}/remove|rel=remove
+  request:
+    body:
+      parameterType: Action
+      signatures:
+      - mandatoryArguments: {}
+        optionalArguments: {}
+    urlparams: {}
+    headers:
+      Content-Type: {value: application/xml|json, required: true}
+      Correlation-Id: {value: 'any string', required: false}
+
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterResource.java
index 00e83e6..b2aa4d5 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterResource.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterResource.java
@@ -7,7 +7,9 @@
 import org.ovirt.engine.api.resource.AssignedNetworksResource;
 import org.ovirt.engine.api.resource.AssignedPermissionsResource;
 import org.ovirt.engine.api.resource.ClusterResource;
+import org.ovirt.engine.api.resource.gluster.GlusterHooksResource;
 import org.ovirt.engine.api.resource.gluster.GlusterVolumesResource;
+import 
org.ovirt.engine.api.restapi.resource.gluster.BackendGlusterHooksResource;
 import 
org.ovirt.engine.api.restapi.resource.gluster.BackendGlusterVolumesResource;
 import org.ovirt.engine.core.common.VdcObjectType;
 import org.ovirt.engine.core.common.action.VdcActionParametersBase;
@@ -71,4 +73,9 @@
         return model;
     }
 
+    @Override
+    public GlusterHooksResource getGlusterHooksResource() {
+        return inject(new BackendGlusterHooksResource(this,id));
+    }
+
 }
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClustersResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClustersResource.java
index d52486b..9e2e80e 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClustersResource.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClustersResource.java
@@ -25,8 +25,8 @@
 public class BackendClustersResource extends 
AbstractBackendCollectionResource<Cluster, VDSGroup>
         implements ClustersResource {
 
-    static final String[] SUB_COLLECTIONS = { "networks", "permissions", 
"glustervolumes" };
-    static final String VIRT_ONLY_MODE_COLLECTIONS_TO_HIDE = "glustervolumes";
+    static final String[] SUB_COLLECTIONS = { "networks", "permissions", 
"glustervolumes", "glusterhooks" };
+    static final String[] VIRT_ONLY_MODE_COLLECTIONS_TO_HIDE = 
{"glustervolumes","glusterhooks" };
     public BackendClustersResource() {
         super(Cluster.class, VDSGroup.class, SUB_COLLECTIONS);
     }
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/gluster/BackendGlusterHookResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/gluster/BackendGlusterHookResource.java
new file mode 100644
index 0000000..99523a2
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/gluster/BackendGlusterHookResource.java
@@ -0,0 +1,96 @@
+package org.ovirt.engine.api.restapi.resource.gluster;
+
+import javax.ws.rs.core.Response;
+
+import org.ovirt.engine.api.model.Action;
+import org.ovirt.engine.api.model.GlusterHook;
+import org.ovirt.engine.api.resource.gluster.GlusterHookResource;
+import org.ovirt.engine.api.restapi.resource.AbstractBackendActionableResource;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.action.gluster.GlusterHookManageParameters;
+import org.ovirt.engine.core.common.action.gluster.GlusterHookParameters;
+import org.ovirt.engine.core.common.businessentities.gluster.GlusterHookEntity;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.core.common.queries.gluster.GlusterHookQueryParameters;
+import org.ovirt.engine.core.compat.Guid;
+
+/**
+ * Implementation of the "glusterhooks/{id}" resource
+ */
+public class BackendGlusterHookResource
+        extends AbstractBackendActionableResource<GlusterHook, 
GlusterHookEntity>
+        implements GlusterHookResource {
+    private BackendGlusterHooksResource parent;
+
+    public BackendGlusterHookResource(String hookId, 
BackendGlusterHooksResource parent) {
+        this(hookId);
+        setParent(parent);
+    }
+
+    public BackendGlusterHookResource(String hookId) {
+        super(hookId, GlusterHook.class, GlusterHookEntity.class);
+    }
+
+    @Override
+    protected GlusterHook addParents(GlusterHook model) {
+        model.setId(id);
+        parent.addParents(model);
+        return model;
+    }
+
+    @Override
+    public GlusterHook get() {
+        return performGet(VdcQueryType.GetGlusterHookById, new 
GlusterHookQueryParameters(guid,true));
+    }
+
+    @Override
+    public Response enable(Action action) {
+        return doAction(VdcActionType.EnableGlusterHook, new 
GlusterHookParameters(guid), action);
+    }
+
+    @Override
+    public Response disable(Action action) {
+        return doAction(VdcActionType.DisableGlusterHook, new 
GlusterHookParameters(guid), action);
+    }
+
+    @Override
+    public Response add(Action action) {
+        return doAction(VdcActionType.AddGlusterHook, new 
GlusterHookManageParameters(guid), action);
+    }
+
+    @Override
+    public Response update(Action action) {
+        GlusterHookManageParameters params = new 
GlusterHookManageParameters(guid);
+        if (action.getHost() != null) {
+            validateParameters(action.getHost(),"host.id|name");
+            Guid hostId = getHostId(action);
+            if (hostId == null) {
+                return handleError(new 
EntityNotFoundException(action.getHost().getId() != null ? id : 
action.getHost().getName()), false);
+            }
+            params.setSourceServerId(hostId);
+        }
+        return doAction(VdcActionType.UpdateGlusterHook, params, action);
+    }
+
+    @Override
+    public Response remove(Action action) {
+        return doAction(VdcActionType.RemoveGlusterHook, new 
GlusterHookManageParameters(guid), action);
+    }
+
+    public BackendGlusterHooksResource getParent() {
+        return parent;
+    }
+
+    public void setParent(BackendGlusterHooksResource parent) {
+        this.parent = parent;
+    }
+
+    @Override
+    protected GlusterHook doPopulate(GlusterHook model, GlusterHookEntity 
entity) {
+        return model;
+    }
+
+    public String getId() {
+       return this.id;
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/gluster/BackendGlusterHooksResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/gluster/BackendGlusterHooksResource.java
new file mode 100644
index 0000000..22f44f1
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/gluster/BackendGlusterHooksResource.java
@@ -0,0 +1,90 @@
+package org.ovirt.engine.api.restapi.resource.gluster;
+
+import java.util.List;
+
+import javax.ws.rs.core.Response;
+
+import org.ovirt.engine.api.model.Cluster;
+import org.ovirt.engine.api.model.GlusterHook;
+import org.ovirt.engine.api.model.GlusterHooks;
+import org.ovirt.engine.api.resource.ClusterResource;
+import org.ovirt.engine.api.resource.gluster.GlusterHookResource;
+import org.ovirt.engine.api.resource.gluster.GlusterHooksResource;
+import org.ovirt.engine.api.restapi.resource.AbstractBackendCollectionResource;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.action.gluster.GlusterVolumeParameters;
+import org.ovirt.engine.core.common.businessentities.gluster.GlusterHookEntity;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.core.common.queries.gluster.GlusterParameters;
+
+/**
+ * Implementation of the "glusterhooks" resource
+ */
+public class BackendGlusterHooksResource
+        extends AbstractBackendCollectionResource<GlusterHook, 
GlusterHookEntity>
+        implements GlusterHooksResource {
+
+    private ClusterResource parent;
+    private String clusterId;
+
+    public BackendGlusterHooksResource() {
+        super(GlusterHook.class, GlusterHookEntity.class);
+    }
+
+    public BackendGlusterHooksResource(ClusterResource parent) {
+        this();
+        setParent(parent);
+    }
+
+    public BackendGlusterHooksResource(ClusterResource parent, String 
clusterId) {
+        this();
+        setParent(parent);
+        this.clusterId = clusterId;
+    }
+
+    public ClusterResource getParent() {
+        return parent;
+    }
+
+    public void setParent(ClusterResource parent) {
+        this.parent = parent;
+    }
+
+    @Override
+    public GlusterHooks list() {
+        List<GlusterHookEntity> entities = 
getBackendCollection(VdcQueryType.GetGlusterHooks, new 
GlusterParameters(asGuid(clusterId)));
+        return mapCollection(entities);
+    }
+
+    private GlusterHooks mapCollection(List<GlusterHookEntity> entities) {
+        GlusterHooks collection = new GlusterHooks();
+        for (GlusterHookEntity entity : entities) {
+            collection.getGlusterHooks().add(addLinks(populate(map(entity), 
entity)));
+        }
+        return collection;
+    }
+
+    @Override
+    protected GlusterHook addParents(GlusterHook hook) {
+        hook.setCluster(new Cluster());
+        hook.getCluster().setId(clusterId);
+        return hook;
+    }
+
+
+
+    @Override
+    protected Response performRemove(String id) {
+        return performAction(VdcActionType.DeleteGlusterVolume, new 
GlusterVolumeParameters(asGuid(id)));
+    }
+
+    @Override
+    public GlusterHookResource getGlusterHookSubResource(String id) {
+        return inject(new BackendGlusterHookResource(id, this));
+    }
+
+    @Override
+    protected GlusterHook doPopulate(GlusterHook model, GlusterHookEntity 
entity) {
+        return model;
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/AbstractBackendCollectionResourceTest.java
 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/AbstractBackendCollectionResourceTest.java
index e6577fe..fc9f9e7 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/AbstractBackendCollectionResourceTest.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/AbstractBackendCollectionResourceTest.java
@@ -65,15 +65,6 @@
     }
 
     @Test
-    public void testQuery() throws Exception {
-        UriInfo uriInfo = setUpUriExpectations(QUERY);
-
-        setUpQueryExpectations(QUERY);
-        collection.setUriInfo(uriInfo);
-        verifyCollection(getCollection());
-    }
-
-    @Test
     public void testListFailure() throws Exception {
         UriInfo uriInfo = setUpUriExpectations(null);
 
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/gluster/BackendGlusterHooksResourceTest.java
 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/gluster/BackendGlusterHooksResourceTest.java
new file mode 100644
index 0000000..a333cc0
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/gluster/BackendGlusterHooksResourceTest.java
@@ -0,0 +1,181 @@
+package org.ovirt.engine.api.restapi.resource.gluster;
+
+
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.UriInfo;
+
+import org.ovirt.engine.api.model.Cluster;
+import org.ovirt.engine.api.model.Fault;
+import org.ovirt.engine.api.model.GlusterHook;
+import org.ovirt.engine.api.resource.ClusterResource;
+import 
org.ovirt.engine.api.restapi.resource.AbstractBackendCollectionResourceTest;
+import org.ovirt.engine.api.restapi.resource.BackendClusterResource;
+import org.ovirt.engine.core.common.businessentities.gluster.GlusterHookEntity;
+import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.core.common.queries.gluster.GlusterParameters;
+import org.ovirt.engine.core.compat.Guid;
+
+public class BackendGlusterHooksResourceTest extends 
AbstractBackendCollectionResourceTest<GlusterHook, GlusterHookEntity, 
BackendGlusterHooksResource> {
+    private static final Guid clusterId = GUIDS[0];
+    private static final String defaultClusterName = "Default";
+    private static ClusterResource parentMock;
+
+    public BackendGlusterHooksResourceTest() {
+        super(new BackendGlusterHooksResource(parentMock, 
clusterId.toString()),
+                null,
+                null);
+    }
+
+    /**
+     * Override init to perform additional mocking required
+     * for the "list" method of the collection resource.
+     */
+    @Override
+    protected void init() {
+        super.init();
+        parentMock = control.createMock(BackendClusterResource.class);
+        collection.setParent(parentMock);
+        setupListExpectations();
+    }
+
+    @Override
+    public void testList() throws Exception {
+        setUpHooksQueryExpectations(null);
+        UriInfo uriInfo = setUpUriExpectations(null);
+        collection.setUriInfo(uriInfo);
+        control.replay();
+
+        verifyCollection(getCollection());
+    }
+
+    @Override
+    public void testListCrash() throws Exception {
+        UriInfo uriInfo = setUpUriExpectations(null);
+        collection.setUriInfo(uriInfo);
+
+        Throwable t = new RuntimeException(FAILURE);
+        setUpHooksQueryExpectations(t);
+        control.replay();
+
+        try {
+            getCollection();
+            fail("expected WebApplicationException");
+        } catch (WebApplicationException wae) {
+            verifyFault(wae, BACKEND_FAILED_SERVER_LOCALE, t);
+        }
+    }
+
+    @Override
+    public void testListCrashClientLocale() throws Exception {
+        collection.setUriInfo(setUpUriExpectations(null));
+        locales.add(CLIENT_LOCALE);
+
+        Throwable t = new RuntimeException(FAILURE);
+        setUpHooksQueryExpectations(t);
+        control.replay();
+
+        try {
+            getCollection();
+            fail("expected WebApplicationException");
+        } catch (WebApplicationException wae) {
+            verifyFault(wae, BACKEND_FAILED_CLIENT_LOCALE, t);
+        } finally {
+            locales.clear();
+        }
+    }
+
+    @Override
+    public void testListFailure() throws Exception {
+        collection.setUriInfo(setUpUriExpectations(null));
+
+        setUpHooksQueryExpectations(FAILURE);
+        control.replay();
+
+        try {
+            getCollection();
+            fail("expected WebApplicationException");
+        } catch (WebApplicationException wae) {
+            assertTrue(wae.getResponse().getEntity() instanceof Fault);
+            assertEquals(mockl10n(FAILURE), ((Fault) 
wae.getResponse().getEntity()).getDetail());
+        }
+    }
+
+    @Override
+    protected List<GlusterHook> getCollection() {
+        return collection.list().getGlusterHooks();
+    }
+
+    @Override
+    protected GlusterHookEntity getEntity(int index) {
+        return setUpEntityExpectations(
+                control.createMock(GlusterHookEntity.class),
+                index);
+    }
+
+
+    /**
+     * Overridden as {@link GlusterHookEntity} does not have description field
+     */
+    @Override
+    protected void verifyModel(GlusterHook model, int index) {
+        assertEquals(GUIDS[index].toString(), model.getId());
+        assertEquals(NAMES[index], model.getName());
+        assertEquals("create",
+                model.getGlusterCommand());
+        assertEquals(clusterId.toString(), model.getCluster().getId());
+        verifyLinks(model);
+    }
+
+
+    static GlusterHookEntity setUpEntityExpectations(
+            GlusterHookEntity entity, int index) {
+        expect(entity.getId()).andReturn(GUIDS[index]).anyTimes();
+        //expect(entity.getName()).andReturn(NAMES[index]).anyTimes();
+        expect(entity.getHookKey()).andReturn(NAMES[index]).anyTimes();
+        expect(entity.getClusterId()).andReturn(GUIDS[2]).anyTimes();
+        expect(entity.getGlusterCommand()).andReturn("create").anyTimes();
+        return entity;
+    }
+
+    private void setupListExpectations() {
+        Cluster cluster = new Cluster();
+        cluster.setName(defaultClusterName);
+        cluster.setId(clusterId.toString());
+
+        parentMock = control.createMock(ClusterResource.class);
+        expect(parentMock.get()).andReturn(cluster).anyTimes();
+    }
+
+    private void setUpHooksQueryExpectations(Object failure) {
+        VdcQueryReturnValue queryResult = 
control.createMock(VdcQueryReturnValue.class);
+        expect(queryResult.getSucceeded()).andReturn(failure == 
null).anyTimes();
+        List<GlusterHookEntity> entities = new ArrayList<GlusterHookEntity>();
+
+        if (failure == null) {
+            for (int i = 0; i < NAMES.length; i++) {
+                entities.add(getEntity(i));
+            }
+            
expect(queryResult.getReturnValue()).andReturn(entities).anyTimes();
+        } else {
+            if (failure instanceof String) {
+                expect(queryResult.getExceptionString()).andReturn((String) 
failure).anyTimes();
+                setUpL10nExpectations((String)failure);
+            } else if (failure instanceof Exception) {
+                expect(backend.RunQuery(eq(VdcQueryType.GetGlusterHooks), 
anyObject(GlusterParameters.class))).andThrow((Exception) failure).anyTimes();
+                return;
+            }
+        }
+        expect(backend.RunQuery(eq(VdcQueryType.GetGlusterHooks), 
anyObject(GlusterParameters.class))).andReturn(
+                queryResult).anyTimes();
+
+    }
+
+}
diff --git 
a/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/GlusterHookMapper.java
 
b/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/GlusterHookMapper.java
new file mode 100644
index 0000000..7b454b5
--- /dev/null
+++ 
b/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/GlusterHookMapper.java
@@ -0,0 +1,152 @@
+package org.ovirt.engine.api.restapi.types;
+
+import org.ovirt.engine.api.model.GlusterHook;
+import org.ovirt.engine.api.model.GlusterServerHooks;
+import org.ovirt.engine.api.model.Host;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterHookConflictFlags;
+import org.ovirt.engine.core.common.businessentities.gluster.GlusterHookEntity;
+import org.ovirt.engine.core.common.businessentities.gluster.GlusterServerHook;
+import org.ovirt.engine.core.compat.Guid;
+
+public class GlusterHookMapper {
+
+    @Mapping(from = GlusterHook.class, to = GlusterHookEntity.class)
+    public static GlusterHookEntity map(GlusterHook hook, GlusterHookEntity 
entity) {
+        GlusterHookEntity hookEntity = entity != null ? entity : new 
GlusterHookEntity();
+
+        if (hook.isSetId()) {
+            
hookEntity.setId(Guid.createGuidFromStringDefaultEmpty(hook.getId()));
+        }
+
+        if (hook.isSetName()) {
+            hookEntity.setName(hook.getName());
+        }
+
+        if (hook.isSetGlusterCommand()) {
+            hookEntity.setGlusterCommand(hook.getGlusterCommand());
+        }
+
+        if (hook.isSetChecksum()) {
+            hookEntity.setChecksum(hook.getChecksum());
+        }
+
+        if (hook.isSetContent()) {
+            hookEntity.setContent(hook.getContent());
+        }
+
+        return hookEntity;
+    }
+
+    @Mapping(from = GlusterHookEntity.class, to = GlusterHook.class)
+    public static GlusterHook map(GlusterHookEntity entity, GlusterHook hook) {
+        GlusterHook model = hook != null ? hook : new GlusterHook();
+
+        if (entity.getId() != null) {
+            model.setId(entity.getId().toString());
+        }
+
+        if (entity.getHookKey() != null) {
+            model.setName(entity.getHookKey());
+        }
+
+        if (entity.getGlusterCommand() != null) {
+            model.setGlusterCommand(entity.getGlusterCommand());
+        }
+
+        if (entity.getStage() != null) {
+            model.setGlusterStage(map(entity.getStage(),null));
+        }
+
+        if (entity.getStatus() != null) {
+            model.setHookStatus(map(entity.getStatus(),null));
+        }
+
+        if (entity.getContentType() != null) {
+            model.setContentType(map(entity.getContentType(), null));
+        }
+
+        if (entity.getContent() != null) {
+            model.setContent(entity.getContent());
+        }
+
+        if (entity.getConflictStatus() != null) {
+            model.setConflictStatus(entity.getConflictStatus());
+            model.setConflicts(mapConflicts(entity));
+        }
+
+        if (entity.getServerHooks() != null && 
!entity.getServerHooks().isEmpty()) {
+            model.setServerHooks(new GlusterServerHooks());
+            for (GlusterServerHook serverHookEntity : entity.getServerHooks()) 
{
+                
model.getServerHooks().getGlusterServerHooks().add(map(serverHookEntity));
+            }
+        }
+
+        return model;
+    }
+
+    private static String mapConflicts(GlusterHookEntity hook) {
+        StringBuffer sb = new StringBuffer();
+        if (hook.isMissingHookConflict()) {
+            sb.append(GlusterHookConflictFlags.MISSING_HOOK.toString());
+        }
+        if (hook.isContentConflict()) {
+            sb.append(sb.length() > 0 ? 
",":"").append(GlusterHookConflictFlags.CONTENT_CONFLICT.toString());
+        }
+        if (hook.isStatusConflict()) {
+            sb.append(sb.length() > 0 ? 
",":"").append(GlusterHookConflictFlags.STATUS_CONFLICT.toString());
+        }
+        return sb.toString();
+    }
+
+    @Mapping 
(from=org.ovirt.engine.core.common.businessentities.gluster.GlusterServerHook.class,
 to=org.ovirt.engine.api.model.GlusterServerHook.class)
+    public static org.ovirt.engine.api.model.GlusterServerHook 
map(GlusterServerHook serverHookEntity) {
+        org.ovirt.engine.api.model.GlusterServerHook serverHookModel = new 
org.ovirt.engine.api.model.GlusterServerHook();
+        if (serverHookEntity.getServerId() != null) {
+            serverHookModel.setHost(new Host());
+            
serverHookModel.getHost().setId(serverHookEntity.getServerId().toString());
+        }
+        return serverHookModel;
+    }
+
+    @Mapping(from = 
org.ovirt.engine.core.common.businessentities.gluster.GlusterHookContentType.class,
 to = String.class)
+    public static String 
map(org.ovirt.engine.core.common.businessentities.gluster.GlusterHookContentType
 hookContentType,
+            String template) {
+        switch (hookContentType) {
+        case BINARY:
+            return 
org.ovirt.engine.core.common.businessentities.gluster.GlusterHookContentType.BINARY.toString();
+        case TEXT:
+            return 
org.ovirt.engine.core.common.businessentities.gluster.GlusterHookContentType.TEXT.toString();
+        default:
+            return null;
+        }
+    }
+
+    @Mapping(from = 
org.ovirt.engine.core.common.businessentities.gluster.GlusterHookStage.class, 
to = String.class)
+    public static String 
map(org.ovirt.engine.core.common.businessentities.gluster.GlusterHookStage 
hookStage,
+            String template) {
+        switch (hookStage) {
+        case POST:
+            return 
org.ovirt.engine.core.common.businessentities.gluster.GlusterHookStage.POST.toString();
+        case PRE:
+            return 
org.ovirt.engine.core.common.businessentities.gluster.GlusterHookStage.PRE.toString();
+        default:
+            return null;
+        }
+    }
+
+    @Mapping(from = 
org.ovirt.engine.core.common.businessentities.gluster.GlusterHookStatus.class, 
to = String.class)
+    public static String 
map(org.ovirt.engine.core.common.businessentities.gluster.GlusterHookStatus 
hookStatus,
+            String template) {
+        switch (hookStatus) {
+        case DISABLED:
+            return 
org.ovirt.engine.core.common.businessentities.gluster.GlusterHookStatus.DISABLED.toString();
+        case ENABLED:
+            return 
org.ovirt.engine.core.common.businessentities.gluster.GlusterHookStatus.ENABLED.toString();
+        case MISSING:
+            return 
org.ovirt.engine.core.common.businessentities.gluster.GlusterHookStatus.MISSING.toString();
+        default:
+            return null;
+        }
+    }
+
+}


-- 
To view, visit http://gerrit.ovirt.org/16512
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibf9c0299977448e0b50feeed6e38a015c60b86fd
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Sahina Bose <[email protected]>
_______________________________________________
Engine-patches mailing list
[email protected]
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to