diff --git a/app/controllers/ems_storage_controller.rb b/app/controllers/ems_storage_controller.rb new file mode 100644 index 00000000000..2e3ed693607 --- /dev/null +++ b/app/controllers/ems_storage_controller.rb @@ -0,0 +1,36 @@ +class EmsStorageController < ApplicationController + include Mixins::GenericListMixin + include Mixins::GenericShowMixin + include EmsCommon + include Mixins::EmsCommonAngular + include Mixins::GenericSessionMixin + + before_action :check_privileges + before_action :get_session_data + after_action :cleanup_action + after_action :set_session_data + + def self.model + ManageIQ::Providers::StorageManager + end + + def self.table_name + @table_name ||= "ems_storage" + end + + def ems_path(*args) + path_hash = {:action => 'show', :id => args[0].id.to_s } + path_hash.merge(args[1]) + end + + def new_ems_path + {:action => 'new'} + end + + def ems_storage_form_fields + ems_form_fields + end + + menu_section :sto + has_custom_buttons +end diff --git a/app/helpers/application_helper/button/ems_storage_timeline.rb b/app/helpers/application_helper/button/ems_storage_timeline.rb new file mode 100644 index 00000000000..24b0885b490 --- /dev/null +++ b/app/helpers/application_helper/button/ems_storage_timeline.rb @@ -0,0 +1,13 @@ +class ApplicationHelper::Button::EmsStorageTimeline < ApplicationHelper::Button::GenericFeatureButton + def calculate_properties + super + self[:hidden] = true unless visible? + end + + def disabled? + unless @record.has_events? || @record.has_events?(:policy_events) + @error_message = _('No Timeline data has been collected for this Storage Manager') + end + @error_message.present? + end +end diff --git a/app/helpers/application_helper/toolbar/ems_storage_center.rb b/app/helpers/application_helper/toolbar/ems_storage_center.rb new file mode 100644 index 00000000000..bd113efa694 --- /dev/null +++ b/app/helpers/application_helper/toolbar/ems_storage_center.rb @@ -0,0 +1,70 @@ +class ApplicationHelper::Toolbar::EmsStorageCenter < ApplicationHelper::Toolbar::Basic + button_group('ems_storage_vmdb', [ + button( + :refresh_server_summary, + 'fa fa-refresh fa-lg', + N_('Refresh this page'), + nil), + select( + :ems_storage_vmdb_choice, + 'fa fa-cog fa-lg', + t = N_('Configuration'), + t, + :items => [ + button( + :ems_storage_refresh, + 'fa fa-refresh fa-lg', + N_('Refresh relationships and power states for all items related to this Storage Manager'), + N_('Refresh Relationships and Power States'), + :confirm => N_("Refresh relationships and power states for all items related to this Storage Manager?")), + separator, + button( + :ems_storage_delete, + 'pficon pficon-delete fa-lg', + t = N_('Remove this Storage Manager from Inventory'), + t, + :url_parms => "&refresh=y", + :confirm => N_("Warning: This Storage Manager and ALL of its components will be permanently removed!")), + ] + ), + ]) + button_group('ems_storage_policy', [ + select( + :ems_storage_policy_choice, + 'fa fa-shield fa-lg', + t = N_('Policy'), + t, + :items => [ + button( + :ems_storage_protect, + 'pficon pficon-edit fa-lg', + N_('Manage Policies for this Storage Manager'), + N_('Manage Policies')), + button( + :ems_storage_tag, + 'pficon pficon-edit fa-lg', + N_('Edit Tags for this Storage Manager'), + N_('Edit Tags')), + ] + ), + ]) + button_group('ems_storage_monitoring', [ + select( + :ems_storage_monitoring_choice, + 'ff ff-monitoring fa-lg', + t = N_('Monitoring'), + t, + :items => [ + button( + :ems_storage_timeline, + 'ff ff-timeline fa-lg', + N_('Show Timelines for this Storage Manager'), + N_('Timelines'), + :options => {:feature => :timeline}, + :klass => ApplicationHelper::Button::EmsStorageTimeline, + :url => "/show", + :url_parms => "?display=timeline"), + ] + ), + ]) +end diff --git a/app/helpers/application_helper/toolbar/ems_storages_center.rb b/app/helpers/application_helper/toolbar/ems_storages_center.rb new file mode 100644 index 00000000000..472bd9a8964 --- /dev/null +++ b/app/helpers/application_helper/toolbar/ems_storages_center.rb @@ -0,0 +1,63 @@ +class ApplicationHelper::Toolbar::EmsStoragesCenter < ApplicationHelper::Toolbar::Basic + button_group('ems_storage_vmdb', [ + select( + :ems_storage_vmdb_choice, + 'fa fa-cog fa-lg', + t = N_('Configuration'), + t, + :items => [ + button( + :ems_storage_refresh, + 'fa fa-refresh fa-lg', + N_('Refresh relationships and power states for all items related to the selected Storage Managers'), + N_('Refresh Relationships and Power States'), + :url_parms => "main_div", + :send_checked => true, + :confirm => N_("Refresh relationships and power states for all items related to the selected Storage Managers?"), + :enabled => false, + :onwhen => "1+"), + separator, + button( + :ems_storage_delete, + 'pficon pficon-delete fa-lg', + N_('Remove selected Storage Managers from Inventory'), + N_('Remove Storage Managers from Inventory'), + :url_parms => "main_div", + :send_checked => true, + :confirm => N_("Warning: The selected Storage Managers and ALL of their components will be permanently removed!"), + :enabled => false, + :onwhen => "1+"), + ] + ), + ]) + button_group('ems_storage_policy', [ + select( + :ems_storage_policy_choice, + 'fa fa-shield fa-lg', + t = N_('Policy'), + t, + :enabled => false, + :onwhen => "1+", + :items => [ + button( + :ems_storage_protect, + 'pficon pficon-edit fa-lg', + N_('Manage Policies for the selected Storage Managers'), + N_('Manage Policies'), + :url_parms => "main_div", + :send_checked => true, + :enabled => false, + :onwhen => "1+"), + button( + :ems_storage_tag, + 'pficon pficon-edit fa-lg', + N_('Edit Tags for the selected Storage Managers'), + N_('Edit Tags'), + :url_parms => "main_div", + :send_checked => true, + :enabled => false, + :onwhen => "1+"), + ] + ), + ]) +end diff --git a/app/helpers/ems_storage_helper.rb b/app/helpers/ems_storage_helper.rb new file mode 100644 index 00000000000..8e99ac78b85 --- /dev/null +++ b/app/helpers/ems_storage_helper.rb @@ -0,0 +1,3 @@ +module EmsStorageHelper + include_concern 'TextualSummary' +end diff --git a/app/helpers/ems_storage_helper/textual_summary.rb b/app/helpers/ems_storage_helper/textual_summary.rb new file mode 100644 index 00000000000..ae14e4c6759 --- /dev/null +++ b/app/helpers/ems_storage_helper/textual_summary.rb @@ -0,0 +1,81 @@ +module EmsStorageHelper::TextualSummary + include TextualMixins::TextualRefreshStatus + # + # Groups + # + + def textual_group_properties + TextualGroup.new(_("Properties"), %i(provider_region hostname ipaddress type port guid)) + end + + def textual_group_relationships + TextualGroup.new( + _("Relationships"), + %i(parent_ems_cloud cloud_volumes cloud_volume_snapshots cloud_volume_backups cloud_object_store_containers) + ) + end + + def textual_group_status + TextualGroup.new(_("Status"), textual_authentications(@record.authentication_for_summary) + %i(refresh_status refresh_date)) + end + + def textual_group_smart_management + TextualTags.new(_("Smart Management"), %i(zone tags)) + end + + def textual_group_topology + end + + # + # Items + # + def textual_provider_region + return nil if @record.provider_region.nil? + {:label => _("Region"), :value => @record.description} + end + + def textual_hostname + @record.hostname + end + + def textual_ipaddress + return nil if @record.ipaddress.blank? + {:label => _("Discovered IP Address"), :value => @record.ipaddress} + end + + def textual_type + {:label => _('Type'), :value => @record.emstype_description} + end + + def textual_port + @record.supports_port? ? {:label => _("API Port"), :value => @record.port} : nil + end + + def textual_guid + {:label => _("Management Engine GUID"), :value => @record.guid} + end + + def textual_parent_ems_cloud + textual_link(@record.try(:parent_manager), :label => _("Parent Cloud Provider")) + end + + def textual_zone + {:label => _("Managed by Zone"), :icon => "pficon pficon-zone", :value => @record.zone.try(:name)} + end + + def textual_cloud_volumes + textual_link(@record.try(:cloud_volumes), :label => _('Cloud Volumes')) + end + + def textual_cloud_volume_snapshots + textual_link(@record.try(:cloud_volume_snapshots), :label => _('Cloud Volume Snapshots')) + end + + def textual_cloud_volume_backups + textual_link(@record.try(:cloud_volume_backups), :label => _('Cloud Volume Backups')) + end + + def textual_cloud_object_store_containers + @record.try(:cloud_object_store_containers) + end +end diff --git a/app/views/ems_storage/edit.html.haml b/app/views/ems_storage/edit.html.haml new file mode 100644 index 00000000000..46288278bb8 --- /dev/null +++ b/app/views/ems_storage/edit.html.haml @@ -0,0 +1,19 @@ +- url = url_for_only_path(:controller => 'ems_storage', :action => 'update', :id => (@ems.id || 'new')) += form_for(@ems, + :url => url, + :method => :post, + :html => {"ng-controller" => "emsCommonFormController", + "name" => "angularForm", + "ng-show" => "afterGet", + "update-url" => url, + "form-fields-url" => "/#{controller_name}/ems_storage_form_fields/", + "novalidate" => true}) do |f| + %input{:type => 'hidden', :id => "form_id", :value => "##{f.options[:html][:id]}"} + %input{:type => 'hidden', :id => "button_name", :name => "button", :value => "save"} + %input{:type => 'hidden', :id => "cred_type", :name => "cred_type", :value => "default"} + = render :partial => "shared/views/ems_common/angular/form" + +:javascript + ManageIQ.angular.app.value('emsCommonFormId', '#{@ems.id || "new"}'); + miq_bootstrap($('#form_id').val()); + diff --git a/app/views/ems_storage/new.html.haml b/app/views/ems_storage/new.html.haml new file mode 100644 index 00000000000..8e5a25eea69 --- /dev/null +++ b/app/views/ems_storage/new.html.haml @@ -0,0 +1,20 @@ +- url = url_for_only_path(:controller => 'ems_storage', :action => 'create', :id => (@ems.id || 'new')) += form_for(@ems, + :url => url, + :method => :post, + :html => {"ng-controller" => "emsCommonFormController", + "name" => "angularForm", + "ng-show" => "afterGet", + "create-url" => url, + "form-fields-url" => "/#{controller_name}/ems_storage_form_fields/", + "novalidate" => true}) do |f| + %input{:type => 'hidden', :id => "form_id", :value => "##{f.options[:html][:id]}"} + %input{:type => 'hidden', :id => "button_name", :name => "button", :value => "add"} + %input{:type => 'hidden', :id => "cred_type", :name => "cred_type", :value => "default"} + + = render :partial => "shared/views/ems_common/angular/form" + +:javascript + ManageIQ.angular.app.value('emsCommonFormId', '#{@ems.id || "new"}'); + miq_bootstrap($('#form_id').val()); + diff --git a/app/views/ems_storage/show_list.html.haml b/app/views/ems_storage/show_list.html.haml new file mode 100644 index 00000000000..eb5845d97d4 --- /dev/null +++ b/app/views/ems_storage/show_list.html.haml @@ -0,0 +1 @@ +#main_div= render :partial => "layouts/gtl" diff --git a/app/views/ems_storage/show_policy_timeline.html.haml b/app/views/ems_storage/show_policy_timeline.html.haml new file mode 100644 index 00000000000..0c644b01556 --- /dev/null +++ b/app/views/ems_storage/show_policy_timeline.html.haml @@ -0,0 +1 @@ +#main_div= render :partial => "layouts/tl_show" diff --git a/spec/controllers/ems_storage_controller_spec.rb b/spec/controllers/ems_storage_controller_spec.rb new file mode 100644 index 00000000000..e68d71943b2 --- /dev/null +++ b/spec/controllers/ems_storage_controller_spec.rb @@ -0,0 +1,5 @@ +describe EmsStorageController do + include_examples :shared_examples_for_ems_storage_controller, %w(openstack) + + it_behaves_like "controller with custom buttons" +end diff --git a/spec/helpers/application_helper/buttons/ems_storage_timeline_spec.rb b/spec/helpers/application_helper/buttons/ems_storage_timeline_spec.rb new file mode 100644 index 00000000000..bd7f19c4850 --- /dev/null +++ b/spec/helpers/application_helper/buttons/ems_storage_timeline_spec.rb @@ -0,0 +1,8 @@ +describe ApplicationHelper::Button::EmsStorageTimeline do + let(:view_context) { setup_view_context_with_sandbox({}) } + let(:record) { FactoryGirl.create(:ext_management_system) } + let(:props) { {:options => {:feature => :timeline}} } + let(:button) { described_class.new(view_context, {}, {'record' => record}, props) } + + it_behaves_like 'a timeline button', :entity => 'Storage Manager' +end diff --git a/spec/routing/ems_storage_routing_spec.rb b/spec/routing/ems_storage_routing_spec.rb new file mode 100644 index 00000000000..118f0dfdee5 --- /dev/null +++ b/spec/routing/ems_storage_routing_spec.rb @@ -0,0 +1,53 @@ +require "routing/shared_examples" + +describe EmsStorageController do + let(:controller_name) { "ems_storage" } + + it_behaves_like "A controller that has compare routes" + it_behaves_like "A controller that has dialog runner routes" + it_behaves_like "A controller that has download_data routes" + it_behaves_like "A controller that has policy protect routes" + it_behaves_like "A controller that has tagging routes" + it_behaves_like "A controller that has timeline routes" + + %w( + dialog_load + ems_storage_form_fields + new + show_list + ).each do |task| + describe "##{task}" do + it 'routes with GET' do + expect(get("/#{controller_name}/#{task}")).to route_to("#{controller_name}##{task}") + end + end + end + + %w( + button + form_field_changed + listnav_search_selected + save_default_search + show + show_list + update + ).each do |task| + describe "##{task}" do + it 'routes with POST' do + expect(post("/#{controller_name}/#{task}")).to route_to("#{controller_name}##{task}") + end + end + end + + describe "#index" do + it "routes with GET" do + expect(get("/#{controller_name}")).to route_to("#{controller_name}#index") + end + end + + describe "#update" do + it "routes with POST" do + expect(post("/#{controller_name}/update/123")).to route_to("#{controller_name}#update", :id => "123") + end + end +end