staypuft 0.3.1 → 0.3.2

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/staypuft/nics_assignment.js +5 -5
  3. data/app/assets/javascripts/staypuft/staypuft.js +58 -5
  4. data/app/assets/javascripts/staypuft/subnets_assignment.js +5 -4
  5. data/app/assets/stylesheets/staypuft/bootstrap_and_overrides.css.scss +16 -0
  6. data/app/assets/stylesheets/staypuft/staypuft.css.scss +30 -71
  7. data/app/controllers/staypuft/deployments_controller.rb +23 -0
  8. data/app/controllers/staypuft/interface_assignments_controller.rb +2 -1
  9. data/app/lib/staypuft/network_query.rb +88 -5
  10. data/app/lib/staypuft/seeder.rb +75 -71
  11. data/app/models/staypuft/concerns/host_interface_management.rb +25 -2
  12. data/app/models/staypuft/concerns/subnet_ip_management.rb +17 -0
  13. data/app/models/staypuft/concerns/vip_nic_scopes.rb +13 -0
  14. data/app/models/staypuft/deployment/attribute_param_storage.rb +59 -1
  15. data/app/models/staypuft/deployment/cinder_service/equallogic.rb +80 -0
  16. data/app/models/staypuft/deployment/cinder_service.rb +53 -94
  17. data/app/models/staypuft/deployment/neutron_service.rb +20 -83
  18. data/app/models/staypuft/deployment/nova_service.rb +2 -31
  19. data/app/models/staypuft/deployment.rb +9 -7
  20. data/app/models/staypuft/subnet_type.rb +4 -0
  21. data/app/views/staypuft/deployments/_assigned_hosts.html.erb +23 -4
  22. data/app/views/staypuft/deployments/_deployment_access_all_details_dialogue.html.erb +5 -5
  23. data/app/views/staypuft/deployments/_deployment_hosts.html.erb +1 -1
  24. data/app/views/staypuft/deployments/_free_hosts.html.erb +4 -4
  25. data/app/views/staypuft/interface_assignments/index.html.erb +36 -31
  26. data/app/views/staypuft/interfaces/_drop_zone.html.erb +22 -22
  27. data/app/views/staypuft/steps/_cinder.html.erb +48 -26
  28. data/app/views/staypuft/steps/_cinder_equallogic_form.html.erb +13 -0
  29. data/app/views/staypuft/steps/_neutron.html.erb +0 -28
  30. data/app/views/staypuft/steps/_nova.html.erb +0 -11
  31. data/app/views/staypuft/steps/network_configuration.html.erb +27 -19
  32. data/app/views/staypuft/steps/services_configuration.html.erb +1 -1
  33. data/app/views/staypuft/subnet_typings/destroy.js.erb +1 -1
  34. data/app/views/staypuft/subnets/_drop_zone.html.erb +5 -5
  35. data/app/views/staypuft/subnets/_subnet_pull.html.erb +3 -4
  36. data/lib/staypuft/engine.rb +2 -0
  37. data/lib/staypuft/version.rb +1 -1
  38. metadata +6 -4
  39. data/app/models/staypuft/deployment/ips.rb +0 -25
  40. data/app/models/staypuft/deployment/vips.rb +0 -40
@@ -203,13 +203,13 @@ module Staypuft
203
203
  :layouts => ALL_LAYOUTS}
204
204
  }
205
205
 
206
- def get_host_format(param_name)
207
- { :string => '<%%= d = @host.deployment; d.ha? ? d.vips.get(:%s) : d.ips.controller_ip %%>' % param_name }
206
+ def get_host_format(param_name, subnet_type_name)
207
+ { :string => "<%= d = @host.deployment; d.ha? ? d.network_query.get_vip(:#{param_name}) : d.network_query.controller_ip('#{subnet_type_name}') %>" }
208
208
  end
209
209
 
210
210
  # virtual ip addresses
211
211
  def vip_format(param_name)
212
- { :string => '<%%= @host.deployment.vips.get(:%s) %%>' % param_name }
212
+ { :string => '<%%= @host.deployment.network_query.get_vip(:%s) %%>' % param_name }
213
213
  end
214
214
 
215
215
  def functional_dependencies
@@ -224,8 +224,8 @@ module Staypuft
224
224
  network_num_networks = { :string => '<%= @host.deployment.nova.num_networks %>' }
225
225
  network_fixed_range = { :string => '<%= @host.deployment.nova.private_fixed_range %>' }
226
226
  network_floating_range = { :string => '<%= @host.deployment.nova.public_floating_range %>' }
227
- network_private_iface = { :string => '<%= @host.deployment.nova.private_iface %>' }
228
- network_public_iface = { :string => '<%= @host.deployment.nova.public_iface %>' }
227
+ network_private_iface = { :string => "<%= @host.deployment.network_query.interface_for_host(@host, '#{Staypuft::SubnetType::TENANT}') %>" }
228
+ network_public_iface = { :string => "<%= @host.deployment.network_query.interface_for_host(@host, '#{Staypuft::SubnetType::EXTERNAL}') %>" }
229
229
  network_create_networks = true
230
230
 
231
231
  # Neutron
@@ -237,12 +237,12 @@ module Staypuft
237
237
  ml2_tunnel_id_ranges = ['10:1000']
238
238
  ml2_vni_ranges = ['10:1000']
239
239
  ovs_tunnel_types = ['vxlan', 'gre']
240
- ovs_tunnel_iface = { :string => '<%= n = @host.deployment.neutron; n.enable_tunneling? ? n.networker_tenant_iface : "" %>' }
241
- ovs_bridge_mappings = { :array => '<%= @host.deployment.neutron.networker_ovs_bridge_mappings %>' }
242
- ovs_bridge_uplinks = { :array => '<%= @host.deployment.neutron.networker_ovs_bridge_uplinks %>' }
243
- compute_ovs_tunnel_iface = { :string => '<%= n = @host.deployment.neutron; n.enable_tunneling? ? n.compute_tenant_iface : "" %>' }
244
- compute_ovs_bridge_mappings = { :array => '<%= @host.deployment.neutron.compute_ovs_bridge_mappings %>' }
245
- compute_ovs_bridge_uplinks = { :array => '<%= @host.deployment.neutron.compute_ovs_bridge_uplinks %>' }
240
+ ovs_tunnel_iface = { :string => '<%= n = @host.deployment.neutron; n.enable_tunneling? ? n.tenant_iface(@host) : "" %>' }
241
+ ovs_bridge_mappings = { :array => '<%= @host.deployment.neutron.networker_ovs_bridge_mappings(@host) %>' }
242
+ ovs_bridge_uplinks = { :array => '<%= @host.deployment.neutron.networker_ovs_bridge_uplinks(@host) %>' }
243
+ compute_ovs_tunnel_iface = { :string => '<%= n = @host.deployment.neutron; n.enable_tunneling? ? n.tenant_iface(@host) : "" %>' }
244
+ compute_ovs_bridge_mappings = { :array => '<%= @host.deployment.neutron.compute_ovs_bridge_mappings(@host) %>' }
245
+ compute_ovs_bridge_uplinks = { :array => '<%= @host.deployment.neutron.compute_ovs_bridge_uplinks(@host) %>' }
246
246
  enable_tunneling = { :string => '<%= @host.deployment.neutron.enable_tunneling?.to_s %>' }
247
247
 
248
248
  # Glance
@@ -263,7 +263,7 @@ module Staypuft
263
263
  cinder_backend_iscsi_name = 'iscsi_backend'
264
264
  cinder_backend_nfs = { :string => '<%= @host.deployment.cinder.nfs_backend? %>' }
265
265
  cinder_backend_nfs_name = 'nfs_backend'
266
- cinder_multiple_backends = false
266
+ cinder_multiple_backends = { :string => '<%= @host.deployment.cinder.multiple_backends? %>' }
267
267
  cinder_nfs_shares = ['<%= @host.deployment.cinder.nfs_uri %>']
268
268
  cinder_nfs_mount_options = 'nosharecache'
269
269
 
@@ -280,11 +280,11 @@ module Staypuft
280
280
  cinder_backend_eqlx_name = ['eqlx_backend']
281
281
  # TODO: confirm these params and add them to model where user input is needed
282
282
  # below dynamic calls are commented out since the model does not yet have san/chap entries
283
- cinder_san_ip = ['<%= @host.deployment.cinder.san_ip %>']
284
- cinder_san_login = ['<%= @host.deployment.cinder.san_login %>']
285
- cinder_san_password = ['<%= @host.deployment.cinder.san_password %>']
286
- cinder_eqlx_group_name = ['<%= @host.deployment.cinder.eqlx_group_name %>']
287
- cinder_eqlx_pool = ['<%= @host.deployment.cinder.eqlx_pool %>']
283
+ cinder_san_ip = { :array => '<%= @host.deployment.cinder.compute_eqlx_san_ips %>' }
284
+ cinder_san_login = { :array => '<%= @host.deployment.cinder.compute_eqlx_san_logins %>' }
285
+ cinder_san_password = { :array => '<%= @host.deployment.cinder.compute_eqlx_san_passwords %>' }
286
+ cinder_eqlx_group_name = { :array => '<%= @host.deployment.cinder.compute_eqlx_group_names %>' }
287
+ cinder_eqlx_pool = { :array => '<%= @host.deployment.cinder.compute_eqlx_pools %>'}
288
288
 
289
289
  cinder_san_thin_provision = ['false']
290
290
  cinder_eqlx_use_chap = ['false']
@@ -326,15 +326,20 @@ module Staypuft
326
326
  neutron_metadata_proxy_secret = { :string => '<%= @host.deployment.passwords.neutron_metadata_proxy_secret %>' }
327
327
 
328
328
 
329
- private_ip = { :string => '<%= @host.ip %>' }
330
- amqp_host = get_host_format :amqp
331
- mysql_host = get_host_format :db
332
- glance_host = get_host_format :glance
333
- auth_host = get_host_format :keystone
334
- neutron_host = get_host_format :neutron
335
- nova_host = get_host_format :nova
329
+ private_ip = { :string => "<%= @host.deployment.network_query.ip_for_host(@host, '#{Staypuft::SubnetType::MANAGEMENT}') %>" }
330
+ # private API/management
331
+ amqp_host = get_host_format :amqp_vip, Staypuft::SubnetType::MANAGEMENT
332
+ mysql_host = get_host_format :db_vip, Staypuft::SubnetType::MANAGEMENT
333
+ glance_host = get_host_format :glance_private_vip, Staypuft::SubnetType::MANAGEMENT
334
+ neutron_host = get_host_format :neutron_private_vip, Staypuft::SubnetType::MANAGEMENT
335
+ #admin API
336
+ auth_host = get_host_format :keystone_admin_vip, Staypuft::SubnetType::ADMIN_API
337
+ # public API
338
+ nova_host = get_host_format :nova_public_vip, Staypuft::SubnetType::PUBLIC_API
336
339
 
337
- controller_host = { :string => '<%= d = @host.deployment; d.ha? ? nil : d.ips.controller_ip %>'}
340
+ controller_admin_host = { :string => "<%= d = @host.deployment; d.ha? ? nil : d.network_query.controller_ip('#{Staypuft::SubnetType::ADMIN_API}') %>"}
341
+ controller_priv_host = { :string => "<%= d = @host.deployment; d.ha? ? nil : d.network_query.controller_ip('#{Staypuft::SubnetType::MANAGEMENT}') %>"}
342
+ controller_pub_host = { :string => "<%= d = @host.deployment; d.ha? ? nil : d.network_query.controller_ip('#{Staypuft::SubnetType::PUBLIC_API}') %>"}
338
343
 
339
344
  {
340
345
  'quickstack::nova_network::controller' => {
@@ -394,11 +399,11 @@ module Staypuft
394
399
  'mysql_host' => mysql_host,
395
400
  'swift_shared_secret' => swift_shared_secret,
396
401
  'swift_ringserver_ip' => '',
397
- 'swift_storage_ips' => { :array => '<%= @host.deployment.ips.controller_ips %>' },
402
+ 'swift_storage_ips' => { :array => "<%= @host.deployment.network_query.controller_ips('#{Staypuft::SubnetType::MANAGEMENT}') %>" },
398
403
  'cinder_gluster_shares' => [],
399
- 'controller_admin_host' => controller_host,
400
- 'controller_priv_host' => controller_host,
401
- 'controller_pub_host' => controller_host },
404
+ 'controller_admin_host' => controller_admin_host,
405
+ 'controller_priv_host' => controller_priv_host,
406
+ 'controller_pub_host' => controller_pub_host },
402
407
  'quickstack::neutron::controller' => {
403
408
  'amqp_provider' => amqp_provider,
404
409
  'tenant_network_type' => tenant_network_type,
@@ -467,11 +472,11 @@ module Staypuft
467
472
  'mysql_host' => mysql_host,
468
473
  'swift_shared_secret' => swift_shared_secret,
469
474
  'swift_ringserver_ip' => '',
470
- 'swift_storage_ips' => { :array => '<%= @host.deployment.ips.controller_ips %>' },
475
+ 'swift_storage_ips' => { :array => "<%= @host.deployment.network_query.controller_ips('#{Staypuft::SubnetType::MANAGEMENT}') %>" },
471
476
  'cinder_gluster_shares' => [],
472
- 'controller_admin_host' => controller_host,
473
- 'controller_priv_host' => controller_host,
474
- 'controller_pub_host' => controller_host },
477
+ 'controller_admin_host' => controller_admin_host,
478
+ 'controller_priv_host' => controller_priv_host,
479
+ 'controller_pub_host' => controller_pub_host },
475
480
  'quickstack::pacemaker::params' => {
476
481
  'include_swift' => 'false',
477
482
  'include_neutron' => neutron,
@@ -494,43 +499,43 @@ module Staypuft
494
499
  'amqp_password' => amqp_pw,
495
500
  'heat_auth_encryption_key' => heat_auth_encrypt_key,
496
501
  'neutron_metadata_proxy_secret' => neutron_metadata_proxy_secret,
497
- 'ceilometer_admin_vip' => vip_format(:ceilometer),
498
- 'ceilometer_private_vip' => vip_format(:ceilometer),
499
- 'ceilometer_public_vip' => vip_format(:ceilometer),
500
- 'cinder_admin_vip' => vip_format(:cinder),
501
- 'cinder_private_vip' => vip_format(:cinder),
502
- 'cinder_public_vip' => vip_format(:cinder),
503
- 'db_vip' => vip_format(:db),
504
- 'glance_admin_vip' => vip_format(:glance),
505
- 'glance_private_vip' => vip_format(:glance),
506
- 'glance_public_vip' => vip_format(:glance),
507
- 'heat_admin_vip' => vip_format(:heat),
508
- 'heat_private_vip' => vip_format(:heat),
509
- 'heat_public_vip' => vip_format(:heat),
510
- 'heat_cfn_admin_vip' => vip_format(:heat_cfn),
511
- 'heat_cfn_private_vip' => vip_format(:heat_cfn),
512
- 'heat_cfn_public_vip' => vip_format(:heat_cfn),
513
- 'horizon_admin_vip' => vip_format(:horizon),
514
- 'horizon_private_vip' => vip_format(:horizon),
515
- 'horizon_public_vip' => vip_format(:horizon),
516
- 'keystone_admin_vip' => vip_format(:keystone),
517
- 'keystone_private_vip' => vip_format(:keystone),
518
- 'keystone_public_vip' => vip_format(:keystone),
519
- 'loadbalancer_vip' => vip_format(:loadbalancer),
520
- 'neutron_admin_vip' => vip_format(:neutron),
521
- 'neutron_private_vip' => vip_format(:neutron),
522
- 'neutron_public_vip' => vip_format(:neutron),
523
- 'nova_admin_vip' => vip_format(:nova),
524
- 'nova_private_vip' => vip_format(:nova),
525
- 'nova_public_vip' => vip_format(:nova),
526
- 'amqp_vip' => vip_format(:amqp),
527
- 'swift_public_vip' => vip_format(:swift),
502
+ 'ceilometer_admin_vip' => vip_format(:ceilometer_admin_vip),
503
+ 'ceilometer_private_vip' => vip_format(:ceilometer_private_vip),
504
+ 'ceilometer_public_vip' => vip_format(:ceilometer_public_vip),
505
+ 'cinder_admin_vip' => vip_format(:cinder_admin_vip),
506
+ 'cinder_private_vip' => vip_format(:cinder_private_vip),
507
+ 'cinder_public_vip' => vip_format(:cinder_public_vip),
508
+ 'db_vip' => vip_format(:db_vip),
509
+ 'glance_admin_vip' => vip_format(:glance_admin_vip),
510
+ 'glance_private_vip' => vip_format(:glance_private_vip),
511
+ 'glance_public_vip' => vip_format(:glance_public_vip),
512
+ 'heat_admin_vip' => vip_format(:heat_admin_vip),
513
+ 'heat_private_vip' => vip_format(:heat_private_vip),
514
+ 'heat_public_vip' => vip_format(:heat_public_vip),
515
+ 'heat_cfn_admin_vip' => vip_format(:heat_cfn_admin_vip),
516
+ 'heat_cfn_private_vip' => vip_format(:heat_cfn_private_vip),
517
+ 'heat_cfn_public_vip' => vip_format(:heat_cfn_public_vip),
518
+ 'horizon_admin_vip' => vip_format(:horizon_admin_vip),
519
+ 'horizon_private_vip' => vip_format(:horizon_private_vip),
520
+ 'horizon_public_vip' => vip_format(:horizon_public_vip),
521
+ 'keystone_admin_vip' => vip_format(:keystone_admin_vip),
522
+ 'keystone_private_vip' => vip_format(:keystone_private_vip),
523
+ 'keystone_public_vip' => vip_format(:keystone_public_vip),
524
+ 'loadbalancer_vip' => vip_format(:loadbalancer_vip),
525
+ 'neutron_admin_vip' => vip_format(:neutron_admin_vip),
526
+ 'neutron_private_vip' => vip_format(:neutron_private_vip),
527
+ 'neutron_public_vip' => vip_format(:neutron_public_vip),
528
+ 'nova_admin_vip' => vip_format(:nova_admin_vip),
529
+ 'nova_private_vip' => vip_format(:nova_private_vip),
530
+ 'nova_public_vip' => vip_format(:nova_public_vip),
531
+ 'amqp_vip' => vip_format(:amqp_vip),
532
+ 'swift_public_vip' => vip_format(:swift_public_vip),
528
533
  'private_ip' => private_ip,
529
- 'cluster_control_ip' => { :string => '<%= @host.deployment.ips.controller_ips.first %>' },
530
- 'lb_backend_server_addrs' => { :array => '<%= @host.deployment.ips.controller_ips %>' },
531
- 'lb_backend_server_names' => { :array => '<%= @host.deployment.ips.controller_fqdns %>' } },
534
+ 'cluster_control_ip' => { :string => "<%= @host.deployment.network_query.controller_ips('#{Staypuft::SubnetType::MANAGEMENT}').first %>" },
535
+ 'lb_backend_server_addrs' => { :array => "<%= @host.deployment.network_query.controller_ips('#{Staypuft::SubnetType::MANAGEMENT}') %>" },
536
+ 'lb_backend_server_names' => { :array => '<%= @host.deployment.network_query.controller_fqdns %>' } },
532
537
  'quickstack::pacemaker::common' => {
533
- 'pacemaker_cluster_members' => { :string => '<%= @host.deployment.ips.controller_ips.join(" ") %>' } },
538
+ 'pacemaker_cluster_members' => { :string => "<%= @host.deployment.network_query.controller_ips('#{Staypuft::SubnetType::MANAGEMENT}').join(' ') %>" } },
534
539
  'quickstack::pacemaker::neutron' => {
535
540
  'ml2_network_vlan_ranges' => ml2_network_vlan_ranges,
536
541
  'ml2_tenant_network_types' => ml2_tenant_network_types,
@@ -580,10 +585,9 @@ module Staypuft
580
585
  'secret_key' => horizon_secret_key },
581
586
  'quickstack::pacemaker::galera' => {
582
587
  'mysql_root_password' => mysql_root_pw,
583
- 'wsrep_cluster_members' => { :array => '<%= @host.deployment.ips.controller_ips %>' } },
588
+ 'wsrep_cluster_members' => { :array => "<%= @host.deployment.network_query.controller_ips('#{Staypuft::SubnetType::MANAGEMENT}') %>" } },
584
589
  'quickstack::pacemaker::swift' => {
585
590
  'swift_shared_secret' => swift_shared_secret,
586
- 'swift_internal_vip' => vip_format(:swift),
587
591
  'swift_storage_ips' => [] },
588
592
  'quickstack::pacemaker::nova' => {
589
593
  'multi_host' => 'true',
@@ -605,7 +609,7 @@ module Staypuft
605
609
  'neutron_metadata_proxy_secret' => neutron_metadata_proxy_secret,
606
610
  'amqp_host' => amqp_host,
607
611
  'mysql_host' => mysql_host,
608
- 'controller_priv_host' => controller_host },
612
+ 'controller_priv_host' => controller_priv_host },
609
613
  'quickstack::storage_backend::cinder' => {
610
614
  'amqp_provider' => amqp_provider,
611
615
  'cinder_db_password' => cinder_db_pw,
@@ -13,16 +13,39 @@ module Staypuft
13
13
 
14
14
  def interfaces_identifiers
15
15
  interfaces = [ self.primary_interface ]
16
- interfaces += self.respond_to?(:interfaces) ? self.interfaces.where("type <> 'Nic::BMC'").physical.map(&:identifier) : []
16
+ interfaces += self.respond_to?(:interfaces) ? self.interfaces.where("type <> 'Nic::BMC'").non_vip.physical.map(&:identifier) : []
17
17
  interfaces
18
18
  end
19
19
 
20
20
  def make_all_interfaces_managed
21
- self.interfaces.each do |interface|
21
+ self.interfaces.non_vip.each do |interface|
22
22
  interface.managed = true
23
23
  interface.save!
24
24
  end
25
25
  end
26
+
27
+ def build_vips(parameters)
28
+ deployment = self.hostgroup.deployment
29
+ typings = deployment.subnet_typings
30
+ types = SubnetType.where(:name => parameters.values).all
31
+ n = 0
32
+
33
+ parameters.each do |parameter, subnet_type|
34
+ type = types.find { |t| t.name == subnet_type }
35
+ raise "unable to find subnet type with name #{subnet_type}" if type.nil?
36
+
37
+ subnet = typings.where(:subnet_type_id => type.id).first.subnet
38
+ raise "unable to find subnet assigned to type #{subnet_type} in deployment #{deployment.name}" if subnet.nil?
39
+
40
+ interface = self.interfaces.build(:type => 'Nic::Managed')
41
+ interface.identifier = "vip#{n}"
42
+ interface.subnet = subnet
43
+ interface.managed = false
44
+ interface.mac = "00:00:00:00:00:#{n.to_s(16).rjust(2, '0')}"
45
+ interface.tag = parameter
46
+ n += 1
47
+ end
48
+ end
26
49
  end
27
50
  end
28
51
  end
@@ -0,0 +1,17 @@
1
+ module Staypuft
2
+ module Concerns
3
+ module SubnetIpManagement
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ before_save :reserve_ip
8
+ end
9
+
10
+ def reserve_ip
11
+ if self.identifier =~ /\Avip\d+\Z/ && self.subnet.present? && self.subnet.ipam?
12
+ self.ip ||= self.subnet.unused_ip
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ module Staypuft
2
+ module Concerns
3
+ module VipNicScopes
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ scope :vip, lambda { where(['identifier LIKE ?', 'vip%']) }
8
+ scope :non_vip, lambda { where(['identifier NOT LIKE ?', 'vip%']) }
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -16,7 +16,7 @@ module Staypuft
16
16
  end
17
17
 
18
18
  define_method "#{name}=" do |value|
19
- instance_variable_set(ivar_name, value)
19
+ instance_variable_set(:"@#{name}", value)
20
20
  end
21
21
 
22
22
  after_save do
@@ -36,6 +36,64 @@ module Staypuft
36
36
  end
37
37
  end
38
38
  end
39
+
40
+ def param_attr_array(*names)
41
+ names.each do |item|
42
+ item.each do |name, type|
43
+ ivar_name = :"@#{name}"
44
+ param_base_name = "ui::#{param_scope}::#{name}"
45
+
46
+ define_method name do
47
+ instance_variable_get(ivar_name) or
48
+ begin
49
+ params = hostgroup.group_parameters.where(['name LIKE ?', "#{param_base_name}%"])
50
+ ivar = []
51
+ params.each do |param|
52
+ value = param.try(:value)
53
+ unless value.nil?
54
+ full, index = *param.name.match(/#{param_base_name}::(\d+)/)
55
+ ivar[index.to_i] ||= type.new({id: index.to_i }.merge(JSON.parse(value)))
56
+ end
57
+ end
58
+ instance_variable_set(ivar_name, ivar)
59
+ end
60
+ end
61
+
62
+ define_method "#{name}=" do |value|
63
+ if value.is_a? Hash
64
+ values = []
65
+ value.each do |k,v|
66
+ values << type.new(v)
67
+ end
68
+ instance_variable_set(:"@#{name}", values)
69
+ else
70
+ instance_variable_set(:"@#{name}", value)
71
+ end
72
+ end
73
+
74
+ define_method "#{name}_attributes=" do |attributes|
75
+ Rails.logger.error attributes
76
+ end
77
+
78
+ after_save do
79
+ values = send(name)
80
+ # Delete all params since array can shrink
81
+ params = hostgroup.group_parameters.where(['name LIKE ?', "#{param_base_name}%"])
82
+ params.each do |param|
83
+ param.try(:destroy)
84
+ end
85
+ if not values.blank?
86
+ values.each_with_index do |value, index|
87
+ param = hostgroup.
88
+ group_parameters.
89
+ find_or_initialize_by_name( "#{param_base_name}::#{index}")
90
+ param.update_attributes!(value: value.to_json(root:false))
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
39
97
  end
40
98
  end
41
99
 
@@ -0,0 +1,80 @@
1
+ #encoding: utf-8
2
+ module Staypuft
3
+ class Deployment::CinderService::Equallogic
4
+ include ActiveModel::Serializers::JSON
5
+ include ActiveModel::Validations
6
+ extend ActiveModel::Naming
7
+
8
+ attr_accessor :id, :san_ip, :san_login, :san_password, :pool, :group_name
9
+ attr_reader :errors
10
+
11
+ def initialize(attrs = {})
12
+ @errors = ActiveModel::Errors.new(self)
13
+ self.attributes = attrs
14
+ end
15
+
16
+ def self.human_attribute_name(attr, options = {})
17
+ attr
18
+ end
19
+
20
+ def self.lookup_ancestors
21
+ [self]
22
+ end
23
+
24
+ def attributes
25
+ { 'san_ip' => nil, 'san_login' => nil, 'san_password' => nil, 'pool' => nil, 'group_name' => nil }
26
+ end
27
+
28
+ def attributes=(attrs)
29
+ attrs.each { |attr, value| send "#{attr}=", value } unless attrs.nil?
30
+ end
31
+
32
+ class SanIpValueValidator < ActiveModel::EachValidator
33
+ def validate_each(record, attribute, value)
34
+ return if value.empty?
35
+
36
+ begin
37
+ ip_addr = IPAddr.new(value)
38
+ ip_range = ip_addr.to_range
39
+ if ip_range.begin == ip_range.end
40
+ true
41
+ else
42
+ record.errors.add attribute, "Specify single IP address, not range"
43
+ false
44
+ end
45
+ rescue
46
+ # not IP addr
47
+ # validating as fqdn
48
+ if /(?=^.{1,254}$)(^(((?!-)[a-zA-Z0-9-]{1,63}(?<!-))|((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+[a-zA-Z]{2,63})$)/ =~ value
49
+ true
50
+ else
51
+ record.errors.add attribute, "Invalid IP address or FQDN supplied"
52
+ false
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ validates :san_ip,
59
+ presence: true,
60
+ san_ip_value: true
61
+ validates :san_login,
62
+ presence: true,
63
+ format: /\A[a-zA-Z\d][\w\.\-]*[\w\-]\z/,
64
+ length: { maximum: 16 }
65
+ validates :san_password,
66
+ presence: true,
67
+ format: /\A[!-~]+\z/,
68
+ length: { minimum:3, maximum: 16 }
69
+ validates :pool,
70
+ presence: true,
71
+ format: /\A[[^\p{Z}\p{C}!"\#$%&'\(\)\*\+,\/;<=>\?@\[\]\\\^\{\}|~\.\-:]][[^\p{Z}\p{C}!"\#$%&'\(\)\*\+,\/;<=>\?@\[\]\\\^\{\}|~]]+[[^\p{Z}\p{C}!"\#$%&'\(\)\*\+,\/;<=>\?@\[\]\\\^\{\}|~\.\-:]]\z/,
72
+ length: { maximum: 63,
73
+ too_long: "Too long: max length is %{count} bytes. Using multibyte characters reduces the maximum number of characters allowed.",
74
+ tokenizer: lambda {|str| str.bytes.to_a } }
75
+ validates :group_name,
76
+ presence: true,
77
+ format: /\A[a-zA-Z\d][a-zA-Z\d\-]*\z/,
78
+ length: { maximum: 54 }
79
+ end
80
+ end