enfcli 4.0.0 → 5.0.0.pre.alpha

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