vagrant-hivemind 0.1.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,77 @@
1
+ require "optparse"
2
+
3
+ require "vagrant/hivemind/constants"
4
+ require "vagrant/hivemind/util"
5
+ require "vagrant/hivemind/host"
6
+
7
+ module Vagrant
8
+ module Hivemind
9
+ module Command
10
+ class Kill < Vagrant.plugin("2", :command)
11
+ include Vagrant::Hivemind::Constants
12
+ include Vagrant::Hivemind::Util
13
+
14
+ def self.synopsis
15
+ "Removes a Drone in the Hive"
16
+ end
17
+
18
+ def execute
19
+ options = {}
20
+
21
+ opts = OptionParser.new do |o|
22
+ o.banner = "Usage: vagrant hivemind kill [options]"
23
+ o.separator ""
24
+ o.separator "Options:"
25
+ o.separator ""
26
+
27
+ o.on("-n", "--hostname HOSTNAME", "The hostname of the Drone (REQUIRED)") do |n|
28
+ options[:hostname] = n
29
+ end
30
+
31
+ o.on("-d", "--directory DIRECTORY", "Specify the directory where '#{HIVE_FILE}' is located (default: current directory)") do |d|
32
+ options[:directory] = []
33
+ options[:directory] << d
34
+ end
35
+ end
36
+
37
+ argv = parse_options(opts)
38
+ return if !argv
39
+
40
+ unless options[:hostname]
41
+ @env.ui.info opts.help
42
+ return 0
43
+ end
44
+
45
+ root_path = Path.get_root_path_from_options options
46
+
47
+ unless HiveFile.exist? root_path
48
+ @env.ui.error "There is no Hive file in the working directory."
49
+ return 1
50
+ end
51
+
52
+ hosts = HiveFile.read_from root_path
53
+
54
+ unless hosts.values.map(&:hostname).include? options[:hostname]
55
+ @env.ui.error "The specified hostname does not exist!"
56
+ return 1
57
+ end
58
+
59
+ host = hosts[options[:hostname]]
60
+
61
+ Vagrant::Hivemind::Util::Vagrantfile.generate_hivemind_vagrantfile @env, host, root_path
62
+
63
+ with_target_vms(options[:hostname]) do |vm|
64
+ action_env = vm.action(:destroy, force_confirm_destroy: true)
65
+ end
66
+
67
+ hosts.delete options[:hostname]
68
+ HiveFile.write_to hosts, root_path
69
+ @env.ui.info "Killed the Drone with hostname '#{options[:hostname]}'"
70
+
71
+ 0
72
+ end
73
+
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,112 @@
1
+ require "optparse"
2
+
3
+ require "vagrant/hivemind/constants"
4
+ require "vagrant/hivemind/util"
5
+ require "vagrant/hivemind/host"
6
+
7
+ module Vagrant
8
+ module Hivemind
9
+ module Command
10
+ class List < Vagrant.plugin("2", :command)
11
+ include Vagrant::Hivemind::Constants
12
+ include Vagrant::Hivemind::Util
13
+
14
+ def self.synopsis
15
+ "Lists all the Drones in the Hive"
16
+ end
17
+
18
+ def execute
19
+ options = {}
20
+
21
+ opts = OptionParser.new do |o|
22
+ o.banner = "Usage: vagrant hivemind list [options]"
23
+ o.separator ""
24
+ o.separator "Options:"
25
+ o.separator ""
26
+
27
+ o.on("-n", "--hostname", "List the Drones ordered by the hostname") do |n|
28
+ options[:hostname] = n
29
+ end
30
+
31
+ o.on("-a", "--ip-address", "List the Drones ordered by the IP address") do |a|
32
+ options[:ip_address] = a
33
+ end
34
+
35
+ o.on("-c", "--control", "List the Drones, Control Machines first") do |c|
36
+ options[:control] = c
37
+ end
38
+
39
+ o.on("-s", "--size", "List the Drones ordered by the Box Size") do |s|
40
+ options[:size] = s
41
+ end
42
+
43
+ o.on("-d", "--directory DIRECTORY", "Specify the directory where '#{HIVE_FILE}' is located (default: current directory)") do |d|
44
+ options[:directory] = []
45
+ options[:directory] << d
46
+ end
47
+ end
48
+
49
+ argv = parse_options(opts)
50
+ return if !argv
51
+
52
+ root_path = Path.get_root_path_from_options options
53
+
54
+ unless HiveFile.exist? root_path
55
+ @env.ui.error "There is no Hive file in the working directory."
56
+ return 1
57
+ end
58
+
59
+ hosts = HiveFile.read_from root_path
60
+
61
+ sorted_hosts = sort_hosts hosts, options
62
+
63
+ @env.ui.info "+----------------------+----------------+---+--------------+------------+---+"
64
+ @env.ui.info "| Hostname | IP Address | C | Size | Box Type | G |"
65
+ @env.ui.info "+----------------------+----------------+---+--------------+------------+---+"
66
+ sorted_hosts.values.each do |host|
67
+ hostname = host.hostname
68
+ ip_address = host.ip_address
69
+ is_control_y_n = host.is_control ? 'Y' : 'N'
70
+ box_size = BOX_SIZES[host.box_size.to_sym][:name]
71
+ box_type = BOX_TYPES[host.box_type.to_sym][:name]
72
+ is_gui_y_n = BOX_TYPES[host.box_type.to_sym][:is_gui] ? 'Y' : 'N'
73
+ @env.ui.info "| #{'%-20.20s' % hostname} | #{'%-14.14s' % ip_address} | #{is_control_y_n} | #{'%-12.12s' % box_size} | #{'%-10.10s' % box_type} | #{is_gui_y_n} |"
74
+ end
75
+ @env.ui.info "+----------------------+----------------+---+--------------+------------+---+"
76
+ @env.ui.info ""
77
+
78
+ 0
79
+ end
80
+
81
+ private
82
+ def sort_hosts(hosts, options = {})
83
+ sorted_hosts = hosts
84
+ options.keys.each do |key|
85
+ sorted_hosts = sort_hosts_by_hostname(hosts) if key == :hostname
86
+ sorted_hosts = sort_hosts_by_ip_address(hosts) if key == :ip_address
87
+ sorted_hosts = sort_hosts_by_control(hosts) if key == :control
88
+ sorted_hosts = sort_hosts_by_box_size(hosts) if key == :size
89
+ end
90
+ sorted_hosts
91
+ end
92
+
93
+ def sort_hosts_by_hostname(hosts)
94
+ (hosts.sort_by { |k,v| v.hostname }).to_h
95
+ end
96
+
97
+ def sort_hosts_by_ip_address(hosts)
98
+ (hosts.sort_by { |k,v| v.ip_address }).to_h
99
+ end
100
+
101
+ def sort_hosts_by_control(hosts)
102
+ (hosts.sort_by { |k,v| v.is_control.to_s }.reverse).to_h
103
+ end
104
+
105
+ def sort_hosts_by_box_size(hosts)
106
+ (hosts.sort_by { |k,v| BOX_SIZES[v.box_size.to_sym][:memory_in_mb] }).to_h
107
+ end
108
+
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,166 @@
1
+ require "optparse"
2
+
3
+ require "vagrant/hivemind/constants"
4
+ require "vagrant/hivemind/util"
5
+ require "vagrant/hivemind/host"
6
+
7
+ module Vagrant
8
+ module Hivemind
9
+ module Command
10
+ class Morph < Vagrant.plugin("2", :command)
11
+ include Vagrant::Hivemind::Constants
12
+ include Vagrant::Hivemind::Util
13
+
14
+ def self.synopsis
15
+ "Changes the settings of a Drone in the Hive"
16
+ end
17
+
18
+ def execute
19
+ options = {}
20
+
21
+ opts = OptionParser.new do |o|
22
+ o.banner = "Usage: vagrant hivemind morph [options]"
23
+ o.separator ""
24
+ o.separator "Options:"
25
+ o.separator ""
26
+
27
+ o.on("-n", "--hostname HOSTNAME", "The hostname of the Drone (REQUIRED)") do |n|
28
+ options[:hostname] = n
29
+ end
30
+
31
+ o.on("-a", "--ip-address IPADDRESS", "The new IP address of the Drone") do |a|
32
+ options[:ip_address] = a
33
+ end
34
+
35
+ o.on("-c", "--control", "Promote the Drone to be a Control Machine") do |c|
36
+ options[:control] = c
37
+ end
38
+
39
+ o.on("-s", "--size SIZE", BOX_SIZES.keys.map(&:to_s), "The new Box Size of the Drone [:extra_small, :small, :medium, :large, :extra_large] (default: :small)") do |s|
40
+ options[:size] = s
41
+ end
42
+
43
+ o.on("-p", "--forwarded-port PORTPAIR", "Forward GUESTPORT to HOSTPORT (the format is GUESTPORT:HOSTPORT)") do |p|
44
+ options[:forwarded_port] = p
45
+ end
46
+
47
+ o.on("-d", "--directory DIRECTORY", "Specify the directory where '#{HIVE_FILE}' is located (default: current directory)") do |d|
48
+ options[:directory] = []
49
+ options[:directory] << d
50
+ end
51
+ end
52
+
53
+ argv = parse_options(opts)
54
+ return if !argv
55
+
56
+ root_path = Path.get_root_path_from_options options
57
+
58
+ unless options[:hostname]
59
+ @env.ui.info opts.help
60
+ return 0
61
+ end
62
+
63
+ unless HiveFile.exist? root_path
64
+ @env.ui.error "There is no Hive file in the working directory."
65
+ return 1
66
+ end
67
+
68
+ hosts = HiveFile.read_from root_path
69
+
70
+ unless hosts.values.map(&:hostname).include? options[:hostname]
71
+ @env.ui.error "The specified hostname does not exist!"
72
+ return 1
73
+ end
74
+
75
+ if options[:ip_address]
76
+ validation_error = is_valid_ip_address?(options[:ip_address], hosts)
77
+ if validation_error
78
+ @env.ui.error validation_error
79
+ return 1
80
+ end
81
+ end
82
+
83
+ if options[:forwarded_port]
84
+ validation_error = is_valid_forwarded_port?(options[:forwarded_port], hosts)
85
+ if validation_error
86
+ @env.ui.error validation_error
87
+ return 1
88
+ end
89
+ end
90
+
91
+ host = hosts[options[:hostname]]
92
+
93
+ if options[:ip_address]
94
+ host.ip_address = options[:ip_address]
95
+ end
96
+
97
+ if options[:control]
98
+ host.is_control = true
99
+ end
100
+
101
+ if options[:size]
102
+ host.box_size = options[:size]
103
+ end
104
+
105
+ if options[:forwarded_port]
106
+ guest_port, host_port = Network.port_pair_to_i(options[:forwarded_port])
107
+ host.forwarded_ports ||= []
108
+
109
+ port_pair = Network.get_host_port_pair_with_guest_port(guest_port, host)
110
+ if port_pair
111
+ port_pair["host_port"] = host_port
112
+ else
113
+ port_pair = {
114
+ "guest_port" => guest_port,
115
+ "host_port" => host_port
116
+ }
117
+ host.forwarded_ports << port_pair
118
+ end
119
+ end
120
+
121
+ hosts.delete options[:hostname]
122
+ drone = {
123
+ options[:hostname] => host
124
+ }
125
+ HiveFile.write_to hosts.merge(drone), root_path
126
+ @env.ui.info "Morphed the Drone with hostname '#{options[:hostname]}'"
127
+
128
+ 0
129
+ end
130
+
131
+ private
132
+ def is_valid_ip_address?(ip_address, hosts)
133
+ if !Network.is_valid_ip_address? ip_address
134
+ return "Invalid IP address format!"
135
+ end
136
+ if Network.get_network(ip_address) != Network.get_network(PRIVATE_NETWORK)
137
+ return "The specified IP address does not belong to the private network of the Hive!"
138
+ end
139
+ if hosts.values.map(&:ip_address).include? ip_address
140
+ return "The specified IP address is already used!"
141
+ end
142
+ return nil
143
+ end
144
+
145
+ def is_valid_forwarded_port?(port_pair, hosts)
146
+ if !Network.is_valid_port_pair? port_pair
147
+ return "Invalid port pair format!"
148
+ end
149
+
150
+ guest_port, host_port = Network.port_pair_to_i(port_pair)
151
+ if !Network.is_valid_port_value? guest_port
152
+ return "Guest port is out of range!"
153
+ end
154
+ if !Network.is_valid_port_value? host_port
155
+ return "Host port is out of range!"
156
+ end
157
+
158
+ if Network.get_host_keys_using_host_port(host_port, hosts).size > 0
159
+ return "Host port is already used!"
160
+ end
161
+ end
162
+
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,90 @@
1
+ require "optparse"
2
+
3
+ module Vagrant
4
+ module Hivemind
5
+ module Command
6
+ class Root < Vagrant.plugin("2", :command)
7
+ def self.synopsis
8
+ "Hivemind operations: init list desc spawn kill morph up halt"
9
+ end
10
+
11
+ def initialize(argv, env)
12
+ super
13
+
14
+ @main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
15
+
16
+ @subcommands = Vagrant::Registry.new
17
+
18
+ @subcommands.register(:init) do
19
+ require_relative "init"
20
+ Init
21
+ end
22
+
23
+ @subcommands.register(:list) do
24
+ require_relative "list"
25
+ List
26
+ end
27
+
28
+ @subcommands.register(:desc) do
29
+ require_relative "desc"
30
+ Desc
31
+ end
32
+
33
+ @subcommands.register(:spawn) do
34
+ require_relative "spawn"
35
+ Spawn
36
+ end
37
+
38
+ @subcommands.register(:kill) do
39
+ require_relative "kill"
40
+ Kill
41
+ end
42
+
43
+ @subcommands.register(:morph) do
44
+ require_relative "morph"
45
+ Morph
46
+ end
47
+
48
+ @subcommands.register(:up) do
49
+ require_relative "up"
50
+ Up
51
+ end
52
+
53
+ @subcommands.register(:halt) do
54
+ require_relative "halt"
55
+ Halt
56
+ end
57
+
58
+ end
59
+
60
+ def execute
61
+ if @main_args.include?("-h") || @main_args.include?("--help")
62
+ return help
63
+ end
64
+
65
+ command_class = @subcommands.get(@sub_command.to_sym) if @sub_command
66
+ return help if !command_class || !@sub_command
67
+
68
+ command_class.new(@sub_args, @env).execute
69
+ end
70
+
71
+ def help
72
+ opts = OptionParser.new do |o|
73
+ o.banner = "Usage: vagrant hivemind <command> [<args>]"
74
+ o.separator ""
75
+ o.separator "Available commands:"
76
+
77
+ @subcommands.each do |key, data|
78
+ o.separator "#{'%8.6s' % key.to_s} #{'%.60s' % data.synopsis}"
79
+ end
80
+
81
+ o.separator ""
82
+ o.separator "For help on any individual command run `vagrant hivemind <command> -h`"
83
+ end
84
+
85
+ @env.ui.info(opts.help, prefix: false)
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end