opennebula-cli 5.12.7 → 6.0.0

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.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/bin/oneacct +9 -4
  3. data/bin/oneacl +8 -5
  4. data/bin/onecluster +10 -7
  5. data/bin/onedatastore +10 -7
  6. data/bin/oneflow +85 -13
  7. data/bin/oneflow-template +45 -8
  8. data/bin/onegroup +10 -7
  9. data/bin/onehook +10 -7
  10. data/bin/onehost +10 -7
  11. data/bin/oneimage +100 -9
  12. data/bin/onemarket +10 -7
  13. data/bin/onemarketapp +114 -11
  14. data/bin/onesecgroup +13 -7
  15. data/bin/oneshowback +18 -10
  16. data/bin/onetemplate +12 -8
  17. data/bin/oneuser +30 -7
  18. data/bin/onevcenter +16 -8
  19. data/bin/onevdc +10 -7
  20. data/bin/onevm +147 -12
  21. data/bin/onevmgroup +13 -7
  22. data/bin/onevnet +8 -5
  23. data/bin/onevntemplate +11 -7
  24. data/bin/onevrouter +10 -7
  25. data/bin/onezone +11 -8
  26. data/lib/cli_helper.rb +17 -8
  27. data/lib/command_parser.rb +1 -1
  28. data/lib/one_helper.rb +398 -37
  29. data/lib/one_helper/oneacct_helper.rb +8 -17
  30. data/lib/one_helper/oneacl_helper.rb +1 -1
  31. data/lib/one_helper/onecluster_helper.rb +1 -1
  32. data/lib/one_helper/onedatastore_helper.rb +11 -1
  33. data/lib/one_helper/oneflow_helper.rb +20 -5
  34. data/lib/one_helper/oneflowtemplate_helper.rb +28 -2
  35. data/lib/one_helper/onegroup_helper.rb +1 -1
  36. data/lib/one_helper/onehook_helper.rb +1 -1
  37. data/lib/one_helper/onehost_helper.rb +1 -5
  38. data/lib/one_helper/oneimage_helper.rb +13 -7
  39. data/lib/one_helper/onemarket_helper.rb +1 -1
  40. data/lib/one_helper/onemarketapp_helper.rb +500 -96
  41. data/lib/one_helper/onequota_helper.rb +1 -1
  42. data/lib/one_helper/onesecgroup_helper.rb +1 -1
  43. data/lib/one_helper/onetemplate_helper.rb +12 -1
  44. data/lib/one_helper/oneuser_helper.rb +11 -3
  45. data/lib/one_helper/onevcenter_helper.rb +176 -146
  46. data/lib/one_helper/onevdc_helper.rb +1 -1
  47. data/lib/one_helper/onevm_helper.rb +4 -3
  48. data/lib/one_helper/onevmgroup_helper.rb +1 -1
  49. data/lib/one_helper/onevnet_helper.rb +1 -1
  50. data/lib/one_helper/onevntemplate_helper.rb +1 -1
  51. data/lib/one_helper/onevrouter_helper.rb +1 -20
  52. data/lib/one_helper/onezone_helper.rb +24 -17
  53. data/share/schemas/xsd/acct.xsd +179 -0
  54. data/share/schemas/xsd/acl_pool.xsd +22 -0
  55. data/share/schemas/xsd/api_info.xsd +43 -0
  56. data/share/schemas/xsd/cluster.xsd +34 -0
  57. data/share/schemas/xsd/cluster_pool.xsd +12 -0
  58. data/share/schemas/xsd/datastore.xsd +67 -0
  59. data/share/schemas/xsd/datastore_pool.xsd +12 -0
  60. data/share/schemas/xsd/document.xsd +42 -0
  61. data/share/schemas/xsd/document_pool.xsd +12 -0
  62. data/share/schemas/xsd/group.xsd +179 -0
  63. data/share/schemas/xsd/group_pool.xsd +194 -0
  64. data/share/schemas/xsd/hook.xsd +59 -0
  65. data/share/schemas/xsd/hook_message_api.xsd +14 -0
  66. data/share/schemas/xsd/hook_message_retry.xsd +12 -0
  67. data/share/schemas/xsd/hook_message_state.xsd +25 -0
  68. data/share/schemas/xsd/hook_pool.xsd +12 -0
  69. data/share/schemas/xsd/host.xsd +164 -0
  70. data/share/schemas/xsd/host_pool.xsd +12 -0
  71. data/share/schemas/xsd/image.xsd +123 -0
  72. data/share/schemas/xsd/image_pool.xsd +12 -0
  73. data/share/schemas/xsd/index.xsd +50 -0
  74. data/share/schemas/xsd/marketplace.xsd +44 -0
  75. data/share/schemas/xsd/marketplace_pool.xsd +12 -0
  76. data/share/schemas/xsd/marketplaceapp.xsd +56 -0
  77. data/share/schemas/xsd/marketplaceapp_pool.xsd +12 -0
  78. data/share/schemas/xsd/monitoring_data.xsd +41 -0
  79. data/share/schemas/xsd/opennebula_configuration.xsd +412 -0
  80. data/share/schemas/xsd/raftstatus.xsd +18 -0
  81. data/share/schemas/xsd/security_group.xsd +74 -0
  82. data/share/schemas/xsd/security_group_pool.xsd +12 -0
  83. data/share/schemas/xsd/showback.xsd +29 -0
  84. data/share/schemas/xsd/user.xsd +186 -0
  85. data/share/schemas/xsd/user_pool.xsd +201 -0
  86. data/share/schemas/xsd/vdc.xsd +76 -0
  87. data/share/schemas/xsd/vdc_pool.xsd +12 -0
  88. data/share/schemas/xsd/vm.xsd +251 -0
  89. data/share/schemas/xsd/vm_group.xsd +59 -0
  90. data/share/schemas/xsd/vm_group_pool.xsd +12 -0
  91. data/share/schemas/xsd/vm_pool.xsd +114 -0
  92. data/share/schemas/xsd/vmtemplate.xsd +52 -0
  93. data/share/schemas/xsd/vmtemplate_pool.xsd +12 -0
  94. data/share/schemas/xsd/vnet.xsd +137 -0
  95. data/share/schemas/xsd/vnet_pool.xsd +85 -0
  96. data/share/schemas/xsd/vntemplate.xsd +50 -0
  97. data/share/schemas/xsd/vntemplate_pool.xsd +12 -0
  98. data/share/schemas/xsd/vrouter.xsd +49 -0
  99. data/share/schemas/xsd/vrouter_pool.xsd +12 -0
  100. data/share/schemas/xsd/zone.xsd +40 -0
  101. data/share/schemas/xsd/zone_pool.xsd +36 -0
  102. metadata +79 -17
  103. data/lib/one_helper/oneprovision_helper.rb +0 -362
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -91,28 +91,19 @@ class AcctHelper < OpenNebulaHelper::OneHelper
91
91
  :format => String
92
92
  }
93
93
 
94
- XML = {
95
- :name => "xml",
96
- :short => "-x",
97
- :large => "--xml",
98
- :description => "Show the resource in xml format"
99
- }
100
-
101
- JSON = {
102
- :name => "json",
103
- :short => "-j",
104
- :large => "--json",
105
- :description => "Show the resource in json format"
106
- }
107
-
108
94
  SPLIT={
109
95
  :name => "split",
110
96
  :large => "--split",
111
97
  :description => "Split the output in a table for each VM"
112
98
  }
113
99
 
114
- ACCT_OPTIONS = [START_TIME_ACCT, END_TIME_ACCT, USERFILTER, GROUP, HOST, XPATH, XML, JSON, SPLIT]
115
- SHOWBACK_OPTIONS = [START_TIME_SHOWBACK, END_TIME_SHOWBACK, USERFILTER, GROUP, XML, JSON]
100
+ ACCT_OPTIONS = [START_TIME_ACCT, END_TIME_ACCT, USERFILTER, GROUP, HOST, XPATH, SPLIT]
101
+ SHOWBACK_OPTIONS = [START_TIME_SHOWBACK, END_TIME_SHOWBACK, USERFILTER, GROUP]
102
+
103
+ ACCT_OPTIONS << OpenNebulaHelper::XML
104
+ ACCT_OPTIONS << OpenNebulaHelper::JSON
105
+
106
+ SHOWBACK_OPTIONS += OpenNebulaHelper::FORMAT
116
107
 
117
108
  ACCT_TABLE = CLIHelper::ShowTable.new(self.table_conf("oneacct.yaml"), nil) do
118
109
  column :UID, "User ID", :size=>4 do |d|
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -28,6 +28,16 @@ class OneDatastoreHelper < OpenNebulaHelper::OneHelper
28
28
  }
29
29
  }
30
30
 
31
+ FILE_DATASTORE = {
32
+ :name => "file_datastore",
33
+ :large => "--file-datastore id|name" ,
34
+ :description => "Selects the file datastore",
35
+ :format => String,
36
+ :proc => lambda { |o, options|
37
+ OpenNebulaHelper.rname_to_id(o, "DATASTORE")
38
+ }
39
+ }
40
+
31
41
  def self.rname
32
42
  "DATASTORE"
33
43
  end
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -57,11 +57,18 @@ class OneFlowHelper < OpenNebulaHelper::OneHelper
57
57
  d['NAME']
58
58
  end
59
59
 
60
+ column :STARTTIME, 'Start time of the Service', :size => 15 do |d|
61
+ d.extend(CLIHelper::HashWithSearch)
62
+ d = d.dsearch('TEMPLATE/BODY')
63
+
64
+ OpenNebulaHelper.time_to_str(d['start_time'])
65
+ end
66
+
60
67
  column :STAT, 'State', :size => 11, :left => true do |d|
61
68
  Service.state_str(d['TEMPLATE']['BODY']['state'])
62
69
  end
63
70
 
64
- default :ID, :USER, :GROUP, :NAME, :STAT
71
+ default :ID, :USER, :GROUP, :NAME, :STARTTIME, :STAT
65
72
  end
66
73
  end
67
74
 
@@ -74,6 +81,8 @@ class OneFlowHelper < OpenNebulaHelper::OneHelper
74
81
 
75
82
  if CloudClient.is_error?(response)
76
83
  [response.code.to_i, response.to_s]
84
+ elsif options[:yaml]
85
+ [0, JSON.parse(response.body).to_yaml(:indent => 4)]
77
86
  else
78
87
  array_list = JSON.parse(response.body)
79
88
  array_list = array_list['DOCUMENT_POOL']['DOCUMENT']
@@ -93,6 +102,8 @@ class OneFlowHelper < OpenNebulaHelper::OneHelper
93
102
  else
94
103
  [0, JSON.pretty_generate(array_list)]
95
104
  end
105
+ elsif options[:yaml]
106
+ [0, array_list.to_yaml(:indent => 4)]
96
107
  else
97
108
  format_service_pool.show(array_list)
98
109
 
@@ -139,6 +150,8 @@ class OneFlowHelper < OpenNebulaHelper::OneHelper
139
150
  else
140
151
  if options[:json]
141
152
  [0, response.body]
153
+ elsif options[:yaml]
154
+ [0, JSON.parse(response.body).to_yaml(:indent => 4)]
142
155
  else
143
156
  str_h1 = '%-80s'
144
157
  document = JSON.parse(response.body)['DOCUMENT']
@@ -260,9 +273,10 @@ class OneFlowHelper < OpenNebulaHelper::OneHelper
260
273
  #
261
274
  # @param document [Hash] Service document information
262
275
  def print_service_info(document)
263
- str = '%-20s: %-20s'
264
- str_h1 = '%-80s'
265
- template = document['TEMPLATE']['BODY']
276
+ str = '%-20s: %-20s'
277
+ str_h1 = '%-80s'
278
+ template = document['TEMPLATE']['BODY']
279
+ start_time = OpenNebulaHelper.time_to_str(template['start_time'])
266
280
 
267
281
  puts Kernel.format(str, 'ID', document['ID'])
268
282
  puts Kernel.format(str, 'NAME', document['NAME'])
@@ -273,6 +287,7 @@ class OneFlowHelper < OpenNebulaHelper::OneHelper
273
287
  puts Kernel.format(str,
274
288
  'SERVICE STATE',
275
289
  Service.state_str(template['state']))
290
+ puts Kernel.format(str, 'START TIME', start_time)
276
291
 
277
292
  if template['shutdown_action']
278
293
  puts Kernel.format(str, 'SHUTDOWN', template['shutdown_action'])
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -57,7 +57,16 @@ class OneFlowTemplateHelper < OpenNebulaHelper::OneHelper
57
57
  d['NAME']
58
58
  end
59
59
 
60
- default :ID, :USER, :GROUP, :NAME
60
+ column :REGTIME,
61
+ 'Registration time of the Service Template',
62
+ :size => 15 do |d|
63
+ d.extend(CLIHelper::HashWithSearch)
64
+ d = d.dsearch('TEMPLATE/BODY')
65
+
66
+ OpenNebulaHelper.time_to_str(d['registration_time'])
67
+ end
68
+
69
+ default :ID, :USER, :GROUP, :NAME, :REGTIME
61
70
  end
62
71
  end
63
72
 
@@ -73,6 +82,8 @@ class OneFlowTemplateHelper < OpenNebulaHelper::OneHelper
73
82
  else
74
83
  if options[:json]
75
84
  [0, response.body]
85
+ elsif options[:yaml]
86
+ [0, JSON.parse(response.body).to_yaml(:indent => 4)]
76
87
  else
77
88
  documents = JSON.parse(response.body)['DOCUMENT_POOL']
78
89
  format_service_template_pool.show(documents['DOCUMENT'])
@@ -120,12 +131,17 @@ class OneFlowTemplateHelper < OpenNebulaHelper::OneHelper
120
131
  else
121
132
  if options[:json]
122
133
  [0, response.body]
134
+ elsif options[:yaml]
135
+ [0, JSON.parse(response.body).to_yaml(:indent => 4)]
123
136
  else
124
137
  str = '%-20s: %-20s'
125
138
  str_h1 = '%-80s'
126
139
 
127
140
  document = JSON.parse(response.body)['DOCUMENT']
128
141
  template = document['TEMPLATE']['BODY']
142
+ reg_time = OpenNebulaHelper.time_to_str(
143
+ template['registration_time']
144
+ )
129
145
 
130
146
  CLIHelper.print_header(
131
147
  str_h1 % "SERVICE TEMPLATE #{document['ID']} INFORMATION"
@@ -135,6 +151,7 @@ class OneFlowTemplateHelper < OpenNebulaHelper::OneHelper
135
151
  puts Kernel.format str, 'NAME', document['NAME']
136
152
  puts Kernel.format str, 'USER', document['UNAME']
137
153
  puts Kernel.format str, 'GROUP', document['GNAME']
154
+ puts Kernel.format str, 'REGISTRATION TIME', reg_time
138
155
 
139
156
  puts
140
157
 
@@ -309,4 +326,13 @@ class OneFlowTemplateHelper < OpenNebulaHelper::OneHelper
309
326
  answers
310
327
  end
311
328
 
329
+ def factory(id = nil)
330
+ if id
331
+ OpenNebula::ServiceTemplate.new_with_id(id, @client)
332
+ else
333
+ xml = OpenNebula::ServiceTemplate.build_xml
334
+ OpenNebula::ServiceTemplate.new(xml, @client)
335
+ end
336
+ end
337
+
312
338
  end
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -222,10 +222,6 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
222
222
  end
223
223
  end
224
224
 
225
- column :PROVIDER, 'Host provider', :left, :size => 6 do |d|
226
- d['TEMPLATE']['PM_MAD'].nil? ? '-' : d['TEMPLATE']['PM_MAD']
227
- end
228
-
229
225
  column :STAT, 'Host status', :left, :size => 6 do |d|
230
226
  OneHostHelper.state_to_str(d['STATE'])
231
227
  end
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -22,7 +22,7 @@ class OneImageHelper < OpenNebulaHelper::OneHelper
22
22
 
23
23
  # This list contains prefixes that should skip adding user home to the path
24
24
  # This must have the same content as the case $FROM in downloader.sh
25
- PREFIXES = %w[http https ssh s3 rbd vcenter lxd docker]
25
+ PREFIXES = %w[http https ssh s3 rbd vcenter lxd docker dockerfile]
26
26
 
27
27
  TEMPLATE_OPTIONS=[
28
28
  {
@@ -98,9 +98,15 @@ class OneImageHelper < OpenNebulaHelper::OneHelper
98
98
  end
99
99
  },
100
100
  {
101
- :name => 'driver',
102
- :large => '--driver driver',
103
- :description => 'Driver to use image (raw, qcow2, tap:aio:...)',
101
+ :name => 'format',
102
+ :large => '--format format',
103
+ :description => 'Format of the image (raw, qcow2, ...)',
104
+ :format => String
105
+ },
106
+ {
107
+ :name => 'fs',
108
+ :large => '--fs filesystem',
109
+ :description => 'Filesystem to format the image (ext4, xfs, ...)',
104
110
  :format => String
105
111
  },
106
112
  {
@@ -295,7 +301,7 @@ class OneImageHelper < OpenNebulaHelper::OneHelper
295
301
  str_h1='%-80s'
296
302
 
297
303
  path = image['PATH']
298
- fstype = image['FSTYPE']
304
+ iformat = image['FORMAT']
299
305
 
300
306
  size = OpenNebulaHelper.unit_to_str(image['SIZE'].to_i, {}, 'M')
301
307
  lock = OpenNebulaHelper.level_lock_to_str(image['LOCK/LOCKED'])
@@ -314,7 +320,7 @@ class OneImageHelper < OpenNebulaHelper::OneHelper
314
320
  puts format(str, 'PERSISTENT', pers)
315
321
  puts format(str, 'SOURCE', image['SOURCE'])
316
322
  puts format(str, 'PATH', path) if path && !path.empty?
317
- puts format(str, 'FSTYPE', fstype) if fstype && !fstype.empty?
323
+ puts format(str, 'FORMAT', iformat) if iformat && !iformat.empty?
318
324
  puts format(str, 'SIZE', size)
319
325
  puts format(str, 'STATE', image.short_state_str)
320
326
  puts format(str, 'RUNNING_VMS', image['RUNNING_VMS'])
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -15,100 +15,118 @@
15
15
  #--------------------------------------------------------------------------- #
16
16
 
17
17
  require 'one_helper'
18
+ require 'opennebula/marketplaceapp_ext'
19
+ require 'opennebula/template_ext'
20
+ require 'opennebula/virtual_machine_ext'
21
+ require 'opennebula/flow/service_template_ext'
18
22
 
23
+ require 'securerandom'
24
+
25
+ # OneMarketApp Command Helper
19
26
  class OneMarketPlaceAppHelper < OpenNebulaHelper::OneHelper
27
+
20
28
  TEMPLATE_OPTIONS=[
21
29
  {
22
- :name => "name",
23
- :large => "--name name",
30
+ :name => 'name',
31
+ :large => '--name name',
24
32
  :format => String,
25
- :description => "Name of the new MarketPlaceApp"
33
+ :description => 'Name of the new MarketPlaceApp'
26
34
  },
27
35
  {
28
- :name => "description",
29
- :large => "--description description",
36
+ :name => 'description',
37
+ :large => '--description description',
30
38
  :format => String,
31
- :description => "Description for the new MarketPlaceApp"
39
+ :description => 'Description for the new MarketPlaceApp'
32
40
  },
33
41
  {
34
- :name => "image",
35
- :large => "--image id|name" ,
36
- :description => "Selects the image",
42
+ :name => 'image',
43
+ :large => '--image id|name',
44
+ :description => 'Selects the image',
37
45
  :format => String,
38
- :template_key => "origin_id",
39
- :proc => lambda { |o, options|
40
- OpenNebulaHelper.rname_to_id(o, "IMAGE")
46
+ :template_key => 'origin_id',
47
+ :proc => lambda {|o, _options|
48
+ OpenNebulaHelper.rname_to_id(o, 'IMAGE')
41
49
  }
42
50
  },
43
51
  OpenNebulaHelper::DRY
44
52
  ]
45
53
 
46
54
  VMNAME = {
47
- :name => "vmname",
48
- :large => "--vmname name" ,
49
- :description => "Selects the name for the new VM Template, if the App contains one",
55
+ :name => 'vmname',
56
+ :large => '--vmname name',
57
+ :description => 'Selects the name for the new VM Template, ' \
58
+ 'if the App contains one',
50
59
  :format => String
51
60
  }
52
61
 
62
+ # Available market place mads to import apps on them
63
+ MARKETS = %w[http s3]
64
+
53
65
  def self.rname
54
- "MARKETPLACEAPP"
66
+ 'MARKETPLACEAPP'
55
67
  end
56
68
 
57
69
  def self.conf_file
58
- "onemarketapp.yaml"
70
+ 'onemarketapp.yaml'
59
71
  end
60
72
 
61
73
  def self.state_to_str(id)
62
74
  id = id.to_i
63
75
  state_str = MarketPlaceApp::MARKETPLACEAPP_STATES[id]
64
- return MarketPlaceApp::SHORT_MARKETPLACEAPP_STATES[state_str]
76
+ MarketPlaceApp::SHORT_MARKETPLACEAPP_STATES[state_str]
65
77
  end
66
78
 
67
- def format_pool(options)
68
- config_file = self.class.table_conf
69
-
70
- table = CLIHelper::ShowTable.new(config_file, self) do
71
- column :ID, "ONE identifier for the marketplace app", :size=>4 do |d|
72
- d["ID"]
79
+ def format_pool(_options)
80
+ CLIHelper::ShowTable.new(self.class.table_conf, self) do
81
+ column :ID,
82
+ 'ONE identifier for the marketplace app',
83
+ :size=>4 do |d|
84
+ d['ID']
73
85
  end
74
86
 
75
- column :NAME, "Name of the marketplace app", :left, :size=>25 do |d|
76
- d["NAME"]
87
+ column :NAME, 'Name of the marketplace app', :left, :size=>25 do |d|
88
+ d['NAME']
77
89
  end
78
90
 
79
- column :VERSION, "Version of the app", :size=>10 do |d|
80
- d["VERSION"]
91
+ column :VERSION, 'Version of the app', :size=>10 do |d|
92
+ d['VERSION']
81
93
  end
82
94
 
83
- column :SIZE, "App size", :size =>5 do |d|
95
+ column :SIZE, 'App size', :size =>5 do |d|
84
96
  OpenNebulaHelper.unit_to_str(d['SIZE'].to_i, {}, 'M')
85
97
  end
86
98
 
87
- column :STAT, "State of the app", :size=>4 do |d|
88
- OneMarketPlaceAppHelper.state_to_str(d["STATE"])
99
+ column :STAT, 'State of the app', :size=>4 do |d|
100
+ OneMarketPlaceAppHelper.state_to_str(d['STATE'])
89
101
  end
90
102
 
91
- column :REGTIME, "Registration time of the app", :size=>8 do |d|
92
- Time.at(d['REGTIME'].to_i).strftime("%D")
103
+ column :REGTIME, 'Registration time of the app', :size=>8 do |d|
104
+ Time.at(d['REGTIME'].to_i).strftime('%D')
93
105
  end
94
106
 
95
- column :TYPE, "Marketplace app type", :size=>4 do |d|
96
- type = MarketPlaceApp::MARKETPLACEAPP_TYPES[d["TYPE"].to_i]
107
+ column :TYPE, 'Marketplace app type', :size=>4 do |d|
108
+ type = MarketPlaceApp::MARKETPLACEAPP_TYPES[d['TYPE'].to_i]
97
109
  MarketPlaceApp::SHORT_MARKETPLACEAPP_TYPES[type]
98
110
  end
99
111
 
100
- column :MARKET, "Name of the MarketPlace", :left, :size=>20 do |d|
101
- d["MARKETPLACE"]
112
+ column :MARKET, 'Name of the MarketPlace', :left, :size=>20 do |d|
113
+ d['MARKETPLACE']
102
114
  end
103
115
 
104
- column :ZONE, "Zone ID", :size=>4 do |d|
105
- d["ZONE_ID"]
116
+ column :ZONE, 'Zone ID', :size=>4 do |d|
117
+ d['ZONE_ID']
106
118
  end
107
119
 
108
- default :ID,:NAME,:VERSION,:SIZE,:STAT,:TYPE,:REGTIME,:MARKET,:ZONE
120
+ default :ID,
121
+ :NAME,
122
+ :VERSION,
123
+ :SIZE,
124
+ :STAT,
125
+ :TYPE,
126
+ :REGTIME,
127
+ :MARKET,
128
+ :ZONE
109
129
  end
110
-
111
- table
112
130
  end
113
131
 
114
132
  def self.create_template_options_used?(options)
@@ -123,9 +141,242 @@ class OneMarketPlaceAppHelper < OpenNebulaHelper::OneHelper
123
141
  (template_options-options.keys)!=template_options
124
142
  end
125
143
 
144
+ # Import object into marketplace
145
+ #
146
+ # @param object [String] Object ID or name
147
+ # @param o_class [Class] Object class
148
+ def import(object, o_class)
149
+ id = get_obj_id(object, o_class)
150
+
151
+ if OpenNebula.is_error?(id)
152
+ STDERR.puts id.message
153
+ exit(-1)
154
+ end
155
+
156
+ rc = yield(id) if block_given?
157
+
158
+ if OpenNebula.is_error?(rc)
159
+ STDERR.puts rc.message
160
+ exit(-1)
161
+ elsif rc[0] == -1
162
+ STDERR.puts rc[1]
163
+ exit(-1)
164
+ end
165
+
166
+ 0
167
+ end
168
+
169
+ # Import service template into marketplace
170
+ #
171
+ # @param id [Integer] Service Template ID
172
+ # @param options [Hash] User CLI options
173
+ #
174
+ # @return [Error code, error message] 0 if everything was correct
175
+ # 1 otherwhise
176
+ def import_service_template(id, options)
177
+ require 'json'
178
+
179
+ pool = private_markets
180
+
181
+ return pool if OpenNebula.is_error?(pool)
182
+
183
+ s_template = ServiceTemplate.new_with_id(id, @client)
184
+ rc = s_template.info
185
+
186
+ return rc if OpenNebula.is_error?(rc)
187
+
188
+ body = JSON.parse(s_template.to_json)['DOCUMENT']['TEMPLATE']['BODY']
189
+ import_all = options[:yes] || options[:no]
190
+
191
+ while import_all != 'no' && import_all != 'yes'
192
+ print 'Do you want to import images too? (yes/no, default=yes): '
193
+ import_all = STDIN.readline.chop.downcase
194
+
195
+ if import_all.empty?
196
+ puts 'yes'
197
+ import_all = 'yes'
198
+ end
199
+ end
200
+
201
+ # Turn import all into a boolean
202
+ import_all == 'yes' ? import_all = true : import_all = false
203
+
204
+ main_market = options[:market]
205
+
206
+ # Read marketplace where import the service template
207
+ # It can only be a private marketplace
208
+ unless main_market
209
+ puts
210
+ puts 'Available Marketplaces (please enter ID)'
211
+ pool.each {|market| puts "- #{market['ID']}: #{market['NAME']}" }
212
+ puts
213
+ end
214
+
215
+ default_mp = pool.first['ID'].to_i
216
+
217
+ # Keep asking while user selects an incorrect marketplace
218
+ until OneMarketPlaceAppHelper.market_exist?(pool, main_market)
219
+ print 'Where do you want to import the Service template? ' \
220
+ "(default=#{default_mp})"
221
+ main_market = STDIN.readline.chop
222
+
223
+ if main_market.empty?
224
+ puts default_mp
225
+ main_market = default_mp
226
+ else
227
+ main_market = main_market.to_i
228
+ end
229
+ end
230
+
231
+ markets = import_service_template_roles(import_all,
232
+ body,
233
+ pool,
234
+ options[:market])
235
+ ids = []
236
+
237
+ # Create roles apps
238
+ if import_all
239
+ rc = create_apps(markets, import_all)
240
+ ids = rc[1]
241
+
242
+ return [-1, rc[0]] unless rc[0].empty?
243
+ end
244
+
245
+ # Create service template app
246
+ s_template.extend(ServiceTemplateExt)
247
+
248
+ rc = s_template.mp_import(markets, main_market, options[:vmname])
249
+
250
+ if rc[0] == -1
251
+ rc
252
+ else
253
+ ids.each {|i| puts "ID: #{i}" }
254
+ puts "ID: #{rc[1]}"
255
+ [0, nil]
256
+ end
257
+ end
258
+
259
+ # Import VM Template into marketplace
260
+ #
261
+ # @param id [Integer] VM Template ID
262
+ # @param options [Hash] User CLI options
263
+ #
264
+ # @return [Error code, error message] 0 if everything was correct
265
+ # 1 otherwhise
266
+ def import_vm_template(id, options)
267
+ pool = private_markets
268
+
269
+ return pool if OpenNebula.is_error?(pool)
270
+
271
+ template = Template.new_with_id(id, @client)
272
+ rc = template.info
273
+
274
+ return rc if OpenNebula.is_error?(rc)
275
+
276
+ import_all = options[:yes] || options[:no]
277
+
278
+ while import_all != 'no' && import_all != 'yes'
279
+ print 'Do you want to import images too? (yes/no, default=yes): '
280
+ import_all = STDIN.readline.chop.downcase
281
+
282
+ if import_all.empty?
283
+ puts 'yes'
284
+ import_all = 'yes'
285
+ end
286
+ end
287
+
288
+ # Turn import all into a boolean
289
+ import_all == 'yes' ? import_all = true : import_all = false
290
+
291
+ main_market = options[:market]
292
+
293
+ # Read marketplace where import the VM template
294
+ # It can only be a private marketplace
295
+ unless main_market
296
+ puts
297
+ puts 'Available Marketplaces (please enter ID)'
298
+ pool.each {|market| puts "- #{market['ID']}: #{market['NAME']}" }
299
+ puts
300
+ end
301
+
302
+ default_mp = pool.first['ID'].to_i
303
+
304
+ # Keep asking while user selects an incorrect marketplace
305
+ until OneMarketPlaceAppHelper.market_exist?(pool, main_market)
306
+ print 'Where do you want to import the VM template? ' \
307
+ "(default=#{default_mp})"
308
+ main_market = STDIN.readline.chop
309
+
310
+ if main_market.empty?
311
+ puts default_mp
312
+ main_market = default_mp
313
+ else
314
+ main_market = main_market.to_i
315
+ end
316
+ end
317
+
318
+ # Templates import information
319
+ #
320
+ # template_id => :market => marketplace ID to import it
321
+ # :template => ONE Template information
322
+ # :name => generated name for the template
323
+ markets = {}
324
+ markets[template['ID']] = {}
325
+ markets[template['ID']][:market] = main_market
326
+ markets[template['ID']][:template] = template
327
+
328
+ rc = create_apps(markets, import_all, options[:vmname])
329
+
330
+ if rc[0] == -1
331
+ rc
332
+ else
333
+ rc[1].each {|i| puts "ID: #{i}" }
334
+ [0, nil]
335
+ end
336
+ end
337
+
338
+ # Save VM as template to be able to import it
339
+ #
340
+ # @param id [Integer] VM ID
341
+ #
342
+ # @return [Integer] New template ID
343
+ def save_as_template(id)
344
+ vm = VirtualMachine.new_with_id(id, @client)
345
+ rc = vm.info
346
+
347
+ return rc if OpenNebula.is_error?(rc)
348
+
349
+ vm.extend(VirtualMachineExt)
350
+
351
+ vm.save_as_template("#{vm['NAME']}-saved", 'App to import')
352
+ end
353
+
354
+ # Get object ID from name
355
+ #
356
+ # @param id [String] ID or NAME
357
+ # @param obj [OpenNebula::Class] OpenNebula pool class
358
+ #
359
+ # @return [Integer] Object ID
360
+ def get_obj_id(id, obj)
361
+ if (id.is_a? Integer) || id.match(/^\d+$/)
362
+ id.to_i
363
+ else
364
+ pool = obj.new(@client)
365
+ rc = pool.info_all
366
+
367
+ return rc if OpenNebula.is_error?(rc)
368
+
369
+ rc = pool.find {|v| v['NAME'] == id }
370
+
371
+ return Error.new("Object `#{id}` not found") unless rc
372
+
373
+ rc['ID'].to_i
374
+ end
375
+ end
376
+
126
377
  private
127
378
 
128
- def factory(id=nil)
379
+ def factory(id = nil)
129
380
  if id
130
381
  OpenNebula::MarketPlaceApp.new_with_id(id, @client)
131
382
  else
@@ -134,91 +385,244 @@ class OneMarketPlaceAppHelper < OpenNebulaHelper::OneHelper
134
385
  end
135
386
  end
136
387
 
137
- def factory_pool(user_flag=-2)
388
+ def factory_pool(user_flag = -2)
138
389
  OpenNebula::MarketPlaceAppPool.new(@client, user_flag)
139
390
  end
140
391
 
141
- def format_resource(app, options = {})
142
- str="%-15s: %-20s"
143
- str_h1="%-80s"
144
-
145
- CLIHelper.print_header(str_h1 % "MARKETPLACE APP #{app['ID']} INFORMATION")
146
- puts str % ["ID", app.id.to_s]
147
- puts str % ["NAME", app.name]
148
- puts str % ["TYPE", app.type_str]
149
- puts str % ["USER", app['UNAME']]
150
- puts str % ["GROUP", app['GNAME']]
151
- puts str % ["MARKETPLACE", app['MARKETPLACE']]
152
- puts str % ["STATE", OneMarketPlaceAppHelper.state_to_str(app["STATE"])]
153
- puts str % ["LOCK", OpenNebulaHelper.level_lock_to_str(app['LOCK/LOCKED'])]
392
+ def format_resource(app, _options = {})
393
+ str='%-15s: %-20s'
394
+ str_h1='%-80s'
395
+
396
+ CLIHelper.print_header(
397
+ str_h1 % "MARKETPLACE APP #{app['ID']} INFORMATION"
398
+ )
399
+ puts format(str, 'ID', app.id.to_s)
400
+ puts format(str, 'NAME', app.name)
401
+ puts format(str, 'TYPE', app.type_str)
402
+ puts format(str, 'USER', app['UNAME'])
403
+ puts format(str, 'GROUP', app['GNAME'])
404
+ puts format(str, 'MARKETPLACE', app['MARKETPLACE'])
405
+ puts format(str,
406
+ 'STATE',
407
+ OneMarketPlaceAppHelper.state_to_str(app['STATE']))
408
+ puts format(str,
409
+ 'LOCK',
410
+ OpenNebulaHelper.level_lock_to_str(app['LOCK/LOCKED']))
154
411
 
155
412
  puts
156
413
 
157
- CLIHelper.print_header(str_h1 % "PERMISSIONS",false)
414
+ CLIHelper.print_header(str_h1 % 'PERMISSIONS', false)
158
415
 
159
- ["OWNER", "GROUP", "OTHER"].each { |e|
160
- mask = "---"
161
- mask[0] = "u" if app["PERMISSIONS/#{e}_U"] == "1"
162
- mask[1] = "m" if app["PERMISSIONS/#{e}_M"] == "1"
163
- mask[2] = "a" if app["PERMISSIONS/#{e}_A"] == "1"
416
+ %w[OWNER GROUP OTHER].each do |e|
417
+ mask = '---'
418
+ mask[0] = 'u' if app["PERMISSIONS/#{e}_U"] == '1'
419
+ mask[1] = 'm' if app["PERMISSIONS/#{e}_M"] == '1'
420
+ mask[2] = 'a' if app["PERMISSIONS/#{e}_A"] == '1'
164
421
 
165
- puts str % [e, mask]
166
- }
422
+ puts format(str, e, mask)
423
+ end
167
424
  puts
168
425
 
169
- CLIHelper.print_header(str_h1 % "DETAILS", false)
170
-
171
- puts str % ["SOURCE", app['SOURCE']]
172
- puts str % ["MD5", app['MD5']]
173
- puts str % ["PUBLISHER", app['PUBLISHER']]
174
- puts str % ["REGISTER TIME", Time.at(app['REGTIME'].to_i).strftime("%c") ]
175
- puts str % ["VERSION", app['VERSION']]
176
- puts str % ["DESCRIPTION", app['DESCRIPTION']]
177
- puts str % ["SIZE", OpenNebulaHelper.unit_to_str(app['SIZE'].to_i,{},'M')]
178
- puts str % ["ORIGIN_ID", app['ORIGIN_ID']]
179
- puts str % ["FORMAT", app['FORMAT']]
426
+ CLIHelper.print_header(str_h1 % 'DETAILS', false)
427
+
428
+ puts format(str, 'SOURCE', app['SOURCE'])
429
+ puts format(str, 'MD5', app['MD5'])
430
+ puts format(str, 'PUBLISHER', app['PUBLISHER'])
431
+ puts format(str,
432
+ 'REGISTER TIME',
433
+ Time.at(app['REGTIME'].to_i).strftime('%c'))
434
+ puts format(str, 'VERSION', app['VERSION'])
435
+ puts format(str, 'DESCRIPTION', app['DESCRIPTION'])
436
+ puts format(str,
437
+ 'SIZE',
438
+ OpenNebulaHelper.unit_to_str(app['SIZE'].to_i, {}, 'M'))
439
+ puts format(str, 'ORIGIN_ID', app['ORIGIN_ID'])
440
+ puts format(str, 'FORMAT', app['FORMAT'])
180
441
 
181
442
  puts
182
443
 
183
- CLIHelper.print_header(str_h1 % "IMPORT TEMPLATE", false)
444
+ CLIHelper.print_header(str_h1 % 'IMPORT TEMPLATE', false)
184
445
 
185
446
  puts Base64.decode64(app['APPTEMPLATE64'])
186
447
 
187
448
  puts
188
449
 
189
- CLIHelper.print_header(str_h1 % "MARKETPLACE APP TEMPLATE", false)
450
+ CLIHelper.print_header(str_h1 % 'MARKETPLACE APP TEMPLATE', false)
190
451
  puts app.template_str
191
452
 
192
453
  puts
193
454
  end
194
455
 
195
- def self.create_variables(options, name)
196
- if Array===name
197
- names=name
198
- else
199
- names=[name]
456
+ class << self
457
+
458
+ def create_variables(options, name)
459
+ names = [name].flatten
460
+ t = ''
461
+
462
+ names.each do |n|
463
+ next unless options[n]
464
+
465
+ t << "#{n.to_s.upcase}=\"#{options[n]}\"\n"
466
+ end
467
+
468
+ t
200
469
  end
201
470
 
202
- t=''
203
- names.each do |n|
204
- if options[n]
205
- t<<"#{n.to_s.upcase}=\"#{options[n]}\"\n"
471
+ def create_datastore_template(options)
472
+ template_options = TEMPLATE_OPTIONS.map do |o|
473
+ o[:name].to_sym
206
474
  end
475
+
476
+ template = create_variables(options,
477
+ template_options-[:dry, :image])
478
+
479
+ template << "ORIGIN_ID=#{options[:image]}\n" if options[:image]
480
+ template << "TYPE=image\n"
481
+
482
+ [0, template]
483
+ end
484
+
485
+ # Check if marketplace exists
486
+ #
487
+ # @param pool [MarketPlacePool] Marketplaces pool
488
+ # @param market [String] ID to check
489
+ #
490
+ # @return [Boolean] True if exists, false otherwise
491
+ def market_exist?(pool, market)
492
+ !pool.select {|v| v['ID'].to_i == market }.empty?
207
493
  end
208
494
 
209
- t
210
495
  end
211
496
 
212
- def self.create_datastore_template(options)
213
- template_options=TEMPLATE_OPTIONS.map do |o|
214
- o[:name].to_sym
497
+ # Get private marketplace to import templates
498
+ #
499
+ # @return [OpenNebula::Pool] Marketplace pool or error if any
500
+ def private_markets
501
+ pool = MarketPlacePool.new(@client)
502
+ rc = pool.info
503
+
504
+ return rc if OpenNebula.is_error?(rc)
505
+
506
+ # Get private marketplaces
507
+ pool = pool.select {|market| MARKETS.include?(market['MARKET_MAD']) }
508
+ pool = pool.sort_by {|market| market['ID'].to_i }
509
+
510
+ if pool.empty?
511
+ return Error.new("There are no #{MARKETS.join('/')} marketplaces")
215
512
  end
216
513
 
217
- template=create_variables(options, template_options-[:dry,:image])
514
+ pool
515
+ end
516
+
517
+ # Get roles information when importing a service template into marketplace
518
+ #
519
+ # @param import_all [Boolean] true to import VM templates too
520
+ # @param body [Hash] Sevice Template information
521
+ # @param pool [Array] Marketplace pool
522
+ # @param market [Integer] Marketplace to import
523
+ #
524
+ # @return [Hash] Roles templates and marketplaces to import them
525
+ def import_service_template_roles(import_all, body, pool, market)
526
+ # Templates import information
527
+ #
528
+ # template_id => :market => marketplace ID to import it
529
+ # :template => ONE Template information
530
+ # :name => generated name for the template
531
+ markets = {}
532
+ default_mp = pool.first['ID'].to_i
533
+
534
+ if import_all
535
+ # Read marketplace where import each different VM template
536
+ # It can only be a private marketplace
537
+ unless market
538
+ puts
539
+ puts 'Available Marketplaces for roles (please enter ID)'
540
+ pool.each do |m|
541
+ puts "- #{m['ID']}: #{m['NAME']}"
542
+ end
543
+ puts
544
+ end
545
+
546
+ # Iterate all the roles to ask for the marketplace
547
+ body['roles'].each do |role|
548
+ # Read role VM template information from OpenNebula
549
+ template = Template.new_with_id(role['vm_template'], @client)
550
+ rc = template.info
551
+
552
+ return rc if OpenNebula.is_error?(rc)
553
+
554
+ next if markets.include?(template['ID'])
555
+
556
+ if market
557
+ m = market
558
+ else
559
+ # Keep asking while user selects an incorrect marketplace
560
+ until OneMarketPlaceAppHelper.market_exist?(pool, m)
561
+ print 'Where do you want to import' \
562
+ "`#{template['NAME']}`? (default=#{default_mp})"
563
+ m = STDIN.readline.chop
564
+
565
+ if m.empty?
566
+ puts default_mp
567
+ m = default_mp
568
+ else
569
+ m = m.to_i
570
+ end
571
+ end
572
+ end
573
+
574
+ # Update current template information
575
+ markets[template['ID']] = {}
576
+ markets[template['ID']][:market] = m
577
+ markets[template['ID']][:template] = template
578
+ end
579
+ else
580
+ # Do not ask for marketplaces, just fill templates information
581
+ body['roles'].each do |role|
582
+ # Read role VM template information from OpenNebula
583
+ template = Template.new_with_id(role['vm_template'], @client)
584
+ rc = template.info
218
585
 
219
- template<<"ORIGIN_ID=#{options[:image]}\n" if options[:image]
220
- template << "TYPE=image\n"
586
+ return rc if OpenNebula.is_error?(rc)
221
587
 
222
- [0, template]
588
+ next if markets.include?(template['ID'])
589
+
590
+ # update current template information
591
+ markets[template['id']] = {}
592
+ markets[template['id']][:template] = template
593
+ end
594
+ end
595
+
596
+ markets
597
+ end
598
+
599
+ # Create applications in Marketplace
600
+ #
601
+ # @param markets [Hash] Marketplaces and templates information
602
+ # @param import_all [Boolean] true to import images too
603
+ # @param template_name [String] Virtual Machine Template app name
604
+ #
605
+ # @return [String] Error message in case of any
606
+ def create_apps(markets, import_all, template_name = nil)
607
+ ids = nil
608
+
609
+ markets.each do |_, market|
610
+ template = market[:template]
611
+
612
+ template.extend(OpenNebula::TemplateExt)
613
+
614
+ rc, ids = template.mp_import(market[:market].to_i,
615
+ import_all,
616
+ template_name)
617
+
618
+ return [rc.message, ids] if OpenNebula.is_error?(rc)
619
+
620
+ # Store name to use it after
621
+ market[:name] = nil
622
+ market[:name] = rc
623
+ end
624
+
625
+ ['', ids]
223
626
  end
627
+
224
628
  end