enfcli 4.0.0 → 5.0.0.pre.alpha

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #
4
- # Copyright 2018-2019 Xaptum,Inc
4
+ # Copyright 2018-2020 Xaptum,Inc
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -15,21 +15,22 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
  #
18
- require 'enfthor'
19
- require 'enfapi'
20
- require 'json'
21
- require 'erb'
18
+ require "enfthor"
19
+ require "enfapi"
20
+ require "json"
21
+ require "erb"
22
22
 
23
23
  module EnfCli
24
24
  module Cmd
25
25
  class Captive < EnfThor
26
- desc 'list-wifi-configurations',
27
- 'List wifi configuration information for all or the matching records.'
28
- method_option :name, default: nil, type: :string, banner: 'NAME',
29
- desc: 'where NAME will match the user-given name.'
30
- method_option :domain, default: nil, type: :string, banner: 'DOMAIN',
31
- aliases: '-d'
32
- method_option :ssid, default: nil, type: :string, banner: 'SSID'
26
+ desc "list-wifi-configurations",
27
+ "List wifi configuration information for all or the matching records."
28
+ method_option :name, default: nil, type: :string, banner: "NAME",
29
+ desc: "where NAME will match the user-given name."
30
+ method_option :domain, default: nil, type: :string, banner: "DOMAIN",
31
+ aliases: "-d"
32
+ method_option :ssid, default: nil, type: :string, banner: "SSID"
33
+
33
34
  def list_wifi_configurations
34
35
  try_with_rescue_in_session do
35
36
  ## TODO: V1 is only listing all of the wifi configurations, it is not
@@ -40,15 +41,16 @@ module EnfCli
40
41
  # display the data
41
42
  display_wifi_configs wifi_configs
42
43
  else
43
- say 'No WiFi configurations found.'
44
+ say "No WiFi configurations found."
44
45
  end
45
46
  end
46
47
  end
47
48
 
48
- desc 'create-wifi-configuration', 'Create a new wifi configuration.'
49
+ desc "create-wifi-configuration", "Create a new wifi configuration."
49
50
  method_option :'wifi-config-file', type: :string, required: true,
50
- banner: '<file>',
51
- desc: '<file> is JSON file with parameters required for configuring the router card.'
51
+ banner: "<file>",
52
+ desc: "<file> is JSON file with parameters required for configuring the router card."
53
+
52
54
  def create_wifi_configuration
53
55
  try_with_rescue_in_session do
54
56
  json_file_name = options[:'wifi-config-file']
@@ -65,20 +67,21 @@ module EnfCli
65
67
  end
66
68
  end
67
69
 
68
- desc 'get-wifi-configuration',
69
- 'Get details of the specified wifi configuration. Exactly one of: ' \
70
- '--wifi-id, --profile-id, --device-id, or --wifi-name must be ' \
71
- 'specified.'
72
- method_option :'wifi-id', defaut: nil, type: :string, banner: 'WIFI-ID',
73
- desc: 'WIFI-ID is the UUID of the wifi record'
74
- method_option :version, defaut: nil, type: :string, banner: 'VERSION',
75
- desc: 'Optionally used with --wifi-id'
76
- method_option :'profile-id', defaut: nil, type: :string, banner: 'PROFILE-ID',
77
- desc: 'PROFILE-ID is the UUID of the profile.'
78
- method_option :'device-id', defaut: nil, type: :string, banner: 'DEVICE-ID',
79
- desc: 'DEVICE-ID is the UUID of the device.'
80
- method_option :'wifi-name', defaut: nil, type: :string, banner: 'WIFI-NAME',
81
- desc: 'Result matches any wifi configuration that contains the substring WIFI-NAME'
70
+ desc "get-wifi-configuration",
71
+ "Get details of the specified wifi configuration. Exactly one of: " \
72
+ "--wifi-id, --profile-id, --device-id, or --wifi-name must be " \
73
+ "specified."
74
+ method_option :'wifi-id', defaut: nil, type: :string, banner: "WIFI-ID",
75
+ desc: "WIFI-ID is the UUID of the wifi record"
76
+ method_option :version, defaut: nil, type: :string, banner: "VERSION",
77
+ desc: "Optionally used with --wifi-id"
78
+ method_option :'profile-id', defaut: nil, type: :string, banner: "PROFILE-ID",
79
+ desc: "PROFILE-ID is the UUID of the profile."
80
+ method_option :'device-id', defaut: nil, type: :string, banner: "DEVICE-ID",
81
+ desc: "DEVICE-ID is the UUID of the device."
82
+ method_option :'wifi-name', defaut: nil, type: :string, banner: "WIFI-NAME",
83
+ desc: "Result matches any wifi configuration that contains the substring WIFI-NAME"
84
+
82
85
  def get_wifi_configuration
83
86
  try_with_rescue_in_session do
84
87
  ## TODO - Currently, this only handles wifi-id, add the others to v2
@@ -95,31 +98,30 @@ module EnfCli
95
98
  num_query_opts += 1 if device_id
96
99
  num_query_opts += 1 if wifi_name
97
100
 
98
-
99
- raise 'ERROR: Exactly one of: --wifi-id, --profile-id, --device-id, or --wifi-name must be specified.' if num_query_opts != 1
101
+ raise "ERROR: Exactly one of: --wifi-id, --profile-id, --device-id, or --wifi-name must be specified." if num_query_opts != 1
100
102
 
101
103
  if wifi_id
102
104
  wifi_config = EnfApi::Captive.instance.get_wifi_configuration wifi_id, version
103
105
 
104
106
  # display the data
105
107
  display_wifi_detail wifi_config
106
-
107
108
  end
108
109
  end
109
110
  end
110
111
 
111
- desc 'update-wifi-configuration',
112
- 'Update an existing wifi configuration.'
112
+ desc "update-wifi-configuration",
113
+ "Update an existing wifi configuration."
113
114
  method_option :'wifi-id', type: :string,
114
115
  required: true,
115
- banner: 'WIFI-ID',
116
- desc: 'WIFI-ID is the UUID of the wifi profile'
116
+ banner: "WIFI-ID",
117
+ desc: "WIFI-ID is the UUID of the wifi profile"
117
118
  method_option :'wifi-config-file', type: :string,
118
119
  required: true,
119
- banner: '<file>',
120
- desc: '<file> is JSON file with ' \
121
- 'parameters required for ' \
122
- 'configuring the router card.'
120
+ banner: "<file>",
121
+ desc: "<file> is JSON file with " \
122
+ "parameters required for " \
123
+ "configuring the router card."
124
+
123
125
  def update_wifi_configuration
124
126
  try_with_rescue_in_session do
125
127
  json_file_name = options[:'wifi-config-file']
@@ -133,29 +135,29 @@ module EnfCli
133
135
  end
134
136
  end
135
137
 
138
+ desc "create-device",
139
+ "Add a new device to the database. This is only available to Xaptum administrators"
140
+ method_option :'device-id', type: :string, required: true, banner: "SERIAL-NUM",
141
+ desc: "SERIAL-NUM is the serial number of the device."
142
+ method_option :'device-name', type: :string, default: nil, banner: "DEVICE-NAME",
143
+ desc: "User-defined name for the device."
144
+ method_option :'mac-addr1', type: :string, default: nil, banner: "MAC-ADDR1",
145
+ desc: "MAC address 1 (wifi address on a wifi-enabled device)"
146
+ method_option :'mac-addr2', type: :string, default: nil, banner: "MAC-ADDR2",
147
+ desc: "MAC address 2"
148
+ method_option :'mac-addr3', type: :string, default: nil, banner: "MAC-ADDR3",
149
+ desc: "MAC address 3"
150
+ method_option :'mac-addr4', type: :string, default: nil, banner: "MAC-ADDR4",
151
+ desc: "MAC address 4"
152
+ method_option :'profile-id', type: :string, default: nil, banner: "PROFILE_ID",
153
+ desc: "UUID of the profile that the device will use. The profile must already exist."
154
+ method_option :model, type: :string, default: nil, banner: "MODEL",
155
+ desc: "Model identifier of the device"
136
156
 
137
- desc 'create-device',
138
- 'Add a new device to the database. This is only available to Xaptum administrators'
139
- method_option :'device-id', type: :string, required: true, banner: 'SERIAL-NUM',
140
- desc: 'SERIAL-NUM is the serial number of the device.'
141
- method_option :'device-name', type: :string, default: nil, banner: 'DEVICE-NAME',
142
- desc: 'User-defined name for the device.'
143
- method_option :'mac-addr1', type: :string, default: nil, banner: 'MAC-ADDR1',
144
- desc: 'MAC address 1 (wifi address on a wifi-enabled device)'
145
- method_option :'mac-addr2', type: :string, default: nil, banner: 'MAC-ADDR2',
146
- desc: 'MAC address 2'
147
- method_option :'mac-addr3', type: :string, default: nil, banner: 'MAC-ADDR3',
148
- desc: 'MAC address 3'
149
- method_option :'mac-addr4', type: :string, default: nil, banner: 'MAC-ADDR4',
150
- desc: 'MAC address 4'
151
- method_option :'profile-id', type: :string, default: nil, banner: 'PROFILE_ID',
152
- desc: 'UUID of the profile that the device will use. The profile must already exist.'
153
- method_option :model, type: :string, default: nil, banner: 'MODEL',
154
- desc: 'Model identifier of the device'
155
157
  def create_device
156
158
  try_with_rescue_in_session do
157
159
  new_device_hash = {
158
- serial_number: options[:'device-id']
160
+ serial_number: options[:'device-id'],
159
161
  }
160
162
 
161
163
  mac1 = options[:'mac-addr1']
@@ -192,10 +194,11 @@ module EnfCli
192
194
  end
193
195
  end
194
196
 
195
- desc 'list-devices',
196
- 'List basic device information for all devices matching the option specified.'
197
- method_option :network, default: nil, type: :string, banner: 'NETWORK',
198
- desc: 'NETWORK is the ipv6 subnet used by the device.'
197
+ desc "list-devices",
198
+ "List basic device information for all devices matching the option specified."
199
+ method_option :network, default: nil, type: :string, banner: "NETWORK",
200
+ desc: "NETWORK is the ipv6 subnet used by the device."
201
+
199
202
  def list_devices
200
203
  try_with_rescue_in_session do
201
204
  network = options[:network]
@@ -205,11 +208,12 @@ module EnfCli
205
208
  end
206
209
  end
207
210
 
208
- desc 'get-device',
209
- 'Get details of the specified device.'
211
+ desc "get-device",
212
+ "Get details of the specified device."
210
213
  method_option :'device-id', required: true, type: :string,
211
- banner: 'DEVICE-ID',
212
- desc: 'DEVICE-ID is either the device serial number or its ipv6 address.'
214
+ banner: "DEVICE-ID",
215
+ desc: "DEVICE-ID is either the device serial number or its ipv6 address."
216
+
213
217
  def get_device
214
218
  try_with_rescue_in_session do
215
219
  device_id = ERB::Util::url_encode(options[:'device-id'])
@@ -220,14 +224,15 @@ module EnfCli
220
224
  end
221
225
  end
222
226
 
223
- desc 'update-device',
224
- 'Update an existing device record with the values specified.'
225
- method_option :'device-id', type: :string, required: true, banner: 'DEVICE-ID',
226
- desc: 'DEVICE-ID is either the device serial number or its ipv6 address.'
227
- method_option :'device-name', type: :string, default: nil, banner: 'DEVICE-NAME',
228
- desc: 'User-defined name for the device.'
229
- method_option :'profile-id', type: :string, default: nil, banner: 'PROFILE_ID',
230
- desc: 'UUID of the profile that the device will use. The profile must already exist.'
227
+ desc "update-device",
228
+ "Update an existing device record with the values specified."
229
+ method_option :'device-id', type: :string, required: true, banner: "DEVICE-ID",
230
+ desc: "DEVICE-ID is either the device serial number or its ipv6 address."
231
+ method_option :'device-name', type: :string, default: nil, banner: "DEVICE-NAME",
232
+ desc: "User-defined name for the device."
233
+ method_option :'profile-id', type: :string, default: nil, banner: "PROFILE_ID",
234
+ desc: "UUID of the profile that the device will use. The profile must already exist."
235
+
231
236
  def update_device
232
237
  try_with_rescue_in_session do
233
238
  id = ERB::Util::url_encode(options[:'device-id'])
@@ -248,11 +253,12 @@ module EnfCli
248
253
  end
249
254
  end
250
255
 
251
- desc 'get-device-status',
252
- 'Get the latest status of the specified device.'
256
+ desc "get-device-status",
257
+ "Get the latest status of the specified device."
253
258
  method_option :'device-id', required: true, type: :string,
254
- banner: 'DEVICE-ID',
255
- desc: 'DEVICE-ID is either the device serial number or its ipv6 address.'
259
+ banner: "DEVICE-ID",
260
+ desc: "DEVICE-ID is either the device serial number or its ipv6 address."
261
+
256
262
  def get_device_status
257
263
  try_with_rescue_in_session do
258
264
  device_id = ERB::Util::url_encode(options[:'device-id'])
@@ -262,22 +268,27 @@ module EnfCli
262
268
  end
263
269
  end
264
270
 
265
- desc 'create-profile',
266
- 'Create a new profile.'
271
+ desc "create-profile",
272
+ "Create a new profile."
267
273
  method_option :'profile-name', type: :string, required: true,
268
- banner: 'PROFILE-NAME',
269
- desc: 'PROFILE-NAME is the user-given name.'
274
+ banner: "PROFILE-NAME",
275
+ desc: "PROFILE-NAME is the user-given name."
270
276
  method_option :'device-mode', type: :string, required: true,
271
- banner: 'DEVICE-MODE',
272
- desc: 'secure-host or passthrough'
273
- method_option :'wifi-id', type: :string, default: nil, banner: 'WIFI-ID',
274
- desc: 'WIFI-ID is the UUID of the wifi record that the profile will use. wifi record must already exist'
277
+ banner: "DEVICE-MODE",
278
+ desc: "secure-host or passthrough"
279
+ method_option :'wifi-id', type: :string, default: nil, banner: "WIFI-ID",
280
+ desc: "WIFI-ID is the UUID of the wifi record that the profile will use. wifi record must already exist"
281
+ method_option :'update-id', type: :string, default: nil,
282
+ banner: "UPDATE-ID",
283
+ desc: "UPDATE-ID is the UUID of the firmware update record. " \
284
+ "The firmware-update record must already exist."
285
+
275
286
  def create_profile
276
287
  try_with_rescue_in_session do
277
288
  profile_name = options[:'profile-name']
278
289
  new_profile_hash = {
279
290
  name: profile_name,
280
- config: { mode: options[:'device-mode'] }
291
+ config: { mode: options[:'device-mode'] },
281
292
  }
282
293
 
283
294
  wifi = options[:'wifi-id']
@@ -286,16 +297,23 @@ module EnfCli
286
297
  new_profile_hash[:config][:wifi][:id] = wifi
287
298
  end
288
299
 
300
+ fw_update = options[:'update-id']
301
+ if fw_update
302
+ new_profile_hash[:config][:firmware] = {}
303
+ new_profile_hash[:config][:firmware][:id] = fw_update if fw_update
304
+ end
305
+
289
306
  # send the POST to create a new profile
290
307
  profile = EnfApi::Captive.instance.create_profile new_profile_hash
291
308
  display_profile profile
292
309
  end
293
310
  end
294
311
 
295
- desc 'list-profiles',
296
- 'List the existing profiles.'
297
- method_option :name, default: nil, type: :string, banner: 'NAME',
298
- desc: 'where NAME will match all or part of the user-given profile name.'
312
+ desc "list-profiles",
313
+ "List the existing profiles."
314
+ method_option :name, default: nil, type: :string, banner: "NAME",
315
+ desc: "where NAME will match all or part of the user-given profile name."
316
+
299
317
  def list_profiles
300
318
  try_with_rescue_in_session do
301
319
  query_name = options[:name]
@@ -304,14 +322,14 @@ module EnfCli
304
322
  end
305
323
  end
306
324
 
307
- desc 'get-profile',
308
- 'Get full detail listing of the profile.'
309
- method_option :'profile-id', required: true, type: :string,
310
- banner: 'PROFILE-ID',
311
- desc: 'PROFILE-ID is the UUID of the profile.'
312
- # TODO - server doesn't support version yet.
313
- # method_option :version, default: nil, type: :integer, banner: 'VERSION',
314
- # desc: 'Get a specific version.'
325
+ desc "get-profile",
326
+ "Get full detail listing of the profile."
327
+ method_option :'profile-id', required: true, type: :string,
328
+ banner: "PROFILE-ID",
329
+ desc: "PROFILE-ID is the UUID of the profile."
330
+ # TODO - server doesn't support version yet.
331
+ # method_option :version, default: nil, type: :integer, banner: 'VERSION',
332
+ # desc: 'Get a specific version.'
315
333
  def get_profile
316
334
  try_with_rescue_in_session do
317
335
  profile = EnfApi::Captive.instance.get_profile options[:'profile-id']
@@ -319,44 +337,274 @@ module EnfCli
319
337
  end
320
338
  end
321
339
 
322
- desc 'update-profile',
323
- 'Update a previously-created profile specified by PROFILE-ID. At ' \
324
- 'least one property must be changed.'
325
- method_option :'profile-id', required: true, type: :string,
326
- banner: 'PROFILE-ID',
327
- desc: 'UUID of the device profile.'
340
+ desc "update-profile",
341
+ "Update a previously-created profile specified by PROFILE-ID. At " \
342
+ "least one property must be changed."
343
+ method_option :'profile-id', required: true, type: :string,
344
+ banner: "PROFILE-ID",
345
+ desc: "UUID of the device profile."
328
346
  method_option :'profile-name', type: :string, default: nil,
329
- banner: 'PROFILE-NAME',
330
- desc: 'PROFILE-NAME is the user-given name.'
347
+ banner: "PROFILE-NAME",
348
+ desc: "PROFILE-NAME is the user-given name."
331
349
  method_option :'device-mode', type: :string, default: nil,
332
- banner: 'DEVICE-MODE',
333
- desc: 'secure-host or passthrough'
334
- method_option :'wifi-id', type: :string, default: nil, banner: 'WIFI-ID',
335
- desc: 'WIFI-ID is the UUID of the wifi record that the profile will use. wifi record must already exist'
350
+ banner: "DEVICE-MODE",
351
+ desc: "secure-host or passthrough"
352
+ method_option :'wifi-id', type: :string, default: nil, banner: "WIFI-ID",
353
+ desc: "WIFI-ID is the UUID of the wifi record that the profile will use. wifi record must already exist"
354
+ method_option :'update-id', type: :string, default: nil,
355
+ banner: "UPDATE-ID",
356
+ desc: "UPDATE-ID is the UUID of the firmware update record. " \
357
+ "The firmware-update record must already exist."
358
+
336
359
  def update_profile
337
360
  try_with_rescue_in_session do
338
361
  id = options[:'profile-id']
339
362
  name = options[:'profile-name']
340
363
  mode = options[:'device-mode']
341
364
  wifi_id = options[:'wifi-id']
365
+ fw_update = options[:'update-id']
342
366
 
343
- raise "At least one option needs to change." if name == nil && mode == nil && wifi_id == nil
367
+ raise "At least one option needs to change." if name == nil && mode == nil && wifi_id == nil && fw_update == nil
344
368
 
345
369
  update_hash = {}
346
370
  update_hash[:name] = name if name
347
- update_hash[:config] = {} if wifi_id || mode
371
+ update_hash[:config] = {} if wifi_id || mode || fw_update
348
372
  update_hash[:config][:mode] = mode if mode
349
373
  if wifi_id
350
374
  update_hash[:config][:wifi] = {}
351
375
  update_hash[:config][:wifi][:id] = wifi_id
352
376
  end
353
377
 
378
+ if fw_update
379
+ update_hash[:config][:firmware] = {}
380
+ update_hash[:config][:firmware][:id] = fw_update
381
+ end
354
382
  profile = EnfApi::Captive.instance.update_profile id, update_hash
355
383
  display_profile profile
384
+ end
385
+ end
386
+
387
+ desc "list-firmware-images",
388
+ "Lists all of the available versions of the firmware"
389
+
390
+ def list_firmware_images
391
+ try_with_rescue_in_session do
392
+ data = EnfApi::Captive.instance.list_firmware_images
393
+ display_firmware_image_list data
394
+ end
395
+ end
396
+
397
+ desc "upload-firmware-image",
398
+ "Uploads a new firmware image. Each version will have multiple " \
399
+ "images -- one for each type of hardware. \nNOTE: This version " \
400
+ "doesn't actually upload the file, it merely informs the server of " \
401
+ "its existance."
402
+ method_option :'image-file', required: true, type: :string,
403
+ banner: "<file>", desc: "<file> is the firmware binary image."
404
+ method_option :version, required: true, type: :string,
405
+ banner: "VERSION",
406
+ desc: "VERSION is the release version."
407
+ method_option :'image-name', type: :string, default: nil, banner: "NAME",
408
+ desc: "NAME is the name to associate with the firmware " \
409
+ "image. This is usually the generated filename. " \
410
+ "Defaults to the base name of <file>"
411
+
412
+ def upload_firmware_image
413
+ try_with_rescue_in_session do
414
+ filename = options[:'image-file']
415
+ version = options[:version]
416
+ image_name = options[:'image-name']
417
+
418
+ temp_img_name = File.basename(filename)
419
+ image_name ||= temp_img_name
420
+
421
+ raise "image-name does not match image-file" if temp_img_name != image_name
422
+
423
+ # This version PUTs an empty body
424
+ resp = EnfApi::Captive.instance.upload_firmware_image version, image_name
425
+
426
+ if (resp.code == 200)
427
+ say "Upload complete."
428
+ else
429
+ say "Upload failed with code #{resp.code}"
430
+ end
431
+ end
432
+ end
433
+
434
+ desc "get-firmware-info",
435
+ "Prints details of an existing firmware version."
436
+ method_option :version, required: true, type: :string,
437
+ banner: "VERSION", desc: "VERSION is the release version."
438
+
439
+ def get_firmware_info
440
+ try_with_rescue_in_session do
441
+ version = options[:version]
356
442
 
443
+ fw_info = EnfApi::Captive.instance.get_firmware_info version
444
+
445
+ display_firmware_detail fw_info
446
+ end
447
+ end
448
+
449
+ desc "create-schedule",
450
+ "Creates a schedule object that will be used to determine when a " \
451
+ "device or group of devices may be upgraded. The schedule will be " \
452
+ "uploaded from a JSON-formatted file."
453
+ method_option :schedule, required: true, type: :string,
454
+ banner: "<file>",
455
+ desc: "<file> is a JSON file containing the desired schedule."
456
+
457
+ def create_schedule
458
+ try_with_rescue_in_session do
459
+ filename = options[:schedule]
460
+
461
+ # reading the whole file - shouldn't get more than a few KB
462
+ content = File.read filename
463
+ sched_hash = JSON.parse(content)
464
+
465
+ resp_data = EnfApi::Captive.instance.create_schedule sched_hash
466
+ display_schedule_detail resp_data
357
467
  end
358
468
  end
359
469
 
470
+ desc "list-schedules",
471
+ "Prints a summary list of all existing schedules."
472
+
473
+ def list_schedules
474
+ try_with_rescue_in_session do
475
+ sched_list = EnfApi::Captive.instance.list_schedules
476
+ display_schedule_list sched_list
477
+ end
478
+ end
479
+
480
+ desc "get-schedule",
481
+ "Prints the detail of a specific, existing schedule."
482
+ method_option :'schedule-id', type: :string, required: true, banner: "ID",
483
+ desc: "ID is the system-assigned UUID of the schedule " \
484
+ "to retrieve."
485
+
486
+ def get_schedule
487
+ try_with_rescue_in_session do
488
+ sched_id = options[:'schedule-id']
489
+ sched_data = EnfApi::Captive.instance.get_schedule sched_id
490
+ display_schedule_detail sched_data
491
+ end
492
+ end
493
+
494
+ desc "update-schedule",
495
+ "Modifies an existing schedule by uploading an updated schedule in " \
496
+ "the form of a JSON file."
497
+ method_option :'schedule-id', type: :string, required: true, banner: "ID",
498
+ desc: "ID is the UUID of the schedule to update."
499
+ method_option :schedule, type: :string, required: true, bannder: "<file>",
500
+ desc: "<file> is a JSON file containing the desired schedule."
501
+
502
+ def update_schedule
503
+ try_with_rescue_in_session do
504
+ sched_id = options[:'schedule-id']
505
+ filename = options[:schedule]
506
+
507
+ # read in whole schedule file
508
+ content = File.read filename
509
+ sched_hash = JSON.parse(content)
510
+
511
+ resp_data = EnfApi::Captive.instance.update_schedule sched_id, sched_hash
512
+ display_schedule_detail resp_data
513
+ end
514
+ end
515
+
516
+ desc "delete-schedule",
517
+ "Deletes the specified, existing schedule."
518
+ method_option :'schedule-id', type: :string, required: true, banner: "ID",
519
+ desc: "ID is the system-assigned UUID of the schedule " \
520
+ "to delete."
521
+
522
+ def delete_schedule
523
+ try_with_rescue_in_session do
524
+ sched_id = options[:'schedule-id']
525
+
526
+ # get the name of the schedule
527
+ resp = EnfApi::Captive.instance.get_schedule(sched_id)
528
+ name = resp[:name]
529
+
530
+ resp = EnfApi::Captive.instance.delete_schedule sched_id
531
+
532
+ if (resp.code == 200)
533
+ say "Successfully deleted schedule named: #{name}"
534
+ elsif (resp.code == 409)
535
+ say "Schedule #{name} is being used by pending updates and cannot be deleted."
536
+ else
537
+ say "Failed to delete schedule #{name} with code #{resp.code}"
538
+ end
539
+ end
540
+ end
541
+
542
+ desc "list-firmware-updates",
543
+ "Lists the existing firmware update tasks."
544
+
545
+ def list_firmware_updates
546
+ try_with_rescue_in_session do
547
+ updates_list = EnfApi::Captive.instance.list_firmware_updates
548
+ display_updates_list updates_list
549
+ end
550
+ end
551
+
552
+ desc "get-firmware-update",
553
+ "Prints the details of the specified firmware update task."
554
+ method_option :'update-id', type: :string, required: true, banner: "ID",
555
+ desc: "ID is the UUID of the firmware update task"
556
+
557
+ def get_firmware_update
558
+ try_with_rescue_in_session do
559
+ update_id = options[:'update-id']
560
+
561
+ update_data = EnfApi::Captive.instance.get_firmware_update update_id
562
+ display_update_detail update_data
563
+ end
564
+ end
565
+
566
+ desc "create-firmware-update",
567
+ "Creates a firmware-update task that the system will use to update " \
568
+ "router-card firmware as prescribed in the specified JSON file."
569
+ method_option :update, type: :string, required: true, banner: "<file>",
570
+ desc: "<file> is a JSON file containing the details of " \
571
+ "the update task."
572
+
573
+ def create_firmware_update
574
+ try_with_rescue_in_session do
575
+ filename = options[:update]
576
+
577
+ # reading the whole file - shouldn't get more than a few KB
578
+ content = File.read filename
579
+ update_hash = JSON.parse(content)
580
+
581
+ resp_data = EnfApi::Captive.instance.create_firmware_update update_hash
582
+ display_update_detail resp_data
583
+ end
584
+ end
585
+
586
+ desc "modify-firmware-update",
587
+ "Modifies an existing firmware-update task with the information " \
588
+ "contained in the specified JSON file"
589
+ method_option :'update-id', type: :string, required: true, banner: "ID",
590
+ desc: "ID is the UUID of the firmware update task to be modified."
591
+ method_option :update, type: :string, required: true, banner: "<file>",
592
+ desc: "<file> is a JSON file containing the details of " \
593
+ "the update task."
594
+
595
+ def modify_firmware_update
596
+ try_with_rescue_in_session do
597
+ update_id = options[:'update-id']
598
+ filename = options[:update]
599
+
600
+ # reading the whole file - shouldn't get more than a few KB
601
+ content = File.read filename
602
+ update_hash = JSON.parse(content)
603
+
604
+ resp_data = EnfApi::Captive.instance.modify_firmware_update update_id, update_hash
605
+ display_update_detail resp_data
606
+ end
607
+ end
360
608
 
361
609
  #########################################################################
362
610
  #
@@ -367,7 +615,7 @@ module EnfCli
367
615
  # Displays the wifi configuration summary list.
368
616
  # TODO - Does non-Xaptum-admin columns only - add option to do admin list
369
617
  def display_wifi_configs(configs)
370
- headings = ['ID', 'Wifi Name', 'Config Vers.']
618
+ headings = ["ID", "Wifi Name", "Config Vers."]
371
619
  rows = configs.map do |hash|
372
620
  [hash[:id], hash[:name], hash[:version]]
373
621
  end
@@ -376,25 +624,24 @@ module EnfCli
376
624
  end
377
625
 
378
626
  # Display a single wifi configuration in detail
379
- def display_wifi_detail(wifi_data, full_listing=true)
627
+ def display_wifi_detail(wifi_data, full_listing = true, tabs = 0)
628
+ indent = " " * tabs
380
629
  name = wifi_data[:name]
381
630
  wifi_id = wifi_data[:id]
382
631
  desc = wifi_data[:description]
383
632
  nets = wifi_data[:networks]
384
633
 
385
- say "Wifi ID : #{wifi_id}", nil, true
386
- say "Name : #{name}", nil, true
387
- say "Description : #{desc}", nil, true if desc
634
+ say indent + "Name : #{name}", nil, true
635
+ say indent + "Wifi ID : #{wifi_id}", nil, true
636
+ say indent + "Description : #{desc}", nil, true if desc
388
637
  if full_listing
389
638
  say "WiFi Networks :"
390
639
  if nets
391
640
  nets.each do |wifi_net|
392
- display_wifi_net(wifi_net, 1)
641
+ display_wifi_net(wifi_net, tabs + 1)
393
642
  end
394
643
  end
395
-
396
644
  end
397
-
398
645
  end
399
646
 
400
647
  def display_wifi_net(wifi_net, tabs)
@@ -412,7 +659,7 @@ module EnfCli
412
659
  display_ipv6_addr(wifi_net[:IPv6], tabs + 1)
413
660
  end
414
661
 
415
- def display_ipv4_addr (ipv4, tabs)
662
+ def display_ipv4_addr(ipv4, tabs)
416
663
  indent = " " * tabs
417
664
  if ipv4.instance_of? String
418
665
  say indent + "IPv4 : #{ipv4}", nil, true
@@ -435,7 +682,7 @@ module EnfCli
435
682
  end
436
683
  end
437
684
 
438
- def display_ipv6_addr (ipv6, tabs)
685
+ def display_ipv6_addr(ipv6, tabs)
439
686
  indent = " " * tabs
440
687
  if ipv6.instance_of? String
441
688
  say indent + "IPv6 : #{ipv6}", nil, true
@@ -458,8 +705,6 @@ module EnfCli
458
705
  end
459
706
  end
460
707
 
461
-
462
-
463
708
  #
464
709
  # display the device info.
465
710
  # device_data is a hash matching the json structure
@@ -469,8 +714,8 @@ module EnfCli
469
714
  ctl_addr = device_data[:control_address]
470
715
  dev_addr = device_data[:device_address] || "\n"
471
716
  mac_addrs = device_data[:mac_address]
472
- firmware = device_data[:firmware_version] || '< not available >'
473
- model = device_data[:model] || '< not available >'
717
+ firmware = device_data[:firmware_version] || "< not available >"
718
+ model = device_data[:model] || "< not available >"
474
719
  profile = device_data[:profile]
475
720
  status = device_data[:status]
476
721
 
@@ -485,18 +730,18 @@ module EnfCli
485
730
  mac4 = mac_addrs[:'4']
486
731
 
487
732
  if !mac1
488
- say 'Mac Address : < not available >'
733
+ say "Mac Address : < not available >"
489
734
  elsif !mac2 && !mac3 && !mac4
490
735
  say "Mac Address : #{mac1}", nil, true
491
736
  else
492
- say 'Mac Address :'
737
+ say "Mac Address :"
493
738
  say " 1 : #{mac1}", nil, true
494
739
  say " 2 : #{mac2}", nil, true if mac2
495
740
  say " 3 : #{mac3}", nil, true if mac3
496
741
  say " 4 : #{mac4}", nil, true if mac4
497
742
  end
498
743
  else
499
- say 'Mac Address : < not available >'
744
+ say "Mac Address : < not available >"
500
745
  end
501
746
 
502
747
  say "Firmware Version : #{firmware}", nil, true
@@ -508,19 +753,19 @@ module EnfCli
508
753
  say "Profile : < not available >"
509
754
  end
510
755
  display_device_status_summary status
511
- say ' ', nil, true
756
+ say " ", nil, true
512
757
  end
513
758
 
514
- #
759
+ #
515
760
  # display the status summary
516
761
  #
517
- def display_device_status_summary (device_status)
762
+ def display_device_status_summary(device_status)
518
763
  if device_status
519
- mode = device_status[:router_mode] || device_status[:mode] || '< not available >'
764
+ mode = device_status[:router_mode] || device_status[:mode] || "< not available >"
520
765
 
521
766
  wifi = device_status[:wifi]
522
767
 
523
- say 'Status :'
768
+ say "Status :"
524
769
  say " Router Mode : #{mode}", nil, true
525
770
 
526
771
  if wifi
@@ -539,21 +784,21 @@ module EnfCli
539
784
  # status is a hash matching the json structure
540
785
  #
541
786
  def display_device_status(device_status)
542
- sn = device_status[:serial_number] || '< not available >'
543
- mode = device_status[:router_mode] || device_status[:mode] || '< not available >'
787
+ sn = device_status[:serial_number] || "< not available >"
788
+ mode = device_status[:router_mode] || device_status[:mode] || "< not available >"
544
789
 
545
- uptime = device_status[:uptime] || '< not available >'
546
- refresh = device_status[:refresh_time] || '< not available >'
790
+ uptime = device_status[:uptime] || "< not available >"
791
+ refresh = device_status[:refresh_time] || "< not available >"
547
792
 
548
793
  wifi = device_status[:wifi]
549
794
  if wifi
550
- connected = wifi[:connected] || '< not available >'
795
+ connected = wifi[:connected] || "< not available >"
551
796
  ssid = wifi[:SSID]
552
797
  ipv4 = wifi[:IPv4_addresses]
553
798
  ipv6 = wifi[:IPv6_addresses]
554
799
  wifi_config = wifi[:config]
555
800
  else
556
- connected = '< not available >'
801
+ connected = "< not available >"
557
802
  ssid = nil
558
803
  ipv4 = nil
559
804
  ipv6 = nil
@@ -564,7 +809,7 @@ module EnfCli
564
809
  say "Router Mode : #{mode}", nil, true
565
810
  say "Uptime (in seconds) : #{uptime}", nil, true
566
811
  say "Status refresh time : #{refresh}", nil, true
567
- say "WIFI :"
812
+ say "WIFI status :"
568
813
  say " connected : #{connected}", nil, true
569
814
  say " SSID : #{ssid}" if ssid
570
815
  if ipv4 && !ipv4.empty?
@@ -581,17 +826,27 @@ module EnfCli
581
826
  end
582
827
  end
583
828
 
584
- display_wifi_detail(wifi_config, false) if wifi_config
829
+ say "WIFI configuration :"
830
+ display_wifi_detail(wifi_config, false, 1) if wifi_config
831
+
832
+ fw_status = device_status[:firmware]
833
+ if fw_status
834
+ image_name = fw_status[:image_name] || "< not available >"
835
+ image_state = fw_status[:state] || " < not available >"
836
+ say "Firmware Status :"
837
+ say " image name : #{image_name}", nil, true
838
+ say " operating state : #{image_state}", nil, true
839
+ end
585
840
 
586
- say ' ', nil, true
841
+ say " ", nil, true
587
842
  end
588
843
 
589
844
  #
590
845
  # display the devices summary list
591
846
  #
592
847
  def display_device_list(devices)
593
- headings = ['Serial No', 'Dev Name', 'Dev Addr', 'Router Mode',
594
- 'Connected', 'SSID']
848
+ headings = ["Serial No", "Dev Name", "Dev Addr", "Router Mode",
849
+ "Connected", "SSID"]
595
850
  rows = devices.map do |hash|
596
851
  status = hash[:status]
597
852
  if status
@@ -601,16 +856,15 @@ module EnfCli
601
856
  mode = status[:router_mode] || status[:mode]
602
857
 
603
858
  [hash[:serial_number], hash[:device_name], hash[:device_address],
604
- mode, connected, ssid]
859
+ mode, connected, ssid]
605
860
  else
606
861
  [hash[:serial_number], hash[:device_name], hash[:device_address],
607
- nil, nil, nil]
862
+ nil, nil, nil]
608
863
  end
609
864
  end
610
865
  # [hash[:serial_number], hash[:device_name], hash[:device_address],
611
866
  # hash[:status][:router_mode], hash[:status][:wifi][:connected],
612
867
  # hash[:status][:wifi][:SSID]]
613
-
614
868
  render_table(headings, rows)
615
869
  end
616
870
 
@@ -618,13 +872,22 @@ module EnfCli
618
872
  # Display profile detail
619
873
  #
620
874
  def display_profile(profile, summary = false)
621
- indent = summary ? ' ' : ''
875
+ indent = summary ? " " : ""
876
+
877
+ firmware = profile[:config][:firmware]
878
+ fw_id = "< not configured >"
879
+ if firmware
880
+ fw_id = firmware[:id]
881
+ fw_version = firmware[:version]
882
+ end
622
883
 
623
884
  say indent + "Name : #{profile[:name]}", nil, true
624
885
  say indent + "Profile ID : #{profile[:id]}", nil, true
625
886
  say indent + "Configuration version : #{profile[:config][:version]}", nil, true
887
+ say indent + "Firmware Update ID : #{fw_id}", nil, true
626
888
  unless summary
627
- say "Mode : #{profile[:config][:mode]}", nil, true
889
+ say indent + " Update version : #{fw_version}", nil, true if fw_version
890
+ say indent + "Mode : #{profile[:config][:mode]}", nil, true
628
891
  display_wifi_summary profile[:config][:wifi]
629
892
  end
630
893
  end
@@ -632,7 +895,7 @@ module EnfCli
632
895
  #
633
896
  # Display summary of the WIFI configuration info
634
897
  #
635
- def display_wifi_summary (wifi)
898
+ def display_wifi_summary(wifi)
636
899
  if wifi
637
900
  say "Wifi config :"
638
901
  say " id : #{wifi[:id]}", nil, true
@@ -645,22 +908,120 @@ module EnfCli
645
908
  else
646
909
  say "Wifi config : < not configured >"
647
910
  end
648
-
649
911
  end
650
912
 
651
913
  #
652
914
  # display the profile summary list
653
915
  #
654
916
  def display_profile_list(profiles)
655
- headings = ['Profile Name', 'Profile ID', 'Version']
917
+ headings = ["Profile Name", "Profile ID", "Version", "Mode", "Wifi ID", "Firmware Update ID"]
656
918
  rows = profiles.map do |hash|
657
- [hash[:name], hash[:id], hash[:config][:version]]
919
+ config = hash[:config]
920
+ fw_id = config[:firmware] ? config[:firmware][:id] : "none"
921
+ [hash[:name], hash[:id], config[:version], config[:mode],
922
+ config[:wifi][:id], fw_id]
658
923
  end
924
+ render_table(headings, rows)
925
+ end
659
926
 
927
+ #
928
+ # Displays the list of firmware releases
929
+ #
930
+ def display_firmware_image_list(images)
931
+ headings = ["Firmware Version"]
932
+ rows = images.map do |element|
933
+ [element[:version]]
934
+ end
935
+ render_table(headings, rows)
936
+ end
937
+
938
+ #
939
+ # Displays firmware detail
940
+ #
941
+ def display_firmware_detail(fw_info)
942
+ version = fw_info[:version] || "< not available >"
943
+ images = fw_info[:images]
944
+
945
+ say "Release version: #{version}"
946
+ display_image_list images
947
+ end
948
+
949
+ #
950
+ # Displays the list of images available for a release version.
951
+ #
952
+ def display_image_list(images)
953
+ headings = ["Image Name", "Hardware Model", "Update Type", "SHA256"]
954
+ rows = images.map do |hash|
955
+ [hash[:name], hash[:model], hash[:type], hash[:sha256]]
956
+ end
957
+ render_table(headings, rows)
958
+ end
959
+
960
+ #
961
+ # Displays the full SCHEDULE object detail
962
+ #
963
+ def display_schedule_detail(sched_data)
964
+ name = sched_data[:name]
965
+ id = sched_data[:id]
966
+ domain = sched_data[:domain]
967
+ times = sched_data[:times]
968
+
969
+ say "Schedule Name : #{name}", nil, true
970
+ say "Shedule ID : #{id}", nil, true
971
+ say "domain : #{domain}", nil, true
972
+ say "Times:", nil, true
973
+ display_time_list(times)
974
+ end
975
+
976
+ #
977
+ # Displays the list of times in a schedule as a table
978
+ #
979
+ def display_time_list(times)
980
+ headings = ["Name", "year", "Month", "Date", "Weekday", "Hour",
981
+ "Minute", "id"]
982
+ rows = times.map do |hash|
983
+ [hash[:name], hash[:year], hash[:month], hash[:day_of_month],
984
+ hash[:day_of_week], hash[:hour], hash[:minute], hash[:id]]
985
+ end
986
+ render_table(headings, rows)
987
+ end
988
+
989
+ #
990
+ # Displays a list of schedules
991
+ #
992
+ def display_schedule_list(sched_list)
993
+ headings = ["Name", "ID"]
994
+ rows = sched_list.map do |hash|
995
+ [hash[:name], hash[:id]]
996
+ end
660
997
  render_table(headings, rows)
661
998
  end
662
999
 
1000
+ #
1001
+ # Displays a list of firmware updates
1002
+ #
1003
+ def display_updates_list(updates_list)
1004
+ headings = ["Update ID", "Update Version"]
1005
+ rows = updates_list.map do |hash|
1006
+ [hash[:id], hash[:version]]
1007
+ end
1008
+ render_table(headings, rows)
1009
+ end
663
1010
 
1011
+ #
1012
+ # Displays detail of a specific firmware update task
1013
+ #
1014
+ def display_update_detail(update_data)
1015
+ id = update_data[:id]
1016
+ sched_id = update_data[:schedule_id]
1017
+ version = update_data[:version]
1018
+ percent = update_data[:update_percentage]
1019
+
1020
+ say "Update Task ID : #{id}"
1021
+ say "Schedule ID : #{sched_id}"
1022
+ say "Firmware Version : #{version}"
1023
+ say "Percent of devices to update : #{percent}"
1024
+ end
664
1025
  end
665
1026
  end
666
1027
  end