You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sm...@apache.org on 2015/11/25 00:37:28 UTC

[1/2] ambari git commit: AMBARI-13956. Add functional test infrastructure commands to perform API calls (Nahappan Somasundaram)

Repository: ambari
Updated Branches:
  refs/heads/trunk aa465686f -> b5e8a3bf8


http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponent/SetServiceComponentStateWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponent/SetServiceComponentStateWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponent/SetServiceComponentStateWebRequest.java
new file mode 100644
index 0000000..df7707b
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponent/SetServiceComponentStateWebRequest.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.servicecomponent;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+import org.apache.ambari.server.state.State;
+
+public class SetServiceComponentStateWebRequest extends AmbariHttpWebRequest {
+    private String clusterName;
+    private String serviceName;
+    private String componentName;
+    private State componentState;
+    private String requestContext;
+    private static String pathFormat = "/api/v1/clusters/%s/services/%s";
+
+    public SetServiceComponentStateWebRequest(ConnectionParams params, String clusterName, String serviceName,
+                                              String componentName, State componentState, String requestContext) {
+        super(params);
+        this.clusterName = clusterName;
+        this.serviceName = serviceName;
+        this.componentName = componentName;
+        this.componentState = componentState;
+        this.requestContext = requestContext;
+    }
+
+    public String getClusterName() { return this.clusterName; }
+
+    public String getServiceName() { return this.serviceName; }
+
+    public State getComponentState() { return this.componentState; }
+
+    public String getRequestContext() { return this.requestContext; }
+
+    @Override
+    public String getHttpMethod() {
+        return "PUT";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName, serviceName, componentName);
+    }
+
+    /**
+     * Constructs the request data.
+     *
+     * @return - Request data.
+     */
+    @Override
+    protected String getRequestData() {
+        /**
+         * {
+         * "RequestInfo" : {"context" : requestContext},
+         * "Body" : {"ServiceComponentInfo" : {"state" : componentState}}
+         * }
+         */
+        JsonObject jsonObject = new JsonObject();
+        jsonObject.add("RequestInfo", createJsonObject("context", requestContext));
+        jsonObject.add("Body", createJsonObject("ServiceComponentInfo", createJsonObject("state", componentState.toString())));
+        Gson gson = new Gson();
+        return gson.toJson(jsonObject);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/AddServiceComponentHostWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/AddServiceComponentHostWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/AddServiceComponentHostWebRequest.java
new file mode 100644
index 0000000..cd0fe0a
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/AddServiceComponentHostWebRequest.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.servicecomponenthost;
+
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+
+/**
+ * Adds a service component to a host.
+ */
+public class AddServiceComponentHostWebRequest extends AmbariHttpWebRequest {
+    private String clusterName;
+    private String hostName;
+    private String componentName;
+    private static String pathFormat = "/api/v1/clusters/%s/hosts/%s/host_components/%s";
+
+    /**
+     * Adds the specified service component to the specified host.
+     *
+     * @param params - Ambari server connection information.
+     * @param clusterName - Existing cluster.
+     * @param hostName - Existing host.
+     * @param componentName - Component to be added to hostName.
+     */
+    public AddServiceComponentHostWebRequest(ConnectionParams params, String clusterName, String hostName,
+                                             String componentName) {
+        super(params);
+        this.clusterName = clusterName;
+        this.hostName = hostName;
+        this.componentName = componentName;
+    }
+
+    public String getClusterName() { return this.clusterName; }
+
+    public String getHostName() { return this.hostName; }
+
+    public String getComponentName() { return this.componentName; }
+
+    @Override
+    public String getHttpMethod() {
+        return "POST";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName, hostName, componentName);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/BulkAddServiceComponentHostsWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/BulkAddServiceComponentHostsWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/BulkAddServiceComponentHostsWebRequest.java
new file mode 100644
index 0000000..bacabb8
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/BulkAddServiceComponentHostsWebRequest.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.servicecomponenthost;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Bulk add a set of components on multiple hosts.
+ * Replaces multiple calls to AddServiceComponentHostWebRequest
+ */
+public class BulkAddServiceComponentHostsWebRequest extends AmbariHttpWebRequest {
+    private String clusterName;
+    private List<String> hostNames;
+    private List<String> componentNames;
+    private static String pathFormat = "/api/v1/clusters/%s/hosts";
+
+    /**
+     * Adds multiple componenents to multiple hosts.
+     *
+     * @param params - Ambari server connection information.
+     * @param clusterName - Existing cluster.
+     * @param hostNames - Hosts on which components are to be added.
+     * @param componentNames - Components to be added.
+     */
+    public BulkAddServiceComponentHostsWebRequest(ConnectionParams params, String clusterName, List<String> hostNames,
+                                                  List<String> componentNames) {
+        super(params);
+        this.clusterName = clusterName;
+        this.hostNames = new ArrayList<>(hostNames);
+        this.componentNames = new ArrayList<>(componentNames);
+    }
+
+    public String getClusterName() { return this.clusterName; }
+
+    public List<String> getHostNames() { return Collections.unmodifiableList(this.hostNames); }
+
+    public List<String> getComponentNames() { return Collections.unmodifiableList(this.componentNames); }
+
+    @Override
+    public String getHttpMethod() {
+        return "POST";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName);
+    }
+
+    /**
+     * Constructs the request data.
+     *
+     * @return - Request data.
+     */
+    @Override
+    protected String getRequestData() {
+        /**
+         * {
+         *   "RequestInfo" : {
+         *     "query":"Hosts/host_name.in(host1,host2)"
+         *   },
+         *   "Body" : {
+         *     "host_components": [
+         *     {
+         *       "HostRoles" : { "component_name" : "HIVE_CLIENT" }
+         *     },
+         *     {
+         *       "HostRoles" : { "component_name" : "TEZ_CLIENT" }
+         *     }
+         *     ]
+         * }
+         */
+        JsonObject jsonObject =  new JsonObject();
+        JsonArray hostRoles = new JsonArray();
+
+        jsonObject.add("RequestInfo", createJsonObject("query", String.format("Hosts/host_name.in(%s)", toCsv(hostNames))));
+
+        for (String componentName : componentNames) {
+            hostRoles.add(createJsonObject("HostRoles", createJsonObject("component_name", componentName)));
+        }
+
+        jsonObject.add("Body", createJsonObject("host_components", hostRoles));
+
+        Gson gson = new Gson();
+        return gson.toJson(jsonObject);
+    }
+
+    private static String toCsv(List<String> list) {
+        StringBuilder sb = new StringBuilder();
+
+        for (String item : list) {
+            sb.append(String.format("%s,", item));
+        }
+
+        sb.deleteCharAt(sb.length() - 1);
+
+        return sb.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/BulkSetServiceComponentHostStateWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/BulkSetServiceComponentHostStateWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/BulkSetServiceComponentHostStateWebRequest.java
new file mode 100644
index 0000000..6634373
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/BulkSetServiceComponentHostStateWebRequest.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.servicecomponenthost;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+import org.apache.ambari.server.state.State;
+
+/**
+ * Updates the state of the specified set of components.
+ */
+public class BulkSetServiceComponentHostStateWebRequest extends AmbariHttpWebRequest {
+    private String clusterName;
+    private State currentState;
+    private State desiredState;
+
+    private static String pathFormat = "/api/v1/clusters/%s/host_components?HostRoles/state=%s";
+
+    /**
+     * Updates the state of multiple components in a cluster.
+     *
+     * @param params - Ambari server connection information.
+     * @param clusterName - Existing cluster name.
+     * @param currentState - Desired state.
+     * @param desiredState - Current state.
+     */
+    public BulkSetServiceComponentHostStateWebRequest(ConnectionParams params, String clusterName, State currentState,
+                                                      State desiredState) {
+        super(params);
+        this.clusterName = clusterName;
+        this.currentState = currentState;
+        this.desiredState = desiredState;
+    }
+
+    @Override
+    public String getHttpMethod() {
+        return "PUT";
+    }
+
+    public State getCurrentState() { return this. currentState; }
+
+    public State getDesiredState() { return this.desiredState; }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName, this.currentState);
+    }
+
+    /**
+     * Constructs the request data.
+     *
+     * @return - Request data.
+     */
+    @Override
+    protected String getRequestData() {
+        /**
+         *     {
+         *       "HostRoles" : { "state" : "INSTALLED" }
+         *     }
+         */
+        JsonObject jsonObject =  new JsonObject();
+
+        jsonObject.add("HostRoles", createJsonObject("state", desiredState.toString()));
+
+        Gson gson = new Gson();
+        return gson.toJson(jsonObject);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/GetServiceComponentHostWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/GetServiceComponentHostWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/GetServiceComponentHostWebRequest.java
new file mode 100644
index 0000000..15d1441
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/GetServiceComponentHostWebRequest.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.servicecomponenthost;
+
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+
+/**
+ * Gets a service component to a host.
+ */
+public class GetServiceComponentHostWebRequest extends AmbariHttpWebRequest {
+    private String clusterName;
+    private String hostName;
+    private String componentName;
+    private static String pathFormat = "/api/v1/clusters/%s/hosts/%s/host_components/%s";
+
+    /**
+     * Gets the specified service component to the specified host.
+     *
+     * @param params - Ambari server connection information.
+     * @param clusterName - Existing cluster.
+     * @param hostName - Existing host.
+     * @param componentName - Component to be added to hostName.
+     */
+    public GetServiceComponentHostWebRequest(ConnectionParams params, String clusterName, String hostName,
+                                             String componentName) {
+        super(params);
+        this.clusterName = clusterName;
+        this.hostName = hostName;
+        this.componentName = componentName;
+    }
+
+    public String getClusterName() { return this.clusterName; }
+
+    public String getHostName() { return this.hostName; }
+
+    public String getComponentName() { return this.componentName; }
+
+    @Override
+    public String getHttpMethod() {
+        return "GET";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName, hostName, componentName);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/SetServiceComponentHostStateWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/SetServiceComponentHostStateWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/SetServiceComponentHostStateWebRequest.java
new file mode 100644
index 0000000..8534a00
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponenthost/SetServiceComponentHostStateWebRequest.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.servicecomponenthost;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.state.State;
+
+public class SetServiceComponentHostStateWebRequest extends AmbariHttpWebRequest {
+    private String clusterName;
+    private String hostName;
+    private String componentName;
+    private State componentState;
+    private String requestContext;
+    private static String pathFormat = "/api/v1/clusters/%s/hosts/%s/host_components/%s";
+
+    public SetServiceComponentHostStateWebRequest(ConnectionParams params, String clusterName, String hostName,
+                                                  String componentName, State componentState, String requestContext) {
+        super(params);
+        this.clusterName = clusterName;
+        this.hostName = hostName;
+        this.componentName = componentName;
+        this.componentState = componentState;
+        this.requestContext = requestContext;
+    }
+
+    public String getClusterName() { return this.clusterName; }
+
+    public String getHostName() { return this.hostName; }
+
+    public State getComponentState() { return this.componentState; }
+
+    public String getRequestContext() { return this.requestContext; }
+
+    @Override
+    public String getHttpMethod() {
+        return "PUT";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName, hostName, componentName);
+    }
+
+    /**
+     * Constructs the request data.
+     *
+     * @return - Request data.
+     */
+    @Override
+    protected String getRequestData() {
+        /**
+         * {
+         * "RequestInfo" : {"context" : requestContext},
+         * "Body" : {"HostRoles" : {"state" : componentState}}
+         * }
+         */
+        String content;
+        JsonObject jsonObject = new JsonObject();
+        jsonObject.add("RequestInfo", createJsonObject("context", requestContext));
+        jsonObject.add("Body", createJsonObject("HostRoles", createJsonObject("state", componentState.toString())));
+        Gson gson = new Gson();
+        content = gson.toJson(jsonObject);
+        return content;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/DeleteServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/DeleteServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/DeleteServiceTest.java
new file mode 100644
index 0000000..f7bd333
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/DeleteServiceTest.java
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.server;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.functionaltests.api.WebResponse;
+import org.apache.ambari.server.functionaltests.api.service.DeleteServiceWebRequest;
+import org.apache.ambari.server.functionaltests.api.service.GetServiceWebRequest;
+import org.apache.ambari.server.functionaltests.api.service.StopServiceWebRequest;
+import org.apache.ambari.server.functionaltests.utils.ClusterUtils;
+import org.apache.ambari.server.functionaltests.utils.RestApiUtils;
+import org.apache.ambari.server.orm.dao.ClusterServiceDAO;
+import org.apache.ambari.server.orm.dao.ServiceDesiredStateDAO;
+import org.apache.ambari.server.orm.dao.ServiceComponentDesiredStateDAO;
+import org.apache.ambari.server.orm.dao.HostComponentStateDAO;
+import org.apache.ambari.server.orm.dao.HostComponentDesiredStateDAO;
+import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
+import org.apache.ambari.server.orm.entities.ServiceDesiredStateEntity;
+import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity;
+import org.apache.ambari.server.orm.entities.HostComponentStateEntity;
+import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity;
+import org.apache.ambari.server.orm.entities.ServiceDesiredStateEntityPK;
+import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntityPK;
+import org.apache.ambari.server.state.State;
+
+import org.apache.commons.httpclient.HttpStatus;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+
+/**
+ * Simple test that starts the local ambari server,
+ * tests it's status and shuts down the server.
+ */
+@Ignore
+public class DeleteServiceTest extends ServerTestBase {
+    /**
+     * Set up a test cluster with a service, a host and a few components.
+     * Attempt to delete the service. Verify the state of the DB.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testDeleteService() throws Exception {
+        String clusterName = "c1";
+        String serviceName = "HDFS";
+        ConnectionParams params = new ConnectionParams();
+
+        params.setServerName("localhost");
+        params.setServerApiPort(serverPort);
+        params.setServerAgentPort(serverAgentPort);
+        params.setUserName("admin");
+        params.setPassword("admin");
+
+        ClusterUtils clusterUtils = injector.getInstance(ClusterUtils.class);
+        clusterUtils.createSampleCluster(params);
+
+        /**
+         * Verify the status of the service
+         */
+        JsonElement jsonResponse = RestApiUtils.executeRequest(new GetServiceWebRequest(params, clusterName, serviceName));
+        assertTrue(!jsonResponse.isJsonNull());
+        JsonObject jsonServiceInfoObj = jsonResponse.getAsJsonObject().get("ServiceInfo").getAsJsonObject();
+        String cluster_name = jsonServiceInfoObj.get("cluster_name").getAsString();
+        assertEquals(cluster_name, clusterName);
+
+        String service_name = jsonServiceInfoObj.get("service_name").getAsString();
+        assertEquals(service_name, serviceName);
+
+        /**
+         * Check the following:
+         * ClusterServiceDAO
+         * ServiceDesiredStateDAO
+         * ServiceComponentDesiredStateDAO
+         * HostComponentStateDAO
+         * HostComponentDesiredStateDAO
+         */
+
+        /**
+         * Stop the service
+         */
+
+        jsonResponse = RestApiUtils.executeRequest(new StopServiceWebRequest(params, clusterName, serviceName));
+
+        /**
+         * clusterservice table
+         */
+        ClusterServiceDAO clusterServiceDAO = injector.getInstance(ClusterServiceDAO.class);
+        List<ClusterServiceEntity> clusterServiceEntities = clusterServiceDAO.findAll();
+        assertEquals(clusterServiceEntities.size(), 1); // Only one service in the sample cluster (HDFS)
+        assertEquals(clusterServiceEntities.get(0).getServiceName(), serviceName); // Verify the only service name
+
+        ClusterServiceEntity clusterServiceEntity = clusterServiceEntities.get(0);
+        long clusterId = clusterServiceEntity.getClusterId();
+
+        /**
+         * servicedesiredstate table
+         */
+        ServiceDesiredStateDAO serviceDesiredStateDAO = injector.getInstance(ServiceDesiredStateDAO.class);
+        List<ServiceDesiredStateEntity> serviceDesiredStateEntities = serviceDesiredStateDAO.findAll();
+        assertEquals(serviceDesiredStateEntities.size(), 1);
+        ServiceDesiredStateEntity serviceDesiredStateEntity = serviceDesiredStateEntities.get(0);
+        assertEquals(serviceDesiredStateEntity.getServiceName(), serviceName);
+        assertEquals(serviceDesiredStateEntity.getDesiredState(), State.INSTALLED);
+
+        /**
+         * servicecomponentdesiredstate table
+         */
+        ServiceComponentDesiredStateDAO serviceComponentDesiredStateDAO = injector.getInstance(ServiceComponentDesiredStateDAO.class);
+        List<ServiceComponentDesiredStateEntity>  serviceComponentDesiredStateEntities =  serviceComponentDesiredStateDAO.findAll();
+        assertEquals(serviceComponentDesiredStateEntities.size(), 3); // NAMENODE, SECONDARY_NAMENODE, DATANODE.
+        for (ServiceComponentDesiredStateEntity serviceComponentDesiredStateEntity : serviceComponentDesiredStateEntities) {
+            assertEquals(serviceComponentDesiredStateEntity.getDesiredState(), State.INSTALLED);
+        }
+
+        /**
+         * hostcomponentstate table
+         */
+        HostComponentStateDAO hostComponentStateDAO = injector.getInstance(HostComponentStateDAO.class);
+        List<HostComponentStateEntity> hostComponentStateEntities = hostComponentStateDAO.findAll();
+        assertEquals(hostComponentStateEntities.size(), 3);
+
+        /**
+         * hostcomponentdesiredstate table
+         */
+        HostComponentDesiredStateDAO hostComponentDesiredStateDAO = injector.getInstance(HostComponentDesiredStateDAO.class);
+        List<HostComponentDesiredStateEntity> hostComponentDesiredStateEntities = hostComponentDesiredStateDAO.findAll();
+        assertEquals(hostComponentDesiredStateEntities.size(), 3);
+
+        /**
+         * Delete the service
+         */
+        jsonResponse = RestApiUtils.executeRequest(new DeleteServiceWebRequest(params, clusterName, serviceName));
+
+        WebResponse webResponse = new GetServiceWebRequest(params, clusterName, serviceName).getResponse();
+        assertEquals(webResponse.getStatusCode(), HttpStatus.SC_NOT_FOUND);
+
+        /**
+         * ClusterServiceDAO - the service entry should have been removed.
+         */
+        clusterServiceEntity = clusterServiceDAO.findByClusterAndServiceNames(clusterName, serviceName);
+        assertTrue(clusterServiceEntity == null);
+
+        /**
+         * ServiceDesiredStateDAO - the service entry should have been removed.
+         */
+        ServiceDesiredStateEntityPK serviceDesiredStateEntityPK = injector.getInstance(ServiceDesiredStateEntityPK.class);
+        serviceDesiredStateEntityPK.setClusterId(clusterId);
+        serviceDesiredStateEntityPK.setServiceName(serviceName);
+        serviceDesiredStateEntity =  serviceDesiredStateDAO.findByPK(serviceDesiredStateEntityPK);
+        assertTrue(serviceDesiredStateEntity == null);
+
+        /**
+         * ServiceComponentDesiredStateDAO
+         */
+        ServiceComponentDesiredStateEntityPK serviceComponentDesiredStateEntityPK = injector.getInstance(ServiceComponentDesiredStateEntityPK.class);
+        ServiceComponentDesiredStateEntity serviceComponentDesiredStateEntity = serviceComponentDesiredStateDAO.findByPK(serviceComponentDesiredStateEntityPK);
+        assertTrue(serviceComponentDesiredStateEntity == null);
+
+        /**
+         * HostComponentStateDAO
+         */
+        hostComponentStateEntities = hostComponentStateDAO.findByService(serviceName);
+        assertEquals(hostComponentStateEntities.size(), 0);
+
+
+        /**
+         * HostComponentDesiredStateDAO
+         */
+        hostComponentDesiredStateEntities = hostComponentDesiredStateDAO.findAll();
+        assertEquals(hostComponentDesiredStateEntities.size(), 0);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/LocalAmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/LocalAmbariServer.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/LocalAmbariServer.java
index ceadbc2..24b4ccf 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/LocalAmbariServer.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/LocalAmbariServer.java
@@ -18,15 +18,13 @@
 
 package org.apache.ambari.server.functionaltests.server;
 
+import com.google.inject.Inject;
 import com.google.inject.persist.PersistService;
 import org.apache.ambari.server.controller.AmbariServer;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import com.google.inject.Guice;
 import com.google.inject.Injector;
-import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
-import org.apache.ambari.server.configuration.Configuration;
 
 /**
 * Wrap AmbariServer as a testable unit.
@@ -40,20 +38,10 @@ public class LocalAmbariServer implements Runnable {
    */
   private AmbariServer ambariServer = null;
 
-  private Injector injector = null;
+  @Inject
+  private Injector injector;
 
-  private InMemoryDefaultTestModule module = null;
-
-  /**
-   * Default constructor using the default implementation of InMemoryDefaultTestModule.
-   */
-  public LocalAmbariServer() { this.module = new InMemoryDefaultTestModule(); }
-
-  /**
-   * Overloaded constructor for sub-classed InMemoryDefaultTestModule implementations.
-   * @param module
-   */
-  public LocalAmbariServer(InMemoryDefaultTestModule module) { this.module = module; }
+  public LocalAmbariServer() {}
 
   /**
    * Thread entry point.
@@ -76,16 +64,6 @@ public class LocalAmbariServer implements Runnable {
    * @throws Exception
    */
   private void startServer() throws Exception {
-    /**
-     * Specify the temp folder as the source for certificate keys.
-     * Without this, the CertificateManager will generate the keys
-     * in the current folder (ambari-server) causing issues with
-     * rat check.
-     */
-    String tmpDir = System.getProperty("java.io.tmpdir");
-    this.module.getProperties().setProperty(Configuration.SRVR_KSTR_DIR_KEY, tmpDir);
-    injector = Guice.createInjector(this.module);
-
     try {
       LOG.info("Attempting to start ambari server...");
 
@@ -99,6 +77,7 @@ public class LocalAmbariServer implements Runnable {
     } catch (Throwable t) {
       LOG.error("Failed to run the Ambari Server", t);
       stopServer();
+      throw t;
     }
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/ServerTestBase.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/ServerTestBase.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/ServerTestBase.java
new file mode 100644
index 0000000..a6d953a
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/ServerTestBase.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.server;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.junit.After;
+import org.junit.Before;
+
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * Base test infrastructure.
+ */
+public class ServerTestBase {
+    /**
+     * Run the ambari server on a thread.
+     */
+    protected Thread serverThread = null;
+
+    /**
+     * Instance of the local ambari server, which wraps the actual
+     * ambari server with test configuration.
+     */
+    protected LocalAmbariServer server = null;
+
+    /**
+     * Server port
+     */
+    protected static int serverPort = 9995;
+
+    /**
+     * Server agent port
+     */
+    protected static int serverAgentPort = 9000;
+
+    /**
+     * Guice injector using an in-memory DB.
+     */
+    protected Injector injector = null;
+
+    /**
+     * Server URL
+     */
+    protected static String SERVER_URL_FORMAT = "http://localhost:%d";
+
+    /**
+     * Start our local server on a thread so that it does not block.
+     *
+     * @throws Exception
+     */
+    @Before
+    public void setup() throws Exception {
+        InMemoryDefaultTestModule testModule = new InMemoryDefaultTestModule();
+        Properties properties = testModule.getProperties();
+        properties.setProperty(Configuration.AGENT_USE_SSL, "false");
+        properties.setProperty(Configuration.CLIENT_API_PORT_KEY, Integer.toString(serverPort));
+        properties.setProperty(Configuration.SRVR_ONE_WAY_SSL_PORT_KEY, Integer.toString(serverAgentPort));
+        String tmpDir = System.getProperty("java.io.tmpdir");
+        testModule.getProperties().setProperty(Configuration.SRVR_KSTR_DIR_KEY, tmpDir);
+        injector = Guice.createInjector(testModule);
+        server = injector.getInstance(LocalAmbariServer.class);
+        serverThread = new Thread(server);
+        serverThread.start();
+        waitForServer();
+    }
+
+    /**
+     * Waits for the local server until it is ready to accept requests.
+     *
+     * @throws Exception
+     */
+    private void waitForServer() throws Exception {
+        int count = 1;
+
+        while (!isServerUp()) {
+            serverThread.join(count * 10000);     // Give a few seconds for the ambari server to start up
+            //count += 1; // progressive back off
+            //count *= 2; // exponential back off
+        }
+    }
+
+    /**
+     * Attempt to query the server for the stack. If the server is up,
+     * we will get a response. If not, an exception will be thrown.
+     *
+     * @return - True if the local server is responsive to queries.
+     *           False, otherwise.
+     */
+    private boolean isServerUp() {
+        String apiPath = "/api/v1/stacks";
+
+        String apiUrl = String.format(SERVER_URL_FORMAT, serverPort) + apiPath;
+        HttpClient httpClient = new HttpClient();
+        GetMethod getMethod = new GetMethod(apiUrl);
+
+        try {
+            int statusCode = httpClient.executeMethod(getMethod);
+            String response = getMethod.getResponseBodyAsString();
+
+            return true;
+        } catch (IOException ex) {
+
+        } finally {
+            getMethod.releaseConnection();
+        }
+
+        return false;
+    }
+
+    /**
+     * Shut down the local server.
+     *
+     * @throws Exception
+     */
+    @After
+    public void teardown() throws Exception {
+        if (serverThread != null) {
+            serverThread.interrupt();
+        }
+        if (server != null) {
+            server.stopServer();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/StartStopServerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/StartStopServerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/StartStopServerTest.java
index c49a01e..55806f4 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/StartStopServerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/server/StartStopServerTest.java
@@ -18,15 +18,9 @@
 
 package org.apache.ambari.server.functionaltests.server;
 
-import org.apache.ambari.server.configuration.Configuration;
-import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
-import org.junit.After;
-import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
 
-import java.util.Properties;
-
 import static org.junit.Assert.assertTrue;
 
 import org.apache.commons.httpclient.HttpClient;
@@ -40,7 +34,6 @@ import com.google.gson.JsonObject;
 import com.google.gson.JsonArray;
 
 import java.io.IOException;
-import java.text.MessageFormat;
 
 import org.apache.http.HttpStatus;
 
@@ -49,63 +42,7 @@ import org.apache.http.HttpStatus;
  * tests it's status and shuts down the server.
  */
 @Ignore
-public class StartStopServerTest {
-  /**
-   * Run the ambari server on a thread.
-   */
-  private Thread serverThread = null;
-
-  /**
-   * Instance of the local ambari server, which wraps the actual
-   * ambari server with test configuration.
-   */
-  private LocalAmbariServer server = null;
-
-  /**
-   * Server port
-   */
-  private static int serverPort = 9995;
-
-  /**
-   * Server URL
-   */
-  private static String SERVER_URL_FORMAT = "http://localhost:%d";
-
-  /**
-   * Test URL for GETting the status of the ambari server
-   */
-  private static String stacksPath = "/api/v1/stacks";
-
-  /**
-   * Start our local server on a thread so that it does not block.
-   * @throws Exception
-   */
-  @Before
-  public void setup() throws Exception {
-    InMemoryDefaultTestModule testModule = new InMemoryDefaultTestModule();
-    Properties properties = testModule.getProperties();
-    properties.setProperty(Configuration.AGENT_USE_SSL, "false");
-    properties.setProperty(Configuration.CLIENT_API_PORT_KEY, Integer.toString(serverPort));
-    server = new LocalAmbariServer(testModule);
-    serverThread = new Thread(server);
-    serverThread.start();
-    serverThread.join(20000);     // Give a few seconds for the ambari server to start up
-  }
-
-  /**
-   * Shut down our local server.
-   * @throws Exception
-   */
-  @After
-  public void teardown() throws Exception {
-    if (serverThread != null) {
-      serverThread.interrupt();
-    }
-    if (server != null) {
-      server.stopServer();
-    }
-  }
-
+public class StartStopServerTest extends ServerTestBase {
   /**
    * Waits for the ambari server to startup and then checks it's
    * status by querying /api/v1/stacks (does not touch the DB)
@@ -129,6 +66,10 @@ public class StartStopServerTest {
      * }
      */
 
+    /**
+     * Test URL for GETting the status of the ambari server
+     */
+    String stacksPath = "/api/v1/stacks";
     String stacksUrl = String.format(SERVER_URL_FORMAT, serverPort) + stacksPath;
     HttpClient httpClient = new HttpClient();
     GetMethod getMethod = new GetMethod(stacksUrl);

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/utils/ClusterUtils.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/utils/ClusterUtils.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/utils/ClusterUtils.java
new file mode 100644
index 0000000..8361bf1
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/utils/ClusterUtils.java
@@ -0,0 +1,247 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.utils;
+
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import org.apache.ambari.server.actionmanager.HostRoleStatus;
+import org.apache.ambari.server.functionaltests.api.ClusterConfigParams;
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.functionaltests.api.WebRequest;
+import org.apache.ambari.server.functionaltests.api.WebResponse;
+import org.apache.ambari.server.functionaltests.api.cluster.*;
+import org.apache.ambari.server.functionaltests.api.host.AddHostWebRequest;
+import org.apache.ambari.server.functionaltests.api.host.RegisterHostWebRequest;
+import org.apache.ambari.server.functionaltests.api.service.AddServiceWebRequest;
+import org.apache.ambari.server.functionaltests.api.service.InstallServiceWebRequest;
+import org.apache.ambari.server.functionaltests.api.service.StartServiceWebRequest;
+import org.apache.ambari.server.functionaltests.api.servicecomponent.AddServiceComponentWebRequest;
+import org.apache.ambari.server.functionaltests.api.servicecomponenthost.BulkAddServiceComponentHostsWebRequest;
+import org.apache.ambari.server.functionaltests.api.servicecomponenthost.BulkSetServiceComponentHostStateWebRequest;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.Host;
+import org.apache.ambari.server.state.State;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ClusterUtils {
+
+    @Inject
+    private Injector injector;
+
+    public void createSampleCluster(ConnectionParams serverParams) throws Exception {
+        WebResponse response = null;
+        JsonElement jsonResponse;
+        String clusterName = "c1";
+        String hostName = "host1";
+        String clusterVersion = "HDP-2.2.0";
+
+        /**
+         * Register a host
+         */
+        if (injector == null) {
+            jsonResponse =  RestApiUtils.executeRequest(new RegisterHostWebRequest(serverParams, hostName));
+        }
+        else {
+            /**
+             * Hack: Until we figure out how to get the agent servlet going,
+             * register a host directly using the Clusters class.
+             */
+            Clusters clusters = injector.getInstance(Clusters.class);
+            clusters.addHost(hostName);
+            Host host1 = clusters.getHost(hostName);
+            Map<String, String> hostAttributes = new HashMap<String, String>();
+            hostAttributes.put("os_family", "redhat");
+            hostAttributes.put("os_release_version", "6.3");
+            host1.setHostAttributes(hostAttributes);
+            host1.persist();
+        }
+
+        /**
+         * Create a cluster
+         */
+        jsonResponse = RestApiUtils.executeRequest(new CreateClusterWebRequest(serverParams, clusterName, clusterVersion));
+
+        /**
+         * Add the registered host to the new cluster
+         */
+        jsonResponse =  RestApiUtils.executeRequest(new AddHostWebRequest(serverParams, clusterName, hostName));
+
+        /**
+         * Create and add a configuration to our cluster
+         */
+
+        String configType = "test-hadoop-env";
+        String configTag = "version1";
+        ClusterConfigParams configParams = new ClusterConfigParams();
+        configParams.setClusterName(clusterName);
+        configParams.setConfigType(configType);
+        configParams.setConfigTag(configTag);
+        configParams.setProperties(new HashMap<String, String>() {{
+            put("fs.default.name", "localhost:9995");
+        }});
+
+        jsonResponse = RestApiUtils.executeRequest(new CreateConfigurationWebRequest(serverParams, configParams));
+
+        /**
+         * Apply the desired configuration to our cluster
+         */
+        jsonResponse = RestApiUtils.executeRequest(new AddDesiredConfigurationWebRequest(serverParams, configParams));
+
+        /**
+         * Add a service to the cluster
+         */
+
+        String serviceName = "HDFS";
+        jsonResponse = RestApiUtils.executeRequest(new AddServiceWebRequest(serverParams, clusterName, serviceName));
+
+        String [] componentNames = new String [] {"NAMENODE", "DATANODE", "SECONDARY_NAMENODE"};
+
+        /**
+         * Add components to the service
+         */
+        for (String componentName : componentNames) {
+            jsonResponse = RestApiUtils.executeRequest(new AddServiceComponentWebRequest(serverParams, clusterName,
+                    serviceName, componentName));
+        }
+
+        /**
+         * Install the service
+         */
+        jsonResponse = RestApiUtils.executeRequest(new InstallServiceWebRequest(serverParams, clusterName, serviceName));
+
+        /**
+         * Add components to the host
+         */
+
+        jsonResponse = RestApiUtils.executeRequest(new BulkAddServiceComponentHostsWebRequest(serverParams, clusterName,
+                Arrays.asList(hostName), Arrays.asList(componentNames)));
+
+        /**
+         * Install the service component hosts
+         */
+        jsonResponse = RestApiUtils.executeRequest(new BulkSetServiceComponentHostStateWebRequest(serverParams,
+                    clusterName, State.INIT, State.INSTALLED));
+        int requestId = parseRequestId(jsonResponse);
+        RequestStatusPoller.poll(serverParams, clusterName, requestId);
+
+        /**
+         * Start the service component hosts
+         */
+
+        jsonResponse = RestApiUtils.executeRequest(new BulkSetServiceComponentHostStateWebRequest(serverParams,
+                clusterName, State.INSTALLED, State.STARTED));
+        requestId = parseRequestId(jsonResponse);
+        RequestStatusPoller.poll(serverParams, clusterName, requestId);
+
+        /**
+         * Start the service
+         */
+        //jsonResponse = RestApiUtils.executeRequest(new StartServiceWebRequest(serverParams, clusterName, serviceName));
+    }
+
+    /**
+     * Parses a JSON response string for  { "Requests" : { "id" : "2" } }
+     *
+     * @param jsonResponse
+     * @return - request id
+     * @throws IllegalArgumentException
+     */
+    private static int parseRequestId(JsonElement jsonResponse) throws IllegalArgumentException {
+        if (jsonResponse.isJsonNull()) {
+            throw new IllegalArgumentException("jsonResponse with request id expected.");
+        }
+
+        JsonObject jsonObject = jsonResponse.getAsJsonObject();
+        int requestId = jsonObject.get("Requests").getAsJsonObject().get("id").getAsInt();
+        return requestId;
+    }
+}
+
+/**
+ * Polls the status of a service component host request.
+ */
+class RequestStatusPoller implements Runnable {
+    private HostRoleStatus hostRoleStatus;
+    private ConnectionParams serverParams;
+    private String clusterName;
+    private int requestId;
+
+    public RequestStatusPoller(ConnectionParams serverParams, String clusterName, int requestId) {
+        this.hostRoleStatus = HostRoleStatus.IN_PROGRESS;
+        this.serverParams = serverParams;
+        this.clusterName = clusterName;
+        this.requestId = requestId;
+    }
+
+    public HostRoleStatus getHostRoleStatus() {
+        return this.hostRoleStatus;
+    }
+
+    public static boolean poll(ConnectionParams serverParams, String clusterName, int requestId) throws Exception {
+        RequestStatusPoller poller = new RequestStatusPoller(serverParams, clusterName, requestId);
+        Thread pollerThread = new Thread(poller);
+        pollerThread.start();
+        pollerThread.join();
+        if (poller.getHostRoleStatus() == HostRoleStatus.COMPLETED)
+            return true;
+
+        return false;
+    }
+
+    @Override
+    public void run() {
+        int retryCount = 5;
+        while (true) {
+            JsonElement jsonResponse;
+
+            try {
+                WebRequest webRequest = new GetRequestStatusWebRequest(serverParams, clusterName, requestId);
+                jsonResponse = RestApiUtils.executeRequest(webRequest);
+            } catch (Exception ex) {
+                throw new RuntimeException(ex);
+            }
+            if (!jsonResponse.isJsonNull()) {
+                JsonObject jsonObj = jsonResponse.getAsJsonObject();
+                JsonObject jsonRequestsObj = jsonObj.getAsJsonObject("Requests");
+                String requestStatus = jsonRequestsObj.get("request_status").getAsString();
+                hostRoleStatus = HostRoleStatus.valueOf(requestStatus);
+
+                if (hostRoleStatus == HostRoleStatus.COMPLETED ||
+                        hostRoleStatus == HostRoleStatus.ABORTED ||
+                        hostRoleStatus == HostRoleStatus.TIMEDOUT ||
+                        retryCount == 0)
+                    break;
+            }
+
+            try {
+                Thread.sleep(5000);
+            } catch (InterruptedException ex) {
+                break;
+            }
+
+            retryCount--;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/utils/RestApiUtils.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/utils/RestApiUtils.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/utils/RestApiUtils.java
new file mode 100644
index 0000000..1cb0f31
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/utils/RestApiUtils.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.utils;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+import com.google.gson.stream.JsonReader;
+import org.apache.ambari.server.functionaltests.api.WebRequest;
+import org.apache.ambari.server.functionaltests.api.WebResponse;
+import org.apache.commons.httpclient.HttpStatus;
+
+import java.io.StringReader;
+
+/**
+ * Helper that executes a web request object and evaluates the response code.
+ */
+public class RestApiUtils {
+    /**
+     * Executes a web request and throws an exception if the status code is incorrect.
+     *
+     * @param request
+     * @return
+     * @throws Exception
+     */
+    public  static JsonElement executeRequest(WebRequest request) throws Exception {
+        WebResponse response = request.getResponse();
+        int responseCode = response.getStatusCode();
+        String responseBody = response.getContent();
+
+        if (responseCode != HttpStatus.SC_OK && responseCode != HttpStatus.SC_CREATED && responseCode != HttpStatus.SC_ACCEPTED) {
+            throw new RuntimeException(String.format("%d:%s", responseCode, responseBody));
+        }
+
+        return new JsonParser().parse(new JsonReader(new StringReader(responseBody)));
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/resources/stacks/HDP/2.1.1/role_command_order.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/resources/stacks/HDP/2.1.1/role_command_order.json b/ambari-server/src/test/resources/stacks/HDP/2.1.1/role_command_order.json
index 656bb63..faaee6e 100644
--- a/ambari-server/src/test/resources/stacks/HDP/2.1.1/role_command_order.json
+++ b/ambari-server/src/test/resources/stacks/HDP/2.1.1/role_command_order.json
@@ -3,7 +3,7 @@
   "_comment" : "blockedRole-blockedCommand: [blockerRole1-blockerCommand1, blockerRole2-blockerCommand2, ...]",
   "general_deps" : {
     "_comment" : "dependencies for all cases",
-    "HBASE_MASTER-START": ["ZOOKEEPER_SERVER-START, ZOOKEEPER_SERVER-START"],
+    "HBASE_MASTER-START": ["ZOOKEEPER_SERVER-START"],
     "OOZIE_SERVER-START": ["JOBTRACKER-START", "TASKTRACKER-START"],
     "WEBHCAT_SERVER-START": ["TASKTRACKER-START", "HIVE_SERVER-START"],
     "HIVE_METASTORE-START": ["MYSQL_SERVER-START"],

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/resources/stacks/HDP/2.2.0/role_command_order.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/resources/stacks/HDP/2.2.0/role_command_order.json b/ambari-server/src/test/resources/stacks/HDP/2.2.0/role_command_order.json
index 656bb63..faaee6e 100644
--- a/ambari-server/src/test/resources/stacks/HDP/2.2.0/role_command_order.json
+++ b/ambari-server/src/test/resources/stacks/HDP/2.2.0/role_command_order.json
@@ -3,7 +3,7 @@
   "_comment" : "blockedRole-blockedCommand: [blockerRole1-blockerCommand1, blockerRole2-blockerCommand2, ...]",
   "general_deps" : {
     "_comment" : "dependencies for all cases",
-    "HBASE_MASTER-START": ["ZOOKEEPER_SERVER-START, ZOOKEEPER_SERVER-START"],
+    "HBASE_MASTER-START": ["ZOOKEEPER_SERVER-START"],
     "OOZIE_SERVER-START": ["JOBTRACKER-START", "TASKTRACKER-START"],
     "WEBHCAT_SERVER-START": ["TASKTRACKER-START", "HIVE_SERVER-START"],
     "HIVE_METASTORE-START": ["MYSQL_SERVER-START"],


[2/2] ambari git commit: AMBARI-13956. Add functional test infrastructure commands to perform API calls (Nahappan Somasundaram)

Posted by sm...@apache.org.
AMBARI-13956. Add functional test infrastructure commands to perform API calls (Nahappan Somasundaram)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/b5e8a3bf
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/b5e8a3bf
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/b5e8a3bf

Branch: refs/heads/trunk
Commit: b5e8a3bf825413ad8d03a14416ae7813c3123dea
Parents: aa46568
Author: Sumit Mohanty <sm...@hortonworks.com>
Authored: Tue Nov 24 15:37:16 2015 -0800
Committer: Sumit Mohanty <sm...@hortonworks.com>
Committed: Tue Nov 24 15:37:16 2015 -0800

----------------------------------------------------------------------
 .../api/AmbariHttpWebRequest.java               | 393 +++++++++++++++++++
 .../api/ClusterConfigParams.java                |  84 ++++
 .../functionaltests/api/ConnectionParams.java   |  89 +++++
 .../server/functionaltests/api/WebRequest.java  | 192 +++++++++
 .../server/functionaltests/api/WebResponse.java |  57 +++
 .../AddDesiredConfigurationWebRequest.java      | 108 +++++
 .../api/cluster/CreateClusterWebRequest.java    |  88 +++++
 .../cluster/CreateConfigurationWebRequest.java  |  87 ++++
 .../api/cluster/GetAllClustersWebRequest.java   |  53 +++
 .../api/cluster/GetClusterWebRequest.java       |  49 +++
 .../api/cluster/GetRequestStatusWebRequest.java |  78 ++++
 .../api/host/AddHostWebRequest.java             |  63 +++
 .../api/host/GetHostWebRequest.java             |  56 +++
 .../api/host/GetRegisteredHostWebRequest.java   |  59 +++
 .../api/host/RegisterHostWebRequest.java        |  59 +++
 .../api/service/AddServiceWebRequest.java       |  98 +++++
 .../api/service/DeleteServiceWebRequest.java    |  67 ++++
 .../api/service/GetServiceWebRequest.java       |  67 ++++
 .../api/service/InstallServiceWebRequest.java   |  39 ++
 .../api/service/SetServiceStateWebRequest.java  |  97 +++++
 .../api/service/StartServiceWebRequest.java     |  38 ++
 .../api/service/StopServiceWebRequest.java      |  38 ++
 .../AddServiceComponentWebRequest.java          |  69 ++++
 .../GetServiceComponentWebRequest.java          |  69 ++++
 .../SetServiceComponentStateWebRequest.java     |  87 ++++
 .../AddServiceComponentHostWebRequest.java      |  69 ++++
 .../BulkAddServiceComponentHostsWebRequest.java | 127 ++++++
 ...kSetServiceComponentHostStateWebRequest.java |  91 +++++
 .../GetServiceComponentHostWebRequest.java      |  69 ++++
 .../SetServiceComponentHostStateWebRequest.java |  89 +++++
 .../server/DeleteServiceTest.java               | 197 ++++++++++
 .../server/LocalAmbariServer.java               |  31 +-
 .../functionaltests/server/ServerTestBase.java  | 146 +++++++
 .../server/StartStopServerTest.java             |  69 +---
 .../functionaltests/utils/ClusterUtils.java     | 247 ++++++++++++
 .../functionaltests/utils/RestApiUtils.java     |  52 +++
 .../stacks/HDP/2.1.1/role_command_order.json    |   2 +-
 .../stacks/HDP/2.2.0/role_command_order.json    |   2 +-
 38 files changed, 3283 insertions(+), 92 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/AmbariHttpWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/AmbariHttpWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/AmbariHttpWebRequest.java
new file mode 100644
index 0000000..d8075b2
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/AmbariHttpWebRequest.java
@@ -0,0 +1,393 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.stream.JsonReader;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.HttpMethodBase;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.DeleteMethod;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.PutMethod;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+import org.apache.commons.codec.binary.Base64;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Map;
+
+
+/**
+ * REST API Client that performs various operations on the Ambari Server
+ * using Http.
+ */
+public class AmbariHttpWebRequest extends WebRequest {
+    private static final Log LOG = LogFactory.getLog(AmbariHttpWebRequest.class);
+    private static String SERVER_URL_FORMAT = "http://%s:%d";
+    private static String SERVER_SSL_URL_FORMAT = "https://%s:%d";
+
+    private String content;
+
+    private String serverName;
+    private int serverApiPort;
+    private int serverAgentPort;
+    private WebResponse response;
+    private String curlApi;
+
+    /**
+     *  Constructor to set the REST API URL, Server API port, Server Agent API port, user id and password.
+     *
+     * @param params
+     */
+    public AmbariHttpWebRequest(ConnectionParams params) {
+        setServerName(params.getServerName());
+        setServerApiPort(params.getServerApiPort());
+        setServerAgentPort(params.getServerAgentPort());
+        setUserName(params.getUserName());
+        setPassword(params.getPassword());
+        addHeader("X-Requested-By", "ambari");
+        if (getUserName() != null) {
+            addHeader("Authorization", getBasicAuthentication());
+        }
+    }
+
+    /**
+     * Sends the request to the Ambari server and returns the response.
+     *
+     * @return - Response from the Ambari server.
+     * @throws IOException
+     */
+    @Override
+    public WebResponse getResponse() throws IOException {
+        if (response == null) {
+            LOG.info(getCurlApi());
+            response = executeRequest();
+        }
+
+        return response;
+    }
+
+    /**
+     * Gets the full URI
+     *
+     * @return - Full path to the URI
+     */
+    @Override
+    public String getUrl() {
+        return getServerApiUrl() + getApiPath();
+    }
+
+    /**
+     * Gets the JSON content (request data).
+     *
+     * @return - JSON content.
+     */
+    @Override
+    public String getContent() {
+        if (content == null) {
+            content = getRequestData();
+        }
+
+        return content;
+    }
+
+    /**
+     * Gets the content encoding.
+     *
+     * @return - Content encoding.
+     */
+    @Override
+    public String getContentEncoding() { return "UTF-8"; }
+
+    /**
+     * Gets the content type, like application/json, application/text, etc.
+     *
+     * @return - Content type.
+     */
+    @Override
+    public String getContentType() { return "application/json"; }
+
+    /**
+     * Gets the curl command line call for this request. Useful for
+     * debugging.
+     *
+     * @return - Curl command line call.
+     */
+    public String getCurlApi() {
+        if (curlApi == null) {
+            StringBuilder sb = new StringBuilder();
+            sb.append("curl");
+            if (getUserName() != null) {
+                sb.append(String.format(" -u %s", getUserName()));
+                if (getPassword() != null) {
+                    sb.append(String.format(":%s", getPassword()));
+                }
+            }
+            sb.append(String.format(" -H \"%s\"", "X-Requested-By: ambari"));
+            sb.append(String.format(" -X %s", getHttpMethod()));
+            if (getHttpMethod().equals("PUT") || getHttpMethod().equals("POST")) {
+                if (getContent() != null) {
+                    sb.append(String.format(" -d '%s'", getContent()));
+                }
+            }
+            sb.append(String.format(" %s", getUrl()));
+            curlApi = sb.toString();
+        }
+
+        return curlApi;
+    }
+
+    /**
+     * Sets the REST API URL for the Ambari Server
+     *
+     * @param serverName - REST API URL
+     */
+    public void setServerName(String serverName) { this.serverName = serverName; }
+
+    /**
+     * Gets the REST API URL for the Ambari Server
+     *
+     * @return - REST API URL
+     */
+    public String getServerName() { return this.serverName; }
+
+    /**
+     * Gets the port number for the REST API used by the web clients.
+     *
+     * @return - Server API port number.
+     */
+    public int getServerApiPort() { return this.serverApiPort; }
+
+    /**
+     * Sets the port number for the REST API used by the web clients.
+     *
+     * @param serverApiPort - Server API port.
+     */
+    public void setServerApiPort(int serverApiPort) { this.serverApiPort = serverApiPort; }
+
+    /**
+     * Gets the port number for the REST API used by the agent.
+     *
+     * @return - Agent API port number.
+     */
+    public int getServerAgentPort() { return this.serverAgentPort; }
+
+    /**
+     * Sets the port number for the REST API used by the agent.
+     *
+     * @param serverAgentPort - Agent API port number.
+     */
+    public void setServerAgentPort(int serverAgentPort) { this.serverAgentPort = serverAgentPort; }
+
+    /**
+     * Gets the REST API path fragment.
+     *
+     * @return - REST API path.
+     */
+    protected String getApiPath() { return ""; }
+
+    /**
+     * Gets the request data used in POST and PUT requests.
+     *
+     * @return - Request data.
+     */
+    protected String getRequestData() { return ""; }
+
+    /**
+     * Gets the basic authentication string to be used for the Authorization header.
+     *
+     * @return - Base-64 encoded authentication string.
+     */
+    protected String getBasicAuthentication() {
+        String authString = getUserName() + ":" + getPassword();
+        byte[] authEncBytes = Base64.encodeBase64(authString.getBytes());
+        String authStringEnc = new String(authEncBytes);
+
+        return "Basic " + authStringEnc;
+    }
+
+    /**
+     * Gets URL for the Ambari Server (without the API path)
+     *
+     * @return - Ambari server URL.
+     */
+    protected String getServerApiUrl() {
+        return String.format(SERVER_URL_FORMAT, getServerName(), getServerApiPort());
+    }
+
+    /**
+     * Gets URL for the Agent Server (without the API path)
+     *
+     * @return - Agent server URL.
+     */
+    protected String getServerAgentUrl() {
+        return String.format(SERVER_URL_FORMAT, getServerName(), getServerAgentPort());
+    }
+
+    /**
+     * Helper method to create simple Json objects.
+     *
+     * @param name - Name
+     * @param value - Value
+     * @return - A JsonObject {name: value}
+     */
+    protected static JsonObject createJsonObject(String name, String value) {
+        JsonObject jsonObject = new JsonObject();
+        jsonObject.addProperty(name, value);
+        return jsonObject;
+    }
+
+    /**
+     * Helper method to create simple Json objects.
+     *
+     * @param name - Name
+     * @param jsonElement - Json object.
+     * @return - A JsonObject {name: jsonElement }
+     */
+    protected static JsonObject createJsonObject(String name, JsonElement jsonElement) {
+        JsonObject jsonObject = new JsonObject();
+        jsonObject.add(name, jsonElement);
+        return jsonObject;
+    }
+
+    /**
+     * Executes the current request by using HttpClient methods and returns the response.
+     *
+     * @return - Response from the Ambari server/Agent server.
+     * @throws IOException
+     */
+    private WebResponse executeRequest() throws IOException {
+        HttpMethodBase methodBase = null;
+        String httpMethod;
+
+        httpMethod = getHttpMethod();
+
+        if (httpMethod.equals("GET")) {
+            methodBase = getGetMethod();
+        } else if (httpMethod.equals("POST")) {
+            methodBase = getPostMethod();
+        } else if (httpMethod.equals("PUT")) {
+            methodBase = getPutMethod();
+        } else if (httpMethod.equals("DELETE")) {
+            methodBase = getDeleteMethod();
+        } else {
+            new RuntimeException(String.format("Unsupported HTTP method: %s", httpMethod));
+        }
+
+        WebResponse response = new WebResponse();
+        HttpClient httpClient = new HttpClient();
+        Map<String, String> headers = getHeaders();
+
+        for (Map.Entry<String, String> header : headers.entrySet()) {
+            methodBase.addRequestHeader(header.getKey(), header.getValue());
+        }
+
+        methodBase.setQueryString(getQueryString());
+
+        try {
+            int statusCode = httpClient.executeMethod(methodBase);
+            response.setStatusCode(statusCode);
+            response.setContent(methodBase.getResponseBodyAsString());
+        } finally {
+            methodBase.releaseConnection();
+        }
+
+        return response;
+    }
+
+    /**
+     * Constructs a GetMethod instance.
+     *
+     * @return - GetMethod.
+     */
+    private GetMethod getGetMethod() {
+        return new GetMethod(getUrl());
+    }
+
+    /**
+     * Constructs a PutMethod instance and sets the request data on it.
+     *
+     * @return - PutMethod.
+     */
+    @SuppressWarnings("deprecation")
+    private PutMethod getPutMethod() {
+        PutMethod putMethod = new PutMethod(getUrl());
+
+        putMethod.setRequestBody(getContent());
+
+        return putMethod;
+    }
+
+    /**
+     * Constructs a PostMethod and sets the request data on it.
+     *
+     * @return - PostMethod.
+     */
+    @SuppressWarnings("deprecation")
+    private PostMethod getPostMethod() {
+        PostMethod postMethod = new PostMethod(getUrl());
+
+        /*
+        RequestEntity requestEntity = new StringRequestEntity(
+                request.getContent(),
+                request.getContentType(),
+                request.getContentEncoding());
+
+        postMethod.setRequestEntity(requestEntity);
+        */
+
+        postMethod.setRequestBody(getContent());
+
+        return postMethod;
+    }
+
+    /**
+     * Constructs a DeleteMethod.
+     *
+     * @return - DeleteMethod.
+     */
+    private DeleteMethod getDeleteMethod() {
+        return new DeleteMethod(getUrl());
+    }
+
+    @SuppressWarnings("deprecation")
+    private RuntimeException createRuntimeException(HttpException httpException) {
+        String message = httpException.getMessage();
+        try {
+            JsonElement jsonElement = new JsonParser().parse(new JsonReader(new StringReader(httpException.getMessage())));
+            if (jsonElement != null && jsonElement.getAsJsonObject().has("message")) {
+                message = jsonElement.getAsJsonObject().get("message").getAsString();
+            }
+        } catch (Throwable t) {
+        }
+        if (httpException.getReasonCode() != HttpStatus.SC_OK) {
+            message = httpException.getReasonCode() + " " + httpException.getReason() + ": " + message;
+        }
+        return new RuntimeException(message, httpException);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/ClusterConfigParams.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/ClusterConfigParams.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/ClusterConfigParams.java
new file mode 100644
index 0000000..7efe3f5
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/ClusterConfigParams.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api;
+
+import java.util.Map;
+
+/**
+ * Configurations in Ambari are distinguished using type and tag.
+ * Once a configuration is created, it can be applied to a service,
+ * specifying the type and tag for the configuration.
+ *
+ * Example:
+ * curl -i -X POST -d '{"type": "core-site", "tag": "version1363902625", "properties" : { "fs.default.name" : "localhost:8020"}}'
+ * http://<cluster-name>:8080/api/v1/clusters/c1/configurations
+ */
+public class ClusterConfigParams {
+    /**
+     * Name of the cluster
+     */
+    private String clusterName;
+
+    /**
+     * Configuration tag
+     */
+    private String configTag;
+
+    /**
+     * Configuration type
+     */
+    private String configType;
+
+    /**
+     * Configuration properties
+     */
+    private Map<String, String> properties;
+
+    public Map<String, String> getProperties() {
+        return properties;
+    }
+
+    public void setProperties(Map<String, String> properties) {
+        this.properties = properties;
+    }
+
+    public String getConfigType() {
+        return configType;
+    }
+
+    public void setConfigType(String configType) {
+        this.configType = configType;
+    }
+
+    public String getConfigTag() {
+        return configTag;
+    }
+
+    public void setConfigTag(String configTag) {
+        this.configTag = configTag;
+    }
+
+    public String getClusterName() {
+        return clusterName;
+    }
+
+    public void setClusterName(String clusterName) {
+        this.clusterName = clusterName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/ConnectionParams.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/ConnectionParams.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/ConnectionParams.java
new file mode 100644
index 0000000..3d0ef7c
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/ConnectionParams.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api;
+
+/**
+ * Ambari server connection parameters
+ */
+public class ConnectionParams {
+    /**
+     * Server name
+     */
+    private String serverName;
+
+    /**
+     * Server port
+     */
+    private int serverApiPort;
+
+    /**
+     * Agent server port
+     */
+    private int serverAgentPort;
+
+    /**
+     * User name
+     */
+    private String userName;
+
+    /**
+     * Password
+     */
+    private String password;
+
+    public String getServerName() {
+        return serverName;
+    }
+
+    public void setServerName(String serverName) {
+        this.serverName = serverName;
+    }
+
+    public int getServerApiPort() {
+        return serverApiPort;
+    }
+
+    public void setServerApiPort(int serverApiPort) {
+        this.serverApiPort = serverApiPort;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public int getServerAgentPort() {
+        return serverAgentPort;
+    }
+
+    public void setServerAgentPort(int serverAgentPort) {
+        this.serverAgentPort = serverAgentPort;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/WebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/WebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/WebRequest.java
new file mode 100644
index 0000000..46dc634
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/WebRequest.java
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * Makes a request to a URL.
+ */
+public class WebRequest {
+    private String httpMethod;
+    private String url;
+    private String queryString;
+    private String content;
+    private String contentType;
+    private String contentEncoding;
+    private String userName;
+    private String password;
+
+    private Map<String, String> headers = new HashMap<>();
+
+    public WebRequest() {}
+
+    public WebResponse getResponse() throws Exception {
+        return null;
+    }
+
+    /**
+     * Gets the HTTP Method (POST, GET, PUT, DELETE)
+     *
+     * @return - HTTP Method
+     */
+    public String getHttpMethod() { return this.httpMethod; }
+
+    /**
+     * Sets the HTTP Method to use.
+     *
+     * @param httpMethod
+     */
+    public void setHttpMethod(String httpMethod) { this.httpMethod = httpMethod; }
+
+    /**
+     * Gets the full URL to the request.
+     *
+     * @return
+     */
+    public String getUrl() { return this.url; }
+
+    /**
+     * Sets the full URL to the request.
+     *
+     * @param url
+     */
+    public void setUrl(String url) { this.url = url; }
+
+    /**
+     * Gets the query string (name1=value1?name2=value2)
+     *
+     * @return
+     */
+    public String getQueryString() { return this.queryString; }
+
+    /**
+     * Sets the query string
+     *
+     * @param queryString
+     */
+    public void setQueryString(String queryString) { this.queryString = queryString; }
+
+    /**
+     * Gets the request data.
+     *
+     * @return
+     */
+    public String getContent() { return this.content; }
+
+    /**
+     * Sets the request data.
+     *
+     * @param content
+     */
+    public void setContent(String content) { this.content = content; }
+
+    /**
+     * Gets the content type (application/json, application/text)
+     *
+     * @return
+     */
+    public String getContentType() { return this.contentType; }
+
+    /**
+     * Sets the content type.
+     *
+     * @param contentType
+     */
+    public void setContentType(String contentType) { this.contentType = contentType; }
+
+    /**
+     * Gets the content encoding (UTF-8)
+     *
+     * @return
+     */
+    public String getContentEncoding() { return this.contentEncoding; }
+
+    /**
+     * Sets the content encoding
+     *
+     * @param contentEncoding
+     */
+    public void setContentEncoding(String contentEncoding) { this.contentEncoding = contentEncoding; }
+
+    /**
+     * Gets the request headers.
+     *
+     * @return - A read-only collection of headers.
+     */
+    public Map<String, String> getHeaders() {
+        return Collections.unmodifiableMap(this.headers);
+    }
+
+    /**
+     * Clear the request headers.
+     */
+    public void clearHeaders() { this.headers.clear(); }
+
+    /**
+     * Add a collection of request headers.
+     *
+     * @param headers
+     */
+    public void addHeaders(Map<String, String> headers) {
+        for (Map.Entry<String, String> entry : headers.entrySet()) {
+            addHeader(entry.getKey(), entry.getValue());
+        }
+    }
+
+    /**
+     * Add a name-value pair to the request headers.
+     *
+     * @param name
+     * @param value
+     */
+    public void addHeader(String name, String value) {
+        this.headers.put(name, value);
+    }
+
+    /**
+     * Sets the user id for the REST API URL
+     *
+     * @param userName
+     */
+    public void setUserName(String userName) { this.userName = userName; }
+
+    /**
+     * Gets the user name
+     *
+     * @return - User name
+     */
+    public String getUserName() { return this.userName; }
+
+    /**
+     * Sets the password
+     *
+     * @param password - Password
+     */
+    public void setPassword(String password) { this.password = password; }
+
+    /**
+     * Gets the password
+     *
+     * @return - Password
+     */
+    public String getPassword() { return this.password; }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/WebResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/WebResponse.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/WebResponse.java
new file mode 100644
index 0000000..b3deae6
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/WebResponse.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api;
+
+/**
+ * Gets a response from a URL.
+ */
+public class WebResponse {
+    private String content;
+    private int statusCode;
+
+    public WebResponse() {}
+
+    /**
+     * Gets the response content.
+     *
+     * @return - Response content.
+     */
+    public String getContent() { return this.content; }
+
+    /**
+     * Sets the response content.
+     *
+     * @param content - Response content.
+     */
+    public void setContent(String content) { this.content = content; }
+
+    /**
+     * Gets the response status code.
+     *
+     * @return - Response status code.
+     */
+    public int getStatusCode() { return this.statusCode; }
+
+    /**
+     * Sets the response status code.
+     *
+     * @param statusCode - Response status code.
+     */
+    public void setStatusCode(int statusCode) { this.statusCode = statusCode;}
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/AddDesiredConfigurationWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/AddDesiredConfigurationWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/AddDesiredConfigurationWebRequest.java
new file mode 100644
index 0000000..7cb893a
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/AddDesiredConfigurationWebRequest.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.cluster;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+import org.apache.ambari.server.functionaltests.api.ClusterConfigParams;
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+
+/**
+ * Adds an existing configuration, identified by it's type and tag, to a cluster.
+ */
+public class AddDesiredConfigurationWebRequest extends AmbariHttpWebRequest {
+    private String clusterName;
+    private String configType;
+    private String configTag;
+    private static String pathFormat = "/api/v1/clusters/%s";
+
+    /**
+     *
+     * @param serverParams - Ambari server connection information
+     * @param configParams - Cluster configuration parameters
+     */
+    public AddDesiredConfigurationWebRequest(ConnectionParams serverParams, ClusterConfigParams configParams) {
+        super(serverParams);
+        this.clusterName = configParams.getClusterName();
+        this.configType = configParams.getConfigType();
+        this.configTag = configParams.getConfigTag();
+    }
+
+    /**
+     * Gets the cluster name.
+     *
+     * @return - Cluster name.
+     */
+    public String getClusterName() { return this.clusterName; }
+
+    /**
+     * Gets the configuration type.
+     *
+     * @return - Configuration type.
+     */
+    public String getConfigType() { return this.configType; }
+
+    /**
+     * Gets the configuration tag.
+     *
+     * @return - Configuration tag.
+     */
+    public String getConfigTag() { return this.configTag; }
+
+    /**
+     * Gets the REST API method.
+     *
+     * @return - PUT.
+     */
+    @Override
+    public String getHttpMethod() {
+        return "PUT";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName);
+    }
+
+    /**
+     * Gets the request data.
+     *
+     * @return - Request data.
+     */
+    @Override
+    protected String getRequestData() {
+        /**
+         * { "Clusters" : {"desired_configs": {"type": "test-site", "tag" : "version1" }}}
+         */
+        JsonObject jsonObject;
+        JsonObject jsonDesiredConfigs = new JsonObject();
+
+        jsonDesiredConfigs.addProperty("type", configType);
+        jsonDesiredConfigs.addProperty("tag", configTag);
+        jsonObject = createJsonObject("Clusters", createJsonObject("desired_configs", jsonDesiredConfigs));
+        Gson gson = new Gson();
+        return gson.toJson(jsonObject);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/CreateClusterWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/CreateClusterWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/CreateClusterWebRequest.java
new file mode 100644
index 0000000..6c8c31e
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/CreateClusterWebRequest.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.cluster;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+
+/**
+ * Creates a new cluster.
+ */
+public class CreateClusterWebRequest extends AmbariHttpWebRequest {
+    private String clusterName;
+    private String clusterVersion;
+    private static String pathFormat = "/api/v1/clusters/%s";
+
+    /**
+     * Creates a new cluster with the specified name and version.
+     *
+     * @param params - Ambari server connection information.
+     * @param clusterName - Cluster name, like "test-cluster"
+     * @param clusterVersion - Cluster version, like "HDP-2.2.0"
+     */
+    public CreateClusterWebRequest(ConnectionParams params, String clusterName, String clusterVersion) {
+        super(params);
+        this.clusterName = clusterName;
+        this.clusterVersion = clusterVersion;
+    }
+
+    /**
+     * Gets the cluster name.
+     *
+     * @return - Cluster name.
+     */
+    public String getClusterName() { return this.clusterName; }
+
+    /**
+     * Gets the cluster version.
+     *
+     * @return - Cluster version.
+     */
+    public String getClusterVersion() { return this.clusterVersion; }
+
+    @Override
+    public String getHttpMethod() {
+        return "POST";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName);
+    }
+
+    /**
+     * Gets the request data.
+     *
+     * @return - Request data.
+     */
+    @Override
+    protected String getRequestData() {
+        JsonObject jsonClustersObj = new JsonObject();
+        jsonClustersObj.add("Clusters", createJsonObject("version", getClusterVersion()));
+        Gson gson = new Gson();
+        return gson.toJson(jsonClustersObj);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/CreateConfigurationWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/CreateConfigurationWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/CreateConfigurationWebRequest.java
new file mode 100644
index 0000000..8e6f972
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/CreateConfigurationWebRequest.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.cluster;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+import org.apache.ambari.server.functionaltests.api.ClusterConfigParams;
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class CreateConfigurationWebRequest extends AmbariHttpWebRequest {
+    private String clusterName;
+    private String configType;
+    private String configTag;
+    private Map<String, String> properties;
+    private static String pathFormat = "/api/v1/clusters/%s/configurations";
+
+    public CreateConfigurationWebRequest(ConnectionParams serverParams, ClusterConfigParams configParams) {
+        super(serverParams);
+        this.clusterName = configParams.getClusterName();
+        this.configType = configParams.getConfigType();
+        this.configTag = configParams.getConfigTag();
+        this.properties = new HashMap<>(configParams.getProperties());
+    }
+
+    public String getClusterName() { return this.clusterName; }
+
+    public String getConfigType() { return this.configType; }
+
+    public String getConfigTag() { return this.configTag; }
+
+    @Override
+    public String getHttpMethod() {
+        return "POST";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName);
+    }
+
+    /**
+     * Gets the request data.
+     *
+     * @return - Request data.
+     */
+    @Override
+    protected String getRequestData() {
+        /**
+         *  {"type": "core-site", "tag": "version1363902625", "properties" : { "fs.default.name" : "localhost:8020"}}
+         */
+        JsonObject jsonPropertiesObj = new JsonObject();
+        for (Map.Entry<String, String> property : properties.entrySet()) {
+            jsonPropertiesObj.addProperty(property.getKey(), property.getValue());
+        }
+        JsonObject jsonObject = new JsonObject();
+        jsonObject.addProperty("type", configType);
+        jsonObject.addProperty("tag", configTag);
+        jsonObject.add("properties", jsonPropertiesObj);
+        Gson gson = new Gson();
+        return gson.toJson(jsonObject);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/GetAllClustersWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/GetAllClustersWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/GetAllClustersWebRequest.java
new file mode 100644
index 0000000..3a0aaf5
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/GetAllClustersWebRequest.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.cluster;
+
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+
+/**
+ * Gets all the clusters.
+ */
+public class GetAllClustersWebRequest extends AmbariHttpWebRequest {
+    private static String pathFormat = "/api/v1/clusters";
+
+    public GetAllClustersWebRequest(ConnectionParams params) {
+        super(params);
+    }
+
+    /**
+     * Gets the REST API method.
+     *
+     * @return - GET.
+     */
+    @Override
+    public String getHttpMethod() {
+        return "GET";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return pathFormat;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/GetClusterWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/GetClusterWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/GetClusterWebRequest.java
new file mode 100644
index 0000000..39b933c
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/GetClusterWebRequest.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.cluster;
+
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+
+public class GetClusterWebRequest extends AmbariHttpWebRequest {
+    private String clusterName;
+    private static String pathFormat = "/api/v1/clusters/%s";
+
+    public GetClusterWebRequest(ConnectionParams params, String clusterName) {
+        super(params);
+        this.clusterName = clusterName;
+    }
+
+    public String getClusterName() { return this.clusterName; }
+
+    @Override
+    public String getHttpMethod() {
+        return "GET";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/GetRequestStatusWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/GetRequestStatusWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/GetRequestStatusWebRequest.java
new file mode 100644
index 0000000..7ac1898
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/cluster/GetRequestStatusWebRequest.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.cluster;
+
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+
+/**
+ * Gets the status of a request by request id. For example:
+ * curl --user admin:admin -i -X GET http://AMBARI_SERVER_HOST:8080/api/v1/clusters/CLUSTER_NAME/requests/9
+ * curl --user admin:admin -i -X GET http://AMBARI_SERVER_HOST:8080/api/v1/clusters/CLUSTER_NAME/requests/9/tasks/101
+ *
+ * Response:
+ * {
+ * "href" : "http://AMBARI_SERVER_HOST:8080/api/v1/clusters/CLUSTER_NAME/requests/9/tasks/101",
+ * "Tasks" : {
+ * ...
+ * "status" : "COMPLETED",
+ * ...
+ * }
+ * }
+ */
+public class GetRequestStatusWebRequest extends AmbariHttpWebRequest {
+    private String clusterName;
+    private int requestId;
+    private int taskId;
+    private static String pathFormat = "/api/v1/clusters/%s/requests/%d";
+    private static String pathFormatWithTask = "/api/v1/clusters/%s/requests/%d/tasks/%d";
+
+    public GetRequestStatusWebRequest(ConnectionParams params, String clusterName, int requestId) {
+        this(params, clusterName, requestId, -1);
+    }
+
+    public GetRequestStatusWebRequest(ConnectionParams params, String clusterName, int requestId, int taskId) {
+        super(params);
+        this.clusterName = clusterName;
+        this.requestId = requestId;
+        this.taskId = taskId;
+    }
+
+    public String getClusterName() { return this.clusterName; }
+
+    public int getRequestId() { return this.requestId; }
+
+    @Override
+    public String getHttpMethod() {
+        return "GET";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        if (taskId != -1)
+            return String.format(pathFormatWithTask, clusterName, requestId, taskId);
+
+        return String.format(pathFormat, clusterName, requestId);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/host/AddHostWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/host/AddHostWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/host/AddHostWebRequest.java
new file mode 100644
index 0000000..429e03c
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/host/AddHostWebRequest.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.host;
+
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+
+/**
+ * Adds a host to an existing cluster.
+ */
+public class AddHostWebRequest extends AmbariHttpWebRequest {
+    private String clusterName = null;
+    private String hostName = null;
+    private static String pathFormat = "/api/v1/clusters/%s/hosts/%s";
+
+    /**
+     * Adds the specified host to an existing cluster.
+     *
+     * @param params - Ambari connection information.
+     * @param clusterName - Existing cluster name.
+     * @param hostName - New host name. Host must have been registered previously using RegisterHostWebRequest.
+     */
+    public AddHostWebRequest(ConnectionParams params, String clusterName, String hostName) {
+        super(params);
+        this.clusterName = clusterName;
+        this.hostName = hostName;
+    }
+
+    public String getClusterName() { return this.clusterName; }
+
+    public String getHostName() { return this.hostName; }
+
+    @Override
+    public String getHttpMethod() {
+        return "POST";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName, hostName);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/host/GetHostWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/host/GetHostWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/host/GetHostWebRequest.java
new file mode 100644
index 0000000..6760640
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/host/GetHostWebRequest.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.host;
+
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+
+/**
+ * Gets the host identitied by the cluster name and host name.
+ */
+public class GetHostWebRequest extends AmbariHttpWebRequest {
+    private String clusterName = null;
+    private String hostName = null;
+    private static String pathFormat = "/api/v1/clusters/%s/hosts/%s";
+
+    public GetHostWebRequest(ConnectionParams params, String clusterName, String hostName) {
+        super(params);
+        this.clusterName = clusterName;
+        this.hostName = hostName;
+    }
+
+    public String getClusterName() { return this.clusterName; }
+
+    public String getHostName() { return this.hostName; }
+
+    @Override
+    public String getHttpMethod() {
+        return "GET";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName, hostName);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/host/GetRegisteredHostWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/host/GetRegisteredHostWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/host/GetRegisteredHostWebRequest.java
new file mode 100644
index 0000000..f4776d9
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/host/GetRegisteredHostWebRequest.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.host;
+
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+
+/**
+ * Gets a host that was previously registered with Ambari. Use this
+ * method to verify if a host was registered.
+ */
+public class GetRegisteredHostWebRequest extends AmbariHttpWebRequest {
+    private String hostName = null;
+    private static String pathFormat = "/api/v1/hosts/%s";
+
+    /**
+     * Gets the host information for a registered host.
+     *
+     * @param params - Ambari server connection information.
+     * @param hostName - Name of the registered host.
+     */
+    public GetRegisteredHostWebRequest(ConnectionParams params, String hostName) {
+        super(params);
+        this.hostName = hostName;
+    }
+
+    public String getHostName() { return this.hostName; }
+
+    @Override
+    public String getHttpMethod() {
+        return "GET";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, hostName);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/host/RegisterHostWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/host/RegisterHostWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/host/RegisterHostWebRequest.java
new file mode 100644
index 0000000..86ae9c5
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/host/RegisterHostWebRequest.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.host;
+
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+
+/**
+ * Registers a host with Ambari. A host must
+ * be registered before it can be added to a cluster.
+ */
+public class RegisterHostWebRequest extends AmbariHttpWebRequest {
+    private String hostName = null;
+    private static String pathFormat = "/agent/v1/register/%s";
+
+    /**
+     * Registers a new host with Ambari.
+     *
+     * @param params - Ambari server connection information.
+     * @param hostName - Host name to be newly registered.
+     */
+    public RegisterHostWebRequest(ConnectionParams params, String hostName) {
+        super(params);
+        this.hostName = hostName;
+    }
+
+    public String getHostName() { return this.hostName; }
+
+    @Override
+    public String getHttpMethod() {
+        return "POST";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, hostName);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/AddServiceWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/AddServiceWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/AddServiceWebRequest.java
new file mode 100644
index 0000000..d27afbc
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/AddServiceWebRequest.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.service;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+
+/**
+ * Adds a service to the specified cluster. The service name is sent in the request data.
+ */
+public class AddServiceWebRequest extends AmbariHttpWebRequest {
+    private String clusterName;
+    private String serviceName;
+    private static String pathFormat = "/api/v1/clusters/%s/services";
+
+    /**
+     * Add serviceName to the cluster clusterName
+     *
+     * @param params - Ambari server connection information
+     * @param clusterName - Existing name of a cluster.
+     * @param serviceName - Service name to be added.
+     */
+    public AddServiceWebRequest(ConnectionParams params, String clusterName, String serviceName) {
+        super(params);
+        this.clusterName = clusterName;
+        this.serviceName = serviceName;
+    }
+
+    /**
+     * Gets the cluster name.
+     * @return
+     */
+    public String getClusterName() { return this.clusterName; }
+
+    /**
+     * Gets the service name to be added.
+     *
+     * @return
+     */
+    public String getServiceName() { return this.serviceName; }
+
+    /**
+     * Gets the REST API method to use.
+     *
+     * @return - POST.
+     */
+    @Override
+    public String getHttpMethod() {
+        return "POST";
+    }
+
+    /**
+     * Gets the API fragment to be added to the server URL.
+     * @return
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName);
+    }
+
+    /**
+     * Constructs the request data.
+     *
+     * @return - Request data.
+     */
+    @Override
+    protected String getRequestData() {
+        /**
+         * {
+         *   "ServiceInfo" : {
+         *     "service_name" : serviceName
+         *   }
+         * }
+         */
+        JsonObject jsonServiceInfoObj;
+        jsonServiceInfoObj = createJsonObject("ServiceInfo", createJsonObject("service_name", serviceName));
+        Gson gson = new Gson();
+        return gson.toJson(jsonServiceInfoObj);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/DeleteServiceWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/DeleteServiceWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/DeleteServiceWebRequest.java
new file mode 100644
index 0000000..50d02ac
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/DeleteServiceWebRequest.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.service;
+
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+
+/**
+ * Deletes the specified service from the specified cluster.
+ */
+public class DeleteServiceWebRequest extends AmbariHttpWebRequest {
+    private String clusterName;
+    private String serviceName;
+    private static String pathFormat = "/api/v1/clusters/%s/services/%s";
+
+    /**
+     * Deletes a service from a cluster.
+     *
+     * @param params - Ambari server connection information
+     * @param clusterName - Cluster from where the service is to be deleted.
+     * @param serviceName - Service to be deleted.
+     */
+    public DeleteServiceWebRequest(ConnectionParams params, String clusterName, String serviceName) {
+        super(params);
+        this.clusterName = clusterName;
+        this.serviceName = serviceName;
+    }
+
+    public String getClusterName() {
+        return this.clusterName;
+    }
+
+    public String getHostName() {
+        return this.serviceName;
+    }
+
+    @Override
+    public String getHttpMethod() {
+        return "DELETE";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName, serviceName);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/GetServiceWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/GetServiceWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/GetServiceWebRequest.java
new file mode 100644
index 0000000..69f2fc5
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/GetServiceWebRequest.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.service;
+
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+
+/**
+ * Gets the specified service from the specified cluster.
+ */
+public class GetServiceWebRequest extends AmbariHttpWebRequest {
+    private String clusterName;
+    private String serviceName;
+    private static String pathFormat = "/api/v1/clusters/%s/services/%s";
+
+    /**
+     * Gets a service from a cluster.
+     *
+     * @param params - Ambari server connection information
+     * @param clusterName - Cluster from where the service is to be deleted.
+     * @param serviceName - Service to be deleted.
+     */
+    public GetServiceWebRequest(ConnectionParams params, String clusterName, String serviceName) {
+        super(params);
+        this.clusterName = clusterName;
+        this.serviceName = serviceName;
+    }
+
+    public String getClusterName() {
+        return this.clusterName;
+    }
+
+    public String getHostName() {
+        return this.serviceName;
+    }
+
+    @Override
+    public String getHttpMethod() {
+        return "GET";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName, serviceName);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/InstallServiceWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/InstallServiceWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/InstallServiceWebRequest.java
new file mode 100644
index 0000000..662b905
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/InstallServiceWebRequest.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.service;
+
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.state.State;
+
+/**
+ * Installs a service.
+ */
+public class InstallServiceWebRequest extends SetServiceStateWebRequest {
+
+    /**
+     * Updates the state of the specified service to INSTALLED.
+     *
+     * @param params - Ambari server connection information.
+     * @param clusterName - Existing cluster name.
+     * @param serviceName - Service to be installed.
+     */
+    public InstallServiceWebRequest(ConnectionParams params, String clusterName, String serviceName) {
+        super(params, clusterName, serviceName, State.INSTALLED, "Install service");
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/SetServiceStateWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/SetServiceStateWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/SetServiceStateWebRequest.java
new file mode 100644
index 0000000..5a5d3e6
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/SetServiceStateWebRequest.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.service;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+import org.apache.ambari.server.state.State;
+
+/**
+ * Updates the state of a service in a cluster.
+ */
+public class SetServiceStateWebRequest extends AmbariHttpWebRequest {
+    private String clusterName;
+    private String serviceName;
+    private State serviceState;
+    private String requestContext;
+    private static String pathFormat = "/api/v1/clusters/%s/services/%s";
+
+    /**
+     * Updates the state of the specified service in the specified cluster.
+     *
+     * @param params - Ambari connection information.
+     * @param clusterName - Existing cluster name.
+     * @param serviceName - Service name whose state is to be updated.
+     * @param serviceState - New service state.
+     * @param requestContext - Comments or remarks.
+     */
+    public SetServiceStateWebRequest(ConnectionParams params, String clusterName, String serviceName, State serviceState,
+                                     String requestContext) {
+        super(params);
+        this.clusterName = clusterName;
+        this.serviceName = serviceName;
+        this.serviceState = serviceState;
+        this.requestContext = requestContext;
+    }
+
+    public String getClusterName() { return this.clusterName; }
+
+    public String getHostName() { return this.serviceName; }
+
+    public State getServiceState() { return this.serviceState; }
+
+    public String getRequestContext() { return this.requestContext; }
+
+    @Override
+    public String getHttpMethod() {
+        return "PUT";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName, serviceName);
+    }
+
+    /**
+     * Constructs the request data.
+     *
+     * @return - Request data.
+     */
+    @Override
+    protected String getRequestData() {
+        /**
+         * {
+         * "RequestInfo" : {"context" : requestContext},
+         * "Body" : {"ServiceInfo" : {"state" : serviceState}}
+         * }
+         */
+        JsonObject jsonObject = new JsonObject();
+        jsonObject.add("RequestInfo", createJsonObject("context", requestContext));
+        jsonObject.add("Body", createJsonObject("ServiceInfo", createJsonObject("state", serviceState.toString())));
+        Gson gson = new Gson();
+        return gson.toJson(jsonObject);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/StartServiceWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/StartServiceWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/StartServiceWebRequest.java
new file mode 100644
index 0000000..26f5bc3
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/StartServiceWebRequest.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.service;
+
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.state.State;
+
+/**
+ * Starts a service by updating it's state to STARTED.
+ */
+public class StartServiceWebRequest extends SetServiceStateWebRequest {
+    /**
+     * Updates the state of the specified service to STARTED.
+     *
+     * @param params - Ambari server connection information.
+     * @param clusterName - Existing cluster name.
+     * @param serviceName - Service to be started.
+     */
+    public StartServiceWebRequest(ConnectionParams params, String clusterName, String serviceName) {
+        super(params, clusterName, serviceName, State.STARTED, "Start service");
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/StopServiceWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/StopServiceWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/StopServiceWebRequest.java
new file mode 100644
index 0000000..8c2d968
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/service/StopServiceWebRequest.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.service;
+
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.state.State;
+
+/**
+ * Stop a service by updating it's state to INSTALLED.
+ */
+public class StopServiceWebRequest extends SetServiceStateWebRequest {
+    /**
+     * Updates the state of the specified service to INSTALLED.
+     *
+     * @param params - Ambari server connection information.
+     * @param clusterName - Existing cluster name.
+     * @param serviceName - Service to be stopped.
+     */
+    public StopServiceWebRequest(ConnectionParams params, String clusterName, String serviceName) {
+        super(params, clusterName, serviceName, State.INSTALLED, "Stop service");
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponent/AddServiceComponentWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponent/AddServiceComponentWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponent/AddServiceComponentWebRequest.java
new file mode 100644
index 0000000..48a7b0d
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponent/AddServiceComponentWebRequest.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.servicecomponent;
+
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+
+/**
+ * Adds a component to a service.
+ */
+public class AddServiceComponentWebRequest extends AmbariHttpWebRequest {
+    private String clusterName;
+    private String serviceName;
+    private String componentName;
+    private static String pathFormat = "/api/v1/clusters/%s/services/%s/components/%s";
+
+    /**
+     * Adds the specified service component to the specified service.
+     *
+     * @param params - Ambari server connection information.
+     * @param clusterName - Existing cluster name.
+     * @param serviceName - Existing service name.
+     * @param componentName - Component to be added to a service.
+     */
+    public AddServiceComponentWebRequest(ConnectionParams params, String clusterName, String serviceName,
+                                         String componentName) {
+        super(params);
+        this.clusterName = clusterName;
+        this.serviceName = serviceName;
+        this.componentName = componentName;
+    }
+
+    public String getClusterName() { return this.clusterName; }
+
+    public String getServiceName() { return this.serviceName; }
+
+    public String getComponentName() { return this.componentName; }
+
+    @Override
+    public String getHttpMethod() {
+        return "POST";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName, serviceName, componentName);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5e8a3bf/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponent/GetServiceComponentWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponent/GetServiceComponentWebRequest.java b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponent/GetServiceComponentWebRequest.java
new file mode 100644
index 0000000..abd35c1
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/functionaltests/api/servicecomponent/GetServiceComponentWebRequest.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.functionaltests.api.servicecomponent;
+
+import org.apache.ambari.server.functionaltests.api.ConnectionParams;
+import org.apache.ambari.server.functionaltests.api.AmbariHttpWebRequest;
+
+/**
+ * Gets a component to a service.
+ */
+public class GetServiceComponentWebRequest extends AmbariHttpWebRequest {
+    private String clusterName;
+    private String serviceName;
+    private String componentName;
+    private static String pathFormat = "/api/v1/clusters/%s/services/%s/components/%s";
+
+    /**
+     * Gets the specified service component to the specified service.
+     *
+     * @param params - Ambari server connection information.
+     * @param clusterName - Existing cluster name.
+     * @param serviceName - Existing service name.
+     * @param componentName - Component to be added to a service.
+     */
+    public GetServiceComponentWebRequest(ConnectionParams params, String clusterName, String serviceName,
+                                         String componentName) {
+        super(params);
+        this.clusterName = clusterName;
+        this.serviceName = serviceName;
+        this.componentName = componentName;
+    }
+
+    public String getClusterName() { return this.clusterName; }
+
+    public String getServiceName() { return this.serviceName; }
+
+    public String getComponentName() { return this.componentName; }
+
+    @Override
+    public String getHttpMethod() {
+        return "GET";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName, serviceName, componentName);
+    }
+}