vagrant-zone 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: []