staypuft 0.1.5 → 0.1.6
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.
- 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
|