katello 3.14.0.rc1 → 3.14.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of katello might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/app/assets/javascripts/katello/containers/container.js +5 -5
- data/app/assets/javascripts/katello/hosts/activation_key_edit.js +1 -1
- data/app/assets/javascripts/katello/hosts/host_and_hostgroup_edit.js +1 -1
- data/app/assets/javascripts/katello/sync_management/sync_management.js +6 -6
- data/app/controllers/katello/api/v2/repositories_controller.rb +1 -1
- data/app/lib/actions/katello/content_view/publish.rb +13 -4
- data/app/lib/actions/katello/content_view_puppet_environment/destroy.rb +3 -1
- data/app/lib/actions/katello/content_view_version/create_repos.rb +25 -0
- data/app/lib/actions/katello/content_view_version/incremental_update.rb +32 -12
- data/app/lib/actions/katello/environment/destroy.rb +5 -1
- data/app/lib/actions/katello/host/hypervisors_update.rb +12 -1
- data/app/lib/actions/katello/repository/clone_to_version.rb +3 -11
- data/app/lib/actions/pulp/repository/copy_units.rb +3 -6
- data/app/lib/actions/pulp/repository/refresh.rb +1 -1
- data/app/lib/actions/pulp/repository/sync.rb +3 -1
- data/app/lib/katello/resources/candlepin.rb +6 -0
- data/app/lib/katello/resources/candlepin/admin.rb +21 -0
- data/app/lib/katello/util/package_clause_generator.rb +10 -0
- data/app/lib/katello/util/support.rb +19 -0
- data/app/models/katello/glue/pulp/repo.rb +0 -13
- data/app/models/katello/host/subscription_facet.rb +2 -1
- data/app/models/katello/kt_environment.rb +1 -0
- data/app/models/katello/ping.rb +35 -3
- data/app/models/katello/repository.rb +5 -2
- data/app/models/katello/rhsm_fact_parser.rb +6 -1
- data/app/models/katello/root_repository.rb +1 -1
- data/app/services/katello/candlepin/consumer.rb +2 -1
- data/app/{lib/actions/candlepin/import_pool_handler.rb → services/katello/candlepin/event_handler.rb} +2 -2
- data/app/services/katello/candlepin_event_listener.rb +106 -0
- data/app/services/katello/candlepin_listening_service.rb +91 -0
- data/app/services/katello/event_daemon.rb +91 -0
- data/app/services/katello/event_monitor/poller_thread.rb +108 -0
- data/app/services/katello/event_queue.rb +4 -0
- data/app/services/katello/pulp/repository.rb +13 -6
- data/app/services/katello/pulp/repository/yum.rb +52 -12
- data/lib/katello/engine.rb +13 -14
- data/lib/katello/middleware/event_daemon.rb +14 -0
- data/lib/katello/plugin.rb +2 -0
- data/lib/katello/tasks/upgrade_check.rake +2 -7
- data/lib/katello/version.rb +1 -1
- data/locale/bn/katello.po +1 -1
- data/locale/cs/katello.po +1 -1
- data/locale/de/katello.po +2 -2
- data/locale/en/katello.po +1 -1
- data/locale/es/katello.po +2 -2
- data/locale/fr/katello.po +2 -2
- data/locale/gu/katello.po +1 -1
- data/locale/hi/katello.po +1 -1
- data/locale/it/katello.po +2 -2
- data/locale/ja/katello.po +2 -2
- data/locale/katello.pot +1 -1
- data/locale/kn/katello.po +1 -1
- data/locale/ko/katello.po +2 -2
- data/locale/mr/katello.po +1 -1
- data/locale/or/katello.po +1 -1
- data/locale/pa/katello.po +1 -1
- data/locale/pt/katello.po +1 -1
- data/locale/pt_BR/katello.po +2 -2
- data/locale/ru/katello.po +2 -2
- data/locale/ta/katello.po +1 -1
- data/locale/te/katello.po +1 -1
- data/locale/zh_CN/katello.po +2 -2
- data/locale/zh_TW/katello.po +2 -2
- data/webpack/components/Content/Details/__tests__/__snapshots__/ContentDetails.test.js.snap +2 -2
- data/webpack/scenes/RedHatRepositories/components/EnabledRepository/EnabledRepository.js +2 -2
- data/webpack/scenes/RedHatRepositories/components/RepositorySetRepository/RepositorySetRepository.js +3 -3
- data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetails.test.js.snap +2 -2
- data/webpack/scenes/Subscriptions/SubscriptionsPage.scss +6 -0
- data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTableHelpers.js +1 -1
- data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/SubscriptionsTable.fixtures.js +1 -1
- metadata +11 -10
- data/app/lib/actions/candlepin/candlepin_listening_service.rb +0 -114
- data/app/lib/actions/candlepin/listen_on_candlepin_events.rb +0 -216
- data/app/lib/actions/katello/event_queue/monitor.rb +0 -122
- data/app/lib/actions/katello/event_queue/poller_thread.rb +0 -83
- data/app/lib/actions/katello/event_queue/suspended_action.rb +0 -23
@@ -149,6 +149,12 @@ module Katello
|
|
149
149
|
end # class << self
|
150
150
|
end # UpstreamCandlepinResource
|
151
151
|
|
152
|
+
module AdminResource
|
153
|
+
def path
|
154
|
+
"#{self.prefix}/admin"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
152
158
|
module ConsumerResource
|
153
159
|
def path(id = nil)
|
154
160
|
"#{self.prefix}/consumers/#{id}"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Katello
|
2
|
+
module Resources
|
3
|
+
module Candlepin
|
4
|
+
class Admin < CandlepinResource
|
5
|
+
extend AdminResource
|
6
|
+
|
7
|
+
def self.queues
|
8
|
+
response = get("#{path}/queues")
|
9
|
+
JSON.parse(response.body).first
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.queue_depth(queue_name)
|
13
|
+
queue = queues.select { |q| q['queueName'] == queue_name }
|
14
|
+
queue['pendingMessageCount'].to_i
|
15
|
+
rescue
|
16
|
+
nil # be graceful when candlepin is down
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -3,6 +3,16 @@ module Katello
|
|
3
3
|
class PackageClauseGenerator
|
4
4
|
include Util::FilterClauseGenerator
|
5
5
|
|
6
|
+
def copy_clause
|
7
|
+
clauses = super
|
8
|
+
{"$and" => [{"is_modular" => false}, clauses]} unless clauses.blank?
|
9
|
+
end
|
10
|
+
|
11
|
+
def remove_clause
|
12
|
+
clauses = super
|
13
|
+
{"$and" => [{"is_modular" => false}, clauses]} unless clauses.blank?
|
14
|
+
end
|
15
|
+
|
6
16
|
protected
|
7
17
|
|
8
18
|
def fetch_filters
|
@@ -72,6 +72,25 @@ module Katello
|
|
72
72
|
stringify(params.keys) - stringify(rule.keys)
|
73
73
|
end
|
74
74
|
|
75
|
+
def self.with_db_connection(logger = Rails.logger)
|
76
|
+
yield
|
77
|
+
rescue PG::ConnectionBad, ActiveRecord::StatementInvalid, ActiveRecord::ConnectionNotEstablished => e
|
78
|
+
logger.error(e.message)
|
79
|
+
logger.error("Lost database connection. Attempting reconnect.")
|
80
|
+
|
81
|
+
active_record_retry_connect
|
82
|
+
|
83
|
+
retry
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.active_record_retry_connect
|
87
|
+
sleep 3
|
88
|
+
ActiveRecord::Base.connection.reconnect!
|
89
|
+
rescue
|
90
|
+
logger.error("Trying to reconnect to the database.")
|
91
|
+
retry
|
92
|
+
end
|
93
|
+
|
75
94
|
# Used for retrying active record transactions when race conditions could cause
|
76
95
|
# RecordNotUnique exceptions
|
77
96
|
def self.active_record_retry(retries = 3)
|
@@ -44,19 +44,6 @@ module Katello
|
|
44
44
|
!repo.distributors_match?(repo_details["distributors"], smart_proxy)
|
45
45
|
end
|
46
46
|
end
|
47
|
-
|
48
|
-
def self.build_override_config(options)
|
49
|
-
config = {}
|
50
|
-
if options[:filters].present? && (options[:solve_dependencies] || options[:resolve_dependencies])
|
51
|
-
if Setting[:dependency_solving_algorithm] == 'greedy'
|
52
|
-
config[:recursive] = true
|
53
|
-
else
|
54
|
-
config[:recursive_conservative] = true
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
config
|
59
|
-
end
|
60
47
|
end
|
61
48
|
end
|
62
49
|
|
@@ -127,7 +127,8 @@ module Katello
|
|
127
127
|
guest_ids = self.candlepin_consumer.virtual_guests.pluck(:id)
|
128
128
|
end
|
129
129
|
|
130
|
-
subscription_facets = SubscriptionFacet.where(:host_id => guest_ids)
|
130
|
+
subscription_facets = SubscriptionFacet.where(:host_id => guest_ids).
|
131
|
+
where("hypervisor_host_id != ? OR hypervisor_host_id is NULL", self.host.id)
|
131
132
|
subscription_facets.update_all(:hypervisor_host_id => self.host.id)
|
132
133
|
elsif (virtual_host = self.candlepin_consumer.virtual_host)
|
133
134
|
self.hypervisor_host = virtual_host
|
@@ -76,6 +76,7 @@ module Katello
|
|
76
76
|
|
77
77
|
scoped_search :on => :name, :complete_value => true
|
78
78
|
scoped_search :on => :organization_id, :complete_value => true, :only_explicit => true, :validator => ScopedSearch::Validators::INTEGER
|
79
|
+
scoped_search :on => :id, :complete_value => true, :only_explicit => true, :validator => ScopedSearch::Validators::INTEGER
|
79
80
|
|
80
81
|
def library?
|
81
82
|
self.library
|
data/app/models/katello/ping.rb
CHANGED
@@ -2,10 +2,12 @@ module Katello
|
|
2
2
|
class Ping
|
3
3
|
OK_RETURN_CODE = 'ok'.freeze
|
4
4
|
FAIL_RETURN_CODE = 'FAIL'.freeze
|
5
|
+
WARN_RETURN_CODE = 'WARN'.freeze
|
5
6
|
PACKAGES = %w(katello candlepin pulp qpid foreman tfm hammer).freeze
|
7
|
+
|
6
8
|
class << self
|
7
9
|
def services(capsule_id = nil)
|
8
|
-
services = [:pulp, :pulp_auth, :candlepin, :candlepin_auth, :foreman_tasks]
|
10
|
+
services = [:pulp, :pulp_auth, :candlepin, :candlepin_auth, :foreman_tasks, :katello_events, :candlepin_events]
|
9
11
|
services += [:pulp3] if fetch_proxy(capsule_id)&.pulp3_enabled?
|
10
12
|
services
|
11
13
|
end
|
@@ -25,11 +27,13 @@ module Katello
|
|
25
27
|
ping_pulp_with_auth(result[:pulp_auth], result[:pulp][:status]) if result.include?(:pulp_auth)
|
26
28
|
ping_candlepin_with_auth(result[:candlepin_auth]) if result.include?(:candlepin_auth)
|
27
29
|
ping_foreman_tasks(result[:foreman_tasks]) if result.include?(:foreman_tasks)
|
30
|
+
ping_katello_events(result[:katello_events]) if result.include?(:katello_events)
|
31
|
+
ping_candlepin_events(result[:candlepin_events]) if result.include?(:candlepin_events)
|
28
32
|
|
29
33
|
# set overall status result code
|
30
34
|
result = {:services => result}
|
31
35
|
result[:services].each_value do |v|
|
32
|
-
result[:status] = v[:status]
|
36
|
+
result[:status] = [OK_RETURN_CODE, WARN_RETURN_CODE].include?(v[:status]) ? OK_RETURN_CODE : FAIL_RETURN_CODE
|
33
37
|
end
|
34
38
|
result
|
35
39
|
end
|
@@ -41,6 +45,34 @@ module Katello
|
|
41
45
|
}
|
42
46
|
end
|
43
47
|
|
48
|
+
def daemon_status_message(status)
|
49
|
+
"#{status[:processed_count]} Processed, #{status[:failed_count]} Failed, #{status[:queue_depth]} in queue"
|
50
|
+
end
|
51
|
+
|
52
|
+
def ping_katello_events(result)
|
53
|
+
exception_watch(result) do
|
54
|
+
status = Katello::EventMonitor::PollerThread.status
|
55
|
+
|
56
|
+
if status[:queue_depth] && status[:queue_depth] > 1000
|
57
|
+
result[:status] = WARN_RETURN_CODE
|
58
|
+
end
|
59
|
+
|
60
|
+
result[:message] = daemon_status_message(status)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def ping_candlepin_events(result)
|
65
|
+
exception_watch(result) do
|
66
|
+
status = Katello::CandlepinEventListener.status
|
67
|
+
|
68
|
+
if status[:queue_depth] && status[:queue_depth] > 1000
|
69
|
+
result[:status] = WARN_RETURN_CODE
|
70
|
+
end
|
71
|
+
|
72
|
+
result[:message] = daemon_status_message(status)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
44
76
|
def ping_pulp3_without_auth(service_result, capsule_id)
|
45
77
|
exception_watch(service_result) do
|
46
78
|
Katello::Ping.pulp3_without_auth(fetch_proxy(capsule_id).pulp3_url("api/v3"))
|
@@ -104,8 +136,8 @@ module Katello
|
|
104
136
|
# check for exception - set the result code properly
|
105
137
|
def exception_watch(result)
|
106
138
|
start = Time.new
|
107
|
-
yield
|
108
139
|
result[:status] = OK_RETURN_CODE
|
140
|
+
yield
|
109
141
|
result[:duration_ms] = ((Time.new - start) * 1000).round.to_s
|
110
142
|
result
|
111
143
|
rescue => e
|
@@ -140,7 +140,6 @@ module Katello
|
|
140
140
|
scoped_search :on => :distribution_variant, :complete_value => true
|
141
141
|
scoped_search :on => :distribution_bootable, :complete_value => true
|
142
142
|
scoped_search :on => :distribution_uuid, :complete_value => true
|
143
|
-
scoped_search :on => :ignore_global_proxy, :relation => :root, :complete_value => true
|
144
143
|
scoped_search :on => :redhat, :complete_value => { :true => true, :false => false }, :ext_method => :search_by_redhat
|
145
144
|
scoped_search :on => :container_repository_name, :complete_value => true
|
146
145
|
scoped_search :on => :description, :relation => :root, :only_explicit => true
|
@@ -157,7 +156,7 @@ module Katello
|
|
157
156
|
:content_type, :product_id, :checksum_type, :docker_upstream_name, :mirror_on_sync, :"mirror_on_sync?",
|
158
157
|
:download_policy, :verify_ssl_on_sync, :"verify_ssl_on_sync?", :upstream_username, :upstream_password,
|
159
158
|
:ostree_upstream_sync_policy, :ostree_upstream_sync_depth, :deb_releases, :deb_components, :deb_architectures,
|
160
|
-
:
|
159
|
+
:ssl_ca_cert_id, :ssl_ca_cert, :ssl_client_cert, :ssl_client_cert_id, :ssl_client_key_id,
|
161
160
|
:ssl_client_key, :ignorable_content, :description, :docker_tags_whitelist, :ansible_collection_requirements, :http_proxy_policy, :http_proxy_id, :to => :root
|
162
161
|
|
163
162
|
delegate :content_id, to: :root, allow_nil: true
|
@@ -315,6 +314,10 @@ module Katello
|
|
315
314
|
found
|
316
315
|
end
|
317
316
|
|
317
|
+
def siblings
|
318
|
+
content_view_version.archived_repos.where.not(:id => id)
|
319
|
+
end
|
320
|
+
|
318
321
|
def clones
|
319
322
|
self.root.repositories.where.not(:id => library_instance_id || id)
|
320
323
|
end
|
@@ -23,7 +23,7 @@ module Katello
|
|
23
23
|
def get_facts_for_interface(interface)
|
24
24
|
{
|
25
25
|
'link' => true,
|
26
|
-
'macaddress' =>
|
26
|
+
'macaddress' => get_rhsm_mac(interface),
|
27
27
|
'ipaddress' => get_rhsm_ip(interface)
|
28
28
|
}
|
29
29
|
end
|
@@ -107,5 +107,10 @@ module Katello
|
|
107
107
|
ip = facts["net.interface.#{interface}.ipv4_address"]
|
108
108
|
Net::Validations.validate_ip(ip) ? ip : nil
|
109
109
|
end
|
110
|
+
|
111
|
+
def get_rhsm_mac(interface)
|
112
|
+
# if slave then permanent_mac_address contains the physical mac
|
113
|
+
facts["net.interface.#{interface}.permanent_mac_address"] || facts["net.interface.#{interface}.mac_address"]
|
114
|
+
end
|
110
115
|
end
|
111
116
|
end
|
@@ -290,7 +290,7 @@ module Katello
|
|
290
290
|
|
291
291
|
def pulp_update_needed?
|
292
292
|
changeable_attributes = %w(url unprotected checksum_type docker_upstream_name download_policy mirror_on_sync verify_ssl_on_sync
|
293
|
-
upstream_username upstream_password ostree_upstream_sync_policy ostree_upstream_sync_depth
|
293
|
+
upstream_username upstream_password ostree_upstream_sync_policy ostree_upstream_sync_depth ignorable_content
|
294
294
|
ssl_ca_cert_id ssl_client_cert_id ssl_client_key_id http_proxy_policy http_proxy_id)
|
295
295
|
changeable_attributes += %w(name container_repository_name docker_tags_whitelist) if docker?
|
296
296
|
changeable_attributes += %w(deb_releases deb_components deb_architectures gpg_key_id) if deb?
|
@@ -100,9 +100,10 @@ module Katello
|
|
100
100
|
end
|
101
101
|
|
102
102
|
def virtual_guests
|
103
|
+
return @virtual_guests unless @virtual_guests.nil?
|
103
104
|
return [] if self.uuid.nil?
|
104
105
|
guest_uuids = Resources::Candlepin::Consumer.virtual_guests(self.uuid).map { |guest| guest['uuid'] }
|
105
|
-
::Host.joins(:subscription_facet).where("#{Katello::Host::SubscriptionFacet.table_name}.uuid" => guest_uuids)
|
106
|
+
@virtual_guests = ::Host.joins(:subscription_facet).where("#{Katello::Host::SubscriptionFacet.table_name}.uuid" => guest_uuids)
|
106
107
|
end
|
107
108
|
|
108
109
|
def virtual_host
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module Katello
|
2
|
+
class CandlepinEventListener
|
3
|
+
PROCESSED_COUNT_CACHE_KEY = 'candlepin_events_processed'.freeze
|
4
|
+
FAILED_COUNT_CACHE_KEY = 'candlepin_events_failed'.freeze
|
5
|
+
AMQP_QUEUE_NAME = 'event.org.candlepin.audit.AMQPBusPublisher'.freeze
|
6
|
+
|
7
|
+
CandlepinEvent = Struct.new(:message_id, :subject, :content)
|
8
|
+
|
9
|
+
@logger = ::Foreman::Logging.logger('katello/candlepin_events')
|
10
|
+
@failed_count = 0
|
11
|
+
@processed_count = 0
|
12
|
+
|
13
|
+
def self.start_service
|
14
|
+
loop do
|
15
|
+
begin
|
16
|
+
result = Katello::CandlepinListeningService.instance.start
|
17
|
+
|
18
|
+
break if result == :connected
|
19
|
+
|
20
|
+
@logger.info("Attempting to restart Candlepin Listening Service")
|
21
|
+
sleep 5
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.run
|
27
|
+
@thread.kill if @thread
|
28
|
+
|
29
|
+
# run in own thread so connecting to qpid won't block the main process
|
30
|
+
@thread = Thread.new do
|
31
|
+
Rails.application.executor.wrap do
|
32
|
+
initialize_listening_service
|
33
|
+
start_service
|
34
|
+
|
35
|
+
Katello::CandlepinListeningService.instance.poll_for_messages do |message|
|
36
|
+
if message[:result]
|
37
|
+
result = message[:result]
|
38
|
+
event = CandlepinEvent.new(result.message_id, result.subject, result.content)
|
39
|
+
act_on_event(event)
|
40
|
+
elsif message[:error]
|
41
|
+
@logger.error("Disconnected from Candlepin Listening Service, reconnecting")
|
42
|
+
start_service
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
rescue => e
|
48
|
+
@logger.error("Fatal error in Candlepin Listening Service")
|
49
|
+
close
|
50
|
+
raise e
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.status
|
54
|
+
{
|
55
|
+
processed_count: Rails.cache.fetch(PROCESSED_COUNT_CACHE_KEY) { @processed_count },
|
56
|
+
failed_count: Rails.cache.fetch(FAILED_COUNT_CACHE_KEY) { @failed_count },
|
57
|
+
queue_depth: Katello::Resources::Candlepin::Admin.queue_depth(AMQP_QUEUE_NAME)
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.reset_status
|
62
|
+
Rails.cache.write(PROCESSED_COUNT_CACHE_KEY, 0)
|
63
|
+
Rails.cache.write(FAILED_COUNT_CACHE_KEY, 0)
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.act_on_event(event)
|
67
|
+
::Katello::Util::Support.with_db_connection(@logger) do
|
68
|
+
::Katello::Candlepin::EventHandler.new(@logger).handle(event)
|
69
|
+
end
|
70
|
+
@processed_count += 1
|
71
|
+
|
72
|
+
Rails.cache.write(PROCESSED_COUNT_CACHE_KEY, @processed_count, expires_in: 24.hours)
|
73
|
+
rescue => e
|
74
|
+
@failed_count += 1
|
75
|
+
Rails.cache.write(FAILED_COUNT_CACHE_KEY, @failed_count, expires_in: 24.hours)
|
76
|
+
@logger.error("Error handling Candlepin event")
|
77
|
+
@logger.error(e.message)
|
78
|
+
@logger.error(e.backtrace.join("\n"))
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.configured?
|
82
|
+
SETTINGS[:katello].key?(:qpid) &&
|
83
|
+
SETTINGS[:katello][:qpid].key?(:url) &&
|
84
|
+
SETTINGS[:katello][:qpid].key?(:subscriptions_queue_address)
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.initialize_listening_service
|
88
|
+
if configured?
|
89
|
+
Katello::CandlepinListeningService.initialize_service(@logger,
|
90
|
+
SETTINGS[:katello][:qpid][:url],
|
91
|
+
SETTINGS[:katello][:qpid][:subscriptions_queue_address])
|
92
|
+
else
|
93
|
+
fail("Katello has not been configured for qpid.url and qpid.subscriptions_queue_address")
|
94
|
+
end
|
95
|
+
rescue => e
|
96
|
+
@logger.error(e.message)
|
97
|
+
@logger.error(e.backtrace)
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.close
|
101
|
+
Katello::CandlepinListeningService.close
|
102
|
+
@thread.kill if @thread
|
103
|
+
reset_status
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Katello
|
2
|
+
class CandlepinListeningService
|
3
|
+
TIMEOUT = Qpid::Messaging::Duration::SECOND
|
4
|
+
NO_MESSAGE_AVAILABLE_ERROR_TYPE = 'NoMessageAvailable'.freeze
|
5
|
+
SLEEP_INTERVAL = 3
|
6
|
+
|
7
|
+
class ConnectionError < StandardError
|
8
|
+
end
|
9
|
+
|
10
|
+
class << self
|
11
|
+
attr_reader :instance
|
12
|
+
|
13
|
+
def initialize_service(logger, url, address)
|
14
|
+
@instance = self.new(logger, url, address)
|
15
|
+
end
|
16
|
+
|
17
|
+
def close
|
18
|
+
@instance.close if @instance
|
19
|
+
@instance = nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(logger, url, address)
|
24
|
+
@url = url
|
25
|
+
@address = address
|
26
|
+
@connection = create_connection
|
27
|
+
@logger = logger
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_connection
|
31
|
+
Qpid::Messaging::Connection.new(:url => @url, :options => {:transport => 'ssl'})
|
32
|
+
end
|
33
|
+
|
34
|
+
def close
|
35
|
+
@logger.info("Stopping Candlepin Listening Service")
|
36
|
+
@thread.kill if @thread
|
37
|
+
@connection.close
|
38
|
+
end
|
39
|
+
|
40
|
+
def retrieve
|
41
|
+
result = @receiver.fetch(TIMEOUT)
|
42
|
+
result
|
43
|
+
rescue => e
|
44
|
+
if e.class.name.include? "TransportFailure"
|
45
|
+
raise ConnectionError, "failed to connect to #{@url}"
|
46
|
+
else
|
47
|
+
raise e unless e.class.name.include? NO_MESSAGE_AVAILABLE_ERROR_TYPE
|
48
|
+
end
|
49
|
+
ensure
|
50
|
+
safe_release(result) if result
|
51
|
+
end
|
52
|
+
|
53
|
+
def safe_release(message)
|
54
|
+
@session.acknowledge(:message => message, :sync => true)
|
55
|
+
rescue => e
|
56
|
+
@session.release(message)
|
57
|
+
raise e
|
58
|
+
end
|
59
|
+
|
60
|
+
def start
|
61
|
+
unless @connection.open?
|
62
|
+
@connection.open
|
63
|
+
@session = @connection.create_session
|
64
|
+
@receiver = @session.create_receiver(@address)
|
65
|
+
@logger.info("Candlepin Event Listener started")
|
66
|
+
end
|
67
|
+
|
68
|
+
:connected
|
69
|
+
rescue => e
|
70
|
+
raise e unless e.class.name.include? "TransportFailure"
|
71
|
+
end
|
72
|
+
|
73
|
+
def fetch_message
|
74
|
+
{:result => retrieve, :error => nil}
|
75
|
+
rescue ConnectionError => e
|
76
|
+
{:result => nil, :error => e.message}
|
77
|
+
end
|
78
|
+
|
79
|
+
def poll_for_messages
|
80
|
+
@thread.kill if @thread
|
81
|
+
@thread = Thread.new do
|
82
|
+
loop do
|
83
|
+
message = fetch_message
|
84
|
+
yield(message) if block_given?
|
85
|
+
|
86
|
+
sleep SLEEP_INTERVAL if message[:result].nil? && message[:error].nil?
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|