是否可以将OpenStack.NET SDK与SoftLayer对象存储一起使用?

时间:2015-10-14 07:08:30

标签: openstack-swift ibm-cloud-infrastructure openstacknetsdk

SoftLayer Object Storage基于OpenStack Swift对象库。

SoftLayer为Python,Ruby,Java和PHP中的对象存储提供SDK,但不提供.NET。在为OpenStack搜索.NET SDK时,我遇到了OpenStack.NET

基于this question OpenStack.NET默认设计用于Rackspace,但可以使用CloudIdentityWithProjectOpenStackIdentityProvider与其他OpenStack提供商合作。

SoftLayer提供以下有关连接其对象存储的信息:

Authentication Endpoint
Public: https://mel01.objectstorage.softlayer.net/auth/v1.0/
Private: https://mel01.objectstorage.service.networklayer.com/auth/v1.0/

Username:
SLOS123456-1:email@example.com

API Key (Password):
1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef

这不会显示如何映射到CloudIdentityWithProjectOpenStackIdentityProvider的字段,但我尝试了以下以及项目名称/用户名/ uri的其他一些组合:

var cloudIdentity = new CloudIdentityWithProject()
{
    ProjectName = "SLOS123456-1",
    Username = "email@example.com",
    Password = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
};

var identityProvider = new OpenStackIdentityProvider(
    new Uri("https://mel01.objectstorage.softlayer.net/auth/v1.0/"),
    cloudIdentity);

var token = identityProvider.GetToken(null);

但是,在所有情况下,我都收到以下错误:

Unable to authenticate user and retrieve authorized service endpoints

基于查看SoftLayer的其他语言库和OpenStack.NET的源代码,看起来SoftLayer的对象存储使用V1 auth,而OpenStack.NET使用V2 auth。

基于this article from SoftLayerthis article from SwiftStack,V1 auth使用/auth/v1.0/路径(类似于SoftLayer提供的路径),X-Auth-UserX-Auth-Key标头为参数,以及包含在标题中的响应,如下所示:

X-Auth-Token-Expires = 83436
X-Auth-Token = AUTH_tk1234567890abcdef1234567890abcdef
X-Storage-Token = AUTH_tk1234567890abcdef1234567890abcdef
X-Storage-Url = https://mel01.objectstorage.softlayer.net/v1/AUTH_12345678-1234-1234-1234-1234567890ab
X-Trans-Id = txbc1234567890abcdef123-1234567890
Connection = keep-alive
Content-Length = 1300
Content-Type = text/html; charset=UTF-8
Date = Wed, 14 Oct 2015 01:19:45 GMT

V2 auth(identity API V2.0)使用/v2.0/tokens路径,而消息体中的JSON对象中包含请求和响应。

基于OpenStack.NET中的OpenStackIdentityProvider类,我一起攻击了我自己的SoftLayerOpenStackIdentityProvider

using JSIStudios.SimpleRESTServices.Client;
using net.openstack.Core.Domain;
using net.openstack.Providers.Rackspace;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OpenStack.Authentication;
using System;
using System.Linq;
using System.Collections.Generic;

namespace OpenStackTest1
{
    public class SoftLayerOpenStackIdentityProvider : CloudIdentityProvider
    {
        public SoftLayerOpenStackIdentityProvider(
            Uri urlBase, CloudIdentity defaultIdentity)
            : base(defaultIdentity, null, null, urlBase)
        {
            if (urlBase == null)
                throw new ArgumentNullException("urlBase");
        }

        public override UserAccess GetUserAccess(
            CloudIdentity identity, bool forceCacheRefresh = false)
        {
            identity = identity ?? DefaultIdentity;

            Func<UserAccess> refreshCallback =
                () =>
                {
                    // Set up request headers.
                    Dictionary<string, string> headers = 
                        new Dictionary<string, string>();
                    headers["X-Auth-User"] = identity.Username;
                    headers["X-Auth-Key"] = identity.APIKey;

                    // Make the request.
                    JObject requestBody = null;
                    var response = ExecuteRESTRequest<JObject>(
                        identity, 
                        UrlBase, 
                        HttpMethod.GET, 
                        requestBody, 
                        headers: headers, 
                        isTokenRequest: true);
                    if (response == null || response.Data == null)
                        return null;

                    // Get response headers.
                    string authToken = response.Headers.Single(
                        h => h.Key == "X-Auth-Token").Value;
                    string storageUrl = response.Headers.Single(
                        h => h.Key == "X-Storage-Url").Value;
                    string tokenExpires = response.Headers.Single(
                        h => h.Key == "X-Auth-Token-Expires").Value;

                    // Convert expiry from seconds to a date.
                    int tokenExpiresSeconds = Int32.Parse(tokenExpires);
                    DateTimeOffset tokenExpiresDate = 
                        DateTimeOffset.UtcNow.AddSeconds(tokenExpiresSeconds);

                    // Create UserAccess via JSON deseralization.
                    UserAccess access = JsonConvert.DeserializeObject<UserAccess>(
                        String.Format(
                            "{{ " +
                            "  token: {{ id: '{0}', expires: '{1}' }}, " +
                            "  serviceCatalog: " +
                            "  [ " +
                            "     {{ " +
                            "        endpoints: [ {{ publicUrl: '{2}' }} ], " +
                            "        type: 'object-store', " +
                            "        name: 'swift' " +
                            "     }} " +
                            "  ], " +
                            "  user: {{ }} " +
                            "}}",
                            authToken,
                            tokenExpiresDate,
                            storageUrl));
                    if (access == null || access.Token == null)
                        return null;

                    return access;
                };

            string key = string.Format("{0}:{1}", UrlBase, identity.Username);
            var userAccess = TokenCache.Get(key, refreshCallback, forceCacheRefresh);

            return userAccess;
        }

        protected override string LookupServiceTypeKey(IServiceType serviceType)
        {
            return serviceType.Type;
        }
    }
}

因为UserAccess的某些成员(如IdentityTokenEndpoint)无法设置其字段(对象只有默认构造函数且只有只读成员) ,我必须通过以V2 API返回的类似格式反序列化一些临时JSON来创建UserAccess对象。

这有效,即我现在可以像这样连接:

var cloudIdentity = new CloudIdentity()
{
    Username = "SLOS123456-1:email@example.com",
    APIKey = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
};

var identityProvider = new SoftLayerOpenStackIdentityProvider(
    new Uri("https://mel01.objectstorage.softlayer.net/auth/v1.0/"),
    cloudIdentity);

var token = identityProvider.GetToken(null);

然后像这样访问文件等:

var cloudFilesProvider = new CloudFilesProvider(identityProvider);

var containers = cloudFilesProvider.ListContainers();

var stream = new MemoryStream();
cloudFilesProvider.GetObject("testcontainer", "testfile.dat", stream);

但是,有没有比这更好的方法来使用.NET的SoftLayer对象存储?

我简要地查看了OpenStack SDK for .NET(与OpenStack.NET不同的库),但它似乎也基于V2 auth。

0 个答案:

没有答案