ocp_registry 0.0.1.alpha

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/.gitignore +25 -0
  2. data/Gemfile +17 -0
  3. data/Gemfile.lock +65 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +29 -0
  6. data/bin/ocp_registry +28 -0
  7. data/config/example-mysql.yml +40 -0
  8. data/config/example-sqlite.yml +33 -0
  9. data/lib/ocp_registry.rb +29 -0
  10. data/lib/ocp_registry/api_controller.rb +146 -0
  11. data/lib/ocp_registry/application_manager.rb +213 -0
  12. data/lib/ocp_registry/cloud_manager/mock.rb +5 -0
  13. data/lib/ocp_registry/cloud_manager/mock/mock.rb +191 -0
  14. data/lib/ocp_registry/cloud_manager/mock/model.rb +22 -0
  15. data/lib/ocp_registry/cloud_manager/openstack.rb +4 -0
  16. data/lib/ocp_registry/cloud_manager/openstack/cinder_helper.rb +27 -0
  17. data/lib/ocp_registry/cloud_manager/openstack/keystone_helper.rb +57 -0
  18. data/lib/ocp_registry/cloud_manager/openstack/nova_helper.rb +37 -0
  19. data/lib/ocp_registry/cloud_manager/openstack/openstack.rb +126 -0
  20. data/lib/ocp_registry/common.rb +54 -0
  21. data/lib/ocp_registry/config.rb +96 -0
  22. data/lib/ocp_registry/db/001_db_initialize.rb +16 -0
  23. data/lib/ocp_registry/error.rb +16 -0
  24. data/lib/ocp_registry/mail_client.rb +141 -0
  25. data/lib/ocp_registry/models.rb +7 -0
  26. data/lib/ocp_registry/models/registry_application.rb +10 -0
  27. data/lib/ocp_registry/runner.rb +47 -0
  28. data/lib/ocp_registry/version.rb +3 -0
  29. data/lib/ocp_registry/yaml_helper.rb +23 -0
  30. data/mail_template/approve_admin.erb +14 -0
  31. data/mail_template/approve_user.erb +22 -0
  32. data/mail_template/refuse_admin.erb +16 -0
  33. data/mail_template/refuse_user.erb +17 -0
  34. data/mail_template/request_admin.erb +15 -0
  35. data/mail_template/request_user.erb +16 -0
  36. data/ocp_registry.gemspec +34 -0
  37. data/public/bootstrap/css/bootstrap-responsive.css +1109 -0
  38. data/public/bootstrap/css/bootstrap-responsive.min.css +9 -0
  39. data/public/bootstrap/css/bootstrap.css +6167 -0
  40. data/public/bootstrap/css/bootstrap.min.css +9 -0
  41. data/public/bootstrap/img/glyphicons-halflings-white.png +0 -0
  42. data/public/bootstrap/img/glyphicons-halflings.png +0 -0
  43. data/public/bootstrap/js/bootstrap.js +2280 -0
  44. data/public/bootstrap/js/bootstrap.min.js +6 -0
  45. data/public/common.css +104 -0
  46. data/public/favicon.ico +0 -0
  47. data/public/images/loading.gif +0 -0
  48. data/public/jquery-1.10.2.min.js +6 -0
  49. data/public/jquery-1.10.2.min.map +1 -0
  50. data/public/jquery.json-2.4.min.js +23 -0
  51. data/public/noty/.gitignore +8 -0
  52. data/public/noty/LICENSE.txt +20 -0
  53. data/public/noty/README.markdown +22 -0
  54. data/public/noty/demo/allLayouts.html +91 -0
  55. data/public/noty/demo/allTypes.html +86 -0
  56. data/public/noty/demo/api.html +103 -0
  57. data/public/noty/demo/buttons.css +320 -0
  58. data/public/noty/demo/consumingAlert.html +78 -0
  59. data/public/noty/demo/customContainer.html +90 -0
  60. data/public/noty/demo/index.html +66 -0
  61. data/public/noty/demo/jquery-1.7.2.min.js +4 -0
  62. data/public/noty/demo/usingMaxVisible.html +104 -0
  63. data/public/noty/demo/usingWithButtons.html +104 -0
  64. data/public/noty/demo/usingWithButtons2.html +98 -0
  65. data/public/noty/demo/usingWithModal.html +87 -0
  66. data/public/noty/demo/usingWithOldOptions.html +110 -0
  67. data/public/noty/js/jquery.noty.js +547 -0
  68. data/public/noty/js/layouts/bottom.js +34 -0
  69. data/public/noty/js/layouts/bottomCenter.js +41 -0
  70. data/public/noty/js/layouts/bottomLeft.js +43 -0
  71. data/public/noty/js/layouts/bottomRight.js +43 -0
  72. data/public/noty/js/layouts/center.js +56 -0
  73. data/public/noty/js/layouts/centerLeft.js +61 -0
  74. data/public/noty/js/layouts/centerRight.js +61 -0
  75. data/public/noty/js/layouts/inline.js +31 -0
  76. data/public/noty/js/layouts/top.js +34 -0
  77. data/public/noty/js/layouts/topCenter.js +41 -0
  78. data/public/noty/js/layouts/topLeft.js +43 -0
  79. data/public/noty/js/layouts/topRight.js +43 -0
  80. data/public/noty/js/promise.js +432 -0
  81. data/public/noty/js/themes/default.js +156 -0
  82. data/views/apply.erb +134 -0
  83. data/views/base.erb +25 -0
  84. data/views/list.erb +41 -0
  85. data/views/review.erb +141 -0
  86. data/views/show.erb +96 -0
  87. data/views/view.erb +7 -0
  88. metadata +294 -0
@@ -0,0 +1,213 @@
1
+
2
+ module Ocp::Registry
3
+
4
+ class ApplicationManager
5
+
6
+ def initialize(cloud_manager,mail_manager)
7
+ @cloud_manager = cloud_manager
8
+ @mail_manager = mail_manager
9
+ @logger = Ocp::Registry.logger
10
+ end
11
+
12
+ def list(email=nil)
13
+ if email
14
+ results = Ocp::Registry::Models::RegistryApplication.reverse_order(:created_at).where(:email => email)
15
+ else
16
+ results = Ocp::Registry::Models::RegistryApplication.reverse_order(:created_at).all
17
+ end
18
+
19
+ results
20
+ end
21
+
22
+ def show(app_id)
23
+ app_info = get_application(app_id)
24
+ return {:status => "error", :message => "Application with id - [#{app_id}] is not existed"} if app_info.nil?
25
+ app_info
26
+ end
27
+
28
+ def default
29
+ @default ||= {
30
+ :email => "" ,
31
+ :project => "" ,
32
+ :description => "" ,
33
+ :settings => Yajl::Encoder.encode(@cloud_manager.default_quota)
34
+ }
35
+ end
36
+
37
+ def approve(app_id)
38
+ app_info = get_application(app_id)
39
+
40
+ return {:status => "error", :message => "Application with id - [#{app_id}] is not existed"} if app_info.nil?
41
+
42
+ return {:status => "error", :message => "Application [#{app_info.project}] - [#{app_id}] has been #{app_info.state}"} unless app_info.state == 'PENDING'
43
+
44
+ unless existed_tenant?(app_info.project, :find_local => false) then
45
+ # create project tenant and user
46
+ tenant = @cloud_manager.create_tenant(app_info.project, app_info.description)
47
+
48
+ @logger.info("Project [#{tenant.name}] - [#{tenant.id}] has been created with detailed json - #{tenant.to_json}")
49
+
50
+ username = Ocp::Registry::Common.parse_email(app_info.email)[:name]
51
+
52
+ user = @cloud_manager.find_user_by_name(username)
53
+
54
+ if user.nil?
55
+ password = Ocp::Registry::Common.gen_password
56
+ user = @cloud_manager.create_user(username, tenant.id, password, app_info.email)
57
+ @logger.info("User [#{user.name}] - [#{user.id}] has been created with detailed json - #{user.to_json}")
58
+ else
59
+ password = "<your-password-in-other-project>"
60
+ @logger.info("Using existed User [#{user.name}] - [#{user.id}] with detailed json - #{user.to_json}")
61
+ end
62
+
63
+ role = @cloud_manager.default_role
64
+
65
+ @cloud_manager.tenant_add_user_with_role(tenant, user.id, role.id)
66
+
67
+ @logger.info("User [#{user.name}] - [#{user.id}] has been added into project [#{tenant.name}] - [#{tenant.id}] as [#{role.name}] - [#{role.id}]")
68
+
69
+ #assign quota to project
70
+
71
+ settings = @cloud_manager.set_tenant_quota(tenant.id, Yajl.load(app_info.settings))
72
+
73
+ Ocp::Registry::Models::RegistryApplication.where(:id => app_id)
74
+ .update(:state => 'APPROVED',
75
+ :updated_at => Time.now.utc.to_s,
76
+ :settings => Yajl::Encoder.encode(settings) )
77
+ app_info = get_application(app_id)
78
+ if @mail_manager
79
+ admin_msg = {
80
+ :app_info => app_info ,
81
+ :application_link => gen_app_uri(app_id, :review => true) ,
82
+ :applications_link => gen_app_uri
83
+ }
84
+ mail = prepare_mail_properties(:approve_admin, @mail_manager.admin_emails, admin_msg)
85
+ @mail_manager.send_mail(mail)
86
+ user_msg = {
87
+ :app_info => app_info ,
88
+ :application_link => gen_app_uri(app_id) ,
89
+ :applications_link => gen_app_uri(nil, :email => app_info.email) ,
90
+ :login => Ocp::Registry.cloud_login_url ,
91
+ :username => username ,
92
+ :password => password
93
+ }
94
+ mail = prepare_mail_properties(:approve_user, app_info.email, user_msg)
95
+ @mail_manager.send_mail(mail)
96
+ end
97
+ app_info
98
+ else
99
+ @logger.info("Project [#{app_info.project}] name has been used during request time")
100
+ refuse(app_info.id,"Project Name [#{app_info.project}] has been used during request time")
101
+ end
102
+
103
+ end
104
+
105
+ def refuse(app_id,comments)
106
+ app_info = get_application(app_id)
107
+ return {:status => "error", :message => "Application with id - [#{app_id}] is not existed"} if app_info.nil?
108
+ return {:status => "error", :message => "Application [#{app_info.project}] - #{app_id} has been #{app_info.state}"} unless app_info.state == 'PENDING'
109
+
110
+ comments ||= "no comments"
111
+ Ocp::Registry::Models::RegistryApplication.where(:id => app_id)
112
+ .update(:state => 'REFUSED',
113
+ :updated_at => Time.now.utc.to_s,
114
+ :comments => comments)
115
+ app_info = get_application(app_id)
116
+
117
+ if @mail_manager
118
+ admin_msg = {
119
+ :app_info => app_info ,
120
+ :application_link => gen_app_uri(app_id, :review => true) ,
121
+ :applications_link => gen_app_uri
122
+ }
123
+ mail = prepare_mail_properties(:refuse_admin, @mail_manager.admin_emails, admin_msg)
124
+ @mail_manager.send_mail(mail)
125
+ user_msg = {
126
+ :app_info => app_info ,
127
+ :application_link => gen_app_uri(app_id) ,
128
+ :applications_link => gen_app_uri(nil, :email => app_info.email)
129
+ }
130
+ mail = prepare_mail_properties(:refuse_user, app_info.email, user_msg)
131
+ @mail_manager.send_mail(mail)
132
+ end
133
+ app_info
134
+ end
135
+
136
+ def create(app_info)
137
+ if existed_tenant?(app_info['project'])
138
+ {:status => "error", :message => "Project name [#{app_info['project']}] has been used"}
139
+ else
140
+ result = Ocp::Registry::Models::RegistryApplication.create(app_info)
141
+ if @mail_manager
142
+ admin_msg = {
143
+ :app_info => result ,
144
+ :application_link => gen_app_uri(result.id, :review => true) ,
145
+ :applications_link => gen_app_uri
146
+ }
147
+ mail = prepare_mail_properties(:request_admin, @mail_manager.admin_emails, admin_msg)
148
+ @mail_manager.send_mail(mail)
149
+ user_msg = {
150
+ :app_info => result ,
151
+ :application_link => gen_app_uri(result.id) ,
152
+ :applications_link => gen_app_uri(nil, :email => result.email)
153
+ }
154
+ mail = prepare_mail_properties(:request_user, result.email, user_msg)
155
+ @mail_manager.send_mail(mail)
156
+ end
157
+ result
158
+ end
159
+ end
160
+
161
+ def existed_tenant?(tenant, find_local = true)
162
+ if find_local
163
+ local_existed = Ocp::Registry::Models::RegistryApplication.where(:project => tenant, :state => 'APPROVED')
164
+ .count == 0? false : true
165
+ return true if local_existed
166
+ end
167
+ remote_existed = @cloud_manager.get_tenant_by_name(tenant)? true : false
168
+ if remote_existed
169
+ return true
170
+ else
171
+ return false
172
+ end
173
+ end
174
+
175
+ private
176
+
177
+ def get_application(app_id)
178
+ Ocp::Registry::Models::RegistryApplication[:id => app_id]
179
+ end
180
+
181
+ def prepare_mail_properties(template, to, msg = {})
182
+ {
183
+ :to => to ,
184
+ :template => template.to_s ,
185
+ :msg => msg
186
+ }
187
+ end
188
+
189
+ def gen_app_uri(app_id = nil, querys = nil)
190
+ host = URI::escape(Ocp::Registry.base_url)
191
+ port = Ocp::Registry.http_port
192
+ path = "/v1/applications"
193
+ if app_id
194
+ path += URI::escape("/#{app_id}")
195
+ end
196
+ query = nil
197
+ if(querys && querys.is_a?(Hash))
198
+ querys.each do |key, value|
199
+ if query.nil?
200
+ query = "#{key.to_s}=#{value}"
201
+ else
202
+ query += "&"
203
+ query += "#{key.to_s}=#{value}"
204
+ end
205
+ end
206
+ end
207
+
208
+ uri = URI::HTTP.build(:host => host, :port => port, :path => path, :query => query).to_s
209
+ end
210
+
211
+ end
212
+
213
+ end
@@ -0,0 +1,5 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
+ $:.unshift(File.dirname(__FILE__))
3
+
4
+ require "mock/model"
5
+ require 'mock/mock'
@@ -0,0 +1,191 @@
1
+ module Ocp::Registry
2
+ class CloudManager
3
+
4
+ class Mock < CloudManager
5
+ def initialize(cloud_config)
6
+ validate_options(cloud_config)
7
+
8
+ @logger = Ocp::Registry.logger
9
+
10
+ @mock_properties = cloud_config["mock"]
11
+
12
+ unless @mock_properties["auth_url"].match(/\/tokens$/)
13
+ @mock_properties["auth_url"] = @mock_properties["auth_url"] + "/tokens"
14
+ end
15
+
16
+ @mock_options = {
17
+ :provider => "mock",
18
+ :mock_auth_url => @mock_properties["auth_url"],
19
+ :mock_username => @mock_properties["username"],
20
+ :mock_api_key => @mock_properties["api_key"],
21
+ :mock_tenant => @mock_properties["tenant"],
22
+ :mock_endpoint_type => @mock_properties["endpoint_type"]
23
+ }
24
+ @default_role_name = cloud_config["default_role"]
25
+ end
26
+
27
+ def validate_options(cloud_config)
28
+ unless cloud_config.has_key?("mock") &&
29
+ cloud_config["mock"].is_a?(Hash) &&
30
+ cloud_config["mock"]["auth_url"] &&
31
+ cloud_config["mock"]["username"] &&
32
+ cloud_config["mock"]["api_key"] &&
33
+ cloud_config["mock"]["tenant"] &&
34
+ cloud_config["default_role"]
35
+ raise ConfigError, "Invalid mock configuration parameters"
36
+ end
37
+ end
38
+
39
+ def default_compute_quota
40
+ {
41
+ "injected_file_content_bytes"=>10240,
42
+ "metadata_items"=>128,
43
+ "ram"=>51200,
44
+ "floating_ips"=>10,
45
+ "key_pairs"=>100,
46
+ "id"=>"defaults",
47
+ "instances"=>10,
48
+ "security_group_rules"=>20,
49
+ "injected_files"=>5,
50
+ "cores"=>20,
51
+ "fixed_ips"=>-1,
52
+ "injected_file_path_bytes"=>255,
53
+ "security_groups"=>10
54
+ }
55
+ end
56
+
57
+ def default_volume_quota
58
+ {
59
+ "gigabytes"=>1000,
60
+ "volumes"=>10,
61
+ "id"=>"defaults",
62
+ "snapshots"=>10
63
+ }
64
+ end
65
+
66
+ def default_quota
67
+ return @default_quota if @default_quota
68
+ compute_quota = default_compute_quota
69
+ volume_quota = default_volume_quota
70
+ @default_quota = compute_quota.merge (volume_quota)
71
+ cloud_error "Default Quota is not found" unless @default_quota
72
+ @default_quota
73
+ end
74
+
75
+ def get_role_by_name(name)
76
+ role = {
77
+ :id => "08bc68483a804ee59f4290256a8003c6",
78
+ :name => name
79
+ }
80
+ Model.new role
81
+ end
82
+
83
+ def default_role
84
+ return @default_role if @default_role
85
+ @default_role ||= get_role_by_name(@default_role_name)
86
+ cloud_error "Default Role [#{cloud_config["default_role"]}] is not found" unless @default_role
87
+ @logger.info("Default Role #{@default_role.name} - #{@default_role.id}")
88
+ @default_role
89
+ end
90
+
91
+ def set_tenant_quota(tenant_id, settings={})
92
+ result = nil
93
+ compute_quota = set_compute_quota(tenant_id, settings)
94
+ volume_quota = set_volume_quota(tenant_id, settings)
95
+ result = compute_quota.merge (volume_quota) if (compute_quota && volume_quota)
96
+ cloud_error "Quota for #{tenant_id} has not been set" unless result
97
+ result
98
+ end
99
+
100
+
101
+ def cloud_error(message, exception = nil)
102
+ @logger.error(message) if @logger
103
+ @logger.error(exception) if @logger && exception
104
+ raise Ocp::Registry::CloudError, message
105
+ end
106
+
107
+ CINDER_QUOTA_FIELDS = ["volumes", "snapshots", "gigabytes"]
108
+
109
+
110
+ def set_volume_quota(tenant_id, hash)
111
+ settings = Ocp::Registry::Common.hash_filter(hash, CINDER_QUOTA_FIELDS)
112
+ {
113
+ "gigabytes"=>1000,
114
+ "volumes"=>10,
115
+ "id"=>"defaults",
116
+ "snapshots"=>10
117
+ }.merge settings
118
+ end
119
+
120
+ def create_tenant(name, description, enabled = true)
121
+ tenant = {
122
+ :name => "your project name",
123
+ :description => "your project description",
124
+ :enabled => true,
125
+ :id => "1bb0fed1c2df4b5faa19e7700c049e35"
126
+ }
127
+ Model.new tenant
128
+ end
129
+
130
+ def create_user(name, tenant_id, password, email = '')
131
+ user = {
132
+ :email => email,
133
+ :enabled => true,
134
+ :name => name,
135
+ :tenant_id => tenant_id,
136
+ :password => password
137
+ }
138
+ Model.new user
139
+ end
140
+
141
+ def get_tenant_by_name(name)
142
+ nil
143
+ end
144
+
145
+ def tenant_add_user_with_role(tenant, user_id, role_id)
146
+ true
147
+ end
148
+
149
+ def find_user_by_name(name)
150
+ user = {
151
+ :email => "#{name}@email.com",
152
+ :enabled => true,
153
+ :name => name,
154
+ :tenant_id => "1bb0fed1c2df4b5faa19e7700c049e35",
155
+ :password => "passwordxxxxx"
156
+ }
157
+ Model.new user
158
+ end
159
+
160
+ NOVA_QUOTA_FIELDS = ["metadata_items",
161
+ "cores",
162
+ "instances",
163
+ "injected_files",
164
+ "injected_file_content_bytes",
165
+ "ram",
166
+ "floating_ips",
167
+ "fixed_ips",
168
+ "security_groups",
169
+ "security_group_rules"]
170
+
171
+ def set_compute_quota(tenant_id, hash)
172
+ settings = Ocp::Registry::Common.hash_filter(hash, NOVA_QUOTA_FIELDS)
173
+ {
174
+ "injected_file_content_bytes"=>10240,
175
+ "metadata_items"=>128, "ram"=>51200,
176
+ "floating_ips"=>10,
177
+ "key_pairs"=>100,
178
+ "id"=>"defaults",
179
+ "instances"=>10,
180
+ "security_group_rules"=>20,
181
+ "injected_files"=>5,
182
+ "cores"=>20,
183
+ "fixed_ips"=>-1,
184
+ "injected_file_path_bytes"=>255,
185
+ "security_groups"=>10
186
+ }.merge settings
187
+ end
188
+
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,22 @@
1
+ module Ocp::Registry
2
+ class CloudManager
3
+
4
+ class Mock < CloudManager
5
+ class Model
6
+ def initialize(properties)
7
+ if properties.is_a? (Hash)
8
+ @properties = properties
9
+ end
10
+ end
11
+
12
+ def method_missing(method, *args)
13
+ return @properties[method.to_sym]
14
+ end
15
+
16
+ def to_json
17
+ Yajl::Encoder.encode(@properties)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,4 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
+ $:.unshift(File.dirname(__FILE__))
3
+
4
+ require 'openstack/openstack'
@@ -0,0 +1,27 @@
1
+ module Ocp::Registry
2
+
3
+ class CloudManager
4
+
5
+ class Openstack
6
+
7
+ module CinderHelper
8
+ CINDER_QUOTA_FIELDS = ["volumes", "snapshots", "gigabytes"]
9
+
10
+ def default_volume_quota
11
+ with_openstack { volume.get_quota_defaults(nil).body["quota_set"] }
12
+ end
13
+
14
+ def set_volume_quota(tenant_id, hash)
15
+ with_openstack do
16
+ settings = Ocp::Registry::Common.hash_filter(hash, CINDER_QUOTA_FIELDS)
17
+ volume.update_quota(tenant_id, settings).body["quota_set"]
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
27
+ end