staypuft 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/staypuft/nics_assignment.js +32 -0
- data/app/assets/javascripts/staypuft/staypuft.js +38 -0
- data/app/assets/javascripts/staypuft/subnets_assignment.js +40 -0
- data/app/assets/stylesheets/staypuft/bootstrap_and_overrides.css.scss +5 -1
- data/app/assets/stylesheets/staypuft/staypuft.css.scss +102 -0
- data/app/controllers/staypuft/deployments_controller.rb +5 -0
- data/app/controllers/staypuft/interface_assignments_controller.rb +76 -0
- data/app/controllers/staypuft/steps_controller.rb +15 -1
- data/app/controllers/staypuft/subnet_typings_controller.rb +42 -0
- data/app/helpers/staypuft/deployments_helper.rb +18 -3
- data/app/lib/actions/staypuft/hostgroup/deploy.rb +38 -1
- data/app/lib/staypuft/network_query.rb +35 -0
- data/app/lib/staypuft/seeder.rb +113 -39
- data/app/models/staypuft/concerns/host_interface_management.rb +28 -0
- data/app/models/staypuft/deployment.rb +35 -3
- data/app/models/staypuft/interface_assigner.rb +137 -0
- data/app/models/staypuft/layout.rb +3 -0
- data/app/models/staypuft/layout_subnet_type.rb +12 -0
- data/app/models/staypuft/role.rb +15 -0
- data/app/models/staypuft/subnet_type.rb +27 -0
- data/app/models/staypuft/subnet_typing.rb +11 -0
- data/app/views/staypuft/deployments/_assigned_hosts.html.erb +5 -2
- data/app/views/staypuft/deployments/_assigned_hosts_table.html.erb +13 -46
- data/app/views/staypuft/deployments/_deployed_hosts_table.html.erb +12 -33
- data/app/views/staypuft/deployments/_deployment_overview.html.erb +12 -9
- data/app/views/staypuft/deployments/_deployment_summary.html.erb +18 -0
- data/app/views/staypuft/deployments/_empty_hosts.html.erb +8 -0
- data/app/views/staypuft/deployments/_free_hosts.html.erb +1 -1
- data/app/views/staypuft/deployments/_free_hosts_table.html.erb +11 -34
- data/app/views/staypuft/deployments/_host_head_row.html.erb +11 -0
- data/app/views/staypuft/deployments/_host_row.html.erb +30 -0
- data/app/views/staypuft/deployments/_hosts_header.html.erb +7 -0
- data/app/views/staypuft/deployments/index.html.erb +1 -1
- data/app/views/staypuft/deployments/show.html.erb +2 -2
- data/app/views/staypuft/interface_assignments/create.js.erb +12 -0
- data/app/views/staypuft/interface_assignments/destroy.js.erb +12 -0
- data/app/views/staypuft/interface_assignments/index.html.erb +38 -0
- data/app/views/staypuft/interfaces/_drop_zone.html.erb +30 -0
- data/app/views/staypuft/steps/network_configuration.html.erb +52 -0
- data/app/views/staypuft/steps/services_configuration.html.erb +45 -39
- data/app/views/staypuft/steps/services_overview.html.erb +1 -1
- data/app/views/staypuft/subnet_types/_subnet_type_pull.html.erb +9 -0
- data/app/views/staypuft/subnet_typings/create.js.erb +12 -0
- data/app/views/staypuft/subnet_typings/destroy.js.erb +12 -0
- data/app/views/staypuft/subnet_typings/update.js.erb +14 -0
- data/app/views/staypuft/subnets/_drop_zone.html.erb +16 -0
- data/app/views/staypuft/subnets/_subnet_pull.html.erb +9 -0
- data/config/routes.rb +3 -0
- data/db/migrate/20140701074900_create_subnet_type.rb +9 -0
- data/db/migrate/20140701075033_create_layout_subnet.rb +10 -0
- data/db/migrate/20140701090256_create_staypuft_subnet_typings.rb +14 -0
- data/db/migrate/20140825164900_add_orchestration_to_staypuft_role.rb +5 -0
- data/db/migrate/20140831234000_add_required_to_subnet_types.rb +5 -0
- data/db/seeds.rb +1 -1
- data/lib/staypuft/engine.rb +11 -8
- data/lib/staypuft/version.rb +1 -1
- metadata +135 -91
data/app/lib/staypuft/seeder.rb
CHANGED
@@ -103,7 +103,9 @@ module Staypuft
|
|
103
103
|
:horizon_ha => { :name => 'Horizon (HA)', :class => ['quickstack::pacemaker::horizon'] },
|
104
104
|
:galera_ha => { :name => 'Galera (HA)', :class => ['quickstack::pacemaker::galera'] },
|
105
105
|
:mysql_ha => { :name => 'Mysql (HA)', :class => ['quickstack::pacemaker::mysql'] },
|
106
|
-
:neutron_ha => { :name => 'Neutron (HA)', :class => ['quickstack::pacemaker::neutron'] }
|
106
|
+
:neutron_ha => { :name => 'Neutron (HA)', :class => ['quickstack::pacemaker::neutron'] },
|
107
|
+
:generic_rhel_7 => { :name => 'Generic RHEL 7', :class => ['quickstack::openstack_common'] },
|
108
|
+
:ceph_osd => { :name => 'Ceph Storage (OSD) (node)', :class => ['quickstack::openstack_common'] },
|
107
109
|
}
|
108
110
|
|
109
111
|
# The list of roles is still from astapor
|
@@ -112,44 +114,94 @@ module Staypuft
|
|
112
114
|
# until we get the real list of roles per layout
|
113
115
|
# layout refs below specify layout keys from layouts hash
|
114
116
|
ROLES = [
|
115
|
-
{ :name
|
116
|
-
:class
|
117
|
-
:layouts
|
118
|
-
:services
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
:
|
123
|
-
:
|
124
|
-
|
125
|
-
:
|
126
|
-
|
127
|
-
:
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
:
|
132
|
-
|
133
|
-
|
134
|
-
:
|
135
|
-
:
|
136
|
-
:
|
137
|
-
{ :name
|
138
|
-
:class
|
139
|
-
:layouts
|
140
|
-
:services
|
141
|
-
|
142
|
-
|
143
|
-
:
|
144
|
-
:
|
145
|
-
|
146
|
-
:
|
147
|
-
|
148
|
-
:
|
149
|
-
|
150
|
-
|
117
|
+
{ :name => 'Controller (Nova)',
|
118
|
+
:class => 'quickstack::nova_network::controller',
|
119
|
+
:layouts => [[:non_ha_nova, 1]],
|
120
|
+
:services => [:non_ha_amqp, :mysql, :non_ha_keystone, :nova_controller, :non_ha_glance,
|
121
|
+
:cinder_controller, :heat, :ceilometer],
|
122
|
+
:orchestration => 'concurrent' },
|
123
|
+
{ :name => 'Compute (Nova)',
|
124
|
+
:class => [],
|
125
|
+
:layouts => [[:ha_nova, 10], [:non_ha_nova, 10]],
|
126
|
+
:services => [:nova_compute],
|
127
|
+
:orchestration => 'leader' },
|
128
|
+
{ :name => 'Controller (Neutron)',
|
129
|
+
:class => 'quickstack::neutron::controller',
|
130
|
+
:layouts => [[:non_ha_neutron, 1]],
|
131
|
+
:services => [:non_ha_amqp, :mysql, :non_ha_keystone, :neutron_controller, :non_ha_glance,
|
132
|
+
:cinder_controller, :heat, :ceilometer],
|
133
|
+
:orchestration => 'concurrent' },
|
134
|
+
{ :name => 'Compute (Neutron)',
|
135
|
+
:class => [],
|
136
|
+
:layouts => [[:ha_neutron, 10], [:non_ha_neutron, 10]],
|
137
|
+
:services => [:neutron_compute],
|
138
|
+
:orchestration => 'concurrent' },
|
139
|
+
{ :name => 'Neutron Networker',
|
140
|
+
:class => [],
|
141
|
+
:layouts => [[:non_ha_neutron, 3]],
|
142
|
+
:services => [:neutron_networker],
|
143
|
+
:orchestration => 'concurrent' },
|
144
|
+
{ :name => 'Cinder Block Storage',
|
145
|
+
:class => [],
|
146
|
+
:layouts => [],
|
147
|
+
:services => [:cinder_node],
|
148
|
+
:orchestration => 'concurrent' },
|
149
|
+
{ :name => 'Swift Storage Node',
|
150
|
+
:class => [],
|
151
|
+
:layouts => [],
|
152
|
+
:services => [:swift],
|
153
|
+
:orchestration => 'concurrent' },
|
154
|
+
{ :name => 'HA Controller',
|
155
|
+
:class => [],
|
156
|
+
:layouts => [[:ha_nova, 1], [:ha_neutron, 1]],
|
157
|
+
:services => [:ha_controller, :keystone_ha, :load_balancer_ha, :memcached_ha, :qpid_ha,
|
158
|
+
:glance_ha, :nova_ha, :heat_ha, :cinder_ha, :swift_ha, :horizon_ha, :mysql_ha,
|
159
|
+
:neutron_ha, :galera_ha],
|
160
|
+
:orchestration => 'concurrent' },
|
161
|
+
{ :name => 'Generic RHEL 7',
|
162
|
+
:class => '',
|
163
|
+
:layouts => [[:non_ha_nova, 20],[:non_ha_neutron, 20], [:ha_nova, 20], [:ha_neutron, 20]],
|
164
|
+
:services => [:generic_rhel_7],
|
165
|
+
:orchestration => 'concurrent' },
|
166
|
+
{ :name => 'Ceph Storage Node (OSD)',
|
167
|
+
:class => '',
|
168
|
+
:layouts => [[:non_ha_nova, 20], [:non_ha_neutron, 20], [:ha_nova, 20], [:ha_neutron, 20]],
|
169
|
+
:services => [:ceph_osd],
|
170
|
+
:orchestration => 'concurrent' },
|
171
|
+
]
|
151
172
|
|
152
173
|
CONTROLLER_ROLES = ROLES.select { |h| h.fetch(:name) =~ /Controller/ }
|
174
|
+
CEPH_ROLES = ROLES.select {|h| h.fetch(:name) =~ /Ceph/ }
|
175
|
+
|
176
|
+
ALL_LAYOUTS = LAYOUTS.keys
|
177
|
+
SUBNET_TYPES = { :pxe => { :name => Staypuft::SubnetType::PXE,
|
178
|
+
:required => true,
|
179
|
+
:layouts => ALL_LAYOUTS},
|
180
|
+
:management => { :name => Staypuft::SubnetType::MANAGEMENT,
|
181
|
+
:required => true,
|
182
|
+
:layouts => ALL_LAYOUTS},
|
183
|
+
:external => { :name => Staypuft::SubnetType::EXTERNAL,
|
184
|
+
:required => true,
|
185
|
+
:layouts => ALL_LAYOUTS},
|
186
|
+
:cluster_mgmt => { :name => Staypuft::SubnetType::CLUSTER_MGMT,
|
187
|
+
:required => true,
|
188
|
+
:layouts => ALL_LAYOUTS},
|
189
|
+
:admin_api => { :name => Staypuft::SubnetType::ADMIN_API,
|
190
|
+
:required => true,
|
191
|
+
:layouts => ALL_LAYOUTS},
|
192
|
+
:public_api => { :name => Staypuft::SubnetType::PUBLIC_API,
|
193
|
+
:required => true,
|
194
|
+
:layouts => ALL_LAYOUTS},
|
195
|
+
:tenant => { :name => Staypuft::SubnetType::TENANT,
|
196
|
+
:required => true,
|
197
|
+
:layouts => ALL_LAYOUTS},
|
198
|
+
:storage => { :name => Staypuft::SubnetType::STORAGE,
|
199
|
+
:required => false,
|
200
|
+
:layouts => ALL_LAYOUTS},
|
201
|
+
:storage_cluster => { :name => Staypuft::SubnetType::STORAGE_CLUSTERING,
|
202
|
+
:required => false,
|
203
|
+
:layouts => ALL_LAYOUTS}
|
204
|
+
}
|
153
205
|
|
154
206
|
def get_host_format(param_name)
|
155
207
|
{ :string => '<%%= d = @host.deployment; d.ha? ? d.vips.get(:%s) : d.ips.controller_ip %%>' % param_name }
|
@@ -201,7 +253,7 @@ module Staypuft
|
|
201
253
|
pcmk_fs_manage = { :string => '<%= @host.deployment.glance.pcmk_fs_manage %>' }
|
202
254
|
pcmk_fs_options = { :string => '<%= @host.deployment.glance.pcmk_fs_options %>' }
|
203
255
|
glance_rbd_store_user = 'images'
|
204
|
-
glance_rbd_store_pool = 'images'
|
256
|
+
glance_rbd_store_pool = 'images'
|
205
257
|
|
206
258
|
# Cinder
|
207
259
|
volume = true
|
@@ -662,13 +714,15 @@ module Staypuft
|
|
662
714
|
|
663
715
|
def seed_roles
|
664
716
|
ROLES.each do |role_hash|
|
665
|
-
role = Staypuft::Role.where(:name => role_hash[:name]).
|
717
|
+
role = Staypuft::Role.where(:name => role_hash[:name]).first_or_initialize
|
666
718
|
|
667
719
|
puppet_classes = collect_puppet_classes(Array(role_hash[:class]))
|
668
720
|
puppet_classes.each { |pc| apply_astapor_defaults pc }
|
669
721
|
role.puppetclasses = puppet_classes
|
670
722
|
|
671
723
|
role.description = role_hash[:description]
|
724
|
+
role.orchestration = role_hash[:orchestration]
|
725
|
+
role.save!
|
672
726
|
old_role_services_arr = role.role_services.to_a
|
673
727
|
role_hash[:services].each do |key|
|
674
728
|
role_service = role.role_services.where(:service_id => SERVICES[key][:obj].id).first_or_create!
|
@@ -719,11 +773,31 @@ module Staypuft
|
|
719
773
|
end
|
720
774
|
end
|
721
775
|
|
776
|
+
def seed_subnet_types
|
777
|
+
# default subnet types
|
778
|
+
SUBNET_TYPES.each do |key, subnet_type_hash|
|
779
|
+
subnet_type = Staypuft::SubnetType.where(:name => subnet_type_hash[:name]).first_or_initialize
|
780
|
+
subnet_type.is_required = subnet_type_hash[:required]
|
781
|
+
subnet_type.save!
|
782
|
+
old_layout_subnet_types_arr = subnet_type.layout_subnet_types.to_a
|
783
|
+
subnet_type_hash[:layouts].each do |layout|
|
784
|
+
layout_subnet_type = subnet_type.layout_subnet_types.where(:layout_id => LAYOUTS[layout][:obj].id).first_or_create!
|
785
|
+
old_layout_subnet_types_arr.delete(layout_subnet_type)
|
786
|
+
end
|
787
|
+
# delete any prior mappings that remain
|
788
|
+
old_layout_subnet_types_arr.each do |layout_subnet_type|
|
789
|
+
Rails.logger.warn "destroying old layout_subnet_type for #{layout_subnet_type.layout.name}, #{subnet_type.name}: This should not happen on a clean install"
|
790
|
+
subnet_type.layouts.destroy(layout_subnet_type.layout)
|
791
|
+
end
|
792
|
+
end
|
793
|
+
end
|
794
|
+
|
722
795
|
def seed
|
723
796
|
seed_layouts
|
724
797
|
seed_services
|
725
798
|
seed_roles
|
726
799
|
seed_functional_dependencies
|
800
|
+
seed_subnet_types
|
727
801
|
end
|
728
802
|
|
729
803
|
def collect_puppet_classes(puppet_class_names)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Staypuft
|
2
|
+
module Concerns
|
3
|
+
module HostInterfaceManagement
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
|
8
|
+
end
|
9
|
+
|
10
|
+
def clean_vlan_interfaces
|
11
|
+
self.interfaces.virtual.map(&:destroy)
|
12
|
+
end
|
13
|
+
|
14
|
+
def interfaces_identifiers
|
15
|
+
interfaces = [ self.primary_interface ]
|
16
|
+
interfaces += self.respond_to?(:interfaces) ? self.interfaces.where("type <> 'Nic::BMC'").physical.map(&:identifier) : []
|
17
|
+
interfaces
|
18
|
+
end
|
19
|
+
|
20
|
+
def make_all_interfaces_managed
|
21
|
+
self.interfaces.each do |interface|
|
22
|
+
interface.managed = true
|
23
|
+
interface.save!
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -7,12 +7,13 @@ module Staypuft
|
|
7
7
|
STEP_CONFIGURATION = :configuration
|
8
8
|
STEP_COMPLETE = :complete
|
9
9
|
STEP_OVERVIEW = :overview
|
10
|
+
STEP_NETWORKING = :networking
|
10
11
|
|
11
12
|
NEW_NAME_PREFIX = 'uninitialized_'
|
12
13
|
|
13
14
|
# supporting import/export
|
14
15
|
EXPORT_PARAMS = [:amqp_provider, :networking, :layout_name, :platform]
|
15
|
-
EXPORT_SERVICES = [:nova, :neutron, :glance, :cinder, :passwords]
|
16
|
+
EXPORT_SERVICES = [:nova, :neutron, :glance, :cinder, :passwords]
|
16
17
|
|
17
18
|
attr_accessible :description, :name, :layout_id, :layout,
|
18
19
|
:amqp_provider, :layout_name, :networking, :platform
|
@@ -40,11 +41,17 @@ module Staypuft
|
|
40
41
|
has_many :services, :through => :roles
|
41
42
|
has_many :hosts, :through => :child_hostgroups
|
42
43
|
|
44
|
+
has_many :subnet_typings, :dependent => :destroy
|
45
|
+
has_many :subnet_types, :through => :subnet_typings
|
46
|
+
has_many :subnets, :through => :subnet_typings
|
47
|
+
|
43
48
|
validates :name, :presence => true, :uniqueness => true
|
44
49
|
|
45
50
|
validates :layout, :presence => true
|
46
51
|
validates :hostgroup, :presence => true
|
47
52
|
|
53
|
+
validate :all_required_subnet_types_associated, :if => Proc.new { |o| o.form_step == STEP_NETWORKING }
|
54
|
+
|
48
55
|
after_validation :check_form_complete
|
49
56
|
before_save :update_layout
|
50
57
|
after_save :update_based_on_settings
|
@@ -114,6 +121,10 @@ module Staypuft
|
|
114
121
|
ForemanTasks::Lock.locked? self, nil
|
115
122
|
end
|
116
123
|
|
124
|
+
def hide_ceph_notification?
|
125
|
+
ceph_hostgroup.hosts.empty?
|
126
|
+
end
|
127
|
+
|
117
128
|
# Helper method for getting the in progress foreman task for this
|
118
129
|
# deployment.
|
119
130
|
def task
|
@@ -127,7 +138,7 @@ module Staypuft
|
|
127
138
|
end
|
128
139
|
|
129
140
|
def progress_summary
|
130
|
-
self.in_progress? ? self.task.humanized[:output] : nil
|
141
|
+
self.in_progress? ? self.task.humanized[:output] : nil
|
131
142
|
end
|
132
143
|
|
133
144
|
# Helper method for getting the progress of this deployment
|
@@ -186,7 +197,8 @@ module Staypuft
|
|
186
197
|
|
187
198
|
class Jail < Safemode::Jail
|
188
199
|
allow :amqp_provider, :networking, :layout_name, :platform, :nova_networking?, :neutron_networking?,
|
189
|
-
:nova, :neutron, :glance, :cinder, :passwords, :vips, :ips, :ha?, :non_ha
|
200
|
+
:nova, :neutron, :glance, :cinder, :passwords, :vips, :ips, :ha?, :non_ha?,
|
201
|
+
:hide_ceph_notification?
|
190
202
|
end
|
191
203
|
|
192
204
|
# TODO(mtaylor)
|
@@ -257,6 +269,17 @@ module Staypuft
|
|
257
269
|
first
|
258
270
|
end
|
259
271
|
|
272
|
+
def unassigned_subnet_types
|
273
|
+
self.layout.subnet_types - self.subnet_types
|
274
|
+
end
|
275
|
+
|
276
|
+
def ceph_hostgroup
|
277
|
+
Hostgroup.includes(:deployment_role_hostgroup).
|
278
|
+
where(DeploymentRoleHostgroup.table_name => { deployment_id: self,
|
279
|
+
role_id: Staypuft::Role.cephosd }).
|
280
|
+
first
|
281
|
+
end
|
282
|
+
|
260
283
|
private
|
261
284
|
|
262
285
|
def update_layout
|
@@ -269,6 +292,15 @@ module Staypuft
|
|
269
292
|
update_hostgroup_list
|
270
293
|
end
|
271
294
|
|
295
|
+
def all_required_subnet_types_associated
|
296
|
+
associated_subnet_types = self.subnet_typings.map(&:subnet_type)
|
297
|
+
missing_required = self.layout.subnet_types.required.select { |t| !associated_subnet_types.include?(t) }
|
298
|
+
unless missing_required.empty?
|
299
|
+
errors.add :base,
|
300
|
+
_("Some required subnet types are missing association of a subnet. Please drag and drop following types: %s") % missing_required.map(&:name).join(', ')
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
272
304
|
def update_hostgroup_name
|
273
305
|
hostgroup.name = self.name
|
274
306
|
hostgroup.save!
|
@@ -0,0 +1,137 @@
|
|
1
|
+
module Staypuft
|
2
|
+
class InterfaceAssigner
|
3
|
+
attr_accessor :deployment, :interface, :subnet, :errors
|
4
|
+
|
5
|
+
def initialize(deployment, interface, subnet)
|
6
|
+
@deployment = deployment
|
7
|
+
if interface.is_a?(Nic::Base)
|
8
|
+
@interface = interface
|
9
|
+
else
|
10
|
+
# interface may be Host::Managed which means primary interface, so we create pseudo-interface object
|
11
|
+
@interface = Nic::Managed.new(
|
12
|
+
:mac => interface.mac,
|
13
|
+
:virtual => false,
|
14
|
+
:identifier => interface.primary_interface,
|
15
|
+
:host => interface,
|
16
|
+
:subnet => interface.subnet)
|
17
|
+
end
|
18
|
+
|
19
|
+
@host = @interface.host
|
20
|
+
@subnet = subnet
|
21
|
+
@errors = []
|
22
|
+
end
|
23
|
+
|
24
|
+
def assign
|
25
|
+
if virtual_assignment?
|
26
|
+
if (existing = conflicting_interface)
|
27
|
+
@errors.push _("Another interface %s on same physical interface with same VLAN exists") % existing.identifier
|
28
|
+
return false
|
29
|
+
end
|
30
|
+
ActiveRecord::Base.transaction do
|
31
|
+
unassign_from_other_nics
|
32
|
+
assign_virtual
|
33
|
+
raise ActiveRecord::Rollback if @errors.present?
|
34
|
+
return true
|
35
|
+
end
|
36
|
+
else
|
37
|
+
if @interface.subnet.present? && @interface.subnet != @subnet
|
38
|
+
@errors.push _("Interface is already assigned to subnet %s") % @interface.subnet.name
|
39
|
+
return false
|
40
|
+
end
|
41
|
+
ActiveRecord::Base.transaction do
|
42
|
+
unassign_from_other_nics
|
43
|
+
assign_physical
|
44
|
+
raise ActiveRecord::Rollback if @errors.present?
|
45
|
+
return true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
return false # we can get there only after rollback
|
50
|
+
end
|
51
|
+
|
52
|
+
def unassign
|
53
|
+
base = @host.interfaces
|
54
|
+
base = virtual_assignment? ? base.virtual : base.physical
|
55
|
+
ActiveRecord::Base.transaction do
|
56
|
+
base.where(:subnet_id => @subnet.id).each do |interface|
|
57
|
+
virtual_assignment? ? unassign_virtual(interface) : unassign_physical(interface)
|
58
|
+
end
|
59
|
+
raise ActiveRecord::Rollback if @errors.present?
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def virtual_assignment?
|
64
|
+
@subnet.vlanid.present?
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def assign_virtual
|
70
|
+
interface = Nic::Managed.new(
|
71
|
+
:subnet => @subnet,
|
72
|
+
:physical_device => @interface.identifier,
|
73
|
+
:mac => @interface.mac,
|
74
|
+
:host => @host,
|
75
|
+
:virtual => true,
|
76
|
+
:identifier => @interface.identifier + ".#{@subnet.vlanid}")
|
77
|
+
suggest_ip(interface) if @subnet.ipam?
|
78
|
+
unless interface.save
|
79
|
+
@errors.push(*interface.errors.full_messages)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def assign_physical
|
84
|
+
@interface.subnet = @subnet
|
85
|
+
suggest_ip(@interface) if @subnet.ipam?
|
86
|
+
unless @interface.save
|
87
|
+
@errors.push(*@interface.errors.full_messages)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# we have to be sure that we remove both physical and virtual,
|
92
|
+
# subnet could become virtual/physical meanwhile
|
93
|
+
def unassign_from_other_nics
|
94
|
+
unassign_physicals
|
95
|
+
unassign_virtuals
|
96
|
+
end
|
97
|
+
|
98
|
+
def unassign_physicals
|
99
|
+
@host.interfaces.physical.where(:subnet_id => @subnet.id).each do |interface|
|
100
|
+
unassign_physical(interface)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# if subnet has IP suggesting enabled we also clear the IP that was suggested
|
105
|
+
# this IP will be used for another interface
|
106
|
+
def unassign_physical(interface)
|
107
|
+
interface.ip = nil if interface.subnet.ipam?
|
108
|
+
interface.subnet_id = nil
|
109
|
+
unless interface.save
|
110
|
+
@errors.push(interface.errors.full_messages)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def unassign_virtuals
|
115
|
+
@host.interfaces.virtual.where(:subnet_id => @subnet.id).each do |interface|
|
116
|
+
unassign_virtual(interface)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def unassign_virtual(interface)
|
121
|
+
unless interface.destroy
|
122
|
+
@errors.push _("Interface %s could not be destroyed") % interface.name
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def conflicting_interface
|
127
|
+
@host.interfaces.
|
128
|
+
where(:identifier => @interface.identifier + ".#{subnet.vlanid}").
|
129
|
+
where(['id <> ?', @interface.id]).
|
130
|
+
first
|
131
|
+
end
|
132
|
+
|
133
|
+
def suggest_ip(interface)
|
134
|
+
interface.ip = @subnet.unused_ip if interface.ip.blank?
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -5,6 +5,9 @@ module Staypuft
|
|
5
5
|
has_many :layout_roles, :dependent => :destroy, :order => "staypuft_layout_roles.deploy_order ASC"
|
6
6
|
has_many :roles, :through => :layout_roles, :order => "staypuft_layout_roles.deploy_order ASC"
|
7
7
|
|
8
|
+
has_many :layout_subnet_types, :dependent => :destroy
|
9
|
+
has_many :subnet_types, :through => :layout_subnet_types
|
10
|
+
|
8
11
|
attr_accessible :description, :name, :networking
|
9
12
|
|
10
13
|
validates :name, :presence => true, :uniqueness => {:scope => :networking}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Staypuft
|
2
|
+
class LayoutSubnetType < ActiveRecord::Base
|
3
|
+
attr_accessible :layout_id, :layout, :subnet_type_id, :subnet_type
|
4
|
+
|
5
|
+
belongs_to :layout
|
6
|
+
belongs_to :subnet_type
|
7
|
+
|
8
|
+
validates :layout, :presence => true
|
9
|
+
validates :subnet_type, :presence => true
|
10
|
+
validates :layout_id, :uniqueness => { :scope => :subnet_type_id }
|
11
|
+
end
|
12
|
+
end
|
data/app/models/staypuft/role.rb
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
module Staypuft
|
2
2
|
class Role < ActiveRecord::Base
|
3
|
+
# until we have puppetssh, "run puppet" below means "provision and run puppet"
|
4
|
+
|
5
|
+
# run puppet on all nodes concurrently
|
6
|
+
ORCHESTRATION_CONCURRENT = "concurrent"
|
7
|
+
# run puppet on one node at a time
|
8
|
+
ORCHESTRATION_SERIAL = "serial"
|
9
|
+
# run puppet on the first mode, then the rest concurrently
|
10
|
+
ORCHESTRATION_LEADER = "leader"
|
11
|
+
|
12
|
+
ORCHESTRATION_MODES = [ORCHESTRATION_CONCURRENT, ORCHESTRATION_SERIAL, ORCHESTRATION_LEADER]
|
13
|
+
|
3
14
|
has_many :layout_roles, :dependent => :destroy
|
4
15
|
has_many :layouts, :through => :layout_roles
|
5
16
|
|
@@ -17,11 +28,15 @@ module Staypuft
|
|
17
28
|
|
18
29
|
validates :name, :presence => true, :uniqueness => true
|
19
30
|
|
31
|
+
validates :orchestration, :inclusion => {:in => ORCHESTRATION_MODES }
|
32
|
+
|
20
33
|
scope(:in_deployment, lambda do |deployment|
|
21
34
|
joins(:deployment_role_hostgroups).
|
22
35
|
where(DeploymentRoleHostgroup.table_name => { deployment_id: deployment })
|
23
36
|
end)
|
24
37
|
|
25
38
|
scope(:controller, where(name: Seeder::CONTROLLER_ROLES.map { |h| h.fetch(:name) }))
|
39
|
+
|
40
|
+
scope(:cephosd, where(name: Seeder::CEPH_ROLES.map { |h| h.fetch(:name) }))
|
26
41
|
end
|
27
42
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Staypuft
|
2
|
+
class SubnetType < ActiveRecord::Base
|
3
|
+
PXE = 'Provisioning/PXE'
|
4
|
+
|
5
|
+
MANAGEMENT = 'Management'
|
6
|
+
EXTERNAL = 'External'
|
7
|
+
CLUSTER_MGMT = 'Cluster Management'
|
8
|
+
ADMIN_API = 'Admin API'
|
9
|
+
PUBLIC_API = 'Public API'
|
10
|
+
TENANT = 'Tenant'
|
11
|
+
|
12
|
+
STORAGE = 'Storage'
|
13
|
+
STORAGE_CLUSTERING = 'Storage Clustering'
|
14
|
+
|
15
|
+
validates :name, :presence => true
|
16
|
+
|
17
|
+
has_many :layout_subnet_types, :dependent => :destroy
|
18
|
+
has_many :layouts, :through => :layout_subnet_types
|
19
|
+
|
20
|
+
attr_accessible :name
|
21
|
+
|
22
|
+
has_many :subnet_typings
|
23
|
+
has_many :subnets, :through => :subnet_typings
|
24
|
+
|
25
|
+
scope :required, lambda { where(:is_required => true) }
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Staypuft
|
2
|
+
class SubnetTyping < ActiveRecord::Base
|
3
|
+
belongs_to :deployment
|
4
|
+
belongs_to :subnet_type
|
5
|
+
belongs_to :subnet
|
6
|
+
|
7
|
+
attr_accessible :subnet_type, :subnet_type_id, :subnet, :subnet_id
|
8
|
+
|
9
|
+
validates :subnet_type_id, :uniqueness => { :scope => :deployment_id }
|
10
|
+
end
|
11
|
+
end
|
@@ -5,7 +5,10 @@
|
|
5
5
|
<div class="pull-right top_actions">
|
6
6
|
<%= render partial: "hosts_filter" %>
|
7
7
|
<div class="pull-right">
|
8
|
-
|
8
|
+
|
9
|
+
<%= submit_tag _("Configure Networks"), :class => "btn btn-default btn-sm dynamic-submit", :disabled => true,
|
10
|
+
:'data-submit-to' => deployment_interface_assignments_path(@deployment), :'data-method' => 'GET',
|
11
|
+
:id => "configure_networks_button"%>
|
9
12
|
<%= submit_tag _("Unassign Hosts"), :class => "btn btn-primary btn-sm", :disabled => true, :id => "unassign_hosts_button" %>
|
10
13
|
</div>
|
11
14
|
</div>
|
@@ -40,7 +43,7 @@
|
|
40
43
|
</td>
|
41
44
|
<td><%= host.cpus %></td>
|
42
45
|
<td><%= host.mem %></td>
|
43
|
-
<td><%= host
|
46
|
+
<td><%= host_nics(host) %></td>
|
44
47
|
<td class="hidden-s hidden-xs"><%= host.ip %></td>
|
45
48
|
</tr>
|
46
49
|
<% end %>
|
@@ -1,60 +1,27 @@
|
|
1
1
|
<div class="tab-pane" id="<%= child_hostgroup.name.parameterize.underscore %>_assigned_hosts">
|
2
|
-
<% if
|
2
|
+
<% if hosts.present? %>
|
3
3
|
<%= form_tag(unassign_host_deployment_path(id: deployment), class: 'form-horizontal well association') do |f| %>
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
<p class="clearfix"></p>
|
8
|
-
<%= hidden_field_tag :hostgroup_id, child_hostgroup.id %>
|
4
|
+
|
5
|
+
<%= render 'hosts_header', :header => _("Assigned Hosts"), :child_hostgroup => child_hostgroup, :assign_text => _("Unassign Hosts") %>
|
6
|
+
|
9
7
|
<table class="table table-bordered table-striped table-condensed">
|
10
8
|
<thead>
|
11
|
-
|
12
|
-
<th class="ca">
|
13
|
-
<%= tag :input, type: 'checkbox', class: 'check_all' %>
|
14
|
-
</th>
|
15
|
-
<th><%= sort :name, :as => _('Name') %></th>
|
16
|
-
<th class="hidden-s hidden-xs"><%= _('Deploying?') %></th>
|
17
|
-
<th class="hidden-s hidden-xs"><%= sort :ip, :as => _('IP Address') %></th>
|
18
|
-
</tr>
|
9
|
+
<%= render 'host_head_row', :deploying_col => true %>
|
19
10
|
</thead>
|
20
11
|
<tbody>
|
21
|
-
<%
|
12
|
+
<% hosts.each do |host| %>
|
22
13
|
<% disabled = ForemanTasks::Lock.locked?(deployment, nil) && host.open_stack_deployed? %>
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
host.id,
|
29
|
-
false,
|
30
|
-
id: "host_ids_#{host.id}",
|
31
|
-
disabled: disabled %>
|
32
|
-
<%= hidden_field_tag 'host_ids[]', host.id if disabled %>
|
33
|
-
</td>
|
34
|
-
<td class="ellipsis">
|
35
|
-
<%= host_label(host) %>
|
36
|
-
</td>
|
37
|
-
<td class="hidden-s hidden-xs">
|
38
|
-
<% if disabled %>
|
39
|
-
<span class="glyphicon glyphicon-cloud-upload"></span>
|
40
|
-
<% else %>
|
41
|
-
<span class="glyphicon glyphicon-minus"></span>
|
42
|
-
<% end %>
|
43
|
-
</td>
|
44
|
-
<td class="hidden-s hidden-xs"><%= host.ip %></td>
|
45
|
-
</tr>
|
14
|
+
<%= render 'host_row',
|
15
|
+
:custom_css_class => disabled ? 'deploying' : '',
|
16
|
+
:disabled => disabled,
|
17
|
+
:host => host,
|
18
|
+
:checkbox_value => false %>
|
46
19
|
<% end %>
|
47
20
|
</tbody>
|
48
21
|
</table>
|
22
|
+
|
49
23
|
<% end %>
|
50
24
|
<% else %>
|
51
|
-
|
52
|
-
<button type="button" class="close pull-right" aria-hidden="true">×</button>
|
53
|
-
<h4><%= _("Assigned Hosts") %></h4>
|
54
|
-
<div class="alert alert-warning">
|
55
|
-
<span class="glyphicon glyphicon-warning-sign"> </span>
|
56
|
-
<%= _("No hosts were assigned to this group yet.") %>
|
57
|
-
</div>
|
58
|
-
</div>
|
25
|
+
<%= render 'empty_hosts', :header => _("Assigned Hosts"), :message => _("No hosts were assigned to this group yet.") %>
|
59
26
|
<% end %>
|
60
27
|
</div>
|