vagrant-zone 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f3c18117a8a3b345b488063565bc03e4778ae50dd4e21f09cd5309de2e043a66
4
+ data.tar.gz: 474569e09d7c50e88021065c28741c2326d6aa0d5fdafe0a6f1aae5cfc394a5f
5
+ SHA512:
6
+ metadata.gz: feec0720ba256d2f6b05495dee6df5c860336cf4749d7a9467891a3d36f01b7c92989bfa856493ea7012630ec7276899713dec53567e551d907cb886ce3166a4
7
+ data.tar.gz: 34a58b2d76e8fe2e6cde84ac567edf0fc478af356c0c9f8ed0b140a8b06ef4ebdab4e605e7cb5c1fd938f73ee4d12eb38af40d92a4f915caaa7f8d931394a2b3
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .bundle
2
+ vendor
3
+ bin
4
+ *.lock
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'vagrant', :git => "https://github.com/hashicorp/vagrant", :tag => "v2.2.7"
7
+ end
8
+
9
+ group :plugins do
10
+ gemspec
11
+ end
data/Vagrantfile ADDED
@@ -0,0 +1,55 @@
1
+ Vagrant.configure("2") do |config|
2
+ config.vm.define :debian do |debian|
3
+ debian.vm.box = 'debian.zss'
4
+ debian.vm.network "public_network",
5
+ ip: "192.168.122.28", bridge: "e1000g0", auto_config: false, :netmask => "255.255.255.0", gateway: "192.168.122.1"
6
+
7
+ debian.vm.provision "shell",
8
+ inline: "id > /home/vagrant/id"
9
+
10
+ debian.vm.provision "ansible_local" do |ansible|
11
+ ansible.playbook = "playbook.yml"
12
+ ansible.install = true
13
+ end
14
+
15
+ debian.vm.provider :zone do |vm|
16
+ vm.brand = 'lx'
17
+ vm.kernel = '4.10'
18
+ vm.zonepath = '/rpool/debian'
19
+ vm.memory = '512M'
20
+ end
21
+ end
22
+
23
+ config.vm.define :centos do |centos|
24
+ centos.vm.box = '3dbbdcca-2eab-11e8-b925-23bf77789921'
25
+ centos.vm.network "public_network",
26
+ ip: "192.168.122.29", bridge: "e1000g0", auto_config: false, :netmask => "255.255.255.0", gateway: "192.168.122.1"
27
+
28
+ centos.vm.provision "shell",
29
+ inline: "id > /home/vagrant/id"
30
+
31
+ centos.vm.provision "ansible_local" do |ansible|
32
+ ansible.playbook = "playbook.yml"
33
+ ansible.install = true
34
+ end
35
+
36
+ centos.vm.provider :zone do |vm|
37
+ vm.brand = 'lx'
38
+ vm.kernel = '3.10.0'
39
+ vm.zonepath = '/rpool/centos'
40
+ vm.memory = '512M'
41
+ end
42
+ end
43
+
44
+ config.vm.define :example do |example|
45
+ example.vm.box = 'example'
46
+ example.vm.network "public_network",
47
+ ip: "192.168.122.30", bridge: "e1000g0", auto_config: false, :netmask => "255.255.255.0", gateway: "192.168.122.1"
48
+
49
+ example.vm.provider :zone do |vm|
50
+ vm.brand = 'lx'
51
+ vm.zonepath = '/rpool/example'
52
+ vm.memory = '512M'
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,21 @@
1
+ require "pathname"
2
+
3
+ module VagrantPlugins
4
+ module ProviderZone
5
+ lib_path = Pathname.new(File.expand_path("../vagrant-zone", __FILE__))
6
+
7
+ autoload :Action, lib_path.join('action')
8
+ autoload :Executor, lib_path.join('executor')
9
+ autoload :Driver, lib_path.join('driver')
10
+ autoload :Errors, lib_path.join('errors')
11
+
12
+ # This function returns the path to the source of this plugin
13
+ #
14
+ # @return [Pathname]
15
+ def self.source_root
16
+ @source_root ||= Pathname.new(File.expand_path("../../", __FILE__))
17
+ end
18
+ end
19
+ end
20
+
21
+ require "vagrant-zone/plugin"
@@ -0,0 +1,147 @@
1
+ require "vagrant/action/builder"
2
+ require 'log4r'
3
+
4
+ module VagrantPlugins
5
+ module ProviderZone
6
+ module Action
7
+ # Include the built-in modules so we can use them as top-level things.
8
+ include Vagrant::Action::Builtin
9
+ @logger = Log4r::Logger.new('vagrant_zone::action')
10
+
11
+ # This action is called to bring the box up from nothing.
12
+ def self.action_up
13
+ Vagrant::Action::Builder.new.tap do |b|
14
+ b.use Call, IsCreated do |env, b2|
15
+ re = env[:result]
16
+ m = env[:machine].state.id
17
+
18
+ if !env[:result]
19
+ b2.use Import
20
+ b2.use Create
21
+ b2.use Network
22
+ b2.use Start
23
+ b2.use Setup
24
+ #b2.use PrepareNFSValidIds
25
+ #b2.use SyncedFolderCleanup
26
+ #b2.use SyncedFolders
27
+ b2.use WaitTillUp
28
+ b2.use Provision
29
+ else
30
+ env[:halt_on_error] = true
31
+ b2.use action_start
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ # Assuming VM is created, just start it. This action is not called
38
+ # directly by any subcommand.
39
+ def self.action_start
40
+ Vagrant::Action::Builder.new.tap do |b|
41
+ b.use Call, IsState, :running do |env, b1|
42
+ if env[:result]
43
+ b1.use Message, I18n.t('vagrant_zone.states.is_running')
44
+ next
45
+ end
46
+ b1.use Call, IsState, :uncleaned do |env1, b2|
47
+ if env1[:result]
48
+ b2.use Cleanup
49
+ end
50
+ end
51
+
52
+ b1.use Start
53
+ b1.use Setup
54
+ end
55
+ end
56
+ end
57
+
58
+ # This is the action that is primarily responsible for halting the
59
+ # virtual machine.
60
+ def self.action_halt
61
+ Vagrant::Action::Builder.new.tap do |b|
62
+ b.use Call, IsCreated do |env, b2|
63
+ unless env[:result]
64
+ b2.use NotCreated
65
+ next
66
+ end
67
+
68
+ if env[:result]
69
+ # VM is running, halt it
70
+ b2.use Halt
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ # This action is called to SSH into the machine.
77
+ def self.action_ssh
78
+ Vagrant::Action::Builder.new.tap do |b|
79
+ b.use SSHExec
80
+ end
81
+ end
82
+ def self.action_ssh_run
83
+ Vagrant::Action::Builder.new.tap do |b|
84
+ b.use SSHRun
85
+ end
86
+ end
87
+
88
+ # This action is called when you try to package an existing virtual
89
+ # machine to an box image.
90
+ def self.action_package
91
+ Vagrant::Action::Builder.new.tap do |b|
92
+ b.use Package
93
+ end
94
+ end
95
+
96
+ # This is the action that is primarily responsible for completely
97
+ # freeing the resources of the underlying virtual machine.
98
+ def self.action_destroy
99
+ Vagrant::Action::Builder.new.tap do |b|
100
+ b.use Call, IsCreated do |env, b2|
101
+ b2.use Destroy
102
+ end
103
+ end
104
+ end
105
+
106
+ # This action is called when `vagrant provision` is called.
107
+ def self.action_provision
108
+ Vagrant::Action::Builder.new.tap do |b|
109
+ b.use Call, IsCreated do |env, b2|
110
+ b2.use Call, IsState, :running do |env, b3|
111
+ b3.use Provision
112
+ end
113
+ end
114
+ end
115
+ end
116
+
117
+ # This is the action implements the reload command
118
+ # It uses the halt and start actions
119
+ def self.action_reload
120
+ Vagrant::Action::Builder.new.tap do |b|
121
+ b.use Call, IsCreated do |env, b2|
122
+ unless env[:result]
123
+ b2.use NotCreated
124
+ next
125
+ end
126
+ b2.use action_halt
127
+ b2.use action_start
128
+ end
129
+ end
130
+ end
131
+
132
+ action_root = Pathname.new(File.expand_path('../action', __FILE__))
133
+ autoload :Import, action_root.join('import')
134
+ autoload :Create, action_root.join('create')
135
+ autoload :Network, action_root.join('network')
136
+ autoload :Setup, action_root.join('setup')
137
+ autoload :Start, action_root.join('start')
138
+ autoload :IsCreated, action_root.join('is_created')
139
+ autoload :NotCreated, action_root.join('not_created')
140
+ autoload :Halt, action_root.join('halt')
141
+ autoload :Destroy, action_root.join('destroy')
142
+ autoload :WaitTillUp, action_root.join('wait_till_up')
143
+ autoload :PrepareNFSValidIds, action_root.join('prepare_nfs_valid_ids.rb')
144
+ autoload :Package, action_root.join('package.rb')
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,26 @@
1
+ require "log4r"
2
+ require "securerandom"
3
+ require "digest/md5"
4
+
5
+ module VagrantPlugins
6
+ module ProviderZone
7
+ module Action
8
+ class Create
9
+ def initialize(app, env)
10
+ @logger = Log4r::Logger.new("vagrant_zone::action::import")
11
+ @app = app
12
+ end
13
+
14
+ def call(env)
15
+ @machine = env[:machine]
16
+ @driver = @machine.provider.driver
17
+
18
+ @machine.id = SecureRandom.uuid
19
+ @driver.zonecfg(@machine, env[:ui])
20
+ @driver.install(@machine, env[:ui])
21
+ @app.call(env)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,24 @@
1
+ require "log4r"
2
+ require "securerandom"
3
+ require "digest/md5"
4
+
5
+ module VagrantPlugins
6
+ module ProviderZone
7
+ module Action
8
+ class Destroy
9
+ def initialize(app, env)
10
+ @logger = Log4r::Logger.new("vagrant_zone::action::import")
11
+ @app = app
12
+ end
13
+
14
+ def call(env)
15
+ @machine = env[:machine]
16
+ @driver = @machine.provider.driver
17
+
18
+ @driver.destroy(@machine, env[:ui])
19
+ @app.call(env)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module ProviderZone
5
+ module Action
6
+ class Halt
7
+ def initialize(app, env)
8
+ @logger = Log4r::Logger.new("vagrant_zone::action::import")
9
+ @app = app
10
+ end
11
+
12
+ def call(env)
13
+ @machine = env[:machine]
14
+ @driver = @machine.provider.driver
15
+
16
+ @driver.halt(@machine, env[:ui])
17
+ @app.call(env)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,65 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module ProviderZone
5
+ module Action
6
+ class Import
7
+ def initialize(app, env)
8
+ @logger = Log4r::Logger.new("vagrant_zone::action::import")
9
+ @joyent_images_url = 'https://images.joyent.com/images/'
10
+ @app = app
11
+ end
12
+
13
+ def validate_uuid_format(uuid)
14
+ uuid_regex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
15
+ return true if uuid_regex.match?(uuid.to_s.downcase)
16
+ end
17
+
18
+ def call(env)
19
+ @machine = env[:machine]
20
+ image = @machine.config.vm.box
21
+ curdir = Dir.pwd
22
+ datadir = @machine.data_dir
23
+ @logger.info("DATADIR #{datadir}")
24
+ # If image ends on '.zss' it's a local ZFS snapshot which
25
+ # should be used
26
+ if image[-4, 4] == '.zss'
27
+ if File.exist?(curdir + '/' + image)
28
+ FileUtils.cp(curdir + '/' + image, datadir.to_s + '/' + image)
29
+ elsif not File.exist?(datadir.to_s + '/' + image)
30
+ raise Vagrant::Errors::BoxNotFound
31
+ end
32
+ ## If image looks like an UUID, download the ZFS snapshot from
33
+ ## Joyent images server
34
+ elsif validate_uuid_format(image)
35
+ raise Vagrant::Errors::BoxNotFound if not check(image)
36
+ download(image, datadir.to_s + '/' + image)
37
+ ## If it's a regular name (everything else), try to find it
38
+ ## on Vagrant Cloud
39
+ else
40
+ # Support zss format only for now
41
+ box_format = env[:machine].box.metadata['format']
42
+ if box_format.nil?
43
+ raise Errors::NoBoxFormatSet
44
+ elsif box_format != 'zss'
45
+ raise Errors::WrongBoxFormatSet
46
+ end
47
+
48
+ box_image_file = env[:machine].box.directory.join('box.zss').to_s
49
+ FileUtils.cp(env[:machine].box.directory.join('box.zss').to_s, datadir.to_s + '/' + image)
50
+ end
51
+ @app.call(env)
52
+ end
53
+
54
+ def check(uuid)
55
+ `curl --output /dev/null --silent -r 0-0 --fail #{@joyent_images_url}/#{uuid}`
56
+ return $?.success?
57
+ end
58
+ def download(uuid, dest)
59
+ `curl --output #{dest} --silent #{@joyent_images_url}/#{uuid}/file`
60
+ return $?.success?
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,22 @@
1
+ require 'log4r'
2
+
3
+ module VagrantPlugins
4
+ module ProviderZone
5
+ module Action
6
+ # This can be used with "Call" built-in to check if the machine
7
+ # is created and branch in the middleware.
8
+ class IsCreated
9
+ def initialize(app, _env)
10
+ @app = app
11
+ @logger = Log4r::Logger.new('vagrant_zone::action')
12
+ end
13
+
14
+ def call(env)
15
+ m = env[:machine].state.id
16
+ env[:result] = env[:machine].state.id != :not_created
17
+ @app.call(env)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ require "log4r"
2
+ require "securerandom"
3
+ require "digest/md5"
4
+
5
+ module VagrantPlugins
6
+ module ProviderZone
7
+ module Action
8
+ class Network
9
+ def initialize(app, env)
10
+ @logger = Log4r::Logger.new("vagrant_zone::action::import")
11
+ @app = app
12
+ end
13
+
14
+ def call(env)
15
+ @machine = env[:machine]
16
+ @driver = @machine.provider.driver
17
+
18
+ @driver.create_vnic(@machine, env[:ui])
19
+ @app.call(env)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ require 'log4r'
2
+
3
+ module VagrantPlugins
4
+ module ProviderZone
5
+ module Action
6
+ class NotCreated
7
+ def initialize(app, _env)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ env[:ui].info(I18n.t('vagrant_zone.states.not_created'))
13
+ @app.call(env)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,108 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module ProviderZone
5
+ module Action
6
+ class Package
7
+ def initialize(app, env)
8
+ @logger = Log4r::Logger.new("vagrant_zone::action::import")
9
+ @app = app
10
+ env['package.output'] ||= 'package.box'
11
+ end
12
+
13
+
14
+
15
+ def call(env)
16
+ @machine = env[:machine]
17
+ @driver = @machine.provider.driver
18
+
19
+ boxname = env['package.output']
20
+ raise "#{boxname}: Already exists" if File.exist?(boxname)
21
+
22
+ tmp_dir = Dir.pwd + '/_tmp_package'
23
+ tmp_img = tmp_dir + '/box.zss'
24
+ Dir.mkdir(tmp_dir) unless File.exists?(tmp_dir)
25
+
26
+ zonepath = @machine.provider_config.zonepath.sub!(/^\//, '')
27
+ brand = @machine.provider_config.brand
28
+ kernel = @machine.provider_config.kernel
29
+
30
+ snapshot_create(zonepath)
31
+ snapshot_send(zonepath, tmp_img)
32
+ snapshot_delete(zonepath)
33
+
34
+ extra = ''
35
+ @tmp_include = tmp_dir + '/_include'
36
+ if env['package.include']
37
+ extra = './_include'
38
+ Dir.mkdir(@tmp_include)
39
+ env['package.include'].each do |f|
40
+ env[:ui].info("Including user file: #{f}")
41
+ FileUtils.cp(f, @tmp_include)
42
+ end
43
+ end
44
+ if env['package.vagrantfile']
45
+ extra = './_include'
46
+ Dir.mkdir(@tmp_include) unless File.directory?(@tmp_include)
47
+ env[:ui].info('Including user Vagrantfile')
48
+ FileUtils.cp(env['package.vagrantfile'], @tmp_include + '/Vagrantfile')
49
+ end
50
+
51
+ File.write(tmp_dir + '/metadata.json', metadata_content(brand, kernel))
52
+ File.write(tmp_dir + '/Vagrantfile', vagrantfile_content(brand, kernel, zonepath))
53
+
54
+ Dir.chdir(tmp_dir)
55
+ assemble_box(boxname, extra)
56
+
57
+ FileUtils.mv(tmp_dir + '/' + boxname, '../' + boxname)
58
+ FileUtils.rm_rf(tmp_dir)
59
+
60
+ env[:ui].info('Box created')
61
+ env[:ui].info('You can now add the box:')
62
+ env[:ui].info("vagrant box add #{boxname} --name any_comfortable_name")
63
+
64
+ @app.call(env)
65
+ end
66
+
67
+ def snapshot_create(zonepath)
68
+ `pfexec zfs snapshot -r #{zonepath}@vagrant_boxing`
69
+ end
70
+ def snapshot_delete(zonepath)
71
+ `pfexec zfs destroy #{zonepath}@vagrant_boxing`
72
+ end
73
+ def snapshot_send(zonepath, destination)
74
+ `pfexec zfs send #{zonepath}@vagrant_boxing > #{destination}`
75
+ end
76
+
77
+ def metadata_content(brand, kernel)
78
+ <<-EOF
79
+ {
80
+ "provider": "zone",
81
+ "format": "zss",
82
+ "brand": "#{brand}",
83
+ "kernel": "#{kernel}"
84
+ }
85
+ EOF
86
+ end
87
+
88
+ def vagrantfile_content(brand, kernel, zonepath)
89
+ <<-EOF
90
+ Vagrant.configure("2") do |config|
91
+ config.vm.provider :zone do |zone|
92
+ zone.brand = "#{brand}"
93
+ zone.kernel = "#{kernel}"
94
+ zone.zonepath = "#{zonepath}"
95
+ end
96
+ end
97
+ user_vagrantfile = File.expand_path('../_include/Vagrantfile', __FILE__)
98
+ load user_vagrantfile if File.exists?(user_vagrantfile)
99
+ EOF
100
+ end
101
+
102
+ def assemble_box(boxname, extra)
103
+ `tar cvzf "#{boxname}" ./metadata.json ./Vagrantfile ./box.zss #{extra}`
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,22 @@
1
+ require "log4r"
2
+ require "securerandom"
3
+ require "digest/md5"
4
+
5
+ module VagrantPlugins
6
+ module ProviderZone
7
+ module Action
8
+ class PrepareNFSValidIds
9
+
10
+ def initialize(app, env)
11
+ @logger = Log4r::Logger.new("vagrant_zone::action::prepare_nfs_valid_ids")
12
+ @app = app
13
+ end
14
+
15
+ def call(env)
16
+ env[:nfs_valid_ids] = [env[:machine].id]
17
+ @app.call(env)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ require "log4r"
2
+ require "securerandom"
3
+ require "digest/md5"
4
+
5
+ module VagrantPlugins
6
+ module ProviderZone
7
+ module Action
8
+ class Setup
9
+ def initialize(app, env)
10
+ @logger = Log4r::Logger.new("vagrant_zone::action::import")
11
+ @app = app
12
+ end
13
+
14
+ def call(env)
15
+ @machine = env[:machine]
16
+ @driver = @machine.provider.driver
17
+
18
+ @driver.setup(@machine, env[:ui])
19
+ @app.call(env)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module ProviderZone
5
+ module Action
6
+ class Start
7
+ def initialize(app, env)
8
+ @logger = Log4r::Logger.new("vagrant_zone::action::import")
9
+ @app = app
10
+ end
11
+
12
+ def call(env)
13
+ @machine = env[:machine]
14
+ @driver = @machine.provider.driver
15
+
16
+ @driver.boot(@machine, env[:ui])
17
+ @app.call(env)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,42 @@
1
+ require "log4r"
2
+ require 'vagrant-zone/util/timer'
3
+ require 'vagrant/util/retryable'
4
+
5
+ module VagrantPlugins
6
+ module ProviderZone
7
+ module Action
8
+ class WaitTillUp
9
+ include Vagrant::Util::Retryable
10
+
11
+ def initialize(app, env)
12
+ @logger = Log4r::Logger.new("vagrant_zone::action::import")
13
+ @app = app
14
+ end
15
+
16
+ def call(env)
17
+ @machine = env[:machine]
18
+ @driver = @machine.provider.driver
19
+
20
+ # Initialize metrics if they haven't been
21
+ env[:metrics] ||= {}
22
+
23
+ env[:metrics]['instance_ssh_time'] = Util::Timer.time do
24
+ retryable(on: Errors::TimeoutError, tries: 60) do
25
+ # If we're interrupted don't worry about waiting
26
+ next if env[:interrupted]
27
+ loop do
28
+ break if env[:interrupted]
29
+ break if env[:machine].communicate.ready?
30
+ end
31
+ end
32
+ end
33
+ # if interrupted above, just terminate immediately
34
+ return terminate(env) if env[:interrupted]
35
+ @logger.info("Time for SSH ready: #{env[:metrics]['instance_ssh_time']}")
36
+
37
+ @app.call(env)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,22 @@
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module ProviderZone
5
+ class Config < Vagrant.plugin('2', :config)
6
+ attr_accessor :brand
7
+ attr_accessor :autoboot
8
+ attr_accessor :kernel
9
+ attr_accessor :zonepath
10
+ attr_accessor :memory
11
+
12
+ def initialize
13
+ # pkgsrc, lx, bhyve, kvm, illumos
14
+ @brand = UNSET_VALUE
15
+ @autoboot = false
16
+ @kernel = UNSET_VALUE
17
+ @zonepath = UNSET_VALUE
18
+ @memory = UNSET_VALUE
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,170 @@
1
+ require "log4r"
2
+ require "fileutils"
3
+ require "digest/md5"
4
+ require "io/console"
5
+ require "ruby_expect"
6
+ require 'netaddr'
7
+
8
+ module VagrantPlugins
9
+ module ProviderZone
10
+ class Driver
11
+ attr_accessor :executor
12
+
13
+ def initialize(machine)
14
+ @logger = Log4r::Logger.new("vagrant_zone::driver")
15
+ @machine = machine
16
+ @executor = Executor::Exec.new
17
+
18
+ if Process.uid == 0
19
+ @pfexec = ''
20
+ else
21
+ sudo = system('sudo -v')
22
+ if sudo
23
+ @pfexec = 'sudo'
24
+ else
25
+ @pfexec = 'pfexec'
26
+ end
27
+ end
28
+ end
29
+
30
+ def state(machine)
31
+ uuid = machine.id
32
+ name = machine.name
33
+ vm_state = execute(false, "#{@pfexec} zoneadm -z #{name} list -p | awk -F: '{ print $3 }'")
34
+ if vm_state == 'running'
35
+ :running
36
+ elsif vm_state == 'configured'
37
+ :preparing
38
+ elsif vm_state == 'installed'
39
+ :stopped
40
+ else
41
+ :not_created
42
+ end
43
+ end
44
+
45
+ def execute(*cmd, **opts, &block)
46
+ @executor.execute(*cmd, **opts, &block)
47
+ end
48
+
49
+ def get_ip_address(machine)
50
+ name = @machine.name
51
+ ip = execute(false, "#{@pfexec} zonecfg -z #{name} info net | sed -n 's|property: (name=ips,value=\"\\(.*\\)/.*\")|\\1|p'")
52
+ return nil if ip.length == 0
53
+ return ip.gsub /\t/, ''
54
+ end
55
+
56
+ def install(machine, ui)
57
+ box = @machine.data_dir.to_s + '/' + @machine.config.vm.box
58
+ name = @machine.name
59
+ execute(false, "#{@pfexec} zoneadm -z #{name} install -s #{box}")
60
+ end
61
+
62
+ def boot(machine, ui)
63
+ name = @machine.name
64
+ execute(false, "#{@pfexec} zoneadm -z #{name} boot")
65
+ end
66
+
67
+ def create_vnic(machine, ui)
68
+ machine.config.vm.networks.each do |_type, opts|
69
+ if _type.to_s == "public_network"
70
+ link = opts[:bridge]
71
+ mac = 'auto'
72
+ if !opts[:mac].nil?
73
+ mac = opts[:mac]
74
+ end
75
+ execute(false, "#{@pfexec} dladm create-vnic -l #{link} -m #{mac} #{machine.name}0")
76
+ end
77
+ end
78
+ end
79
+
80
+ def zonecfg(machine, ui)
81
+ config = machine.provider_config
82
+ machine.config.vm.networks.each do |_type, opts|
83
+ if _type.to_s == "public_network"
84
+ @ip = opts[:ip].to_s
85
+ @network = NetAddr.parse_net(opts[:ip].to_s + '/' + opts[:netmask].to_s)
86
+ @defrouter = opts[:gateway]
87
+ end
88
+ end
89
+
90
+ allowed_address = @ip + @network.netmask.to_s
91
+ lofs_current_dir = Dir.pwd
92
+
93
+ data = %{
94
+ create
95
+ set zonepath=#{config.zonepath}
96
+ set brand=#{config.brand}
97
+ set autoboot=false
98
+ add net
99
+ set physical=#{machine.name}0
100
+ set global-nic=auto
101
+ add property (name=gateway,value="#{@defrouter.to_s}")
102
+ add property (name=ips,value="#{allowed_address}")
103
+ add property (name=primary,value="true")
104
+ end
105
+ add attr
106
+ set name=kernel-version
107
+ set type=string
108
+ set value=#{config.kernel}
109
+ end
110
+ add capped-memory
111
+ set physical=#{config.memory}
112
+ set swap=#{config.memory}
113
+ set locked=#{config.memory}
114
+ end
115
+ add fs
116
+ set dir=/vagrant
117
+ set special=#{lofs_current_dir}
118
+ set type=lofs
119
+ end
120
+ set max-lwps=2000
121
+ exit
122
+ }
123
+ File.open('zone_config', 'w') do |f|
124
+ f.puts data
125
+ end
126
+ execute(false, "cat zone_config | #{@pfexec} zonecfg -z #{machine.name}")
127
+ end
128
+
129
+ def setup(machine, ui)
130
+ zlogin(machine, %('echo nameserver 1.1.1.1 >> /etc/resolv.conf'))
131
+ if not user_exists?(machine)
132
+ zlogin(machine, "useradd -m -s /bin/bash -U vagrant")
133
+ end
134
+ zlogin(machine, %('echo "vagrant ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers.d/vagrant'))
135
+ zlogin(machine, "mkdir -p /home/vagrant/.ssh")
136
+ zlogin(machine, %('echo "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key" > /home/vagrant/.ssh/authorized_keys'))
137
+ zlogin(machine, "chown -R vagrant:vagrant /home/vagrant/.ssh")
138
+ zlogin(machine, "chmod 600 /home/vagrant/.ssh/authorized_keys")
139
+ end
140
+
141
+ def zlogin(machine, cmd)
142
+ name = @machine.name
143
+ execute(false, "#{@pfexec} zlogin #{name} #{cmd}")
144
+ end
145
+
146
+ def user_exists?(machine, user = 'vagrant')
147
+ name = @machine.name
148
+ ret = execute(true, "#{@pfexec} zlogin #{name} id -u #{user}")
149
+ if ret == 0
150
+ return true
151
+ end
152
+ return false
153
+ end
154
+
155
+ def halt(machine, ui)
156
+ name = @machine.name
157
+ execute(false, "#{@pfexec} zoneadm -z #{name} halt")
158
+ end
159
+
160
+ def destroy(machine, id)
161
+ name = @machine.name
162
+ execute(false, "#{@pfexec} zoneadm -z #{name} halt")
163
+ execute(false, "#{@pfexec} zoneadm -z #{name} uninstall -F")
164
+ execute(false, "#{@pfexec} zonecfg -z #{name} delete -F")
165
+ execute(false, "#{@pfexec} dladm delete-vnic #{name}0")
166
+
167
+ end
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,27 @@
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module ProviderZone
5
+ module Errors
6
+ class VagrantZoneError < Vagrant::Errors::VagrantError
7
+ error_namespace('vagrant_zone.errors')
8
+ end
9
+
10
+ class SystemVersionIsTooLow < VagrantZoneError
11
+ error_key(:system_version_too_low)
12
+ end
13
+
14
+ class HasNoRootPrivilege < VagrantZoneError
15
+ error_key(:has_no_root_privilege)
16
+ end
17
+
18
+ class ExecuteError < VagrantZoneError
19
+ error_key(:execute_error)
20
+ end
21
+
22
+ class TimeoutError < VagrantZoneError
23
+ error_key(:timeout_error)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,38 @@
1
+ require "vagrant/util/busy"
2
+ require "vagrant/util/subprocess"
3
+
4
+ module VagrantPlugins
5
+ module ProviderZone
6
+ module Executor
7
+ # This class is used to execute commands as subprocess.
8
+ class Exec
9
+ # When we need the command's exit code we should set parameter
10
+ # exit_code to true, otherwise this method will return executed
11
+ # command's stdout
12
+ def execute(exit_code, *cmd, **opts, &block)
13
+ # Append in the options for subprocess
14
+ cmd << { notify: [:stdout, :stderr] }
15
+ cmd.unshift('sh', '-c')
16
+
17
+ interrupted = false
18
+ # Lambda to change interrupted to true
19
+ int_callback = ->{ interrupted = true }
20
+ result = ::Vagrant::Util::Busy.busy(int_callback) do
21
+ ::Vagrant::Util::Subprocess.execute(*cmd, &block)
22
+ end
23
+
24
+ return result.exit_code if exit_code
25
+
26
+ result.stderr.gsub!("\r\n", "\n")
27
+ result.stdout.gsub!("\r\n", "\n")
28
+
29
+ if result.exit_code != 0 || interrupted
30
+ raise Errors::ExecuteError
31
+ end
32
+
33
+ result.stdout[0..-2]
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,68 @@
1
+ begin
2
+ require "vagrant"
3
+ rescue LoadError
4
+ raise "The Vagrant Zone plugin must be run within Vagrant."
5
+ end
6
+
7
+ module VagrantPlugins
8
+ module ProviderZone
9
+ class Plugin < Vagrant.plugin('2')
10
+ name "zone"
11
+ description <<-DESC
12
+ This plugin allows vagrant to manage lx-branded zones or native zones on
13
+ OmniOSce or any other illumos based distribution
14
+ DESC
15
+
16
+ config(:zone, :provider) do
17
+ require_relative "config"
18
+ Config
19
+ end
20
+
21
+ provider(:zone) do
22
+ require_relative "provider"
23
+ Provider
24
+ end
25
+
26
+ # This initializes the internationalization strings.
27
+ def self.setup_i18n
28
+ I18n.load_path << File.expand_path('locales/en.yml', ProviderZone.source_root)
29
+ I18n.reload!
30
+ end
31
+
32
+ # This sets up our log level to be whatever VAGRANT_LOG is.
33
+ def self.setup_logging
34
+ require 'log4r'
35
+
36
+ level = nil
37
+ begin
38
+ level = Log4r.const_get(ENV['VAGRANT_LOG'].upcase)
39
+ rescue NameError
40
+ # This means that the logging constant wasn't found,
41
+ # which is fine. We just keep `level` as `nil`. But
42
+ # we tell the user.
43
+ level = nil
44
+ end
45
+
46
+ # Some constants, such as "true" resolve to booleans, so the
47
+ # above error checking doesn't catch it. This will check to make
48
+ # sure that the log level is an integer, as Log4r requires.
49
+ level = nil if !level.is_a?(Integer)
50
+
51
+ # Set the logging level on all "vagrant" namespaced
52
+ # logs as long as we have a valid level.
53
+ if level
54
+ logger = Log4r::Logger.new('vagrant_zone')
55
+ logger.outputters = Log4r::Outputter.stderr
56
+ logger.level = level
57
+ logger = nil
58
+ end
59
+ end
60
+
61
+ # Setup logging and i18n before any autoloading loads other classes
62
+ # with logging configured as this prevents inheritance of the log level
63
+ # from the parent logger.
64
+ setup_logging
65
+ setup_i18n
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,93 @@
1
+ require "vagrant"
2
+ require "log4r"
3
+
4
+ module VagrantPlugins
5
+ module ProviderZone
6
+ autoload :Driver, 'vagrant-zone/driver'
7
+
8
+ class Provider < Vagrant.plugin('2', :provider)
9
+ def initialize(machine)
10
+ @logger = Log4r::Logger.new("vagrant::provider::zone")
11
+ @machine = machine
12
+ end
13
+
14
+ def driver
15
+ return @driver if @driver
16
+ @driver = Driver.new(@machine)
17
+ end
18
+
19
+ # This should return a hash of information that explains how to SSH
20
+ # into the machine. If the machine is not at a point where SSH is
21
+ # even possiable, then 'nil' should be returned
22
+ #
23
+ # The general structure of this returned hash should be the
24
+ # following:
25
+ #
26
+ # {
27
+ # host: "1.2.3.4",
28
+ # port: "22",
29
+ # username: "vagrant",
30
+ # private_key_path: "/path/to/my/key"
31
+ # }
32
+ def ssh_info
33
+ # We just return nil if were not able to identify the VM's IP and
34
+ # let Vagrant core deal with it like docker provider does
35
+ return nil if state.id != :running
36
+ ip = driver.get_ip_address(@machine)
37
+ return nil if !ip
38
+ ssh_info = {
39
+ host: ip,
40
+ port: 22,
41
+ }
42
+ end
43
+
44
+ # This should return an action callable for the given name.
45
+ #
46
+ # @param [Symbol] name Name of the action.
47
+ # @return [Object] A callable action sequence object, whether it
48
+ # is a proc, object, etc.
49
+ def action(name)
50
+ # Attrmpt to get the action method from the Action class if it
51
+ # exists, otherwise return nil to show that we don't support the
52
+ # given action
53
+ action_method = "action_#{name}"
54
+ return Action.send(action_method) if Action.respond_to?(action_method)
55
+ nil
56
+ end
57
+
58
+ # This method is called if the underying machine ID changes. Providers
59
+ # can use this method to load in new data for the actual backing
60
+ # machine or to realize that the machine is now gone (the ID can
61
+ # become `nil`). No parameters are given, since the underlying machine
62
+ # is simply the machine instance given to this object. And no
63
+ # return value is necessary.
64
+ def machine_id_changed
65
+ end
66
+
67
+ def state
68
+ id = @machine.id
69
+ state_id = nil
70
+ state_id = :not_created unless @machine.id
71
+ state_id = driver.state(@machine) if @machine.id && !state_id
72
+
73
+
74
+ # This is a special pseudo-state so that we don't set the
75
+ # NOT_CREATED_ID while we're setting up the machine. This avoids
76
+ # clearing the data dir.
77
+ state_id = :preparing if @machine.id == 'preparing'
78
+
79
+ # Get the short and long description
80
+ short = state_id.to_s.tr('_', ' ')
81
+
82
+ # If we're not created, then specify the special ID flag
83
+ if state_id == :not_created
84
+ state_id = Vagrant::MachineState::NOT_CREATED_ID
85
+ end
86
+
87
+ # Return the MachineState object
88
+ Vagrant::MachineState.new(state_id, short, short)
89
+ end
90
+
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,17 @@
1
+ module VagrantPlugins
2
+ module ProviderZone
3
+ module Util
4
+ class Timer
5
+ # A basic utility method that times the execution of the given
6
+ # block and returns it.
7
+ def self.time
8
+ start_time = Time.now.to_f
9
+ yield
10
+ end_time = Time.now.to_f
11
+
12
+ end_time - start_time
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ module VagrantPlugins
2
+ module ProviderZone
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
data/locales/en.yml ADDED
@@ -0,0 +1,12 @@
1
+ en:
2
+ vagrant_zone:
3
+ states:
4
+ not_created: |-
5
+ Your instance of this box haven't been created.
6
+ is_running: |-
7
+ Your instance has already be booted.
8
+ errors:
9
+ execute_error: |-
10
+ Failed when execute commands.
11
+ timeout_error: |-
12
+ Timeout exceeded.
data/playbook.yml ADDED
@@ -0,0 +1,9 @@
1
+ ---
2
+ - name: First Playbook
3
+ hosts: all
4
+ gather_facts: yes
5
+ tasks:
6
+ - name: Display the config
7
+ debug:
8
+ msg: "The hostname is {{ ansible_hostname }} and the OS is {{ ansible_version }}"
9
+
@@ -0,0 +1,24 @@
1
+ require File.expand_path('../lib/vagrant-zone/version', __FILE__)
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "vagrant-zone"
5
+ spec.version = VagrantPlugins::ProviderZone::VERSION
6
+ spec.authors = ["Thomas Merkel"]
7
+ spec.email = ["thomas.merkel@skylime.net"]
8
+
9
+ spec.summary = %q{Vagrant provider plugin to support zones}
10
+ spec.description = spec.summary
11
+ spec.homepage = "https://github.com/skylime/vagrant-zone"
12
+ spec.license = "MIT"
13
+
14
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
15
+ spec.bindir = "exe"
16
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_development_dependency "bundler", "~> 1.10"
20
+ spec.add_development_dependency "rake", "~> 10.0"
21
+ spec.add_development_dependency "rspec"
22
+ spec.add_runtime_dependency "ruby_expect"
23
+ spec.add_runtime_dependency "netaddr"
24
+ end
metadata ADDED
@@ -0,0 +1,141 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vagrant-zone
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Thomas Merkel
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-04-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: ruby_expect
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: netaddr
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Vagrant provider plugin to support zones
84
+ email:
85
+ - thomas.merkel@skylime.net
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - Gemfile
92
+ - Vagrantfile
93
+ - lib/vagrant-zone.rb
94
+ - lib/vagrant-zone/action.rb
95
+ - lib/vagrant-zone/action/create.rb
96
+ - lib/vagrant-zone/action/destroy.rb
97
+ - lib/vagrant-zone/action/halt.rb
98
+ - lib/vagrant-zone/action/import.rb
99
+ - lib/vagrant-zone/action/is_created.rb
100
+ - lib/vagrant-zone/action/network.rb
101
+ - lib/vagrant-zone/action/not_created.rb
102
+ - lib/vagrant-zone/action/package.rb
103
+ - lib/vagrant-zone/action/prepare_nfs_valid_ids.rb
104
+ - lib/vagrant-zone/action/setup.rb
105
+ - lib/vagrant-zone/action/start.rb
106
+ - lib/vagrant-zone/action/wait_till_up.rb
107
+ - lib/vagrant-zone/config.rb
108
+ - lib/vagrant-zone/driver.rb
109
+ - lib/vagrant-zone/errors.rb
110
+ - lib/vagrant-zone/executor.rb
111
+ - lib/vagrant-zone/plugin.rb
112
+ - lib/vagrant-zone/provider.rb
113
+ - lib/vagrant-zone/util/timer.rb
114
+ - lib/vagrant-zone/version.rb
115
+ - locales/en.yml
116
+ - playbook.yml
117
+ - vagrant-zone.gemspec
118
+ homepage: https://github.com/skylime/vagrant-zone
119
+ licenses:
120
+ - MIT
121
+ metadata: {}
122
+ post_install_message:
123
+ rdoc_options: []
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ required_rubygems_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ requirements: []
137
+ rubygems_version: 3.0.3
138
+ signing_key:
139
+ specification_version: 4
140
+ summary: Vagrant provider plugin to support zones
141
+ test_files: []