From: Dies Koper <[email protected]>

---
 server/lib/deltacloud/drivers/fgcp/fgcp_client.rb | 44 +++++++++++++++++++++++
 server/lib/deltacloud/drivers/fgcp/fgcp_driver.rb | 38 +++++++++++++++++++-
 server/views/storage_volumes/show.html.haml       |  2 +-
 3 files changed, 82 insertions(+), 2 deletions(-)

diff --git a/server/lib/deltacloud/drivers/fgcp/fgcp_client.rb 
b/server/lib/deltacloud/drivers/fgcp/fgcp_client.rb
index 4d569da..fed3b70 100644
--- a/server/lib/deltacloud/drivers/fgcp/fgcp_client.rb
+++ b/server/lib/deltacloud/drivers/fgcp/fgcp_client.rb
@@ -274,6 +274,44 @@ eoidxml
     request('DestroyVDiskBackup', {'vsysId' => vsys_id, 'backupId' => 
backup_id})
   end
 
+  def get_vdisk_backup_copy_key(vsys_id, backup_id)
+    @version = '2012-07-20'
+    request('GetVDiskBackupCopyKey', {'vsysId' => vsys_id, 'backupId' => 
backup_id})
+  end
+
+  def set_vdisk_backup_copy_key(vsys_id, backup_id, contracts)
+    @version = '2012-07-20'
+    contracts_xml = <<-"eoctxml"
+<?xml version="1.0" encoding ="UTF-8"?>
+<Request>
+  <contracts>
+    <contract>
+#{contracts.collect { |c| "      <number>#{c}</number>" }.join("\n")}
+    </contract>
+  </contracts>
+</Request>
+eoctxml
+    request('SetVDiskBackupCopyKey',
+      {
+        'vsysId'   => vsys_id,
+        'backupId' => backup_id
+      },
+      contracts_xml,
+      'contractsXMLFilePath'
+    )
+  end
+
+  def external_restore_vdisk(src_vsys_id, src_backup_id, dst_vsys_id, 
dst_vdisk_id, key)
+    @version = '2012-07-20'
+    request('ExternalRestoreVDisk', {
+      'srcVsysId'   => src_vsys_id,
+      'srcBackupId' => src_backup_id,
+      'dstVsysId'   => dst_vsys_id,
+      'dstVdiskId'  => dst_vdisk_id,
+      'key'         => key}
+    )
+  end
+
   def list_public_ips(vsys_id=nil)
     if vsys_id.nil?
       request('ListPublicIP')
@@ -321,6 +359,12 @@ eoidxml
     $1
   end
 
+  #extract contract id from vserverId, efmId or networkId
+  def extract_contract_id(id)
+    /^(\w+)-\w+\b.*/ =~ id
+    $1
+  end
+
   private
 
   # params hash is of the form :vserverId => 'ABC123', etc.
diff --git a/server/lib/deltacloud/drivers/fgcp/fgcp_driver.rb 
b/server/lib/deltacloud/drivers/fgcp/fgcp_driver.rb
index 71b53bd..8d29a8e 100644
--- a/server/lib/deltacloud/drivers/fgcp/fgcp_driver.rb
+++ b/server/lib/deltacloud/drivers/fgcp/fgcp_driver.rb
@@ -556,7 +556,43 @@ class FgcpDriver < Deltacloud::BaseDriver
         opts[:realm_id] = xml[0]['vsys'][0]['vsysId'][0] if xml
       end
 
-      vdisk_id = client.create_vdisk(opts[:realm_id], opts[:name], 
opts[:capacity])['vdiskId'][0]
+      if not opts[:snapshot_id]
+        vdisk_id = client.create_vdisk(opts[:realm_id], opts[:name], 
opts[:capacity])['vdiskId'][0]
+      else
+        orig_vdisk_id, backup_id = split_snapshot_id(opts[:snapshot_id])
+        orig_vsys_id = client.extract_vsys_id(orig_vdisk_id)
+        # check snapshot size
+        size = 
client.get_vdisk_attributes(orig_vdisk_id)['vdisk'][0]['size'][0]
+        #set and retrieve key
+        contract_id = client.extract_contract_id(opts[:realm_id])
+        client.set_vdisk_backup_copy_key(orig_vsys_id, backup_id, 
[contract_id])
+        key = client.get_vdisk_backup_copy_key(opts[:realm_id], 
backup_id)['keyInfo'][0]['key'][0]
+        # create vdisk with same size as snapshot
+        size = 
client.get_vdisk_attributes(orig_vdisk_id)['vdisk'][0]['size'][0]
+        vdisk_id = client.create_vdisk(opts[:realm_id], opts[:name], 
size)['vdiskId'][0]
+        # try a restore straight away. It will likely fail (as the vdisk 
creation has not
+        # completed yet), but at least the parameters will be validated 
straight away.
+        begin
+          client.external_restore_vdisk(orig_vsys_id, backup_id, 
opts[:realm_id], vdisk_id, key)
+        rescue Exception => ex
+          # ignore expected error that destination vdisk is not ready yet
+          raise unless ex.message =~ /ILLEGAL_STATE_DST.*/
+        end
+        #wait until creation completes in a separate thread
+        Thread.new {
+          attempts = 0
+          begin
+            sleep 10
+            # this fails if the destination vdisk is still being deployed
+            client.external_restore_vdisk(orig_vsys_id, backup_id, 
opts[:realm_id], vdisk_id, key)
+          rescue Exception => ex
+            raise unless attempts < 30 and ex.message =~ /ILLEGAL_STATE_DST.*/
+            # Deployment takes a few minutes, so keep trying for a while
+            attempts += 1
+            retry
+          end
+        }
+      end
 
       StorageVolume.new(
         :id          => vdisk_id,
diff --git a/server/views/storage_volumes/show.html.haml 
b/server/views/storage_volumes/show.html.haml
index eddf5a9..725bbdf 100644
--- a/server/views/storage_volumes/show.html.haml
+++ b/server/views/storage_volumes/show.html.haml
@@ -24,7 +24,7 @@
       - if @storage_volume.instance_id
         %a{ :href => instance_url( @storage_volume.instance_id)}
           = @storage_volume.instance_id
-      - elsif @storage_volume.state == "AVAILABLE"
+      - elsif @storage_volume.state and @storage_volume.state != "IN-USE"
         %p{ :'data-role' => 'fieldcontain'}= 'none (detached)'
       -else
         %p{ :'data-role' => 'fieldcontain'}= 'unknown'
-- 
1.8.0.msysgit.0


Reply via email to