[Ovirt-devel] [PATCH] lvm storage volume HW pool admin tab.

Scott Seago sseago at redhat.com
Thu Oct 30 23:53:15 UTC 2008


Includes 'view storage volume' facebox popup and new/delete LVM volume functionality. Although lvm tasks are created, taskomatic doesn't yet know what to do with them.

Signed-off-by: Scott Seago <sseago at redhat.com>
---
 src/app/controllers/hardware_controller.rb   |    5 +-
 src/app/controllers/storage_controller.rb    |  180 +++++++++++++++++++++++++-
 src/app/controllers/task_controller.rb       |    2 +
 src/app/models/lvm_storage_pool.rb           |    5 +
 src/app/models/storage_volume_task.rb        |    3 +-
 src/app/views/storage/_lvm_volume_form.rhtml |   19 +++
 src/app/views/storage/new_lvm_volume.rhtml   |   42 ++++++
 src/app/views/storage/show.rhtml             |   63 +++++----
 src/app/views/storage/show_volume.rhtml      |  169 +++++++++++++++++-------
 9 files changed, 404 insertions(+), 84 deletions(-)
 create mode 100644 src/app/views/storage/_lvm_volume_form.rhtml
 create mode 100644 src/app/views/storage/new_lvm_volume.rhtml

diff --git a/src/app/controllers/hardware_controller.rb b/src/app/controllers/hardware_controller.rb
index 4f24cb3..8c26184 100644
--- a/src/app/controllers/hardware_controller.rb
+++ b/src/app/controllers/hardware_controller.rb
@@ -117,7 +117,8 @@ class HardwareController < PoolController
   def show_tasks
     @task_types = [["VM Task", "VmTask"],
                    ["Host Task", "HostTask"],
-                   ["Storage Task", "StorageTask", "break"],
+                   ["Storage Task", "StorageTask"],
+                   ["Storage Volume Task", "StorageVolumeTask", "break"],
                    ["Show All", ""]]
     super
   end
@@ -162,7 +163,7 @@ class HardwareController < PoolController
     if params[:id]
       pre_show
       storage_pools = @pool.storage_pools
-      find_opts = {}
+      find_opts = {:conditions => "type != 'LvmStoragePool'"}
       include_pool = false
     else
       # FIXME: no permissions or usage checks here yet
diff --git a/src/app/controllers/storage_controller.rb b/src/app/controllers/storage_controller.rb
index fe524f3..75058cd 100644
--- a/src/app/controllers/storage_controller.rb
+++ b/src/app/controllers/storage_controller.rb
@@ -25,6 +25,7 @@ class StorageController < ApplicationController
   before_filter :pre_pool_admin, :only => [:refresh]
   before_filter :pre_new2, :only => [:new2]
   before_filter :pre_json, :only => [:storage_volumes_json]
+  before_filter :pre_create_volume, :only => [:create_volume]
 
   def index
     list
@@ -90,15 +91,25 @@ class StorageController < ApplicationController
       flash[:notice] = 'You do not have permission to view this storage pool: redirecting to top level'
       redirect_to :controller => 'dashboard'
     end
-    json_list(@storage_pool.storage_volumes, 
-              [:display_name, :size_in_gb, :get_type_label])
+    attr_list = []
+    attr_list << :id if (@storage_pool.user_subdividable and @can_modify)
+    attr_list += [:display_name, :size_in_gb, :get_type_label]
+    json_list(@storage_pool.storage_volumes, attr_list)
   end
   def show_volume
     @storage_volume = StorageVolume.find(params[:id])
     set_perms(@storage_volume.storage_pool.hardware_pool)
     unless @can_view
       flash[:notice] = 'You do not have permission to view this storage volume: redirecting to top level'
-      redirect_to :controller => 'dashboard'
+      respond_to do |format|
+        format.html { redirect_to :controller => 'dashboard' }
+        format.xml { head :forbidden }
+      end
+    else
+      respond_to do |format|
+        format.html { render :layout => 'popup' }
+        format.xml { render :xml => @storage_volume.to_xml }
+      end
     end
   end
 
@@ -110,6 +121,70 @@ class StorageController < ApplicationController
     render :layout => false
   end
 
+  def new_volume
+    new_volume_internal(StoragePool.find(params[:storage_pool_id]),
+                        { :storage_pool_id => params[:storage_pool_id]})
+    render :layout => 'popup'
+  end
+
+  def new_lvm_volume
+    @source_volume = StorageVolume.find(params[:source_volume_id])
+    @return_facebox = params[:return_facebox]
+    unless @source_volume.supports_lvm_subdivision
+      #fixme: proper error page for popups
+      redirect_to :controller => 'dashboard'
+      return
+    end
+    lvm_pool = @source_volume.lvm_storage_pool
+    unless lvm_pool
+      # FIXME: what should we do about VG/LV names?
+      # for now auto-create VG name as ovirt_vg_#{@source_volume.id}
+      lvm_pool = LvmStoragePool.new(:vg_name => "ovirt_vg_#{@source_volume.id}",
+              :hardware_pool_id => @source_volume.storage_pool.hardware_pool_id)
+      lvm_pool.source_volumes << @source_volume
+      lvm_pool.save!
+    end
+    new_volume_internal(lvm_pool, { :storage_pool_id => lvm_pool.id})
+    @storage_volume.lv_owner_perms='0744'
+    @storage_volume.lv_group_perms='0744'
+    @storage_volume.lv_mode_perms='0744'
+    render :layout => 'popup'
+  end
+
+  def create_volume
+    begin
+      StorageVolume.transaction do
+        @storage_volume.save!
+        @task = StorageVolumeTask.new({ :user        => @user,
+                              :task_target => @storage_volume,
+                              :action      => StorageVolumeTask::ACTION_CREATE_VOLUME,
+                              :state       => Task::STATE_QUEUED})
+        @task.save!
+      end
+      respond_to do |format|
+        format.json { render :json => { :object => "storage_volume",
+            :success => true,
+            :alert => "Storage Volume was successfully created." } }
+        format.xml { render :xml => @storage_volume,
+            :status => :created,
+            # FIXME: create storage_volume_url method if relevant
+            :location => storage_pool_url(@storage_volume)
+        }
+      end
+    rescue => ex
+      # FIXME: need to distinguish volume vs. task save errors
+      respond_to do |format|
+        format.json {
+          json_hash = { :object => "storage_volume", :success => false,
+            :errors => @storage_volume.errors.localize_error_messages.to_a  }
+          json_hash[:message] = ex.message if json_hash[:errors].empty?
+          render :json => json_hash }
+        format.xml { render :xml => @storage_volume.errors,
+          :status => :unprocessable_entity }
+      end
+    end
+  end
+
   def insert_refresh_task
     @task = StorageTask.new({ :user        => @user,
                               :task_target => @storage_pool,
@@ -244,6 +319,67 @@ class StorageController < ApplicationController
     end
   end
 
+  def delete_volumes
+    storage_volume_ids_str = params[:storage_volume_ids]
+    storage_volume_ids = storage_volume_ids_str.split(",").collect {|x| x.to_i}
+    alerts = []
+    status = true
+    begin
+      StorageVolume.transaction do
+        storage = StorageVolume.find(:all, :conditions => "id in (#{storage_volume_ids.join(', ')})")
+        unless storage.empty?
+          set_perms(storage[0].storage_pool.hardware_pool)
+          unless @can_modify and storage[0].storage_pool.user_subdividable
+            respond_to do |format|
+              format.json { render :json => { :object => "storage_volume",
+                  :success => false,
+                  :alert => "You do not have permission to delete this storage volume." } }
+              format.xml { head :forbidden }
+            end
+          else
+            storage.each do |storage_volume|
+              alert, success = delete_volume_internal(storage_volume)
+              alerts << alert
+              status = false unless success
+            end
+            respond_to do |format|
+              format.json { render :json => { :object => "storage_volume",
+                  :success => status, :alert => alerts.join("\n") } }
+              format.xml { head(status ? :ok : :method_not_allowed) }
+            end
+          end
+        else
+          respond_to do |format|
+            format.json { render :json => { :object => "storage_volume",
+                :success => false, :alert => "no volumes selected" } }
+            format.xml { head(status ? :ok : :method_not_allowed) }
+          end
+        end
+      end
+    end
+  end
+
+  def delete_volume
+    @storage_volume = StorageVolume.find(params[:id])
+    set_perms(@storage_volume.storage_pool.hardware_pool)
+    unless @can_modify and @storage_volume.storage_pool.user_subdividable
+      respond_to do |format|
+        format.json { render :json => { :object => "storage_volume",
+            :success => false,
+            :alert => "You do not have permission to delete this storage volume." } }
+        format.xml { head :forbidden }
+      end
+    else
+      alert, success = delete_volume_internal(@storage_volume)
+      respond_to do |format|
+        format.json { render :json => { :object => "storage_volume",
+            :success => success, :alert => alert } }
+        format.xml { head(success ? :ok : :method_not_allowed) }
+      end
+    end
+
+  end
+
   def pre_new
     @hardware_pool = HardwarePool.find(params[:hardware_pool_id])
     @perm_obj = @hardware_pool
@@ -274,6 +410,16 @@ class StorageController < ApplicationController
     @perm_obj = @storage_pool.hardware_pool
     @redir_obj = @storage_pool
   end
+  def pre_create_volume
+    volume = params[:storage_volume]
+    unless type = params[:storage_type]
+      type = volume.delete(:storage_type)
+    end
+    @storage_volume = StorageVolume.factory(type, volume)
+    @perm_obj = @storage_volume.storage_pool.hardware_pool
+    @redir_controller = @storage_volume.storage_pool.hardware_pool.get_controller
+    authorize_admin
+  end
   def pre_json
     pre_show
   end
@@ -282,4 +428,32 @@ class StorageController < ApplicationController
     authorize_admin
   end
 
+  private
+  def new_volume_internal(storage_pool, new_params)
+    @storage_volume = StorageVolume.factory(storage_pool.get_type_label, new_params)
+    @perm_obj = @storage_volume.storage_pool.hardware_pool
+    authorize_admin
+  end
+
+  def delete_volume_internal(volume)
+    begin
+      name = volume.display_name
+      if !volume.vms.empty?
+        vm_list = volume.vms.collect {|vm| vm.description}.join(", ")
+        ["Storage Volume #{name} must be unattached from VMs (#{vm_list}) before deleting it.",
+         false]
+        #FIXME: create delete volume task. include metadata in task
+      else
+        #FIXME: need to set volume to 'unavailable' state once we have states
+        @task = StorageVolumeTask.new({ :user        => @user,
+                              :task_target => volume,
+                              :action      => StorageVolumeTask::ACTION_DELETE_VOLUME,
+                              :state       => Task::STATE_QUEUED})
+        @task.save!
+        ["Storage Volume #{name} deletion was successfully queued.", true]
+      end
+    rescue => ex
+      ["Failed to delete storage volume #{name} (#{ex.message}.",false]
+    end
+  end
 end
diff --git a/src/app/controllers/task_controller.rb b/src/app/controllers/task_controller.rb
index 73e5155..647d69c 100644
--- a/src/app/controllers/task_controller.rb
+++ b/src/app/controllers/task_controller.rb
@@ -24,6 +24,8 @@ class TaskController < ApplicationController
       set_perms(@task.vm.vm_resource_pool)
     elsif @task[:type] == StorageTask.name 
       set_perms(@task.storage_pool.hardware_pool)
+    elsif @task[:type] == StorageVolumeTask.name
+      set_perms(@task.storage_volume.storage_pool.hardware_pool)
     elsif @task[:type] == HostTask.name 
       set_perms(@task.host.hardware_pool)
     end
diff --git a/src/app/models/lvm_storage_pool.rb b/src/app/models/lvm_storage_pool.rb
index 08b8938..84fbb28 100644
--- a/src/app/models/lvm_storage_pool.rb
+++ b/src/app/models/lvm_storage_pool.rb
@@ -44,5 +44,10 @@ class LvmStoragePool < StoragePool
     kb_to_gb(size)
   end
 
+  # FIXME: needs to take free space into account here
+  def user_subdividable
+    true
+  end
+
 
 end
diff --git a/src/app/models/storage_volume_task.rb b/src/app/models/storage_volume_task.rb
index 78f2895..136f1ba 100644
--- a/src/app/models/storage_volume_task.rb
+++ b/src/app/models/storage_volume_task.rb
@@ -20,7 +20,7 @@
 class StorageVolumeTask < Task
 
   ACTION_CREATE_VOLUME = "create_volume"
-  ACTION_EDIT_VOLUME = "edit_volume"
+  ACTION_DELETE_VOLUME = "delete_volume"
 
   def after_initialize
     self.hardware_pool = task_target.storage_pool.hardware_pool if self.task_target_type=="StorageVolume"
@@ -29,7 +29,6 @@ class StorageVolumeTask < Task
   def task_obj
     "StorageVolume;;;#{self.storage_volume.id};;;#{self.storage_volume.display_name}"
   end
-  end
   def host
     nil
   end
diff --git a/src/app/views/storage/_lvm_volume_form.rhtml b/src/app/views/storage/_lvm_volume_form.rhtml
new file mode 100644
index 0000000..823158e
--- /dev/null
+++ b/src/app/views/storage/_lvm_volume_form.rhtml
@@ -0,0 +1,19 @@
+<%= error_messages_for 'storage_volume' %>
+
+<!--[form:storage_pool]-->
+<%= hidden_field 'storage_volume', 'storage_pool_id'  %>
+<%= hidden_field_tag 'storage_type', @storage_volume.get_type_label  %>
+
+<%= text_field_with_label "Size (GB):", 'storage_volume', 'size_in_gb'  %>
+
+<%= text_field_with_label "LV Name:", 'storage_volume', 'lv_name' %>
+
+<%= text_field_with_label "Owner permissions:", 'storage_volume', 'lv_owner_perms' %>
+
+<%= text_field_with_label "Group permissions:", 'storage_volume', 'lv_group_perms' %>
+
+<%= text_field_with_label "Mode permissions:", 'storage_volume', 'lv_mode_perms' %>
+
+
+<!--[eoform:storage_volume]-->
+
diff --git a/src/app/views/storage/new_lvm_volume.rhtml b/src/app/views/storage/new_lvm_volume.rhtml
new file mode 100644
index 0000000..ea51cc5
--- /dev/null
+++ b/src/app/views/storage/new_lvm_volume.rhtml
@@ -0,0 +1,42 @@
+<%- content_for :title do -%>
+  <%= _("Add New LVM Volume") %>
+<%- end -%>
+<%- content_for :description do -%>
+  Add a new LVM Storage Volume to <%= @source_volume.display_name %>.
+<%- end -%>
+<div class="panel_header"></div>
+<div class="dialog_form">
+<form method="POST" action="<%= url_for :action => 'create_volume' %>" id="lvm_volume_form" >
+  <div class="dialog_form">
+    <div id="new_storage_pool">
+      <%= render :partial => 'lvm_volume_form' %>
+    </div>
+  </div>
+  <!-- FIXME: need to pop up the details dialog again -->
+  <%= popup_footer("$('#lvm_volume_form').submit()", "New LVM Volume") %>
+</form>
+</div>
+<script type="text/javascript">
+function afterLvmVolume(response, status){
+    ajax_validation(response, status);
+    if (response.success) {
+    <% if @return_facebox %>
+      $('#window').fadeOut('fast');
+      $("#window").empty().load("<%= @return_facebox %>")
+      $('#window').fadeIn('fast');
+    <% else %>
+      $(document).trigger('close.facebox');
+    <% end %>
+    }
+}
+$(function() {
+    var lvmvolumeoptions = {
+        target:        '<%= url_for :action => 'create_volume' %>',   // target element to update
+	dataType:      'json',
+        success:       afterLvmVolume  // post-submit callback
+    };
+
+    // bind form using 'ajaxForm'
+    $('#lvm_volume_form').ajaxForm(lvmvolumeoptions);
+});
+</script>
diff --git a/src/app/views/storage/show.rhtml b/src/app/views/storage/show.rhtml
index 82c9dab..a84dc62 100644
--- a/src/app/views/storage/show.rhtml
+++ b/src/app/views/storage/show.rhtml
@@ -18,24 +18,24 @@
 
     <div id="storage_selection_id" style="display:none"><%= @storage_pool.id %></div>
     <div class="selection_key">
-        IP address: </br>
+        IP address:<br/>
         <% if @storage_pool[:type] == "IscsiStoragePool" %>
-          Port:       </br>
-          Target:     </br>
+          Port:<br/>
+          Target:<br/>
         <% elsif @storage_pool[:type] == "NfsStoragePool" %>
-          Export path:</br>
+          Export path:<br/>
         <% end %>
-        Type:       </br>
+        Type:<br/>
     </div>
     <div class="selection_value">
-        <%=h @storage_pool.ip_addr %></br>
+        <%=h @storage_pool.ip_addr %><br/>
         <% if @storage_pool[:type] == "IscsiStoragePool" %>
-          <%=h @storage_pool.port %></br>
-          <%=h @storage_pool.target %></br>
+          <%=h @storage_pool.port %><br/>
+          <%=h @storage_pool.target %><br/>
         <% elsif @storage_pool[:type] == "NfsStoragePool" %>
-          <%=h @storage_pool.export_path %></br>
+          <%=h @storage_pool.export_path %><br/>
         <% end %>
-        <%=h @storage_pool.get_type_label %></br>
+        <%=h @storage_pool.get_type_label %><br/>
     </div>
 <%- content_for :right do -%>
   <div class="selection_right_title">Volumes</div>
@@ -54,24 +54,33 @@
 
 <%= confirmation_dialog("confirm_delete_storage", "Are you sure?", "delete_storage_pool()") %>
 <script type="text/javascript">
-	$("#storage_volumes_grid").flexigrid
-	(
-	{
-	url: '<%=  url_for :action => "storage_volumes_json", :id => @storage_pool.id %>',
-	dataType: 'json',
-	colModel : [
-		{display: 'Alias', name : 'display_name', width : 180, sortable : false, align: 'left'},
-	        {display: 'Size (Gb)', name : 'size', width : 80, sortable : true, align: 'left'},
-		{display: 'Type', name : 'type', width : 80, sortable : true, align: 'left'}
-		],
-	sortname: "size",
-	sortorder: "desc",
-	usepager: false,
-	useRp: true,
-	rp: 40,
-	showTableToggleBtn: true,
-	}
+    $("#storage_volumes_grid").flexigrid
+    (
+    {
+    url: '<%=  url_for :action => "storage_volumes_json", :id => @storage_pool.id %>',
+    dataType: 'json',
+    colModel : [
+        <%= "{display: '', width : 20, align: 'left', process: storage_volumes_gridcheckbox}," if (@storage_pool.user_subdividable and @can_modify) %>
+        {display: 'Alias', width : 180, sortable : false, align: 'left', process: storage_volume_details_link},
+        {display: 'Size (Gb)', name : 'size', width : 80, sortable : true, align: 'left'},
+        {display: 'Type', name : 'type', width : 80, sortable : true, align: 'left'}
+        ],
+    sortname: "size",
+    sortorder: "desc",
+    usepager: false,
+    useRp: true,
+    rp: 40,
+    showTableToggleBtn: true,
+    }
 	);   
+    function storage_volumes_gridcheckbox(celDiv)
+    {
+        $(celDiv).html('<input class="grid_checkbox" type="checkbox" name="grid_checkbox'+$(celDiv).html()+'" value="'+$(celDiv).html()+'"/>');
+    }
+    function storage_volume_details_link(celDiv,pid)
+    {
+        $(celDiv).html('<a href="<%= url_for :controller => 'storage', :action => 'show_volume' %>/'+ pid +'" rel="facebox[.bolder]">' + $(celDiv).html() + '</a>');
+    }
 </script>
 <script type="text/javascript">
       
diff --git a/src/app/views/storage/show_volume.rhtml b/src/app/views/storage/show_volume.rhtml
index 9aeb808..e39c10e 100644
--- a/src/app/views/storage/show_volume.rhtml
+++ b/src/app/views/storage/show_volume.rhtml
@@ -1,54 +1,123 @@
-    <div id="data">
-      <div class="inside">
-
-          <div id="dataTableWrapper">
-
-          <div class="dataTable">
-              <div class="inside">
-
-                <div class="data-table-column">
+<%- content_for :title do -%>
+  <%=h @storage_volume.display_name %>
+<%- end -%>
+<%- content_for :description do -%>
+  Details for Storage Volume <%=h @storage_volume.display_name %>
+<%- end -%>
 
-                <p><b>IP address:</b> <%=h @storage_volume.storage_pool.ip_addr %></p>
-<% if @storage_volume.storage_pool[:type] == "IscsiStoragePool" %>
-                <p><b>Port:</b>       <%=h @storage_volume.storage_pool.port %></p>
-                <p><b>Target:</b>     <%=h @storage_volume.storage_pool[:target] %></p>
-<% elsif @storage_volume.storage_pool[:type] == "NfsStoragePool" %>
-                <p><b>Export path:</b> <%=h @storage_volume.storage_pool.export_path %></p>
-<% end %>
-                <p><b>Type:</b>       <%=h @storage_volume.storage_pool.get_type_label %></p>
-		<p></p>
-                <p><b>Path:</b>       <%=h @storage_volume.path %></p>
-<% if @storage_volume[:type] == "IscsiStorageVolume" %>
-                <p><b>LUN:</b>        <%=h @storage_volume.lun %></p>
-<% elsif @storage_volume[:type] == "NfsStorageVolume" %>
-                <p><b>Filename:</b>        <%=h @storage_volume.filename %></p>
+<% if @storage_volume.supports_lvm_subdivision %>
+  <div id="dialog-content-area">
+    <div id="toolbar_nav">
+      <ul>
+        <li><a href="#" id="new_lvm_volume_button"><%=image_tag "icon_addstorage.png", :style=>"vertical-align:middle;" %>Add</a></li>
+        <% if (@storage_volume.lvm_storage_pool and
+               !@storage_volume.lvm_storage_pool.storage_volumes.empty?) %>
+          <li><a href="#" onClick="return remove_lvm_volumes();"><%=image_tag "icon_remove.png" %>  Remove</a></li>
+        <% end %>
+      </ul>
+     </div>
+   </div>
 <% end %>
-                <p><b>Size:</b>       <%=h @storage_volume.size_in_gb %> GB</p>
-
-                </div>
-
-              </div> <!-- end #data-table.inside -->
-            </div> <!-- end #dataTable -->
-
-          </div> <!-- end #dataTableWrapper -->
-
-      </div> <!-- end #data.inside -->
-      </div> <!-- end #data -->
-
-  </td>
-  <td id="right">
-    <div class="heading"> </div>
-    <div id="tools">
-    <h3>Actions</h3>
-    <%if @can_modify -%>
-    <% end -%>
-    <div class="actions">
-      <%= link_to "Back to #{@storage_volume.storage_pool.ip_addr}: #{@storage_volume.storage_pool[:target]}", { :action => 'show', :id => @storage_volume.storage_pool.id }, { :class => "" } %>
-    </div>
+<div class="panel_header"></div>
+  <div class="selection_key">
+    IP address:<br/>
+    <% if @storage_volume.storage_pool[:type] == "IscsiStoragePool" %>
+      Port:<br/>
+      Target:<br/>
+    <% elsif @storage_volume.storage_pool[:type] == "NfsStoragePool" %>
+      Export path:<br/>
+    <% end %>
+    Type:<br/>
+    Path:<br/>
+    <% if @storage_volume[:type] == "IscsiStorageVolume" %>
+      LUN:<br/>
+    <% elsif @storage_volume[:type] == "NfsStorageVolume" %>
+      Filename:<br/>
+    <% end %>
+    Size:<br/>
   </div>
+  <div class="selection_value">
+    <%=h @storage_volume.storage_pool.ip_addr %><br/>
+    <% if @storage_volume.storage_pool[:type] == "IscsiStoragePool" %>
+      <%=h @storage_volume.storage_pool.port %><br/>
+      <%=h @storage_volume.storage_pool[:target] %><br/>
+    <% elsif @storage_volume.storage_pool[:type] == "NfsStoragePool" %>
+      <%=h @storage_volume.storage_pool.export_path %><br/>
+    <% end %>
+    <%=h @storage_volume.storage_pool.get_type_label %><br/>
+    <%=h @storage_volume.path %><br/>
+    <% if @storage_volume[:type] == "IscsiStorageVolume" %>
+      <%=h @storage_volume.lun %><br/>
+    <% elsif @storage_volume[:type] == "NfsStorageVolume" %>
+      <%=h @storage_volume.filename %><br/>
+    <% end %>
+    <%=h @storage_volume.size_in_gb %> GB<br/>
+  </div>
+<% if @storage_volume.supports_lvm_subdivision %>
+  <div class="dialog_form">
+    <div class="form_heading">LVM Volumes</div>
+    <% if @storage_volume.lvm_storage_pool %>
+      <form id="lvm_storage_volumes_grid_form">
+        <table id="lvm_storage_volumes_grid" style="display:none"></table>
+      </form>
+    <% end %>
+  </div>
+<% end %>
 
-  </td>
-
-<%- content_for :title do -%>
-<%= _("Storage Volume") %>
-<%- end -%>
+<div class="facebox_timfooter">
+        <div class="button">
+          <div class="button_left_grey"></div>
+          <div class="button_middle_grey"><a href="#" onclick="jQuery(document).trigger('close.facebox')">Close</a></div>
+          <div class="button_right_grey"></div>
+        </div>
+</div>
+<script type="text/javascript">
+    $("#lvm_storage_volumes_grid").flexigrid
+    (
+    {
+    url: '<%=  url_for :action => "storage_volumes_json", :id => @storage_volume.lvm_storage_pool.id %>',
+    dataType: 'json',
+    colModel : [
+        <%= "{display: '', width : 20, align: 'left', process: lvm_storage_volumes_gridcheckbox}," if @can_modify %>
+        {display: 'Alias', width : 180, sortable : false, align: 'left'},
+        {display: 'Size (Gb)', name : 'size', width : 80, sortable : true, align: 'left'},
+        {display: 'Type', name : 'type', width : 80, sortable : true, align: 'left'}
+        ],
+    sortname: "size",
+    sortorder: "desc",
+    usepager: false,
+    useRp: true,
+    rp: 40,
+    showTableToggleBtn: true,
+    }
+    );
+    function lvm_storage_volumes_gridcheckbox(celDiv)
+    {
+        $(celDiv).html('<input class="grid_checkbox" type="checkbox" name="grid_checkbox'+$(celDiv).html()+'" value="'+$(celDiv).html()+'"/>');
+    }
+  function get_selected_lvm_volumes()
+  {
+    return get_selected_checkboxes("lvm_storage_volumes_grid_form");
+  }
+  function remove_lvm_volumes()
+  {
+    var volumes = get_selected_lvm_volumes();
+    if (validate_selected(volumes, "storage volume")) {
+      $.post('<%= url_for :controller => "storage", :action => "delete_volumes" %>',
+             { storage_volume_ids: volumes.toString() },
+              function(data,status){
+                $("#lvm_storage_volumes_grid").flexReload();
+		if (data.alert) {
+		  $.jGrowl(data.alert);
+                }
+               }, 'json');
+    }
+  }
+$('#new_lvm_volume_button').click(function(){
+		$('#window').fadeOut('fast');
+        $("#window").empty().load("<%= url_for :controller => 'storage', :action => 'new_lvm_volume' %>",
+	{ source_volume_id: <%=@storage_volume.id%>,
+          return_facebox: '<%= url_for :controller => 'storage', :action => 'show_volume', :id => @storage_volume.id %>' });
+		$('#window').fadeIn('fast');
+});
+</script>
-- 
1.5.5.1




More information about the ovirt-devel mailing list