ocp_registry 0.0.1.alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +25 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +65 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/bin/ocp_registry +28 -0
- data/config/example-mysql.yml +40 -0
- data/config/example-sqlite.yml +33 -0
- data/lib/ocp_registry.rb +29 -0
- data/lib/ocp_registry/api_controller.rb +146 -0
- data/lib/ocp_registry/application_manager.rb +213 -0
- data/lib/ocp_registry/cloud_manager/mock.rb +5 -0
- data/lib/ocp_registry/cloud_manager/mock/mock.rb +191 -0
- data/lib/ocp_registry/cloud_manager/mock/model.rb +22 -0
- data/lib/ocp_registry/cloud_manager/openstack.rb +4 -0
- data/lib/ocp_registry/cloud_manager/openstack/cinder_helper.rb +27 -0
- data/lib/ocp_registry/cloud_manager/openstack/keystone_helper.rb +57 -0
- data/lib/ocp_registry/cloud_manager/openstack/nova_helper.rb +37 -0
- data/lib/ocp_registry/cloud_manager/openstack/openstack.rb +126 -0
- data/lib/ocp_registry/common.rb +54 -0
- data/lib/ocp_registry/config.rb +96 -0
- data/lib/ocp_registry/db/001_db_initialize.rb +16 -0
- data/lib/ocp_registry/error.rb +16 -0
- data/lib/ocp_registry/mail_client.rb +141 -0
- data/lib/ocp_registry/models.rb +7 -0
- data/lib/ocp_registry/models/registry_application.rb +10 -0
- data/lib/ocp_registry/runner.rb +47 -0
- data/lib/ocp_registry/version.rb +3 -0
- data/lib/ocp_registry/yaml_helper.rb +23 -0
- data/mail_template/approve_admin.erb +14 -0
- data/mail_template/approve_user.erb +22 -0
- data/mail_template/refuse_admin.erb +16 -0
- data/mail_template/refuse_user.erb +17 -0
- data/mail_template/request_admin.erb +15 -0
- data/mail_template/request_user.erb +16 -0
- data/ocp_registry.gemspec +34 -0
- data/public/bootstrap/css/bootstrap-responsive.css +1109 -0
- data/public/bootstrap/css/bootstrap-responsive.min.css +9 -0
- data/public/bootstrap/css/bootstrap.css +6167 -0
- data/public/bootstrap/css/bootstrap.min.css +9 -0
- data/public/bootstrap/img/glyphicons-halflings-white.png +0 -0
- data/public/bootstrap/img/glyphicons-halflings.png +0 -0
- data/public/bootstrap/js/bootstrap.js +2280 -0
- data/public/bootstrap/js/bootstrap.min.js +6 -0
- data/public/common.css +104 -0
- data/public/favicon.ico +0 -0
- data/public/images/loading.gif +0 -0
- data/public/jquery-1.10.2.min.js +6 -0
- data/public/jquery-1.10.2.min.map +1 -0
- data/public/jquery.json-2.4.min.js +23 -0
- data/public/noty/.gitignore +8 -0
- data/public/noty/LICENSE.txt +20 -0
- data/public/noty/README.markdown +22 -0
- data/public/noty/demo/allLayouts.html +91 -0
- data/public/noty/demo/allTypes.html +86 -0
- data/public/noty/demo/api.html +103 -0
- data/public/noty/demo/buttons.css +320 -0
- data/public/noty/demo/consumingAlert.html +78 -0
- data/public/noty/demo/customContainer.html +90 -0
- data/public/noty/demo/index.html +66 -0
- data/public/noty/demo/jquery-1.7.2.min.js +4 -0
- data/public/noty/demo/usingMaxVisible.html +104 -0
- data/public/noty/demo/usingWithButtons.html +104 -0
- data/public/noty/demo/usingWithButtons2.html +98 -0
- data/public/noty/demo/usingWithModal.html +87 -0
- data/public/noty/demo/usingWithOldOptions.html +110 -0
- data/public/noty/js/jquery.noty.js +547 -0
- data/public/noty/js/layouts/bottom.js +34 -0
- data/public/noty/js/layouts/bottomCenter.js +41 -0
- data/public/noty/js/layouts/bottomLeft.js +43 -0
- data/public/noty/js/layouts/bottomRight.js +43 -0
- data/public/noty/js/layouts/center.js +56 -0
- data/public/noty/js/layouts/centerLeft.js +61 -0
- data/public/noty/js/layouts/centerRight.js +61 -0
- data/public/noty/js/layouts/inline.js +31 -0
- data/public/noty/js/layouts/top.js +34 -0
- data/public/noty/js/layouts/topCenter.js +41 -0
- data/public/noty/js/layouts/topLeft.js +43 -0
- data/public/noty/js/layouts/topRight.js +43 -0
- data/public/noty/js/promise.js +432 -0
- data/public/noty/js/themes/default.js +156 -0
- data/views/apply.erb +134 -0
- data/views/base.erb +25 -0
- data/views/list.erb +41 -0
- data/views/review.erb +141 -0
- data/views/show.erb +96 -0
- data/views/view.erb +7 -0
- metadata +294 -0
@@ -0,0 +1,57 @@
|
|
1
|
+
module Ocp::Registry
|
2
|
+
|
3
|
+
class CloudManager
|
4
|
+
|
5
|
+
class Openstack
|
6
|
+
|
7
|
+
module KeystoneHelper
|
8
|
+
#{
|
9
|
+
# "name": "ACME corp",
|
10
|
+
# "description": "A description ...",
|
11
|
+
# "enabled": true
|
12
|
+
#}
|
13
|
+
def create_tenant(name, description, enabled = true)
|
14
|
+
with_openstack do
|
15
|
+
keystone.tenants.create( :name => name ,
|
16
|
+
:description => description ,
|
17
|
+
:enabled => enabled )
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
#{
|
22
|
+
# "username": "jqsmith",
|
23
|
+
# "email": "john.smith@example.org",
|
24
|
+
# "enabled": true,
|
25
|
+
# "OS-KSADM:password": "secrete"
|
26
|
+
#}
|
27
|
+
def create_user(name, tenant_id, password, email = '')
|
28
|
+
with_openstack do
|
29
|
+
keystone.users.create( :name => name,
|
30
|
+
:tenant_id => tenant_id,
|
31
|
+
:password => password,
|
32
|
+
:email => email)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_tenant_by_name(name)
|
37
|
+
with_openstack { keystone.tenants.find {|tenant| tenant.name == name} }
|
38
|
+
end
|
39
|
+
|
40
|
+
def tenant_add_user_with_role(tenant, user_id, role_id)
|
41
|
+
with_openstack { tenant.grant_user_role(user_id, role_id) }
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_role_by_name(name)
|
45
|
+
with_openstack { keystone.roles.find {|role| role.name == name} }
|
46
|
+
end
|
47
|
+
|
48
|
+
def find_user_by_name(name)
|
49
|
+
with_openstack { keystone.users.find {|user| user.name == name} }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Ocp::Registry
|
2
|
+
|
3
|
+
class CloudManager
|
4
|
+
|
5
|
+
class Openstack
|
6
|
+
|
7
|
+
module NovaHelper
|
8
|
+
|
9
|
+
NOVA_QUOTA_FIELDS = ["metadata_items",
|
10
|
+
"cores",
|
11
|
+
"instances",
|
12
|
+
"injected_files",
|
13
|
+
"injected_file_content_bytes",
|
14
|
+
"ram",
|
15
|
+
"floating_ips",
|
16
|
+
"fixed_ips",
|
17
|
+
"security_groups",
|
18
|
+
"security_group_rules"]
|
19
|
+
|
20
|
+
def default_compute_quota
|
21
|
+
with_openstack { compute.get_quota_defaults(nil).body["quota_set"] }
|
22
|
+
end
|
23
|
+
|
24
|
+
def set_compute_quota(tenant_id, hash)
|
25
|
+
with_openstack do
|
26
|
+
settings = Ocp::Registry::Common.hash_filter(hash, NOVA_QUOTA_FIELDS)
|
27
|
+
compute.update_quota(tenant_id,settings).body["quota_set"]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
|
2
|
+
module Ocp::Registry
|
3
|
+
|
4
|
+
class CloudManager
|
5
|
+
|
6
|
+
class Openstack < CloudManager
|
7
|
+
|
8
|
+
require 'openstack/cinder_helper'
|
9
|
+
require 'openstack/nova_helper'
|
10
|
+
require 'openstack/keystone_helper'
|
11
|
+
|
12
|
+
include KeystoneHelper
|
13
|
+
include NovaHelper
|
14
|
+
include CinderHelper
|
15
|
+
|
16
|
+
def initialize(cloud_config)
|
17
|
+
validate_options(cloud_config)
|
18
|
+
|
19
|
+
@logger = Ocp::Registry.logger
|
20
|
+
|
21
|
+
@openstack_properties = cloud_config["openstack"]
|
22
|
+
|
23
|
+
unless @openstack_properties["auth_url"].match(/\/tokens$/)
|
24
|
+
@openstack_properties["auth_url"] = @openstack_properties["auth_url"] + "/tokens"
|
25
|
+
end
|
26
|
+
|
27
|
+
@openstack_options = {
|
28
|
+
:provider => "OpenStack",
|
29
|
+
:openstack_auth_url => @openstack_properties["auth_url"],
|
30
|
+
:openstack_username => @openstack_properties["username"],
|
31
|
+
:openstack_api_key => @openstack_properties["api_key"],
|
32
|
+
:openstack_tenant => @openstack_properties["tenant"],
|
33
|
+
:openstack_endpoint_type => @openstack_properties["endpoint_type"]
|
34
|
+
}
|
35
|
+
@default_role_name = cloud_config["default_role"]
|
36
|
+
end
|
37
|
+
|
38
|
+
def logger
|
39
|
+
@logger
|
40
|
+
end
|
41
|
+
|
42
|
+
def compute
|
43
|
+
@compute ||= Fog::Compute.new(@openstack_options)
|
44
|
+
end
|
45
|
+
|
46
|
+
def keystone
|
47
|
+
@keystone ||= Fog::Identity.new(@openstack_options)
|
48
|
+
end
|
49
|
+
|
50
|
+
def volume
|
51
|
+
@volume ||= Fog::Volume.new(@openstack_options)
|
52
|
+
end
|
53
|
+
|
54
|
+
def validate_options(cloud_config)
|
55
|
+
unless cloud_config.has_key?("openstack") &&
|
56
|
+
cloud_config["openstack"].is_a?(Hash) &&
|
57
|
+
cloud_config["openstack"]["auth_url"] &&
|
58
|
+
cloud_config["openstack"]["username"] &&
|
59
|
+
cloud_config["openstack"]["api_key"] &&
|
60
|
+
cloud_config["openstack"]["tenant"] &&
|
61
|
+
cloud_config["default_role"]
|
62
|
+
raise ConfigError, "Invalid OpenStack configuration parameters"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def set_tenant_quota(tenant_id, settings={})
|
67
|
+
result = nil
|
68
|
+
with_openstack do
|
69
|
+
compute_quota = set_compute_quota(tenant_id, settings)
|
70
|
+
volume_quota = set_volume_quota(tenant_id, settings)
|
71
|
+
result = compute_quota.merge (volume_quota) if (compute_quota && volume_quota)
|
72
|
+
end
|
73
|
+
cloud_error "Quota for #{tenant_id} has not been set" unless result
|
74
|
+
result
|
75
|
+
end
|
76
|
+
|
77
|
+
def default_quota
|
78
|
+
return @default_quota if @default_quota
|
79
|
+
with_openstack do
|
80
|
+
compute_quota = default_compute_quota
|
81
|
+
volume_quota = default_volume_quota
|
82
|
+
@default_quota = compute_quota.merge (volume_quota)
|
83
|
+
end
|
84
|
+
cloud_error "Default Quota is not found" unless @default_quota
|
85
|
+
@default_quota
|
86
|
+
end
|
87
|
+
|
88
|
+
def default_role
|
89
|
+
return @default_role if @default_role
|
90
|
+
with_openstack do
|
91
|
+
@default_role ||= get_role_by_name(@default_role_name)
|
92
|
+
end
|
93
|
+
cloud_error "Default Role [#{cloud_config["default_role"]}] is not found" unless @default_role
|
94
|
+
@logger.info("Default Role #{@default_role.name} - #{@default_role.id}")
|
95
|
+
@default_role
|
96
|
+
end
|
97
|
+
|
98
|
+
def with_openstack
|
99
|
+
retried = false
|
100
|
+
begin
|
101
|
+
yield
|
102
|
+
rescue Excon::Errors::Unauthorized => e
|
103
|
+
unless retried
|
104
|
+
retried = true
|
105
|
+
@compute = nil
|
106
|
+
@volume = nil
|
107
|
+
@keystone = nil
|
108
|
+
retry
|
109
|
+
end
|
110
|
+
cloud_error "Unable to connect to OpenStack API: #{e.message}", e
|
111
|
+
rescue Excon::Errors::InternalServerError => e
|
112
|
+
cloud_error "OpenStack API Internal Server error. Check debug log for details.", e
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def cloud_error(message, exception = nil)
|
117
|
+
@logger.error(message) if @logger
|
118
|
+
@logger.error(exception) if @logger && exception
|
119
|
+
raise Ocp::Registry::CloudError, message
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Ocp::Registry::Common
|
2
|
+
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def uuid
|
6
|
+
SecureRandom.uuid
|
7
|
+
end
|
8
|
+
|
9
|
+
def gen_password
|
10
|
+
SecureRandom.base64
|
11
|
+
end
|
12
|
+
|
13
|
+
def parse_email(email)
|
14
|
+
return unless email =~ /[a-z0-9_.-]+@[a-z0-9-]+\.[a-z.]+/
|
15
|
+
email =~ /([a-z0-9_.-]+)@([a-z0-9-]+\.[a-z.]+)/
|
16
|
+
{
|
17
|
+
:name => $1 ,
|
18
|
+
:domain => $2
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def hash_filter(hash, fields = [])
|
23
|
+
copy = deep_copy(hash)
|
24
|
+
do_hash_filter(copy, fields)
|
25
|
+
end
|
26
|
+
|
27
|
+
def deep_copy(o)
|
28
|
+
Marshal.load(Marshal.dump(o))
|
29
|
+
end
|
30
|
+
|
31
|
+
def json_merge(a,b,reverse = false)
|
32
|
+
hash_a = Yajl::load a
|
33
|
+
hash_b = Yajl::load b
|
34
|
+
if reverse
|
35
|
+
b.merge a
|
36
|
+
else
|
37
|
+
a.merge b
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def do_hash_filter(hash, fields = [])
|
44
|
+
hash.keep_if do |k,v|
|
45
|
+
if v.is_a? Hash
|
46
|
+
do_hash_filter(v, fields)
|
47
|
+
!v.empty?
|
48
|
+
else
|
49
|
+
fields.include? k
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
|
2
|
+
module Ocp::Registry
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
attr_accessor :logger
|
7
|
+
attr_accessor :base_url
|
8
|
+
attr_accessor :http_port
|
9
|
+
attr_accessor :http_user
|
10
|
+
attr_accessor :http_password
|
11
|
+
attr_accessor :db
|
12
|
+
attr_accessor :application_manager
|
13
|
+
attr_accessor :cloud_login_url
|
14
|
+
|
15
|
+
def configure(config)
|
16
|
+
validate_config(config)
|
17
|
+
|
18
|
+
@logger ||= Logger.new(config["logfile"] || STDOUT)
|
19
|
+
if config["loglevel"].kind_of?(String)
|
20
|
+
@logger.level = Logger.const_get(config["loglevel"].upcase)
|
21
|
+
end
|
22
|
+
|
23
|
+
@base_url = config["http"]["base_url"] || "127.0.0.1"
|
24
|
+
@http_port = config["http"]["port"]
|
25
|
+
@http_user = config["http"]["user"]
|
26
|
+
@http_password = config["http"]["password"]
|
27
|
+
|
28
|
+
@db = connect_db(config["db"])
|
29
|
+
|
30
|
+
migrate_db if @db
|
31
|
+
|
32
|
+
@cloud_login_url = config["cloud"]["login_url"]
|
33
|
+
|
34
|
+
plugin = config["cloud"]["plugin"]
|
35
|
+
begin
|
36
|
+
require "ocp_registry/cloud_manager/#{plugin}"
|
37
|
+
rescue LoadError
|
38
|
+
raise ConfigError, "Could not find Provider Plugin: #{plugin}"
|
39
|
+
end
|
40
|
+
@cloud_manager = Ocp::Registry::CloudManager.const_get(plugin.capitalize).new(config["cloud"])
|
41
|
+
|
42
|
+
@mail_client = init_mail_client(config["mail"]) if config["mail"]
|
43
|
+
|
44
|
+
@application_manager = Ocp::Registry::ApplicationManager.new(@cloud_manager,@mail_client)
|
45
|
+
end
|
46
|
+
|
47
|
+
def init_mail_client(mail_config)
|
48
|
+
require "ocp_registry/mail_client"
|
49
|
+
MailClient.new(mail_config)
|
50
|
+
end
|
51
|
+
|
52
|
+
def migrate_db
|
53
|
+
Sequel.extension :migration
|
54
|
+
Sequel::Migrator.apply(@db,File.expand_path('./lib/ocp_registry/db'))
|
55
|
+
end
|
56
|
+
|
57
|
+
def connect_db(db_config)
|
58
|
+
connection_options = db_config.delete('connection_options') {{}}
|
59
|
+
db_config.delete_if { |_, v| v.to_s.empty? }
|
60
|
+
db_config = db_config.merge(connection_options)
|
61
|
+
|
62
|
+
db = Sequel.connect(db_config)
|
63
|
+
if logger
|
64
|
+
db.logger = @logger
|
65
|
+
db.sql_log_level = :debug
|
66
|
+
end
|
67
|
+
|
68
|
+
db
|
69
|
+
end
|
70
|
+
|
71
|
+
def validate_config(config)
|
72
|
+
unless config.is_a?(Hash)
|
73
|
+
raise ConfigError, "Invalid config format, Hash expected, " \
|
74
|
+
"#{config.class} given"
|
75
|
+
end
|
76
|
+
|
77
|
+
unless config.has_key?("http") && config["http"].is_a?(Hash)
|
78
|
+
raise ConfigError, "HTTP configuration is missing from config file"
|
79
|
+
end
|
80
|
+
|
81
|
+
unless config.has_key?("db") && config["db"].is_a?(Hash)
|
82
|
+
raise ConfigError, "Database configuration is missing from config file"
|
83
|
+
end
|
84
|
+
|
85
|
+
unless config.has_key?("cloud") && config["cloud"].is_a?(Hash)
|
86
|
+
raise ConfigError, "Cloud configuration is missing from config file"
|
87
|
+
end
|
88
|
+
|
89
|
+
if config["cloud"]["plugin"].nil?
|
90
|
+
raise ConfigError, "Cloud plugin is missing from config file"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
Sequel.migration do
|
3
|
+
change do
|
4
|
+
create_table(:registry_applications) do
|
5
|
+
primary_key :id ,:auto_increment => false, :type => String
|
6
|
+
String :email , :null => false
|
7
|
+
String :project , :null => false
|
8
|
+
String :description , :text => true
|
9
|
+
String :state , :null => false , :default => 'PENDING'
|
10
|
+
String :created_at , :null => false
|
11
|
+
String :updated_at
|
12
|
+
String :comments , :text => true
|
13
|
+
String :settings , :null => false , :text => true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Ocp::Registry
|
2
|
+
|
3
|
+
class Error < StandardError
|
4
|
+
def self.code(code = 500)
|
5
|
+
define_method(:code) { code }
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class FatalError < Error; end
|
10
|
+
|
11
|
+
class ConfigError < Error; end
|
12
|
+
class ConnectionError < Error; end
|
13
|
+
|
14
|
+
class CloudError < Error ; end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
module Ocp::Registry
|
2
|
+
class MailClient
|
3
|
+
|
4
|
+
require "net/smtp"
|
5
|
+
require "thread"
|
6
|
+
|
7
|
+
DEFAULT_WORKER = 1
|
8
|
+
DEFAULT_PORT = '25'
|
9
|
+
DEFAULT_HELO = 'ocp.com'
|
10
|
+
TEMPLATES_PATH = 'mail_template'
|
11
|
+
DEFAULT_FROM = 'registry@ocp.com'
|
12
|
+
DEFAULT_TLS = false
|
13
|
+
DEFAULT_ADMIN_EMAIL = 'admin@ocp.com'
|
14
|
+
|
15
|
+
def initialize(mail_config)
|
16
|
+
validate_opinions(mail_config)
|
17
|
+
|
18
|
+
@logger = Ocp::Registry.logger
|
19
|
+
|
20
|
+
@worker = mail_config["worker"] || DEFAULT_WORKER
|
21
|
+
@enable_tls = mail_config["enable_tls"] || DEFAULT_TLS
|
22
|
+
|
23
|
+
@mail_opinions = {
|
24
|
+
:address => mail_config["smtp_server"] ,
|
25
|
+
:port => mail_config["port"] || DEFAULT_PORT ,
|
26
|
+
:helo => mail_config["helo"] || DEFAULT_HELO ,
|
27
|
+
:user => mail_config["username"] || nil ,
|
28
|
+
:secret => mail_config["password"] || nil ,
|
29
|
+
:authtype => mail_config["authentication"] || nil
|
30
|
+
}
|
31
|
+
|
32
|
+
@admin_emails = mail_config["admin_emails"] || DEFAULT_ADMIN_EMAIL
|
33
|
+
|
34
|
+
@mail_queue = Queue.new
|
35
|
+
|
36
|
+
setup_senders
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
def admin_emails
|
41
|
+
@admin_emails
|
42
|
+
end
|
43
|
+
|
44
|
+
def send_mail(mail_info)
|
45
|
+
mail_info.merge!({ :from => DEFAULT_FROM })
|
46
|
+
@mail_queue << mail_info if mail_validated?(mail_info)
|
47
|
+
end
|
48
|
+
|
49
|
+
def validate_opinions(mail_config)
|
50
|
+
unless mail_config["smtp_server"] && mail_config["admin_emails"]
|
51
|
+
raise ConfigError, "Invalid Mail configuration"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def mail_validated?(mail_info)
|
56
|
+
unless mail_info[:from] && mail_info[:to] && mail_info[:template] && has_template?(mail_info[:template])
|
57
|
+
@logger.waring "Mail is ignored because less of necessary fields "
|
58
|
+
return false
|
59
|
+
end
|
60
|
+
true
|
61
|
+
end
|
62
|
+
|
63
|
+
def has_template?(template)
|
64
|
+
File.exists? File.expand_path("#{TEMPLATES_PATH}/#{template}.erb")
|
65
|
+
end
|
66
|
+
|
67
|
+
def prepare_message(mail)
|
68
|
+
template = mail.delete(:template)
|
69
|
+
template = File.read(File.expand_path("#{TEMPLATES_PATH}/#{template}.erb"))
|
70
|
+
@logger.debug "Starting prepare message for mail - #{mail.to_s}"
|
71
|
+
begin
|
72
|
+
info = mail[:msg]
|
73
|
+
message = ERB.new(template).result binding
|
74
|
+
rescue Exception => e
|
75
|
+
@logger.error "Load email template failed - #{e.message}"
|
76
|
+
@logger.debug(e.backtrace.join("\n"))
|
77
|
+
end
|
78
|
+
return message , mail[:from] , mail[:to]
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
# Here we use multi-thread to realize a provider-consumer mode with a block-queue
|
84
|
+
# TODO: Realize with Fiber
|
85
|
+
def setup_senders
|
86
|
+
@worker.times do |index|
|
87
|
+
|
88
|
+
thread = Thread.new { create_sender }
|
89
|
+
thread.run
|
90
|
+
|
91
|
+
@logger.info("Mail sender thread #{index} is running ")
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
def create_sender
|
99
|
+
loop do
|
100
|
+
mail = @mail_queue.pop
|
101
|
+
begin
|
102
|
+
if @enable_tls
|
103
|
+
require "tlsmail"
|
104
|
+
Net::SMTP.enable_tls(OpenSSL::SSL::VERIFY_NONE)
|
105
|
+
end
|
106
|
+
@logger.info("Starting SMTP with opinions #{@mail_opinions}")
|
107
|
+
Net::SMTP.start(@mail_opinions[:address] ,
|
108
|
+
@mail_opinions[:port] ,
|
109
|
+
@mail_opinions[:helo] ,
|
110
|
+
@mail_opinions[:user] ,
|
111
|
+
@mail_opinions[:secret] ,
|
112
|
+
@mail_opinions[:authtype]) do |smtp|
|
113
|
+
until mail.nil? do
|
114
|
+
msg, from, to = prepare_message(mail)
|
115
|
+
smtp.send_message(msg, from, to)
|
116
|
+
@logger.debug("Mail is sent with message \n#{msg}")
|
117
|
+
begin
|
118
|
+
mail = @mail_queue.pop(:non_block => true )
|
119
|
+
rescue ThreadError => e
|
120
|
+
mail = nil
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
rescue Net::SMTPAuthenticationError => e
|
125
|
+
@logger.error("Mail server authentication failed - #{e.message}", e)
|
126
|
+
@logger.debug(e.backtrace.join("\n"))
|
127
|
+
rescue Net::SMTPError => e
|
128
|
+
@logger.error("Mail is not sent because of SMTP error - #{e.message}")
|
129
|
+
@logger.debug(e.backtrace.join("\n"))
|
130
|
+
rescue Exception => e
|
131
|
+
@logger.error(e.message)
|
132
|
+
@logger.debug(e.backtrace.join("\n"))
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|