使用我们自己的硬件,我们已经安装了包含所有组件的vanilla openstack,但由于区域问题,我在访问Identity以外的服务时遇到了问题。所使用的代码如下所示:使用我们创建的管理员帐户和管理员终端...
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(地区:区域)时失败并显示错误...&#39;用户无法访问所请求的服务或区域&#39;如果我没有指定区域,则错误只是“没有提供区域”,该服务不提供与区域无关的端点,并且没有为用户设置默认区域帐户&#39;
我们目前只访问我们的内部网络,因此区域对我们来说并不重要......
同样值得注意的是,在打电话给...时
CloudNetwork detail = cnp.ShowNetwork(networkGuid, "regionOne");
我可以看到网络的返回错误&#39;该项目未找到或不存在。&#39;
非常感谢帮助和建议。
答案 0 :(得分:0)
我设法简单地扩展了Openstack.Net SDK的功能。下面的代码将其扩展为包含租户/项目操作的各种功能......
首先,创建一个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;
}
}
}
现在我们可以创建任何新的Request类来发布数据......
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;
}
}
}
现在为请求创建Response对象以帮助检索数据
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的类,其中包含我们想要的Tenant / Project操作的附加功能......
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版本中,但如果没有,我希望它有用。