bandshell 0.0.20 → 0.0.21

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.
@@ -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