veewee 0.3.0.alpha5 → 0.3.0.alpha6

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,24 +1,3 @@
1
- # Note: due to a miss manipulation on my side, the veewee03 branch got merged with master
2
- # Therefore the current state of the masterbranch on github is highly unstable
3
-
4
- To refer to the old master, I've put up the state before the error at
5
- <https://github.com/jedi4ever/veewee-old>
6
-
7
- -------
8
-
9
- Maintaining two branches with complete different structures isn't fun. So..... I want to merge the two.
10
-
11
- Veewee03 will bring many new features:
12
-
13
- - kvm and vmware fusion support -
14
- - veewee as a standalone tool tool if you don't use virtualbox,vagrant
15
- - postinstall scripts can now be toggle with --include and --exclude
16
-
17
- Caveat: it's alpha-functional but not as polished as the previous version. But I'm sure with your help this won't take long.
18
-
19
- My apologies for all the pull-requests to the previous version that will not be merged automatically. I'm focusing more on get this version stable and will incorporate the ideas later (some already are)
20
-
21
- ---
22
1
  **VeeWee:** the tool to easily build vagrant base boxes or kvm,virtualbox and fusion images
23
2
 
24
3
  Vagrant is a great tool to test new things or changes in a virtual machine(Virtualbox) using either chef or puppet.
@@ -52,3 +31,7 @@ People have reported good experiences, why don't you give it a try?
52
31
  IDEAS:
53
32
 
54
33
  - Now you integrate this with your CI build to create a daily basebox
34
+
35
+ [whren - 2012/04/12]
36
+
37
+ See [use of pre_postinstall_file in defition.rb](https://github.com/whren/veewee/wiki/Use-of-pre_postinstall_file-in-definition.rb)
@@ -1,5 +1,6 @@
1
1
  Changelog
2
2
  now has include-postinstall, exclude-postinstall
3
+ now has pre_postinstall_file allowing pre postinstall execution (ie to export http_proxy, https_proxy)
3
4
  ostypes are now synchronized accross kvm
4
5
  require libvirt 0.8+ version
5
6
  user veewee instead of vagrant
@@ -13,7 +14,7 @@ Todo:
13
14
  validate vms - + features selection
14
15
  check libvirt version
15
16
  windows test
16
- validation of checks (also - inclide/exclude)
17
+ validation of checks (also - include/exclude)
17
18
  check execs with exit code
18
19
  multinetwork card
19
20
  dkms for kernel installs
data/doc/TODO CHANGED
@@ -54,7 +54,7 @@ Todo:
54
54
  validate vms - + features selection
55
55
  check libvirt version
56
56
  windows test
57
- validation of checks (also - inclide/exclude)
57
+ validation of checks (also - include/exclude)
58
58
  check execs with exit code
59
59
  multinetwork card
60
60
  dkms for kernel installs
@@ -327,7 +327,9 @@ module Fission
327
327
 
328
328
  unless File.binary?(file)
329
329
  text = (File.read file).gsub from, to
330
- File.open(file, 'w'){ |f| f.print text }
330
+ # Force binary mode to prevent windows from putting CR-LF end line style
331
+ # http://www.ruby-forum.com/topic/60697#58748
332
+ File.open(file, 'wb'){ |f| f.print text }
331
333
  end
332
334
 
333
335
  end
@@ -349,7 +351,9 @@ module Fission
349
351
  content=content+"uuid.action = \"create\"\n"
350
352
 
351
353
  # Now rewrite the vmx file
352
- File.open(new_vmx_file,'w'){ |f| f.print content}
354
+ # Force binary mode to prevent windows from putting CR-LF end line style
355
+ # http://www.ruby-forum.com/topic/60697#58748
356
+ File.open(new_vmx_file,'wb'){ |f| f.print content}
353
357
 
354
358
  end
355
359
 
@@ -24,6 +24,8 @@ module Veewee
24
24
  attr_accessor :sudo_cmd
25
25
  attr_accessor :shutdown_cmd
26
26
 
27
+ attr_accessor :pre_postinstall_file
28
+
27
29
  attr_accessor :postinstall_files, :postinstall_timeout
28
30
 
29
31
  attr_accessor :floppy_files
@@ -58,6 +60,7 @@ module Veewee
58
60
  @floppy_files = nil
59
61
 
60
62
  # Default there are no post install files
63
+ @pre_postinstall_file = nil
61
64
  @postinstall_files=[]; @postinstall_timeout = 10000;
62
65
 
63
66
  @iso_file=""
@@ -38,7 +38,7 @@ module Veewee
38
38
  self.create(options)
39
39
 
40
40
  # Check the GUI mode required
41
- env.logger.info "Provider asks the box to start: GUI enabled? #{!options[:nogui]}"
41
+ env.logger.info "Provider asks the box to start: GUI enabled? #{!options['nogui']}"
42
42
  self.up(options)
43
43
 
44
44
  # Waiting for it to boot
@@ -77,6 +77,7 @@ module Veewee
77
77
  self.transfer_buildinfo(options)
78
78
  self.handle_postinstall(options)
79
79
 
80
+
80
81
  env.ui.success "The box #{name} was built succesfully!"
81
82
  env.ui.info "You can now login to the box with:"
82
83
  env.ui.info ssh_command_string
@@ -157,7 +158,7 @@ module Veewee
157
158
  # It requires a definition to find all the necessary information
158
159
  def handle_kickstart(options)
159
160
 
160
- # Filtering post install files based upon --postinstall-include and --postinstall--exclude
161
+ # Filtering post install files based upon --postinstall-include and --postinstall--exclude
161
162
  definition.postinstall_files=filter_postinstall_files(options)
162
163
  # Handling the kickstart by web
163
164
  kickstartfiles=definition.kickstart_file
@@ -190,13 +191,32 @@ module Veewee
190
191
  # This function handles all the post-install scripts
191
192
  # It requires a box(to login to) and a definition(listing the postinstall files)
192
193
  def handle_postinstall(options)
194
+ is_pre_postinstall_file = !definition.pre_postinstall_file.nil? && !definition.pre_postinstall_file.length != 0
195
+ transfered = false
193
196
  definition.postinstall_files.each do |postinstall_file|
194
197
  # Filenames of postinstall_files are relative to their definition
195
198
  filename=File.join(definition.path,postinstall_file)
196
199
  unless File.basename(postinstall_file)=~/^_/
197
200
  self.scp(filename,File.basename(filename))
198
201
  self.exec("chmod +x \"#{File.basename(filename)}\"")
199
- self.exec(sudo("./"+File.basename(filename)))
202
+ if is_pre_postinstall_file
203
+ # Filename of pre_postinstall_file are relative to their definition
204
+ pre_filename=File.join(definition.path, definition.pre_postinstall_file)
205
+ # Upload the pre postinstall script if not already transfered
206
+ if !transfered
207
+ self.scp(pre_filename,File.basename(pre_filename))
208
+ transfered = true
209
+ self.exec("chmod +x \"#{File.basename(pre_filename)}\"")
210
+ # Inject the call to the real script by executing the first argument (it will be the postinstall script file name to be executed)
211
+ self.exec("execute=\"\\n# We must execute the script passed as the first argument\\n\\$1\" && printf \"%b\\n\" \"$execute\" >> #{File.basename(pre_filename)}")
212
+ end
213
+ command = "./" + File.basename(pre_filename)
214
+ command = sudo(command) + " ./"+File.basename(filename)
215
+ else
216
+ command = "./"+File.basename(filename)
217
+ command = sudo(command)
218
+ end
219
+ self.exec(command)
200
220
  else
201
221
  env.logger.info "Skipping postinstallfile #{postinstall_file}"
202
222
  end
@@ -210,6 +230,9 @@ module Veewee
210
230
  build_info.each do |info|
211
231
  begin
212
232
  infofile=Tempfile.open("#{info[:filename]}")
233
+ # Force binary mode to prevent windows from putting CR-LF end line style
234
+ # http://www.ruby-forum.com/topic/127453#568546
235
+ infofile.binmode
213
236
  infofile.puts "#{info[:content]}"
214
237
  infofile.rewind
215
238
  infofile.close
@@ -40,6 +40,9 @@ module Veewee
40
40
  # We assume large 10K files, so this is tempfile object
41
41
  env.logger.info "#{src.class}"
42
42
  env.ui.info "Moving #{src.path} to #{localfile}"
43
+ # Force the close of the src stream to release handle before moving
44
+ # Not forcing the close may cause an issue on windows (Permission Denied)
45
+ src.close
43
46
  FileUtils.mv(src.path,localfile)
44
47
  #open(localfile,"wb") { |dst|
45
48
  #dst.write(src.read)
@@ -51,7 +54,7 @@ module Veewee
51
54
  def hashsum(filename)
52
55
  checksum=Digest::MD5.new
53
56
  buflen=1024
54
- open(filename, "r") do |io|
57
+ open(filename, "rb") do |io|
55
58
  counter = 0
56
59
  while (!io.eof)
57
60
  readBuf = io.readpartial(buflen)
@@ -19,7 +19,7 @@ module Veewee
19
19
  sleep 2
20
20
  end
21
21
 
22
- command="#{@vboxcmd} unregistervm '#{name}' --delete"
22
+ command="#{@vboxcmd} unregistervm \"#{name}\" --delete"
23
23
  env.ui.info command
24
24
  env.ui.info "Deleting vm #{name}"
25
25
 
@@ -39,9 +39,9 @@ module Veewee
39
39
  if location.match(/#{pattern}/)
40
40
 
41
41
  if File.exists?(location)
42
- command="#{@vboxcmd} closemedium disk '#{location}' --delete"
42
+ command="#{@vboxcmd} closemedium disk \"#{location}\" --delete"
43
43
  else
44
- command="#{@vboxcmd} closemedium disk '#{location}'"
44
+ command="#{@vboxcmd} closemedium disk \"#{location}\""
45
45
  end
46
46
 
47
47
  env.ui.info "Deleting disk #{location}"
@@ -44,7 +44,7 @@ module Veewee
44
44
  end
45
45
 
46
46
  def send_keycode(keycode)
47
- command= "#{@vboxcmd} controlvm '#{name}' keyboardputscancode #{keycode}"
47
+ command= "#{@vboxcmd} controlvm \"#{name}\" keyboardputscancode #{keycode}"
48
48
  env.logger.info "#{command}"
49
49
  sshresult=shell_exec("#{command}",{:mute => true})
50
50
  unless sshresult.stdout.index("E_ACCESSDENIED").nil?
@@ -4,21 +4,21 @@ module Veewee
4
4
  module BoxCommand
5
5
 
6
6
  def add_ide_controller
7
- #unless => "${vboxcmd} showvminfo '${vname}' | grep 'IDE Controller' "
8
- command ="#{@vboxcmd} storagectl '#{name}' --name 'IDE Controller' --add ide"
7
+ #unless => "${vboxcmd} showvminfo \"${vname}\" | grep \"IDE Controller\" "
8
+ command ="#{@vboxcmd} storagectl \"#{name}\" --name \"IDE Controller\" --add ide"
9
9
  shell_exec("#{command}")
10
10
  end
11
11
 
12
12
  def add_sata_controller
13
- #unless => "${vboxcmd} showvminfo '${vname}' | grep 'SATA Controller' ";
14
- command ="#{@vboxcmd} storagectl '#{name}' --name 'SATA Controller' --add sata --hostiocache #{definition.hostiocache} --sataportcount 1"
13
+ #unless => "${vboxcmd} showvminfo \"${vname}\" | grep \"SATA Controller\" ";
14
+ command ="#{@vboxcmd} storagectl \"#{name}\" --name \"SATA Controller\" --add sata --hostiocache #{definition.hostiocache} --sataportcount 1"
15
15
  shell_exec("#{command}")
16
16
  end
17
17
 
18
18
  def attach_serial_console
19
- command ="#{@vboxcmd} modifyvm '#{name}' --uart1 0x3F8 4"
19
+ command ="#{@vboxcmd} modifyvm \"#{name}\" --uart1 0x3F8 4"
20
20
  shell_exec("#{command}")
21
- command ="#{@vboxcmd} modifyvm '#{name}' --uartmode1 file '#{File.join(FileUtils.pwd,name+"-serial-console"+'.log')}'"
21
+ command ="#{@vboxcmd} modifyvm \"#{name}\" --uartmode1 file \"#{File.join(FileUtils.pwd,name+"-serial-console"+".log")}\""
22
22
  shell_exec("#{command}")
23
23
  end
24
24
 
@@ -26,20 +26,23 @@ module Veewee
26
26
 
27
27
  unless definition.nil?
28
28
  #Map SSH Ports
29
- command="#{@vboxcmd} modifyvm '#{name}' --natpf#{self.natinterface} 'guestssh,tcp,,#{definition.ssh_host_port},,#{definition.ssh_guest_port}'"
29
+ command="#{@vboxcmd} modifyvm \"#{name}\" --natpf#{self.natinterface} \"guestssh,tcp,,#{definition.ssh_host_port},,#{definition.ssh_guest_port}\""
30
30
  shell_exec("#{command}")
31
31
  end
32
32
  end
33
33
 
34
34
  def add_shared_folder
35
- command="#{@vboxcmd} sharedfolder add '#{name}' --name 'veewee-validation' --hostpath '#{File.expand_path(env.validation_dir)}' --automount"
35
+ command="#{@vboxcmd} sharedfolder add \"#{name}\" --name \"veewee-validation\" --hostpath \"#{File.expand_path(env.validation_dir)}\" --automount"
36
36
  shell_exec("#{command}")
37
37
  end
38
38
 
39
39
  def get_vbox_home
40
40
  command="#{@vboxcmd} list systemproperties"
41
41
  shell_results=shell_exec("#{command}")
42
- location=shell_results.stdout.split(/\n/).grep(/Default machine/)[0].split(":")[1].strip
42
+ # On windows Default machine path would include a drive letter, then ':'.
43
+ # So here we tell to split no more than 2 elements to keep the full path
44
+ # This should work for all OS as we just need to separate the parameter name with first ':' from the value
45
+ location=shell_results.stdout.split(/\n/).grep(/Default machine/)[0].split(":", 2)[1].strip
43
46
  return location
44
47
  end
45
48
 
@@ -55,7 +58,7 @@ module Veewee
55
58
  ["GUI/UpdateCheckCount","60"]
56
59
  ]
57
60
  extraData.each do |data|
58
- command="#{@vboxcmd} setextradata global '#{data[0]}' '#{data[1]}'"
61
+ command="#{@vboxcmd} setextradata global \"#{data[0]}\" \"#{data[1]}\""
59
62
  shell_results=shell_exec("#{command}")
60
63
  end
61
64
 
@@ -67,7 +70,7 @@ module Veewee
67
70
 
68
71
 
69
72
  place=get_vbox_home
70
- command ="#{@vboxcmd} createhd --filename '#{File.join(place,name,name+"."+definition.disk_format.downcase)}' --size '#{definition.disk_size.to_i}' --format #{definition.disk_format.downcase}"
73
+ command ="#{@vboxcmd} createhd --filename \"#{File.join(place,name,name+"."+definition.disk_format.downcase)}\" --size \"#{definition.disk_size.to_i}\" --format #{definition.disk_format.downcase}"
71
74
  shell_exec("#{command}")
72
75
 
73
76
  end
@@ -80,8 +83,8 @@ module Veewee
80
83
  location="#{File.join(place,name,location)}"
81
84
  env.ui.info "Attaching disk: #{location}"
82
85
 
83
- #command => "${vboxcmd} storageattach '${vname}' --storagectl 'SATA Controller' --port 0 --device 0 --type hdd --medium '${vname}.vdi'",
84
- command ="#{@vboxcmd} storageattach '#{name}' --storagectl 'SATA Controller' --port 0 --device 0 --type hdd --medium '#{location}'"
86
+ #command => "${vboxcmd} storageattach \"${vname}\" --storagectl \"SATA Controller\" --port 0 --device 0 --type hdd --medium \"${vname}.vdi\"",
87
+ command ="#{@vboxcmd} storageattach \"#{name}\" --storagectl \"SATA Controller\" --port 0 --device 0 --type hdd --medium \"#{location}\""
85
88
  shell_exec("#{command}")
86
89
 
87
90
  end
@@ -90,14 +93,14 @@ module Veewee
90
93
  def attach_isofile
91
94
  full_iso_file=File.join(env.config.veewee.iso_dir,definition.iso_file)
92
95
  env.ui.info "Mounting cdrom: #{full_iso_file}"
93
- command ="#{@vboxcmd} storageattach '#{name}' --storagectl 'IDE Controller' --type dvddrive --port 0 --device 0 --medium '#{full_iso_file}'"
96
+ command ="#{@vboxcmd} storageattach \"#{name}\" --storagectl \"IDE Controller\" --type dvddrive --port 0 --device 0 --medium \"#{full_iso_file}\""
94
97
  shell_exec("#{command}")
95
98
  end
96
99
 
97
100
  def attach_guest_additions
98
101
  full_iso_file=File.join(env.config.veewee.iso_dir,"VBoxGuestAdditions_#{self.vbox_version}.iso")
99
102
  env.ui.info "Mounting guest additions: #{full_iso_file}"
100
- command ="#{@vboxcmd} storageattach '#{name}' --storagectl 'IDE Controller' --type dvddrive --port 1 --device 0 --medium '#{full_iso_file}'"
103
+ command ="#{@vboxcmd} storageattach \"#{name}\" --storagectl \"IDE Controller\" --type dvddrive --port 1 --device 0 --medium \"#{full_iso_file}\""
101
104
  shell_exec("#{command}")
102
105
  end
103
106
 
@@ -106,7 +109,7 @@ module Veewee
106
109
  # Create floppy controller
107
110
  unless definition.floppy_files.nil?
108
111
 
109
- command="#{@vboxcmd} storagectl '#{name}' --name 'Floppy Controller' --add floppy"
112
+ command="#{@vboxcmd} storagectl \"#{name}\" --name \"Floppy Controller\" --add floppy"
110
113
  shell_exec("#{command}")
111
114
  end
112
115
  end
@@ -117,7 +120,7 @@ module Veewee
117
120
 
118
121
  # Attach floppy to machine (the vfd extension is crucial to detect msdos type floppy)
119
122
  floppy_file=File.join(definition.path,"virtualfloppy.vfd")
120
- command="#{@vboxcmd} storageattach '#{name}' --storagectl 'Floppy Controller' --port 0 --device 0 --type fdd --medium '#{floppy_file}'"
123
+ command="#{@vboxcmd} storageattach \"#{name}\" --storagectl \"Floppy Controller\" --port 0 --device 0 --type fdd --medium \"#{floppy_file}\""
121
124
  shell_exec("#{command}")
122
125
  end
123
126
  end
@@ -129,7 +132,7 @@ module Veewee
129
132
  end
130
133
 
131
134
  def create_vm
132
- command="#{@vboxcmd} createvm --name '#{name}' --ostype '#{vbox_os_type_id(definition.os_type_id)}' --register"
135
+ command="#{@vboxcmd} createvm --name \"#{name}\" --ostype \"#{vbox_os_type_id(definition.os_type_id)}\" --register"
133
136
 
134
137
  #Exec and system stop the execution here
135
138
  shell_exec("#{command}")
@@ -137,15 +140,15 @@ module Veewee
137
140
  env.ui.info "Creating vm #{name} : #{definition.memory_size}M - #{definition.cpu_count} CPU - #{vbox_os_type_id(definition.os_type_id)}"
138
141
 
139
142
  #setting cpu's
140
- command="#{@vboxcmd} modifyvm '#{name}' --cpus #{definition.cpu_count}"
143
+ command="#{@vboxcmd} modifyvm \"#{name}\" --cpus #{definition.cpu_count}"
141
144
  shell_exec("#{command}")
142
145
 
143
146
  #setting memory size
144
- command="#{@vboxcmd} modifyvm '#{name}' --memory #{definition.memory_size}"
147
+ command="#{@vboxcmd} modifyvm \"#{name}\" --memory #{definition.memory_size}"
145
148
  shell_exec("#{command}")
146
149
 
147
150
  #setting bootorder
148
- command="#{@vboxcmd} modifyvm '#{name}' --boot1 disk --boot2 dvd --boot3 none --boot4 none"
151
+ command="#{@vboxcmd} modifyvm \"#{name}\" --boot1 disk --boot2 dvd --boot3 none --boot4 none"
149
152
  shell_exec("#{command}")
150
153
 
151
154
  # Modify the vm to enable or disable hw virtualization extensions
@@ -4,7 +4,7 @@ module Veewee
4
4
  module BoxCommand
5
5
 
6
6
  def forwarding(name)
7
- command="#{@vboxcmd} showvminfo --details --machinereadable '#{self.name}'"
7
+ command="#{@vboxcmd} showvminfo --details --machinereadable \"#{self.name}\""
8
8
  shell_results=shell_exec("#{command}")
9
9
  rules=shell_results.stdout.split(/\n/).grep(/^Forward/)
10
10
  result=nil
@@ -28,7 +28,7 @@ module Veewee
28
28
 
29
29
  def delete_forwarding(name)
30
30
  forward=self.forwarding(name)
31
- command="#{@vboxcmd} controlvm '#{self.name}' natpf#{self.natinterface} delete #{name}"
31
+ command="#{@vboxcmd} controlvm \"#{self.name}\" natpf#{self.natinterface} delete #{name}"
32
32
  shell_results=shell_exec("#{command}")
33
33
  end
34
34
 
@@ -8,7 +8,7 @@ module Veewee
8
8
  if (self.exists? && self.running?)
9
9
  env.ui.info "Shutting down vm #{name}"
10
10
  #We force it here, maybe vm.shutdown is cleaner
11
- command="#{@vboxcmd} controlvm '#{name}' poweroff"
11
+ command="#{@vboxcmd} controlvm \"#{name}\" poweroff"
12
12
  shell_exec("#{command}")
13
13
  end
14
14
  end
@@ -10,7 +10,7 @@ module Veewee
10
10
  exit -1
11
11
  end
12
12
 
13
- gui_enabled=options[:nogui]==true ? false : true
13
+ gui_enabled=options['nogui']==true ? false : true
14
14
 
15
15
  raise Veewee::Error,"Box is already running" if self.running?
16
16
 
@@ -35,9 +35,9 @@ module Veewee
35
35
  # Once assembled we start the machine
36
36
  env.logger.info "Started the VM with GUI Enabled? #{gui_enabled}"
37
37
 
38
- command="#{@vboxcmd} startvm --type gui '#{name}'"
38
+ command="#{@vboxcmd} startvm --type gui \"#{name}\""
39
39
  unless (gui_enabled)
40
- command="#{@vboxcmd} startvm --type headless '#{name}'"
40
+ command="#{@vboxcmd} startvm --type headless \"#{name}\""
41
41
  end
42
42
  shell_results=shell_exec("#{command}",{:mute => true})
43
43
  end
@@ -4,5 +4,5 @@ end
4
4
 
5
5
  # Only set the version constant if it wasn't set before
6
6
  unless defined?(Veewee::VERSION)
7
- ::Veewee::VERSION="0.3.0.alpha5"
7
+ ::Veewee::VERSION="0.3.0.alpha6"
8
8
  end
@@ -32,7 +32,10 @@ Gem::Specification.new do |s|
32
32
  s.add_dependency "fog", "~> 1.1.2"
33
33
  s.add_dependency "childprocess"
34
34
 
35
- s.add_dependency "CFPropertyList", "~> 2.0.17"
35
+ # Modified dependency version, as libxml-ruby dependency has been removed in version 2.1.1
36
+ # See : https://github.com/ckruse/CFPropertyList/issues/14
37
+ # See : https://github.com/jedi4ever/veewee/issues/6
38
+ s.add_dependency "CFPropertyList", ">= 2.1.1"
36
39
  # s.add_dependency "libvirt"
37
40
  s.add_dependency "rspec", "~> 2.5"
38
41
 
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: veewee
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: 6
5
- version: 0.3.0.alpha5
5
+ version: 0.3.0.alpha6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Patrick Debois
@@ -149,9 +149,9 @@ dependencies:
149
149
  requirement: &id013 !ruby/object:Gem::Requirement
150
150
  none: false
151
151
  requirements:
152
- - - ~>
152
+ - - ">="
153
153
  - !ruby/object:Gem::Version
154
- version: 2.0.17
154
+ version: 2.1.1
155
155
  type: :runtime
156
156
  prerelease: false
157
157
  version_requirements: *id013
@@ -916,7 +916,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
916
916
  requirements:
917
917
  - - ">="
918
918
  - !ruby/object:Gem::Version
919
- hash: -2945739560758709107
919
+ hash: -1280042332517595849
920
920
  segments:
921
921
  - 0
922
922
  version: "0"