[PATCH conductor 3/3] deployable details Images part

jtomasek at redhat.com jtomasek at redhat.com
Fri Dec 9 15:06:27 UTC 2011


From: Jiri Tomasek <jtomasek at redhat.com>

Added Image status in the Images table in the left column. If the Hardware
Profile or Image UUID isnt found in the database user is alerted via
flash message describing missing HWP or UUID of missing Image.

Launch button is disabled until Images in Deployable are all valid.
---
 src/app/controllers/deployables_controller.rb |   16 +++-
 src/app/helpers/deployables_helper.rb         |   18 +++--
 src/app/models/deployable.rb                  |    7 +-
 src/app/stylesheets/layout.scss               |  107 ++++++++++++++++++++++++-
 src/app/views/deployables/show.html.haml      |   51 ++++++------
 src/config/locales/en.yml                     |   50 +++++++-----
 6 files changed, 185 insertions(+), 64 deletions(-)

diff --git a/src/app/controllers/deployables_controller.rb b/src/app/controllers/deployables_controller.rb
index 241ebb2..48f5b3a 100644
--- a/src/app/controllers/deployables_controller.rb
+++ b/src/app/controllers/deployables_controller.rb
@@ -57,18 +57,24 @@ class DeployablesController < ApplicationController
     @catalogs_options = Catalog.list_for_user(current_user, Privilege::VIEW).select {|c| !@deployable.catalogs.include?(c)}
     add_permissions_inline(@deployable)
     @images_details = @deployable.get_image_details
+    images = @deployable.fetch_images
+    uuids = @deployable.fetch_image_uuids
+    @missing_images = images.zip(uuids).select{|p| p.first.nil?}.map{|p| p.second}
+
     @images_details.each do |assembly|
       assembly.keys.each do |key|
-        flash[:error] = assembly[key] if key.to_s =~ /^error\w+/
+        flash.now[:error] ||= []
+        flash.now[:error] << "#{assembly[:name]}: #{assembly[key]}" if key.to_s =~ /^error\w+/
+      end
+      if @missing_images.include?(assembly[:image_uuid])
+        flash.now[:error] << "#{assembly[:name]}: Image (UUID: #{assembly[:image_uuid]}) doesn't exist."
       end
     end
-    images = @deployable.fetch_images
-    uuids = @deployable.fetch_image_uuids
-    @missing_images = images.zip(uuids).select{|p| p.first.nil?}.map{|p| p.second}
+
     return unless @missing_images.empty?
 
     @build_results = {}
-    ProviderAccount.list_for_user(current_user, Privilege::VIEW).each do |account|
+    ProviderAccount.list_for_user(current_user, Privilege::VIEW).includes(:provider).where('providers.enabled' => true).each do |account|
       type = account.provider.provider_type.deltacloud_driver
       @build_results[type] ||= []
       @build_results[type] << {
diff --git a/src/app/helpers/deployables_helper.rb b/src/app/helpers/deployables_helper.rb
index 2c9ad8e..1677197 100644
--- a/src/app/helpers/deployables_helper.rb
+++ b/src/app/helpers/deployables_helper.rb
@@ -1,13 +1,17 @@
 module DeployablesHelper
   def image_ready?(assembly)
-    if @missing_images.empty?
-      "image is ready"
+    if @missing_images.empty? && assembly[:hwp_name].present?
+      link_to t('.images_ready'), edit_catalog_deployable_path(@catalog, @deployable, :edit_xml => true), :class => 'images_ready', :id => 'edit_xml_button'
+    elsif assembly[:hwp_name].nil?
+      link_to t('.repair_images'), edit_catalog_deployable_path(@catalog, @deployable, :edit_xml => true), :class => 'repair_images', :id => 'edit_xml_button'
+    elsif @missing_images.include?(assembly[:image_uuid])
+      link_to t('.repair_images'), edit_catalog_deployable_path(@catalog, @deployable, :edit_xml => true), :class => 'repair_images', :id => 'edit_xml_button'
     else
-      if @missing_images.include?(assembly[:image_uuid])
-        "Image specified in xml does not exist"
-      else
-        "image is ready"
-      end
+      link_to t('.images_ready'), edit_catalog_deployable_path(@catalog, @deployable, :edit_xml => true), :class => 'images_ready', :id => 'edit_xml_button'
     end
   end
+
+  def deployable_ready?
+    false
+  end
 end
diff --git a/src/app/models/deployable.rb b/src/app/models/deployable.rb
index f5eb873..ebd230c 100644
--- a/src/app/models/deployable.rb
+++ b/src/app/models/deployable.rb
@@ -111,12 +111,9 @@ class Deployable < ActiveRecord::Base
     deployable_xml = DeployableXML.new(xml)
     assemblies_array ||= []
     deployable_xml.assemblies.each do |assembly|
-      if assembly.name
-        assembly_hash ||= {:name => assembly.name}
-      else
-        assembly_hash ||= {:error_name => I18n.t('deployables.error.attribute_not_exist')}
-      end
+      assembly_hash ||= {:name => assembly.name}
       assembly_hash[:image_uuid] = assembly.image_id
+      assembly_hash[:images_count] = assembly.image.count
       if assembly.hwp
         hwp_name = assembly.hwp
         hwp = HardwareProfile.find_by_name(hwp_name)
diff --git a/src/app/stylesheets/layout.scss b/src/app/stylesheets/layout.scss
index 8cad81b..47844bb 100644
--- a/src/app/stylesheets/layout.scss
+++ b/src/app/stylesheets/layout.scss
@@ -2388,12 +2388,117 @@ ul.instances-array{
 /********************************************* Deployable Detail page */
 /************************************************************************** */
 
+a#launch_deployable_button{
+  display: inline-block;
+  margin: -7px 0px 0px 10px;
+  padding: 13px 12px 9px 46px;
+  font-weight: bold;
+  font-size: 14px;
+  color: white;
+  text-decoration: none;
+  border: 1px solid #669933;
+  -webkit-border-radius: 0.2em; -moz-border-radius: 0.2em; border-radius: 0.2em;
+
+  background: #5AB45C url(../../images/deployment_large_icon_provider_white.png) no-repeat 12px center; /* Old browsers */
+  background: url(../../images/deployment_large_icon_provider_white.png) 12px center no-repeat, -moz-linear-gradient(top, #ace3ac 0%, #5ab45c 100%); /* FF3.6+ */
+  background: url(../../images/deployment_large_icon_provider_white.png) 12px center no-repeat, -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ace3ac), color-stop(100%,#5ab45c)); /* Chrome,Safari4+ */
+  background: url(../../images/deployment_large_icon_provider_white.png) 12px center no-repeat, -webkit-linear-gradient(top, #ace3ac 0%,#5ab45c 100%); /* Chrome10+,Safari5.1+ */
+  background: url(../../images/deployment_large_icon_provider_white.png) 12px center no-repeat, -o-linear-gradient(top, #ace3ac 0%,#5ab45c 100%); /* Opera 11.10+ */
+  background: url(../../images/deployment_large_icon_provider_white.png) 12px center no-repeat, -ms-linear-gradient(top, #ace3ac 0%,#5ab45c 100%); /* IE10+ */
+  background: url(../../images/deployment_large_icon_provider_white.png) 12px center no-repeat, linear-gradient(top, #ace3ac 0%,#5ab45c 100%); /* W3C */
+  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ace3ac', endColorstr='#5ab45c',GradientType=0 ); /* IE6-9 */
+  &:active{
+    background: #458944; /* Old browsers */
+    background: url(../../images/deployment_large_icon_provider_white.png) 12px center no-repeat, -moz-linear-gradient(top, #9ecc9b 0%, #458944 100%); /* FF3.6+ */
+    background: url(../../images/deployment_large_icon_provider_white.png) 12px center no-repeat, -webkit-gradient(linear, left top, left bottom, color-stop(0%,#9ecc9b), color-stop(100%,#458944)); /* Chrome,Safari4+ */
+    background: url(../../images/deployment_large_icon_provider_white.png) 12px center no-repeat, -webkit-linear-gradient(top, #9ecc9b 0%, #458944 100%); /* Chrome10+,Safari5.1+ */
+    background: url(../../images/deployment_large_icon_provider_white.png) 12px center no-repeat, -o-linear-gradient(top, #9ecc9b 0%, #458944 100%); /* Opera 11.10+ */
+    background: url(../../images/deployment_large_icon_provider_white.png) 12px center no-repeat, -ms-linear-gradient(top, #9ecc9b 0%, #458944 100%); /* IE10+ */
+    background: url(../../images/deployment_large_icon_provider_white.png) 12px center no-repeat, linear-gradient(top, #9ecc9b 0%, #458944 100%); /* W3C */
+    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#9ecc9b', endColorstr='#458944',GradientType=0 ); /* IE6-9 */
+    -webkit-box-shadow: inset 1px 1px 2px 0px #333; -moz-box-shadow: inset 1px 1px 2px 0px #333; box-shadow: inset 1px 1px 2px 0px #333;
+  }
+  &.disabled{
+    cursor: default;
+    zoom: 1;
+    filter: alpha(opacity=50);
+    -moz-opacity:0.5;
+    opacity: 0.5;
+  }
+}
+
 table.light_table{
   margin: 10px;
   td,th{ padding: 5px 10px; vertical-align: middle;}
-  th{border-bottom: 1px solid #CCCCCC;}
+  th{ border-bottom: 1px solid #CCCCCC; }
   td:first-child, th:first-child{padding-left: 0px;}
   td:last-child, th:last-child{padding-right: 0px;}
+  th.status{ border-bottom: none; text-align: right; }
+  td.status{ text-align: right; }
+  td.status a{
+    text-transform: uppercase;
+    text-decoration: none;
+    font-size: 10px;
+    font-weight: bold;
+    color: white;
+    padding: 4px 8px 3px 8px;
+    border: 1px solid black;
+    -webkit-border-radius: 8px; -moz-border-radius: 8px; border-radius: 8px;
+    -webkit-box-shadow: 0px 0px 1px 0px #333;
+    -moz-box-shadow: 0px 0px 1px 0px #333;
+    box-shadow: 0px 0px 1px 0px #333;
+    text-shadow: 0px -1px 1px #888;
+    &.images_ready{
+      background: #33cc00; /* Old browsers */
+      background: -moz-linear-gradient(top, #33cc00 0%, #28a600 100%); /* FF3.6+ */
+      background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#33cc00), color-stop(100%,#28a600)); /* Chrome,Safari4+ */
+      background: -webkit-linear-gradient(top, #33cc00 0%,#28a600 100%); /* Chrome10+,Safari5.1+ */
+      background: -o-linear-gradient(top, #33cc00 0%,#28a600 100%); /* Opera 11.10+ */
+      background: -ms-linear-gradient(top, #33cc00 0%,#28a600 100%); /* IE10+ */
+      background: linear-gradient(top, #33cc00 0%,#28a600 100%); /* W3C */
+      filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#33cc00', endColorstr='#28a600',GradientType=0 ); /* IE6-9 */
+      &:active{
+        box-shadow: 0px 0px 1px 0px #333 inset;
+        background: #31a500; /* Old browsers */
+        background: -moz-linear-gradient(top, #31a500 0%, #297700 100%); /* FF3.6+ */
+        background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#31a500), color-stop(100%,#297700)); /* Chrome,Safari4+ */
+        background: -webkit-linear-gradient(top, #31a500 0%,#297700 100%); /* Chrome10+,Safari5.1+ */
+        background: -o-linear-gradient(top, #31a500 0%,#297700 100%); /* Opera 11.10+ */
+        background: -ms-linear-gradient(top, #31a500 0%,#297700 100%); /* IE10+ */
+        background: linear-gradient(top, #31a500 0%,#297700 100%); /* W3C */
+        filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#31a500', endColorstr='#297700',GradientType=0 ); /* IE6-9 */
+      }
+    }
+    &.repair_images{
+      background: #6d6d6d; /* Old browsers */
+      background: -moz-linear-gradient(top, #6d6d6d 0%, #1c1c1c 100%); /* FF3.6+ */
+      background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#6d6d6d), color-stop(100%,#1c1c1c)); /* Chrome,Safari4+ */
+      background: -webkit-linear-gradient(top, #6d6d6d 0%,#1c1c1c 100%); /* Chrome10+,Safari5.1+ */
+      background: -o-linear-gradient(top, #6d6d6d 0%,#1c1c1c 100%); /* Opera 11.10+ */
+      background: -ms-linear-gradient(top, #6d6d6d 0%,#1c1c1c 100%); /* IE10+ */
+      background: linear-gradient(top, #6d6d6d 0%,#1c1c1c 100%); /* W3C */
+      filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#6d6d6d', endColorstr='#1c1c1c',GradientType=0 ); /* IE6-9 */
+      &:active{
+        box-shadow: 0px 0px 1px 0px #333 inset;
+        background: #4c4c4c; /* Old browsers */
+        background: -moz-linear-gradient(top, #4c4c4c 0%, #0f0f0f 100%); /* FF3.6+ */
+        background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#4c4c4c), color-stop(100%,#0f0f0f)); /* Chrome,Safari4+ */
+        background: -webkit-linear-gradient(top, #4c4c4c 0%,#0f0f0f 100%); /* Chrome10+,Safari5.1+ */
+        background: -o-linear-gradient(top, #4c4c4c 0%,#0f0f0f 100%); /* Opera 11.10+ */
+        background: -ms-linear-gradient(top, #4c4c4c 0%,#0f0f0f 100%); /* IE10+ */
+        background: linear-gradient(top, #4c4c4c 0%,#0f0f0f 100%); /* W3C */
+        filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#4c4c4c', endColorstr='#0f0f0f',GradientType=0 ); /* IE6-9 */
+      }
+    }
+  }
+  th.remove_catalog{ text-align: right; border-bottom: none; }
+  td.remove_catalog{ text-align: right; }
+  td.remove_catalog input.remove_catalog{
+    background: transparent url(../../images/icon_remove.png) no-repeat -3px -3px;
+    border: none;
+    width: 15px;
+    height: 15px;
+  }
 }
 
 div.build_status{
diff --git a/src/app/views/deployables/show.html.haml b/src/app/views/deployables/show.html.haml
index c367633..0d422b4 100644
--- a/src/app/views/deployables/show.html.haml
+++ b/src/app/views/deployables/show.html.haml
@@ -3,10 +3,15 @@
   %h1{:class => controller.controller_name}= @deployable.name
   #obj_actions.button-container
     .button-group
-      = button_to t('catalog_entries.show.delete'), catalog_deployable_path(@catalog, @deployable), :method => 'delete', :confirm => "#{t'catalog_entries.show.confirm_delete'}", :class => 'button danger', :id => 'delete'
-      = link_to t('catalog_entries.show.edit'), edit_catalog_deployable_path(@catalog, @deployable), :class => 'button', :id => 'edit_button'
+      = button_to t('.delete'), catalog_deployable_path(@catalog, @deployable), :method => 'delete', :confirm => "#{t'catalog_entries.show.confirm_delete'}", :class => 'button danger', :id => 'delete'
+      = link_to t('.edit'), edit_catalog_deployable_path(@catalog, @deployable), :class => 'button', :id => 'edit_button'
+      = link_to t('.edit_xml'), edit_catalog_deployable_path(@catalog, @deployable, :edit_xml => true), :class => 'button', :id => 'edit_xml_button'
+
+    - if @missing_images.empty? && @images_details.select{|assembly| assembly[:hwp_name] == nil}.empty?
+      = link_to t('.launch'), launch_new_deployments_path(:deployable_id => @deployable.id, :pool_id => @catalog.pool), :id => :launch_deployable_button
+    -else
+      %a{:id => :launch_deployable_button, :class => 'disabled'}= t('.launch')
 
-    = link_to t('deployments.overview.launch'), launch_new_deployments_path(:deployable_id => @deployable.id, :pool_id => @catalog.pool), :id => :launch_deployment
 
 %section.admin-content-section
   %header
@@ -16,29 +21,25 @@
       %table.light_table
         %thead
           %tr
-            %th
+            %th.status
             %th
               %strong=t'.name'
-            %th=t'.hwp_profile'
+            %th.align-center=t'.images'
+            %th=t'.hw_profile'
             %th.align-center=t'.hdd'
             %th.align-center=t'.ram'
             %th.align-center=t'.arch'
         %tbody
           - @images_details.each do |assembly|
             %tr
-              %td= image_ready?(assembly)
-              - if assembly.has_key?(:name)
-                %td
-                  %strong=assembly[:name]
-              -else
-                %td=assembly[:error_name]
-              -if assembly.has_key?(:hwp_name)
-                %td=assembly[:hwp_name]
-                %td.align-center=assembly[:hwp_hdd]
-                %td.align-center=assembly[:hwp_ram]
-                %td.align-center=assembly[:hwp_arch]
-              -else
-                %td{:colspan => 4}= assembly[:error_hwp]
+              %td.status= image_ready?(assembly)
+              %td
+                %strong=assembly[:name]
+              %td.align-center=assembly[:images_count]
+              %td=assembly[:hwp_name]
+              %td.align-center=assembly[:hwp_hdd]
+              %td.align-center=assembly[:hwp_ram]
+              %td.align-center=assembly[:hwp_arch]
 
 %section.admin-content-section
   - if @missing_images.empty?
@@ -63,13 +64,15 @@
                   %span= result[:account]
                 .controls
                   .build_status
-                    %span= t("catalog_entries.build_statuses_descriptions.#{result[:status]}")
+                    %span= t(".build_statuses_descriptions.#{result[:status]}")
                     %div{:class => "build_status_icon #{result[:status]}"}
   - else
     %header
       %h2= t('.build')
     .content
-      %h3= t('.missing_images')
+      .centered.align-center
+        %strong Assemblies in Deployable XML arent properly configured.
+      %strong= t('.missing_images')
       %ul#missing-images-list
         - @missing_images.each do |uuid|
           %li= uuid
@@ -79,15 +82,15 @@
     %h2= t('.catalogs')
     .section-controls
       = form_for(:catalog_entry, :url => catalog_entries_path) do |f|
-        = f.label :catalog_id, t('catalog_entries.show.choose_catalog')
+        = f.label :catalog_id, t('.choose_catalog')
         = f.select :catalog_id, options_for_select(@catalogs_options.map {|c| [c.name, c.id]})
         = f.hidden_field(:deployable_id, :value => @deployable.id)
-        = f.submit t('catalog_entries.show.add_catalog'), :id => :add_catalog, :class => 'button pill', :disabled => @catalogs_options.empty?
+        = f.submit t('.add_catalog'), :id => :add_catalog, :class => 'button pill', :disabled => @catalogs_options.empty?
   .content
     .centered
       %table.light_table
         %tr
-          %th
+          %th.remove_catalog
           %th
             %label
               %strong= t('.catalog_name')
@@ -96,7 +99,7 @@
               %strong= t('.environment')
         - @deployable.catalog_entries.each do |catalog_entry|
           %tr
-            %td= button_to t('catalog_entries.show.delete'), catalog_entry_path(catalog_entry), :method => 'delete', :confirm => "#{t'catalog_entries.show.confirm_delete'}", :id => 'delete'
+            %td.remove_catalog= button_to "", catalog_entry_path(catalog_entry), :method => 'delete', :confirm => "#{t'catalog_entries.show.confirm_delete'}", :id => 'delete', :class => 'remove_catalog'
             %td= catalog_entry.catalog.name
             %td= catalog_entry.catalog.pool.pool_family.name
 
diff --git a/src/config/locales/en.yml b/src/config/locales/en.yml
index 8b0f2d4..023da47 100644
--- a/src/config/locales/en.yml
+++ b/src/config/locales/en.yml
@@ -618,6 +618,7 @@ en:
       deployable_xml_url: "URL of Deployable XML:"
     show:
       edit: Edit
+      edit_xml: Edit XML
       delete: Delete
       confirm_delete: "Are you sure you want to delete?"
       image: Image
@@ -626,18 +627,6 @@ en:
       roles: Roles
       rebuild_all: Rebuild all images
       start: Start
-      build_description:
-        "Allow this deployable's associated image(s) to be built and
-        pushed to cloud resource providers by enabling them below."
-      catalog_name: Catalog name
-      environment: Environment
-      choose_catalog: "Choose a catalog to enable access:"
-      add_catalog: "Add +"
-      name: Name
-      profile: Profile
-      hdd: HDD
-      ram: RAM
-      arch: ARCH
     edit:
       editing_catalog_entry: Editing Catalog Entry
     list:
@@ -653,12 +642,6 @@ en:
         deleted: Catalog entry deleted.
     preset_filters:
       all_catalog_entries: All Catalog Entries
-    build_statuses_descriptions:
-      not_built: "Images are not Built"
-      building: "Images are being built."
-      not_pushed: "Some of the images are not pushed"
-      pushing: "Images are being pushed."
-      pushed: "All Images are pushed and recent."
   catalogs:
     catalogs: Catalogs
     new_catalog: New Catalog
@@ -791,14 +774,37 @@ en:
         one: "Deployable %{list} was not deleted. There are deployments associated with it."
         other: "Deployables %{list} were not deleted. They have deployments associated with them."
     show:
+      launch: "Launch"
+      edit: Edit
+      edit_xml: Edit XML
+      delete: Delete
       build: Build
-      build_description:
-        "Allow this deployable's associated image(s) to be built and pushed to
-        providers by enabling them below."
       start: Start
       rebuild_all: Build missing images
       push_all: Push missing images
       missing_images: Images missing from the Image Warehouse
+      choose_catalog: "Choose a catalog to enable access:"
+      add_catalog: "Add +"
+      name: Name
+      hw_profile: HW Profile
+      hdd: HDD
+      ram: RAM
+      arch: ARCH
+      repair_images: Repair Images
+      images_ready: Images Ready
+      build_description:
+        "Allow this deployable's associated image(s) to be built and
+        pushed to cloud resource providers by enabling them below."
+      catalog_name: Catalog name
+      environment: Environment
+      build_statuses_descriptions:
+        not_built: "Images are not Built"
+        building: "Images are being built."
+        not_pushed: "Some of the images are not pushed"
+        pushing: "Images are being pushed."
+        pushed: "All Images are pushed and recent."
+      build_missing: "Build missing"
+      push_missing: "Push missing"
     flash:
       error:
         attribute_not_exist: "Some attribute(s) is missing in XML, please check the file!"
@@ -807,7 +813,7 @@ en:
         failed: "Deployable was not created: %{message}"
     error:
       attribute_not_exists: invalid
-      hwp_not_exists: "Hardware profile %{name} doesn't exist in DB"
+      hwp_not_exists: "Hardware profile %{name} specified in XML doesn't exist."
   name: Name
   summary: Summary
   settings:
-- 
1.7.7.3




More information about the aeolus-devel mailing list