bandshell 0.0.20 → 0.0.21

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,31 +3,31 @@ require 'tempfile'
3
3
  # Functions for dealing with the live image
4
4
  # (where it's mounted, if it's read-only, etc)
5
5
  module Bandshell
6
- module LiveImage
7
- def self.mountpoint
8
- if File.exist? '/etc/concerto/medium_path'
9
- IO.read('/etc/concerto/medium_path').chomp
10
- else
11
- # sane default for Debian Live-based systems
12
- # (as of 2013-04-24)
13
- '/lib/live/mount/medium'
14
- end
15
- end
6
+ module LiveImage
7
+ def self.mountpoint
8
+ if File.exist? '/etc/concerto/medium_path'
9
+ IO.read('/etc/concerto/medium_path').chomp
10
+ else
11
+ # sane default for Debian Live-based systems
12
+ # (as of 2013-04-24)
13
+ '/lib/live/mount/medium'
14
+ end
15
+ end
16
16
 
17
- def self.readonly?
18
- # on a readonly file system this will fail
19
- if not File.exist? self.mountpoint
20
- true
21
- else
22
- begin
23
- f = Tempfile.new('test', self.mountpoint)
24
- f.close!
25
- false
26
- rescue
27
- # if the tempfile creation bombs we assume readonly
28
- true
29
- end
30
- end
31
- end
32
- end
17
+ def self.readonly?
18
+ # on a readonly file system this will fail
19
+ if not File.exist? self.mountpoint
20
+ true
21
+ else
22
+ begin
23
+ f = Tempfile.new('test', self.mountpoint)
24
+ f.close!
25
+ false
26
+ rescue
27
+ # if the tempfile creation bombs we assume readonly
28
+ true
29
+ end
30
+ end
31
+ end
32
+ end
33
33
  end
@@ -20,523 +20,524 @@ require 'bandshell/config_store'
20
20
  # files such as wpa_supplicant.conf, resolv.conf etc.
21
21
 
22
22
  class Module
23
- # Get the name of a class/module and strip off any leading modules.
24
- # This is useful in determining arguments for Module#const_get.
25
- def basename
26
- name.gsub(/^.*::/, '')
27
- end
23
+ # Get the name of a class/module and strip off any leading modules.
24
+ # This is useful in determining arguments for Module#const_get.
25
+ def basename
26
+ name.gsub(/^.*::/, '')
27
+ end
28
28
  end
29
29
 
30
30
  module Bandshell
31
- # The Debian interfaces configuration file we are going to write out.
32
- INTERFACES_FILE='/etc/network/interfaces'
33
-
34
- # Some useful interface operations.
35
- class Interface
36
- # Wrap an interface name (eth0, wlan0 etc) with some useful operations.
37
- def initialize(name)
38
- @name = name
39
- end
40
-
41
- # Get the name of the interface as a string.
42
- attr_reader :name
43
-
44
- # Get the (first) IPv4 address assigned to the interface.
45
- # Return "0.0.0.0" if we don't have any v4 addresses.
46
- def ip
47
- if ifconfig =~ /inet addr:([0-9.]+)/
48
- $1
49
- else
50
- "0.0.0.0"
51
- end
52
- end
31
+ # The Debian interfaces configuration file we are going to write out.
32
+ INTERFACES_FILE='/etc/network/interfaces'
33
+
34
+ # Some useful interface operations.
35
+ class Interface
36
+ # Wrap an interface name (eth0, wlan0 etc) with some useful operations.
37
+ def initialize(name)
38
+ @name = name
39
+ end
53
40
 
54
- # Get the physical (mac, ethernet) address of the interface.
55
- def mac
56
- File.open("/sys/class/net/#{@name}/address") do |f|
57
- f.read.chomp
58
- end
59
- end
41
+ # Get the name of the interface as a string.
42
+ attr_reader :name
43
+
44
+ # Get the (first) IPv4 address assigned to the interface.
45
+ # Return "0.0.0.0" if we don't have any v4 addresses.
46
+ def ip
47
+ if ifconfig =~ /inet addr:([0-9.]+)/
48
+ $1
49
+ else
50
+ "0.0.0.0"
51
+ end
52
+ end
60
53
 
61
- def up
62
- system("/sbin/ifconfig #{@name} up")
63
- end
54
+ # Get the physical (mac, ethernet) address of the interface.
55
+ def mac
56
+ File.open("/sys/class/net/#{@name}/address") do |f|
57
+ f.read.chomp
58
+ end
59
+ end
64
60
 
65
- def down
66
- system("/sbin/ifconfig #{@name} down")
67
- end
61
+ def up
62
+ system("/sbin/ifconfig #{@name} up")
63
+ end
68
64
 
69
- def ifup
70
- system("/sbin/ifup #{@name}")
71
- end
65
+ def down
66
+ system("/sbin/ifconfig #{@name} down")
67
+ end
72
68
 
73
- def ifdown
74
- system("/sbin/ifdown #{@name}")
75
- end
69
+ def ifup
70
+ system("/sbin/ifup #{@name}")
71
+ end
76
72
 
77
- def up?
78
- if ifconfig =~ /UP/
79
- true
80
- else
81
- false
82
- end
83
- end
73
+ def ifdown
74
+ system("/sbin/ifdown #{@name}")
75
+ end
84
76
 
85
- def medium_present?
86
- brought_up = false
87
- result = false
88
-
89
- if not up?
90
- brought_up = true
91
- up
92
- sleep 10
93
- end
94
-
95
- if ifconfig =~ /RUNNING/
96
- result = true
97
- end
98
-
99
- if brought_up
100
- down
101
- end
102
-
103
- result
104
- end
105
- private
106
- def ifconfig
107
- `/sbin/ifconfig #{@name}`
108
- end
77
+ def up?
78
+ if ifconfig =~ /UP/
79
+ true
80
+ else
81
+ false
82
+ end
109
83
  end
110
84
 
111
- # (Instance) methods that must be defined by all connection and
112
- # addressing method classes
113
- #
114
- # creation and serialization:
115
- #
116
- # initialize(args={}): Create a new instance. When unserializing the args
117
- # hash created during serialization is passed in.
118
- #
119
- # args: return a hash of data needed to reconstruct the instance. This
120
- # hash will be passed to initialize() when unserializing.
121
- #
122
- # OS-level configuration:
123
- #
124
- # write_configs: Write out any additional configuration files needed
125
- # (e.g. resolv.conf, wpa_supplicant.conf, ...)
126
- #
127
- # config_interface_name (only for connection methods): return the name of
128
- # the physical interface to be used for the connection
129
- #
130
- # addressing_type (only for addressing methods): return the name of the
131
- # addressing method (dhcp, static, manual...) to be used in the Debian
132
- # network configuration file /etc/network/interfaces.
133
- #
134
- # interfaces_lines: an array of strings representing lines to be added
135
- # to the /etc/network/interfaces file after the line naming the interface.
136
- #
137
- # Stuff for the Web interface:
138
- #
139
- # safe_assign: return an array of symbols representing fields the user
140
- # should be allowed to modify.
141
- #
142
- # validate: check that the internal configuration is at least somewhat
143
- # consistent and stands a chance of working; throw exception if not
144
- # (FIXME! need a better error handling mechanism)
145
- #
146
- # and attr_accessors for everything the web interface
147
- # should be able to assign to.
148
- #
149
- # Everyone must define a class method self.description as well.
150
- # This returns a string that is displayed in the web interface dropdowns
151
- # because using plain class identifiers there doesn't look good.
152
- # This should be something short like "Wired Connection".
153
-
154
- # Layer 2 connection via wired media.
155
- # We will look for wired interfaces that have media connected,
156
- # or use an interface chosen by the user via the args. There's
157
- # nothing extra to be contributed to the interfaces file besides
158
- # the name of the interface to be used.
159
- class WiredConnection
160
- def initialize(args={})
161
- if args['interface_name']
162
- @interface_name = args['interface_name']
163
- end
164
- end
85
+ def medium_present?
86
+ brought_up = false
87
+ result = false
165
88
 
166
- def write_configs
167
- # We don't need any.
168
- end
89
+ if not up?
90
+ brought_up = true
91
+ up
92
+ sleep 10
93
+ end
169
94
 
170
- def config_interface_name
171
- if @interface_name && @interface_name.length > 0
172
- # the user has specified an interface to use
173
- @interface_name
174
- else
175
- # scan for the first wired interface that has media
176
- scan_interfaces
177
- end
178
- end
95
+ if ifconfig =~ /RUNNING/
96
+ result = true
97
+ end
179
98
 
180
- # If interface_name is something other than nil or the empty string,
181
- # we will override the automatic detection and use that interface.
182
- attr_accessor :interface_name
99
+ if brought_up
100
+ down
101
+ end
183
102
 
184
- def safe_assign
185
- [ :interface_name ]
186
- end
103
+ result
104
+ end
187
105
 
188
- def args
189
- {
190
- 'interface_name' => @interface_name
191
- }
192
- end
193
-
194
- def interfaces_lines
195
- []
196
- end
106
+ private
107
+ def ifconfig
108
+ `/sbin/ifconfig #{@name}`
109
+ end
110
+ end
111
+
112
+ # (Instance) methods that must be defined by all connection and
113
+ # addressing method classes
114
+ #
115
+ # creation and serialization:
116
+ #
117
+ # initialize(args={}): Create a new instance. When unserializing the args
118
+ # hash created during serialization is passed in.
119
+ #
120
+ # args: return a hash of data needed to reconstruct the instance. This
121
+ # hash will be passed to initialize() when unserializing.
122
+ #
123
+ # OS-level configuration:
124
+ #
125
+ # write_configs: Write out any additional configuration files needed
126
+ # (e.g. resolv.conf, wpa_supplicant.conf, ...)
127
+ #
128
+ # config_interface_name (only for connection methods): return the name of
129
+ # the physical interface to be used for the connection
130
+ #
131
+ # addressing_type (only for addressing methods): return the name of the
132
+ # addressing method (dhcp, static, manual...) to be used in the Debian
133
+ # network configuration file /etc/network/interfaces.
134
+ #
135
+ # interfaces_lines: an array of strings representing lines to be added
136
+ # to the /etc/network/interfaces file after the line naming the interface.
137
+ #
138
+ # Stuff for the Web interface:
139
+ #
140
+ # safe_assign: return an array of symbols representing fields the user
141
+ # should be allowed to modify.
142
+ #
143
+ # validate: check that the internal configuration is at least somewhat
144
+ # consistent and stands a chance of working; throw exception if not
145
+ # (FIXME! need a better error handling mechanism)
146
+ #
147
+ # and attr_accessors for everything the web interface
148
+ # should be able to assign to.
149
+ #
150
+ # Everyone must define a class method self.description as well.
151
+ # This returns a string that is displayed in the web interface dropdowns
152
+ # because using plain class identifiers there doesn't look good.
153
+ # This should be something short like "Wired Connection".
154
+
155
+ # Layer 2 connection via wired media.
156
+ # We will look for wired interfaces that have media connected,
157
+ # or use an interface chosen by the user via the args. There's
158
+ # nothing extra to be contributed to the interfaces file besides
159
+ # the name of the interface to be used.
160
+ class WiredConnection
161
+ def initialize(args={})
162
+ if args['interface_name']
163
+ @interface_name = args['interface_name']
164
+ end
165
+ end
197
166
 
198
- def validate
199
- if @interface_name != ''
200
- if self.class.interfaces.find {
201
- |iface| iface.name == @interface_name
202
- }.nil?
203
- fail "The interface doesn't exist on the system"
204
- end
205
- end
206
- end
167
+ def write_configs
168
+ # We don't need any.
169
+ end
207
170
 
208
- # Try to find all wired interfaces on the system.
209
- def self.interfaces
210
- # This is somewhat Linux specific and may miss some oddballs.
211
- devices = Dir.glob('/sys/class/net/eth*')
212
- devices.map { |d| Interface.new(File.basename(d)) }
213
- end
171
+ def config_interface_name
172
+ if @interface_name && @interface_name.length > 0
173
+ # the user has specified an interface to use
174
+ @interface_name
175
+ else
176
+ # scan for the first wired interface that has media
177
+ scan_interfaces
178
+ end
179
+ end
214
180
 
215
- def self.description
216
- "Wired connection"
217
- end
181
+ # If interface_name is something other than nil or the empty string,
182
+ # we will override the automatic detection and use that interface.
183
+ attr_accessor :interface_name
218
184
 
219
- private
220
- # Find the first wired interface with medium present. If none
221
- # is found default to eth0.
222
- def scan_interfaces
223
- first_with_medium = self.class.interfaces.find {
224
- |iface| iface.medium_present?
225
- }
226
-
227
- if first_with_medium
228
- first_with_medium.name
229
- else
230
- # if we get here no interface was found with a cable attached
231
- # default to eth0 and hope for the best
232
- STDERR.puts "warning: no suitable interface found, using eth0"
233
- 'eth0'
234
- end
235
- end
185
+ def safe_assign
186
+ [ :interface_name ]
236
187
  end
237
188
 
238
- # 802.11* unencrypted wireless connections.
239
- # These are managed by wpa_supplicant on Debian so we need to create its
240
- # configuration file and link it to the interfaces file.
241
- class WirelessConnection
242
- def initialize(args={})
243
- @ssid = args['ssid'] || ''
244
- @interface_name = args['interface_name'] if args['interface_name']
245
- @wpa_config_file = '/tmp/wpa_supplicant.concerto.conf'
246
- end
189
+ def args
190
+ {
191
+ 'interface_name' => @interface_name
192
+ }
193
+ end
247
194
 
248
- attr_accessor :ssid, :interface_name
249
-
250
- def config_interface_name
251
- # If the user has requested a specific interface, use it.
252
- # Otherwise, just pick the first wlan interface, assuming
253
- # it works and all wlan interfaces have approximately equal
254
- # reception. When this assumption is wrong the user must force.
255
- if @interface_name && @interface_name != ''
256
- @interface_name
257
- else
258
- self.class.interfaces[0].name
259
- end
260
- end
195
+ def interfaces_lines
196
+ []
197
+ end
261
198
 
262
- def validate
263
- if @ssid == ''
264
- fail "Need SSID for wireless connection"
265
- end
199
+ def validate
200
+ if @interface_name != ''
201
+ if self.class.interfaces.find {
202
+ |iface| iface.name == @interface_name
203
+ }.nil?
204
+ fail "The interface doesn't exist on the system"
266
205
  end
206
+ end
207
+ end
267
208
 
268
- def safe_assign
269
- [ :ssid, :interface_name ]
270
- end
209
+ # Try to find all wired interfaces on the system.
210
+ def self.interfaces
211
+ # This is somewhat Linux specific and may miss some oddballs.
212
+ devices = Dir.glob('/sys/class/net/eth*')
213
+ devices.map { |d| Interface.new(File.basename(d)) }
214
+ end
271
215
 
272
- def write_configs
273
- # Write a wpa_supplicant.conf file for an unsecured network.
274
- File.open(@wpa_config_file, 'w') do |wpaconf|
275
- # long lines, sorry!
276
- wpaconf.puts "ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev"
277
- wpaconf.puts "network={"
278
- wpaconf.puts "ssid=\"#{@ssid}\""
279
- wpaconf.puts "scan_ssid=1"
280
- wpaconf.puts "key_mgmt=NONE"
281
- wpaconf.puts "}"
282
- end
283
- end
216
+ def self.description
217
+ "Wired connection"
218
+ end
284
219
 
285
- def interfaces_lines
286
- # This links the wpa config to the interfaces file.
287
- ["wpa-conf #{@wpa_config_file}"]
288
- end
220
+ private
221
+ # Find the first wired interface with medium present. If none
222
+ # is found default to eth0.
223
+ def scan_interfaces
224
+ first_with_medium = self.class.interfaces.find {
225
+ |iface| iface.medium_present?
226
+ }
227
+
228
+ if first_with_medium
229
+ first_with_medium.name
230
+ else
231
+ # if we get here no interface was found with a cable attached
232
+ # default to eth0 and hope for the best
233
+ STDERR.puts "warning: no suitable interface found, using eth0"
234
+ 'eth0'
235
+ end
236
+ end
237
+ end
238
+
239
+ # 802.11* unencrypted wireless connections.
240
+ # These are managed by wpa_supplicant on Debian so we need to create its
241
+ # configuration file and link it to the interfaces file.
242
+ class WirelessConnection
243
+ def initialize(args={})
244
+ @ssid = args['ssid'] || ''
245
+ @interface_name = args['interface_name'] if args['interface_name']
246
+ @wpa_config_file = '/tmp/wpa_supplicant.concerto.conf'
247
+ end
289
248
 
290
- def args
291
- {
292
- 'interface_name' => @interface_name,
293
- 'ssid' => @ssid
294
- }
295
- end
249
+ attr_accessor :ssid, :interface_name
250
+
251
+ def config_interface_name
252
+ # If the user has requested a specific interface, use it.
253
+ # Otherwise, just pick the first wlan interface, assuming
254
+ # it works and all wlan interfaces have approximately equal
255
+ # reception. When this assumption is wrong the user must force.
256
+ if @interface_name && @interface_name != ''
257
+ @interface_name
258
+ else
259
+ self.class.interfaces[0].name
260
+ end
261
+ end
296
262
 
297
- def self.description
298
- "Wireless connection (no encryption)"
299
- end
263
+ def validate
264
+ if @ssid == ''
265
+ fail "Need SSID for wireless connection"
266
+ end
267
+ end
300
268
 
301
- def self.interfaces
302
- # Again this is not guaranteed to be a catch all.
303
- devices = Dir.glob('/sys/class/net/{ath,wlan}*')
304
- devices.map { |d| Interface.new(File.basename(d)) }
305
- end
269
+ def safe_assign
270
+ [ :ssid, :interface_name ]
306
271
  end
307
272
 
308
- # Static IPv4 addressing.
309
- # We use the IPAddress gem to validate that the address information
310
- # is vaguely correct (weeding out errors like the gateway
311
- # being on another subnet)
312
- class StaticAddressing
313
- def initialize(args={})
314
- @nameservers = args['nameservers']
315
- @address = args['address']
316
- @netmask = args['netmask']
317
- @gateway = args['gateway']
318
- end
273
+ def write_configs
274
+ # Write a wpa_supplicant.conf file for an unsecured network.
275
+ File.open(@wpa_config_file, 'w') do |wpaconf|
276
+ # long lines, sorry!
277
+ wpaconf.puts "ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev"
278
+ wpaconf.puts "network={"
279
+ wpaconf.puts "ssid=\"#{@ssid}\""
280
+ wpaconf.puts "scan_ssid=1"
281
+ wpaconf.puts "key_mgmt=NONE"
282
+ wpaconf.puts "}"
283
+ end
284
+ end
319
285
 
320
- def addressing_type
321
- 'static'
322
- end
286
+ def interfaces_lines
287
+ # This links the wpa config to the interfaces file.
288
+ ["wpa-conf #{@wpa_config_file}"]
289
+ end
323
290
 
324
- def args
325
- {
326
- 'address' => @address,
327
- 'netmask' => @netmask,
328
- 'gateway' => @gateway,
329
- 'nameservers' => @nameservers
330
- }
331
- end
291
+ def args
292
+ {
293
+ 'interface_name' => @interface_name,
294
+ 'ssid' => @ssid
295
+ }
296
+ end
332
297
 
333
- def interfaces_lines
334
- [
335
- "address #{@address}",
336
- "netmask #{@netmask}",
337
- "gateway #{@gateway}"
338
- ]
339
- end
298
+ def self.description
299
+ "Wireless connection (no encryption)"
300
+ end
340
301
 
302
+ def self.interfaces
303
+ # Again this is not guaranteed to be a catch all.
304
+ devices = Dir.glob('/sys/class/net/{ath,wlan}*')
305
+ devices.map { |d| Interface.new(File.basename(d)) }
306
+ end
307
+ end
308
+
309
+ # Static IPv4 addressing.
310
+ # We use the IPAddress gem to validate that the address information
311
+ # is vaguely correct (weeding out errors like the gateway
312
+ # being on another subnet)
313
+ class StaticAddressing
314
+ def initialize(args={})
315
+ @nameservers = args['nameservers']
316
+ @address = args['address']
317
+ @netmask = args['netmask']
318
+ @gateway = args['gateway']
319
+ end
341
320
 
342
- def write_configs
343
- File.open('/etc/resolv.conf','w') do |resolvconf|
344
- @nameservers.each do |nameserver|
345
- resolvconf.puts("nameserver #{nameserver}");
346
- end
347
- end
348
- end
321
+ def addressing_type
322
+ 'static'
323
+ end
349
324
 
350
- def self.description
351
- "Static Addressing"
352
- end
325
+ def args
326
+ {
327
+ 'address' => @address,
328
+ 'netmask' => @netmask,
329
+ 'gateway' => @gateway,
330
+ 'nameservers' => @nameservers
331
+ }
332
+ end
353
333
 
354
- attr_accessor :address, :netmask, :gateway, :nameservers
334
+ def interfaces_lines
335
+ [
336
+ "address #{@address}",
337
+ "netmask #{@netmask}",
338
+ "gateway #{@gateway}"
339
+ ]
340
+ end
355
341
 
356
- def safe_assign
357
- [ :address, :netmask, :gateway, :nameservers_flat ]
358
- end
359
342
 
360
- def validate
361
- @address.strip!
362
- @netmask.strip!
363
- @gateway.strip!
364
-
365
- if not IPAddress.valid_ipv4?(@address)
366
- fail "Static address is invalid"
367
- end
368
-
369
- p @netmask
370
- if not IPAddress.valid_ipv4_netmask?(@netmask)
371
- fail "Static netmask is invalid"
372
- end
373
-
374
- p @netmask
375
- subnet = IPAddress::IPv4.new(@address)
376
- subnet.netmask = @netmask
377
- if not subnet.include? IPAddress::IPv4.new(gateway)
378
- fail "Gateway provided is unreachable"
379
- end
343
+ def write_configs
344
+ File.open('/etc/resolv.conf','w') do |resolvconf|
345
+ @nameservers.each do |nameserver|
346
+ resolvconf.puts("nameserver #{nameserver}");
380
347
  end
348
+ end
349
+ end
381
350
 
382
- # These next two methods are for the web interface, where it's
383
- # more convenient to enter a bunch of nameservers on one line
384
- # than to have to deal with an array of fields.
385
- def nameservers_flat=(separated_list)
386
- servers = separated_list.strip.split(/\s*[,|:;\s]\s*/)
387
- servers.each do |server|
388
- server.strip!
389
- p server
390
- if not IPAddress.valid? server
391
- fail "One or more invalid IP addresses in nameserver list"
392
- end
393
- end
394
- @nameservers = servers
395
- end
351
+ def self.description
352
+ "Static Addressing"
353
+ end
396
354
 
397
- def nameservers_flat
398
- @nameservers.join(',')
399
- end
355
+ attr_accessor :address, :netmask, :gateway, :nameservers
356
+
357
+ def safe_assign
358
+ [ :address, :netmask, :gateway, :nameservers_flat ]
400
359
  end
401
360
 
402
- # Dynamic IPv4 addressing via DHCP
403
- class DHCPAddressing
404
- def initialize(args={})
405
- # we accept no args
406
- end
361
+ def validate
362
+ @address.strip!
363
+ @netmask.strip!
364
+ @gateway.strip!
365
+
366
+ if not IPAddress.valid_ipv4?(@address)
367
+ fail "Static address is invalid"
368
+ end
369
+
370
+ p @netmask
371
+ if not IPAddress.valid_ipv4_netmask?(@netmask)
372
+ fail "Static netmask is invalid"
373
+ end
374
+
375
+ p @netmask
376
+ subnet = IPAddress::IPv4.new(@address)
377
+ subnet.netmask = @netmask
378
+ if not subnet.include? IPAddress::IPv4.new(gateway)
379
+ fail "Gateway provided is unreachable"
380
+ end
381
+ end
407
382
 
408
- def addressing_type
409
- 'dhcp'
410
- end
383
+ # These next two methods are for the web interface, where it's
384
+ # more convenient to enter a bunch of nameservers on one line
385
+ # than to have to deal with an array of fields.
386
+ def nameservers_flat=(separated_list)
387
+ servers = separated_list.strip.split(/\s*[,|:;\s]\s*/)
388
+ servers.each do |server|
389
+ server.strip!
390
+ p server
391
+ if not IPAddress.valid? server
392
+ fail "One or more invalid IP addresses in nameserver list"
393
+ end
394
+ end
395
+ @nameservers = servers
396
+ end
411
397
 
412
- def interfaces_lines
413
- # DHCP needs no additional interfaces args
414
- # from the addressing side
415
- []
416
- end
398
+ def nameservers_flat
399
+ @nameservers.join(',')
400
+ end
401
+ end
417
402
 
418
- def validate
419
- # nothing to validate
420
- end
403
+ # Dynamic IPv4 addressing via DHCP
404
+ class DHCPAddressing
405
+ def initialize(args={})
406
+ # we accept no args
407
+ end
421
408
 
422
- def safe_assign
423
- [] # no args
424
- end
409
+ def addressing_type
410
+ 'dhcp'
411
+ end
425
412
 
426
- def args
427
- { }
428
- end
413
+ def interfaces_lines
414
+ # DHCP needs no additional interfaces args
415
+ # from the addressing side
416
+ []
417
+ end
429
418
 
430
- def write_configs
431
- # dhclient will write our resolv.conf so we do not need
432
- # to do anything
433
- end
419
+ def validate
420
+ # nothing to validate
421
+ end
434
422
 
435
- def self.description
436
- "Dynamic Addressing - DHCP"
437
- end
423
+ def safe_assign
424
+ [] # no args
438
425
  end
439
426
 
440
- # Read a JSON formatted network configuration from the config store.
441
- # This instantiates the connection and addressing method classes
442
- # and returns the instances i.e. cm, am = read_network_config
443
- #
444
- # If no configuration is saved or it is corrupt this returns
445
- # a default configuration that is somewhat likely to work.
446
- def self.read_network_config
447
- input = ConfigStore.read_config('network_config', '')
448
-
449
- begin
450
- args = JSON.parse(input)
451
- rescue
452
- # set up some sane defaults if we have no configuration
453
- # or it can't be parsed
454
- args = {
455
- 'connection_method' => 'WiredConnection',
456
- 'addressing_method' => 'DHCPAddressing',
457
- 'connection_method_args' => { },
458
- 'addressing_method_args' => { }
459
- }
460
- end
461
-
462
- connection_method_class = Bandshell.const_get(args['connection_method'])
463
- addressing_method_class = Bandshell.const_get(args['addressing_method'])
464
-
465
- connection_method = connection_method_class.new(
466
- args['connection_method_args']
467
- )
468
-
469
- addressing_method = addressing_method_class.new(
470
- args['addressing_method_args']
471
- )
472
-
473
- return [connection_method, addressing_method]
474
- end
475
-
476
- # Save the network configuration to the configuration store.
477
- # Arguments are instances of connection method and addressing
478
- # method classes. Throws exception if either one is not valid.
479
- def self.write_network_config(cm, am)
480
- # Check that everything is consistent. If not, we currently throw
481
- # an exception, which probably is not the best long term solution.
482
- cm.validate
483
- am.validate
484
-
485
- # Serialize our instances as JSON data to be written to the config file.
486
- json_data = {
487
- 'connection_method' => cm.class.basename,
488
- 'connection_method_args' => cm.args,
489
- 'addressing_method' => am.class.basename,
490
- 'addressing_method_args' => am.args
491
- }.to_json
492
-
493
- # Save the serialized configuration.
494
- ConfigStore.write_config('network_config', json_data)
495
- end
496
-
497
- # This reads a JSON configuration file on STDIN and writes the interfaces
498
- # file. Also the classes instantiated will have a chance to write
499
- # out any auxiliary files needed.
500
- def self.configure_system_network
501
- connection_method, addressing_method = read_network_config
502
-
503
- ifname = connection_method.config_interface_name
504
-
505
- # squirrel away the name of the interface we are configuring
506
- # This will be useful later for getting network status information.
507
- ConfigStore.write_config('network_interface', ifname)
508
-
509
- # Write the /etc/network/interfaces file.
510
- File.open(INTERFACES_FILE, 'w') do |f|
511
- f.puts "# Concerto Live network configuration"
512
- f.puts "# Generated by netconfig.rb"
513
- f.puts "# Changes will be lost on reboot"
514
- f.puts "auto lo"
515
- f.puts "iface lo inet loopback"
516
- f.puts ""
517
- f.puts "auto #{ifname}"
518
- f.puts "iface #{ifname} inet #{addressing_method.addressing_type}"
519
-
520
- addressing_method.interfaces_lines.each do |line|
521
- f.puts "\t#{line}"
522
- end
523
-
524
- connection_method.interfaces_lines.each do |line|
525
- f.puts "\t#{line}"
526
- end
527
- end
427
+ def args
428
+ { }
429
+ end
430
+
431
+ def write_configs
432
+ # dhclient will write our resolv.conf so we do not need
433
+ # to do anything
434
+ end
435
+
436
+ def self.description
437
+ "Dynamic Addressing - DHCP"
438
+ end
439
+ end
440
+
441
+ # Read a JSON formatted network configuration from the config store.
442
+ # This instantiates the connection and addressing method classes
443
+ # and returns the instances i.e. cm, am = read_network_config
444
+ #
445
+ # If no configuration is saved or it is corrupt this returns
446
+ # a default configuration that is somewhat likely to work.
447
+ def self.read_network_config
448
+ input = ConfigStore.read_config('network_config', '')
449
+
450
+ begin
451
+ args = JSON.parse(input)
452
+ rescue
453
+ # set up some sane defaults if we have no configuration
454
+ # or it can't be parsed
455
+ args = {
456
+ 'connection_method' => 'WiredConnection',
457
+ 'addressing_method' => 'DHCPAddressing',
458
+ 'connection_method_args' => { },
459
+ 'addressing_method_args' => { }
460
+ }
461
+ end
528
462
 
529
- # Write auxiliary configuration files.
530
- connection_method.write_configs
463
+ connection_method_class = Bandshell.const_get(args['connection_method'])
464
+ addressing_method_class = Bandshell.const_get(args['addressing_method'])
465
+
466
+ connection_method = connection_method_class.new(
467
+ args['connection_method_args']
468
+ )
469
+
470
+ addressing_method = addressing_method_class.new(
471
+ args['addressing_method_args']
472
+ )
473
+
474
+ return [connection_method, addressing_method]
475
+ end
476
+
477
+ # Save the network configuration to the configuration store.
478
+ # Arguments are instances of connection method and addressing
479
+ # method classes. Throws exception if either one is not valid.
480
+ def self.write_network_config(cm, am)
481
+ # Check that everything is consistent. If not, we currently throw
482
+ # an exception, which probably is not the best long term solution.
483
+ cm.validate
484
+ am.validate
485
+
486
+ # Serialize our instances as JSON data to be written to the config file.
487
+ json_data = {
488
+ 'connection_method' => cm.class.basename,
489
+ 'connection_method_args' => cm.args,
490
+ 'addressing_method' => am.class.basename,
491
+ 'addressing_method_args' => am.args
492
+ }.to_json
493
+
494
+ # Save the serialized configuration.
495
+ ConfigStore.write_config('network_config', json_data)
496
+ end
497
+
498
+ # This reads a JSON configuration file on STDIN and writes the interfaces
499
+ # file. Also the classes instantiated will have a chance to write
500
+ # out any auxiliary files needed.
501
+ def self.configure_system_network
502
+ connection_method, addressing_method = read_network_config
503
+
504
+ ifname = connection_method.config_interface_name
505
+
506
+ # squirrel away the name of the interface we are configuring
507
+ # This will be useful later for getting network status information.
508
+ ConfigStore.write_config('network_interface', ifname)
509
+
510
+ # Write the /etc/network/interfaces file.
511
+ File.open(INTERFACES_FILE, 'w') do |f|
512
+ f.puts "# Concerto Live network configuration"
513
+ f.puts "# Generated by netconfig.rb"
514
+ f.puts "# Changes will be lost on reboot"
515
+ f.puts "auto lo"
516
+ f.puts "iface lo inet loopback"
517
+ f.puts ""
518
+ f.puts "auto #{ifname}"
519
+ f.puts "iface #{ifname} inet #{addressing_method.addressing_type}"
520
+
521
+ addressing_method.interfaces_lines.each do |line|
522
+ f.puts "\t#{line}"
523
+ end
524
+
525
+ connection_method.interfaces_lines.each do |line|
526
+ f.puts "\t#{line}"
527
+ end
531
528
  end
532
529
 
533
- # Get the name of the interface we configured
534
- def self.configured_interface
535
- ifname = ConfigStore.read_config('network_interface', '')
536
- if ifname != ''
537
- Interface.new(ifname)
538
- else
539
- nil
540
- end
530
+ # Write auxiliary configuration files.
531
+ connection_method.write_configs
532
+ end
533
+
534
+ # Get the name of the interface we configured
535
+ def self.configured_interface
536
+ ifname = ConfigStore.read_config('network_interface', '')
537
+ if ifname != ''
538
+ Interface.new(ifname)
539
+ else
540
+ nil
541
541
  end
542
+ end
542
543
  end