This patch needs to be applied on top of Jan's "Deploaybles and catalog_entries cleanups" patch.
From: Tomas Sedovic tomas@sedovic.cz
https://www.aeolusproject.org/redmine/issues/2853
It shows the following states: not built, building, not pushed, pushing, pushed. And it allows the user to rebuild and re-push all images.
As things are now, building and pushing is a 2-step operation.
Note that the page isn't styled properly yet. --- src/app/controllers/deployables_controller.rb | 33 ++++++++++++ src/app/models/deployable.rb | 70 ++++++++++++++++++++++--- src/app/views/deployables/show.html.haml | 35 ++++++++----- src/config/locales/en.yml | 9 +++ src/config/routes.rb | 1 + 5 files changed, 127 insertions(+), 21 deletions(-)
diff --git a/src/app/controllers/deployables_controller.rb b/src/app/controllers/deployables_controller.rb index a1d7f9b..a6457d3 100644 --- a/src/app/controllers/deployables_controller.rb +++ b/src/app/controllers/deployables_controller.rb @@ -64,6 +64,21 @@ class DeployablesController < ApplicationController flash[:error] = assembly[key] if key.to_s =~ /^error\w+/ 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| + type = account.provider.provider_type.deltacloud_driver + @build_results[type] ||= [] + @build_results[type] << { + :account => account.label, + :provider => account.provider.name, + :status => @deployable.build_status(images, account), + } + end end
def create @@ -171,6 +186,24 @@ class DeployablesController < ApplicationController redirect_to original_path.merge(original_params).merge("catalog_entries_preset_filter" => params[:catalog_entries_preset_filter], "catalog_entries_search" => params[:catalog_entries_search]) end
+ def build + catalog = Catalog.find(params[:catalog_id]) + deployable = Deployable.find(params[:deployable_id]) + require_privilege(Privilege::MODIFY, catalog) + require_privilege(Privilege::MODIFY, deployable) + + images = deployable.fetch_images + accounts = ProviderAccount.list_for_user(current_user, Privilege::VIEW) + options = params[:build_options].to_sym + case options + when :build_missing + deployable.build_missing(images, accounts) + when :push_missing + deployable.push_missing(images, accounts) + end + redirect_to catalog_deployable_path(catalog, deployable) + end + private
def set_header diff --git a/src/app/models/deployable.rb b/src/app/models/deployable.rb index 2a568ac..ac68454 100644 --- a/src/app/models/deployable.rb +++ b/src/app/models/deployable.rb @@ -60,13 +60,8 @@ class Deployable < ActiveRecord::Base
# Round up Catalog Entries, fetch their Deployables, and extract image UUIDs. def fetch_images - images = [] - unless fetch_image_uuids.nil? - fetch_image_uuids.each do |uuid| - images << Aeolus::Image::Warehouse::Image.find(uuid) - end - return images.compact.uniq - end + uuids = fetch_image_uuids || [] + uuids.map { |uuid| Aeolus::Image::Warehouse::Image.find(uuid) } end
def fetch_image_uuids @@ -143,6 +138,66 @@ class Deployable < ActiveRecord::Base result_array end
+ def build_status(images, account) + image_statuses = images.map { |i| image_status(i, account) } + return :not_built if image_statuses.any? { |status| status == :not_built } + return :building if image_statuses.any? { |status| status == :building } + return :pushing if image_statuses.any? { |status| status == :pushing } + return :not_pushed if image_statuses.any? { |status| status == :not_pushed } + :pushed + end + + def image_status(image, account) + build = image.latest_pushed_or_unpushed_build + target = account.provider.provider_type.deltacloud_driver + return :not_built unless build + + builder = Aeolus::Image::Factory::Builder.first + return :building if builder.find_active_build(build.id, target) + + target_image = build.target_images.find { |ti| ti.target == target } + return :not_built unless target_image + + return :pushing if builder.find_active_push(target_image.id, + account.provider.name, + account.credentials_hash["username"]) + + provider_image = target_image.find_provider_image_by_provider_and_account( + account.provider.name, account.warehouse_id).first + return :not_pushed unless provider_image + :pushed + end + + def build_missing(images, accounts) + targets = accounts.map { |acc| acc.provider.provider_type.deltacloud_driver }.uniq.join(',') + images.each do |image| + factory_image = Aeolus::Image::Factory::Image.new(:id => image.id) + factory_image.targets = targets + factory_image.template = image.template + factory_image.save! + end + end + + def push_missing(images, accounts) + images.each do |image| + accounts.each do |account| + if image_status(image, account) == :not_pushed + target = account.provider.provider_type.deltacloud_driver + build = image.latest_pushed_or_unpushed_build + target_image = build.target_images.find { |ti| ti.target == target } + provider_image = Aeolus::Image::Factory::ProviderImage.new( + :provider => account.provider.name, + :credentials => account.to_xml(:with_credentials => true), + :image_id => image.uuid, + :build_id => build.uuid, + :target_image_id => target_image.uuid + ) + provider_image.save! + end + end + end + end + private
def self.apply_search_filter(search) @@ -152,5 +207,4 @@ class Deployable < ActiveRecord::Base scoped end end - end diff --git a/src/app/views/deployables/show.html.haml b/src/app/views/deployables/show.html.haml index e09f4bf..6a8576a 100644 --- a/src/app/views/deployables/show.html.haml +++ b/src/app/views/deployables/show.html.haml @@ -39,19 +39,28 @@ %header %h2= t('.build')
- = form_tag() do - = select_tag :build_option, options_for_select([[t("rebuild_all"), 1]]) - = submit_tag t('.start'), :id => :start_build + - if @missing_images.empty? + = form_tag(catalog_deployable_build_path(@catalog, @deployable)) do + = select_tag :build_options, options_for_select([[t(".build_missing"), :build_missing], [t(".push_missing"), :push_missing]]) + = submit_tag t('.start'), :id => :start_build
- %p.description= t('.build_description') + %p.description= t('.build_description')
- %ul#providers-list - - @providers.each do |provider| - %li - %span.provider= provider.name - %span.status Building 98% - -#= form_tag() - -# %button on/off + %ul#providers-list + - @build_results.each do |provider_type, results| + %li + = provider_type + %ul + - results.each do |result| + %li + %span.provider= result[:provider] + %span.account= result[:account] + %span.status= result[:status] + - else + %h3= t('.missing_images') + %ul#missing-images-list + - @missing_images.each do |uuid| + %li= uuid
%section.catalogs diff --git a/src/config/locales/en.yml b/src/config/locales/en.yml index e45d743..2819ce6 100644 --- a/src/config/locales/en.yml +++ b/src/config/locales/en.yml @@ -783,6 +783,15 @@ en: not_deleted: 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: + 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 flash: error: attribute_not_exist: "Some attribute(s) is missing in XML, please check the file!" diff --git a/src/config/routes.rb b/src/config/routes.rb index 7a7df6e..b07ba9e 100644 --- a/src/config/routes.rb +++ b/src/config/routes.rb @@ -205,6 +205,7 @@ Conductor::Application.routes.draw do resources :deployables do delete 'multi_destroy', :on => :collection post :filter, :on => :collection + post :build end end
On 12/02/2011 04:13 PM, tsedovic@redhat.com wrote:
From: Tomas Sedovictomas@sedovic.cz
https://www.aeolusproject.org/redmine/issues/2853
It shows the following states: not built, building, not pushed, pushing, pushed. And it allows the user to rebuild and re-push all images.
As things are now, building and pushing is a 2-step operation.
Note that the page isn't styled properly yet.
src/app/controllers/deployables_controller.rb | 33 ++++++++++++ src/app/models/deployable.rb | 70 ++++++++++++++++++++++--- src/app/views/deployables/show.html.haml | 35 ++++++++----- src/config/locales/en.yml | 9 +++ src/config/routes.rb | 1 + 5 files changed, 127 insertions(+), 21 deletions(-)
diff --git a/src/app/controllers/deployables_controller.rb b/src/app/controllers/deployables_controller.rb index a1d7f9b..a6457d3 100644 --- a/src/app/controllers/deployables_controller.rb +++ b/src/app/controllers/deployables_controller.rb @@ -64,6 +64,21 @@ class DeployablesController< ApplicationController flash[:error] = assembly[key] if key.to_s =~ /^error\w+/ 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|
type = account.provider.provider_type.deltacloud_driver
@build_results[type] ||= []
@build_results[type]<< {
:account => account.label,
:provider => account.provider.name,
:status => @deployable.build_status(images, account),
}
end end
def create
@@ -171,6 +186,24 @@ class DeployablesController< ApplicationController redirect_to original_path.merge(original_params).merge("catalog_entries_preset_filter" => params[:catalog_entries_preset_filter], "catalog_entries_search" => params[:catalog_entries_search]) end
def build
catalog = Catalog.find(params[:catalog_id])
deployable = Deployable.find(params[:deployable_id])
require_privilege(Privilege::MODIFY, catalog)
require_privilege(Privilege::MODIFY, deployable)
images = deployable.fetch_images
accounts = ProviderAccount.list_for_user(current_user, Privilege::VIEW)
options = params[:build_options].to_sym
case options
when :build_missing
deployable.build_missing(images, accounts)
when :push_missing
deployable.push_missing(images, accounts)
end
redirect_to catalog_deployable_path(catalog, deployable)
end
private
def set_header
diff --git a/src/app/models/deployable.rb b/src/app/models/deployable.rb index 2a568ac..ac68454 100644 --- a/src/app/models/deployable.rb +++ b/src/app/models/deployable.rb @@ -60,13 +60,8 @@ class Deployable< ActiveRecord::Base
# Round up Catalog Entries, fetch their Deployables, and extract image UUIDs. def fetch_images
- images = []
- unless fetch_image_uuids.nil?
fetch_image_uuids.each do |uuid|
images<< Aeolus::Image::Warehouse::Image.find(uuid)
end
return images.compact.uniq
- end
- uuids = fetch_image_uuids || []
- uuids.map { |uuid| Aeolus::Image::Warehouse::Image.find(uuid) } end
^ since this method now returns nil values too, handle nil value where it's called from: app/models/pool.rb app/views/deployments/launch_from_catalog.html.haml
def fetch_image_uuids
@@ -143,6 +138,66 @@ class Deployable< ActiveRecord::Base result_array end
def build_status(images, account)
image_statuses = images.map { |i| image_status(i, account) }
return :not_built if image_statuses.any? { |status| status == :not_built }
return :building if image_statuses.any? { |status| status == :building }
return :pushing if image_statuses.any? { |status| status == :pushing }
return :not_pushed if image_statuses.any? { |status| status == :not_pushed }
:pushed
end
def image_status(image, account)
build = image.latest_pushed_or_unpushed_build
target = account.provider.provider_type.deltacloud_driver
return :not_built unless build
builder = Aeolus::Image::Factory::Builder.first
return :building if builder.find_active_build(build.id, target)
target_image = build.target_images.find { |ti| ti.target == target }
return :not_built unless target_image
return :pushing if builder.find_active_push(target_image.id,
account.provider.name,
account.credentials_hash["username"])
provider_image = target_image.find_provider_image_by_provider_and_account(
account.provider.name, account.warehouse_id).first
return :not_pushed unless provider_image
:pushed
end
def build_missing(images, accounts)
targets = accounts.map { |acc| acc.provider.provider_type.deltacloud_driver }.uniq.join(',')
images.each do |image|
factory_image = Aeolus::Image::Factory::Image.new(:id => image.id)
factory_image.targets = targets
factory_image.template = image.template
factory_image.save!
end
end
def push_missing(images, accounts)
images.each do |image|
accounts.each do |account|
if image_status(image, account) == :not_pushed
target = account.provider.provider_type.deltacloud_driver
build = image.latest_pushed_or_unpushed_build
target_image = build.target_images.find { |ti| ti.target == target }
provider_image = Aeolus::Image::Factory::ProviderImage.new(
:provider => account.provider.name,
:credentials => account.to_xml(:with_credentials => true),
:image_id => image.uuid,
:build_id => build.uuid,
:target_image_id => target_image.uuid
)
provider_image.save!
end
end
end
end
private
def self.apply_search_filter(search)
@@ -152,5 +207,4 @@ class Deployable< ActiveRecord::Base scoped end end
- end
diff --git a/src/app/views/deployables/show.html.haml b/src/app/views/deployables/show.html.haml index e09f4bf..6a8576a 100644 --- a/src/app/views/deployables/show.html.haml +++ b/src/app/views/deployables/show.html.haml @@ -39,19 +39,28 @@ %header %h2= t('.build')
= form_tag() do
= select_tag :build_option, options_for_select([[t("rebuild_all"), 1]])
= submit_tag t('.start'), :id => :start_build
- if @missing_images.empty?
= form_tag(catalog_deployable_build_path(@catalog, @deployable)) do
= select_tag :build_options, options_for_select([[t(".build_missing"), :build_missing], [t(".push_missing"), :push_missing]])
= submit_tag t('.start'), :id => :start_build
%p.description= t('.build_description')
%p.description= t('.build_description')
%ul#providers-list
- @providers.each do |provider|
%li
%span.provider= provider.name
%span.status Building 98%
-#= form_tag()
-# %button on/off
%ul#providers-list
- @build_results.each do |provider_type, results|
%li
= provider_type
%ul
- results.each do |result|
%li
%span.provider= result[:provider]
%span.account= result[:account]
%span.status= result[:status]
- else
%h3= t('.missing_images')
%ul#missing-images-list
- @missing_images.each do |uuid|
%li= uuid
%section.catalogs
diff --git a/src/config/locales/en.yml b/src/config/locales/en.yml index e45d743..2819ce6 100644 --- a/src/config/locales/en.yml +++ b/src/config/locales/en.yml @@ -783,6 +783,15 @@ en: not_deleted: 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:
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 flash: error: attribute_not_exist: "Some attribute(s) is missing in XML, please check the file!"
diff --git a/src/config/routes.rb b/src/config/routes.rb index 7a7df6e..b07ba9e 100644 --- a/src/config/routes.rb +++ b/src/config/routes.rb @@ -205,6 +205,7 @@ Conductor::Application.routes.draw do resources :deployables do delete 'multi_destroy', :on => :collection post :filter, :on => :collection
endpost :build end
Hi Tomas, code looks good, works for me. Conditional ACK - see inline note.
As we discussed on IRC: optional build_id param in deployable XML is ignored for now, will be fixed later.
Great work, Jan
aeolus-devel@lists.fedorahosted.org