Revision 8838eb42
Added by Ohad Levy over 11 years ago
- ID 8838eb42a2a292f50126966d3fa768edad3a237a
app/controllers/hosts_controller.rb | ||
---|---|---|
@report_summary = Report.summarise(@range.days.ago, @host)
|
||
}
|
||
format.yaml { render :text => params["rundeck"].nil? ? @host.info.to_yaml : @host.rundeck.to_yaml }
|
||
format.json { render :json => @host.to_json({:methods => [:host_parameters]}) }
|
||
format.json { render :json => @host.to_json({:methods => [:host_parameters], :include => :interfaces }) }
|
||
end
|
||
end
|
||
|
||
... | ... | |
if @domain.subnets.any?
|
||
page['#subnet_select'].html(render(:partial => 'common/domain', :locals => {:item => @host}))
|
||
page['#host_subnet_id'].val(@subnet.id).change if @subnet
|
||
page['#sp_subnet'].html(render(:partial => 'hosts/sp_subnet', :locals => {:item => @host}))
|
||
end
|
||
end
|
||
end
|
app/controllers/subnets_controller.rb | ||
---|---|---|
# query our subnet dhcp proxy for an unused IP
|
||
def freeip
|
||
not_found and return unless (s=params[:subnet_id].to_i) > 0
|
||
not_found and return unless (subnet = Subnet.find(s))
|
||
|
||
if (ip = subnet.unused_ip(params[:host_mac]))
|
||
respond_to do |format|
|
||
format.html do
|
||
render :update do |page|
|
||
page['#host_ip'].val(ip)
|
||
page['#host_ip'].show('highlight', 5000)
|
||
@organization = params[:organization_id].blank? ? nil : Organization.find(params[:organization_id])
|
||
@location = params[:location_id].blank? ? nil : Location.find(params[:location_id])
|
||
Taxonomy.as_taxonomy @organization, @location do
|
||
not_found and return unless (subnet = Subnet.find(s))
|
||
if (ip = subnet.unused_ip(params[:host_mac]))
|
||
respond_to do |format|
|
||
format.html do
|
||
render :update do |page|
|
||
page['#host_ip'].val(ip)
|
||
page['#host_ip'].show('highlight', 5000)
|
||
end
|
||
end
|
||
format.json { render :json => {:ip => ip} }
|
||
end
|
||
format.json { render :json => {:ip => ip} }
|
||
else
|
||
# we don't want any failures if we failed to query our proxy
|
||
head :status => 200
|
||
end
|
||
else
|
||
# we don't want any failures if we failed to query our proxy
|
||
head :status => 200
|
||
end
|
||
rescue => e
|
||
logger.warn "Failed to query #{subnet} for free ip: #{e}"
|
app/helpers/hosts_and_hostgroups_helper.rb | ||
---|---|---|
classes.select { |pc| klasses.include?(pc.id) }
|
||
end
|
||
|
||
def ifs_bmc_opts obj
|
||
case obj.read_attribute(:type)
|
||
when "Nic::BMC"
|
||
{}
|
||
else
|
||
{ :disabled => true, :value => nil }
|
||
end
|
||
end
|
||
|
||
end
|
app/helpers/hosts_helper.rb | ||
---|---|---|
)
|
||
)
|
||
end
|
||
|
||
def conflict_objects errors
|
||
errors.keys.map(&:to_s).grep(/conflict$/).map(&:to_sym)
|
||
end
|
||
|
||
def has_conflicts? errors
|
||
conflict_objects(errors).each do |c|
|
||
return true if errors[c.to_sym].any?
|
||
end
|
||
false
|
||
end
|
||
end
|
app/models/domain.rb | ||
---|---|---|
belongs_to :dns, :class_name => "SmartProxy"
|
||
has_many :domain_parameters, :dependent => :destroy, :foreign_key => :reference_id
|
||
has_and_belongs_to_many :users, :join_table => "user_domains"
|
||
has_many :interfaces, :class_name => 'Nic::Base'
|
||
|
||
accepts_nested_attributes_for :domain_parameters, :reject_if => lambda { |a| a[:value].blank? }, :allow_destroy => true
|
||
validates_uniqueness_of :name
|
||
validates_uniqueness_of :fullname, :allow_blank => true, :allow_nil => true
|
app/models/host.rb | ||
---|---|---|
has_many :reports, :dependent => :destroy
|
||
has_many :host_parameters, :dependent => :destroy, :foreign_key => :reference_id
|
||
accepts_nested_attributes_for :host_parameters, :reject_if => lambda { |a| a[:value].blank? }, :allow_destroy => true
|
||
has_many :interfaces, :dependent => :destroy, :inverse_of => :host, :class_name => 'Nic::Base'
|
||
accepts_nested_attributes_for :interfaces, :reject_if => lambda { |a| a[:mac].blank? }, :allow_destroy => true
|
||
belongs_to :owner, :polymorphic => true
|
||
belongs_to :sp_subnet, :class_name => "Subnet"
|
||
belongs_to :compute_resource
|
||
belongs_to :image
|
||
|
||
... | ... | |
# handles all orchestration of smart proxies.
|
||
include Foreman::Renderer
|
||
include Orchestration
|
||
include Orchestration::DHCP
|
||
include Orchestration::DNS
|
||
include Orchestration::Compute
|
||
include Orchestration::TFTP
|
||
include Orchestration::Puppetca
|
||
include Orchestration::SSHProvision
|
||
include HostTemplateHelpers
|
||
|
||
validates_uniqueness_of :ip, :if => Proc.new {|host| host.require_ip_validation?}
|
||
validates_uniqueness_of :mac, :unless => Proc.new { |host| host.compute? or !host.managed }
|
||
validates_uniqueness_of :sp_mac, :allow_nil => true, :allow_blank => true
|
||
validates_uniqueness_of :sp_name, :sp_ip, :allow_blank => true, :allow_nil => true
|
||
validates_presence_of :architecture_id, :operatingsystem_id, :if => Proc.new {|host| host.managed}
|
||
validates_presence_of :domain_id, :if => Proc.new {|host| host.managed}
|
||
validates_presence_of :mac, :unless => Proc.new { |host| host.compute? or !host.managed }
|
||
... | ... | |
validates_format_of :ip, :with => Net::Validations::IP_REGEXP, :if => Proc.new { |host| host.require_ip_validation? }
|
||
validates_presence_of :ptable_id, :message => "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) }
|
||
validates_format_of :sp_mac, :with => Net::Validations::MAC_REGEXP, :allow_nil => true, :allow_blank => true
|
||
validates_format_of :sp_ip, :with => Net::Validations::IP_REGEXP, :allow_nil => true, :allow_blank => true
|
||
validates_format_of :serial, :with => /[01],\d{3,}n\d/, :message => "should follow this format: 0,9600n8", :allow_blank => true, :allow_nil => true
|
||
|
||
validates_presence_of :puppet_proxy_id, :if => Proc.new {|h| h.managed? } if SETTINGS[:unattended]
|
||
... | ... | |
false
|
||
end
|
||
|
||
def sp_valid?
|
||
!sp_name.empty? and !sp_ip.empty? and !sp_mac.empty?
|
||
end
|
||
|
||
def jumpstart?
|
||
operatingsystem.family == "Solaris" and architecture.name =~/Sparc/i rescue false
|
||
end
|
||
... | ... | |
new.puppetclasses = puppetclasses
|
||
# Clone any parameters as well
|
||
host_parameters.each{|param| new.host_parameters << HostParameter.new(:name => param.name, :value => param.value, :nested => true)}
|
||
interfaces.each {|int| new.interfaces << int.clone }
|
||
# clear up the system specific attributes
|
||
[:name, :mac, :ip, :uuid, :certname, :last_report, :sp_mac, :sp_ip, :sp_name, :puppet_status, ].each do |attr|
|
||
[:name, :mac, :ip, :uuid, :certname, :last_report].each do |attr|
|
||
new.send "#{attr}=", nil
|
||
end
|
||
new.puppet_status = 0
|
||
new
|
||
end
|
||
|
||
def sp_ip
|
||
bmc_nic.try(:ip)
|
||
end
|
||
|
||
def sp_mac
|
||
bmc_nic.try(:mac)
|
||
end
|
||
|
||
def sp_subnet_id
|
||
bmc_nic.try(:subnet_id)
|
||
end
|
||
|
||
def sp_subnet
|
||
bmc_nic.try(:subnet)
|
||
end
|
||
|
||
def sp_name
|
||
bmc_nic.try(:name)
|
||
end
|
||
|
||
def host_status
|
||
if build
|
||
"Pending Installation"
|
||
... | ... | |
Classification.new(:host => self).enc
|
||
end
|
||
|
||
# align common mac and ip address input
|
||
def normalize_addresses
|
||
# a helper for variable scoping
|
||
helper = []
|
||
[self.mac,self.sp_mac].each do |m|
|
||
unless m.empty?
|
||
m.downcase!
|
||
if m=~/[a-f0-9]{12}/
|
||
m = m.gsub(/(..)/){|mh| mh + ":"}[/.{17}/]
|
||
elsif mac=~/([a-f0-9]{1,2}:){5}[a-f0-9]{1,2}/
|
||
m = m.split(":").map{|nibble| "%02x" % ("0x" + nibble)}.join(":")
|
||
end
|
||
end
|
||
helper << m
|
||
end
|
||
self.mac, self.sp_mac = helper
|
||
|
||
helper = []
|
||
[self.ip,self.sp_ip].each do |i|
|
||
unless i.empty?
|
||
i = i.split(".").map{|nibble| nibble.to_i}.join(".") if i=~/(\d{1,3}\.){3}\d{1,3}/
|
||
end
|
||
helper << i
|
||
end
|
||
self.ip, self.sp_ip = helper
|
||
def bmc_nic
|
||
interfaces.bmc.first
|
||
end
|
||
|
||
# ensure that host name is fqdn
|
||
... | ... | |
self.certname = Foreman.uuid if read_attribute(:certname).blank? or new_record?
|
||
end
|
||
|
||
def normalize_addresses
|
||
self.mac = Net::Validations.normalize_mac(mac)
|
||
self.ip = Net::Validations.normalize_ip(ip)
|
||
end
|
||
|
||
def force_lookup_value_matcher
|
||
lookup_values.each { |v| v.match = "fqdn=#{fqdn}" }
|
||
end
|
||
|
||
end
|
app/models/nic.rb | ||
---|---|---|
# Represents a Host's network interface
|
||
# This class is the both parent
|
||
module Nic
|
||
class Base < ActiveRecord::Base
|
||
include Authorization
|
||
include Foreman::STI
|
||
|
||
set_table_name :nics
|
||
|
||
attr_accessible :host_id, :host,
|
||
:mac,
|
||
:_destroy # used for nested_attributes
|
||
|
||
before_validation :normalize_mac
|
||
|
||
validates_uniqueness_of :mac
|
||
validates_presence_of :mac
|
||
validates_format_of :mac, :with => Net::Validations::MAC_REGEXP
|
||
|
||
validate :uniq_with_hosts
|
||
|
||
validates_presence_of :host
|
||
|
||
scope :bootable, where(:type => "Nic::Bootable")
|
||
scope :bmc, where(:type => "Nic::BMC")
|
||
scope :interfaces, where(:type => "Nic::Interface")
|
||
scope :managed, where(:type => "Nic::Managed")
|
||
|
||
belongs_to :host, :inverse_of => :interfaces
|
||
# keep extra attributes needed for sub classes.
|
||
serialize :attrs, Hash
|
||
|
||
protected
|
||
|
||
def uniq_fields_with_hosts
|
||
[:mac]
|
||
end
|
||
|
||
# make sure we don't have a conflicting interface with an host record
|
||
def uniq_with_hosts
|
||
failed = false
|
||
uniq_fields_with_hosts.each do |attr|
|
||
value = self.send(attr)
|
||
unless value.blank?
|
||
if host.send(attr) == value
|
||
errors.add attr, "Can't use the same value as the primary interface"
|
||
failed = true
|
||
elsif Host.where(attr => value).limit(1).pluck(attr).any?
|
||
errors.add attr, "already in use"
|
||
failed = true
|
||
end
|
||
end
|
||
end
|
||
!failed
|
||
end
|
||
|
||
def normalize_mac
|
||
self.mac = Net::Validations.normalize_mac(mac)
|
||
end
|
||
end
|
||
end
|
app/models/nic/bmc.rb | ||
---|---|---|
module Nic
|
||
class BMC < Managed
|
||
|
||
ATTRIBUTES = [:username, :password, :provider]
|
||
attr_accessible *ATTRIBUTES
|
||
|
||
PROVIDERS = %w(IPMI)
|
||
validates_inclusion_of :provider, :in => PROVIDERS
|
||
|
||
ATTRIBUTES.each do |method|
|
||
define_method method do
|
||
self.attrs ||= { }
|
||
self.attrs[method]
|
||
end
|
||
|
||
define_method "#{method}=" do |value|
|
||
self.attrs ||= { }
|
||
self.attrs[method] = value
|
||
end
|
||
end
|
||
end
|
||
end
|
app/models/nic/bootable.rb | ||
---|---|---|
module Nic
|
||
class Bootable < Managed
|
||
|
||
delegate :tftp?, :tftp, :to => :subnet
|
||
delegate :jumpstart?, :build?, :to => :host
|
||
|
||
# ensure that we can only have one bootable interface
|
||
validates_uniqueness_of :type, :scope => :host_id, :message => "Only one bootable interface is allowed"
|
||
|
||
def dhcp_record
|
||
return unless dhcp? or @dhcp_record
|
||
@dhcp_record ||= host.jumpstart? ? Net::DHCP::SparcRecord.new(dhcp_attrs) : Net::DHCP::Record.new(dhcp_attrs)
|
||
end
|
||
|
||
protected
|
||
|
||
def dhcp_attrs
|
||
attrs = super.merge({
|
||
:filename => host.operatingsystem.boot_filename(host),
|
||
:nextServer => boot_server
|
||
})
|
||
# Are we booting SPARC solaris?
|
||
if host.jumpstart?
|
||
jumpstart_arguments = host.os.jumpstart_params host, host.model.vendor_class
|
||
attrs.merge! jumpstart_arguments unless jumpstart_arguments.empty?
|
||
end
|
||
attrs
|
||
end
|
||
|
||
end
|
||
end
|
app/models/nic/interface.rb | ||
---|---|---|
module Nic
|
||
class Interface < Base
|
||
|
||
attr_accessible :ip
|
||
|
||
validates_uniqueness_of :ip
|
||
validates_presence_of :ip
|
||
validates_format_of :ip, :with => Net::Validations::IP_REGEXP
|
||
|
||
validate :normalize_ip
|
||
|
||
protected
|
||
|
||
def uniq_fields_with_hosts
|
||
[:mac, :ip]
|
||
end
|
||
|
||
def normalize_ip
|
||
self.ip = Net::Validations.normalize_ip(ip)
|
||
end
|
||
|
||
end
|
||
end
|
app/models/nic/managed.rb | ||
---|---|---|
module Nic
|
||
class Managed < Interface
|
||
include Orchestration
|
||
include Orchestration::DHCP
|
||
include Orchestration::DNS
|
||
|
||
attr_accessible :name, :subnet_id, :subnet, :domain_id, :domain
|
||
|
||
validates_uniqueness_of :name, :scope => :domain_id
|
||
validates_presence_of :subnet_id, :domain_id
|
||
|
||
belongs_to :subnet
|
||
belongs_to :domain
|
||
|
||
delegate :vlanid, :network, :to => :subnet
|
||
|
||
# Interface normally are not executed by them self, so we use the host queue and related methods.
|
||
# this ensures our orchestration works on both a host and a managed interface
|
||
delegate :progress_report_id, :require_ip_validation?, :overwrite?, :capabilities, :managed?, :to => :host
|
||
|
||
# this ensures we can create an interface even when there is no host queue
|
||
# e.g. outside to Host nested attributes
|
||
def queue_with_host
|
||
if host
|
||
logger.debug 'Using host queue'
|
||
host.queue
|
||
else
|
||
logger.debug 'Using nic queue'
|
||
queue_without_host
|
||
end
|
||
end
|
||
alias_method_chain :queue, :host
|
||
|
||
# returns a DHCP reservation object
|
||
def dhcp_record
|
||
return unless dhcp? or @dhcp_record
|
||
@dhcp_record ||= Net::DHCP::Record.new(dhcp_attrs)
|
||
end
|
||
|
||
protected
|
||
|
||
def uniq_fields_with_hosts
|
||
[:mac, :ip, :name]
|
||
end
|
||
|
||
# returns a hash of dhcp record attributes
|
||
def dhcp_attrs
|
||
raise "DHCP not supported for this NIC" unless dhcp?
|
||
{
|
||
:hostname => name,
|
||
:ip => ip,
|
||
:mac => mac,
|
||
:proxy => subnet.dhcp_proxy,
|
||
:network => network
|
||
}
|
||
end
|
||
end
|
||
end
|
app/models/orchestration.rb | ||
---|---|---|
require_dependency "proxy_api"
|
||
require "proxy_api"
|
||
require 'orchestration/queue'
|
||
|
||
module Orchestration
|
||
def self.included(base)
|
||
base.send :include, InstanceMethods
|
||
base.class_eval do
|
||
attr_reader :queue, :post_queue, :old, :record_conflicts
|
||
# stores actions to be performed on our proxies based on priority
|
||
before_validation :set_queue
|
||
before_validation :setup_clone
|
||
|
||
# extend our Host model to know how to handle subsystems
|
||
include Orchestration::DNS
|
||
include Orchestration::DHCP
|
||
include Orchestration::TFTP
|
||
include Orchestration::Puppetca
|
||
include Orchestration::Compute
|
||
include Orchestration::SSHProvision
|
||
attr_reader :old
|
||
|
||
# save handles both creation and update of hosts
|
||
before_save :on_save
|
||
... | ... | |
# after validation callbacks status, as rails by default does
|
||
# not care about their return status.
|
||
def valid?(context = nil)
|
||
setup_clone
|
||
super
|
||
orchestration_errors?
|
||
end
|
||
|
||
# we override the destroy method, in order to ensure our queue exists before other callbacks
|
||
# and to process the queue only if we found no errors
|
||
def destroy
|
||
set_queue
|
||
super
|
||
def queue
|
||
@queue ||= Orchestration::Queue.new
|
||
end
|
||
|
||
def post_queue
|
||
@post_queue ||= Orchestration::Queue.new
|
||
end
|
||
|
||
def record_conflicts
|
||
@record_conflicts ||= []
|
||
end
|
||
|
||
private
|
||
... | ... | |
# in order not to keep any left overs in our proxies.
|
||
def process queue_name
|
||
return true if Rails.env == "test"
|
||
|
||
# queue is empty - nothing to do.
|
||
q = send(queue_name)
|
||
return if q.empty?
|
||
... | ... | |
|
||
rescue Net::Conflict => e
|
||
task.status = "conflict"
|
||
@record_conflicts << e
|
||
record_conflicts << e
|
||
failure e.message, nil, :conflict
|
||
#TODO: This is not a real error, but at the moment the proxy / foreman lacks better handling
|
||
# of the error instead of explode.
|
||
... | ... | |
end
|
||
end
|
||
|
||
def set_queue
|
||
@queue = Orchestration::Queue.new
|
||
@post_queue = Orchestration::Queue.new
|
||
@record_conflicts = []
|
||
end
|
||
|
||
# we keep the before update host object in order to compare changes
|
||
def setup_clone
|
||
return if new_record?
|
||
... | ... | |
end
|
||
|
||
def update_cache
|
||
Rails.cache.write(progress_report_id, (queue.all + post_queue.all).to_json, :expires_in => 5.minutes)
|
||
Rails.cache.write(progress_report_id, (queue.all + post_queue.all).to_json, :expires_in => 5.minutes)
|
||
end
|
||
|
||
end
|
app/models/orchestration/dhcp.rb | ||
---|---|---|
base.class_eval do
|
||
after_validation :queue_dhcp
|
||
before_destroy :queue_dhcp_destroy
|
||
validate :ip_belongs_to_subnet?, :valid_jumpstart_model
|
||
validate :ip_belongs_to_subnet?
|
||
end
|
||
end
|
||
|
||
module InstanceMethods
|
||
|
||
def dhcp?
|
||
!subnet.nil? and subnet.dhcp? and managed? and capabilities.include?(:build)
|
||
end
|
||
|
||
def sp_dhcp?
|
||
sp_valid? and !sp_subnet.nil? and sp_subnet.dhcp?
|
||
name.present? and ip.present? and !subnet.nil? and subnet.dhcp? and managed? and capabilities.include?(:build)
|
||
end
|
||
|
||
def dhcp_record
|
||
... | ... | |
@dhcp_record ||= jumpstart? ? Net::DHCP::SparcRecord.new(dhcp_attrs) : Net::DHCP::Record.new(dhcp_attrs)
|
||
end
|
||
|
||
def sp_dhcp_record
|
||
return unless sp_dhcp? or @sp_dhcp_record
|
||
@sp_dhcp_record ||= Net::DHCP::Record.new sp_dhcp_attrs
|
||
end
|
||
|
||
protected
|
||
|
||
def set_dhcp
|
||
... | ... | |
dhcp_record.conflicts.each{|conflict| conflict.create}
|
||
end
|
||
|
||
def set_sp_dhcp
|
||
sp_dhcp_record.create
|
||
end
|
||
|
||
def set_sp_dhcp_conflicts
|
||
sp_dhcp_record.conflicts.each{|conflict| conflict.create}
|
||
end
|
||
|
||
def del_dhcp
|
||
dhcp_record.destroy
|
||
end
|
||
... | ... | |
dhcp_record.conflicts.each{|conflict| conflict.destroy}
|
||
end
|
||
|
||
def del_sp_dhcp
|
||
sp_dhcp_record.destroy
|
||
end
|
||
|
||
def del_sp_dhcp_conflicts
|
||
sp_dhcp_record.conflicts.each{|conflict| conflict.destroy}
|
||
end
|
||
|
||
private
|
||
# returns a hash of dhcp record settings
|
||
def dhcp_attrs
|
||
return unless dhcp?
|
||
dhcp_attr = { :name => name, :filename => operatingsystem.boot_filename(self),
|
||
:ip => ip, :mac => mac, :hostname => name, :proxy => proxy_for_host,
|
||
:network => subnet.network, :nextServer => boot_server }
|
||
|
||
if jumpstart?
|
||
jumpstart_arguments = os.jumpstart_params self, model.vendor_class
|
||
dhcp_attr.merge! jumpstart_arguments unless jumpstart_arguments.empty?
|
||
end
|
||
dhcp_attr
|
||
end
|
||
|
||
# returns a hash of service processor / ilo dhcp record settings
|
||
def sp_dhcp_attrs
|
||
return unless sp_dhcp?
|
||
{ :hostname => sp_name, :name => sp_name, :ip => sp_ip, :mac => sp_mac, :proxy => proxy_for_sp, :network => sp_subnet.network }
|
||
end
|
||
|
||
# where are we booting from
|
||
def boot_server
|
||
# if we don't manage tftp at all, we dont create a next-server entry.
|
||
... | ... | |
failure "failed to detect boot server: #{e}"
|
||
end
|
||
|
||
private
|
||
|
||
# returns a hash of dhcp record settings
|
||
def dhcp_attrs
|
||
return unless dhcp?
|
||
dhcp_attr = { :name => name, :filename => operatingsystem.boot_filename(self),
|
||
:ip => ip, :mac => mac, :hostname => name, :proxy => subnet.dhcp_proxy,
|
||
:network => subnet.network, :nextServer => boot_server }
|
||
|
||
if jumpstart?
|
||
jumpstart_arguments = os.jumpstart_params self, model.vendor_class
|
||
dhcp_attr.merge! jumpstart_arguments unless jumpstart_arguments.empty?
|
||
end
|
||
dhcp_attr
|
||
end
|
||
|
||
def queue_dhcp
|
||
return unless (dhcp? or (old and old.dhcp?) or sp_dhcp? or (old and old.sp_dhcp?)) and orchestration_errors?
|
||
return unless (dhcp? or (old and old.dhcp?)) and orchestration_errors?
|
||
queue_remove_dhcp_conflicts if dhcp_conflict_detected?
|
||
new_record? ? queue_dhcp_create : queue_dhcp_update
|
||
end
|
||
|
||
def queue_dhcp_create
|
||
logger.debug "Scheduling new DHCP reservations"
|
||
logger.debug "Scheduling new DHCP reservations for #{self}"
|
||
queue.create(:name => "Create DHCP Settings for #{self}", :priority => 10,
|
||
:action => [self, :set_dhcp]) if dhcp?
|
||
queue.create(:name => "Create DHCP Settings for #{sp_name}", :priority => 15,
|
||
:action => [self, :set_sp_dhcp]) if sp_dhcp?
|
||
|
||
end
|
||
|
||
def queue_dhcp_update
|
||
... | ... | |
queue.create(:name => "Create DHCP Settings for #{self}", :priority => 9,
|
||
:action => [self, :set_dhcp]) if dhcp?
|
||
end
|
||
|
||
if sp_dhcp_update_required?
|
||
logger.debug("Detected a changed required for BMC DHCP record")
|
||
queue.create(:name => "Remove DHCP Settings for #{old.sp_name}", :priority => 5,
|
||
:action => [old, :del_sp_dhcp]) if old.sp_dhcp?
|
||
queue.create(:name => "Create DHCP Settings for #{sp_name}", :priority => 14,
|
||
:action => [self, :set_sp_dhcp]) if sp_dhcp?
|
||
end
|
||
end
|
||
|
||
# do we need to update our dhcp reservations
|
||
... | ... | |
# IP Address / name changed
|
||
return true if ((old.ip != ip) or (old.name != name) or (old.mac != mac) or (old.subnet != subnet))
|
||
# Handle jumpstart
|
||
if jumpstart?
|
||
#TODO, abstract this way once interfaces are fully used
|
||
if self.is_a?(Host) and jumpstart?
|
||
if !old.build? or (old.medium != medium or old.arch != arch) or
|
||
(os and old.os and (old.os.name != os.name or old.os != os))
|
||
return true
|
||
... | ... | |
false
|
||
end
|
||
|
||
def sp_dhcp_update_required?
|
||
return true if ((old.sp_name != sp_name) or (old.sp_mac != sp_mac) or (old.sp_ip != sp_ip) or (old.sp_subnet != sp_subnet))
|
||
false
|
||
end
|
||
|
||
def queue_dhcp_destroy
|
||
return unless dhcp? and errors.empty?
|
||
queue.create(:name => "Remove DHCP Settings for #{self}", :priority => 5,
|
||
:action => [self, :del_dhcp])
|
||
queue.create(:name => "Remove DHCP Settings for #{sp_name}", :priority => 5,
|
||
:action => [self, :del_sp_dhcp]) if sp_valid?
|
||
true
|
||
end
|
||
|
||
... | ... | |
logger.debug "Scheduling DHCP conflicts removal"
|
||
queue.create(:name => "DHCP conflicts removal for #{self}", :priority => 5,
|
||
:action => [self, :del_dhcp_conflicts]) if dhcp_record and dhcp_record.conflicting?
|
||
queue.create(:name => "DHCP conflicts removal for #{sp_name}", :priority => 5,
|
||
:action => [self, :del_sp_dhcp_conflicts]) if sp_valid? and sp_dhcp and sp_dhcp_record.conflicting?
|
||
end
|
||
|
||
def ip_belongs_to_subnet?
|
||
... | ... | |
# we let other validations handle that
|
||
end
|
||
|
||
def valid_jumpstart_model
|
||
return unless jumpstart?
|
||
errors.add :model_id, "is required for Solaris SPARC deployment" if model.blank?
|
||
errors.add :model_id, "Has an unknown vendor class" if model and model.vendor_class.empty?
|
||
false
|
||
end
|
||
|
||
def proxy_for_host
|
||
subnet.dhcp_proxy
|
||
end
|
||
|
||
def proxy_for_sp
|
||
sp_subnet.dhcp_proxy
|
||
end
|
||
|
||
def dhcp_conflict_detected?
|
||
# we can't do any dhcp based validations when our MAC address is defined afterwards (e.g. in vm creation)
|
||
return false if mac.blank? or name.blank?
|
||
... | ... | |
|
||
return false unless dhcp?
|
||
status = true
|
||
status = failure("DHCP record #{dhcp_record.conflicts[0]} already exists", nil, :conflict) if dhcp_record and dhcp_record.conflicting?
|
||
status &= failure("DHCP record #{sp_dhcp_record.conflicts[0]} already exists", nil, :conflict) if sp_dhcp? and sp_dhcp_record and sp_dhcp_record.conflicting?
|
||
status = failure("DHCP records #{dhcp_record.conflicts.to_sentence} already exists", nil, :conflict) if dhcp_record and dhcp_record.conflicting?
|
||
overwrite? ? errors.are_all_conflicts? : status
|
||
end
|
||
|
app/models/orchestration/dns.rb | ||
---|---|---|
module InstanceMethods
|
||
|
||
def dns?
|
||
!domain.nil? and !domain.proxy.nil? and managed?
|
||
name.present? and ip.present? and !domain.nil? and !domain.proxy.nil? and managed?
|
||
end
|
||
|
||
def reverse_dns?
|
||
!subnet.nil? and !subnet.dns_proxy.nil? and managed? and capabilities.include?(:build)
|
||
name.present? and ip.present? and !subnet.nil? and subnet.dns? and managed?
|
||
end
|
||
|
||
def dns_a_record
|
||
... | ... | |
:action => [self, :del_conflicting_dns_a_record]) if dns? and dns_a_record and dns_a_record.conflicting?
|
||
queue.create(:name => "Remove conflicting Reverse DNS record for #{self}", :priority => 0,
|
||
:action => [self, :del_conflicting_dns_ptr_record]) if reverse_dns? and dns_ptr_record and dns_ptr_record.conflicting?
|
||
|
||
end
|
||
|
||
def dns_conflict_detected?
|
||
... | ... | |
return false if overwrite?
|
||
|
||
status = true
|
||
status = failure("DNS A Record #{dns_a_record.conflicts[0]} already exists", nil, :conflict) if dns? and dns_a_record and dns_a_record.conflicting?
|
||
status &= failure("DNS PTR Record #{dns_ptr_record.conflicts[0]} already exists", nil, :conflict) if reverse_dns? and dns_ptr_record and dns_ptr_record.conflicting?
|
||
status = failure("DNS A Records #{dns_a_record.conflicts.to_sentence} already exists", nil, :conflict) if dns? and dns_a_record and dns_a_record.conflicting?
|
||
status &= failure("DNS PTR Records #{dns_ptr_record.conflicts.to_sentence} already exists", nil, :conflict) if reverse_dns? and dns_ptr_record and dns_ptr_record.conflicting?
|
||
status
|
||
end
|
||
|
app/models/subnet.rb | ||
---|---|---|
include Authorization
|
||
include Taxonomix
|
||
has_many :hosts
|
||
# sps = Service processors / ilom boards etc
|
||
has_many :sps, :class_name => "Host", :foreign_key => 'sp_subnet_id'
|
||
belongs_to :dhcp, :class_name => "SmartProxy"
|
||
belongs_to :tftp, :class_name => "SmartProxy"
|
||
belongs_to :dns, :class_name => "SmartProxy"
|
||
has_many :subnet_domains, :dependent => :destroy
|
||
has_many :domains, :through => :subnet_domains
|
||
has_many :interfaces, :class_name => 'Nic::Base'
|
||
validates_presence_of :network, :mask, :name
|
||
validates_associated :subnet_domains
|
||
validates_uniqueness_of :network
|
||
... | ... | |
end
|
||
}
|
||
|
||
before_destroy EnsureNotUsedBy.new(:hosts, :sps)
|
||
before_destroy EnsureNotUsedBy.new(:hosts, :interfaces )
|
||
|
||
scoped_search :on => [:name, :network, :mask, :gateway, :dns_primary, :dns_secondary, :vlanid], :complete_value => true
|
||
scoped_search :in => :domains, :on => :name, :rename => :domain, :complete_value => true
|
||
... | ... | |
end.compact
|
||
end
|
||
|
||
def as_json options = {}
|
||
super({:methods => [:cidr, :to_label]}.merge(options))
|
||
end
|
||
|
||
private
|
||
|
||
def validate_ranges
|
app/views/api/v1/subnets/show.json.rabl | ||
---|---|---|
|
||
attributes :id, :name, :network, :mask, :priority, :vlanid,
|
||
:gateway, :dns_primary, :dns_secondary, :from, :to, :domain_ids,
|
||
:dns_id, :dhcp_id, :tftp_id
|
||
:dns_id, :dhcp_id, :tftp_id, :cidr
|
||
|
||
child :dhcp => :dhcp do
|
||
attributes :id, :name, :url
|
app/views/compute_resources_vms/form/libvirt/_network.html.erb | ||
---|---|---|
<div class="fields">
|
||
<% if (networks = compute_resource.networks).any? -%>,
|
||
<% if (networks = compute_resource.networks).any? -%>
|
||
<%= selectable_f f, :bridge, networks.map(&:name), { }, :class => "span2", :label => "Network",
|
||
:help_inline => remove_child_link("X", f, { :method => :'_delete', :title => 'remove network interface', :class => 'label label-important' }) %>
|
||
<% else -%>
|
app/views/hosts/_conflicts.html.erb | ||
---|---|---|
<p> Please review them carefully, if you are certain that they should be removed, please click on overwrite.</p>
|
||
|
||
<div class="alert alert-message alert-block base">
|
||
<% @host.errors[:conflict].each do |e| -%>
|
||
<li><%= e %></li>
|
||
<% conflict_objects(@host.errors).each do |obj| -%>
|
||
<% @host.errors[obj].each do |e| -%>
|
||
<li><%= e %></li>
|
||
<% end -%>
|
||
<% end -%>
|
||
</div>
|
||
|
app/views/hosts/_form.html.erb | ||
---|---|---|
<%= javascript 'host_edit', 'compute_resource', 'lookup_keys'%>
|
||
<%= render "conflicts" if @host.errors[:conflict].any? %>
|
||
<%= render "conflicts" if has_conflicts?(@host.errors) %>
|
||
<%= render "progress" %>
|
||
<%= form_for @host, :html => {:'data-submit' => 'progress_bar'} do |f| %>
|
||
<%= base_errors_for @host %>
|
app/views/hosts/_interfaces.html.erb | ||
---|---|---|
<div class="fields">
|
||
<%= field_set_tag "Interface #{remove_child_link('x', f, { :rel => 'twipsy', "data-title" => 'remove network interface', :'data-placement' => 'left',
|
||
:class => 'fr badge badge-important'})}".html_safe, :id => "interface" do -%>
|
||
<%= selectable_f f, :type, [["Interface", Nic::Managed],["BMC", Nic::BMC]], {}, :class => 'interface_type', :disabled => !f.object.new_record? %>
|
||
<%= text_f f, :mac, :label => "MAC" %>
|
||
<%= text_f f, :name, :help_inline => "DNS name" %>
|
||
<%= select_f f, :domain_id, accessible_domains, :id, :to_label,
|
||
{ :include_blank => accessible_domains.any? ? true : "No domains"},
|
||
{ :disabled => accessible_domains.empty? ? true : false,
|
||
:help_inline => image_tag("spinner.gif", :class => "indicator hide"),
|
||
:class => 'interface_domain', :'data-url' => domain_selected_hosts_path } %>
|
||
<%= select_f f, :subnet_id, domain_subnets, :id, :title,
|
||
{ :include_blank => domain_subnets.any? ? true : "No subnets"},
|
||
{ :disabled => domain_subnets.empty? ? true : false,
|
||
:help_inline => image_tag("spinner.gif", :class => "indicator hide"),
|
||
:class => 'interface_subnet', :'data-url' => freeip_subnets_path } %>
|
||
<%= text_f f, :ip, :label => "IP" %>
|
||
|
||
<%# hack to get BMC attributes show up without AJAX -%>
|
||
<%= content_tag :span, :id => 'bmc_fields', :class => f.object.is_a?(Nic::BMC) ? '' : 'hide' do %>
|
||
<%= text_f f, :username, ifs_bmc_opts(f.object) %>
|
||
<%= password_f f, :password, ifs_bmc_opts(f.object) %>
|
||
<%# TODO: current rails version does not allow to pass a selected value where there is no method (e.g. providers below) rescue here is a hack %>
|
||
<%= selectable_f f, :provider, Nic::BMC::PROVIDERS, {:selected => nil}, ifs_bmc_opts(f.object) rescue f.hidden_field :provider, :value => 'IPMI' %>
|
||
<% end %>
|
||
|
||
<% end %>
|
||
</div>
|
||
|
app/views/hosts/_sp_subnet.html.erb | ||
---|---|---|
<%= fields_for item do |f| -%>
|
||
<%= select_f f, :sp_subnet_id, domain_subnets, :id, :title,
|
||
{ :include_blank => domain_subnets.any? ? true : "No subnets"},
|
||
{ :disabled => domain_subnets.empty? ? true : false, :label => "BMC Subnet" }
|
||
%>
|
||
<% end -%>
|
app/views/hosts/_unattended.html.erb | ||
---|---|---|
</div>
|
||
|
||
<div class="tab-pane" id="network">
|
||
<div id="mac_address" <%= display? @host.compute_resource_id %> >
|
||
<%= text_f f, :mac, :label => "MAC", :help_inline => "MAC address for this host", :autocomplete => 'off' %>
|
||
</div>
|
||
<%= field_set_tag "Primary Interface", :id => "primary_interface" do -%>
|
||
<div id="mac_address" <%= display? @host.compute_resource_id %> >
|
||
<%= text_f f, :mac, :label => "MAC", :help_inline => "MAC address for this host", :autocomplete => 'off' %>
|
||
</div>
|
||
|
||
<%= select_f f, :domain_id, accessible_domains, :id, :to_label, {:include_blank => true},
|
||
{:onchange => 'domain_selected(this);', :'data-url' => domain_selected_hosts_path} %>
|
||
<% if @host.capabilities.include?(:build) %>
|
||
<%= select_f f, :domain_id, accessible_domains, :id, :to_label, {:include_blank => true},
|
||
{:onchange => 'domain_selected(this);', :'data-url' => domain_selected_hosts_path} %>
|
||
<% if @host.capabilities.include?(:build) %>
|
||
<div id='manage_network'>
|
||
<span id="subnet_select">
|
||
<%= render 'common/domain', :item => @host %>
|
||
</span>
|
||
<%= text_f f, :ip, :help_inline => "IP Address for this host, if DHCP Smart proxy is enabled, this should be auto suggested to you", :label => "IP" , :autocomplete => 'off'%>
|
||
<div id="bmc" <%= display? @host.compute_resource_id %> >
|
||
<%= text_f f, :sp_name, :help_inline => "BMC interface DNS name", :label => "BMC Name" , :autocomplete => 'off'%>
|
||
<%= text_f f, :sp_ip, :label => "BMC IP" , :autocomplete => 'off'%>
|
||
<%= text_f f, :sp_mac, :label => "BMC MAC", :autocomplete => 'off' %>
|
||
<span id="sp_subnet">
|
||
<%= render 'sp_subnet', :item => @host %>
|
||
</span>
|
||
</div>
|
||
<%# the following field is required to see child validations %>
|
||
<%= f.hidden_field :updated_at, :value => Time.now.to_i %>
|
||
<%= f.fields_for :interfaces do |interfaces| %>
|
||
<%= render 'interfaces', :f => interfaces %>
|
||
<% end %>
|
||
<%= new_child_fields_template(f, :interfaces, {:partial => "interfaces"})%>
|
||
<%= add_child_link "+ Add Interface", :interfaces, { :class => "info", :title => 'add new network interface' } %>
|
||
</div>
|
||
<% end %>
|
||
<% end %>
|
||
</div>
|
||
|
db/migrate/20120110113051_create_subnet_domain.rb | ||
---|---|---|
end
|
||
|
||
def self.down
|
||
add_column :subnets, :domain, :references
|
||
add_column :subnets, :domain_id, :integer
|
||
drop_table :subnet_domains
|
||
end
|
||
end
|
db/migrate/20120311081257_create_nics.rb | ||
---|---|---|
class CreateNics < ActiveRecord::Migration
|
||
def self.up
|
||
create_table :nics do |t|
|
||
t.string :mac
|
||
t.string :ip
|
||
t.string :type
|
||
t.string :name
|
||
t.references :host
|
||
t.references :subnet
|
||
t.references :domain
|
||
t.text :attrs
|
||
|
||
t.timestamps
|
||
end
|
||
|
||
add_index :nics, [:type], :name => 'index_by_type'
|
||
add_index :nics, [:host_id], :name => 'index_by_host'
|
||
add_index :nics, [:type, :id], :name => 'index_by_type_and_id'
|
||
|
||
Host.where(["sp_mac <> ? and sp_ip <> ?", "", ""]).each do |host|
|
||
begin
|
||
sp_ip = host.read_attribute(:sp_ip)
|
||
sp_mac = host.read_attribute(:sp_mac)
|
||
Nic::BMC.create! :host_id => host.id, :mac => sp_mac, :ip => sp_ip, :subnet_id => host.read_attribute(:sp_subnet_id),
|
||
:name => host.read_attribute(:sp_name), :priority => 1
|
||
say "created BMC interface for #{host}"
|
||
rescue => e
|
||
say "failed to import nics for #{host} : #{e}"
|
||
end
|
||
end
|
||
|
||
remove_columns :hosts, :sp_mac, :sp_ip, :sp_name, :sp_subnet_id
|
||
# TODO: fix this stuff in search
|
||
end
|
||
|
||
def self.down
|
||
add_column :hosts, :sp_mac, :string, :limit => 17, :default => ""
|
||
add_column :hosts, :sp_ip, :string, :limit => 15, :default => ""
|
||
add_column :hosts, :sp_name, :string, :default => ""
|
||
add_column :hosts, :sp_subnet_id, :integer
|
||
|
||
Nic::BMC.all.each do |bmc|
|
||
if bmc.host_id
|
||
bmc.host.update_attributes(:sp_mac => bmc.mac, :sp_ip => bmc.ip, :sp_name => bmc.name, :sp_subnet_id => bmc.subnet_id)
|
||
end
|
||
end
|
||
drop_table :nics
|
||
end
|
||
end
|
lib/foreman/controller/host_details.rb | ||
---|---|---|
end
|
||
|
||
def domain_selected
|
||
assign_parameter "domain", "common/"
|
||
respond_to do |format|
|
||
format.html {assign_parameter "domain", "common/"}
|
||
format.json do
|
||
@organization = params[:organization_id].blank? ? nil : Organization.find(params[:organization_id])
|
||
@location = params[:location_id].blank? ? nil : Location.find(params[:location_id])
|
||
Taxonomy.as_taxonomy @organization, @location do
|
||
if (domain = Domain.find(params[:domain_id]))
|
||
render :json => domain.subnets
|
||
else
|
||
not_found
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
def use_image_selected
|
lib/foreman/sti.rb | ||
---|---|---|
module Foreman
|
||
module STI
|
||
def self.included(base)
|
||
base.class_eval do
|
||
class << self
|
||
# ensures that the correct STI object is created when :type is passed.
|
||
def new_with_cast(*attributes, &block)
|
||
if (h = attributes.first).is_a?(Hash) && (type = h.delete(:type)) && type.length > 0
|
||
if (klass = type.constantize) != self
|
||
raise "Invalid type #{type}" unless klass <= self
|
||
return klass.new(*attributes, &block)
|
||
end
|
||
end
|
||
|
||
new_without_cast(*attributes, &block)
|
||
end
|
||
|
||
alias_method_chain :new, :cast
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
lib/net/validations.rb | ||
---|---|---|
network
|
||
end
|
||
|
||
# ensures that the ip address does not contain any leading spaces or invalid strings
|
||
def self.normalize_ip ip
|
||
return unless ip.present?
|
||
ip.split(".").map(&:to_i).join(".")
|
||
end
|
||
|
||
def self.normalize_mac mac
|
||
return unless mac.present?
|
||
m = mac.downcase
|
||
case m
|
||
when /[a-f0-9]{12}/
|
||
m.gsub(/(..)/) { |mh| mh + ":" }[/.{17}/]
|
||
when /([a-f0-9]{1,2}:){5}[a-f0-9]{1,2}/
|
||
m.split(":").map { |nibble| "%02x" % ("0x" + nibble) }.join(":")
|
||
end
|
||
end
|
||
end
|
||
end
|
public/javascripts/host_edit.js | ||
---|---|---|
var label = $(item).children(":selected").text();
|
||
if(compute=='') { //Bare Metal
|
||
$('#mac_address').show();
|
||
$('#bmc').show();
|
||
$("#model_name").show();
|
||
$('#compute_resource').empty();
|
||
$('#vm_details').empty();
|
||
... | ... | |
else
|
||
{
|
||
$('#mac_address').hide();
|
||
$('#bmc').hide();
|
||
$("#model_name").hide();
|
||
$("#compute_resource_tab").show();
|
||
$('#vm_details').empty();
|
||
... | ... | |
$('#image_selection').appendTo($('#image_provisioning'));
|
||
$('#params-tab').on('shown', function(){mark_params_override()});
|
||
}
|
||
|
||
$(document).on('change', '.interface_domain', function () {
|
||
interface_domain_selected(this);
|
||
});
|
||
|
||
$(document).on('change', '.interface_subnet', function () {
|
||
interface_subnet_selected(this);
|
||
});
|
||
|
||
$(document).on('change', '.interface_type', function () {
|
||
interface_type_selected(this);
|
||
});
|
||
|
||
function interface_domain_selected(element) {
|
||
var domain_id = element.value;
|
||
var subnet_options = $(element).parentsUntil('.fields').parent().find('[id$=_subnet_id]').empty();
|
||
var indicator = $(element).parent().find('.indicator')
|
||
|
||
subnet_options.attr('disabled', true);
|
||
if (domain_id == '') {
|
||
subnet_options.append($("<option />").val(null).text('No subnets'));
|
||
return false;
|
||
}
|
||
|
||
indicator.removeClass('hide');
|
||
|
||
var url = $(element).attr('data-url');
|
||
|
||
var org = $('#host_organization_id :selected').val();
|
||
var loc = $('#host_location_id :selected').val();
|
||
|
||
$.ajax({
|
||
data:{domain_id: domain_id, organization_id:org, location_id: loc},
|
||
type:'post',
|
||
url:url,
|
||
dataType:'json',
|
||
success:function (result) {
|
||
if (result.length > 1)
|
||
subnet_options.append($("<option />").val(null).text('Please select'));
|
||
|
||
$.each(result, function () {
|
||
subnet_options.append($("<option />").val(this.subnet.id).text(this.subnet.name + ' (' + this.subnet.to_label + ')'));
|
||
});
|
||
if (subnet_options.find('option').length > 0) {
|
||
subnet_options.attr('disabled', false);
|
||
subnet_options.change();
|
||
}
|
||
else {
|
||
subnet_options.append($("<option />").text('No subnets'));
|
||
subnet_options.attr('disabled', true);
|
||
}
|
||
indicator.addClass('hide');
|
||
}
|
||
});
|
||
}
|
||
|
||
function interface_subnet_selected(element) {
|
||
var subnet_id = $(element).val();
|
||
if (subnet_id == '') return;
|
||
var indicator = $(element).parent().find('.indicator')
|
||
var interface_ip = $(element).parentsUntil('.fields').parent().find('input[id$=_ip]')
|
||
|
||
interface_ip.attr('disabled', true);
|
||
indicator.removeClass('hide');
|
||
|
||
// We do not query the proxy if the ip field is filled in and contains an
|
||
// IP that is in the selected subnet
|
||
var drop_text = $(element).children(":selected").text();
|
||
// extracts network / cidr / ip
|
||
if (drop_text.length != 0 && drop_text.search(/^.+ \([0-9\.\/]+\)/) != -1) {
|
||
var details = drop_text.replace(/^[^(]+\(/, "").replace(")", "").split("/");
|
||
var network = details[0];
|
||
var cidr = details[1];
|
||
|
||
if (subnet_contains(network, cidr, interface_ip.val())) {
|
||
interface_ip.attr('disabled', false);
|
||
indicator.addClass('hide');
|
||
return;
|
||
}
|
||
}
|
||
var interface_mac = $(element).parentsUntil('.fields').parent().find('input[id$=_mac]')
|
||
var url = $(element).attr('data-url');
|
||
var org = $('#host_organization_id :selected').val();
|
||
var loc = $('#host_location_id :selected').val();
|
||
|
||
var data = {subnet_id: subnet_id, host_mac: interface_mac.val(), organization_id:org, location_id:loc }
|
||
$.ajax({
|
||
data: data,
|
||
type:'post',
|
||
url: url,
|
||
dataType:'json',
|
||
success:function (result) {
|
||
interface_ip.val(result['ip']);
|
||
},
|
||
complete:function () {
|
||
indicator.addClass('hide');
|
||
interface_ip.attr('disabled', false);
|
||
}
|
||
});
|
||
}
|
||
|
||
function interface_type_selected(element) {
|
||
|
||
var type = $(element).find('option:selected').text();
|
||
var bmc_fields = $(element).parentsUntil('.fields').parent().find('#bmc_fields')
|
||
if (type == 'BMC') {
|
||
bmc_fields.find("input:disabled").prop('disabled',false);
|
||
bmc_fields.removeClass("hide");
|
||
} else {
|
||
bmc_fields.find("input").prop('disabled',true);
|
||
bmc_fields.addClass("hide");
|
||
}
|
||
|
||
}
|
public/javascripts/lookup_keys.js | ||
---|---|---|
}
|
||
$(item).closest("form").trigger({type: 'nested:fieldAdded', field: field});
|
||
$('a[rel="popover"]').popover();
|
||
$('a[rel="twipsy"]').tooltip();
|
||
return new_id;
|
||
}
|
||
|
test/fixtures/hosts.yml | ||
---|---|---|
ptable: ubuntu
|
||
medium: ubuntu
|
||
puppet_proxy: puppetmaster
|
||
domain: useless
|
||
compute_resource: one
|
||
|
||
sol10host:
|
||
... | ... | |
operatingsystem: redhat
|
||
ptable: one
|
||
subnet: one
|
||
sp_subnet: one
|
||
sp_name: dhcp-bmc.mydomain.net
|
||
sp_ip: 2.3.4.50
|
||
sp_mac: da:bb:cc:dd:ee:aa
|
||
domain: mydomain
|
||
puppet_proxy: puppetmaster
|
||
managed: true
|
test/fixtures/nics.yml | ||
---|---|---|
nic:
|
||
mac: aabbCCddedee
|
test/fixtures/smart_proxies.yml | ||
---|---|---|
one:
|
||
name: DHCP Proxy
|
||
url: https://somewhere.net:8443
|
||
features: dhcp
|
||
|
||
two:
|
||
name: TFTP Proxy
|
||
... | ... | |
three:
|
||
name: DNS Proxy
|
||
url: http://else.where:4567
|
||
features: dns
|
||
|
||
puppetmaster:
|
||
name: Puppetmaster Proxy
|
test/functional/api/v1/subnets_controller_test.rb | ||
---|---|---|
assert_response :unprocessable_entity
|
||
end
|
||
|
||
def test_destroy_json
|
||
subnet = Subnet.first
|
||
subnet.hosts.clear
|
||
subnet.interfaces.clear
|
||
as_admin { delete :destroy, {:id => subnet.id} }
|
||
ActiveSupport::JSON.decode(@response.body)
|
||
assert_response :ok
|
||
assert !Subnet.exists?(:id => subnet.id)
|
||
end
|
||
end
|
test/functional/subnets_controller_test.rb | ||
---|---|---|
def test_destroy
|
||
subnet = Subnet.first
|
||
subnet.hosts.clear
|
||
subnet.sps.clear
|
||
subnet.interfaces.clear
|
||
delete :destroy, {:id => subnet}, set_session_user
|
||
assert_redirected_to subnets_url
|
||
assert !Subnet.exists?(subnet.id)
|
||
... | ... | |
def test_destroy_json
|
||
subnet = Subnet.first
|
||
subnet.hosts.clear
|
||
subnet.sps.clear
|
||
subnet.interfaces.clear
|
||
delete :destroy, {:format => "json", :id => subnet}, set_session_user
|
||
subnet = ActiveSupport::JSON.decode(@response.body)
|
||
assert_response :ok
|
test/test_helper.rb | ||
---|---|---|
Net::DHCP::SparcRecord.any_instance.stubs(:create).returns(true)
|
||
Net::DHCP::Record.any_instance.stubs(:conflicting?).returns(false)
|
||
ProxyAPI::Puppet.any_instance.stubs(:environments).returns(["production"])
|
||
ProxyAPI::DHCP.any_instance.stubs(:unused_ip).returns('127.0.0.1')
|
||
end
|
||
|
||
def disable_orchestration
|
test/unit/domain_test.rb | ||
---|---|---|
test "user with destroy permissions should be able to destroy" do
|
||
setup_user "destroy"
|
||
record = domains(:useless)
|
||
record.interfaces.clear
|
||
record.hosts.clear
|
||
assert record.destroy
|
||
assert record.frozen?
|
||
end
|
test/unit/host_test.rb | ||
---|---|---|
assert host.save!
|
||
end
|
||
|
||
|
||
test "should have only one bootable interface" do
|
||
h = hosts(:redhat)
|
||
assert_equal 0, h.interfaces.count
|
||
bootable = Nic::Bootable.create! :host => h, :name => "dummy-bootable", :ip => "2.3.4.102", :mac => "aa:bb:cd:cd:ee:ff",
|
||
:subnet => h.subnet, :type => 'Nic::Bootable', :domain => h.domain
|
||
assert_equal 1, h.interfaces.count
|
||
h.interfaces_attributes = [{:name => "dummy-bootable2", :ip => "2.3.4.103", :mac => "aa:bb:cd:cd:ee:ff",
|
||
:subnet_id => h.subnet_id, :type => 'Nic::Bootable', :domain_id => h.domain_id }]
|
||
assert !h.valid?
|
||
assert_equal "Only one bootable interface is allowed", h.errors['interfaces.type'][0]
|
||
assert_equal 1, h.interfaces.count
|
||
end
|
||
|
||
# Token tests
|
||
|
||
test "built should clean tokens" do
|
||
Setting[:token_duration] = 30
|
||
h = hosts(:one)
|
||
... | ... | |
h = hosts(:one)
|
||
assert_equal h.token, nil
|
||
end
|
||
|
||
end
|
test/unit/nic_test.rb | ||
---|---|---|
require 'test_helper'
|
||
|
||
class NicTest < ActiveSupport::TestCase
|
||
|
||
def setup
|
||
disable_orchestration
|
||
User.current = User.admin
|
||
end
|
||
|
||
def teardown
|
||
User.current = nil
|
||
end
|
||
|
||
test "should create simple interface" do
|
||
i = ''
|
||
assert_nothing_raised { i = Nic::Base.create! :mac => "cabbccddeeff", :host => hosts(:one) }
|
||
assert_equal "Nic::Base", i.class.to_s
|
Also available in: Unified diff
fixes #1814 - converts sp_* attributes into a BMC interface class
this patch also includes the following
and a bootable interface.
interface objects and on the primary interface information that still
reside in the hosts table.
this refactor also helps to simply refactoring the host object into
multiple objects.
this patch also fixes
fixes #1325 - BMC NIC should also create DNS entry
fixes #1813 - allow to support multiple NIC per host