On 12/02/2011 04:13 PM, tsedovic(a)redhat.com wrote:
From: Tomas Sedovic<tomas(a)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
+ post :build
end
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