imagefactory-console 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,77 @@
1
+ #
2
+ # Copyright (C) 2011 Red Hat, Inc.
3
+ # Written by Jason Guiditta <jguiditt@redhat.com>
4
+ #
5
+ # This program is free software; you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation; version 2 of the License.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ # MA 02110-1301, USA. A copy of the GNU General Public License is
18
+ # also available at http://www.gnu.org/copyleft/gpl.html.
19
+
20
+
21
+ require 'rubygems'
22
+ require 'rake'
23
+ require 'rake/clean'
24
+ require 'rake/gempackagetask'
25
+ require 'rake/rdoctask'
26
+ require 'rake/testtask'
27
+ require 'spec/rake/spectask'
28
+ require 'rake/rpmtask'
29
+
30
+ RPMBUILD_DIR = "#{File.expand_path('~')}/rpmbuild"
31
+ RPM_SPEC = "rubygem-imagefactory-console.spec"
32
+
33
+ spec = Gem::Specification.new do |s|
34
+ s.name = 'imagefactory-console'
35
+ s.version = '0.4.0'
36
+ s.has_rdoc = true
37
+ #s.extra_rdoc_files = ['README', 'COPYING']
38
+ s.summary = 'QMF Console for Aeolus Image Factory'
39
+ s.description = s.summary
40
+ s.author = 'Jason Guiditta'
41
+ s.email = 'jguiditt@redhat.com'
42
+ # s.executables = ['your_executable_here']
43
+ s.files = %w(Rakefile) + Dir.glob("{bin,lib,spec}/**/*")
44
+ s.require_path = "lib"
45
+ s.bindir = "bin"
46
+ end
47
+
48
+ Rake::GemPackageTask.new(spec) do |p|
49
+ p.gem_spec = spec
50
+ p.need_tar = true
51
+ p.need_zip = true
52
+ end
53
+
54
+ Rake::RDocTask.new do |rdoc|
55
+ files =['lib/**/*.rb'] #'README', 'COPYING',
56
+ rdoc.rdoc_files.add(files)
57
+ #rdoc.main = "README" # page to start on
58
+ rdoc.title = "console Docs"
59
+ rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder
60
+ rdoc.options << '--line-numbers'
61
+ end
62
+
63
+ Rake::TestTask.new do |t|
64
+ t.test_files = FileList['test/**/*.rb']
65
+ end
66
+
67
+ Spec::Rake::SpecTask.new do |t|
68
+ t.libs << 'lib'
69
+ t.spec_files = FileList['spec/**/*.rb']
70
+ t.spec_opts = ['--color', '--format nested']
71
+ end
72
+
73
+ Rake::RpmTask.new(RPM_SPEC) do |rpm|
74
+ rpm.need_tar = true
75
+ rpm.package_files.include("lib/*")
76
+ rpm.topdir = "#{RPMBUILD_DIR}"
77
+ end
@@ -0,0 +1,2 @@
1
+ require 'imagefactory/console'
2
+ require 'imagefactory/base_handler'
@@ -0,0 +1,56 @@
1
+ #
2
+ # Copyright (C) 2011 Red Hat, Inc.
3
+ # Written by Jason Guiditta <jguiditt@redhat.com>
4
+ #
5
+ # This program is free software; you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation; version 2 of the License.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ # MA 02110-1301, USA. A copy of the GNU General Public License is
18
+ # also available at http://www.gnu.org/copyleft/gpl.html.
19
+
20
+ require 'logger'
21
+
22
+ class BaseHandler
23
+
24
+ def initialize(logger=nil)
25
+ logger(logger)
26
+ end
27
+
28
+ def handle(data)
29
+ logger.debug "====== Type of event: #{data.event}"
30
+ if data.event == 'STATUS'
31
+ logger.debug "calling handle status in base handler"
32
+ handle_status(data)
33
+ elsif data.event == 'FAILURE'
34
+ handle_failed(data)
35
+ end
36
+ end
37
+
38
+ def handle_status(data)
39
+ logger.debug "{data.event}, #{data.new_status}"
40
+ end
41
+
42
+ def handle_failed(data)
43
+ logger.error "#{data.to_s}"
44
+ end
45
+
46
+ protected
47
+ def logger(logger=nil)
48
+ @logger ||= logger
49
+ unless @logger
50
+ @logger = Logger.new(STDOUT)
51
+ @logger.level = Logger::ERROR
52
+ @logger.datetime_format = "%Y-%m-%d %H:%M:%S"
53
+ end
54
+ return @logger
55
+ end
56
+ end
@@ -0,0 +1,251 @@
1
+ #
2
+ # Copyright (C) 2011 Red Hat, Inc.
3
+ # Written by Jason Guiditta <jguiditt@redhat.com>
4
+ #
5
+ # This program is free software; you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation; version 2 of the License.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ # MA 02110-1301, USA. A copy of the GNU General Public License is
18
+ # also available at http://www.gnu.org/copyleft/gpl.html.
19
+
20
+ # TODO: figure out what I am doing wrong here that I need this line
21
+ $: << File.expand_path(File.join(File.dirname(__FILE__), "."))
22
+ require 'cqpid'
23
+ require 'qmf2'
24
+ require 'logger'
25
+ require 'base_handler'
26
+
27
+ class ImageFactoryConsole < Qmf2::ConsoleHandler
28
+
29
+ attr_accessor :q, :handler
30
+
31
+ def initialize(args={})
32
+ # @retry_limit = args.include?(:retry_limit) ? args[:retry_limit] : 20
33
+ # @delay = args.include?(:delay) ? args[:delay] : 15
34
+ host = args.include?(:host) ? args[:host] : "localhost"
35
+ port = args.include?(:port) ? args[:port] : 5672
36
+ # url = "amqp://#{host}:#{port}" <- the amqp part here doesnt work yet
37
+ url = "#{host}:#{port}"
38
+ opts = {"reconnect"=>"true"}
39
+ @connection = Cqpid::Connection.new(url, opts)
40
+ @connection.open
41
+ @session = Qmf2::ConsoleSession.new(@connection)
42
+ @session.open
43
+ @session.set_agent_filter("[and, [eq, _vendor, [quote, 'redhat.com']], [eq, _product, [quote, 'imagefactory']]]")
44
+
45
+ if args.include?(:logger)
46
+ @logger = args[:logger]
47
+ else
48
+ @logger = Logger.new(STDOUT)
49
+ @logger.level = Logger::ERROR
50
+ @logger.datetime_format = "%Y-%m-%d %H:%M:%S"
51
+ end
52
+ @handler = args.include?(:handler)? args[:handler]: BaseHandler.new(@logger)
53
+ super(@session)
54
+ end
55
+
56
+ # Call this method to initiate a build, and get back an
57
+ # array of BuildAdaptor objects.
58
+ # * template => String
59
+ # Description of what to build. Can be xml, uuid, or url
60
+ # * targets => Array
61
+ # Represents the names of the clouds to target (ec2, mock, rackspace, etc)
62
+ # * image_id => String
63
+ # The UUID of an image previously built
64
+ # * build_id => String
65
+ # The UUID of a previous build of the image
66
+ # * Returns => an array of BuildAdaptor objects
67
+ #
68
+ def build(template, targets, image='', build='')
69
+ targets = [targets] unless targets.instance_of?(Array)
70
+ # TODO: return error if there is a problem calling this method or getting
71
+ # a factory instance
72
+ begin
73
+ response = factory.build_image(image, build, template, targets)
74
+ build_adaptors(response)
75
+ rescue Exception => e
76
+ @logger.debug "Encountered error in build_image: #{e}"
77
+ return e
78
+ end
79
+ end
80
+
81
+ # Call this method to push an image to a provider, and get back an
82
+ # array of BuildAdaptor objects.
83
+ # * providers => Array
84
+ # Represents the target providers to build for (ec2-us-east, mock1, etc)
85
+ # * credentials => String
86
+ # XML block to be used for registration, upload, etc
87
+ # * image_id => String
88
+ # The UUID of an image previously built
89
+ # * build_id => String
90
+ # The UUID of a previous build of the image
91
+ # * Returns => an array of BuildAdaptor objects
92
+ #
93
+ def push(providers, credentials, image_id, build_id='')
94
+ providers = [providers] unless providers.instance_of?(Array)
95
+ # TODO: return error if there is a problem calling this method or getting
96
+ # a factory instance
97
+ begin
98
+ response = factory.push_image(image_id, build_id, providers, credentials)
99
+ build_adaptors(response)
100
+ rescue Exception => e
101
+ @logger.debug "Encountered error in push_image: #{e}"
102
+ return e
103
+ end
104
+ end
105
+
106
+ # Call this method to import an image
107
+ # array of BuildAdaptor objects.
108
+ # * image => string
109
+ # The uuid of an existing image
110
+ # * build => string
111
+ # the uuid of an existing build, or the empty string
112
+ # * target_identifier => string
113
+ # the target specific image ID
114
+ # * image_desc => string
115
+ # an xml string description of the image
116
+ # * target => string
117
+ # name of the cloud to target
118
+ # * provider => string
119
+ # the name of the cloud provider, often a region
120
+ # Returns => a map including UUIDs as strings for 'target_image', 'build', 'image', 'provider_image'
121
+
122
+ def import_image(image, build, target_identifier, image_description, target, provider)
123
+ # TODO: return error if there is a problem calling this method or getting
124
+ # a factory instance
125
+ begin
126
+ factory.import_image(image, build, target_identifier, image_description, target, provider)
127
+ rescue Exception => e
128
+ @logger.debug "Encountered error in import_image: #{e}"
129
+ return e
130
+ end
131
+ end
132
+
133
+ # <b>DEPRECATED:</b> Please use <tt>build</tt> instead.
134
+ # Call this method to initiate a build, and get back an
135
+ # BuildAdaptor object.
136
+ # * descriptor => String
137
+ # This can be either xml or a url pointing to the xml
138
+ # * target => String
139
+ # Represents the target provider type to build for (ec2, mock, etc)
140
+ # * Returns => a BuildAdaptor object
141
+ #
142
+ def build_image(descriptor, target)
143
+ @logger.warn "[DEPRECATION] 'build_image' is deprecated. Please use 'build' instead."
144
+ # TODO: return error if there is a problem calling this method or getting
145
+ # a factory instance
146
+ begin
147
+ response = factory.image(descriptor, target)
148
+ build_adaptor(response)
149
+ rescue Exception => e
150
+ @logger.debug "Encountered error in build_image: #{e}"
151
+ return e
152
+ end
153
+ end
154
+
155
+ # <b>DEPRECATED:</b> Please use <tt>push</tt> instead.
156
+ # Call this method to push an image to a provider, and get back an
157
+ # BuildAdaptor object.
158
+ # * image_id => String (uuid)
159
+ # * provider => String
160
+ # Represents the target provider to build for (ec2-us-east, mock, etc)
161
+ # * credentials => String
162
+ # XML block to be used for registration, upload, etc
163
+ # * Returns => a BuildAdaptor object
164
+ #
165
+ def push_image(image_id, provider, credentials)
166
+ @logger.warn "[DEPRECATION] 'push_image' is deprecated. Please use 'push' instead."
167
+ # TODO: return error if there is a problem calling this method or getting
168
+ # a factory instance
169
+ begin
170
+ response = factory.provider_image(image_id, provider, credentials)
171
+ build_adaptor(response)
172
+ rescue Exception => e
173
+ @logger.debug "Encountered error in push_image: #{e}"
174
+ return e
175
+ end
176
+ end
177
+
178
+ #TODO: enhance both of these methods to handle multiple agents
179
+ def agent_added(agent)
180
+ @logger.debug "GOT AN AGENT: #{agent} at #{Time.now.utc}"
181
+ @q = agent if agent.product == "imagefactory"
182
+ end
183
+
184
+ def agent_deleted(agent, reason)
185
+ @logger.debug "AGENT GONE: #{agent} at #{Time.now.utc}, because #{reason}"
186
+ unless @q==nil
187
+ @q = nil if (@q.product == agent.product && @q.name.eql?(agent.name))
188
+ end
189
+ end
190
+
191
+ # TODO: handle agent restart events (this will be more useful when
192
+ # restarted agent can recover an in-process build
193
+ def agent_restarted(agent)
194
+ @logger.debug "AGENT RESTARTED: #{agent.product}"
195
+ end
196
+
197
+ # TODO: handle schema updates. This will be more useful when/if
198
+ # we make this a more generic console to talk to different agents.
199
+ def agent_schema_updated(agent)
200
+ @logger.debug "AGENT SCHEMA UPDATED: #{agent.product}"
201
+ end
202
+
203
+ def event_raised(agent, data, timestamp, severity)
204
+ @logger.debug "GOT AN EVENT: #{agent}, #{data} at #{timestamp}"
205
+ @handler.handle(data)
206
+ end
207
+
208
+ def shutdown
209
+ @logger.debug "Closing connections.."
210
+ if @session
211
+ @session.close
212
+ end
213
+ @connection.close
214
+
215
+ #TODO Replace this with some control flow to manage the cancelling of the console handler, atm
216
+ # this code swallows error message generated by closing connection, then cancelling console.
217
+ begin
218
+ self.cancel
219
+ rescue QmfError
220
+ # TODO We should be logging to a file rather than STDOUT, uncomment this code when logging is configured properly
221
+ # Commented out to clean up user output
222
+ #@logger.error "Issue Closing Console Handler"
223
+ end
224
+ end
225
+
226
+ private
227
+
228
+ def factory
229
+ @factory ||= @q.query("{class:ImageFactory, package:'com.redhat.imagefactory'}").first
230
+ end
231
+
232
+ def build_adaptors(response)
233
+ ret = []
234
+ response['build_adaptors'].each do |imgfacaddr|
235
+ query = Qmf2::Query.new(Qmf2::DataAddr.new(imgfacaddr))
236
+ ret << @q.query(query,5).first
237
+ end
238
+ ret
239
+ end
240
+
241
+ def build_adaptor(response)
242
+ @logger.warn "[DEPRECATION] 'build_adaptor' is deprecated. Please use 'build_adaptors' instead."
243
+ imgfacaddr = Qmf2::DataAddr.new(response['build_adaptor'])
244
+ query = Qmf2::Query.new(imgfacaddr)
245
+ @q.query(query,5).first
246
+ end
247
+
248
+ def make_array(a)
249
+ return a ||= [a] unless a.instance_of?(Array)
250
+ end
251
+ end
@@ -0,0 +1,217 @@
1
+ require 'spec_helper'
2
+
3
+ module ImageFactory
4
+ describe ImageFactoryConsole do
5
+ context "needs a real agent running" do
6
+ # for now, these all require an actual agent on the bus
7
+ before(:all) do
8
+ @logger = Logger.new(STDOUT)
9
+ @logger.level = Logger::DEBUG
10
+ @logger.datetime_format = "%Y-%m-%d %H:%M:%S"
11
+ @i = ImageFactoryConsole.new() # Pass this in for more logging: (:logger => @logger)
12
+ @i.start
13
+ # Sadly, this is needed so we wait for an agent to appear.
14
+ # We might be able to extract this somewhere to hold off
15
+ # on tests until we get an agent_added notification
16
+ sleep(5)
17
+ #TODO: take this snippet and make a fixture of some sort to use in tests
18
+ #tmpl = '<template> <name>tmpl1</name> <description>foo</description> <os> <name>Fedora</name>
19
+ # <arch>x86_64</arch> <version>14</version> <install type="url">
20
+ # <url>http://download.fedoraproject.org/pub/fedora/linux/releases/14/Fedora/x86_64/os/</url> </install>
21
+ # </os> <repositories> <repository name="custom"> <url>http://repos.fedorapeople.org/repos/aeolus/demo/webapp/</url>
22
+ # <signed>false</signed> </repository> </repositories> </template>'
23
+ end
24
+
25
+ describe "#q" do
26
+ it "should get an agent set" do
27
+ @i.q.should_not be_nil
28
+ end
29
+ end
30
+
31
+ describe "#build_image" do
32
+ it "should return a build-adaptor with uuid" do
33
+ @i.build_image("<template></template>", "mock").image_id.should_not be_nil
34
+ end
35
+ end
36
+
37
+ describe "#push_image" do
38
+ it "should return a build-adaptor with uuid" do
39
+ @image = @i.build_image("<template></template>", "mock")
40
+ #@i.handler = BaseHandler.new(@logger)
41
+ @i.handler.should_not_receive(:handle_failed)
42
+ @i.push_image(@image.image_id, "mock", "some creds").image_id.should_not be_nil
43
+ end
44
+ end
45
+
46
+ describe "#import_image" do
47
+ it "should return a build-adaptor with uuid" do
48
+ @import = @i.import_image("", "", "ami-test", "<image><name>Test Image</name></image>", "ec2", "ec2-us-east-1")
49
+ is_uuid?(@import['image']).should == true
50
+ is_uuid?(@import['target_image']).should == true
51
+ is_uuid?(@import['build']).should == true
52
+ is_uuid?(@import['provider_image']).should == true
53
+ end
54
+ end
55
+
56
+ describe "#build" do
57
+ it "should return an array of build-adaptors with uuids" do
58
+ @i.build("<template></template>", ["mock"]).each do |adaptor|
59
+ adaptor.image_id.should_not be_nil
60
+ adaptor.image.should_not be_nil
61
+ adaptor.build.should_not be_nil
62
+ end
63
+ end
64
+
65
+ it "should work with single target as string" do
66
+ @i.build("<template></template>", "mock").each do |adaptor|
67
+ adaptor.image_id.should_not be_nil
68
+ adaptor.image.should_not be_nil
69
+ adaptor.build.should_not be_nil
70
+ end
71
+ end
72
+ end
73
+
74
+ describe "#push" do
75
+ it "should return an array of build-adaptors with uuids" do
76
+ @i.build("<template></template>", ["mock"]).each do |adaptor|
77
+ #@i.handler = BaseHandler.new(@logger)
78
+ @i.handler.should_not_receive(:handle_failed)
79
+ @i.push(["mock"], "<provider_credentials/>", adaptor.image).each do |a|
80
+ a.image_id.should_not be_nil
81
+ a.image.should_not be_nil
82
+ a.build.should_not be_nil
83
+ end
84
+ end
85
+ end
86
+
87
+ it "should work with single provider as string" do
88
+ @i.build("<template></template>", "mock").each do |adaptor|
89
+ #@i.handler = BaseHandler.new(@logger)
90
+ @i.handler.should_not_receive(:handle_failed)
91
+ @i.push("mock1", "<provider_credentials/>", adaptor.image).each do |a|
92
+ a.image_id.should_not be_nil
93
+ a.image.should_not be_nil
94
+ a.build.should_not be_nil
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ after(:all) do
101
+ @i.shutdown
102
+ end
103
+ end
104
+
105
+ context "agent is stubbed" do
106
+ before(:each) do
107
+ @agent = mock('agent', :null_object => true)
108
+ @agent.stub(:product).and_return("imagefactory")
109
+ @agent.stub(:name).and_return("redhat.com:imagefactory:b9e131c7-7905-409e-bfb5-dd4848a776a7")
110
+ @output = double('output')
111
+ @i2 = ImageFactoryConsole.new(:logger => @output)
112
+ end
113
+
114
+ describe "#agent_added" do
115
+ it "logs when a new agent appears" do
116
+ @output.should_receive(:debug).with(/GOT AN AGENT/).as_null_object
117
+ @i2.agent_added(@agent)
118
+ end
119
+
120
+ it "stores a reference to that agent if it is a factory" do
121
+ @output.should_receive(:debug).with(/GOT AN AGENT/)
122
+ @i2.agent_added(@agent)
123
+ @i2.q.should respond_to(:product)
124
+ end
125
+ end
126
+
127
+ describe "#agent_deleted" do
128
+ before(:each) do
129
+ @old_agent = mock('agent', :null_object => true)
130
+ @old_agent.stub(:product).and_return("imagefactory")
131
+ @old_agent.stub(:name).and_return("redhat.com:imagefactory:4eb3776e-d91e-4239-9a73-3ab43ecc7e15")
132
+ @output.should_receive(:debug).with(/GOT AN AGENT/)
133
+ @i2.agent_added(@agent)
134
+ end
135
+
136
+ it "logs when an agent is removed" do
137
+ @output.should_receive(:debug).with(/AGENT GONE/).as_null_object
138
+ @i2.agent_deleted(@agent, "aged")
139
+ end
140
+
141
+ it "removes the agent reference if removed agent is the same as console reference" do
142
+ @output.should_receive(:debug).with(/AGENT GONE/).as_null_object
143
+ @i2.agent_deleted(@agent, "aged")
144
+ @i2.q.should be_nil
145
+ end
146
+
147
+ it "does not remove the agent reference if removed agent is the not same as console reference" do
148
+ @output.should_receive(:debug).with(/AGENT GONE/).as_null_object
149
+ @i2.agent_deleted(@old_agent, "aged")
150
+ @i2.q.should_not be_nil
151
+ end
152
+ end
153
+
154
+ describe "#event_raised" do
155
+ before(:each) do
156
+ @data = mock('data', :null_object => true)
157
+ @data.stub(:event).and_return("STATUS")
158
+ end
159
+
160
+ it "should call handle on an event" do
161
+ @output.should_receive(:debug).with(/GOT AN EVENT/)
162
+
163
+ @i2.handler.should_receive(:handle).once
164
+ @i2.event_raised(@agent, @data, Time.now, "horrid")
165
+ end
166
+ end
167
+
168
+ describe "#build_image" do
169
+ it "should gracefully handle errors" do
170
+ @output.should_receive(:debug).with(/Encountered error in build_image/)
171
+ @output.should_receive(:warn).with("[DEPRECATION] 'build_image' is deprecated. Please use 'build' instead.")
172
+ @i2.q=nil
173
+ error = @i2.build_image("<template></template>", "mock")
174
+ error.to_s.should include("undefined method")
175
+ end
176
+ end
177
+
178
+ describe "#push_image" do
179
+ it "should gracefully handle errors" do
180
+ @output.should_receive(:debug).with(/Encountered error in push_image/)
181
+ @output.should_receive(:warn).with("[DEPRECATION] 'push_image' is deprecated. Please use 'push' instead.")
182
+ @i2.q=nil
183
+ error = @i2.push_image(123, "mock", "some creds")
184
+ error.to_s.should include("undefined method")
185
+ end
186
+ end
187
+
188
+ describe "#build" do
189
+ it "should gracefully handle errors" do
190
+ @output.should_receive(:debug).with(/Encountered error in build_image/)
191
+ @i2.q=nil
192
+ error = @i2.build("<template></template>", "mock")
193
+ error.to_s.should include("undefined method")
194
+ end
195
+ end
196
+
197
+ describe "#push" do
198
+ it "should gracefully handle errors" do
199
+ @output.should_receive(:debug).with(/Encountered error in push_image/)
200
+ @i2.q=nil
201
+ error = @i2.push(123, "mock", "some creds")
202
+ error.to_s.should include("undefined method")
203
+ end
204
+ end
205
+
206
+ after(:each) do
207
+ @output.should_receive(:debug).with(/Closing/)
208
+ @i2.shutdown
209
+ end
210
+ end
211
+
212
+ def is_uuid?(test_string)
213
+ regexp = Regexp.new('^[\w]{8}[-][\w]{4}[-][\w]{4}[-][\w]{4}[-][\w]{12}')
214
+ regexp.match(test_string) ? true : false
215
+ end
216
+ end
217
+ end
@@ -0,0 +1,3 @@
1
+ $: << File.expand_path(File.join(File.dirname(__FILE__), "../lib"))
2
+ require 'rubygems'
3
+ require 'imagefactory'
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: imagefactory-console
3
+ version: !ruby/object:Gem::Version
4
+ hash: 15
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 4
9
+ - 0
10
+ version: 0.4.0
11
+ platform: ruby
12
+ authors:
13
+ - Jason Guiditta
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-07-22 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: QMF Console for Aeolus Image Factory
23
+ email: jguiditt@redhat.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - Rakefile
32
+ - lib/imagefactory.rb
33
+ - lib/imagefactory/base_handler.rb
34
+ - lib/imagefactory/console.rb
35
+ - spec/spec_helper.rb
36
+ - spec/image_factory/console_spec.rb
37
+ has_rdoc: true
38
+ homepage:
39
+ licenses: []
40
+
41
+ post_install_message:
42
+ rdoc_options: []
43
+
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ hash: 3
52
+ segments:
53
+ - 0
54
+ version: "0"
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 3
61
+ segments:
62
+ - 0
63
+ version: "0"
64
+ requirements: []
65
+
66
+ rubyforge_project:
67
+ rubygems_version: 1.3.7
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: QMF Console for Aeolus Image Factory
71
+ test_files: []
72
+