vagrant-subutai 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,62 @@
1
+ # Functions dealing with hook scripts
2
+
3
+ # True if script starts with #!/bin/bash
4
+ # --------------------------------------
5
+ def shebang?(bash_hook)
6
+ text = File.open(bash_hook).read
7
+ text.gsub!(/\r\n?/, "\n")
8
+ line = text.next
9
+ return true if line.start_with? '#!/bin/bash'
10
+ true if line.start_with? '#!/usr/bin/env bash'
11
+ end
12
+
13
+ # Handle hook scripts or normal files: returns path to file to provision
14
+ # ----------------------------------------------------------------------
15
+ def hook_handler(hook)
16
+ # hook might be the upload file or an executable to give the path to the
17
+ # file to be provisioned. Builders can use this to hook into the
18
+ # provisioning process for new snaps and management templates.
19
+ unless File.executable?(hook)
20
+ puts '[WARNING] hook script ' + hook + ' not executable. Abandoning launch.'
21
+ return nil
22
+ end
23
+
24
+ fext = File.extname(hook)
25
+ if fext == '.sh' && shebang?(hook)
26
+ `#{hook}`.strip # executes and returns output (should be file)
27
+ # elsif fext == '.bat'
28
+ # return `#{hook}`.strip # executes and returns output (should be file)
29
+ else
30
+ # raise '[WARNING] hook script not valid bash .sh or .bat. Abandoning launch.'
31
+ raise '[WARNING] hook script not valid bash file with .sh extension. Abandoning launch.'
32
+ end
33
+ end
34
+
35
+ # TODO: Match extension to OS and pick appropriately if
36
+ # both a .bat and .sh are present.
37
+
38
+ # If arg is nil check for presence of snap_hook.${ext}
39
+ # ----------------------------------------------------
40
+ def snap_handler(hook)
41
+ if hook.nil?
42
+ %w[.sh .bat].each do |e|
43
+ return hook_handler('./snap_hook' + e) if File.exist?('./snap_hook' + e)
44
+ end
45
+ return nil
46
+ end
47
+ hook_handler(hook)
48
+ end
49
+
50
+ # if arg is nil check for presence of management_hook.${ext}
51
+ # ----------------------------------------------------
52
+ def management_handler(hook)
53
+ if hook.nil?
54
+ %w[.sh .bat].each do |e|
55
+ if File.exist?('./management_hook' + e)
56
+ return hook_handler('management_hook' + e)
57
+ end
58
+ end
59
+ return nil
60
+ end
61
+ hook_handler(hook)
62
+ end
@@ -0,0 +1,125 @@
1
+ require 'socket'
2
+ require 'timeout'
3
+ require 'rbconfig'
4
+ require 'log4r'
5
+
6
+ # methods dealing with port management
7
+
8
+ # Checks if a port is not available
9
+ # ---------------------------------
10
+ def port_bound?(host, port)
11
+ Timeout.timeout(1) do
12
+ s = TCPSocket.new(host, port)
13
+ s.close rescue nil
14
+ return true
15
+ end
16
+ rescue Timeout::Error, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, \
17
+ Errno::ENETUNREACH, Errno::EACCES, Errno::ENOTCONN, \
18
+ Errno::EADDRNOTAVAIL
19
+ return false
20
+ end
21
+
22
+ # Finds free port for console and puts in wormstore
23
+ # -------------------------------------------------
24
+ def find_port(port)
25
+ port += 1 while port_bound?('127.0.0.1', port)
26
+ port
27
+ end
28
+
29
+ # Most hypervisors uses a mac prefix: we cannot just generate a random mac
30
+ PROVIDERS=%i[:virtualbox :libvirt :vmware_fusion :vmware :parallels :hyper_v]
31
+ PROVIDER_MAC_PREFIXES = {
32
+ :virtualbox => '080027',
33
+ :libvirt => '525400',
34
+ :vmware_fusion => '______',
35
+ :vmware => '______',
36
+ :parallels => '______',
37
+ :hyper_v => '______'
38
+ }
39
+
40
+ os = nil
41
+ os = :windows if (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
42
+ os = :mac if (RbConfig::CONFIG['host_os'] =~ /darwin/)
43
+ os = :linux if (RbConfig::CONFIG['host_os'] =~ /linux/)
44
+
45
+ def broadcast_addr
46
+ octets = `route print 0.0.0.0 | findstr 0.0.0.0`.split(' ').map(&:strip)[2].split('.') \
47
+ if (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
48
+ octets = `ip route show | grep default | awk '{print $3}'`.gsub(/\s+/, "").split(".") \
49
+ if (RbConfig::CONFIG['host_os'] =~ /linux/)
50
+ octets = `route -n get default | grep gateway | awk '{print $2}'`.gsub(/\s+/, "").split(".") \
51
+ if (RbConfig::CONFIG['host_os'] =~ /darwin/)
52
+ octets[3] = 255
53
+ octets.join('.')
54
+ end
55
+
56
+ def broadcast_ping(count)
57
+ system("ping -n #{count} #{broadcast_addr} >/dev/null") \
58
+ if (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
59
+ system("ping -c #{count} #{broadcast_addr} >/dev/null") \
60
+ if (RbConfig::CONFIG['host_os'] =~ /darwin|linux/)
61
+ end
62
+
63
+ def zero_pad_mac(mac)
64
+ reassembled = ''
65
+ mac.split(':').each do |octet|
66
+ octet = '0' + octet if octet.length == 1
67
+ reassembled += octet
68
+ end
69
+ reassembled
70
+ end
71
+
72
+ def arp_table
73
+ broadcast_ping(2)
74
+ arp_table = {}
75
+ `arp -a`.split("\n").each do |line|
76
+ matches = /.*(\d+\.\d+\.\d+.\d+)[[:space:]]((([a-f]|[0-9]){1,2}:){5}([a-f]|[0-9]){1,2})[[:space:]].*/.match(line) \
77
+ if (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
78
+ matches = /.*\((\d+\.\d+\.\d+.\d+)\) at ((([a-f]|[0-9]){1,2}:){5}([a-f]|[0-9]){1,2}) .*/.match(line) \
79
+ if (RbConfig::CONFIG['host_os'] =~ /darwin|linux/)
80
+
81
+ if ! matches.nil? && ! matches[2].nil?
82
+ key_mac = zero_pad_mac(matches[2])
83
+ value_ip = matches[1]
84
+ arp_table.store(key_mac, value_ip)
85
+ end
86
+ end
87
+ arp_table
88
+ end
89
+
90
+ def mac_uniq?(mac)
91
+ arptab = arp_table
92
+ arptab[mac].nil?
93
+ end
94
+
95
+ def find_mac(provider)
96
+ mac = random_mac_addr(provider)
97
+ until mac_uniq?(mac) do
98
+ mac = random_mac_addr(provider)
99
+ end
100
+ mac
101
+ end
102
+
103
+ # Generate a random mac address that works with the hypervisor of a provider
104
+ def random_mac_addr(provider)
105
+ symbol = provider.to_sym
106
+ case symbol
107
+ when :virtualbox
108
+ PROVIDER_MAC_PREFIXES[:virtualbox] + 3.times.map { '%02x' % rand(0..255) }.join
109
+ when :libvirt
110
+ PROVIDER_MAC_PREFIXES[:libvirt] + 3.times.map { '%02x' % rand(0..255) }.join
111
+ when :vmware_fusion
112
+ # PROVIDER_MAC_PREFIXES[:vmware_fusion] + 3.times.map { '%02x' % rand(0..255) }.join
113
+ raise "Unsupported provider #{provider}"
114
+ when :vmware
115
+ # PROVIDER_MAC_PREFIXES[:vmware] + 3.times.map { '%02x' % rand(0..255) }.join
116
+ raise "Unsupported provider #{provider}"
117
+ when :parallels
118
+ # PROVIDER_MAC_PREFIXES[:parallels] + 3.times.map { '%02x' % rand(0..255) }.join
119
+ raise "Unsupported provider #{provider}"
120
+ when :hyper_v
121
+ # PROVIDER_MAC_PREFIXES[:hyper_v] + 3.times.map { '%02x' % rand(0..255) }.join
122
+ else
123
+ raise "Unsupported provider #{provider}"
124
+ end
125
+ end
@@ -0,0 +1,20 @@
1
+ module VagrantSubutai
2
+ module Subutai
3
+ class Plugin < Vagrant.plugin(2)
4
+ name 'Subutai'
5
+ description <<-DESC
6
+ Vagrant Subutai CLI - executes Subutai scripts in target hosts
7
+ DESC
8
+
9
+ command(:subutai) do
10
+ require_relative 'command'
11
+ Command
12
+ end
13
+
14
+ config 'subutai_console' do
15
+ require_relative 'config'
16
+ Config
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,77 @@
1
+ require 'net/https'
2
+ require 'uri'
3
+ require_relative '../vagrant-subutai'
4
+
5
+ module VagrantSubutai
6
+ module Rest
7
+ class SubutaiConsole
8
+ # Subutai Console credentials username, password
9
+ # Subutai Console url
10
+ # login methods gets token
11
+ def self.token(url, username, password)
12
+ uri = URI.parse(url + SubutaiConsoleAPI::V1::TOKEN)
13
+ http = Net::HTTP.new(uri.host, uri.port)
14
+ http.use_ssl = true
15
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
16
+
17
+ request = Net::HTTP::Post.new(uri.request_uri)
18
+ request.set_form_data('username' => username, 'password' => password)
19
+
20
+ # returns response
21
+ return http.request(request)
22
+ end
23
+
24
+ # Subutai Hub credentials email, password
25
+ # specify your peer_name
26
+ # peer_scope acceptable only like this "Public" : "Private"
27
+ def self.register(token, url, email, password, peer_name, peer_scope)
28
+ uri = URI.parse(url + SubutaiConsoleAPI::V1::REGISTER_HUB + token)
29
+ https = Net::HTTP.new(uri.host, uri.port)
30
+ https.use_ssl = true
31
+ https.verify_mode = OpenSSL::SSL::VERIFY_NONE
32
+
33
+ request = Net::HTTP::Post.new(uri.request_uri)
34
+ request.set_form_data({'email' => email, 'password' => password, 'peerName' => peer_name, 'peerScope' => peer_scope})
35
+
36
+ # returns response
37
+ return https.request(request)
38
+ end
39
+
40
+ # Approves Resource Host
41
+ def self.approve(token, url, id)
42
+ uri = URI.parse(url + SubutaiConsoleAPI::V1::APPROVE + "/#{id}/approve?sptoken?=" + token)
43
+ https = Net::HTTP.new(uri.host, uri.port)
44
+ https.use_ssl = true
45
+ https.verify_mode = OpenSSL::SSL::VERIFY_NONE
46
+
47
+ request = Net::HTTP::Post.new(uri.request_uri)
48
+
49
+ return https.request(request)
50
+ end
51
+
52
+ # Gets Finger print Subutai Console
53
+ def self.fingerprint(url)
54
+ uri = URI.parse(url + SubutaiConsoleAPI::V1::FINGERPRINT)
55
+ https = Net::HTTP.new(uri.host, uri.port)
56
+ https.use_ssl = true
57
+ https.verify_mode = OpenSSL::SSL::VERIFY_NONE
58
+
59
+ request = Net::HTTP::Get.new(uri.request_uri)
60
+
61
+ return https.request(request)
62
+ end
63
+
64
+ # Get Subutai Console RH requests
65
+ def self.requests(url, token)
66
+ uri = URI.parse(url + SubutaiConsoleAPI::V1::REQUESTS + token)
67
+ https = Net::HTTP.new(uri.host, uri.port)
68
+ https.use_ssl = true
69
+ https.verify_mode = OpenSSL::SSL::VERIFY_NONE
70
+
71
+ request = Net::HTTP::Get.new(uri.request_uri)
72
+
73
+ return https.request(request)
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,32 @@
1
+ require_relative '../vagrant-subutai'
2
+ require 'json'
3
+
4
+ module VagrantSubutai
5
+ class RhController
6
+
7
+ def all(token)
8
+ response = VagrantSubutai::Rest::SubutaiConsole.requests($SUBUTAI_CONSOLE_URL, token)
9
+ rhs = []
10
+
11
+ case response
12
+ when Net::HTTPOK
13
+ json = JSON.parse(response.body)
14
+
15
+ json.each do |data|
16
+ rh = VagrantSubutai::Models::Rh.new
17
+ rh.id = data['id']
18
+ rh.hostname = data['hostname']
19
+ rh.status = data['status']
20
+ rh.isConnected = data['isConnected']
21
+ rh.isManagement = data['isManagement']
22
+ rhs << rh
23
+ end
24
+ else
25
+ STDERR.puts "#{response.body}"
26
+ raise 'Can\'t get requests info from Subutai Console'
27
+ end
28
+
29
+ rhs
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,215 @@
1
+ require_relative '../vagrant-subutai'
2
+ require_relative 'command'
3
+ require 'net/https'
4
+ require 'io/console'
5
+ require 'fileutils'
6
+ require_relative 'rh_controller'
7
+
8
+ module VagrantSubutai
9
+ class Commands < Vagrant.plugin('2', :command)
10
+
11
+ def initialize(arg, env)
12
+ super(arg, env)
13
+ end
14
+
15
+ # show snap logs
16
+ def log
17
+ ssh(base + SubutaiAgentCommand::LOG)
18
+ end
19
+
20
+ def base
21
+ env = SubutaiConfig.get(:SUBUTAI_ENV)
22
+
23
+ if env.nil?
24
+ SubutaiAgentCommand::BASE
25
+ else
26
+ if env.to_s == "prod"
27
+ SubutaiAgentCommand::BASE
28
+ else
29
+ "sudo /snap/bin/subutai-#{env.to_s}"
30
+ end
31
+ end
32
+ end
33
+
34
+ # info id
35
+ def info(arg)
36
+ with_target_vms(nil, single_target: true) do |vm|
37
+ vm.communicate.sudo("#{base} #{SubutaiAgentCommand::INFO} #{arg}") do |type, data|
38
+ if type == :stdout
39
+ result = data.split(/[\r\n]+/)
40
+ STDOUT.puts result.first
41
+ return result.first
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ # update Subutai rh or management
48
+ def update(name)
49
+ ssh(base + SubutaiAgentCommand::UPDATE + " #{name}")
50
+ end
51
+
52
+ # register Subutai Peer to Hub
53
+ def register(username, password)
54
+ username, password = get_input_token if username.nil? && password.nil?
55
+ response = VagrantSubutai::Rest::SubutaiConsole.token($SUBUTAI_CONSOLE_URL, username, password)
56
+
57
+ case response
58
+ when Net::HTTPOK
59
+ STDOUT.puts "Successfully you signed Subutai Console"
60
+ hub_email, hub_password, peer_name, peer_scope = get_input_register
61
+ response = VagrantSubutai::Rest::SubutaiConsole.register(response.body, $SUBUTAI_CONSOLE_URL, hub_email, hub_password, peer_name, peer_scope)
62
+
63
+ case response
64
+ when Net::HTTPOK
65
+ STDOUT.puts "You peer: \"#{peer_name}\" successfully registered to hub."
66
+ else
67
+ STDOUT.puts "Try again! #{response.body}\n"
68
+ register(username, password)
69
+ end
70
+ else
71
+ STDERR.puts "Try again! #{response.body}\n"
72
+ register(nil, nil)
73
+ end
74
+ end
75
+
76
+ # Add new RH to Peer
77
+ def add(peer_path, rh_name)
78
+ # TODO peer_path also be fixed(this path must work on all platforms)
79
+ peer_path = peer_path + "/#{VagrantSubutai::Subutai::RH_FOLDER_NAME}/#{rh_name}"
80
+
81
+ # create RH folder your_peer_path/RH/rh_name
82
+ unless File.exists?(peer_path)
83
+ FileUtils.mkdir_p(peer_path)
84
+
85
+ # 1. create RH
86
+ Dir.chdir(peer_path){
87
+ unless system(VagrantCommand::INIT + " " + $SUBUTAI_BOX_NAME)
88
+ raise "#{VagrantCommand::INIT} command failed."
89
+ end
90
+ }
91
+
92
+ # 2. vagrant up
93
+ Dir.chdir(peer_path){
94
+ unless system(VagrantCommand::RH_UP)
95
+ raise "#{VagrantCommand::RH_UP} command failed."
96
+ end
97
+ }
98
+
99
+ # 3. vagrant provision
100
+ Dir.chdir(peer_path){
101
+ unless system(VagrantCommand::PROVISION)
102
+ raise "#{VagrantCommand::PROVISION} command failed."
103
+ end
104
+ }
105
+
106
+ # 4. TODO set Subutai Console host and fingerprint in RH agent config
107
+ fingerprint = VagrantSubutai::Rest::SubutaiConsole.fingerprint($SUBUTAI_CONSOLE_URL).body
108
+ ip = info(VagrantCommand::ARG_IP_ADDR)
109
+
110
+ STDOUT.puts "Subutai Console(Peer)"
111
+ STDOUT.puts "ip: #{ip}"
112
+ STDOUT.puts "fingerprint: #{fingerprint}"
113
+
114
+ # 5. Check is RH request exist in Subutai Console
115
+ # then approve
116
+ rhs = []
117
+ # Get RH requests from Subutai Console
118
+ rhs = VagrantSubutai::RhController.new.all(get_token)
119
+
120
+ # Get RH id
121
+ id = nil
122
+ Dir.chdir(peer_path){
123
+ r, w = IO.pipe
124
+
125
+ pid = spawn(VagrantCommand::SUBUTAI_ID, :out => w)
126
+
127
+ w.close
128
+ id = r.read
129
+ }
130
+
131
+ # Check is this RH request exist in Subutai Console
132
+ found = rhs.detect {|rh| rh.id == id}
133
+
134
+ if found.nil?
135
+ raise 'RH not send request to Subutai Console for approve'
136
+ else
137
+ # TODO send REST call for approve RH to Subutai Console
138
+ end
139
+
140
+ STDOUT.puts "Your RH path: #{peer_path}"
141
+ end
142
+ end
143
+
144
+ # Show Subutai Console finger print
145
+ def fingerprint(url)
146
+ response = VagrantSubutai::Rest::SubutaiConsole.fingerprint(url)
147
+
148
+ case response
149
+ when Net::HTTPOK
150
+ STDOUT.puts response.body
151
+ else
152
+ STDOUT.puts "Try again! #{response.body}"
153
+ end
154
+ end
155
+
156
+ # Get Subutai console credentials from input
157
+ def get_input_token
158
+ STDOUT.puts "\nPlease enter credentials Subutai Console:\n"
159
+ STDOUT.puts "username: "
160
+ username = STDIN.gets.chomp
161
+ puts "password: "
162
+ password = STDIN.noecho(&:gets).chomp
163
+
164
+ [username, password]
165
+ end
166
+
167
+ # gets token
168
+ def get_token
169
+ username, password = get_input_token
170
+ response = VagrantSubutai::Rest::SubutaiConsole.token($SUBUTAI_CONSOLE_URL, username, password)
171
+
172
+ case response
173
+ when Net::HTTPOK
174
+ return response.body
175
+ else
176
+ get_token
177
+ end
178
+ end
179
+
180
+ # Get Hub credentials and peer info
181
+ def get_input_register
182
+ STDOUT.puts "\nRegister your peer to HUB:\n"
183
+
184
+ # Hub email
185
+ STDOUT.puts "Enter Hub email: "
186
+ hub_email = STDIN.gets.chomp
187
+
188
+ # Hub password
189
+ STDOUT.puts "Enter Hub password: "
190
+ hub_password = STDIN.noecho(&:gets).chomp
191
+
192
+ # Peer name
193
+ STDOUT.puts "Enter peer name: "
194
+ peer_name = STDIN.gets.chomp
195
+
196
+ # Peer scope
197
+ STDOUT.puts "1. Public"
198
+ STDOUT.puts "2. Private"
199
+ STDOUT.puts "Choose your peer scope (1 or 2): "
200
+ peer_scope = STDIN.gets.chomp.to_i
201
+
202
+ [hub_email, hub_password, peer_name, peer_scope]
203
+ end
204
+
205
+ def list(arg)
206
+ ssh(base + "#{SubutaiAgentCommand::LIST} #{arg}")
207
+ end
208
+
209
+ def ssh(command)
210
+ with_target_vms(nil, single_target: true) do |vm|
211
+ vm.action(:ssh_run, ssh_run_command: command, ssh_opts: {extra_args: ['-q']})
212
+ end
213
+ end
214
+ end
215
+ end