staypuft 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +8 -8
  2. data/app/assets/javascripts/staypuft/staypuft.js +99 -1
  3. data/app/assets/stylesheets/staypuft/bootstrap_and_overrides.css.scss +48 -4
  4. data/app/assets/stylesheets/staypuft/staypuft.css.scss +7 -11
  5. data/app/controllers/staypuft/deployments_controller.rb +23 -20
  6. data/app/controllers/staypuft/steps_controller.rb +18 -24
  7. data/app/helpers/staypuft/application_helper.rb +16 -1
  8. data/app/helpers/staypuft/deployments_helper.rb +1 -1
  9. data/app/lib/actions/staypuft/host/wait_until_host_ready.rb +2 -8
  10. data/app/lib/staypuft/seeder.rb +702 -0
  11. data/app/models/staypuft/concerns/host_open_stack_affiliation.rb +29 -2
  12. data/app/models/staypuft/concerns/hostgroup_extensions.rb +28 -3
  13. data/app/models/staypuft/concerns/lookup_key_extensions.rb +72 -0
  14. data/app/models/staypuft/deployment/abstract_param_scope.rb +31 -0
  15. data/app/models/staypuft/deployment/attribute_param_storage.rb +41 -0
  16. data/app/models/staypuft/deployment/cinder_service.rb +87 -0
  17. data/app/models/staypuft/deployment/glance_service.rb +85 -0
  18. data/app/models/staypuft/deployment/ips.rb +26 -0
  19. data/app/models/staypuft/deployment/neutron_service.rb +165 -0
  20. data/app/models/staypuft/deployment/nova_service.rb +84 -0
  21. data/app/models/staypuft/deployment/passwords.rb +66 -0
  22. data/app/models/staypuft/deployment/vips.rb +36 -0
  23. data/app/models/staypuft/deployment.rb +179 -72
  24. data/app/models/staypuft/deployment_role_hostgroup.rb +1 -1
  25. data/app/models/staypuft/role.rb +8 -1
  26. data/app/models/staypuft/service/ui_params.rb +12 -1
  27. data/app/views/staypuft/deployments/_assigned_hosts_table.html.erb +60 -0
  28. data/app/views/staypuft/deployments/_deployed_hosts_table.html.erb +51 -0
  29. data/app/views/staypuft/deployments/_free_hosts_table.html.erb +47 -0
  30. data/app/views/staypuft/deployments/edit.html.erb +50 -0
  31. data/app/views/staypuft/deployments/show.html.erb +41 -79
  32. data/app/views/staypuft/deployments/summary.html.erb +4 -1
  33. data/app/views/staypuft/steps/_cinder.html.erb +17 -0
  34. data/app/views/staypuft/steps/_glance.html.erb +16 -0
  35. data/app/views/staypuft/steps/_neutron.html.erb +57 -0
  36. data/app/views/staypuft/steps/_nova.html.erb +34 -0
  37. data/app/views/staypuft/steps/deployment_settings.html.erb +41 -17
  38. data/app/views/staypuft/steps/services_configuration.html.erb +19 -32
  39. data/app/views/staypuft/steps/{services_selection.html.erb → services_overview.html.erb} +7 -3
  40. data/config/routes.rb +2 -0
  41. data/db/migrate/20140623142500_remove_amqp_provider_from_staypuft_deployment.rb +6 -0
  42. data/db/seeds.rb +1 -314
  43. data/lib/staypuft/engine.rb +1 -0
  44. data/lib/staypuft/version.rb +1 -1
  45. 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
- respond_to?(:environment) &&
9
- environment != Environment.get_discovery
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 own_and_free_hosts
52
- # TODO update to Discovered only?
53
- Host::Base.where('hostgroup_id = ? OR hostgroup_id IS NULL', id)
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