foreman_opennebula 2.3.0

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.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +619 -0
  3. data/README.md +26 -0
  4. data/Rakefile +47 -0
  5. data/app/assets/javascripts/foreman_opennebula/scheduler_hint_filter_selected.js +30 -0
  6. data/app/assets/javascripts/foreman_opennebula/vmgroup_selected.js +30 -0
  7. data/app/controllers/foreman_opennebula/hosts_controller.rb +21 -0
  8. data/app/helpers/concerns/foreman_opennebula/form_helper_extensions.rb +9 -0
  9. data/app/helpers/concerns/foreman_opennebula/hosts_helper_extensions.rb +20 -0
  10. data/app/models/concerns/fog_extensions/opennebula/flavor.rb +109 -0
  11. data/app/models/concerns/fog_extensions/opennebula/interface.rb +11 -0
  12. data/app/models/concerns/fog_extensions/opennebula/server.rb +135 -0
  13. data/app/models/concerns/foreman_opennebula/key_pair_compute_resource.rb +80 -0
  14. data/app/models/foreman_opennebula/opennebula.rb +221 -0
  15. data/app/views/api/v2/compute_resources/opennebula.json.rabl +1 -0
  16. data/app/views/compute_resources/form/_opennebula.html.erb +6 -0
  17. data/app/views/compute_resources/show/_opennebula.html.erb +4 -0
  18. data/app/views/compute_resources_vms/form/opennebula/_base.html.erb +85 -0
  19. data/app/views/compute_resources_vms/form/opennebula/_network.html.erb +2 -0
  20. data/app/views/compute_resources_vms/form/opennebula/_scheduler_hint_data.html.erb +13 -0
  21. data/app/views/compute_resources_vms/form/opennebula/_vmgroup_role.html.erb +6 -0
  22. data/app/views/compute_resources_vms/index/_opennebula.html.erb +26 -0
  23. data/app/views/compute_resources_vms/show/_opennebula.html.erb +47 -0
  24. data/app/views/images/form/_opennebula.html.erb +4 -0
  25. data/config/routes.rb +6 -0
  26. data/lib/foreman_opennebula/engine.rb +59 -0
  27. data/lib/foreman_opennebula/version.rb +3 -0
  28. data/lib/foreman_opennebula.rb +4 -0
  29. data/lib/tasks/foreman_opennebula_tasks.rake +48 -0
  30. data/locale/Makefile +60 -0
  31. data/locale/en/foreman_opennebula.po +19 -0
  32. data/locale/foreman_opennebula.pot +19 -0
  33. data/locale/gemspec.rb +2 -0
  34. data/package.json +22 -0
  35. data/test/factories/foreman_opennebula_factories.rb +5 -0
  36. data/test/test_plugin_helper.rb +6 -0
  37. data/test/unit/foreman_opennebula_test.rb +11 -0
  38. data/webpack/components/MemorySizeInput/MemorySizeInput.css +4 -0
  39. data/webpack/components/MemorySizeInput/MemorySizeInput.js +83 -0
  40. data/webpack/components/MemorySizeInput/index.js +3 -0
  41. data/webpack/global_index.js +4 -0
  42. data/webpack/index.js +6 -0
  43. metadata +145 -0
@@ -0,0 +1,221 @@
1
+ module ForemanOpennebula
2
+ class Opennebula < ComputeResource
3
+ include ForemanOpennebula::KeyPairComputeResource
4
+
5
+ validates :url, :format => { :with => URI::DEFAULT_PARSER.make_regexp }, :presence => true
6
+ validates :user, :password, :presence => true
7
+
8
+ delegate :flavors, :networks, :to => :client
9
+
10
+ def self.provider_friendly_name
11
+ 'OpenNebula'
12
+ end
13
+
14
+ def self.model_name
15
+ ComputeResource.model_name
16
+ end
17
+
18
+ def capabilities
19
+ [:build, :image, :key_pair]
20
+ end
21
+
22
+ def provided_attributes
23
+ super.merge({ :mac => :mac })
24
+ end
25
+
26
+ def possible_scheduler_hints
27
+ %w[Cluster Host Raw]
28
+ end
29
+
30
+ def available_flavors
31
+ # TODO: Sort by name.
32
+ flavors.sort_by { |flavor| flavor.id.to_i }
33
+ end
34
+
35
+ def available_networks
36
+ networks.sort_by(&:name)
37
+ end
38
+
39
+ def available_images
40
+ image_pool = ::OpenNebula::ImagePool.new(client.client)
41
+ rc = image_pool.info
42
+ raise ::Foreman::Exception.new N_(rc.message) if ::OpenNebula.is_error?(rc)
43
+ image_pool.sort_by(&:name)
44
+ end
45
+
46
+ def available_clusters
47
+ cluster_pool = ::OpenNebula::ClusterPool.new(client.client)
48
+ rc = cluster_pool.info
49
+ raise ::Foreman::Exception.new N_(rc.message) if ::OpenNebula.is_error?(rc)
50
+ cluster_pool.sort_by(&:name)
51
+ end
52
+
53
+ def available_hosts
54
+ host_pool = ::OpenNebula::HostPool.new(client.client)
55
+ rc = host_pool.info
56
+ raise ::Foreman::Exception.new N_(rc.message) if ::OpenNebula.is_error?(rc)
57
+ host_pool.sort_by(&:name)
58
+ end
59
+
60
+ def available_vmgroups
61
+ vmgroup_pool = ::OpenNebula::VMGroupPool.new(client.client)
62
+ rc = vmgroup_pool.info
63
+ raise ::Foreman::Exception.new N_(rc.message) if ::OpenNebula.is_error?(rc)
64
+ vmgroup_pool.sort_by(&:name)
65
+ end
66
+
67
+ def available_roles(vmgroup_id)
68
+ available_vmgroups.detect { |vmgroup| vmgroup.id == vmgroup_id.to_i }.role_names.sort
69
+ end
70
+
71
+ def available_users
72
+ user_pool = ::OpenNebula::UserPool.new(client.client)
73
+ rc = user_pool.info
74
+ raise ::Foreman::Exception.new N_(rc.message) if ::OpenNebula.is_error?(rc)
75
+ user_pool
76
+ end
77
+
78
+ def create_vm(args = {})
79
+ vm_attrs = {:name => args[:name]}
80
+ vm_attrs[:flavor] = flavors.get(args[:template_id])
81
+ vm_attrs[:flavor].template_id = args[:template_id]
82
+ vm_attrs[:flavor].cpu = args[:cpu] if args[:cpu].present?
83
+ vm_attrs[:flavor].vcpu = args[:vcpu] if args[:vcpu].present?
84
+ vm_attrs[:flavor].memory = args[:memory] if args[:memory].present?
85
+
86
+ if args[:disk_size].present?
87
+ [vm_attrs[:flavor].disk].flatten.compact.first[:SIZE] = args[:disk_size]
88
+ end
89
+
90
+ vm_attrs[:flavor].nic = args[:interfaces_attributes].map do |_, attrs|
91
+ nic = {
92
+ :vnet => networks.get(attrs[:vnet])
93
+ }
94
+ nic[:ip] = attrs['ip'] if args['provision_method'] == 'image' && attrs['ip'].present?
95
+ if vm_attrs[:flavor].nic_default.present?
96
+ vm_attrs[:flavor].nic_default.each do |param, value|
97
+ nic[param.downcase.to_sym] = value
98
+ end
99
+ end
100
+ new_interface(nic)
101
+ end
102
+
103
+ if args[:scheduler_hint_filter].present? && args[:scheduler_hint_data].present?
104
+ if args[:scheduler_hint_filter] == 'Cluster'
105
+ cluster = available_clusters.detect { |c| c.id == args[:scheduler_hint_data].to_i }
106
+ vm_attrs[:flavor].sched_requirements = "CLUSTER_ID = #{cluster.id}"
107
+ elsif args[:scheduler_hint_filter] == 'Host'
108
+ host = available_hosts.detect { |h| h.id == args[:scheduler_hint_data].to_i }
109
+ vm_attrs[:flavor].sched_requirements = "ID = #{host.id}"
110
+ else
111
+ vm_attrs[:flavor].sched_requirements = args[:scheduler_hint_data]
112
+ end
113
+ end
114
+
115
+ if args[:vmgroup_id].present? && args[:vmgroup_role].present?
116
+ vm_attrs[:flavor].vmgroup = { 'VMGROUP_ID' => args[:vmgroup_id], 'ROLE' => args[:vmgroup_role] }
117
+ end
118
+
119
+ if args['provision_method'] == 'image' && args['image_id'].present?
120
+ [vm_attrs[:flavor].disk].flatten.compact.first.delete('IMAGE')
121
+ [vm_attrs[:flavor].disk].flatten.compact.first['IMAGE_ID'] = args[:image_id]
122
+
123
+ vm_attrs[:flavor].context['SET_HOSTNAME'] = args[:name]
124
+ vm_attrs[:flavor].context['USER_DATA'] = args[:user_data] if args[:user_data].present?
125
+
126
+ vm_attrs[:flavor].os['BOOT'] = 'disk0'
127
+ else
128
+ vm_attrs[:flavor].os['BOOT'] = 'nic0,disk0'
129
+ end
130
+
131
+ vm = super(vm_attrs)
132
+ vm.wait_for { vm.status == 1 }
133
+ find_vm_by_uuid(vm.id)
134
+ end
135
+
136
+ def vm_ready(vm)
137
+ vm.wait_for { ready? || poweroff? }
138
+ raise Foreman::Exception.new(N_('Failed to run VM %{name}'), { :name => vm.name }) if vm.poweroff?
139
+ end
140
+
141
+ def supports_update?
142
+ true
143
+ end
144
+
145
+ def update_required?(old_attrs, new_attrs)
146
+ vm = find_vm_by_uuid(old_attrs[:uuid])
147
+ old_attrs[:disk_size] = vm.disk_size
148
+ super(old_attrs, new_attrs)
149
+ end
150
+
151
+ def save_vm(uuid, attr)
152
+ vm = find_vm_by_uuid(uuid)
153
+ changed_attrs = %i[cpu vcpu memory].reject { |k| vm.send(k).to_s == attr[k].to_s }
154
+
155
+ if !vm.ready? && !vm.poweroff?
156
+ raise ::Foreman::Exception.new N_("The VM status: #{vm.status}. It should be ACTIVE (3) or POWEROFF (8)")
157
+ end
158
+
159
+ last_state = vm.state
160
+ if vm.ready?
161
+ vm.onevm_object.poweroff(true)
162
+ vm.wait_for { poweroff? }
163
+ end
164
+
165
+ if changed_attrs.any?
166
+ flavor = client.flavors.new
167
+ %i[cpu vcpu memory].each { |k| flavor.send("#{k}=", attr[k].to_s) }
168
+ vm.onevm_object.resize(flavor.to_s, true)
169
+
170
+ renewed_vm = find_vm_by_uuid(uuid)
171
+ unchanged_attrs = changed_attrs.reject { |k| renewed_vm.send(k).to_s == attr[k].to_s }
172
+ if unchanged_attrs.any?
173
+ raise ::Foreman::Exception.new N_("Parameter #{unchanged_attrs.join(', ')} was not changed. "\
174
+ 'Check if the host has enough resources for this VM')
175
+ end
176
+ end
177
+
178
+ if vm.disk_size.to_i != attr[:disk_size].to_i
179
+ disk_id = vm.disks.first.disk_id.to_i
180
+ rc = vm.onevm_object.disk_resize(disk_id, attr[:disk_size].to_i)
181
+ raise ::Foreman::Exception.new N_(rc.message) if ::OpenNebula.is_error?(rc)
182
+ sleep(1) # wait before resume vm
183
+ end
184
+
185
+ if last_state == 'RUNNING'
186
+ vm.onevm_object.resume
187
+ sleep(2)
188
+ vm_ready(vm)
189
+ end
190
+ vm
191
+ end
192
+
193
+ def test_connection(options = {})
194
+ super
195
+ %i[url user password].all? { |i| errors[i].empty? } && !client.client.get_version.is_a?(OpenNebula::Error)
196
+ rescue => e
197
+ errors[:base] << e.message
198
+ end
199
+
200
+ def console(uuid)
201
+ vm = find_vm_by_uuid(uuid)
202
+ WsProxy.start(:host => vm.host, :host_port => vm.display[:port],
203
+ :password => vm.display[:password]).merge(:type => vm.display[:type], :name => vm.name)
204
+ end
205
+
206
+ def associated_host(vm)
207
+ associate_by('mac', vm.interfaces.map(&:mac))
208
+ end
209
+
210
+ private
211
+
212
+ def client
213
+ @client ||= Fog::Compute.new(
214
+ provider: 'OpenNebula',
215
+ opennebula_username: user,
216
+ opennebula_password: password,
217
+ opennebula_endpoint: url
218
+ )
219
+ end
220
+ end
221
+ end
@@ -0,0 +1 @@
1
+ attributes :url
@@ -0,0 +1,6 @@
1
+ <%= text_f f, :url, :label => _("URL"), :size => "col-md-8", :help_block => _("e.g. http://host.example.com:2633/RPC2") %>
2
+ <%= text_f f, :user, :label => _("User") %>
3
+ <%= password_f f, :password, :label => _("Password"), :unset => unset_password? %>
4
+ <div class="col-md-offset-2">
5
+ <%= test_connection_button_f(f, (f.object.flavors rescue false)) %>
6
+ </div>
@@ -0,0 +1,4 @@
1
+ <tr>
2
+ <td><%= _("URL") %></td>
3
+ <td><%= @compute_resource.url %></td>
4
+ </tr>
@@ -0,0 +1,85 @@
1
+ <% unless new_vm %>
2
+ <% if host.compute_object.ready? %>
3
+ <%= alert(:header => _('Warning'),
4
+ :class => 'alert-warning',
5
+ :text => _('Editing VM parameters causes it to reboot.')) %>
6
+ <% end %>
7
+ <%= alert(:header => _('Notice'),
8
+ :class => 'alert-info',
9
+ :text => _('Disk size can only be increased.')) %>
10
+ <% disabled = true %>
11
+ <% else %>
12
+ <% disabled = false %>
13
+ <% end %>
14
+
15
+ <%= select_f f, :template_id, compute_resource.available_flavors, :id, :name, {},
16
+ :label => _('Template'),
17
+ :disabled => disabled %>
18
+
19
+ <%= counter_f f, :cpu,
20
+ :label => _('CPU'),
21
+ :min => 0.01,
22
+ :help_inline => _('Default from template') %>
23
+
24
+ <%= counter_f f, :vcpu,
25
+ :label => _('VCPU'),
26
+ :min => 1,
27
+ :help_inline => _('Default from template') %>
28
+
29
+ <%= megabyte_size_f f, :memory,
30
+ :label => _('Memory'),
31
+ :help_inline => _('Default from template') %>
32
+
33
+ <%= megabyte_size_f f, :disk_size,
34
+ :label => _('Disk'),
35
+ :help_inline => _('Default from template') %>
36
+
37
+ <% unless controller_name == 'compute_attributes' %>
38
+ <%= select_f f, :vmgroup_id, compute_resource.available_vmgroups, :id, :name, { :include_blank => true },
39
+ :label => _('VM Group'),
40
+ :help_inline => _('Optional'),
41
+ :'data-url' => url_for(controller: 'foreman_opennebula/hosts', action: 'vmgroup_selected'),
42
+ :onchange => 'vmgroupSelected(this);',
43
+ :disabled => disabled %>
44
+
45
+ <div id='vmgroup_role_wrapper'>
46
+ <% if host.compute_object.vmgroup_id.present? %>
47
+ <%= render :partial => 'compute_resources_vms/form/opennebula/vmgroup_role', :locals => {
48
+ :vmgroup_id => host.compute_object.vmgroup_id,
49
+ :disabled => disabled
50
+ } %>
51
+ <% end %>
52
+ </div>
53
+
54
+ <%= selectable_f f, :scheduler_hint_filter, compute_resource.possible_scheduler_hints, { :include_blank => true },
55
+ :label => _('Scheduler hint filter'),
56
+ :'data-url' => url_for(controller: 'foreman_opennebula/hosts',
57
+ action: 'scheduler_hint_filter_selected'),
58
+ :'data-minimum-results-for-search' => 'Infinity',
59
+ :onchange => 'schedulerHintFilterSelected(this);',
60
+ :help_inline => _('Optional'),
61
+ :disabled => disabled %>
62
+
63
+ <div id='scheduler_hint_data_wrapper'>
64
+ <% if host.compute_object.scheduler_hint_filter.present? %>
65
+ <%= render :partial => 'compute_resources_vms/form/opennebula/scheduler_hint_data', :locals => {
66
+ :scheduler_hint_filter => host.compute_object.scheduler_hint_filter,
67
+ :disabled => disabled
68
+ } %>
69
+ <% end %>
70
+ </div>
71
+
72
+ <%-
73
+ arch ||= nil ; os ||= nil
74
+ images = possible_images(compute_resource, arch, os)
75
+ -%>
76
+ <div id='image_selection'>
77
+ <%= select_f f, :image_id, images, :uuid, :name, {
78
+ :include_blank => (images.empty? || images.size == 1) ? false : _('Please select an image') },
79
+ :disabled => images.empty? || (params[:host] && params[:host][:provision_method] == 'build'),
80
+ :label => _('Image') %>
81
+ </div>
82
+
83
+ <%= javascript_include_tag 'foreman_opennebula/vmgroup_selected' %>
84
+ <%= javascript_include_tag 'foreman_opennebula/scheduler_hint_filter_selected' %>
85
+ <% end %>
@@ -0,0 +1,2 @@
1
+ <%= select_f f, :vnet, compute_resource.available_networks, :id, :name, { :include_blank => true },
2
+ { :label => _('Network'), :label_size => "col-md-3", :size => "col-md-8" } %>
@@ -0,0 +1,13 @@
1
+ <%- scheduler_hint_filter ||= @host.compute_attributes[:scheduler_hint_filter] %>
2
+ <%- disabled ||= false %>
3
+ <%= fields_for "#{type}[compute_attributes]", @host.compute_object do |f| %>
4
+ <%- if scheduler_hint_filter == 'Cluster' %>
5
+ <%= select_f f, :scheduler_hint_data, @host.compute_resource.available_clusters, :id, :name,
6
+ { :include_blank => true }, :label => _("Deploy to cluster"), :disabled => disabled %>
7
+ <%- elsif scheduler_hint_filter == 'Host' %>
8
+ <%= select_f f, :scheduler_hint_data, @host.compute_resource.available_hosts, :id, :name,
9
+ { :include_blank => true }, :label => _("Deploy to host"), :disabled => disabled %>
10
+ <%- else %>
11
+ <%= text_f f, :scheduler_hint_data, :label => _("Scheduler hint data"), :disabled => disabled %>
12
+ <%- end %>
13
+ <%- end %>
@@ -0,0 +1,6 @@
1
+ <%- vmgroup_id ||= @host.compute_attributes[:vmgroup_id] %>
2
+ <%- disabled ||= false %>
3
+ <%= fields_for "#{type}[compute_attributes]", @host.compute_object do |f| %>
4
+ <%= selectable_f f, :vmgroup_role, @host.compute_resource.available_roles(vmgroup_id),
5
+ { :include_blank => true }, :label => _("Role"), :disabled => disabled %>
6
+ <%- end %>
@@ -0,0 +1,26 @@
1
+ <thead>
2
+ <tr>
3
+ <th><%= _('Name') %></th>
4
+ <th><%= _('CPU') %></th>
5
+ <th><%= _('VCPU') %></th>
6
+ <th><%= _('Memory') %></th>
7
+ <th><%= _('Storage') %></th>
8
+ <th><%= _('Host') %></th>
9
+ <th><%= _('State') %></th>
10
+ <th><%= _('Actions') %></th>
11
+ </tr>
12
+ </thead>
13
+ <tbody>
14
+ <% @vms.each do |vm| %>
15
+ <tr>
16
+ <td><%= link_to_if_authorized vm.name, hash_for_compute_resource_vm_path(:compute_resource_id => @compute_resource, :id => vm.uuid).merge(:auth_object => @compute_resource, :auth_action => 'view', :authorizer => authorizer) %></td>
17
+ <td><%= vm.cpu %></td>
18
+ <td><%= vm.vcpu %></td>
19
+ <td><%= number_to_human_size(vm.memory.to_i.megabytes) %></td>
20
+ <td><%= number_to_human_size(vm.disks.map { |disk| disk.size.to_i.megabytes }.sum) %></td>
21
+ <td><%= vm.host %></td>
22
+ <td><span <%= vm_power_class(vm.ready?) %>><%= vm_state(vm) %></span></td>
23
+ <td><%= action_buttons(*available_actions(vm)) %></td>
24
+ </tr>
25
+ <% end %>
26
+ </tbody>
@@ -0,0 +1,47 @@
1
+ <% title @vm.name %>
2
+ <div class='col-md-12'>
3
+ <table class="<%= table_css_classes %>">
4
+ <thead>
5
+ <tr><th colspan="2"><%= _('Properties') %></th></tr>
6
+ </thead>
7
+ <tbody>
8
+ <%= prop :cpu, 'CPU' %>
9
+ <%= prop :vcpu, 'VCPU' %>
10
+ <tr>
11
+ <td><%= _('Memory') %></td>
12
+ <td><%= number_to_human_size(@vm.memory.to_i.megabytes) %></td>
13
+ </tr>
14
+ <% @vm.disks.each do |disk| %>
15
+ <tr>
16
+ <td><%= _("Disk %s") % disk.target %></td>
17
+ <td><%= "#{disk.image} / #{number_to_human_size(disk.size.to_i.megabytes)}" %></td>
18
+ </tr>
19
+ <% end %>
20
+ <% @vm.interfaces.each do |iface| %>
21
+ <tr>
22
+ <td><%= _("Nic %s") % iface.nic_id %></td>
23
+ <td><%= "#{iface.network} / #{iface.mac}" %></td>
24
+ </tr>
25
+ <% end %>
26
+ <% if @vm.vmgroup_id.present? %>
27
+ <tr>
28
+ <td><%= _("VM Group") %></td>
29
+ <td><%= @compute_resource.available_vmgroups.detect { |vmgroup| vmgroup.id == @vm.vmgroup_id.to_i }.name %></td>
30
+ </tr>
31
+ <tr>
32
+ <td><%= _("Role") %></td>
33
+ <td><%= @vm.vmgroup_role %></td>
34
+ </tr>
35
+ <% end %>
36
+ <% if @vm.host.present? %>
37
+ <tr>
38
+ <td><%= _("Cluster") %></td>
39
+ <td><%= @compute_resource.available_hosts.detect { |host| host.name == @vm.host }.to_hash['HOST']['CLUSTER'] %></td>
40
+ </tr>
41
+ <%= prop :host %>
42
+ <% end %>
43
+ <%= prop :state, 'LCM State' %>
44
+ <%= prop :sched_message if @vm.sched_message %>
45
+ </tbody>
46
+ </table>
47
+ </div>
@@ -0,0 +1,4 @@
1
+ <%= image_field f, :label => _("Image"), :help_inline => _("Image used to create new vm.") %>
2
+ <%= text_f f, :username, :value => @image.username || "root", :help_inline => _("The user that is used to ssh into the instance, normally cloud-user, ec2-user, ubuntu, root etc") %>
3
+ <%= password_f f, :password, :help_inline => _("Password to authenticate with - used for SSH finish step.") %>
4
+ <%= checkbox_f f, :user_data, :help_inline => _("Does this image support user data input (e.g. via cloud-init)?") %>
data/config/routes.rb ADDED
@@ -0,0 +1,6 @@
1
+ Rails.application.routes.draw do
2
+ namespace :foreman_opennebula do
3
+ match 'hosts/vmgroup_selected', :to => 'hosts#vmgroup_selected', :via => 'post'
4
+ match 'hosts/scheduler_hint_filter_selected', :to => 'hosts#scheduler_hint_filter_selected', :via => 'post'
5
+ end
6
+ end
@@ -0,0 +1,59 @@
1
+ require 'fast_gettext'
2
+ require 'gettext_i18n_rails'
3
+ require 'fog/opennebula'
4
+
5
+ module ForemanOpennebula
6
+ class Engine < ::Rails::Engine
7
+ isolate_namespace ForemanOpennebula
8
+ engine_name 'foreman_opennebula'
9
+
10
+ initializer 'foreman_opennebula.register_gettext', after: :load_config_initializers do |_app|
11
+ locale_dir = File.join(File.expand_path('../..', __dir__), 'locale')
12
+ locale_domain = 'foreman_opennebula'
13
+ Foreman::Gettext::Support.add_text_domain locale_domain, locale_dir
14
+ end
15
+
16
+ initializer 'foreman_opennebula.register_plugin', :before => :finisher_hook do |_app|
17
+ Foreman::Plugin.register :foreman_opennebula do
18
+ requires_foreman '>= 3.7'
19
+ compute_resource ForemanOpennebula::Opennebula
20
+ register_global_js_file 'global'
21
+ end
22
+ end
23
+
24
+ config.to_prepare do
25
+ require 'fog/opennebula/models/compute/server'
26
+ require 'fog/opennebula/models/compute/flavor'
27
+ require 'fog/opennebula/models/compute/interface'
28
+ require File.expand_path('../../app/models/concerns/fog_extensions/opennebula/server', __dir__)
29
+ require File.expand_path('../../app/models/concerns/fog_extensions/opennebula/flavor', __dir__)
30
+ require File.expand_path('../../app/models/concerns/fog_extensions/opennebula/interface', __dir__)
31
+ require File.expand_path('../../app/helpers/concerns/foreman_opennebula/hosts_helper_extensions', __dir__)
32
+ require File.expand_path('../../app/helpers/concerns/foreman_opennebula/form_helper_extensions', __dir__)
33
+
34
+ ::Fog::Compute::OpenNebula::Server.include(FogExtensions::OpenNebula::Server)
35
+ ::Fog::Compute::OpenNebula::Flavor.include(FogExtensions::OpenNebula::Flavor)
36
+ ::Fog::Compute::OpenNebula::Interface.include(FogExtensions::OpenNebula::Interface)
37
+ ::HostsHelper.include(ForemanOpennebula::HostsHelperExtensions)
38
+ # ::FormHelper.include(ForemanOpennebula::FormHelperExtensions)
39
+ ::ActionView::Base.include(ForemanOpennebula::FormHelperExtensions)
40
+ rescue => e
41
+ Rails.logger.warn "ForemanOpennebula: skipping engine hook (#{e})"
42
+ end
43
+
44
+ assets_to_precompile =
45
+ Dir.chdir(root) do
46
+ Dir['app/assets/javascripts/**/*', 'app/assets/stylesheets/**/*'].map do |f|
47
+ f.split(File::SEPARATOR, 4).last
48
+ end
49
+ end
50
+
51
+ initializer 'foreman_opennebula.assets.precompile' do |app|
52
+ app.config.assets.precompile += assets_to_precompile
53
+ end
54
+
55
+ initializer 'foreman_opennebula.configure_assets', group: :assets do
56
+ SETTINGS[:foreman_opennebula] = { assets: { precompile: assets_to_precompile } }
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,3 @@
1
+ module ForemanOpennebula
2
+ VERSION = '2.3.0'.freeze
3
+ end
@@ -0,0 +1,4 @@
1
+ require 'foreman_opennebula/engine'
2
+
3
+ module ForemanOpennebula
4
+ end
@@ -0,0 +1,48 @@
1
+ require 'rake/testtask'
2
+
3
+ # Tasks
4
+ namespace :foreman_opennebula do
5
+ namespace :example do
6
+ desc 'Example Task'
7
+ task task: :environment do
8
+ # Task goes here
9
+ end
10
+ end
11
+ end
12
+
13
+ # Tests
14
+ namespace :test do
15
+ desc 'Test ForemanOpennebula'
16
+ Rake::TestTask.new(:foreman_opennebula) do |t|
17
+ test_dir = File.expand_path('../../test', __dir__)
18
+ t.libs << 'test'
19
+ t.libs << test_dir
20
+ t.pattern = "#{test_dir}/**/*_test.rb"
21
+ t.verbose = true
22
+ t.warning = false
23
+ end
24
+ end
25
+
26
+ namespace :foreman_opennebula do
27
+ task :rubocop do
28
+ begin
29
+ require 'rubocop/rake_task'
30
+ RuboCop::RakeTask.new(:rubocop_foreman_opennebula) do |task|
31
+ task.patterns = ["#{ForemanOpennebula::Engine.root}/app/**/*.rb",
32
+ "#{ForemanOpennebula::Engine.root}/lib/**/*.rb",
33
+ "#{ForemanOpennebula::Engine.root}/test/**/*.rb"]
34
+ end
35
+ rescue
36
+ puts 'Rubocop not loaded.'
37
+ end
38
+
39
+ Rake::Task['rubocop_foreman_opennebula'].invoke
40
+ end
41
+ end
42
+
43
+ Rake::Task[:test].enhance ['test:foreman_opennebula']
44
+
45
+ load 'tasks/jenkins.rake'
46
+ if Rake::Task.task_defined?(:'jenkins:unit')
47
+ Rake::Task['jenkins:unit'].enhance ['test:foreman_opennebula', 'foreman_opennebula:rubocop']
48
+ end
data/locale/Makefile ADDED
@@ -0,0 +1,60 @@
1
+ #
2
+ # Makefile for PO merging and MO generation. More info in the README.
3
+ #
4
+ # make all-mo (default) - generate MO files
5
+ # make check - check translations using translate-tool
6
+ # make tx-update - download and merge translations from Transifex
7
+ # make clean - clean everything
8
+ #
9
+ DOMAIN = foreman_opennebula
10
+ VERSION = $(shell ruby -e 'require "rubygems";spec = Gem::Specification::load(Dir.glob("../*.gemspec")[0]);puts spec.version')
11
+ POTFILE = $(DOMAIN).pot
12
+ MOFILE = $(DOMAIN).mo
13
+ POFILES = $(shell find . -name '$(DOMAIN).po')
14
+ MOFILES = $(patsubst %.po,%.mo,$(POFILES))
15
+ POXFILES = $(patsubst %.po,%.pox,$(POFILES))
16
+ EDITFILES = $(patsubst %.po,%.edit.po,$(POFILES))
17
+
18
+ %.mo: %.po
19
+ mkdir -p $(shell dirname $@)/LC_MESSAGES
20
+ msgfmt -o $(shell dirname $@)/LC_MESSAGES/$(MOFILE) $<
21
+
22
+ # Generate MO files from PO files
23
+ all-mo: $(MOFILES)
24
+
25
+ # Check for malformed strings
26
+ %.pox: %.po
27
+ msgfmt -c $<
28
+ pofilter --nofuzzy -t variables -t blank -t urls -t emails -t long -t newlines \
29
+ -t endwhitespace -t endpunc -t puncspacing -t options -t printf -t validchars --gnome $< > $@
30
+ cat $@
31
+ ! grep -q msgid $@
32
+
33
+ %.edit.po:
34
+ touch $@
35
+
36
+ check: $(POXFILES)
37
+
38
+ # Unify duplicate translations
39
+ uniq-po:
40
+ for f in $(shell find ./ -name "*.po") ; do \
41
+ msguniq $$f -o $$f ; \
42
+ done
43
+
44
+ tx-pull: $(EDITFILES)
45
+ tx pull -f
46
+ for f in $(EDITFILES) ; do \
47
+ sed -i 's/^\("Project-Id-Version: \).*$$/\1$(DOMAIN) $(VERSION)\\n"/' $$f; \
48
+ done
49
+
50
+ tx-update: tx-pull
51
+ @echo
52
+ @echo Run rake plugin:gettext[$(DOMAIN)] from the Foreman installation, then make -C locale mo-files to finish
53
+ @echo
54
+
55
+ mo-files: $(MOFILES)
56
+ git add $(POFILES) $(POTFILE) ../locale/*/LC_MESSAGES
57
+ git commit -m "i18n - pulling from tx"
58
+ @echo
59
+ @echo Changes commited!
60
+ @echo
@@ -0,0 +1,19 @@
1
+ # foreman_opennebula
2
+ #
3
+ # This file is distributed under the same license as foreman_opennebula.
4
+ #
5
+ #, fuzzy
6
+ msgid ""
7
+ msgstr ""
8
+ "Project-Id-Version: version 0.0.1\n"
9
+ "Report-Msgid-Bugs-To: \n"
10
+ "POT-Creation-Date: 2014-08-20 08:46+0100\n"
11
+ "PO-Revision-Date: 2014-08-20 08:54+0100\n"
12
+ "Last-Translator: Foreman Team <foreman-dev@googlegroups.com>\n"
13
+ "Language-Team: Foreman Team <foreman-dev@googlegroups.com>\n"
14
+ "Language: \n"
15
+ "MIME-Version: 1.0\n"
16
+ "Content-Type: text/plain; charset=UTF-8\n"
17
+ "Content-Transfer-Encoding: 8bit\n"
18
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
19
+
@@ -0,0 +1,19 @@
1
+ # foreman_opennebula
2
+ #
3
+ # This file is distributed under the same license as foreman_opennebula.
4
+ #
5
+ #, fuzzy
6
+ msgid ""
7
+ msgstr ""
8
+ "Project-Id-Version: version 0.0.1\n"
9
+ "Report-Msgid-Bugs-To: \n"
10
+ "POT-Creation-Date: 2014-08-20 08:46+0100\n"
11
+ "PO-Revision-Date: 2014-08-20 08:46+0100\n"
12
+ "Last-Translator: Foreman Team <foreman-dev@googlegroups.com>\n"
13
+ "Language-Team: Foreman Team <foreman-dev@googlegroups.com>\n"
14
+ "Language: \n"
15
+ "MIME-Version: 1.0\n"
16
+ "Content-Type: text/plain; charset=UTF-8\n"
17
+ "Content-Transfer-Encoding: 8bit\n"
18
+ "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
19
+
data/locale/gemspec.rb ADDED
@@ -0,0 +1,2 @@
1
+ # Matches foreman_opennebula.gemspec
2
+ _('TODO: Description of ForemanOpennebula.')