staypuft 0.3.0 → 0.3.1
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 +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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 21289b770a15e38194b88261c2de8622344538f5
|
4
|
+
data.tar.gz: d53a1a5ca729733020a5da1e539cd3c46f6422e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 08d0914ace7e6cfeadcc1f618bba70a765a3ff02ed933ffb5272d169a8b8e96654f333dd33dc3342742f6ac862476b7be31bd9e2e82e7543264f26b26c8766de
|
7
|
+
data.tar.gz: dab396f6ac46c3ca10b0f614ed42671a88a7ecef079887ee47457b96e53e2e169fb5af26236b458a7bcace11785e98268894eebb0bac0e7482da75eaad5833e7
|
@@ -0,0 +1,32 @@
|
|
1
|
+
$(function() {
|
2
|
+
$("div.subnet-pull.active").draggable({
|
3
|
+
revert: 'invalid'
|
4
|
+
});
|
5
|
+
|
6
|
+
$("div.interface").droppable({
|
7
|
+
activeClass: "ui-state-default",
|
8
|
+
hoverClass: "ui-state-hover",
|
9
|
+
accept: "div.subnet-pull",
|
10
|
+
drop: function(event, ui) {
|
11
|
+
$.ajax({
|
12
|
+
type: 'POST',
|
13
|
+
url: ui.draggable.data('create-url'),
|
14
|
+
data: 'interface=' + $(this).data('interface'),
|
15
|
+
dataType: 'script'
|
16
|
+
});
|
17
|
+
}
|
18
|
+
});
|
19
|
+
$("#subnets").droppable({
|
20
|
+
activeClass: "ui-state-default",
|
21
|
+
hoverClass: "ui-state-hover",
|
22
|
+
accept: "div.subnet-pull.existing",
|
23
|
+
drop: function(event, ui) {
|
24
|
+
$.ajax({
|
25
|
+
type: 'DELETE',
|
26
|
+
url: ui.draggable.data('delete-url'),
|
27
|
+
data: 'interface=' + ui.draggable.closest('div.interface').data('interface'),
|
28
|
+
dataType: 'script'
|
29
|
+
});
|
30
|
+
}
|
31
|
+
});
|
32
|
+
});
|
@@ -11,6 +11,8 @@
|
|
11
11
|
// GO AFTER THE REQUIRES BELOW.
|
12
12
|
//
|
13
13
|
//= require_tree .
|
14
|
+
//= require jquery.ui.draggable
|
15
|
+
//= require jquery.ui.droppable
|
14
16
|
|
15
17
|
$(function () {
|
16
18
|
// Check all checkboxes in table
|
@@ -48,6 +50,22 @@ $(function () {
|
|
48
50
|
$(this).siblings('.hidden_password, .shown_password').toggleClass('hide');
|
49
51
|
});
|
50
52
|
|
53
|
+
$('#ceph_notification_dismissal').click(function(e) {
|
54
|
+
e.preventDefault();
|
55
|
+
$('.ceph_notification').toggleClass('hide');
|
56
|
+
var pathname = window.location.pathname
|
57
|
+
var id = pathname.substring(pathname.lastIndexOf('/') + 1)
|
58
|
+
var cephDeploymentNotification = readFromCookie();
|
59
|
+
cephDeploymentNotification[id] = true
|
60
|
+
$.cookie('ceph-deployment-notification', JSON.stringify(cephDeploymentNotification))
|
61
|
+
});
|
62
|
+
function readFromCookie() {
|
63
|
+
if (r = $.cookie('ceph-deployment-notification'))
|
64
|
+
return $.parseJSON(r);
|
65
|
+
else
|
66
|
+
return {};
|
67
|
+
}
|
68
|
+
|
51
69
|
var duration = 150;
|
52
70
|
|
53
71
|
showPasswords();
|
@@ -127,6 +145,18 @@ $(function () {
|
|
127
145
|
}
|
128
146
|
}
|
129
147
|
|
148
|
+
showCephNotification();
|
149
|
+
function showCephNotification() {
|
150
|
+
var cephDeploymentNotification = readFromCookie();
|
151
|
+
var pathname = window.location.pathname;
|
152
|
+
var id = pathname.substring(pathname.lastIndexOf('/') + 1);
|
153
|
+
if (cephDeploymentNotification !== null && cephDeploymentNotification !== undefined) {
|
154
|
+
if (cephDeploymentNotification[id]) {
|
155
|
+
$('.ceph_notification').addClass('hide');
|
156
|
+
}
|
157
|
+
}
|
158
|
+
}
|
159
|
+
|
130
160
|
if ($('.configuration').length > 0) {
|
131
161
|
$('.configuration').find('li').first().find('a')[0].click();
|
132
162
|
}
|
@@ -186,6 +216,13 @@ $(function () {
|
|
186
216
|
$(window).scrollTop( 0 );
|
187
217
|
}
|
188
218
|
|
219
|
+
$('.dynamic-submit').click(function() {
|
220
|
+
this.form.action = $(this).data('submit-to');
|
221
|
+
this.form.method = $(this).data('method');
|
222
|
+
this.form.submit();
|
223
|
+
return false;
|
224
|
+
})
|
225
|
+
|
189
226
|
var free_host_checkboxes = $('#free-hosts table input:checkbox');
|
190
227
|
free_host_checkboxes.click(function(){
|
191
228
|
$("#assign_hosts_modal").attr("disabled", !free_host_checkboxes.is(":checked"));
|
@@ -194,6 +231,7 @@ $(function () {
|
|
194
231
|
var assigned_host_checkboxes = $('#assigned-hosts table input:checkbox');
|
195
232
|
assigned_host_checkboxes.click(function(){
|
196
233
|
$("#unassign_hosts_button").attr("disabled", !assigned_host_checkboxes.is(":checked"));
|
234
|
+
$("#configure_networks_button").attr("disabled", !assigned_host_checkboxes.is(":checked"));
|
197
235
|
});
|
198
236
|
|
199
237
|
var deployed_host_checkboxes = $('#deployed-hosts table input:checkbox');
|
@@ -0,0 +1,40 @@
|
|
1
|
+
$(function() {
|
2
|
+
$("div.subnet-type-pull").draggable({
|
3
|
+
revert: 'invalid'
|
4
|
+
});
|
5
|
+
|
6
|
+
$("div.subnet-drop-zone").droppable({
|
7
|
+
activeClass: "ui-state-default",
|
8
|
+
hoverClass: "ui-state-hover",
|
9
|
+
accept: "div.subnet-type-pull",
|
10
|
+
drop: function(event, ui) {
|
11
|
+
if(ui.draggable.hasClass('new')) {
|
12
|
+
$.ajax({
|
13
|
+
type: 'POST',
|
14
|
+
url: ui.draggable.data('create-url'),
|
15
|
+
data: 'subnet_type_id=' + ui.draggable.data('subnet-type-id') + '&subnet_id=' + $(this).data('subnet-id'),
|
16
|
+
dataType: 'script'
|
17
|
+
})
|
18
|
+
} else {
|
19
|
+
$.ajax({
|
20
|
+
type: 'PUT',
|
21
|
+
url: ui.draggable.data('update-url'),
|
22
|
+
data: 'subnet_id=' + $(this).data('subnet-id'),
|
23
|
+
dataType: 'script'
|
24
|
+
})
|
25
|
+
}
|
26
|
+
}
|
27
|
+
});
|
28
|
+
$("#subnet_types").droppable({
|
29
|
+
activeClass: "ui-state-default",
|
30
|
+
hoverClass: "ui-state-hover",
|
31
|
+
accept: "div.subnet-type-pull.existing",
|
32
|
+
drop: function(event, ui) {
|
33
|
+
$.ajax({
|
34
|
+
type: 'DELETE',
|
35
|
+
url: ui.draggable.data('delete-url'),
|
36
|
+
dataType: 'script'
|
37
|
+
});
|
38
|
+
}
|
39
|
+
});
|
40
|
+
});
|
@@ -46,6 +46,10 @@
|
|
46
46
|
padding: 19px 36px;
|
47
47
|
background-color: #f5f5f5;
|
48
48
|
@include center-block;
|
49
|
+
|
50
|
+
table tbody td {
|
51
|
+
background-color: #fff;
|
52
|
+
}
|
49
53
|
}
|
50
54
|
|
51
55
|
.tabbed_side_nav_form{
|
@@ -80,7 +84,7 @@
|
|
80
84
|
}
|
81
85
|
|
82
86
|
.wizard {
|
83
|
-
width:
|
87
|
+
width: 900px;
|
84
88
|
display: block;
|
85
89
|
@include center-block;
|
86
90
|
}
|
@@ -101,6 +101,18 @@ span.editable, span.editable:hover {
|
|
101
101
|
overflow: auto;
|
102
102
|
}
|
103
103
|
|
104
|
+
|
105
|
+
.nav > li > a.roles_list {
|
106
|
+
padding: 0;
|
107
|
+
border: 1px solid #ddd;
|
108
|
+
& > div {
|
109
|
+
padding: 10px;
|
110
|
+
&:not(:first-child) {
|
111
|
+
border-left: 1px solid #ddd;
|
112
|
+
}
|
113
|
+
}
|
114
|
+
}
|
115
|
+
|
104
116
|
.association.well {
|
105
117
|
min-height: 500px;
|
106
118
|
margin-top: 50px;
|
@@ -111,3 +123,93 @@ span.editable, span.editable:hover {
|
|
111
123
|
}
|
112
124
|
}
|
113
125
|
}
|
126
|
+
|
127
|
+
$pull_line_height: 40px;
|
128
|
+
.subnet-type-pull, .empty-zone {
|
129
|
+
height: $pull_line_height;
|
130
|
+
line-height: $pull_line_height;
|
131
|
+
}
|
132
|
+
|
133
|
+
.subnet-type-pull, .subnet-pull, .empty-zone {
|
134
|
+
float: left;
|
135
|
+
min-width: 100px;
|
136
|
+
text-align: center;
|
137
|
+
margin-left: 10px;
|
138
|
+
background-color: #f5f5f5;
|
139
|
+
border-color: #000;
|
140
|
+
border-width: 1px;
|
141
|
+
}
|
142
|
+
|
143
|
+
.subnet-type-pull, .subnet-pull {
|
144
|
+
z-index: 1;
|
145
|
+
border-style: solid;
|
146
|
+
background-color: #ffffff;
|
147
|
+
}
|
148
|
+
|
149
|
+
.subnet-type-pull, .subnet-pull.active {
|
150
|
+
cursor: pointer;
|
151
|
+
background-color: #f5f5f5;
|
152
|
+
}
|
153
|
+
|
154
|
+
.subnet-pull {
|
155
|
+
height: $pull_line_height;
|
156
|
+
display: table;
|
157
|
+
padding-left: 5px;
|
158
|
+
padding-right: 5px;
|
159
|
+
margin-top: 10px;
|
160
|
+
|
161
|
+
.name {
|
162
|
+
font-weight: bold;
|
163
|
+
}
|
164
|
+
|
165
|
+
.content {
|
166
|
+
display: table-cell;
|
167
|
+
vertical-align: middle;
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
.subnet-pull.virtual {
|
172
|
+
background-color: #d7f5f5;
|
173
|
+
}
|
174
|
+
|
175
|
+
div.cleared {
|
176
|
+
clear: left;
|
177
|
+
}
|
178
|
+
|
179
|
+
.empty-zone {
|
180
|
+
border-style: dashed;
|
181
|
+
}
|
182
|
+
|
183
|
+
.subnet-drop-zone {
|
184
|
+
border: 1px solid black;
|
185
|
+
height: 90px;
|
186
|
+
margin-bottom: 10px;
|
187
|
+
|
188
|
+
.name {
|
189
|
+
margin-left: 5px;
|
190
|
+
margin-top: 5px;
|
191
|
+
margin-bottom: 10px;
|
192
|
+
font-weight: bold;
|
193
|
+
}
|
194
|
+
}
|
195
|
+
|
196
|
+
div.interface {
|
197
|
+
margin-bottom: 10px;
|
198
|
+
|
199
|
+
div.identifier {
|
200
|
+
float: left;
|
201
|
+
width: 70px;
|
202
|
+
border: 1px solid #000;
|
203
|
+
height: $pull_line_height + 20px;
|
204
|
+
line-height: $pull_line_height + 20px;
|
205
|
+
text-align: center;
|
206
|
+
font-weight: bold;
|
207
|
+
}
|
208
|
+
|
209
|
+
div.subnet-drop-zones {
|
210
|
+
border: 1px solid #000;
|
211
|
+
padding-top: 10px;
|
212
|
+
width: 100%;
|
213
|
+
height: $pull_line_height + 20px;
|
214
|
+
}
|
215
|
+
}
|
@@ -190,6 +190,11 @@ module Staypuft
|
|
190
190
|
# root_pass is not copied for some reason
|
191
191
|
host.root_pass = hostgroup.root_pass
|
192
192
|
|
193
|
+
# clear all virtual devices that may have been created during previous assignment
|
194
|
+
host.clean_vlan_interfaces
|
195
|
+
# by default foreman will try to manage all NICs unless user disables manually after assignment
|
196
|
+
host.make_all_interfaces_managed
|
197
|
+
|
193
198
|
# I do not why but the final save! adds following condytion to the update SQL command
|
194
199
|
# "WHERE "hosts"."type" IN ('Host::Managed') AND "hosts"."id" = 283"
|
195
200
|
# which will not find the record since it's still Host::Discovered.
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Staypuft
|
2
|
+
class InterfaceAssignmentsController < Staypuft::ApplicationController
|
3
|
+
def index
|
4
|
+
@deployment = Deployment.find(params[:deployment_id])
|
5
|
+
@hosts = Host::Managed.where(:id => params[:host_ids]).includes(:interfaces)
|
6
|
+
@subnets = @deployment.subnets.uniq
|
7
|
+
@host = @hosts.first
|
8
|
+
@interfaces = @host ? @host.interfaces.where("type <> 'Nic::BMC'").order(:identifier).physical : []
|
9
|
+
|
10
|
+
errors = {}
|
11
|
+
@hosts.each do |host|
|
12
|
+
host_errors = compare(host, @host)
|
13
|
+
errors[host.name] = host_errors.join(' and ') if host_errors.present?
|
14
|
+
end
|
15
|
+
|
16
|
+
if errors.present?
|
17
|
+
flash[:error] = errors.map{ |k, v| "#{k}: #{v}" }.join('<br />')
|
18
|
+
redirect_to deployment_path(@deployment)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def create
|
23
|
+
@errors = {}
|
24
|
+
@deployment = Deployment.find(params[:deployment_id])
|
25
|
+
@hosts = Host::Managed.where(:id => params[:host_ids])
|
26
|
+
@hosts.each do |host|
|
27
|
+
@interface = host.interfaces.find_by_identifier(params[:interface]) || host
|
28
|
+
@subnet = Subnet.find(params[:subnet_id])
|
29
|
+
@assigner = InterfaceAssigner.new(@deployment, @interface, @subnet)
|
30
|
+
@assigner.assign
|
31
|
+
@errors[host.name] = @assigner.errors if @assigner.errors.present?
|
32
|
+
end
|
33
|
+
@saved = @errors.blank?
|
34
|
+
end
|
35
|
+
|
36
|
+
def destroy
|
37
|
+
@errors = {}
|
38
|
+
@deployment = Deployment.find(params[:deployment_id])
|
39
|
+
@hosts = Host::Managed.where(:id => params[:host_ids])
|
40
|
+
@hosts.each do |host|
|
41
|
+
@interface = host.interfaces.find_by_identifier(params[:interface]) || host
|
42
|
+
@subnet = Subnet.find(params[:subnet_id])
|
43
|
+
@assigner = InterfaceAssigner.new(@deployment, @interface, @subnet)
|
44
|
+
@assigner.unassign
|
45
|
+
@errors[host.name] = @assigner.errors if @assigner.errors.present?
|
46
|
+
end
|
47
|
+
@destroyed = @errors.blank?
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def compare(comparing, original)
|
53
|
+
errors = []
|
54
|
+
# primary interfaces, we don't check subnet_id since it's always PXE subnet
|
55
|
+
if comparing.primary_interface != original.primary_interface
|
56
|
+
errors.push _('does not have interfaces with same names')
|
57
|
+
return errors
|
58
|
+
end
|
59
|
+
|
60
|
+
# other interfaces
|
61
|
+
comparing = get_interfaces_to_compare(comparing)
|
62
|
+
original = get_interfaces_to_compare(original)
|
63
|
+
errors.push _('does not have same amount of interfaces') and return errors if comparing.size != original.size
|
64
|
+
comparing.each do |interface|
|
65
|
+
original_interface = original.select { |i| i.identifier == interface.identifier }.first
|
66
|
+
errors.push _('does not have interfaces with same names') and return errors if original_interface.nil?
|
67
|
+
errors.push _('has different subnet assignment on interface %s') % interface.identifier if interface.subnet_id != original_interface.subnet_id
|
68
|
+
end
|
69
|
+
errors
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_interfaces_to_compare(host)
|
73
|
+
host.interfaces.where("type <> 'Nic::BMC'").order(:identifier)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Staypuft
|
2
2
|
class StepsController < Staypuft::ApplicationController
|
3
3
|
include Wicked::Wizard
|
4
|
-
steps :deployment_settings, :services_overview, :services_configuration
|
4
|
+
steps :deployment_settings, :network_configuration, :services_overview, :services_configuration
|
5
5
|
|
6
6
|
before_filter :get_deployment
|
7
7
|
|
@@ -13,6 +13,8 @@ module Staypuft
|
|
13
13
|
if !@deployment.ha? && @deployment.cinder.lvm_ptable.nil?
|
14
14
|
flash[:warning] = "Missing Partition Table 'LVM with cinder-volumes', LVM cinder backend won't work."
|
15
15
|
end
|
16
|
+
when :network_configuration
|
17
|
+
@subnets = Subnet.search_for(params[:search], :order => params[:order]).includes(:domains, :dhcp).paginate :page => params[:page]
|
16
18
|
when :services_configuration
|
17
19
|
@services_map = [:nova, :neutron, :glance, :cinder]
|
18
20
|
end
|
@@ -30,6 +32,15 @@ module Staypuft
|
|
30
32
|
@deployment.passwords.attributes = params[:staypuft_deployment].delete(:passwords)
|
31
33
|
@deployment.attributes = params[:staypuft_deployment]
|
32
34
|
|
35
|
+
# we don't care too much whether pxe network was detected or all typings were saved since it's
|
36
|
+
# just a helper for user to have all types preassigned to pxe network
|
37
|
+
pxe_network = Subnet.where('dhcp_id IS NOT NULL').first
|
38
|
+
if pxe_network
|
39
|
+
@deployment.unassigned_subnet_types.each do |type|
|
40
|
+
@deployment.subnet_typings.new(:subnet_id => pxe_network.id, :subnet_type_id => type.id).save
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
33
44
|
when :services_overview
|
34
45
|
@deployment.form_step = Deployment::STEP_OVERVIEW
|
35
46
|
|
@@ -41,6 +52,9 @@ module Staypuft
|
|
41
52
|
@deployment.send(service).attributes = params[:staypuft_deployment].delete(service)
|
42
53
|
end
|
43
54
|
end
|
55
|
+
when :network_configuration
|
56
|
+
@deployment.form_step = Deployment::STEP_NETWORKING
|
57
|
+
@subnets = Subnet.search_for(params[:search], :order => params[:order]).includes(:domains, :dhcp).paginate :page => params[:page]
|
44
58
|
else
|
45
59
|
raise 'unknown step'
|
46
60
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Staypuft
|
2
|
+
class SubnetTypingsController < ActionController::Base
|
3
|
+
def create
|
4
|
+
@deployment = Deployment.find(params[:deployment_id])
|
5
|
+
@subnet_type = SubnetType.find(params[:subnet_type_id])
|
6
|
+
@subnet = Subnet.find(params[:subnet_id])
|
7
|
+
check_for_existing_assignments
|
8
|
+
@subnet_typing = @deployment.subnet_typings.new(:subnet_id => @subnet.id, :subnet_type_id => @subnet_type.id)
|
9
|
+
@saved = @subnet_typing.save
|
10
|
+
end
|
11
|
+
|
12
|
+
def update
|
13
|
+
@subnet_typing = SubnetTyping.find(params[:id])
|
14
|
+
@deployment = @subnet_typing.deployment
|
15
|
+
@subnet_type = @subnet_typing.subnet_type
|
16
|
+
@subnet = Subnet.find(params[:subnet_id])
|
17
|
+
check_for_existing_assignments
|
18
|
+
@subnet_typing.subnet = @subnet
|
19
|
+
@saved = @subnet_typing.save
|
20
|
+
end
|
21
|
+
|
22
|
+
def destroy
|
23
|
+
@subnet_typing = SubnetTyping.find(params[:id])
|
24
|
+
@deployment = @subnet_typing.deployment
|
25
|
+
@subnet = @subnet_typing.subnet
|
26
|
+
check_for_existing_assignments
|
27
|
+
@subnet_type = @subnet_typing.subnet_type
|
28
|
+
@destroyed = @subnet_typing.destroy
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def check_for_existing_assignments
|
34
|
+
existing = @deployment.hosts.includes(:interfaces).any? do |h|
|
35
|
+
h.subnet_id == @subnet.id || h.interfaces.any? { |i| i.subnet_id == @subnet.id }
|
36
|
+
end
|
37
|
+
if existing
|
38
|
+
@warn = _('Some hosts interfaces were already assigned to this subnet, check interface assignment before deploying!')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -4,6 +4,7 @@ module Staypuft
|
|
4
4
|
wizard_header(
|
5
5
|
step,
|
6
6
|
_("Deployment Settings"),
|
7
|
+
_("Network Configuration"),
|
7
8
|
_("Services Overview"),
|
8
9
|
_("Services Configuration")
|
9
10
|
)
|
@@ -33,9 +34,7 @@ module Staypuft
|
|
33
34
|
style ="label-default"
|
34
35
|
short = s_("Discovered|D")
|
35
36
|
label = _('Discovered Host')
|
36
|
-
|
37
|
-
hash_for_method = [:hash_for_discovered_host_path, :hash_for_discover_path].find { |m| respond_to? m }
|
38
|
-
path = send hash_for_method, host
|
37
|
+
path = hash_for_discovered_host_path(host)
|
39
38
|
else
|
40
39
|
style = 'label-warning'
|
41
40
|
short = s_("Error|E")
|
@@ -48,6 +47,22 @@ module Staypuft
|
|
48
47
|
:class => "label label-light " + style,
|
49
48
|
:"data-original-title" => _(label) }) + link_to(trunc(" #{host}", 32), path)
|
50
49
|
end
|
50
|
+
|
51
|
+
def host_nics(host)
|
52
|
+
host.interfaces_identifiers.compact.sort.join(tag(:br)).html_safe
|
53
|
+
end
|
54
|
+
|
55
|
+
def is_pxe?(deployment, subnet)
|
56
|
+
subnet_typings(deployment, subnet).any? { |t| t.subnet_type.name == Staypuft::SubnetType::PXE }
|
57
|
+
end
|
58
|
+
|
59
|
+
def subnet_types(deployment, subnet)
|
60
|
+
subnet_typings(deployment, subnet).map { |t| h(t.subnet_type.name) }.join(' + ')
|
61
|
+
end
|
62
|
+
|
63
|
+
def subnet_typings(deployment, subnet)
|
64
|
+
deployment.subnet_typings.where(:subnet_id => subnet.id).includes(:subnet_type)
|
65
|
+
end
|
51
66
|
end
|
52
67
|
|
53
68
|
end
|
@@ -26,12 +26,49 @@ module Actions
|
|
26
26
|
# hostgroup.hosts returns already converted hosts from Host::Discovered with build flag
|
27
27
|
# set to false so they are not built when assigned to the hostgroup in wizard
|
28
28
|
# run Hostgroup's Hosts filtered by hosts
|
29
|
-
|
29
|
+
host_list = hostgroup.hosts & hosts
|
30
|
+
orchestration_mode = hostgroup.role.orchestration unless hostgroup.role.nil?
|
31
|
+
|
32
|
+
case orchestration_mode
|
33
|
+
when ::Staypuft::Role::ORCHESTRATION_CONCURRENT
|
34
|
+
deploy_concurrently(host_list)
|
35
|
+
when ::Staypuft::Role::ORCHESTRATION_SERIAL
|
36
|
+
deploy_serially(host_list)
|
37
|
+
when ::Staypuft::Role::ORCHESTRATION_LEADER
|
38
|
+
deploy_leader_first(host_list)
|
39
|
+
else
|
40
|
+
deploy_concurrently(host_list)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def deploy_concurrently(hosts)
|
45
|
+
hosts.each do |host|
|
30
46
|
# planned in concurrence
|
31
47
|
plan_action Host::Deploy, host
|
32
48
|
end
|
33
49
|
end
|
34
50
|
|
51
|
+
def deploy_serially(hosts)
|
52
|
+
sequence do
|
53
|
+
hosts.each do |host|
|
54
|
+
plan_action Host::Deploy, host
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def deploy_leader_first(hosts)
|
60
|
+
first_host = hosts.shift
|
61
|
+
sequence do
|
62
|
+
#deploy first host, then deploy remainder in parallel
|
63
|
+
plan_action Host::Deploy, first_host unless first_host.nil?
|
64
|
+
concurrence do
|
65
|
+
hosts.each do |host|
|
66
|
+
plan_action Host::Deploy, host
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
35
72
|
def humanized_input
|
36
73
|
input[:name]
|
37
74
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Staypuft
|
2
|
+
class NetworkQuery
|
3
|
+
|
4
|
+
def initialize(deployment)
|
5
|
+
@deployment = deployment
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
def interface_hash_for_host(host, subnet_type_name)
|
10
|
+
subnet_type = @deployment.layout.subnet_types.where(:name=> subnet_type_name).first
|
11
|
+
|
12
|
+
# raise error if no subnet with this name is assigned to this layout
|
13
|
+
if subnet_type.nil?
|
14
|
+
raise ArgumentError, "Invalid subnet type '#{subnet_type_name}' for layout of this deployment #{@deployment.name}"
|
15
|
+
end
|
16
|
+
|
17
|
+
subnet_typing = @deployment.subnet_typings.where(:subnet_type_id => subnet_type.id).first
|
18
|
+
# if this subnet type isn't assigned to a subnet for this deployment, return nil
|
19
|
+
return nil if subnet_typing.nil?
|
20
|
+
subnet = subnet_typing.subnet
|
21
|
+
|
22
|
+
secondary_iface = host.interfaces.where(:subnet_id => subnet.id).first
|
23
|
+
# check for primary interface
|
24
|
+
if (host.subnet_id == subnet.id)
|
25
|
+
{:subnet => host.subnet, :ip => host.ip,
|
26
|
+
:interface => host.primary_interface, :mac => host.mac }
|
27
|
+
elsif !iface.nil?
|
28
|
+
{:subnet => secondary_iface.subnet, :ip => secondary_iface.ip,
|
29
|
+
:interface => secondary_iface.name, :mac => secondary_iface.mac }
|
30
|
+
else
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|