简体   繁体   English

Openstack.Net SDK无法访问具有区域的服务

[英]Openstack.Net SDK cannot access service with region

Using our own hardware, we've installed vanilla openstack with all components however I am having problems accessing services other than the Identity due to a region issue. 使用我们自己的硬件,我们为所有组件安装了vanilla openstack,但是由于地区问题,我在访问身份以外的服务时遇到了问题。 The code used is as follows called with the admin account and admin tennant we created... 所使用的代码如下所示,并使用我们创建的admin帐户和admin tennant进行调用...

    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;
        }
    }

The code fails at the call to ListContainers(region: region) with the error... 'The user does not have access to the requested service or region' where as if I don't specify a region the error is simply 'No region was provided, the service does not provide a region-independent endpoint, and there is no default region set for the user's account' 该代码在调用ListContainers(region:region)时失败,并显示以下错误...“用户无权访问所请求的服务或区域”,好像我没有指定区域一样,错误仅是“ No region”已提供,该服务不提供与区域无关的终结点,并且没有为用户帐户设置默认区域

We are only accessing our internal network at the moment so regions aren't important to us yet... 我们目前仅访问内部网络,因此区域对我们而言并不重要...

Also of note is that when making a call to... 还要注意的是,在致电...

CloudNetwork detail = cnp.ShowNetwork(networkGuid, "regionOne");

of a network I can see returns the error 'The item was not found or does not exist.' 我可以看到的网络返回错误“找不到或不存在该项目”。

Help and advice much appreciated. 帮助和建议,不胜感激。

I managed to extend the functionality of the Openstack.Net SDK fairly simply. 我设法相当简单地扩展了Openstack.Net SDK的功能。 The code below extends it to include various functions for Tenant/Project manipulations... 下面的代码将其扩展为包括用于承租人/项目操纵的各种功能...

Firstly, create a NewTenant container that will be used to pass data to and from the webservices, I've put it in the same namespace as the others... 首先,创建一个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;
        }
    }
}

Now we can create any new Request classes for posting the data... 现在我们可以创建任何新的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;
        }
    }
}

Now create the Response objects for the requests to help retrieve the data 现在为请求创建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; }
    }
}

Now we can create a class that inherits from OpenStackIdentityProvider with the additional functionality for Tenant/Project manipulation that we want... 现在,我们可以创建一个继承自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;
        }
    }
}

I imagine that this functionality will appear in the GitHub version soon, but if not I hope it's useful. 我想这个功能很快就会出现在GitHub版本中,但是如果没有,我希望它会有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Openstack.Net SDK无法访问服务 - Openstack.Net SDK cannot access services 如何使用OpenStack.NET创建新服务器 - How to create a new server using OpenStack.NET 使用伦敦帐户通过openstack.net API云文件进行身份验证 - Authenticating with openstack.net API cloud files using London account 如何使用openstack.net从Rackspace上的CloudFiles获取jpg文件 - How to get jpg file from CloudFiles on Rackspace using openstack.net 如何使用openstack.net在rackspace CloudFiles容器中创建Content-Type“application / directory”对象? - How to create an object with Content-Type “application/directory” inside a rackspace CloudFiles Container with openstack.net? 无法访问ASP.NET Core后台服务中的已处置对象 - Cannot access a disposed object in ASP.NET Core background service OpenStack SDK GetObjectSaveToFile标头 - OpenStack SDK GetObjectSaveToFile Headers 无法访问Windows服务中托管的ASP.NET Core应用程序 - Cannot access ASP.NET Core application hosted in a Windows Service .NET SDK天蓝色媒体服务 - .NET SDK azure media service 访问没有使用.Net SDK的美国区域的存储桶时遇到问题 - Having problems accessing bucket that is not using US region with the .Net SDK
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM