staypuft 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/app/assets/javascripts/staypuft/staypuft.js +99 -1
- data/app/assets/stylesheets/staypuft/bootstrap_and_overrides.css.scss +48 -4
- data/app/assets/stylesheets/staypuft/staypuft.css.scss +7 -11
- data/app/controllers/staypuft/deployments_controller.rb +23 -20
- data/app/controllers/staypuft/steps_controller.rb +18 -24
- data/app/helpers/staypuft/application_helper.rb +16 -1
- data/app/helpers/staypuft/deployments_helper.rb +1 -1
- data/app/lib/actions/staypuft/host/wait_until_host_ready.rb +2 -8
- data/app/lib/staypuft/seeder.rb +702 -0
- data/app/models/staypuft/concerns/host_open_stack_affiliation.rb +29 -2
- data/app/models/staypuft/concerns/hostgroup_extensions.rb +28 -3
- data/app/models/staypuft/concerns/lookup_key_extensions.rb +72 -0
- data/app/models/staypuft/deployment/abstract_param_scope.rb +31 -0
- data/app/models/staypuft/deployment/attribute_param_storage.rb +41 -0
- data/app/models/staypuft/deployment/cinder_service.rb +87 -0
- data/app/models/staypuft/deployment/glance_service.rb +85 -0
- data/app/models/staypuft/deployment/ips.rb +26 -0
- data/app/models/staypuft/deployment/neutron_service.rb +165 -0
- data/app/models/staypuft/deployment/nova_service.rb +84 -0
- data/app/models/staypuft/deployment/passwords.rb +66 -0
- data/app/models/staypuft/deployment/vips.rb +36 -0
- data/app/models/staypuft/deployment.rb +179 -72
- data/app/models/staypuft/deployment_role_hostgroup.rb +1 -1
- data/app/models/staypuft/role.rb +8 -1
- data/app/models/staypuft/service/ui_params.rb +12 -1
- data/app/views/staypuft/deployments/_assigned_hosts_table.html.erb +60 -0
- data/app/views/staypuft/deployments/_deployed_hosts_table.html.erb +51 -0
- data/app/views/staypuft/deployments/_free_hosts_table.html.erb +47 -0
- data/app/views/staypuft/deployments/edit.html.erb +50 -0
- data/app/views/staypuft/deployments/show.html.erb +41 -79
- data/app/views/staypuft/deployments/summary.html.erb +4 -1
- data/app/views/staypuft/steps/_cinder.html.erb +17 -0
- data/app/views/staypuft/steps/_glance.html.erb +16 -0
- data/app/views/staypuft/steps/_neutron.html.erb +57 -0
- data/app/views/staypuft/steps/_nova.html.erb +34 -0
- data/app/views/staypuft/steps/deployment_settings.html.erb +41 -17
- data/app/views/staypuft/steps/services_configuration.html.erb +19 -32
- data/app/views/staypuft/steps/{services_selection.html.erb → services_overview.html.erb} +7 -3
- data/config/routes.rb +2 -0
- data/db/migrate/20140623142500_remove_amqp_provider_from_staypuft_deployment.rb +6 -0
- data/db/seeds.rb +1 -314
- data/lib/staypuft/engine.rb +1 -0
- data/lib/staypuft/version.rb +1 -1
- metadata +23 -3
@@ -3,16 +3,43 @@ module Staypuft
|
|
3
3
|
module HostOpenStackAffiliation
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
+
included do
|
7
|
+
scope(:in_deployment, lambda do |deployment|
|
8
|
+
joins(hostgroup: :deployment_role_hostgroup).
|
9
|
+
where(DeploymentRoleHostgroup.table_name => { deployment_id: deployment })
|
10
|
+
end)
|
11
|
+
|
12
|
+
scope(:in_roles, lambda do |*roles|
|
13
|
+
joins(hostgroup: :deployment_role_hostgroup).
|
14
|
+
where(DeploymentRoleHostgroup.table_name => { role_id: roles })
|
15
|
+
end)
|
16
|
+
|
17
|
+
scope :in_role, lambda { |role| in_roles(role) }
|
18
|
+
|
19
|
+
has_one :deployment, through: :hostgroup
|
20
|
+
end
|
21
|
+
|
22
|
+
|
6
23
|
def open_stack_deployed?
|
24
|
+
!deployment.nil? && !deployment.in_progress? &&
|
25
|
+
open_stack_environment_set? && open_stack_assigned?
|
26
|
+
end
|
27
|
+
|
28
|
+
def open_stack_environment_set?
|
7
29
|
open_stack_assigned? &&
|
8
|
-
|
9
|
-
|
30
|
+
respond_to?(:environment) &&
|
31
|
+
environment != Environment.get_discovery
|
10
32
|
end
|
11
33
|
|
12
34
|
def open_stack_assigned?
|
13
35
|
respond_to?(:hostgroup) &&
|
14
36
|
hostgroup.try(:parent).try(:parent) == Hostgroup.get_base_hostgroup
|
15
37
|
end
|
38
|
+
|
39
|
+
def open_stack_unassign
|
40
|
+
self.hostgroup = nil
|
41
|
+
save!
|
42
|
+
end
|
16
43
|
end
|
17
44
|
end
|
18
45
|
end
|
@@ -48,9 +48,34 @@ module Staypuft::Concerns::HostgroupExtensions
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
51
|
+
def free_hosts
|
52
|
+
Host::Base.where('hostgroup_id IS NULL')
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns all hosts associated with this hostgroup with the openstack
|
56
|
+
# deployment environment set. These can be filtered based by setting
|
57
|
+
# errors=true or errors=false to return only the hosts with no errors or
|
58
|
+
# with errors respectively.
|
59
|
+
def openstack_hosts(errors=nil)
|
60
|
+
oshosts = hosts.select { |h| h.open_stack_environment_set? }
|
61
|
+
|
62
|
+
unless errors.nil?
|
63
|
+
oshosts.select! { |h| (!errors ^ h.error?) }
|
64
|
+
end
|
65
|
+
oshosts
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns all hosts associated with this hostgroup with the openstack
|
69
|
+
# deployment environment set. These can be filtered based by setting
|
70
|
+
# errors=true or errors=false to return only the hosts with no errors or
|
71
|
+
# with errors respectively.
|
72
|
+
def openstack_hosts(errors=nil)
|
73
|
+
oshosts = hosts.select { |h| h.open_stack_environment_set? }
|
74
|
+
|
75
|
+
unless errors.nil?
|
76
|
+
oshosts.select! { |h| (!errors ^ h.error?) }
|
77
|
+
end
|
78
|
+
oshosts
|
54
79
|
end
|
55
80
|
|
56
81
|
module ClassMethods
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Staypuft::Concerns::LookupKeyExtensions
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
alias_method_chain :cast_validate_value, :erb
|
6
|
+
alias_method_chain :value_before_type_cast, :limpet
|
7
|
+
|
8
|
+
# apply only when this extension is included
|
9
|
+
::Staypuft::Concerns::LookupKeyExtensions.monkey_path_safe_render
|
10
|
+
end
|
11
|
+
|
12
|
+
LIMPET_FORMAT = '<%%={key_id:%s};'
|
13
|
+
LIMPET_FORMAT_REGEXP = /#{LIMPET_FORMAT % '(\d+)'}/
|
14
|
+
|
15
|
+
def cast_validate_value_with_erb(value)
|
16
|
+
if has_erb? value
|
17
|
+
if value =~ LIMPET_FORMAT_REGEXP
|
18
|
+
value.gsub(/#{LIMPET_FORMAT_REGEXP}/, LIMPET_FORMAT % id)
|
19
|
+
else
|
20
|
+
value.gsub(/<%=/, LIMPET_FORMAT % id)
|
21
|
+
end
|
22
|
+
else
|
23
|
+
cast_validate_value_without_erb value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def cast_validate_value_after_erb(value, type)
|
28
|
+
method = "cast_value_#{type}".to_sym
|
29
|
+
return value unless self.respond_to? method, true
|
30
|
+
self.send(method, value) rescue raise TypeError
|
31
|
+
end
|
32
|
+
|
33
|
+
def has_erb? value
|
34
|
+
value =~ /<%.*%>/
|
35
|
+
end
|
36
|
+
|
37
|
+
def value_before_type_cast_with_limpet(value)
|
38
|
+
value_before_type_cast_without_limpet(value).tap do |v|
|
39
|
+
v.gsub!(LIMPET_FORMAT_REGEXP, '<%=') if has_erb? v
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.monkey_path_safe_render
|
44
|
+
::SafeRender.class_eval do
|
45
|
+
def parse_string(string)
|
46
|
+
raise ::ForemanException.new(N_('SafeRender#parse_string was passed a %s instead of a string') % string.class) unless string.is_a? String
|
47
|
+
|
48
|
+
lookup_key_id = string[Staypuft::Concerns::LookupKeyExtensions::LIMPET_FORMAT_REGEXP, 1]
|
49
|
+
if lookup_key_id
|
50
|
+
lookup_key = LookupKey.find(lookup_key_id)
|
51
|
+
type = lookup_key.key_type
|
52
|
+
end
|
53
|
+
|
54
|
+
p string
|
55
|
+
value = if Setting[:safemode_render]
|
56
|
+
box = Safemode::Box.new self, @allowed_methods
|
57
|
+
box.eval(ERB.new(string, nil, '-').src, @allowed_vars)
|
58
|
+
else
|
59
|
+
@allowed_vars.each { |k, v| instance_variable_set "@#{k}", v }
|
60
|
+
ERB.new(string, nil, '-').result(binding)
|
61
|
+
end
|
62
|
+
|
63
|
+
if type
|
64
|
+
lookup_key.cast_validate_value_after_erb value, type
|
65
|
+
else
|
66
|
+
value
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Staypuft
|
2
|
+
class Deployment::AbstractParamScope
|
3
|
+
include ActiveModel::Validations
|
4
|
+
extend ActiveModel::Callbacks
|
5
|
+
extend Deployment::AttributeParamStorage
|
6
|
+
define_model_callbacks :save, :only => [:after]
|
7
|
+
|
8
|
+
def self.param_scope
|
9
|
+
raise NotImplementedError
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :deployment
|
13
|
+
|
14
|
+
def initialize(deployment)
|
15
|
+
@deployment = deployment
|
16
|
+
end
|
17
|
+
|
18
|
+
def hostgroup
|
19
|
+
deployment.hostgroup
|
20
|
+
end
|
21
|
+
|
22
|
+
# compatibility with validates_associated
|
23
|
+
def marked_for_destruction?
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
27
|
+
def attributes=(attr_list)
|
28
|
+
attr_list.each { |attr, value| send "#{attr}=", value } unless attr_list.nil?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Staypuft
|
2
|
+
module Deployment::AttributeParamStorage
|
3
|
+
def param_scope
|
4
|
+
raise NotImplementedError
|
5
|
+
end
|
6
|
+
|
7
|
+
def param_attr(*names)
|
8
|
+
names.each do |name|
|
9
|
+
ivar_name = :"@#{name}"
|
10
|
+
param_name = "ui::#{param_scope}::#{name}"
|
11
|
+
|
12
|
+
define_method name do
|
13
|
+
instance_variable_get(ivar_name) or
|
14
|
+
instance_variable_set(ivar_name,
|
15
|
+
hostgroup.group_parameters.find_by_name(param_name).try(:value))
|
16
|
+
end
|
17
|
+
|
18
|
+
define_method "#{name}=" do |value|
|
19
|
+
instance_variable_set(ivar_name, value)
|
20
|
+
end
|
21
|
+
|
22
|
+
after_save do
|
23
|
+
value = send(name)
|
24
|
+
# FIXME: not sure if hard-coding false is correct here, but without it, false was
|
25
|
+
# being set to 'nil', breaking boolean values (empty arrays may prove to be a similar problem)
|
26
|
+
if value.blank? && !(value == false)
|
27
|
+
hostgroup.
|
28
|
+
group_parameters.
|
29
|
+
find_by_name(param_name).try(:destroy)
|
30
|
+
else
|
31
|
+
param = hostgroup.
|
32
|
+
group_parameters.
|
33
|
+
find_or_initialize_by_name(param_name)
|
34
|
+
param.update_attributes!(value: value)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Staypuft
|
2
|
+
class Deployment::CinderService < Deployment::AbstractParamScope
|
3
|
+
def self.param_scope
|
4
|
+
'cinder'
|
5
|
+
end
|
6
|
+
|
7
|
+
param_attr :driver_backend, :nfs_uri, :nfs_mount_options
|
8
|
+
|
9
|
+
module DriverBackend
|
10
|
+
LVM = 'lvm'
|
11
|
+
NFS = 'nfs'
|
12
|
+
CEPH = 'ceph'
|
13
|
+
EQUALLOGIC = 'equallogic'
|
14
|
+
LABELS = { LVM => N_('LVM'),
|
15
|
+
NFS => N_('NFS'),
|
16
|
+
CEPH => N_('Ceph'),
|
17
|
+
EQUALLOGIC => N_('EqualLogic') }
|
18
|
+
TYPES = LABELS.keys
|
19
|
+
HUMAN = N_('Choose Driver Backend')
|
20
|
+
end
|
21
|
+
validates :driver_backend, presence: true, inclusion: { in: lambda {|c| c.backend_types_for_layout } }
|
22
|
+
|
23
|
+
module NfsUri
|
24
|
+
HUMAN = N_('NFS URI:')
|
25
|
+
HUMAN_AFTER = N_('("example.com/path/to/mount")')
|
26
|
+
end
|
27
|
+
validates :nfs_uri,
|
28
|
+
:presence => true,
|
29
|
+
:if => :nfs_backend?
|
30
|
+
# TODO: uri validation
|
31
|
+
|
32
|
+
# TODO: add ceph UI parameters
|
33
|
+
|
34
|
+
# TODO: add EqualLogic UI parameters
|
35
|
+
|
36
|
+
|
37
|
+
def set_defaults
|
38
|
+
self.driver_backend = DriverBackend::LVM
|
39
|
+
end
|
40
|
+
|
41
|
+
# cinder config always shows up
|
42
|
+
def active?
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
def lvm_backend?
|
47
|
+
!self.deployment.ha? && (self.driver_backend == DriverBackend::LVM)
|
48
|
+
end
|
49
|
+
|
50
|
+
def nfs_backend?
|
51
|
+
self.driver_backend == DriverBackend::NFS
|
52
|
+
end
|
53
|
+
|
54
|
+
def ceph_backend?
|
55
|
+
self.driver_backend == DriverBackend::CEPH
|
56
|
+
end
|
57
|
+
|
58
|
+
def equallogic_backend?
|
59
|
+
self.driver_backend == DriverBackend::EQUALLOGIC
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
# view should use this rather than DriverBackend::LABELS to hide LVM for HA.
|
64
|
+
# TODO: Add back CEPH and EQUALLOGIC as they're suppoirted
|
65
|
+
def backend_labels_for_layout
|
66
|
+
ret_list = DriverBackend::LABELS.clone
|
67
|
+
ret_list.delete(DriverBackend::LVM) if self.deployment.ha?
|
68
|
+
# TODO: remove this line when Ceph is supported
|
69
|
+
ret_list.delete(DriverBackend::CEPH)
|
70
|
+
# TODO: remove this line when EqualLogic is supported
|
71
|
+
ret_list.delete(DriverBackend::EQUALLOGIC)
|
72
|
+
|
73
|
+
ret_list
|
74
|
+
end
|
75
|
+
def backend_types_for_layout
|
76
|
+
ret_list = DriverBackend::TYPES.clone
|
77
|
+
ret_list.delete(DriverBackend::LVM) if self.deployment.ha?
|
78
|
+
# TODO: remove this line when Ceph is supported
|
79
|
+
ret_list.delete(DriverBackend::CEPH)
|
80
|
+
# TODO: remove this line when EqualLogic is supported
|
81
|
+
ret_list.delete(DriverBackend::EQUALLOGIC)
|
82
|
+
|
83
|
+
ret_list
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Staypuft
|
2
|
+
class Deployment::GlanceService < Deployment::AbstractParamScope
|
3
|
+
def self.param_scope
|
4
|
+
'glance'
|
5
|
+
end
|
6
|
+
|
7
|
+
param_attr :driver_backend, :nfs_network_path, :gluster_network_path,
|
8
|
+
:gluster_backup_volfile_servers
|
9
|
+
|
10
|
+
module DriverBackend
|
11
|
+
LOCAL = 'local'
|
12
|
+
NFS = 'nfs'
|
13
|
+
LABELS = { LOCAL => N_('Local File'),
|
14
|
+
NFS => N_('NFS') }
|
15
|
+
TYPES = LABELS.keys
|
16
|
+
HUMAN = N_('Choose Driver Backend')
|
17
|
+
end
|
18
|
+
|
19
|
+
validates :driver_backend, presence: true, inclusion: { in: lambda {|g| g.backend_types_for_layout } }
|
20
|
+
|
21
|
+
module NfsNetworkPath
|
22
|
+
HUMAN = N_('network path')
|
23
|
+
HUMAN_AFTER = '(server:localpath)'
|
24
|
+
end
|
25
|
+
|
26
|
+
validates :nfs_network_path,
|
27
|
+
:presence => true,
|
28
|
+
:if => :nfs_backend?
|
29
|
+
# TODO: network_path validation
|
30
|
+
|
31
|
+
def set_defaults
|
32
|
+
self.driver_backend = DriverBackend::LOCAL
|
33
|
+
end
|
34
|
+
|
35
|
+
# gluster config only shows up for HA
|
36
|
+
# glance UI is HA only until we add ceph (since there's only one option for non-HA)
|
37
|
+
def active?
|
38
|
+
deployment.ha?
|
39
|
+
end
|
40
|
+
|
41
|
+
def local_backend?
|
42
|
+
self.driver_backend == DriverBackend::LOCAL
|
43
|
+
end
|
44
|
+
|
45
|
+
def nfs_backend?
|
46
|
+
self.driver_backend == DriverBackend::NFS
|
47
|
+
end
|
48
|
+
|
49
|
+
def network_path
|
50
|
+
if self.nfs_backend?
|
51
|
+
self.nfs_network_path
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def pcmk_fs_device
|
56
|
+
network_path.nil? ? '' : network_path.split(':')[0]
|
57
|
+
end
|
58
|
+
|
59
|
+
def pcmk_fs_dir
|
60
|
+
network_path.nil? ? '' : network_path.split(':')[1]
|
61
|
+
end
|
62
|
+
|
63
|
+
def pcmk_fs_options
|
64
|
+
if self.nfs_backend?
|
65
|
+
"context=\"system_u:object_r:glance_var_lib_t:s0\")"
|
66
|
+
else
|
67
|
+
""
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# view should use this rather than DriverBackend::LABELS to hide LOCAL for HA.
|
72
|
+
def backend_labels_for_layout
|
73
|
+
ret_list = DriverBackend::LABELS.clone
|
74
|
+
ret_list.delete(DriverBackend::LOCAL) if self.deployment.ha?
|
75
|
+
ret_list
|
76
|
+
end
|
77
|
+
|
78
|
+
def backend_types_for_layout
|
79
|
+
ret_list = DriverBackend::TYPES.clone
|
80
|
+
ret_list.delete(DriverBackend::LOCAL) if self.deployment.ha?
|
81
|
+
ret_list
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Staypuft
|
2
|
+
class Deployment::IPS < Deployment::AbstractParamScope
|
3
|
+
|
4
|
+
def controllers
|
5
|
+
@controllers ||= Hostgroup.
|
6
|
+
includes(:deployment_role_hostgroup).
|
7
|
+
where(DeploymentRoleHostgroup.table_name => { deployment_id: deployment,
|
8
|
+
role_id: Staypuft::Role.controller }).
|
9
|
+
first.
|
10
|
+
hosts
|
11
|
+
end
|
12
|
+
|
13
|
+
def controller_ips
|
14
|
+
controllers.map &:ip
|
15
|
+
end
|
16
|
+
|
17
|
+
def controller_fqdns
|
18
|
+
controllers.map &:fqdn
|
19
|
+
end
|
20
|
+
|
21
|
+
def controller_ip
|
22
|
+
controllers.tap { |v| v.size == 1 or raise }.first.ip
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
module Staypuft
|
2
|
+
class Deployment::NeutronService < Deployment::AbstractParamScope
|
3
|
+
def self.param_scope
|
4
|
+
'neutron'
|
5
|
+
end
|
6
|
+
|
7
|
+
SEGMENTATION_LIST = ['vxlan', 'vlan', 'gre', 'flat']
|
8
|
+
|
9
|
+
param_attr :network_segmentation, :tenant_vlan_ranges, :networker_tenant_interface,
|
10
|
+
:use_external_interface, :external_interface_name, :compute_tenant_interface,
|
11
|
+
:use_vlan_for_external_network, :vlan_ranges_for_external_network
|
12
|
+
|
13
|
+
module NetworkSegmentation
|
14
|
+
VXLAN = 'vxlan'
|
15
|
+
GRE = 'gre'
|
16
|
+
VLAN = 'vlan'
|
17
|
+
FLAT = 'flat'
|
18
|
+
LABELS = { VXLAN => N_('VXLAN Segmentation'),
|
19
|
+
GRE => N_('GRE Segmentation'),
|
20
|
+
VLAN => N_('VLAN Segmentation'),
|
21
|
+
FLAT => N_('Flat') }
|
22
|
+
TYPES = LABELS.keys
|
23
|
+
HUMAN = N_('Tenant Network Type')
|
24
|
+
end
|
25
|
+
|
26
|
+
validates :network_segmentation, presence: true, inclusion: { in: NetworkSegmentation::TYPES }
|
27
|
+
|
28
|
+
module TenantVlanRanges
|
29
|
+
HUMAN = N_('Tenant (VM data) VLAN Ranges')
|
30
|
+
HUMAN_AFTER = '[1-4094] (i.e. 10:100)'
|
31
|
+
end
|
32
|
+
|
33
|
+
validates :tenant_vlan_ranges,
|
34
|
+
:presence => true,
|
35
|
+
:if => :vlan_segmentation?
|
36
|
+
# TODO: vlan range format validation
|
37
|
+
|
38
|
+
module NetworkerTenantInterface
|
39
|
+
HUMAN = N_('Which interface to use for tenant networks:')
|
40
|
+
HUMAN_AFTER = N_('(i.e. eth0, em1, etc.)')
|
41
|
+
end
|
42
|
+
|
43
|
+
validates :networker_tenant_interface,
|
44
|
+
:presence => true
|
45
|
+
# TODO: interface name format validation
|
46
|
+
|
47
|
+
module UseExternalInterface
|
48
|
+
HUMAN = N_('Configure external interface on network node')
|
49
|
+
end
|
50
|
+
|
51
|
+
validates :use_external_interface, inclusion: { in: [true, false, 'true', 'false'] }
|
52
|
+
|
53
|
+
module ExternalInterfaceName
|
54
|
+
HUMAN = N_('External interface connected to')
|
55
|
+
HUMAN_AFTER = N_('(interface) (i.e. eth1)')
|
56
|
+
end
|
57
|
+
|
58
|
+
validates :external_interface_name,
|
59
|
+
:presence => true,
|
60
|
+
:if => :use_external_interface?
|
61
|
+
# TODO: interface name format validation
|
62
|
+
|
63
|
+
module UseVlanForExternalNetwork
|
64
|
+
HUMAN = N_('Configure VLAN for external network')
|
65
|
+
end
|
66
|
+
|
67
|
+
validates :use_vlan_for_external_network, inclusion: { in: [true, false, 'true', 'false'] }
|
68
|
+
|
69
|
+
module VlanRangesForExternalNetwork
|
70
|
+
HUMAN = N_('VLAN Range for external network')
|
71
|
+
HUMAN_AFTER = N_('i.e. physnet1:1000:2999')
|
72
|
+
end
|
73
|
+
|
74
|
+
validates :vlan_ranges_for_external_network,
|
75
|
+
:presence => true,
|
76
|
+
:if => :external_network_vlan?
|
77
|
+
# TODO: vlan rangesformat validation
|
78
|
+
|
79
|
+
module ComputeTenantInterface
|
80
|
+
HUMAN = N_('Which interface to use for tenant networks:')
|
81
|
+
HUMAN_AFTER = N_('(i.e. eth0, em1, etc.)')
|
82
|
+
end
|
83
|
+
|
84
|
+
validates :compute_tenant_interface,
|
85
|
+
:presence => true
|
86
|
+
# TODO: interface name format validation
|
87
|
+
|
88
|
+
def set_defaults
|
89
|
+
self.network_segmentation = NetworkSegmentation::VXLAN
|
90
|
+
self.use_external_interface = 'false'
|
91
|
+
end
|
92
|
+
|
93
|
+
def active?
|
94
|
+
deployment.networking == Deployment::Networking::NEUTRON
|
95
|
+
end
|
96
|
+
|
97
|
+
# TODO: make this less clumsy w/ consistent handling of true/false values
|
98
|
+
def use_external_interface?
|
99
|
+
(self.use_external_interface == true) || (self.use_external_interface == 'true')
|
100
|
+
end
|
101
|
+
|
102
|
+
# TODO: make this less clumsy w/ consistent handling of true/false values
|
103
|
+
def use_vlan_for_external_network?
|
104
|
+
(self.use_vlan_for_external_network == true) || (self.use_vlan_for_external_network == 'true')
|
105
|
+
end
|
106
|
+
|
107
|
+
# return list of supported segmentation options with selected option at the
|
108
|
+
# beginning of the list
|
109
|
+
def network_segmentation_list
|
110
|
+
[self.network_segmentation, *(SEGMENTATION_LIST - [self.network_segmentation])]
|
111
|
+
end
|
112
|
+
|
113
|
+
def controller_ovs_bridge_mappings
|
114
|
+
if self.vlan_segmentation?
|
115
|
+
["physnet-tenants:br-#{self.networker_tenant_interface}",
|
116
|
+
('physnet-external:br-ex' if self.use_external_interface?)].compact
|
117
|
+
else
|
118
|
+
[]
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def controller_ovs_bridge_uplinks
|
123
|
+
if self.vlan_segmentation?
|
124
|
+
["br-#{self.networker_tenant_interface}:#{self.networker_tenant_interface}",
|
125
|
+
("br-ex:#{self.external_interface_name}" if self.use_external_interface?)]
|
126
|
+
else
|
127
|
+
[]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def compute_ovs_bridge_mappings
|
132
|
+
if self.vlan_segmentation?
|
133
|
+
["physnet-tenants:br-#{self.compute_tenant_interface}"]
|
134
|
+
else
|
135
|
+
[]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def compute_ovs_bridge_uplinks
|
140
|
+
if self.vlan_segmentation?
|
141
|
+
["br-#{self.compute_tenant_interface}:#{self.compute_tenant_interface}"]
|
142
|
+
else
|
143
|
+
[]
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# FIXME: mapping is off here -- both external and tenant vlan ranges map to the same back end
|
148
|
+
# params: fix this with morazi in the AM
|
149
|
+
def ml2_network_vlan_ranges
|
150
|
+
if self.external_network_vlan?
|
151
|
+
[self.vlan_ranges_for_external_network]
|
152
|
+
else
|
153
|
+
[]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
def vlan_segmentation?
|
157
|
+
self.network_segmentation == NetworkSegmentation::VLAN
|
158
|
+
end
|
159
|
+
|
160
|
+
def external_network_vlan?
|
161
|
+
self.use_external_interface? && self.use_vlan_for_external_network?
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Staypuft
|
2
|
+
class Deployment::NovaService < Deployment::AbstractParamScope
|
3
|
+
def self.param_scope
|
4
|
+
'nova'
|
5
|
+
end
|
6
|
+
|
7
|
+
param_attr :network_manager, :vlan_range, :external_interface_name, :public_floating_range,
|
8
|
+
:compute_tenant_interface, :private_fixed_range
|
9
|
+
|
10
|
+
module NetworkManager
|
11
|
+
FLAT_DHCP = 'FlatDHCPManager'
|
12
|
+
VLAN = 'VlanManager'
|
13
|
+
LABELS = { FLAT_DHCP => N_('Flat with DHCP'),
|
14
|
+
VLAN => N_('VLAN') }
|
15
|
+
TYPES = LABELS.keys
|
16
|
+
HUMAN = N_('Tenant Network Type')
|
17
|
+
end
|
18
|
+
|
19
|
+
validates :network_manager, presence: true, inclusion: { in: NetworkManager::TYPES }
|
20
|
+
|
21
|
+
module VlanRange
|
22
|
+
HUMAN = N_('VLAN Range')
|
23
|
+
HUMAN_AFTER = '[1-4094] (i.e. 10:100)'
|
24
|
+
end
|
25
|
+
|
26
|
+
validates :vlan_range,
|
27
|
+
:presence => true,
|
28
|
+
:if => :vlan_manager?
|
29
|
+
# TODO: vlan range format validation
|
30
|
+
# TODO: determine whether this is a true range or a single value
|
31
|
+
|
32
|
+
module ExternalInterfaceName
|
33
|
+
HUMAN = N_('Which interface to use for external networks:')
|
34
|
+
HUMAN_AFTER = N_('(interface) (i.e. eth1)')
|
35
|
+
end
|
36
|
+
|
37
|
+
validates :external_interface_name, presence: true
|
38
|
+
# TODO: interface name format validation
|
39
|
+
|
40
|
+
module PublicFloatingRange
|
41
|
+
HUMAN = N_('Floating IP range for external network:')
|
42
|
+
HUMAN_AFTER = N_('("10.0.0.0/24", for example)')
|
43
|
+
end
|
44
|
+
|
45
|
+
validates :public_floating_range, presence: true
|
46
|
+
# TODO: interface format validation
|
47
|
+
|
48
|
+
module ComputeTenantInterface
|
49
|
+
HUMAN = N_('Which interface to use for tenant networks:')
|
50
|
+
HUMAN_AFTER = N_('(i.e. eth0, em1, etc.)')
|
51
|
+
end
|
52
|
+
|
53
|
+
validates :compute_tenant_interface,
|
54
|
+
:presence => true
|
55
|
+
# TODO: interface name format validation
|
56
|
+
|
57
|
+
module PrivateFixedRange
|
58
|
+
HUMAN = N_('Private IP range for tenant networks:')
|
59
|
+
HUMAN_AFTER = N_('("10.0.0.0/24", for example)')
|
60
|
+
end
|
61
|
+
|
62
|
+
validates :private_fixed_range, presence: true
|
63
|
+
# TODO: interface format validation
|
64
|
+
|
65
|
+
def set_defaults
|
66
|
+
self.network_manager = NetworkManager::FLAT_DHCP
|
67
|
+
end
|
68
|
+
|
69
|
+
def active?
|
70
|
+
deployment.networking == Deployment::Networking::NOVA
|
71
|
+
end
|
72
|
+
|
73
|
+
def vlan_manager?
|
74
|
+
self.network_manager == NetworkManager::VLAN
|
75
|
+
end
|
76
|
+
|
77
|
+
def network_overrides
|
78
|
+
{ 'force_dhcp_release' => false }.tap do |h|
|
79
|
+
h.update 'vlan_start' => self.vlan_range.split(':')[0] if self.vlan_manager?
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|