Skip to content
Browse files

fixes #4015 - support oVirt using templates like images

  • Loading branch information...
1 parent 823d4e1 commit 99527500ba12e0217e853ec85c709e73337c84ee @jimmidyson jimmidyson committed with domcleal Jan 17, 2014
View
4 .gitignore
@@ -25,8 +25,8 @@ foreman_client
doc/apidoc*
.rbenv*
.rvmrc*
-.ruby-version
-.ruby-gemset
+.ruby-version*
+.ruby-gemset*
locale/*.mo
locale/*/*.pox
locale/*/LC_MESSAGES
View
26 app/assets/javascripts/application.js
@@ -163,18 +163,26 @@ function toggleRowGroup(el) {
}
function template_info(div, url) {
- form = $("form").serialize();
+ // Ignore method as PUT redirects to host page if used on update
+ form = $("form :input[name!='_method']").serialize();
build = $('input:radio[name$="[provision_method]"]:checked').val();
$(div).html(spinner_placeholder());
- $(div).load(url + "?provisioning=" + build + "&" + form,
- function(response, status, xhr) {
- if (status == "error") {
- $(div).html('<div class="alert alert-warning alert-dismissable">' +
- '<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>' +
- __('Sorry but no templates were configured.') + '</div>');
- }
- });
+
+ // Use a post to avoid request URI too large issues with big forms
+ $.ajax({
+ type: "POST",
+ url: url + "?provisioning=" + build,
+ data: form,
+ success: function(response, status, xhr) {
+ $(div).html(response);
+ },
+ error: function(jqXHR, textStatus, errorThrown) {
+ $(div).html('<div class="alert alert-warning alert-dismissable">' +
+ '<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>' +
+ __('Sorry but no templates were configured.') + '</div>');
+ }
+ });
}
//add bookmark dialog
View
9 app/assets/javascripts/compute_resource.js
@@ -50,9 +50,10 @@ function testConnection(item) {
function ovirt_templateSelected(item){
var template = $(item).val();
- var url = $(item).attr('data-url');
- $(item).indicator_show();
- $.ajax({
+ if (template) {
+ var url = $(item).attr('data-url');
+ $(item).indicator_show();
+ $.ajax({
type:'post',
url: url,
data:'template_id=' + template,
@@ -69,7 +70,9 @@ function ovirt_templateSelected(item){
$('[rel="twipsy"]').tooltip();
}
})
+ }
}
+
// fill in the template interfaces.
function add_network_interface(item){
var new_id = add_child_node($("#network_interfaces .add_nested_fields"));
View
23 app/assets/javascripts/host_edit.js
@@ -368,8 +368,16 @@ function update_provisioning_image(){
$.each(result, function() {
image_options.append($("<option />").val(this.image.uuid).text(this.image.name));
});
- if (image_options.find('option').length > 0)
+ if (image_options.find('option').length > 0) {
image_options.attr('disabled', false);
+ if ($('#host_provision_method_image')[0].checked && $('#provider').val() == 'Ovirt') {
+ var template_select = $('#host_compute_attributes_template');
+ if (template_select.length > 0) {
+ template_select.val(image_options.val());
+ ovirt_templateSelected(image_options);
+ }
+ }
+ }
}
})
}
@@ -496,11 +504,24 @@ $(document).on('submit',"[data-submit='progress_bar']", function() {
$(document).on('change', '#host_provision_method_build', function () {
$('#network_provisioning').show();
$('#image_provisioning').hide();
+ $('#image_selection select').attr('disabled', true);
+ if ($('#provider').val() == 'Ovirt')
+ $('#host_compute_attributes_template').attr('disabled', false);
});
$(document).on('change', '#host_provision_method_image', function () {
$('#network_provisioning').hide();
$('#image_provisioning').show();
+ var image_options = $('#image_selection select');
+ image_options.attr('disabled', false);
+ if ($('#provider').val() == 'Ovirt') {
+ var template_options = $('#host_compute_attributes_template');
+ if (template_options.length > 0) {
+ template_options.attr('disabled', true);
+ template_options.val(image_options.val());
+ ovirt_templateSelected(image_options);
+ }
+ }
});
$(document).on('change', '.interface_domain', function () {
View
2 app/controllers/compute_resources_controller.rb
@@ -98,8 +98,6 @@ def test_connection
def template_selected
compute = @compute_resource.template(params[:template_id])
- compute.interfaces
- compute.volumes
respond_to do |format|
format.json { render :json => compute }
end
View
4 app/helpers/layout_helper.rb
@@ -99,9 +99,7 @@ def radio_button_f(f, attr, options = {})
text = options.delete(:text)
value = options.delete(:value)
label_tag('', :class=>"radio-inline") do
- content_tag(:div, :class => "radio") do
- f.radio_button(attr, value, options) + " #{text} "
- end
+ f.radio_button(attr, value, options) + " #{text} "
end
end
View
10 app/models/compute_resources/foreman/model/ovirt.rb
@@ -13,7 +13,7 @@ def self.model_name
end
def capabilities
- [:build]
+ [:build, :image]
end
def supports_update?
@@ -50,7 +50,10 @@ def templates(opts={})
end
def template(id)
- client.templates.get(id) || raise(ActiveRecord::RecordNotFound)
+ compute = client.templates.get(id) || raise(ActiveRecord::RecordNotFound)
+ compute.interfaces
+ compute.volumes
+ compute
end
def clusters
@@ -122,6 +125,9 @@ def start_vm(uuid)
def create_vm(args = {})
#ovirt doesn't accept '.' in vm name.
args[:name] = args[:name].parameterize
+ if (image_id = args[:image_id])
+ args.merge!({:template => image_id})
+ end
vm = super({ :first_boot_dev => 'network', :quota => ovirt_quota }.merge(args))
begin
create_interfaces(vm, args[:interfaces_attributes])
View
6 app/models/concerns/fog_extensions/ovirt/server.rb
@@ -5,6 +5,8 @@ module Server
include ActionView::Helpers::NumberHelper
+ attr_accessor :image_id
+
def state
status
end
@@ -13,7 +15,7 @@ def interfaces_attributes=(attrs); end
def volumes_attributes=(attrs); end
- def poweroff
+ def poweroff
service.vm_action(:id =>id, :action => :shutdown)
end
@@ -28,4 +30,4 @@ def vm_description
end
end
-end
+end
View
4 app/models/concerns/orchestration/ssh_provision.rb
@@ -7,7 +7,7 @@ module Orchestration::SSHProvision
end
def ssh_provision?
- compute_attributes.present? && capabilities.include?(:image) && !image.try(:user_data)
+ compute_attributes.present? && capabilities.include?(:image) && !image.try(:user_data) && provision_method == 'image'
end
protected
@@ -47,6 +47,8 @@ def setSSHWaitForResponse
credentials = { :key_data => [compute_resource.key_pair.secret] }
elsif vm.respond_to?(:password) and vm.password.present?
credentials = { :password => vm.password, :auth_methods => ["password"] }
+ elsif image.respond_to?(:password) and image.password.present?
+ credentials = { :password => image.password, :auth_methods => ["password"] }
else
raise ::Foreman::Exception.new(N_('Unable to find proper authentication method'))
end
View
2 app/models/concerns/orchestration/tftp.rb
@@ -10,7 +10,7 @@ module Orchestration::TFTP
end
def tftp?
- !!(subnet and subnet.tftp?) and (operatingsystem and operatingsystem.pxe_variant) and managed? and capabilities.include?(:build)
+ !!(subnet and subnet.tftp?) and (operatingsystem and operatingsystem.pxe_variant) and managed? and capabilities.include?(:build) and provision_method != 'image'
end
def tftp
View
2 app/models/host/managed.rb
@@ -137,7 +137,7 @@ class Jail < ::Safemode::Jail
:unless => Proc.new { |host| !host.managed or capabilities.include?(:image) }
validates :ip, :format => {:with => Net::Validations::IP_REGEXP}, :if => Proc.new { |host| host.require_ip_validation? }
validates :ptable_id, :presence => {:message => N_("cant be blank unless a custom partition has been defined")},
- :if => Proc.new { |host| host.managed and host.disk.empty? and not defined?(Rake) and capabilities.include?(:build) }
+ :if => Proc.new { |host| host.managed and host.disk.empty? and not defined?(Rake) and host.provision_method != 'image' and capabilities.include?(:build) }
validates :serial, :format => {:with => /[01],\d{3,}n\d/, :message => N_("should follow this format: 0,9600n8")},
:allow_blank => true, :allow_nil => true
after_validation :set_compute_attributes
View
15 app/views/compute_resources_vms/form/_ovirt.html.erb
@@ -43,3 +43,18 @@
</div>
<% checked = params[:host] && params[:host][:compute_attributes] && params[:host][:compute_attributes][:start] || '1' %>
<%= checkbox_f f, :start, { :checked => (checked == '1'), :help_inline => _("Power ON this machine"), :label => _('Start') } if new && controller_name != "compute_attributes" %>
+
+<%
+ arch ||= nil ; os ||= nil
+ images = possible_images(compute_resource, arch, os)
+-%>
+
+<div id='image_selection'>
+ <%= select_f f, :image_id, images, :uuid, :name,{:include_blank => (images.empty? || images.size == 1) ? false : _('Please select an image')},
+ { :disabled => true, :'data-url' => template_selected_compute_resource_path(compute_resource),
+ :onchange => 'ovirt_templateSelected(this);',
+ :help_inline => :indicator,
+ :help_block => _("Image to use"),
+ :label => _('Image')} %>
+</div>
+
View
1 app/views/hosts/_compute.html.erb
@@ -15,5 +15,6 @@
</div>
<% end%>
<%= hidden_field_tag 'capabilities', compute_resource.capabilities %>
+ <%= hidden_field_tag 'provider', compute_resource.provider %>
<%= content_tag(:div,'', :id => :'supports_update', :data=>{:'supports-update'=> compute_resource.supports_update? || (@host && @host.new_record?)}) %>
<% end if compute_resource %>
View
12 app/views/hosts/_operating_system.html.erb
@@ -6,15 +6,15 @@
<span id="os_select">
<%= render 'common/os_selection/architecture', :item => @host %>
</span>
-<% image_provisioning = f.object.capabilities && f.object.capabilities.include?(:image) %>
+<% build_provisioning = f.object.capabilities && f.object.capabilities.include?(:build) && !@host.image %>
<div id='provisioning_method' <%= display? (@host.capabilities.size < 2) %> >
<%= field(f, :provision_method, :label => _('Provisioning Method')) do
- radio_button_f(f, :provision_method, :value=>'build', :checked=> !image_provisioning, :text=> _("Network Based"))+
- radio_button_f(f, :provision_method, :value=>'image', :checked=> image_provisioning, :text=> _("Image Based"))
+ radio_button_f(f, :provision_method, :value=>'build', :checked=> build_provisioning, :text=> _("Network Based"))+
+ radio_button_f(f, :provision_method, :value=>'image', :checked=> !build_provisioning, :text=> _("Image Based"))
end %>
</div>
-<div id='network_provisioning' <%= display? image_provisioning %> >
- <% if @host.new_record? or @host.type_changed? %>
+<div id='network_provisioning' <%= display? !build_provisioning %> >
+ <% if @host.new_record? or @host.type_changed? -%>
<%= checkbox_f f, :build, :checked => true, :help_inline => _("Enable this host for provisioning") %>
<% end %>
<span id="media_select">
@@ -27,7 +27,7 @@
<%= password_f f, :root_pass %>
</div>
-<div id='image_provisioning' <%= display? !image_provisioning %> >
+<div id='image_provisioning' <%= display? build_provisioning %> >
</div>
<!-- this section is used for displaying the provisioning scripts-->
View
3 app/views/images/_form.html.erb
@@ -5,6 +5,9 @@
<%= select_f f, :operatingsystem_id, Operatingsystem.all, :id, :to_label %>
<%= select_f f, :architecture_id, Architecture.all, :id, :to_label %>
<%= 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") %>
+ <% if @compute_resource.provider == 'Ovirt' %>
+ <%= password_f f, :password, :help_inline => _("Password to authenticate with - used for SSH finish step.") %>
+ <% end %>
<%= image_field(f) %>
<%= checkbox_f f, :user_data, :help_inline => _("Does this image support user data input (e.g. via cloud-init)?") %>
<% if @compute_resource.provider == 'EC2' %>
View
2 config/routes.rb
@@ -51,7 +51,7 @@
get 'multiple_disassociate'
post 'update_multiple_disassociate'
get 'auto_complete_search'
- get 'template_used'
+ post 'template_used'
get 'active'
get 'pending'
get 'out_of_sync'
View
5 db/migrate/20140115130443_add_password_to_images.rb
@@ -0,0 +1,5 @@
+class AddPasswordToImages < ActiveRecord::Migration
+ def change
+ add_column :images, :password, :string
+ end
+end

0 comments on commit 9952750

Please sign in to comment.
Something went wrong with that request. Please try again.