opennebula 6.3.85.pre → 6.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9037eadf643ff9e3cb8745aea4cbfe59d88fec16905216f170123da1670cda30
4
- data.tar.gz: 6171ac7fbd6f35e063204eb4a7c35ae4ec5afb0e548d2558623a7095f9a008cf
3
+ metadata.gz: 266777cd8cbee1a5dd1a31a5a13be7cebb30ea31fb570f250e86879ba3bdbb0e
4
+ data.tar.gz: 3a60b62aa8040d838ba5a838ee30e53ae3f120e63c9d348329e1ed01e82f982a
5
5
  SHA512:
6
- metadata.gz: 30d60c2a1447a38a642d4bb93792df47ce39c520a7255fbaa2fd49a445885cc0cd4b28662f9cf45e8d730a3cc7f16db1901489662149a1121c623df35250b5ea
7
- data.tar.gz: 5de0e5c492f708e3e56869c6e8b3aea9cfa05c78a5945f84a32884d0a9be5f347e3d35d3b08289c26084a245aa758071a07bf7231e8ef71c7806a97d9e3dbdad
6
+ metadata.gz: 5b62bafc5c642cef2ba2b3f9e10c656cefe8c65a2c4835f3b9aaceda2b5eec3fc40513abbd77ee592369e805d14a936a925d5168e380e2c94b7e7ec9f9d05d3a
7
+ data.tar.gz: c10696616d94b1acaf6bc29912d92c331b7ff0f25d543312fbbec802dcfbe466616da36a74537e06f009315d25a762f375aa989910234ecc0bb879c4cb1b667c
@@ -51,7 +51,7 @@ end
51
51
  module CloudClient
52
52
 
53
53
  # OpenNebula version
54
- VERSION = '6.3.85'
54
+ VERSION = '6.4.0'
55
55
 
56
56
  # #########################################################################
57
57
  # Default location for the authentication file
data/lib/models/role.rb CHANGED
@@ -65,7 +65,8 @@ module OpenNebula
65
65
  'FAILED_DEPLOYING' => 7,
66
66
  'SCALING' => 8,
67
67
  'FAILED_SCALING' => 9,
68
- 'COOLDOWN' => 10
68
+ 'COOLDOWN' => 10,
69
+ 'HOLD' => 11
69
70
  }
70
71
 
71
72
  STATE_STR = %w[
@@ -80,6 +81,7 @@ module OpenNebula
80
81
  SCALING
81
82
  FAILED_SCALING
82
83
  COOLDOWN
84
+ HOLD
83
85
  ]
84
86
 
85
87
  RECOVER_DEPLOY_STATES = %w[
@@ -147,6 +149,7 @@ module OpenNebula
147
149
 
148
150
  @body['cooldown'] = @@default_cooldown if @body['cooldown'].nil?
149
151
  @body['nodes'] ||= []
152
+ @body['on_hold'] = false if @body['on_hold'].nil?
150
153
  end
151
154
 
152
155
  def name
@@ -195,12 +198,25 @@ module OpenNebula
195
198
  true
196
199
  end
197
200
 
201
+ def can_release?
202
+ state == STATE['HOLD']
203
+ end
204
+
198
205
  # Returns the role parents
199
206
  # @return [Array] the role parents
200
207
  def parents
201
208
  @body['parents'] || []
202
209
  end
203
210
 
211
+ def any_parent_on_hold?
212
+ parents.each do |parent|
213
+ next unless @service.roles[parent]
214
+
215
+ return true if @service.roles[parent].on_hold?
216
+ end
217
+ false
218
+ end
219
+
204
220
  # Returns the role cardinality
205
221
  # @return [Integer] the role cardinality
206
222
  def cardinality
@@ -357,6 +373,23 @@ module OpenNebula
357
373
  @body.delete('scale_way')
358
374
  end
359
375
 
376
+ # Returns the on_hold role option
377
+ # @return [true, false] true if the on_hold option is enabled
378
+ def on_hold?
379
+ @body['on_hold']
380
+ end
381
+
382
+ # Returns the on_hold service option
383
+ # @return [true, false] true if the on_hold option is enabled
384
+ def service_on_hold?
385
+ @service.on_hold?
386
+ end
387
+
388
+ # Set the on_hold vm option to true
389
+ def hold(hold)
390
+ @body['on_hold'] = hold
391
+ end
392
+
360
393
  # Retrieves the VM information for each Node in this Role. If a Node
361
394
  # is to be disposed and it is found in DONE, it will be cleaned
362
395
  #
@@ -436,7 +469,7 @@ module OpenNebula
436
469
  "template #{template_id}, with name #{vm_name}",
437
470
  @service.id
438
471
 
439
- vm_id = template.instantiate(vm_name, false, extra_template)
472
+ vm_id = template.instantiate(vm_name, on_hold?, extra_template)
440
473
 
441
474
  deployed_nodes << vm_id
442
475
 
@@ -546,6 +579,44 @@ module OpenNebula
546
579
  [true, nil]
547
580
  end
548
581
 
582
+ # Release all the nodes in this role
583
+ # @return [Array, Bool] true if all the VMs
584
+ # were released, false otherwise and Array with VMs released
585
+ def release
586
+ release_nodes = []
587
+ success = true
588
+
589
+ # Release all vms in the role
590
+ nodes.each do |node|
591
+ vm_id = node['deploy_id']
592
+
593
+ Log.debug(LOG_COMP,
594
+ "Role #{name}: Releasing VM #{vm_id}",
595
+ @service.id)
596
+
597
+ vm = OpenNebula::VirtualMachine.new_with_id(vm_id,
598
+ @service.client)
599
+ rc = vm.release
600
+
601
+ if OpenNebula.is_error?(rc)
602
+ msg = "Role #{name}: Release failed for VM #{vm_id}, " \
603
+ "#{rc.message}"
604
+
605
+ Log.error(LOG_COMP, msg, @service.id)
606
+ @service.log_error(msg)
607
+ success = false
608
+ else
609
+ Log.debug(LOG_COMP,
610
+ "Role #{name}: Release success for VM #{vm_id}",
611
+ @service.id)
612
+
613
+ release_nodes << vm_id
614
+ end
615
+ end
616
+
617
+ [release_nodes, success]
618
+ end
619
+
549
620
  # Schedule the given action on all the VMs that belong to the Role
550
621
  # @param [String] action one of the available SCHEDULE_ACTIONS
551
622
  # @param [Integer] period
@@ -38,7 +38,8 @@ module OpenNebula
38
38
  'DEPLOYING_NETS' => 11,
39
39
  'UNDEPLOYING_NETS' => 12,
40
40
  'FAILED_DEPLOYING_NETS' => 13,
41
- 'FAILED_UNDEPLOYING_NETS' => 14
41
+ 'FAILED_UNDEPLOYING_NETS' => 14,
42
+ 'HOLD' => 15
42
43
  }
43
44
 
44
45
  STATE_STR = %w[
@@ -57,6 +58,7 @@ module OpenNebula
57
58
  UNDEPLOYING_NETS
58
59
  FAILED_DEPLOYING_NETS
59
60
  FAILED_UNDEPLOYING_NETS
61
+ HOLD
60
62
  ]
61
63
 
62
64
  TRANSIENT_STATES = %w[
@@ -216,6 +218,16 @@ module OpenNebula
216
218
  self['GID'].to_i
217
219
  end
218
220
 
221
+ # Returns the on_hold service option
222
+ # @return [true, false] true if the on_hold option is enabled
223
+ def on_hold?
224
+ @body['on_hold']
225
+ end
226
+
227
+ def hold?
228
+ state_str == 'HOLD'
229
+ end
230
+
219
231
  # Replaces this object's client with a new one
220
232
  # @param [OpenNebula::Client] owner_client the new client
221
233
  def replace_client(owner_client)
@@ -265,6 +277,18 @@ module OpenNebula
265
277
  true
266
278
  end
267
279
 
280
+ # Returns true if all the nodes are in hold state
281
+ # @return [true, false] true if all the nodes are in hold state
282
+ def all_roles_hold?
283
+ @roles.each do |_name, role|
284
+ if role.state != Role::STATE['HOLD']
285
+ return false
286
+ end
287
+ end
288
+
289
+ true
290
+ end
291
+
268
292
  # Returns virtual networks IDs
269
293
  # @return [Array] Array of integers containing the IDs
270
294
  def networks(deploy)
@@ -73,6 +73,10 @@ module OpenNebula
73
73
  :required => false,
74
74
  :minimum => 0
75
75
  },
76
+ 'on_hold' => {
77
+ :type => :boolean,
78
+ :required => false
79
+ },
76
80
  'elasticity_policies' => {
77
81
  :type => :array,
78
82
  :items => {
@@ -220,6 +224,10 @@ module OpenNebula
220
224
  :properties => {}
221
225
  },
222
226
  :required => false
227
+ },
228
+ 'on_hold' => {
229
+ :type => :boolean,
230
+ :required => false
223
231
  }
224
232
  }
225
233
  }
@@ -406,9 +414,6 @@ module OpenNebula
406
414
  return rc
407
415
  end
408
416
 
409
- # add registration time, as the template is new
410
- body['registration_time'] = Integer(Time.now)
411
-
412
417
  # update the template with the new body
413
418
  doc.update(body.to_json)
414
419
 
@@ -460,7 +460,11 @@ module OpenNebula::MarketPlaceAppExt
460
460
  end
461
461
 
462
462
  if !options[:template] || options[:template] == -1
463
- vmtpl = create_vcenter_template(ds, options)
463
+ vmtpl = create_vcenter_template(
464
+ ds,
465
+ options,
466
+ self['TEMPLATE/VMTEMPLATE64']
467
+ )
464
468
  else
465
469
  template_id = options[:template]
466
470
  template = Template.new_with_id(template_id, @client)
@@ -599,6 +603,8 @@ module OpenNebula::MarketPlaceAppExt
599
603
  # :names = [name_a, name_b, ...]
600
604
  exported = {}
601
605
  idx = 0
606
+ idy = 0
607
+ opt_name = ''
602
608
 
603
609
  # Store IDs of created resources
604
610
  images = []
@@ -623,16 +629,35 @@ module OpenNebula::MarketPlaceAppExt
623
629
 
624
630
  obj.extend(MarketPlaceAppExt)
625
631
 
632
+ # Fix name if duplicates exist
633
+ imgp = OpenNebula::ImagePool.new(@client)
634
+ rc = imgp.info
635
+ break rc if OpenNebula.is_error?(rc)
636
+
637
+ img_names = imgp.retrieve_elements('/IMAGE_POOL/IMAGE/NAME')
638
+
639
+ opt_name = options[:name]
640
+ t_short = "#{opt_name}-#{obj_name}-#{idx}"
641
+
642
+ if !img_names.nil? && img_names.include?(t_short)
643
+ idy = 0
644
+ while img_names.include? \
645
+ "#{opt_name}_#{idy}-#{obj_name}-#{idx}"
646
+ idy += 1
647
+ end
648
+ opt_name = "#{opt_name}_#{idy}"
649
+ end
650
+
626
651
  rc = obj.export(
627
652
  :dsid => options[:dsid],
628
- :name => "#{options[:name]}-#{idx}",
653
+ :name => "#{opt_name}-#{obj_name}-#{idx}",
629
654
  :notemplate => options[:notemplate]
630
655
  )
631
656
 
632
- image = rc[:image].first if rc[:image]
633
- vmtemplate = rc[:vmtemplate].first if rc[:vmtemplate]
634
-
657
+ image = rc[:image].first if rc[:image]
635
658
  break image if OpenNebula.is_error?(image)
659
+
660
+ vmtemplate = rc[:vmtemplate].first if rc[:vmtemplate]
636
661
  break vmtemplate if OpenNebula.is_error?(vmtemplate)
637
662
 
638
663
  idx += 1
@@ -676,7 +701,8 @@ module OpenNebula::MarketPlaceAppExt
676
701
  "Error deleting template #{id}"]
677
702
  }
678
703
 
679
- delete_method = 'delete(true)'
704
+ delete_method = 'delete'
705
+ args = true
680
706
  else
681
707
  obj_factory = lambda {|v|
682
708
  id = v[:image].first
@@ -690,7 +716,13 @@ module OpenNebula::MarketPlaceAppExt
690
716
  exported.each do |_, v|
691
717
  obj, err_msg = obj_factory.call(v)
692
718
 
693
- next unless OpenNebula.is_error?(obj.send(delete_method))
719
+ if args
720
+ rc = obj.send(delete_method, args)
721
+ else
722
+ rc = obj.send(delete_method)
723
+ end
724
+
725
+ next unless OpenNebula.is_error?(rc)
694
726
 
695
727
  ret << err_msg
696
728
  end
@@ -56,10 +56,7 @@ module Role
56
56
  'SCALING' => 8,
57
57
  'FAILED_SCALING' => 9,
58
58
  'COOLDOWN' => 10,
59
- 'DEPLOYING_NETS' => 11,
60
- 'UNDEPLOYING_NETS' => 12,
61
- 'FAILED_DEPLOYING_NETS' => 13,
62
- 'FAILED_UNDEPLOYING_NETS' => 14
59
+ 'HOLD' => 11
63
60
  }
64
61
 
65
62
  STATE_STR = [
@@ -74,10 +71,7 @@ module Role
74
71
  'SCALING',
75
72
  'FAILED_SCALING',
76
73
  'COOLDOWN',
77
- 'DEPLOYING_NETS',
78
- 'UNDEPLOYING_NETS',
79
- 'FAILED_DEPLOYING_NETS',
80
- 'FAILED_UNDEPLOYING_NETS'
74
+ 'HOLD'
81
75
  ]
82
76
 
83
77
  # Returns the string representation of the role state
@@ -105,7 +99,8 @@ module Service
105
99
  'DEPLOYING_NETS' => 11,
106
100
  'UNDEPLOYING_NETS' => 12,
107
101
  'FAILED_DEPLOYING_NETS' => 13,
108
- 'FAILED_UNDEPLOYING_NETS' => 14
102
+ 'FAILED_UNDEPLOYING_NETS' => 14,
103
+ 'HOLD' => 15
109
104
  }
110
105
 
111
106
  STATE_STR = [
@@ -123,7 +118,8 @@ module Service
123
118
  'DEPLOYING_NETS',
124
119
  'UNDEPLOYING_NETS',
125
120
  'FAILED_DEPLOYING_NETS',
126
- 'FAILED_UNDEPLOYING_NETS'
121
+ 'FAILED_UNDEPLOYING_NETS',
122
+ 'HOLD'
127
123
  ]
128
124
 
129
125
  # Returns the string representation of the service state
@@ -68,6 +68,8 @@ module OpenNebula::TemplateExt
68
68
 
69
69
  image = image_lookup(disk)
70
70
 
71
+ next unless image
72
+
71
73
  if OpenNebula.is_error?(image)
72
74
  logger.fatal image.message if logger
73
75
 
@@ -318,6 +320,9 @@ module OpenNebula::TemplateExt
318
320
  uname = disk['IMAGE_UNAME']
319
321
  uname ||= self['UNAME']
320
322
 
323
+ # Volatile disk
324
+ return unless name
325
+
321
326
  name.gsub!('"', '')
322
327
  image = @image_lookup_cache.find do |v|
323
328
  v['NAME'] == name && v['UNAME'] == uname
@@ -138,6 +138,28 @@ module OpenNebula::WaitExt
138
138
 
139
139
  # Wait classes and the name published in ZMQ/STATE
140
140
  WAIT = {
141
+ OpenNebula::VirtualNetwork => {
142
+ :event => lambda {|o, s1, _s2|
143
+ "EVENT STATE NET/#{s1}//#{o['ID']}"
144
+ },
145
+
146
+ :in_state => lambda {|o, s1, _s2|
147
+ obj_s = Integer(o['STATE'])
148
+ inx_s = OpenNebula::VirtualNetwork::VN_STATES.index(s1)
149
+
150
+ obj_s == inx_s
151
+ },
152
+
153
+ :in_state_e => lambda {|s1, _s2, content|
154
+ xml = Nokogiri::XML(Base64.decode64(content))
155
+
156
+ obj_s = Integer(xml.xpath('//VNET/STATE').text)
157
+ inx_s = OpenNebula::VirtualNetwork::VN_STATES.index(s1)
158
+
159
+ obj_s == inx_s
160
+ }
161
+ },
162
+
141
163
  OpenNebula::Host => {
142
164
  :event => lambda {|o, s1, _s2|
143
165
  "EVENT STATE HOST/#{s1}//#{o['ID']}"
data/lib/opennebula.rb CHANGED
@@ -77,5 +77,5 @@ require 'opennebula/flow'
77
77
  module OpenNebula
78
78
 
79
79
  # OpenNebula version
80
- VERSION = '6.3.85'
80
+ VERSION = '6.4.0'
81
81
  end
@@ -1695,6 +1695,34 @@ end
1695
1695
  info_nics
1696
1696
  end
1697
1697
 
1698
+ # Clear extraconfig tags from a vCenter VM
1699
+ #
1700
+ def clear_tags
1701
+ keys_to_remove = extra_config_keys
1702
+
1703
+ spec_hash =
1704
+ keys_to_remove.map {|key| { :key => key, :value => '' } }
1705
+
1706
+ spec = RbVmomi::VIM.VirtualMachineConfigSpec(
1707
+ :extraConfig => spec_hash
1708
+ )
1709
+ @item.ReconfigVM_Task(:spec => spec).wait_for_completion
1710
+ end
1711
+
1712
+ # Get extraconfig tags from a vCenter VM
1713
+ #
1714
+ def extra_config_keys
1715
+ keys_to_remove = []
1716
+ @item['config.extraConfig'].each do |extraconfig|
1717
+ next unless extraconfig.key.include?('opennebula.disk') ||
1718
+ extraconfig.key.include?('opennebula.vm') ||
1719
+ extraconfig.key.downcase.include?('remotedisplay')
1720
+
1721
+ keys_to_remove << extraconfig.key
1722
+ end
1723
+ keys_to_remove
1724
+ end
1725
+
1698
1726
  # Get required parameters to use VMware HTML Console SDK
1699
1727
  # To be used with the following SDK:
1700
1728
  # https://code.vmware.com/web/sdk/2.1.0/html-console
@@ -3388,6 +3416,9 @@ end
3388
3416
  pool.info
3389
3417
 
3390
3418
  src_id = pool["/HOST_POOL/HOST[NAME='#{src_host}']/ID"].to_i
3419
+
3420
+ return if src_id == 0
3421
+
3391
3422
  dst_id = pool["/HOST_POOL/HOST[NAME='#{dst_host}']/ID"].to_i
3392
3423
 
3393
3424
  # different destination ds
data/lib/vm_template.rb CHANGED
@@ -975,23 +975,14 @@ module VCenterDriver
975
975
  host_id = vi_client.instance_variable_get '@host_id'
976
976
 
977
977
  begin
978
- nsx_client =
979
- NSXDriver::NSXClient
980
- .new_from_id(
981
- host_id
982
- )
978
+ nsx_client = NSXDriver::NSXClient.new_from_id(host_id)
983
979
  rescue StandardError
984
980
  nsx_client = nil
985
981
  end
986
982
 
987
983
  if !nsx_client.nil?
988
- nsx_net =
989
- NSXDriver::VirtualWire
990
- .new_from_name(
991
- nsx_client,
992
- nic[:net_name]
993
- )
994
-
984
+ nsx_net = NSXDriver::VirtualWire
985
+ .new_from_name(nsx_client, nic[:net_name])
995
986
  config[:nsx_id] = nsx_net.ls_id
996
987
  config[:nsx_vni] = nsx_net.ls_vni
997
988
  config[:nsx_tz_id] = nsx_net.tz_id
@@ -1002,11 +993,8 @@ module VCenterDriver
1002
993
  # so all Standard
1003
994
  # PortGroups are networks and no uplinks
1004
995
  config[:uplink] = false
1005
- config[:sw_name] =
1006
- VCenterDriver::Network
1007
- .virtual_switch(
1008
- nic[:network]
1009
- )
996
+ config[:sw_name] = VCenterDriver::Network
997
+ .virtual_switch(nic[:network])
1010
998
  # NSX-T PortGroups
1011
999
  when VCenterDriver::Network::NETWORK_TYPE_NSXT
1012
1000
  config[:sw_name] = \
@@ -1027,10 +1015,7 @@ module VCenterDriver
1027
1015
  if !nsx_client.nil?
1028
1016
  nsx_net =
1029
1017
  NSXDriver::OpaqueNetwork
1030
- .new_from_name(
1031
- nsx_client,
1032
- nic[:net_name]
1033
- )
1018
+ .new_from_name(nsx_client, nic[:net_name])
1034
1019
 
1035
1020
  config[:nsx_id] = nsx_net.ls_id
1036
1021
  config[:nsx_vni] = nsx_net.ls_vni
@@ -1104,6 +1089,31 @@ module VCenterDriver
1104
1089
  VCenterDriver::VIHelper.clean_ref_hash
1105
1090
  one_vn.info
1106
1091
 
1092
+ # Wait until the virtual network is in ready state
1093
+ t_start = Time.now
1094
+ error = false
1095
+ timeout = 30
1096
+
1097
+ while Time.now - t_start < timeout
1098
+ begin
1099
+ if one_vn.short_state_str == 'rdy'
1100
+ error = false
1101
+ break
1102
+ end
1103
+ rescue StandardError
1104
+ error = true
1105
+ end
1106
+
1107
+ sleep 1
1108
+ one_vn.info
1109
+ end
1110
+
1111
+ if error
1112
+ error_msg = "VNET #{one_vn.id} in state "
1113
+ error_msg += "#{one_vn.short_state_str}, aborting import"
1114
+ raise error_msg
1115
+ end
1116
+
1107
1117
  one_vn
1108
1118
  end
1109
1119
 
data/lib/vmm_importer.rb CHANGED
@@ -47,6 +47,36 @@ module VCenterDriver
47
47
  vm = selected[:one_item] || build
48
48
  template = selected[:template] || import_tmplt
49
49
  template = "DEPLOY_ID = #{vm_ref}\n" + template
50
+
51
+ # Index where start GRAPHICS block
52
+ graphics_index = template.index('GRAPHICS = [')
53
+ unless graphics_index.nil?
54
+ # Index where finish GRAPHICS block
55
+ end_of_graphics = template[graphics_index..-1].index(']') + 1
56
+
57
+ # GRAPHICS block
58
+ graphics_sub_string =
59
+ template[graphics_index, end_of_graphics]
60
+
61
+ # GRAPHICS block with PORT removed
62
+ # OpenNebula will asing a new not used PORT
63
+ graphics_sub_string =
64
+ graphics_sub_string.gsub(/PORT(.*?),[\r\n]/, '')
65
+
66
+ # Index where graphics block finish
67
+ before_graphics = template[0, graphics_index]
68
+
69
+ # Block after graphics block
70
+ after_graphics =
71
+ template[graphics_index..-1][end_of_graphics..-1]
72
+
73
+ # Template with out PORT inside GRAPHICS
74
+ template =
75
+ before_graphics +
76
+ graphics_sub_string +
77
+ after_graphics
78
+ end
79
+
50
80
  host_id = selected[:host] || @list.keys[0]
51
81
 
52
82
  vc_uuid = @vi_client.vim.serviceContent.about.instanceUuid
@@ -56,6 +86,9 @@ module VCenterDriver
56
86
  vc_vm = VCenterDriver::VirtualMachine.new_without_id(@vi_client,
57
87
  vm_ref)
58
88
 
89
+ # clear OpenNebula attributes
90
+ vc_vm.clear_tags
91
+
59
92
  # Importing Wild VMs with snapshots is not supported
60
93
  # https://github.com/OpenNebula/one/issues/1268
61
94
  if vc_vm.snapshots? && vc_vm.disk_keys.empty?
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opennebula
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.3.85.pre
4
+ version: 6.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - OpenNebula
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-18 00:00:00.000000000 Z
11
+ date: 2022-07-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -255,9 +255,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
255
255
  version: '0'
256
256
  required_rubygems_version: !ruby/object:Gem::Requirement
257
257
  requirements:
258
- - - ">"
258
+ - - ">="
259
259
  - !ruby/object:Gem::Version
260
- version: 1.3.1
260
+ version: '0'
261
261
  requirements: []
262
262
  rubygems_version: 3.1.2
263
263
  signing_key: