Skip to content

Commit f6b62b7

Browse files
committed
Merge pull request #90 from rackspace/master
Merge Rackspace specific changes
2 parents bd3eb3c + 0f6c59b commit f6b62b7

35 files changed

Lines changed: 239 additions & 115 deletions

src/console/console.csproj

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,13 @@
3535
<WarningLevel>4</WarningLevel>
3636
</PropertyGroup>
3737
<ItemGroup>
38-
<Reference Include="Newtonsoft.Json">
38+
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
39+
<SpecificVersion>False</SpecificVersion>
3940
<HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath>
4041
</Reference>
41-
<Reference Include="SimpleRESTServices, Version=1.0.6.3, Culture=neutral, processorArchitecture=MSIL">
42+
<Reference Include="SimpleRESTServices, Version=1.0.6.6, Culture=neutral, processorArchitecture=MSIL">
4243
<SpecificVersion>False</SpecificVersion>
43-
<HintPath>..\packages\SimpleRESTServices.1.0.6.3\lib\net40\SimpleRESTServices.dll</HintPath>
44+
<HintPath>..\packages\SimpleRESTServices.1.0.6.6\lib\net40\SimpleRESTServices.dll</HintPath>
4445
</Reference>
4546
<Reference Include="System" />
4647
<Reference Include="System.Core" />

src/console/packages.config

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<packages>
33
<package id="Newtonsoft.Json" version="4.5.11" targetFramework="net40" />
4-
<package id="SimpleRESTServices" version="1.0.6.3" targetFramework="net40" />
4+
<package id="SimpleRESTServices" version="1.0.6.6" targetFramework="net40" />
55
</packages>

src/corelib/Core/Domain/Volume.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Runtime.Serialization;
34

45
namespace net.openstack.Core.Domain
@@ -25,7 +26,7 @@ public class Volume
2526
public string SnapshotId { get; set; }
2627

2728
[DataMember]
28-
public string[] Attachments { get; set; }
29+
public Dictionary<string, string>[] Attachments { get; set; }
2930

3031
[DataMember]
3132
public string Status { get; set; }

src/corelib/Core/Providers/IObjectStorageProvider.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -331,24 +331,39 @@ public interface IObjectStorageProvider
331331
/// <param name="sourceObjectName">Name of the source object.<remarks>Example image_name.jpeg</remarks></param>
332332
/// <param name="destinationContainer">The destination container name.</param>
333333
/// <param name="destinationObjectName">Name of the destination object.<remarks>Example image_name.jpeg</remarks></param>
334-
/// <param name="headers">The headers. </param>
334+
/// <param name="headers">A list of HTTP headers to send to the service. </param>
335335
/// <param name="region">The region in which to execute this action.<remarks>If not specified, the user’s default region will be used.</remarks></param>
336336
///<param name="useInternalUrl">If set to <c>true</c> uses ServiceNet URL.</param>
337337
/// <param name="identity">The users Cloud Identity. <see cref="CloudIdentity"/> <remarks>If not specified, the default identity given in the constructor will be used.</remarks> </param>
338338
/// <returns><see cref="ObjectStore"/></returns>
339339
ObjectStore CopyObject(string sourceContainer, string sourceObjectName, string destinationContainer, string destinationObjectName, Dictionary<string, string> headers = null, string region = null, bool useInternalUrl = false, CloudIdentity identity = null);
340340

341+
/// <summary>
342+
/// Moves an object. <remarks>The original source object will be deleted only if the move is successful.</remarks>
343+
/// </summary>
344+
/// <param name="sourceContainer">The source container name.</param>
345+
/// <param name="sourceObjectName">Name of the source object.<remarks>Example image_name.jpeg</remarks></param>
346+
/// <param name="destinationContainer">The destination container name.</param>
347+
/// <param name="destinationObjectName">Name of the destination object.<remarks>Example image_name.jpeg</remarks></param>
348+
/// <param name="headers">A list of HTTP headers to send to the service. </param>
349+
/// <param name="region">The region in which to execute this action.<remarks>If not specified, the user’s default region will be used.</remarks></param>
350+
///<param name="useInternalUrl">If set to <c>true</c> uses ServiceNet URL.</param>
351+
/// <param name="identity">The users Cloud Identity. <see cref="CloudIdentity"/> <remarks>If not specified, the default identity given in the constructor will be used.</remarks> </param>
352+
/// <returns><see cref="ObjectStore"/></returns>
353+
ObjectStore MoveObject(string sourceContainer, string sourceObjectName, string destinationContainer, string destinationObjectName, Dictionary<string, string> headers = null, string region = null, bool useInternalUrl = false, CloudIdentity identity = null);
354+
341355
/// <summary>
342356
/// Deletes the object.
343357
/// </summary>
344358
/// <param name="container">The container name.</param>
345359
/// <param name="objectName">Name of the object.<remarks>Example image_name.jpeg</remarks></param>
346-
/// <param name="headers">The headers. </param>
360+
/// <param name="headers">A list of HTTP headers to send to the service. </param>
361+
/// <param name="deleteSegments">Indicates whether the file's segments should be deleted if any exist.</param>
347362
/// <param name="region">The region in which to execute this action.<remarks>If not specified, the user’s default region will be used.</remarks></param>
348363
/// <param name="useInternalUrl">If set to <c>true</c> uses ServiceNet URL.</param>
349364
/// <param name="identity">The users Cloud Identity. <see cref="CloudIdentity"/> <remarks>If not specified, the default identity given in the constructor will be used.</remarks> </param>
350365
/// <returns><see cref="ObjectStore"/></returns>
351-
ObjectStore DeleteObject(string container, string objectName, Dictionary<string, string> headers = null, string region = null, bool useInternalUrl = false, CloudIdentity identity = null);
366+
ObjectStore DeleteObject(string container, string objectName, Dictionary<string, string> headers = null, bool deleteSegments = true, string region = null, bool useInternalUrl = false, CloudIdentity identity = null);
352367

353368
/// <summary>
354369
/// Purges the object from CDN.

src/corelib/Providers/Rackspace/CloudFilesProvider.cs

Lines changed: 42 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ public void CreateObject(string container, Stream stream, string objectName, int
572572
}
573573
var urlPath = new Uri(string.Format("{0}/{1}/{2}", GetServiceEndpointCloudFiles(identity, region, useInternalUrl), _encodeDecodeProvider.UrlEncode(container), _encodeDecodeProvider.UrlEncode(objectName)));
574574

575-
StreamRESTRequest(identity, urlPath, HttpMethod.PUT, stream, chunkSize, headers: headers, isRetry: true, progressUpdated: progressUpdated, requestSettings: new RequestSettings {ChunkRequest = true});
575+
StreamRESTRequest(identity, urlPath, HttpMethod.PUT, stream, chunkSize, headers: headers, progressUpdated: progressUpdated, requestSettings: new RequestSettings {ChunkRequest = true});
576576
}
577577

578578
/// <inheritdoc />
@@ -659,53 +659,57 @@ public ObjectStore CopyObject(string sourceContainer, string sourceObjectName, s
659659
_cloudFilesValidator.ValidateContainerName(destinationContainer);
660660
_cloudFilesValidator.ValidateObjectName(destinationObjectName);
661661

662-
if (headers != null)
663-
{
664-
if (string.IsNullOrWhiteSpace(headers.FirstOrDefault(x => x.Key.Equals(ContentLength, StringComparison.OrdinalIgnoreCase)).Value))
665-
{
666-
var contentLength = GetObjectContentLength(identity, sourceContainer, sourceObjectName, region, useInternalUrl);
667-
headers.Add(ContentLength, contentLength);
668-
}
669-
}
670-
else
671-
{
662+
var urlPath = new Uri(string.Format("{0}/{1}/{2}", GetServiceEndpointCloudFiles(identity, region, useInternalUrl), _encodeDecodeProvider.UrlEncode(sourceContainer), _encodeDecodeProvider.UrlEncode(sourceObjectName)));
663+
664+
if(headers == null)
672665
headers = new Dictionary<string, string>();
673-
var contentLength = GetObjectContentLength(identity, sourceContainer, sourceObjectName, region, useInternalUrl);
674-
headers.Add(ContentLength, contentLength);
675-
676-
}
677-
678-
headers.Add(CopyFrom, string.Format("{0}/{1}", sourceContainer, sourceObjectName));
679-
680-
var urlPath = new Uri(string.Format("{0}/{1}/{2}", GetServiceEndpointCloudFiles(identity, region, useInternalUrl), _encodeDecodeProvider.UrlEncode(destinationContainer), _encodeDecodeProvider.UrlEncode(destinationObjectName)));
681666

682-
var response = ExecuteRESTRequest(identity, urlPath, HttpMethod.PUT, headers);
667+
headers.Add(DestinationMetadataKey, string.Format("{0}/{1}", destinationContainer, destinationObjectName));
668+
ExecuteRESTRequest(identity, urlPath, HttpMethod.COPY, headers: headers);
683669

684-
if (response.StatusCode == 201)
685-
return ObjectStore.ObjectCreated;
686-
if (response.StatusCode == 404)
687-
return ObjectStore.ContainerNotFound;
688-
689-
return ObjectStore.Unknown;
670+
return ObjectStore.ObjectCreated;
690671
}
691672

692673
/// <inheritdoc />
693-
public ObjectStore DeleteObject(string container, string objectName, Dictionary<string, string> headers = null, string region = null, bool useInternalUrl = false, CloudIdentity identity = null)
674+
public ObjectStore DeleteObject(string container, string objectName, Dictionary<string, string> headers = null, bool deleteSegments = true, string region = null, bool useInternalUrl = false, CloudIdentity identity = null)
694675
{
695676
_cloudFilesValidator.ValidateContainerName(container);
696677
_cloudFilesValidator.ValidateObjectName(objectName);
697678

679+
Dictionary<string, string> objectHeader = null;
680+
if(deleteSegments)
681+
objectHeader = GetObjectHeaders(container, objectName, region, useInternalUrl, identity);
682+
698683
var urlPath = new Uri(string.Format("{0}/{1}/{2}", GetServiceEndpointCloudFiles(identity, region, useInternalUrl), _encodeDecodeProvider.UrlEncode(container), _encodeDecodeProvider.UrlEncode(objectName)));
699684

700-
var response = ExecuteRESTRequest(identity, urlPath, HttpMethod.DELETE, headers);
685+
ExecuteRESTRequest(identity, urlPath, HttpMethod.DELETE, headers: headers);
701686

702-
if (response.StatusCode == 204)
703-
return ObjectStore.ObjectDeleted;
704-
if (response.StatusCode == 404)
705-
return ObjectStore.ContainerNotFound;
687+
if (deleteSegments && objectHeader != null && objectHeader.Any(h => h.Key.Equals(ObjectManifestMetadataKey, StringComparison.OrdinalIgnoreCase)))
688+
{
689+
var objects = this.ListObjects(container, region: region, useInternalUrl: useInternalUrl, identity: identity);
706690

707-
return ObjectStore.Unknown;
691+
if (objects != null && objects.Any())
692+
{
693+
var segments = objects.Where(f => f.Name.StartsWith(string.Format("{0}.seg", objectName)));
694+
foreach (var segment in segments)
695+
{
696+
DeleteObject(container, segment.Name, headers, false, region, useInternalUrl, identity);
697+
}
698+
}
699+
}
700+
701+
return ObjectStore.ObjectDeleted;
702+
}
708703

704+
/// <inheritdoc />
705+
public ObjectStore MoveObject(string sourceContainer, string sourceObjectName, string destinationContainer, string destinationObjectName, Dictionary<string, string> headers = null, string region = null, bool useInternalUrl = false, CloudIdentity identity = null)
706+
{
707+
var result = CopyObject(sourceContainer, sourceObjectName, destinationContainer, destinationObjectName, headers, region, useInternalUrl, identity);
708+
709+
if (result != ObjectStore.ObjectCreated)
710+
return result;
711+
712+
return DeleteObject(sourceContainer, sourceObjectName, headers, true, region, useInternalUrl, identity);
709713
}
710714

711715
/// <inheritdoc />
@@ -828,13 +832,6 @@ public void UpdateAccountHeaders(Dictionary<string, string> headers, string regi
828832

829833
#region Private methods
830834

831-
private string GetObjectContentLength(CloudIdentity identity, string sourceContainer, string sourceObjectName, string region, bool useInternalUrl)
832-
{
833-
var sourceHeaders = GetObjectHeaders(sourceContainer, sourceObjectName, region,useInternalUrl, identity);
834-
var contentLength = sourceHeaders.FirstOrDefault(x => x.Key.Equals(ContentLength, StringComparison.OrdinalIgnoreCase)).Value;
835-
return contentLength;
836-
}
837-
838835
protected string GetServiceEndpointCloudFiles(CloudIdentity identity, string region = null, bool useInternalUrl = false)
839836
{
840837
return useInternalUrl ? base.GetInternalServiceEndpoint(identity, "cloudFiles", region) : base.GetPublicServiceEndpoint(identity, "cloudFiles", region);
@@ -886,7 +883,7 @@ private void CreateObjectInSegments(string container, Stream stream, string obje
886883

887884
var urlPath = new Uri(string.Format("{0}/{1}/{2}.seg{3}", GetServiceEndpointCloudFiles(identity, region, useInternalUrl), container, objectName, i));
888885
long segmentBytesWritten = 0;
889-
StreamRESTRequest(identity, urlPath, HttpMethod.PUT, stream, chunkSize, length, headers: headers, isRetry: true, requestSettings: new RequestSettings {ChunkRequest = true}, progressUpdated:
886+
StreamRESTRequest(identity, urlPath, HttpMethod.PUT, stream, chunkSize, length, headers: headers, requestSettings: new RequestSettings {ChunkRequest = true}, progressUpdated:
890887
bytesWritten =>
891888
{
892889
if (progressUpdated != null)
@@ -906,7 +903,7 @@ private void CreateObjectInSegments(string container, Stream stream, string obje
906903
headers = new Dictionary<string, string>();
907904

908905
headers.Add(ObjectManifestMetadataKey, string.Format("{0}/{1}", container, objectName));
909-
StreamRESTRequest(identity, segmentUrlPath, HttpMethod.PUT, new MemoryStream(new Byte[0]), chunkSize, headers: headers, isRetry: true, requestSettings: new RequestSettings {ChunkRequest = true}, progressUpdated:
906+
StreamRESTRequest(identity, segmentUrlPath, HttpMethod.PUT, new MemoryStream(new Byte[0]), chunkSize, headers: headers, requestSettings: new RequestSettings {ChunkRequest = true}, progressUpdated:
910907
(bytesWritten) =>
911908
{
912909
if (progressUpdated != null)
@@ -957,10 +954,9 @@ protected override IObjectStorageProvider BuildProvider(CloudIdentity identity)
957954
public const string ObjectDeleteAfter = "x-delete-after";
958955
public const string ObjectDeleteAt = "x-delete-at";
959956
public const string Etag = "etag";
960-
public const string ContentType = "content-type";
961-
public const string ContentLength = "content-length";
962-
public const string CopyFrom = "x-copy-from";
963-
public const string ObjectManifestMetadataKey = "X-Object-Manifest";
957+
public const string DestinationMetadataKey = "destination";
958+
public const string ObjectManifestMetadataKey = "x-object-manifest";
959+
964960
//Cdn Object Constants
965961
public const string CdnPurgeEmail = "x-purge-email";
966962

src/corelib/Providers/Rackspace/CloudIdentityProviderFactory.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using net.openstack.Core.Caching;
55
using net.openstack.Core.Domain;
66
using net.openstack.Providers.Rackspace.Exceptions;
7+
using net.openstack.Providers.Rackspace.Objects;
78
using net.openstack.Providers.Rackspace.Validators;
89

910
namespace net.openstack.Providers.Rackspace

src/corelib/Providers/Rackspace/GeographicalCloudIdentityProvider.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using net.openstack.Core.Caching;
1010
using net.openstack.Core.Domain;
1111
using net.openstack.Core.Validators;
12+
using net.openstack.Providers.Rackspace.Objects;
1213
using net.openstack.Providers.Rackspace.Objects.Request;
1314
using net.openstack.Providers.Rackspace.Objects.Response;
1415

src/corelib/Providers/Rackspace/Objects/AuthDetails.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,8 @@ internal class AuthDetails
1010

1111
[DataMember(Name = "RAX-KSKEY:apiKeyCredentials", EmitDefaultValue = true)]
1212
public Credentials APIKeyCredentials { get; set; }
13+
14+
[DataMember(Name = "RAX-AUTH:domain", EmitDefaultValue = true)]
15+
public Domain Domain { get; set; }
1316
}
1417
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System.Runtime.Serialization;
2+
3+
namespace net.openstack.Providers.Rackspace.Objects
4+
{
5+
[DataContract]
6+
public class Domain
7+
{
8+
[DataMember(Name = "name")]
9+
public string Name { get; set; }
10+
}
11+
}

src/corelib/Providers/Rackspace/RackspaceCloudIdentity.cs renamed to src/corelib/Providers/Rackspace/Objects/RackspaceCloudIdentity.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using net.openstack.Core.Domain;
22

3-
namespace net.openstack.Providers.Rackspace
3+
namespace net.openstack.Providers.Rackspace.Objects
44
{
55
public class RackspaceCloudIdentity : CloudIdentity
66
{
@@ -17,6 +17,8 @@ public RackspaceCloudIdentity(CloudIdentity cloudIdentity) : this()
1717
}
1818

1919
public CloudInstance CloudInstance { get; set; }
20+
21+
public Domain Domain { get; set; }
2022
}
2123

2224
public enum CloudInstance

0 commit comments

Comments
 (0)