Task<HostedServiceInfo[]> DoDiscoverHostedServices(HttpClient client, CancellationToken cancellationToken)
        {
            return client.GetXmlAsync<HostedServiceInfo[]>(
                "services/hostedservices",
                cancellationToken, _policies.RetryOnTransientErrors,
                (xml, tcs) =>
                {
                    var serviceNames = xml.AzureElements("HostedServices", "HostedService")
                        .Select(e => e.AzureValue("ServiceName"))
                        .ToArray();

                    Task.Factory.ContinueWhenAll(
                        serviceNames.Select(serviceName => DoDiscoverHostedService(client, serviceName, cancellationToken)).ToArray(),
                        tasks =>
                        {
                            // TODO (ruegg, 2011-05-27): Check task fault state and deal with it

                            try
                            {
                                tcs.TrySetResult(tasks.Select(t => t.Result).ToArray());
                            }
                            catch (Exception e)
                            {
                                tcs.TrySetException(e);
                            }
                        },
                        cancellationToken);
                });
        }
        Task<DeploymentReference[]> DoDiscoverDeployment(HttpClient client, string serviceName, CancellationToken cancellationToken)
        {
            return client.GetXmlAsync<DeploymentReference[]>(
                string.Format("services/hostedservices/{0}?embed-detail=true", serviceName),
                cancellationToken, _policies.RetryOnTransientErrors,
                (xml, tcs) =>
                {
                    var xmlService = xml.AzureElement("HostedService");
                    var references = xmlService.AzureElements("Deployments", "Deployment").Select(d => new DeploymentReference
                    {
                        HostedServiceName = xmlService.AzureValue("ServiceName"),
                        DeploymentName = d.AzureValue("Name"),
                        DeploymentPrivateId = d.AzureValue("PrivateID")
                    }).ToArray();

                    tcs.TrySetResult(references);
                });
        }
        Task<HostedServiceInfo> DoDiscoverHostedService(HttpClient client, string serviceName, CancellationToken cancellationToken)
        {
            return client.GetXmlAsync<HostedServiceInfo>(
                string.Format("services/hostedservices/{0}?embed-detail=true", serviceName),
                cancellationToken, _policies.RetryOnTransientErrors,
                (xml, tcs) =>
                {
                    var xmlService = xml.AzureElement("HostedService");
                    var xmlProperties = xmlService.AzureElement("HostedServiceProperties");

                    var info = new HostedServiceInfo
                    {
                        ServiceName = xmlService.AzureValue("ServiceName"),
                        Description = xmlProperties.AzureValue("Description"),
                        ServiceLabel = xmlProperties.AzureEncodedValue("Label"),

                        Deployments = xmlService.AzureElements("Deployments", "Deployment").Select(d =>
                        {
                            var config = d.AzureConfiguration();
                            var instanceCountPerRole = d.AzureElements("RoleInstanceList", "RoleInstance")
                                .GroupBy(ri => ri.AzureValue("RoleName"))
                                .ToDictionary(g => g.Key, g => g.Count());

                            return new DeploymentInfo
                            {
                                DeploymentName = d.AzureValue("Name"),
                                DeploymentLabel = d.AzureEncodedValue("Label"),
                                Slot = (DeploymentSlot)Enum.Parse(typeof(DeploymentSlot), d.AzureValue("DeploymentSlot")),
                                PrivateId = d.AzureValue("PrivateID"),
                                Status = (DeploymentStatus)Enum.Parse(typeof(DeploymentStatus), d.AzureValue("Status")),
                                Roles = d.AzureElements("RoleList", "Role").Select(r =>
                                {
                                    var roleName = r.AzureValue("RoleName");
                                    var roleConfig = config.ServiceConfigElements("ServiceConfiguration", "Role")
                                        .Single(role => role.AttributeValue("name") == roleName);

                                    int instanceCount;
                                    if (!instanceCountPerRole.TryGetValue(roleName, out instanceCount))
                                    {
                                        instanceCount = 0;
                                    }

                                    return new RoleInfo
                                    {
                                        RoleName = roleName,
                                        ActualInstanceCount = instanceCount,
                                        ConfiguredInstanceCount = Int32.Parse(roleConfig.ServiceConfigElement("Instances").AttributeValue("count")),
                                        Settings = roleConfig.ServiceConfigElements("ConfigurationSettings", "Setting").ToDictionary(
                                            x => x.AttributeValue("name"), x => x.AttributeValue("value"))
                                    };
                                }).ToList()
                            };
                        }).ToList()
                    };

                    tcs.TrySetResult(info);
                });
        }
 Task<XDocument> DoGetDeploymentConfiguration(HttpClient client, string serviceName, DeploymentSlot deploymentSlot, CancellationToken cancellationToken)
 {
     return client.GetXmlAsync<XDocument>(
         string.Format("services/hostedservices/{0}/deploymentslots/{1}", serviceName, deploymentSlot.ToString().ToLower()),
         cancellationToken, _policies.RetryOnTransientErrors,
         (xml, tcs) => tcs.TrySetResult(xml.AzureElement("Deployment").AzureConfiguration()));
 }