public Task<IHttpResponseMessageAbstraction> EnableDisableUserChangeRequest(string dnsName, string location, string payload)
        {
            lock (Clusters)
            {
                var converter = new ClusterProvisioningServerPayloadConverter();
                var request = converter.DeserializeChangeRequest<HttpUserChangeRequest>(payload);
                var passThroughResponse = new PassthroughResponse();
                var statusResponse = new UserChangeOperationStatusResponse();
                var pendingOp = new PendingOp(statusResponse);
                passThroughResponse.Data = pendingOp.Id;
                statusResponse.OperationType = request.Operation;
                statusResponse.UserType = UserType.Http;
                statusResponse.RequestIssueDate = DateTime.UtcNow;
                statusResponse.State = UserChangeOperationState.Pending;
                Microsoft.WindowsAzure.Management.HDInsight.Contracts.ErrorDetails error;

                var cluster = GetCloudServiceInternal(dnsName);
                // If the Cluster is not Found.
                if (cluster.IsNull())
                {
                    error = new Microsoft.WindowsAzure.Management.HDInsight.Contracts.ErrorDetails()
                    {
                        StatusCode = HttpStatusCode.NotFound,
                        ErrorId = "NOT FOUND",
                        ErrorMessage = "The requested cluster does not exist.",
                    };
                    passThroughResponse.Error = error;
                    passThroughResponse.Data = null;
                    return this.ReturnResponse(passThroughResponse);
                }
                if (!this.SupportedConnectivityClusterVersions.Contains(cluster.Cluster.Version))
                {
                    error = new Microsoft.WindowsAzure.Management.HDInsight.Contracts.ErrorDetails()
                    {
                        StatusCode = HttpStatusCode.BadRequest,
                        ErrorId = "UNSUPPORTED",
                        ErrorMessage =
                            string.Format(
                                CultureInfo.InvariantCulture,
                                "Cluster connectivity changes are not supported for this cluster version '{0}'.",
                                cluster.Cluster.Version)
                    };
                    passThroughResponse.Error = error;
                    passThroughResponse.Data = null;
                    return this.ReturnResponse(passThroughResponse);
                }
                // If the cluster has a pending operation (for the simulator pending operations always take <OperationTimeToCompletionInSeconds> seconds)
                if (cluster.HttpPendingOp.IsNotNull())
                {
                    if (cluster.HttpPendingOp.Response.RequestIssueDate.AddMilliseconds(OperationTimeToCompletionInMilliseconds) > DateTime.UtcNow)
                    {
                        error = new Microsoft.WindowsAzure.Management.HDInsight.Contracts.ErrorDetails()
                        {
                            StatusCode = HttpStatusCode.Conflict,
                            ErrorId = "CONFLICT",
                            ErrorMessage = "Another attempt to update the server is in progress."
                        };
                        passThroughResponse.Error = error;
                        passThroughResponse.Data = null;
                        return this.ReturnResponse(passThroughResponse);
                    }
                }
                if (request.Operation == UserChangeOperationType.Enable)
                {
                    // If the cluster already has a User and we are trying to enable again.
                    if (cluster.Cluster.HttpUserName.IsNotNullOrEmpty())
                    {
                        error = new Microsoft.WindowsAzure.Management.HDInsight.Contracts.ErrorDetails()
                        {
                            StatusCode = HttpStatusCode.BadRequest,
                            ErrorId = "Bad Request",
                            ErrorMessage =
                                "Attempt to enable a user when a user has already been enabled.  Please disable the user first and try again."
                        };
                        passThroughResponse.Error = error;
                        passThroughResponse.Data = null;
                        return this.ReturnResponse(passThroughResponse);
                    }
                    // check that the user is not trying to update the http user with the same user name as rdp
                    if (!String.IsNullOrEmpty(cluster.Cluster.RdpUserName))
                    {
                        if (cluster.Cluster.RdpUserName.Equals(request.Username))
                        {
                            error = new Microsoft.WindowsAzure.Management.HDInsight.Contracts.ErrorDetails()
                            {
                                StatusCode = HttpStatusCode.BadRequest,
                                ErrorId = "USERCHANGE_INVALIDNAME",
                                ErrorMessage = "Http username is not allowed to be same as RDP user name"
                            };
                            passThroughResponse.Error = error;
                            passThroughResponse.Data = null;
                            return this.ReturnResponse(passThroughResponse);
                        }
                    }
                    // Otherwise this is a good request, set the pending op.
                    if (request.Username == "fail")
                    {
                        statusResponse.State = UserChangeOperationState.Error;
                        statusResponse.Error = new Microsoft.WindowsAzure.Management.HDInsight.Contracts.ErrorDetails()
                        {
                            StatusCode = HttpStatusCode.BadRequest,
                            ErrorId = "Bad Request",
                            ErrorMessage = "The request failed."
                        };
                    }
                    cluster.HttpPendingOp = pendingOp;
                    ProcessingOps.Add(pendingOp.Id, pendingOp);
                    cluster.Cluster.HttpUserName = request.Username;
                    cluster.Cluster.HttpPassword = request.Password;
                    return this.ReturnResponse(passThroughResponse);
                }
                // It's a disable, that's always an op (or a duplicate op).
                cluster.HttpPendingOp = pendingOp;
                ProcessingOps.Add(pendingOp.Id, pendingOp);
                cluster.Cluster.HttpUserName = string.Empty;
                cluster.Cluster.HttpPassword = string.Empty;
                return this.ReturnResponse(passThroughResponse);
            }
        }
        public void ICanSerializeAndDeserializeAGetOperationStatusWithErrorDetails()
        {
            var errorStatusCode = HttpStatusCode.NotAcceptable;
            var errorIdDetails = "Error123";
            var errorMessageDetails = "This is an error!";
            ErrorDetails errorDetails = new ErrorDetails()
            {
                StatusCode = errorStatusCode,
                ErrorId = errorIdDetails,
                ErrorMessage = errorMessageDetails
            };

            var userChangeResponse = new UserChangeOperationStatusResponse()
            {
                OperationType = UserChangeOperationType.Enable,
                UserType = UserType.Http,
                RequestIssueDate = DateTime.UtcNow,
                State = UserChangeOperationState.Completed,
                Error = errorDetails
            };

            var responseObject = new PassthroughResponse()
            {
                Data = userChangeResponse,
                Error = errorDetails
            };

            // SERIALIZE THE RESPONSE
            var serializedPassthroughResponse = new ClusterProvisioningServerPayloadConverter();
            var serializedOpResponse = serializedPassthroughResponse.SerailizeChangeRequestResponse(responseObject);

            // now deseialize it
            var deserialized = new PayloadConverter().DeserializeConnectivityStatus(serializedOpResponse);

            Assert.IsNotNull(deserialized, "Nothing was returned from the deserializer.");
            Assert.IsNotNull(deserialized.ErrorDetails, "No error object was present after deserialization.");
            Assert.AreEqual(responseObject.Error.ErrorId, deserialized.ErrorDetails.ErrorId, "The Error Id did not match after deserialization.");
            Assert.AreEqual(responseObject.Error.ErrorMessage, deserialized.ErrorDetails.ErrorMessage, "The error message did not match after deserialization.");
            Assert.AreEqual(responseObject.Error.StatusCode, deserialized.ErrorDetails.StatusCode, "The status code did not match after deserialization.");
            Assert.IsNotNull(deserialized.Data, "No data object was present after deserialization.");
            Assert.AreEqual(userChangeResponse.OperationType.ToString(), deserialized.Data.OperationType.ToString(), "The OperationType did not match after deserialization.");
            Assert.AreEqual(userChangeResponse.RequestIssueDate, deserialized.Data.RequestIssueDate, "The IssueDate did not match after deserialization.");
            Assert.AreEqual(userChangeResponse.State.ToString(), deserialized.Data.State.ToString(), "The State did not match after deserialization.");
            Assert.AreEqual(userChangeResponse.UserType.ToString(), deserialized.Data.UserType.ToString(), "The user type not match after deserialization.");

            Assert.IsNotNull(deserialized.Data.ErrorDetails, "No error object was present after deserialization.");
            Assert.AreEqual(userChangeResponse.Error.ErrorId, deserialized.Data.ErrorDetails.ErrorId, "The (inner) Error Id did not match after deserialization.");
            Assert.AreEqual(userChangeResponse.Error.ErrorMessage, deserialized.Data.ErrorDetails.ErrorMessage, "The (inner) error message did not match after deserialization.");
            Assert.AreEqual(userChangeResponse.Error.StatusCode, deserialized.Data.ErrorDetails.StatusCode, "The (inner) status code did not match after deserialization.");
        }
 public PendingOp(UserChangeOperationStatusResponse response)
 {
     this.Response = response;
     this.Id = Guid.NewGuid();
 }
        public void ICanSerializeAndDeserializeAGetOperationStatusWithNoErrorDetails()
        {
            var responseObject = new UserChangeOperationStatusResponse()
            {
                OperationType = UserChangeOperationType.Enable,
                UserType = UserType.Http,
                RequestIssueDate = DateTime.UtcNow,
                State = UserChangeOperationState.Completed,
                Error = null
            };

            var passthroughOpStatus = new PassthroughResponse()
            {
                Data = responseObject,
                Error = null
            };

            // serialize the non error response
            var serializedPassthroughResponse = new ClusterProvisioningServerPayloadConverter();
            var serializedOpResponse = serializedPassthroughResponse.SerailizeChangeRequestResponse(passthroughOpStatus);

            // now deseialize it
            var deserialized = new PayloadConverter().DeserializeConnectivityStatus(serializedOpResponse);
            Assert.IsNotNull(deserialized, "Nothing was returned from the deserializer.");
            Assert.IsNotNull(deserialized.Data, "No data object was present after deserialization.");
            Assert.AreEqual(responseObject.OperationType.ToString(), deserialized.Data.OperationType.ToString(), "The OperationType did not match after deserialization.");
            Assert.AreEqual(responseObject.RequestIssueDate, deserialized.Data.RequestIssueDate, "The IssueDate did not match after deserialization.");
            Assert.AreEqual(responseObject.State.ToString(), deserialized.Data.State.ToString(), "The State did not match after deserialization.");
            Assert.AreEqual(responseObject.UserType.ToString(), deserialized.Data.UserType.ToString(), "The user type not match after deserialization.");
        }