From: Jan Provaznik <jprov...@redhat.com> TBD: - add template group on page 5130 - TEMPLATE_* permissions - after reworked pool views will be pushed, I'll remove also _instances.haml partial (is now referenced by pool) --- src/app/controllers/instance_controller.rb | 131 ++++++++++----------- src/app/views/instance/configure.haml | 23 ++++ src/app/views/instance/index.haml | 49 ++++++++- src/app/views/instance/new.haml | 92 +++------------ src/app/views/instance/select_template.haml | 5 - src/app/views/instance/show.haml | 105 +++++++---------- src/db/migrate/20090804142049_create_instances.rb | 1 + 7 files changed, 193 insertions(+), 213 deletions(-) create mode 100644 src/app/views/instance/configure.haml delete mode 100644 src/app/views/instance/select_template.haml
diff --git a/src/app/controllers/instance_controller.rb b/src/app/controllers/instance_controller.rb index e5e339c..c82d378 100644 --- a/src/app/controllers/instance_controller.rb +++ b/src/app/controllers/instance_controller.rb @@ -33,84 +33,59 @@ class InstanceController < ApplicationController require_privilege(Privilege::INSTANCE_VIEW) @pools = Pool.list_for_user(@current_user, Privilege::INSTANCE_MODIFY) - @order_dir = params[:order_dir] == 'desc' ? 'desc' : 'asc' - @order = params[:order] || 'name' - @instances = Instance.search_filter(params[:search], Instance::SEARCHABLE_COLUMNS).paginate( - :page => params[:page] || 1, - :order => @order + ' ' + @order_dir - ) - if request.xhr? and params[:partial] - render :partial => 'instances' - return + @order_dir = params[:order_dir] == 'desc' ? 'desc' : 'asc' + @order_field = params[:order_field] || 'name' + + # we can't use pool.instances, because we need custom sorting + @sorted_instances_by_pool = {} + Instance.find( + :all, + :include => [:template, :hardware_profile, :owner, :pool], + :order => @order_field + ' ' + @order_dir + ).each do |inst| + pool_id = inst.pool.id + next unless @pools.find {|p| p.id == pool_id} + (@sorted_instances_by_pool[pool_id] ||= []) << inst end end - def select_template - if params[:select] - redirect_to :action => 'new', 'instance[template_id]' => (params[:ids] || []).first - end + def show + @instance = Instance.find(params[:id]) + require_privilege(Privilege::INSTANCE_VIEW, @instance.pool) + end - # FIXME: replace by template_view priv - require_privilege(Privilege::IMAGE_VIEW) - @order_dir = params[:order_dir] == 'desc' ? 'desc' : 'asc' - @order = "templates.#{params[:order] || 'name'}" + def new + @instance = Instance.new(params[:instance]) + require_privilege(Privilege::INSTANCE_MODIFY, @instance.pool) if @instance.pool + # FIXME: we need to list only templates for particular user, + # => TODO: add TEMPLATE_* permissions @templates = Template.paginate( :page => params[:page] || 1, - :order => @order + ' ' + @order_dir, :include => {:images => :replicated_images}, :conditions => "replicated_images.uploaded = 't'" ) - #:include => {:images => :replicated_images}, :conditions => "replicated_images.uploaded = 'f'" - @single_select = true - - if request.xhr? and params[:partial] - render :partial => 'templates/templates' - return - end - end - - ## Right now this is essentially a duplicate of PoolController#show, - # # but really it should be a single instance should we decide to have a page - # # for that. Redirect on create was all that brought you here anyway, so - # # should be unused for the moment. - #def show - # require_privilege(Privilege::INSTANCE_VIEW,@pool) - # @pool = Pool.find(params[:id]) - # @order_dir = params[:order_dir] == 'desc' ? 'desc' : 'asc' - # @order = params[:order] || 'name' - # @instances = Instance.search_filter(params[:search], Instance::SEARCHABLE_COLUMNS).paginate( - # :page => params[:page] || 1, - # :order => @order + ' ' + @order_dir, - # :conditions => {:pool_id => @pool.id} - # ) - # if request.xhr? and params[:partial] - # render :partial => 'instances' - # return - # end - #end - - def show - @instance = Instance.find(params[:id]) end - def new + def configure @instance = Instance.new(params[:instance]) - require_privilege(Privilege::INSTANCE_MODIFY, @instance.pool) if @instance.pool - @pools = Pool.list_for_user(@current_user, Privilege::INSTANCE_MODIFY) - # FIXME: what error msg to show if no pool is selected and the user has - # permission on none? - @instance.pool = @pools[0] if (@instance.pool.nil? and (@pools.size == 1)) + require_privilege(Privilege::INSTANCE_MODIFY, @instance.pool) end def create + if params[:cancel] + redirect_to :action => 'new' + return + end + @instance = Instance.new(params[:instance]) @instance.state = Instance::STATE_NEW @instance.owner_id = current_user + require_privilege(Privilege::INSTANCE_MODIFY, Pool.find(@instance.pool_id)) #FIXME: This should probably be in a transaction - if @instance.save + if @instance.save! @task = InstanceTask.new({:user => current_user, :task_target => @instance, @@ -118,27 +93,48 @@ class InstanceController < ApplicationController if @task.save condormatic_instance_create(@task) flash[:notice] = "Instance added." - redirect_to :controller => "pool", :action => 'show', :id => @instance.pool_id + redirect_to :action => 'index' else @pool = @instance.pool - render :action => 'new' + render :action => 'configure' end else - @pool = Pool.find(@instance.pool_id) - render :action => 'new' + #...@pool = Pool.find(@instance.pool_id) + @hardware_profiles = HardwareProfile.all + render :action => 'configure' end end def instance_action - action = params[:instance_action] - action_args = params[:action_data] - @instance = Instance.find(params[:id]) + params.keys.each do |param| + if param =~ /^launch_instance_(\d+)$/ + redirect_to :action => 'new', 'instance[pool_id]' => $1 + return + end + end + + @instance = Instance.find((params[:id] || []).first) require_privilege(Privilege::INSTANCE_CONTROL,@instance.pool) + + if params[:instance_details] + render :action => 'show' + return + end + + # action list will be longer (restart, start, stop..) + action = if params[:shutdown] + 'stop' + #elsif params[:restart] + # 'restart' + end + unless @instance.valid_action?(action) - raise ActionError.new("#{action} is an invalid action.") + raise ActionError.new("'#{action}' is an invalid action.") end + + # not sure if task is used as everything goes through condor #permissons check here - @task = @instance.queue_action(@current_user, action, action_args) + @task = @instance.queue_action(@current_user, action) unless @task raise ActionError.new("#{action} cannot be performed on this instance.") end @@ -154,9 +150,8 @@ class InstanceController < ApplicationController raise ActionError.new("Sorry, action '#{action}' is currently not supported by condor backend.") end - alert = "#...@instance.name}: #{action} was successfully queued." - flash[:notice] = alert - redirect_to :controller => "pool", :action => 'show', :id => @instance.pool_id + flash[:notice] = "#...@instance.name}: #{action} was successfully queued." + redirect_to :action => 'index' end def delete diff --git a/src/app/views/instance/configure.haml b/src/app/views/instance/configure.haml new file mode 100644 index 0000000..95efffc --- /dev/null +++ b/src/app/views/instance/configure.haml @@ -0,0 +1,23 @@ +%h2 Launch instance +- form_for @instance, :url => {:action => 'create'} do + = hidden_field :instance, :template_id + = hidden_field :instance, :pool_id + %ul + %li + = label :instance, :name + = text_field :instance, :name + %li + = label :instance, :template + = text_field_tag :template_name, @instance.template ? @instance.template.name : '', :disabled => true + %li + = label :instance, :pool + = text_field_tag :pool_name, @instance.pool ? @instance.pool.name : '', :disabled => true + %li + = label :instance, :hardware_profile + = select :instance, :hardware_profile_id, @instance.pool.hardware_profiles.map {|p| [ p.name, p.id ]}, { :include_blank => true } + %li + = label :instance, :realm + = select :instance, :realm_id, @instance.pool.realms, { :include_blank => true } + + = submit_tag 'Cancel', :name => 'cancel' + = submit_tag 'Launch', :name => 'launch' diff --git a/src/app/views/instance/index.haml b/src/app/views/instance/index.haml index fa8a917..73782db 100644 --- a/src/app/views/instance/index.haml +++ b/src/app/views/instance/index.haml @@ -1 +1,48 @@ -= render :partial => 'instance/instances' +- columns = [ | + {:name => '', :sortable => false}, | + {:name => 'STATUS', :sortable => false}, | + {:name => 'VM NAME', :sort_attr => 'name'}, | + {:name => 'TYPE', :sort_attr => 'hardware_profiles.name'}, | + {:name => 'TEMPLATE', :sort_attr => 'templates.name'}, | + {:name => 'IP ADDRESS', :sort_attr => 'public_ip_addresses'}, | + {:name => 'PROVIDER', :sortable => false}, | + {:name => 'STARTED BY', :sort_attr => 'users.last_name'}, | +] | + + +%h2 POOL STATUS +TODO (include michal's pool partial) + +%h2 INSTANCES BY POOL +- form_tag(:action => 'instance_action') do + %ul + %li ACTIONS + %li CONTROL INSTANCES + %li= submit_tag "Shutdown", :name => "shutdown" + %hr + %li MANAGE INSTANCES + %li= submit_tag "Instance Details", :name => "instance_details" + - @pools.each do |pool| + %hr + = pool.name + = submit_tag "Launch Instance", :name => "launch_instance_#{pool.id}" + Show All + %table + = sortable_table_header(columns) + %tbody + - if not instances = @sorted_instances_by_pool[pool.id] or instances.empty? + %tr + %td{:colspan => 8} No Instances + - else + - instances.each do |inst| + %tr + %td= check_box_tag 'id[]' + %td + / N/A for all (not supported yet) + %img{:src => '', :alt => 'n/a'} + %td= inst.name + %td= inst.hardware_profile.name + %td= inst.template.name + %td= inst.public_ip_addresses + %td= inst.cloud_account ? inst.cloud_account.provider.name : '' + %td= "#{inst.owner.first_name} #{inst.owner.last_name}" # TODO, there is "started by" in comps pdf, but we don't save this info diff --git a/src/app/views/instance/new.haml b/src/app/views/instance/new.haml index 7942036..71af6d3 100644 --- a/src/app/views/instance/new.haml +++ b/src/app/views/instance/new.haml @@ -1,78 +1,14 @@ -:javascript - $(document).ready(function() { - $(".select_template").click(function() { - var wrapper = $("#select_template_dialog"); - if (wrapper.length == 0) wrapper = $('<div id="select_template_dialog"></div>'); - wrapper.dialog({ - title: "Select template for new instance", - width: 600, - height: 500, - modal: true, - overlay: {opacity: 0.2, background: "black"} - }); - wrapper.load('#{url_for :action => 'select_template'}', null, function() { - $(":submit[name=select]").click(function() { - var checkbox = $("input[name='ids[]']:checked").first(); - var id = checkbox.val(); - if (id !== undefined) { - var name = $(".template_name", checkbox.parent().parent()).text(); - $(".select_template").text(name); - $("input[name='instance[template_id]']").val(id); - } - $("#select_template_dialog").dialog('close'); - return false; - }); - }); - return false; - }); - - $("select[name='instance[pool_id]']").change(function() { - location.href = '#{url_for(:action => "new")}?' + $("#instance_form").serialize(); - }); - }); -.dcloud_form - = error_messages_for 'instance' - %h2 Add a New Instance - %br/ - - form_tag({:action => 'create'}, :id => "instance_form") do - %ul - %li - %label - Name - %span Name for this new Instance - = text_field :instance, :name, :class => "txtfield" - %li - %label - Template - %span Choose a template to use - = link_to(@instance.template ? @instance.template.name : "Select template...", {:action => 'select_template'}, {:class => 'actionlink select_template'}) - %input{:name => "instance[template_id]", :type => "hidden", :value => @instance.template ? @instance.template.id : ''}/ - - if @instance.pool - %input{:name => "instance[pool_id]", :type => "hidden", :value => @instance.pool_id}/ - - if (@pools.size > 1) - %li - %label Pool - = @instance.pool.name - - else - %li - %label - Pool - %span Pick your pool - = select("instance", "pool_id", | - @pools.collect {|p| [ p.name, p.id ] }, | - { :include_blank => true }) | - - if @instance.pool and @instance.pool.hardware_profiles.size > 0 - %li - %label - Hardware Profile - %span Pick your hardware profile - = select("instance", "hardware_profile_id", | - @instance.pool.hardware_profiles.collect {|p| [ p.name, p.id ] }, | - { :include_blank => true }) | - - if @instance.pool and @instance.pool.realms.size > 0 - %li - %label - Realm - %span Choose a realm - = select("instance", "front_end_realm", @instance.pool.realms, { :include_blank => true }) - = submit_tag "Save", :class => "submit" +%h3 Show Templates +%hr +%ul + - @templates.each do |tpl| + %li + - form_tag(:action => 'configure') do + = hidden_field :instance, :template_id, :value => tpl.id + = hidden_field :instance, :pool_id, :value => @instance.pool.id + %img{:src => "/images/platform_#{tpl.platform}.png", :width => '32px', :height => '32px', :alt => tpl.platform} + %h3= tpl.name + %p= tpl.summary + = submit_tag 'Launch', :name => 'launch' += will_paginate(@templates) += page_entries_info(@templates) diff --git a/src/app/views/instance/select_template.haml b/src/app/views/instance/select_template.haml deleted file mode 100644 index b1739cf..0000000 --- a/src/app/views/instance/select_template.haml +++ /dev/null @@ -1,5 +0,0 @@ -- buttons = capture_haml do - .action_buttons - = submit_tag "Select", :name => "select" - -= render :partial => 'templates/templates', :locals => {:footer => buttons} diff --git a/src/app/views/instance/show.haml b/src/app/views/instance/show.haml index d9c0e4c..d90d63e 100644 --- a/src/app/views/instance/show.haml +++ b/src/app/views/instance/show.haml @@ -1,61 +1,44 @@ -%table - %tr - %td :external_key - %td= @instance.external_key - %tr - %td :name - %td= @instance.name - %tr - %td :hardware_profile_id - %td= @instance.hardware_profile_id - %tr - %td :image_id - %td= @instance.image_id - %tr - %td :realm_id - %td= @instance.realm_id - %tr - %td :pool_id - %td= @instance.pool_id - %tr - %td :cloud_account_id - %td= @instance.cloud_account_id - %tr - %td :public_address - %td= @instance.public_address - %tr - %td :private_address - %td= @instance.private_address - %tr - %td :state - %td= @instance.state - %tr - %td :condor_job_id - %td= @instance.condor_job_id - %tr - %td :lock_version - %td= @instance.lock_version - %tr - %td :acc_pending_time - %td= @instance.acc_pending_time - %tr - %td :acc_running_time - %td= @instance.acc_running_time - %tr - %td :acc_shutting_down_time - %td= @instance.acc_shutting_down_time - %tr - %td :acc_stopped_time - %td= @instance.acc_stopped_time - %tr - %td :time_last_pending - %td= @instance.time_last_pending - %tr - %td :time_last_running - %td= @instance.time_last_running - %tr - %td :time_last_shutting_down - %td= @instance.time_last_shutting_down - %tr - %td :time_last_stopped - %td= @instance.time_last_stopped +%h2 Instance Details +- form_tag(:action => 'index') do + %ul + %li + = label_tag :ip_address, 'IP Address' + %span= @instance.public_ip_addresses + %li + = label_tag :operating_system, 'Operating system' + %span= @instance.template.xml.platform + %li + = label_tag :provider, 'Provider' + %span= @instance.cloud_account.provider.name + %li + = label_tag :base_template, 'Base Template' + %span= @instance.template.name + %li + = label_tag :architecture, 'Architecture' + %span= @instance.hardware_profile.architecture.value + %li + = label_tag :memory, 'Memory' + %span= @instance.hardware_profile.memory.value + %li + = label_tag :storage, 'Storage' + %span= @instance.hardware_profile.storage.value + %li + = label_tag :instantiation_time, 'Instantiation Time' + %span= @instance.created_at.strftime("%d-%b-%Y %H:%M:%S") + %li + = label_tag :uptime, 'Uptime' + %span= @instance.state == Instance::STATE_RUNNING ? @instance.total_state_time : 0 # returns 0, when instance is not running + %li + = label_tag :current_alerts, 'Current Alerts' + %span= 0 + %li + = label_tag :console_connection, 'Console Connection' + %span= 'via SSH' + %li + = label_tag :owner, 'Owner' + %span= "#...@instance.owner.first_name} #...@instance.owner.last_name}" + %li + = label_tag :shared_to, 'Shared to' + %span= "N/A" + + = submit_tag 'Back', :name => 'back' diff --git a/src/db/migrate/20090804142049_create_instances.rb b/src/db/migrate/20090804142049_create_instances.rb index bc4ce3a..b485031 100644 --- a/src/db/migrate/20090804142049_create_instances.rb +++ b/src/db/migrate/20090804142049_create_instances.rb @@ -44,6 +44,7 @@ class CreateInstances < ActiveRecord::Migration t.timestamp :time_last_running t.timestamp :time_last_shutting_down t.timestamp :time_last_stopped + t.string :public_ip_addresses t.timestamps end end -- 1.7.2.2 _______________________________________________ deltacloud-devel mailing list deltacloud-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/deltacloud-devel