[PATCH 1/2] Add 'status' to ProviderImage
by steve linabery
From: Scott Seago <sseago(a)redhat.com>
Signed-off-by: Scott Seago <sseago(a)redhat.com>
---
.../controllers/resources/instances_controller.rb | 2 +-
src/app/models/image.rb | 3 +-
src/app/models/provider_image.rb | 15 +++++++--
src/app/views/image_factory/templates/_builds.haml | 3 +-
.../20110302120000_add_status_to_provider_image.rb | 31 ++++++++++++++++++++
src/features/template.feature | 2 +-
src/image_builder_service/image_builder_service | 3 +-
src/spec/factories/provider_image.rb | 3 +-
8 files changed, 48 insertions(+), 14 deletions(-)
create mode 100644 src/db/migrate/20110302120000_add_status_to_provider_image.rb
diff --git a/src/app/controllers/resources/instances_controller.rb b/src/app/controllers/resources/instances_controller.rb
index 30aeccd..6eba323 100644
--- a/src/app/controllers/resources/instances_controller.rb
+++ b/src/app/controllers/resources/instances_controller.rb
@@ -35,7 +35,7 @@ class Resources::InstancesController < ApplicationController
@templates = Template.paginate(
:page => params[:page] || 1,
:include => {:images => :provider_images},
- :conditions => "provider_images.uploaded = 't'"
+ :conditions => "provider_images.status = '#{ProviderImage::STATE_COMPLETE}'"
)
end
diff --git a/src/app/models/image.rb b/src/app/models/image.rb
index fc33b53..2109fe6 100644
--- a/src/app/models/image.rb
+++ b/src/app/models/image.rb
@@ -170,8 +170,7 @@ class Image < ActiveRecord::Base
:image_id => image.id,
:provider_id => account.provider.id,
:provider_image_key => image_id,
- :uploaded => true,
- :registered => true
+ :status => 'complete'
)
rep.save!
diff --git a/src/app/models/provider_image.rb b/src/app/models/provider_image.rb
index e218970..ea2209b 100644
--- a/src/app/models/provider_image.rb
+++ b/src/app/models/provider_image.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 20110223132404
+# Schema version: 20110302120000
#
# Table name: provider_images
#
@@ -7,9 +7,8 @@
# image_id :integer not null
# provider_id :integer not null
# provider_image_key :string(255)
-# uploaded :boolean
-# registered :boolean
# uuid :string(255)
+# status :string(255)
#
class ProviderImage < ActiveRecord::Base
@@ -24,6 +23,14 @@ class ProviderImage < ActiveRecord::Base
validates_uniqueness_of :uuid, :allow_nil => true
validates_uniqueness_of :image_id, :scope => :provider_id
+ STATE_QUEUED = 'queued'
+ STATE_COMPLETE = 'complete'
+ STATE_CANCELED = 'canceled'
+ STATE_FAILED = 'failed'
+
+ ACTIVE_STATES = [ STATE_QUEUED ]
+ INACTIVE_STATES = [STATE_COMPLETE, STATE_FAILED, STATE_CANCELED]
+
def push
# TODO: this is just stubbed upload call,
# when new image_builder_service is done, replace
@@ -31,7 +38,7 @@ class ProviderImage < ActiveRecord::Base
end
def after_update
- if self.uploaded_changed? and self.uploaded == true
+ if self.status_changed? and self.status == STATE_COMPLETE
begin
invoke_sync
rescue => e
diff --git a/src/app/views/image_factory/templates/_builds.haml b/src/app/views/image_factory/templates/_builds.haml
index 6b5667a..79150c3 100644
--- a/src/app/views/image_factory/templates/_builds.haml
+++ b/src/app/views/image_factory/templates/_builds.haml
@@ -25,5 +25,4 @@ Builds for
%ul
- img.provider_images.each do |pimg|
%li
- / TODO: uploaded attr will go away, shoud be changed to status then
- = "#{pimg.provider.name}: #{pimg.uploaded ? 'uploaded' : 'not-uploaded'}"
+ = "#{pimg.provider.name}: #{pimg.status}"
diff --git a/src/db/migrate/20110302120000_add_status_to_provider_image.rb b/src/db/migrate/20110302120000_add_status_to_provider_image.rb
new file mode 100644
index 0000000..7a54db1
--- /dev/null
+++ b/src/db/migrate/20110302120000_add_status_to_provider_image.rb
@@ -0,0 +1,31 @@
+class AddStatusToProviderImage < ActiveRecord::Migration
+ def self.up
+ add_column :provider_images, :status, :string
+ ProviderImage.all.each do |image|
+ if image.uploaded
+ image.status = "complete"
+ else
+ image.status = "queued"
+ end
+ image.save!
+ end
+ remove_column :provider_images, :uploaded
+ remove_column :provider_images, :registered
+ end
+
+ def self.down
+ add_column :provider_images, :uploaded, :boolean
+ add_column :provider_images, :registered, :boolean
+ ProviderImage.all.each do |image|
+ if image.status == "complete"
+ image.uploaded = true
+ image.registered = true
+ else
+ image.uploaded = false
+ image.registered = false
+ end
+ image.save!
+ end
+ remove_column :provider_images, :status
+ end
+end
diff --git a/src/features/template.feature b/src/features/template.feature
index 7dd4643..859542a 100644
--- a/src/features/template.feature
+++ b/src/features/template.feature
@@ -122,7 +122,7 @@ Feature: Manage Templates
And I am on the image factory templates page
When I choose this template
And I follow "Builds"
- Then I should see "amazon-ec2: uploaded"
+ Then I should see "amazon-ec2: complete"
Scenario: Build template
Given there is a "mock1" template
diff --git a/src/image_builder_service/image_builder_service b/src/image_builder_service/image_builder_service
index 5167e10..19ea709 100755
--- a/src/image_builder_service/image_builder_service
+++ b/src/image_builder_service/image_builder_service
@@ -177,8 +177,7 @@ class ImageBuilderService
if new_status == 'complete'
ri = image.provider_images.first
ri.provider_image_key = obj[:build].finished_image
- ri.uploaded =true
- ri.registered=true
+ ri.status = ProviderImage::STATE_COMPLETE
ri.save!
# FIXME: Might be cleaner to do this in an active record observer instead.
diff --git a/src/spec/factories/provider_image.rb b/src/spec/factories/provider_image.rb
index 5de1a13..42053e8 100644
--- a/src/spec/factories/provider_image.rb
+++ b/src/spec/factories/provider_image.rb
@@ -2,8 +2,7 @@ Factory.define :provider_image do |ri|
ri.association :image
ri.association :provider
ri.sequence(:provider_image_key) { |n| "provider_image_key#(n)" }
- ri.uploaded true
- ri.registered true
+ ri.status "complete"
ri.association :icicle
end
--
1.7.4
13 years, 2 months
[PATCH conductor 1/2] delayed_jobs to build and push with new image factory console
by Richard Su
The jobs submits requests to the console. The console communicates
with the new factory. The responses are in xml and indicates the uuid.
---
src/app/models/build_job.rb | 69 ++++++++++++++++++++++++++++++++
src/app/models/image.rb | 17 ++------
src/app/models/provider_image.rb | 6 ---
src/app/models/push_job.rb | 72 ++++++++++++++++++++++++++++++++++
src/config/image_factory_console.yml | 2 +
src/spec/factories/build_job.rb | 7 +++
src/spec/factories/push_job.rb | 7 +++
src/spec/models/build_job_spec.rb | 10 +++++
src/spec/models/push_job_spec.rb | 11 +++++
9 files changed, 182 insertions(+), 19 deletions(-)
create mode 100644 src/app/models/build_job.rb
create mode 100644 src/app/models/push_job.rb
create mode 100644 src/config/image_factory_console.yml
create mode 100644 src/spec/factories/build_job.rb
create mode 100644 src/spec/factories/push_job.rb
create mode 100644 src/spec/models/build_job_spec.rb
create mode 100644 src/spec/models/push_job_spec.rb
diff --git a/src/app/models/build_job.rb b/src/app/models/build_job.rb
new file mode 100644
index 0000000..08450da
--- /dev/null
+++ b/src/app/models/build_job.rb
@@ -0,0 +1,69 @@
+#
+# Copyright (C) 2011 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+require 'typhoeus'
+require 'nokogiri'
+
+class BuildJob < Struct.new(:image_id, :hydra)
+
+ def perform
+ @hydra = hydra
+ print "--- start ---\n"
+ print "BuildJob for image_id: "
+ print image_id
+ print "\n"
+ return_uuid = nil
+ begin
+ if (@hydra == nil)
+ @hydra = Typhoeus::Hydra.new
+ end
+ image = Image.find(image_id)
+ template_url = YAML.load_file("#{RAILS_ROOT}/config/image_warehouse.yml")['baseurl'] + "/templates/" + image.template.uuid
+ request = Typhoeus::Request.new(YAML.load_file("#{RAILS_ROOT}/config/image_factory_console.yml")['buildurl'],
+ :method => :post,
+ :timeout => 60*1000, # in milliseconds
+ :params => {
+ :template => template_url,
+ :target => image.provider_type.codename})
+ request.on_complete do |response|
+ if response.success?
+ print "success "
+ xml = Nokogiri::XML(response.body)
+ return_uuid = xml.xpath('//image/uuid').first.text
+ image.uuid = return_uuid
+ image.save
+ print "uuid: "
+ print return_uuid
+ print "\n"
+ else
+ print "failure\n"
+ print response.body
+ print "\n"
+ end
+ end
+ @hydra.queue(request)
+ @hydra.run
+ rescue Exception => e
+ print "Exception: \n"
+ print e
+ print "\n"
+ end
+ print "--- done --- \n"
+ return return_uuid
+ end
+end
diff --git a/src/app/models/image.rb b/src/app/models/image.rb
index fc33b53..2bb8ad9 100644
--- a/src/app/models/image.rb
+++ b/src/app/models/image.rb
@@ -91,15 +91,6 @@ class Image < ActiveRecord::Base
end
end
- def build
- # TODO: this is just stubbed upload call,
- # when new image_builder_service is done, replace
- # with real request to image_builder_service
- unless self.provider_type.build_supported
- raise "Build is not supported on images with provider type #{self.provider_type.name}"
- end
- end
-
def self.create_and_build!(template, provider_type)
if Image.find_by_template_id_and_provider_type_id(template.id, provider_type.id)
raise ImageExistsError, "An attempted build of this template for the target '#{provider_type.name}' already exists"
@@ -114,10 +105,9 @@ class Image < ActiveRecord::Base
:template_id => template.id,
:status => Image::STATE_QUEUED
)
- img.delay.build
+ Delayed::Job.enqueue(BuildJob.new(img.id))
img
end
-
def self.single_import(providername, username, password, image_id)
account = Image.get_account(providername, username, password)
Image.import(account, image_id)
@@ -186,11 +176,12 @@ class Image < ActiveRecord::Base
provider_type.providers.each do |p|
# upload only to providers with account
unless p.provider_accounts.empty?
- ProviderImage.create!(
+ pimg = ProviderImage.create!(
:uuid => UUIDTools::UUID.timestamp_create.to_s,
:image => self,
:provider => p
- ).delay.push
+ )
+ Delayed::Job.enqueue(PushJob.new(pimg.id))
end
end
end
diff --git a/src/app/models/provider_image.rb b/src/app/models/provider_image.rb
index e218970..5e5ed3f 100644
--- a/src/app/models/provider_image.rb
+++ b/src/app/models/provider_image.rb
@@ -24,12 +24,6 @@ class ProviderImage < ActiveRecord::Base
validates_uniqueness_of :uuid, :allow_nil => true
validates_uniqueness_of :image_id, :scope => :provider_id
- def push
- # TODO: this is just stubbed upload call,
- # when new image_builder_service is done, replace
- # with real request to image_builder_service
- end
-
def after_update
if self.uploaded_changed? and self.uploaded == true
begin
diff --git a/src/app/models/push_job.rb b/src/app/models/push_job.rb
new file mode 100644
index 0000000..deec592
--- /dev/null
+++ b/src/app/models/push_job.rb
@@ -0,0 +1,72 @@
+#
+# Copyright (C) 2011 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+require 'typhoeus'
+require 'nokogiri'
+
+class PushJob < Struct.new(:provider_image_id, :hydra)
+ def perform
+ print "--- start ---\n"
+ print "PushJob for provider_image_id: "
+ print provider_image_id
+ print "\n"
+ # TODO: what if a provider has multiple accounts
+ # for now pick first account
+ begin
+ return_uuid = nil
+ @hydra = hydra
+ if (@hydra == nil)
+ @hydra = Typhoeus::Hydra.new
+ end
+ provider_image = ProviderImage.find(provider_image_id)
+ provider_account = provider_image.provider.provider_accounts.first
+ request = Typhoeus::Request.new(YAML.load_file("#{RAILS_ROOT}/config/image_factory_console.yml")['pushurl'],
+ :method => :post,
+ :timeout => 60*1000, # in milliseconds
+ :params => {
+ :image_id => provider_image.image.uuid,
+ :provider => provider_image.provider.name,
+ :credentials => provider_account.build_credentials
+ })
+ request.on_complete do |response|
+ if response.success?
+ print "success "
+ xml = Nokogiri::XML(response.body)
+ return_uuid = xml.xpath('//image/uuid').first.text
+ provider_image.uuid = return_uuid
+ provider_image.uploaded = true
+ provider_image.save
+ print "uuid: "
+ print return_uuid
+ print "\n"
+ else
+ print "failure\n"
+ print response.body
+ end
+ end
+ @hydra.queue(request)
+ @hydra.run
+ rescue Exception => e
+ print "Exception: \n"
+ print e
+ print "\n"
+ end
+ print "--- done --- \n"
+ return return_uuid
+ end
+end
diff --git a/src/config/image_factory_console.yml b/src/config/image_factory_console.yml
new file mode 100644
index 0000000..b5d66d6
--- /dev/null
+++ b/src/config/image_factory_console.yml
@@ -0,0 +1,2 @@
+buildurl: http://localhost:2003/build
+pushurl: http://localhost:2003/push
diff --git a/src/spec/factories/build_job.rb b/src/spec/factories/build_job.rb
new file mode 100644
index 0000000..6f3186c
--- /dev/null
+++ b/src/spec/factories/build_job.rb
@@ -0,0 +1,7 @@
+Factory.define :build_job do |p|
+ hydra = Typhoeus::Hydra.new
+ response = Typhoeus::Response.new(:code => 200, :headers => "", :body => "<?xml version=\"1.0\" encoding=\"UTF-8\"><image><uuid>build-job-stub-id</uuid></image>", :time => 0.1)
+ hydra.stub(:post, YAML.load_file("#{RAILS_ROOT}/config/image_factory_console.yml")['buildurl']).and_return(response)
+ p.image_id 1
+ p.hydra hydra
+end
diff --git a/src/spec/factories/push_job.rb b/src/spec/factories/push_job.rb
new file mode 100644
index 0000000..f4346dc
--- /dev/null
+++ b/src/spec/factories/push_job.rb
@@ -0,0 +1,7 @@
+Factory.define :push_job do |p|
+ hydra = Typhoeus::Hydra.new
+ response = Typhoeus::Response.new(:code => 200, :headers => "", :body => "<?xml version=\"1.0\" encoding=\"UTF-8\"><image><uuid>push-job-stub-id</uuid></image>", :time => 0.1)
+ hydra.stub(:post, YAML.load_file("#{RAILS_ROOT}/config/image_factory_console.yml")['pushurl']).and_return(response)
+ p.provider_image_id 10
+ p.hydra hydra
+end
diff --git a/src/spec/models/build_job_spec.rb b/src/spec/models/build_job_spec.rb
new file mode 100644
index 0000000..aa4cae7
--- /dev/null
+++ b/src/spec/models/build_job_spec.rb
@@ -0,0 +1,10 @@
+require 'spec_helper'
+
+describe BuildJob do
+ it "should match request and parse stubbed xml" do
+ image = Factory.create(:image, :id => 1)
+ job = Factory.build(:build_job)
+ uuid = job.perform
+ uuid.should == "build-job-stub-id"
+ end
+end
diff --git a/src/spec/models/push_job_spec.rb b/src/spec/models/push_job_spec.rb
new file mode 100644
index 0000000..b728478
--- /dev/null
+++ b/src/spec/models/push_job_spec.rb
@@ -0,0 +1,11 @@
+require 'spec_helper'
+
+describe PushJob do
+ it "should match request and parse stubbed xml" do
+ provider_account = Factory.create(:mock_provider_account)
+ provider_image = Factory.create(:provider_image, :id => 10, :provider => provider_account.provider)
+ job = Factory.build(:push_job)
+ uuid = job.perform
+ uuid.should == "push-job-stub-id"
+ end
+end
--
1.7.4
13 years, 2 months
[PATCH conductor] Fix BZ 678071
by Tomas Sedovic
From: Tomas Sedovic <tsedovic(a)redhat.com>
https://bugzilla.redhat.com/show_bug.cgi?id=678071
The user couldn't delete a provider account that had any instances associated
with it -- even if these instances were stopped. Moreover, the UI did not show
any error message.
This fix allows deleting an account that has all its instances in the 'stopped'
state and shows a propper message.
---
.../admin/provider_accounts_controller.rb | 23 ++++++++++++++++---
src/app/models/provider_account.rb | 2 +-
src/config/locales/en.yml | 6 +++++
3 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/src/app/controllers/admin/provider_accounts_controller.rb b/src/app/controllers/admin/provider_accounts_controller.rb
index 6affc73..ceffe17 100644
--- a/src/app/controllers/admin/provider_accounts_controller.rb
+++ b/src/app/controllers/admin/provider_accounts_controller.rb
@@ -119,13 +119,28 @@ class Admin::ProviderAccountsController < ApplicationController
end
def multi_destroy
- if (not params[:accounts_selected]) or (params[:accounts_selected].length == 0)
+ if params[:accounts_selected].blank?
flash[:notice] = "You must select some accounts first."
- else
- ProviderAccount.find(params[:accounts_selected]).each do |account|
- account.destroy if check_privilege(Privilege::MODIFY, account)
+ redirect_to admin_provider_accounts_url and return
+ end
+
+ succeeded = []
+ failed = []
+ ProviderAccount.find(params[:accounts_selected]).each do |account|
+ if check_privilege(Privilege::MODIFY, account) && account.destroyable?
+ account.destroy
+ succeeded << account.label
+ else
+ failed << account.label
end
end
+
+ unless succeeded.empty?
+ flash[:notice] = t 'provider_accounts.index.account_deleted', :count => succeeded.length, :list => succeeded.join(', ')
+ end
+ unless failed.empty?
+ flash[:error] = t 'provider_accounts.index.account_not_deleted', :count => failed.length, :list => failed.join(', ')
+ end
redirect_to admin_provider_accounts_url
end
diff --git a/src/app/models/provider_account.rb b/src/app/models/provider_account.rb
index 6ed677b..076bafd 100644
--- a/src/app/models/provider_account.rb
+++ b/src/app/models/provider_account.rb
@@ -114,7 +114,7 @@ class ProviderAccount < ActiveRecord::Base
end
def destroyable?
- instances.empty?
+ instances.all? { |i| i.state == Instance::STATE_STOPPED }
end
def read_x509_files
diff --git a/src/config/locales/en.yml b/src/config/locales/en.yml
index 233cd14..da36621 100644
--- a/src/config/locales/en.yml
+++ b/src/config/locales/en.yml
@@ -119,6 +119,12 @@ en:
provider_accounts:
index:
provider_accounts: Provider Accounts
+ account_deleted:
+ one: "Account %{list} was deleted."
+ other: "Accounts %{list} were deleted."
+ account_not_deleted:
+ one: "Account %{list} was not deleted. Its instances must be stopped first."
+ other: "Accounts %{list} were not deleted. Their instances must be stopped first."
new:
new_provider_account: New Account
required_field: Required field.
--
1.7.4
13 years, 2 months
[PATCH conductor 2/2] template xml change to conform to new format
by Richard Su
new format: https://github.com/clalancette/oz/blob/master/examples/f14x86_64.tdl
---
src/app/models/template.rb | 8 ++-
src/app/util/image_descriptor_xml.rb | 74 ++++++++++++-------
.../image_descriptor_package_repositories.yml | 2 +-
3 files changed, 53 insertions(+), 31 deletions(-)
diff --git a/src/app/models/template.rb b/src/app/models/template.rb
index b84409c..71d835b 100644
--- a/src/app/models/template.rb
+++ b/src/app/models/template.rb
@@ -67,9 +67,11 @@ class Template < ActiveRecord::Base
def update_xml
xml.name = self.name
xml.description = self.summary
- xml.platform = self.platform
- xml.platform_version = self.platform_version
- xml.architecture = self.architecture
+ platform = {}
+ platform['name'] = self.platform.capitalize
+ platform['version'] = self.platform_version
+ platform['arch'] = self.architecture
+ xml.platform = platform
write_attribute(:xml, xml.to_xml)
end
diff --git a/src/app/util/image_descriptor_xml.rb b/src/app/util/image_descriptor_xml.rb
index 70f2e34..3a4bbae 100644
--- a/src/app/util/image_descriptor_xml.rb
+++ b/src/app/util/image_descriptor_xml.rb
@@ -28,9 +28,9 @@ class ImageDescriptorXML
@doc = Nokogiri::XML(xmlstr)
# create at least root node if it doesn't exist
unless @doc.root
- @doc.root = Nokogiri::XML::Node.new('image', @doc)
+ @doc.root = Nokogiri::XML::Node.new('template', @doc)
end
- @root = @doc.root.at_xpath('/image')
+ @root = @doc.root.at_xpath('/template')
end
def name=(str)
@@ -42,45 +42,65 @@ class ImageDescriptorXML
return get_node_text('name')
end
+ def description=(str)
+ node = get_or_create_node('description')
+ node.content = str
+ end
+
+ def description
+ return get_node_text('description')
+ end
+
def platform
- node = @root.at_xpath('/image/os')
+ node = @root.at_xpath('/template/os')
return node ? node['name'] : nil
end
- def platform=(str)
+ def platform=(platform_hash)
# FIXME: we remove all repos because we don't know which one is for
# platform
# update: we don't add platform repo, image builder chooses right one from OS
# name, but we add all other repos
#recreate_repo_nodes
- get_or_create_node('os')['name'] = str
+ platform_node = get_or_create_node('os')
+ platform_node.xpath('.//*').remove
+ platform_hash.each do |key, value|
+ snode = Nokogiri::XML::Node.new(key, @doc)
+ platform_node << snode
+ snode.content = value
+ end
+ install_node = Nokogiri::XML::Node.new('install', @doc)
+ install_node.set_attribute('type', 'url')
+ platform_node << install_node
+ url_node = Nokogiri::XML::Node.new('url', @doc)
+ # TODO: change when more than one os is supported by conductor
+ # url_node.content = "http://download.fedoraproject.org/pub/fedora/linux/releases/13/Fedora/x86..."
+ url_node.content = YAML.load_file("#{RAILS_ROOT}/config/image_descriptor_package_repositories.yml")['baseurl']
+ install_node << url_node
end
def platform_version
- node = @root.at_xpath('/image/os')
- return node ? node['version'] : nil
- end
-
- def platform_version=(str)
- get_or_create_node('os')['version'] = str
+ node = @root.at_xpath('/image/os/version')
+ return node ? node.content : nil
end
def architecture
- node = @root.at_xpath('/image/os')
- return node ? node['architecture'] : nil
+ node = @root.at_xpath('/template/os/arch')
+ return node ? node.content : nil
end
def architecture=(str)
get_or_create_node('os')['architecture'] = str
end
- def description=(str)
- node = get_or_create_node('description')
- node.content = str
- end
-
- def description
- return get_node_text('description')
+ def services=(services)
+ service_node = get_or_create_node('services')
+ service_node.xpath('.//service').remove
+ platform_hash.each do |key, value|
+ snode = Nokogiri::XML::Node.new(key, @doc)
+ platform_node << snode
+ snode.content = value
+ end
end
def services=(services)
@@ -97,7 +117,7 @@ class ImageDescriptorXML
def services
unless @services
@services = []
- @root.xpath('/image/services/service').each do |s|
+ @root.xpath('/template/services/service').each do |s|
services << s.text
end
end
@@ -109,13 +129,13 @@ class ImageDescriptorXML
end
def packages
- @root.xpath('/image/packages/package').map do |s|
+ @root.xpath('/template/packages/package').map do |s|
s.at_xpath('.//name').text
end
end
def groups
- @root.xpath('/image/groups/group').map do |s|
+ @root.xpath('/template/groups/group').map do |s|
s.at_xpath('.//name').text
end
end
@@ -138,7 +158,7 @@ class ImageDescriptorXML
end
def remove_package(package)
- @root.xpath('/image/packages/package').each do |s|
+ @root.xpath('/template/packages/package').each do |s|
if name = s.at_xpath('.//name') and name.text.to_s == package
s.remove
end
@@ -146,11 +166,11 @@ class ImageDescriptorXML
end
def clear_packages
- @root.xpath('/image/packages').each { |s| s.remove }
+ @root.xpath('/template/packages').each { |s| s.remove }
end
def clear_groups
- @root.xpath('/image/groups').each { |s| s.remove }
+ @root.xpath('/template/groups').each { |s| s.remove }
end
private
@@ -180,7 +200,7 @@ class ImageDescriptorXML
end
def get_node_text(path)
- node = @root.at_xpath('/image/' + path)
+ node = @root.at_xpath('/template/' + path)
return node ? node.text : nil
end
diff --git a/src/config/image_descriptor_package_repositories.yml b/src/config/image_descriptor_package_repositories.yml
index c600ccc..12a15d1 100644
--- a/src/config/image_descriptor_package_repositories.yml
+++ b/src/config/image_descriptor_package_repositories.yml
@@ -1,6 +1,6 @@
id: fedora
name: Fedora
-baseurl: http://download.fedoraproject.org/pub/fedora/linux/releases/13/Everything...
+baseurl: http://download.fedoraproject.org/pub/fedora/linux/releases/13/Fedora/x86...
type: xml
# you can define multiple repositories, as array, for example:
--
1.7.4
13 years, 2 months
[PATCH 1/2] Redmine Task #578 -- Check NTP is correctly configured
by steve linabery
---
spec/configure_spec.rb | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/spec/configure_spec.rb b/spec/configure_spec.rb
index 01f7816..2958961 100644
--- a/spec/configure_spec.rb
+++ b/spec/configure_spec.rb
@@ -69,4 +69,9 @@ describe "aeolus-configure" do
node.content.should =~ /.*Red Hat Cloud Engine.*/
end
+ it "should properly configure ntpd" do
+ #This ensures that ntpd is a client to at least one upstream ntp server
+ output = `/bin/echo listpeers | /usr/sbin/ntpdc`
+ output.should =~ /.*client.*/
+ end
end
--
1.7.4
13 years, 2 months
[PATCH 1/2] Redmine Task #578 -- Check NTP is correctly configured
by steve linabery
---
spec/configure_spec.rb | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/spec/configure_spec.rb b/spec/configure_spec.rb
index 01f7816..2958961 100644
--- a/spec/configure_spec.rb
+++ b/spec/configure_spec.rb
@@ -69,4 +69,9 @@ describe "aeolus-configure" do
node.content.should =~ /.*Red Hat Cloud Engine.*/
end
+ it "should properly configure ntpd" do
+ #This ensures that ntpd is a client to at least one upstream ntp server
+ output = `/bin/echo listpeers | /usr/sbin/ntpdc`
+ output.should =~ /.*client.*/
+ end
end
--
1.7.4
13 years, 2 months
[PATCH Conductor] REST API call for image status updates
by Scott Seago
There are two patches here -- one refactors the ProviderImage model to replace the
boolean 'uploaded' and 'registered' fields with a single 'status' field to
match the way Image is handled. The second implements an update_status
REST API call for the image factory console to update the status of a
current build or push operation.
Patches are numbered 9 and 10 because they must currently be applied on
top of jprovazn's patches:
[PATCH conductor 6/8] warehouse_sync - first shot
and the 7 patch set: warehouse integration (rev. 4)
13 years, 2 months
[PATCH] warehouse_sync - first shot (revised)
by steve linabery
From: Jan Provaznik <jprovazn(a)redhat.com>
periodically pulls data from warehouse and updates conductor's db
corrected to include conductor-warehouse_sync script in aeolus-conductor.spec.in
---
aeolus-conductor.spec.in | 5 +
conf/conductor-warehouse_sync | 78 ++++++++++++++++
src/app/models/template.rb | 8 ++
src/warehouse_sync/warehouse_sync-server | 89 ++++++++++++++++++
src/warehouse_sync/warehouse_sync.rb | 144 ++++++++++++++++++++++++++++++
5 files changed, 324 insertions(+), 0 deletions(-)
create mode 100755 conf/conductor-warehouse_sync
create mode 100755 src/warehouse_sync/warehouse_sync-server
create mode 100644 src/warehouse_sync/warehouse_sync.rb
diff --git a/aeolus-conductor.spec.in b/aeolus-conductor.spec.in
index 6e44e8b..6babce9 100644
--- a/aeolus-conductor.spec.in
+++ b/aeolus-conductor.spec.in
@@ -128,6 +128,7 @@ mv %{buildroot}/%{app_root}/doc %{buildroot}/%{app_root}/test %{buildroot}/%{doc
%{__cp} conf/conductor-condor_refreshd %{buildroot}%{_initrddir}
%{__cp} conf/conductor-image_builder_service %{buildroot}%{_initrddir}
%{__cp} conf/conductor-delayed_job %{buildroot}%{_initrddir}
+%{__cp} conf/conductor-warehouse_sync %{buildroot}%{_initrddir}
%{__cp} conf/aeolus-conductor-httpd.conf %{buildroot}%{_sysconfdir}/httpd/conf.d/aeolus-conductor.conf
%{__cp} conf/aeolus-conductor.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/aeolus-conductor
%{__cp} conf/aeolus-conductor.sysconf %{buildroot}%{_sysconfdir}/sysconfig/aeolus-conductor
@@ -195,6 +196,7 @@ getent passwd aeolus >/dev/null || \
/sbin/chkconfig --add conductor-condor_refreshd
/sbin/chkconfig --add conductor-image_builder_service
/sbin/chkconfig --add conductor-delayed_job
+/sbin/chkconfig --add conductor-warehouse_sync
%preun daemons
if [ $1 = 0 ]; then
@@ -208,6 +210,8 @@ if [ $1 = 0 ]; then
/sbin/chkconfig --del conductor-image_builder_service
/sbin/service conductor-delayed_job stop > /dev/null 2>&1
/sbin/chkconfig --del conductor-delayed_job
+/sbin/service conductor-warehouse_sync stop > /dev/null 2>&1
+/sbin/chkconfig --del conductor-warehouse_sync
fi
%files
@@ -229,6 +233,7 @@ fi
%{_initrddir}/conductor-condor_refreshd
%{_initrddir}/conductor-image_builder_service
%{_initrddir}/conductor-delayed_job
+%{_initrddir}/conductor-warehouse_sync
%config(noreplace) %{_sysconfdir}/logrotate.d/%{name}
%config(noreplace) %{_sysconfdir}/sysconfig/aeolus-conductor
%config(noreplace) %{_sysconfdir}/sysconfig/conductor-rails
diff --git a/conf/conductor-warehouse_sync b/conf/conductor-warehouse_sync
new file mode 100755
index 0000000..38b9f35
--- /dev/null
+++ b/conf/conductor-warehouse_sync
@@ -0,0 +1,78 @@
+#!/bin/bash
+#
+#
+# conductor-warehouse_sync startup script for conductor-warehouse_sync
+#
+# chkconfig: - 99 01
+# description: conductor-warehouse_sync populates the Conductor scheduler
+# from the Aeolus Conductor db
+
+[ -r /etc/sysconfig/conductor-rails ] && . /etc/sysconfig/conductor-rails
+
+[ -r /etc/sysconfig/aeolus-conductor ] && . /etc/sysconfig/aeolus-conductor
+
+CONDUCTOR_DIR="${CONDUCTOR_DIR:-/usr/share/aeolus-conductor}"
+REFRESHD_LOG="${REFRESHD_LOG:-/var/log/aeolus-conductor/warehouse_sync.log}"
+REFRESHD_PID="${REFRESHD_PID:-/var/run/aeolus-conductor/warehouse_sync.pid}"
+REFRESHD_LOCKFILE="${REFRESHD_LOCKFILE:-/var/lock/subsys/conductor-warehouse_sync}"
+AEOLUS_USER="${AEOLUS_USER:-aeolus}"
+
+REFRESHD_PATH=$CONDUCTOR_DIR/warehouse_sync
+REFRESHD_PROG=warehouse_sync-server
+
+. /etc/init.d/functions
+
+start() {
+ echo -n "Starting conductor-warehouse_sync: "
+
+ daemon --user=$AEOLUS_USER $REFRESHD_PATH/$REFRESHD_PROG
+ RETVAL=$?
+ if [ $RETVAL -eq 0 ] && touch $REFRESHD_LOCKFILE ; then
+ echo_success
+ echo
+ else
+ echo_failure
+ echo
+ fi
+}
+
+stop() {
+ echo -n "Shutting down conductor-warehouse_sync: "
+ killproc -p $REFRESHD_PID $REFRESHD_PROG
+ RETVAL=$?
+ if [ $RETVAL -eq 0 ] && rm -f $REFRESHD_LOCKFILE ; then
+ echo_success
+ echo
+ else
+ echo_failure
+ echo
+ fi
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ restart)
+ stop
+ start
+ ;;
+ reload)
+ ;;
+ force-reload)
+ restart
+ ;;
+ status)
+ status -p $REFRESHD_PID $REFRESHD_PROG
+ RETVAL=$?
+ ;;
+ *)
+ echo "Usage: conductor-warehouse_sync {start|stop|restart|status}"
+ exit 1
+ ;;
+esac
+
+exit $RETVAL
diff --git a/src/app/models/template.rb b/src/app/models/template.rb
index b84409c..21efc6f 100644
--- a/src/app/models/template.rb
+++ b/src/app/models/template.rb
@@ -73,6 +73,14 @@ class Template < ActiveRecord::Base
write_attribute(:xml, xml.to_xml)
end
+ def update_from_xml
+ self.name = xml.name
+ self.summary = xml.description
+ self.platform = xml.platform
+ self.platform_version = xml.platform_version
+ self.architecture = xml.architecture
+ end
+
def providers
# TODO: rewrite cleanly
ProviderImage.all(
diff --git a/src/warehouse_sync/warehouse_sync-server b/src/warehouse_sync/warehouse_sync-server
new file mode 100755
index 0000000..89ec30d
--- /dev/null
+++ b/src/warehouse_sync/warehouse_sync-server
@@ -0,0 +1,89 @@
+#!/usr/bin/ruby
+
+$: << File.dirname(__FILE__)
+
+require 'rubygems'
+require 'optparse'
+require 'warehouse_sync'
+
+DELAY = 5
+WAREHOUSE_CONFIG = YAML.load_file(File.join(File.dirname(__FILE__), "../config/image_warehouse.yml"))
+
+# show timestamp in log file
+class Logger
+ def format_message(severity, timestamp, progname, msg)
+ time = timestamp.getutc.strftime("%Y-%m-%d %H:%M:%S")
+ "\n#{time}:#{severity.to_s.upcase}: #{msg}"
+ end
+end
+
+help = false
+daemon = true
+log_dir = "/var/log/aeolus-conductor"
+pid_dir = "/var/run/aeolus-conductor"
+
+optparse = OptionParser.new do |opts|
+
+ opts.banner = <<BANNER
+Usage:
+warehouse_sync [options]
+
+Options:
+BANNER
+ opts.on( '-f', '--pid-file PATH', "Use PATH to the warehouse_sync pid directory (defaults to #{pid_dir})") do |newpath|
+ pid_dir = newpath
+ end
+ opts.on( '-h', '--help', '') { help = true }
+ opts.on( '-l', '--log PATH', "Use PATH to the warehouse_sync log directory (defaults to #{log_dir}). Use '-' for stdout") do |newpath|
+ log_dir = newpath
+ end
+ opts.on( '-n', '--nodaemon', 'Do not daemonize (useful in combination with -l for debugging)') { daemon = false }
+end
+
+begin
+ optparse.parse!
+rescue OptionParser::InvalidOption => e
+ puts "Invalid option #{e.args}"
+ puts
+ puts optparse
+ exit(1)
+end
+
+if help
+ puts optparse
+ exit(0)
+end
+
+if log_dir == '-'
+ LOG_FILE = STDOUT
+else
+ LOG_FILE = "#{log_dir}/warehouse_sync.log"
+end
+
+logger = Logger.new(LOG_FILE)
+logger.level = Logger::DEBUG
+logger.datetime_format = "%Y-%m-%d %H:%M:%S"
+logger.info "Warehouse_sync starting up"
+
+def create_pid_file(file)
+ FileUtils.mkdir_p File.dirname(file)
+ open(file, "w") {|f| f.write(Process.pid) }
+ File.chmod(0644, file)
+end
+
+# daemonize
+if daemon
+ # note that this requires 'active_support', which we get for free from dutils
+ Process.daemon
+end
+
+begin
+ #create_pid_file("#{pid_dir}/warehouse_sync.pid")
+ WarehouseSync.new(:uri => WAREHOUSE_CONFIG['baseurl'], :logger => logger, :delay => DELAY * 60).run
+rescue Exception => e
+ logger.error "#{e.backtrace.shift}: #{e.message}"
+ e.backtrace.each do |step|
+ logger.error "\tfrom #{step}"
+ end
+ exit 1
+end
diff --git a/src/warehouse_sync/warehouse_sync.rb b/src/warehouse_sync/warehouse_sync.rb
new file mode 100644
index 0000000..c28213d
--- /dev/null
+++ b/src/warehouse_sync/warehouse_sync.rb
@@ -0,0 +1,144 @@
+$: << File.join(File.dirname(__FILE__), "../dutils")
+
+require 'rubygems'
+require 'dutils'
+require 'warehouse_client'
+
+class WarehouseSync
+ def initialize(opts)
+ @uri = opts[:uri]
+ @delay = opts[:delay] || 10*60
+ @logger = opts[:logger]
+ @whouse = Warehouse::Client.new(@uri)
+ end
+
+ def run
+ while true
+ begin
+ @logger.debug "---------------------------------------"
+ pull_templates
+ pull_images
+ pull_provider_images
+ rescue => e
+ @logger.error e.message
+ @logger.error "backtrace:\n" + e.backtrace.join("\n ")
+ ensure
+ @logger.debug "sleep #{@delay}"
+ sleep @delay
+ end
+ end
+ end
+
+ def pull_templates
+ @logger.debug "*** Getting templates"
+ @whouse.bucket('templates').objects.each do |bucket_obj|
+ safely_process(bucket_obj) do |obj|
+ attrs = obj.attrs([:uuid])
+ #unless tpl = Template.find_by_uuid(attrs[:uuid])
+ # raise "Template with uuid #{attrs[:uuid]} not found"
+ #end
+ tpl = Template.find_by_uuid(attrs[:uuid]) || Template.new(:uuid => attrs[:uuid])
+ tpl.xml = obj.body
+ tpl.update_from_xml
+ update_changes(tpl)
+ end
+ end
+ end
+
+ def pull_images
+ @logger.debug "*** Getting images"
+ @whouse.bucket('images').objects.each do |bucket_obj|
+ safely_process(bucket_obj) do |obj|
+ attrs = obj.attrs([:uuid, :target, :template])
+ #img = Image.find_by_uuid(attrs[:uuid]) || Image.new(:uuid => attrs[:uuid])
+ unless img = Image.find_by_uuid(attrs[:uuid])
+ raise "image with uuid #{attrs[:uuid]} not found"
+ end
+ unless attrs[:target]
+ raise "target uuid is not set"
+ end
+ unless ptype = ProviderType.find_by_codename(attrs[:target])
+ raise "provider type #{attrs[:target]} not found"
+ end
+ unless attrs[:template]
+ raise "template uuid is not set"
+ end
+ unless tpl = Template.find_by_uuid(attrs[:template])
+ raise "Template with uuid #{attrs[:template]} not found"
+ end
+ img.provider_type_id = ptype.id
+ img.template_id = tpl.id
+ update_changes(img)
+ end
+ end
+ end
+
+ def pull_provider_images
+ @logger.debug "*** Getting provider images"
+ @whouse.bucket('provider_images').objects.each do |bucket_obj|
+ safely_process(bucket_obj) do |obj|
+ attrs = obj.attrs([:uuid, :image, :icicle])
+ # we don't allow create non-existing ProviderImage in conductor because
+ # we don't know provider_id (provider attribute contains only url or
+ # string which is not unique in conductor)
+ unless pimg = ProviderImage.find_by_uuid(attrs[:uuid])
+ raise "provider image with uuid #{attrs[:uuid]} not found"
+ end
+ unless attrs[:image]
+ raise "image uuid is not set"
+ end
+ unless img = Image.find_by_uuid(attrs[:image])
+ raise "image with uuid #{attrs[:image]} not found"
+ end
+ unless attrs[:icicle]
+ raise "icicle uuid is not set"
+ end
+ pimg.image_id = img.id
+ pimg.icicle = pull_provider_image_icicle(attrs[:icicle])
+ # TODO: set target_identifier too?
+ update_changes(img)
+ end
+ end
+ end
+
+ private
+
+ def pull_provider_image_icicle(uuid)
+ @logger.debug " getting provider image icicle with uuid #{uuid}"
+ whouse_icicle = @whouse.bucket('icicles').object(uuid)
+ icicle = Icicle.find_by_uuid(uuid) || Icicle.new(:uuid => uuid)
+ icicle.xml = whouse_icicle.body
+ icicle.uuid = uuid
+ update_changes(icicle)
+ icicle
+ end
+
+ def safely_process(obj)
+ begin
+ yield obj
+ rescue => e
+ @logger.error "Error while processing #{obj.key} (skipping): #{e.message}"
+ @logger.debug e.backtrace.join("\n ")
+ end
+ end
+
+ def update_changes(obj)
+ if obj.new_record?
+ @logger.debug "#{obj.class.class_name} #{obj.uuid} is not in DB, saving"
+ obj.save!
+ elsif obj.changed?
+ @logger.debug "#{obj.class.class_name} #{obj.uuid} has been changed:"
+ log_changes(obj)
+ obj.save!
+ else
+ @logger.debug "#{obj.class.class_name} #{obj.uuid} is without changes"
+ end
+ end
+
+ def log_changes(obj)
+ obj.changed.each do |attr|
+ @logger.debug "old #{attr}: #{obj.send(attr + '_was')}"
+ @logger.debug "new #{attr}: #{obj[attr]}"
+ end
+ end
+end
--
1.7.4
13 years, 2 months
warehouse sync script
by Jan Provazník
First patch is for configure repo, second for conductor repo. This script
polls warehouse and updates conductor db with data from warehouse.
[PATCH configure] Start/stop script for warehouse sync
[PATCH conductor] warehouse_sync - first shot
13 years, 2 months