2014-06-19 42 views
0

使用我們自己的硬件,我們已經安裝了所有組件的vanilla openstack,但由於地區問題,我在訪問身份之外的其他服務時遇到問題。所使用的代碼如下調用我們創建的管理員帳戶和管理員坦...Openstack.Net SDK無法訪問區域服務

public static void TestAccess(string userName, string password, string projectName, string projectId) 
    { 
     try 
     { 
      Uri baseUrl = new Uri(URL_IDENTITY); 

      CloudIdentityWithProject projectCloudId = new CloudIdentityWithProject(); 
      projectCloudId.Username = userName; 
      projectCloudId.Password = password; 
      projectCloudId.ProjectName = projectName; 
      projectCloudId.ProjectId = new ProjectId(projectId); 

      OpenStackIdentityProvider idProvider = new OpenStackIdentityProvider(baseUrl, projectCloudId); 
      UserAccess userAccess = idProvider.Authenticate(projectCloudId); 
      IEnumerable<ExtendedEndpoint> eps = idProvider.ListEndpoints(userAccess.Token.Id); 

      string reg = idProvider.DefaultRegion; // This is null 

      ServiceCatalog[] scs = userAccess.ServiceCatalog; 

      // Get the list of regions 
      regionList = new List<string>(); 
      foreach (ServiceCatalog sc in scs) 
      { 
       foreach (Endpoint ep in sc.Endpoints) 
       { 
        regionList.Add(ep.Region); // This is 'regionOne' in every case 
       } 
      } 

      // Try stuff... 
      foreach(string region in regionList.Distinct()) 
      { 
       // Get a list of containers 
       CloudFilesProvider cfp = new CloudFilesProvider(projectCloudId, idProvider); 
       // THIS LINE FAILS 
       IEnumerable<Container> listOfContainers = cfp.ListContainers(region: region); 
       foreach (Container ctnr in listOfContainers) 
       { 
        Console.WriteLine("Container: {0}", ctnr.Name); 
       } 

       CloudNetworksProvider cnp = new CloudNetworksProvider(identity: null, identityProvider: idProvider); 
       IEnumerable<CloudNetwork> networks = cnp.ListNetworks(identity: null, region: region); 
       foreach (CloudNetwork network in networks) 
       { 
        Console.WriteLine("Network[{0}] name: {1}", networkCount, network.Label); 
        Console.WriteLine("Network[{0}] Id: {1}", networkCount, network.Id); 
        ++networkCount; 
       } 

       Console.WriteLine("{0} networks listed.", networkCount); 
      } 
     } 
     catch(Exception ex) 
     { 
      throw; 
     } 
    } 

的代碼在調用ListContainers(區:區)失敗,出現錯誤......「用戶不有權訪問所請求的服務或區域',因爲如果我沒有指定區域,錯誤就是'沒有提供區域,服務不提供區域無關的端點,並且沒有爲用戶設置默認區域帳戶」

我們只是在一瞬間進入我們的內部網絡,以便地區並不重要,對我們可是...

而且值得注意的是,撥打電話,以...

CloudNetwork detail = cnp.ShowNetwork(networkGuid, "regionOne"); 
網絡,我可以看到返回錯誤

當「的項目沒有被發現或不存在。」

幫助和建議非常感謝。

+0

如果在Visual Studio中啓用符號源,則可以在調試器中進入ListContainers的代碼。 http://www.symbolsource.org/Public/Home/VisualStudio這可以幫助您追蹤更具體的原因。 –

+0

我從github下載了源代碼,並將其鎖定。我現在可以看到問題... CloudNetworksProvider跳到{0}/os-networksv2,因爲標準OpenStack需要爲{0}/os-networks,導致「找不到項目」異常。 CloudFilesProvider是一個誤解,只是沒有安裝「存儲用戶無法訪問...」異常的事實。有關如何繞過{0}/os-networksv2而不創建該類的Vanilla OpenStack版本的任何建議? – Hoots

+0

Rackspace使用類似[Compute API網絡(os-networks)擴展]的不同網絡支持實現(http://docs.openstack.org/api/openstack-compute/2/content/ext-os-networks。 HTML),但使用不同的端點。 openstack.net SDK的v2.0版本增加了對[OpenStack Networking API](http://docs.openstack.org/api/openstack-network/2.0/content/)的支持,這是您需要的另一個OpenStack安裝。有關此主要更新的當前狀態,請參閱以下頁面:https://github.com/openstacknetsdk/openstack.net/wiki/V2.0 –

回答

0

我設法很簡單地擴展了Openstack.Net SDK的功能。下面的代碼將其擴展爲包含租戶/項目操作的各種功能...

首先,創建一個用於將數據傳入和傳出Web服務的NewTenant容器,我將它放在與Web服務相同的名稱空間中別人...

using Newtonsoft.Json; 

namespace net.openstack.Core.Domain 
{ 

    [JsonObject(MemberSerialization.OptIn)] 
    public class NewTenant 
    { 
     /// <summary> 
     /// Gets the ID for the new user. 
     /// <note type="warning">The value of this property is not defined. Do not use.</note> 
     /// </summary> 
     [JsonProperty("id", DefaultValueHandling = DefaultValueHandling.Include)] 
     public string Id { get; private set; } 

     [JsonProperty("name")] 
     public string Name { get; private set; } 

     [JsonProperty("description")] 
     public string Description { get; private set; } 

     [JsonProperty("enabled")] 
     public bool Enabled { get; private set; } 

     public NewTenant(string name, string description, bool enabled = true) 
     { 
      Name = name; 
      Description = description; 
      Enabled = enabled; 
     } 
    } 
} 

現在,我們可以創建任何新的請求類張貼數據...

using System; 
using Newtonsoft.Json; 
using net.openstack.Core.Domain; 

namespace net.openstack.Core.Request 
{ 

    [JsonObject(MemberSerialization.OptIn)] 
    internal class AddTenantRequest 
    { 
     [JsonProperty("tenant")] 
     public NewTenant Tenant { get; private set; } 

     public AddTenantRequest(NewTenant tenant) 
     { 
      if (tenant == null) 
       throw new ArgumentNullException("tenant"); 

      Tenant = tenant; 
     } 
    } 
} 

現在創建響應對象的請求,以幫助檢索數據

using net.openstack.Core.Domain; 
using Newtonsoft.Json; 

namespace net.openstack.Core.Response 
{ 
    [JsonObject(MemberSerialization.OptIn)] 
    internal class NewTenantResponse 
    { 
     [JsonProperty("tenant")] 
     public NewTenant NewTenant { get; private set; } 
    } 

    [JsonObject(MemberSerialization.OptIn)] 
    internal class TenantResponse 
    { 
     [JsonProperty("tenant")] 
     public Tenant Tenant { get; private set; } 
    } 
} 

現在,我們可以創建一個OpenStackIdentityProvider繼承與我們希望租戶/項目操作的附加功能的類...

using System; 
using System.Net; 
using JSIStudios.SimpleRESTServices.Client; 
using net.openstack.Core.Domain; 
using net.openstack.Core.Request; 
using net.openstack.Core.Response; 

namespace net.openstack.Core.Providers 
{ 
    public class ExtendedOpenStackIdentityProvider : OpenStackIdentityProvider 
    { 
     public ExtendedOpenStackIdentityProvider(Uri urlBase) 
      : base(urlBase) 
     { 
     } 

     public ExtendedOpenStackIdentityProvider(Uri urlBase, CloudIdentity identity) 
      : base(urlBase, identity) 
     { 
     } 

     public ExtendedOpenStackIdentityProvider(Uri urlBase, JSIStudios.SimpleRESTServices.Client.IRestService restService, net.openstack.Core.Caching.ICache<UserAccess> tokenCache) 
      : base(urlBase, restService, tokenCache) 
     { 
     } 

     public ExtendedOpenStackIdentityProvider(Uri urlBase, CloudIdentity identity, JSIStudios.SimpleRESTServices.Client.IRestService restService, net.openstack.Core.Caching.ICache<UserAccess> tokenCache) 
      : base(urlBase, identity, restService, tokenCache) 
     { 
     } 

     public NewTenant AddTenant(NewTenant tenant, CloudIdentity identity) 
     { 
      if (tenant == null) 
       throw new ArgumentNullException("tenant"); 
      if (string.IsNullOrEmpty(tenant.Name)) 
       throw new ArgumentException("tenant.Name cannot be null or empty"); 
      if (tenant.Id != null) 
       throw new InvalidOperationException("tenant.Id must be null"); 

      CheckIdentity(identity); 

      var response = ExecuteRESTRequest<NewTenantResponse>(identity, new Uri(UrlBase, "/v2.0/tenants"), HttpMethod.POST, new AddTenantRequest(tenant)); 

      if (response == null || response.Data == null) 
       return null; 

      return response.Data.NewTenant; 
     } 

     public Tenant GetTenant(string tenantId, CloudIdentity identity) 
     { 
      if (tenantId == null) 
       throw new ArgumentNullException("tenantId"); 

      CheckIdentity(identity); 

      var urlPath = string.Format("v2.0/tenants/{0}", tenantId); 

      var response = ExecuteRESTRequest<TenantResponse>(identity, new Uri(UrlBase, urlPath), HttpMethod.GET); 

      if (response == null || response.Data == null) 
       return null; 

      return response.Data.Tenant; 
     } 

     public bool DeleteTenant(string tenantId, CloudIdentity identity) 
     { 
      if (tenantId == null) 
       throw new ArgumentNullException("tenantId"); 
      if (string.IsNullOrEmpty(tenantId)) 
       throw new ArgumentException("tenantId cannot be empty"); 
      CheckIdentity(identity); 

      var urlPath = string.Format("v2.0/tenants/{0}", tenantId); 
      var response = ExecuteRESTRequest(identity, new Uri(UrlBase, urlPath), HttpMethod.DELETE); 

      if (response != null && response.StatusCode == HttpStatusCode.NoContent) 
       return true; 

      return false; 
     } 

     public bool AddTenantUserRole(string tenantId, string userId, string roleId, CloudIdentity identity) 
     { 
      if (tenantId == null) 
       throw new ArgumentNullException("tenantId"); 
      if (string.IsNullOrEmpty(tenantId)) 
       throw new ArgumentException("tenantId cannot be empty"); 
      if (userId == null) 
       throw new ArgumentNullException("userId"); 
      if (string.IsNullOrEmpty(userId)) 
       throw new ArgumentException("userId cannot be empty"); 
      if (roleId == null) 
       throw new ArgumentNullException("roleId"); 
      if (string.IsNullOrEmpty(roleId)) 
       throw new ArgumentException("roleId cannot be empty"); 

      CheckIdentity(identity); 

      var urlPath = string.Format("v2.0/tenants/{0}/users/{1}/roles/OS-KSADM/{2}", tenantId, userId, roleId); 
      var response = ExecuteRESTRequest(identity, new Uri(UrlBase, urlPath), HttpMethod.PUT); 

      if (response != null && response.StatusCode == HttpStatusCode.NoContent) 
       return true; 

      return false; 
     } 
    } 
} 

我想象,這個功能將很快出現在GitHub的版本,但如果不是,我希望它是有用的。