danarchy_sys 0.2.10

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.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +2 -0
  6. data/LICENSE +21 -0
  7. data/README.txt +86 -0
  8. data/Rakefile +6 -0
  9. data/bin/console +6 -0
  10. data/bin/danarchy_sys +4 -0
  11. data/bin/setup +18 -0
  12. data/bin/setup.rb +86 -0
  13. data/danarchy_sys.gemspec +38 -0
  14. data/lib/danarchy_sys.rb +16 -0
  15. data/lib/danarchy_sys/aws.rb +9 -0
  16. data/lib/danarchy_sys/aws/compute.rb +13 -0
  17. data/lib/danarchy_sys/cli.rb +63 -0
  18. data/lib/danarchy_sys/cli/instance_manager.rb +130 -0
  19. data/lib/danarchy_sys/cli/instance_manager/instance_status.rb +50 -0
  20. data/lib/danarchy_sys/cli/instance_manager/prompts_create_instance.rb +182 -0
  21. data/lib/danarchy_sys/cli/menus.rb +60 -0
  22. data/lib/danarchy_sys/cli/providers.rb +33 -0
  23. data/lib/danarchy_sys/config.rb +66 -0
  24. data/lib/danarchy_sys/helpers.rb +61 -0
  25. data/lib/danarchy_sys/openstack.rb +9 -0
  26. data/lib/danarchy_sys/openstack/compute.rb +59 -0
  27. data/lib/danarchy_sys/openstack/compute/flavors.rb +47 -0
  28. data/lib/danarchy_sys/openstack/compute/images.rb +52 -0
  29. data/lib/danarchy_sys/openstack/compute/instances.rb +120 -0
  30. data/lib/danarchy_sys/openstack/compute/keypairs.rb +84 -0
  31. data/lib/danarchy_sys/openstack/compute/tests/answer_yes.rb +7 -0
  32. data/lib/danarchy_sys/openstack/compute/tests/flavors_test.rb +10 -0
  33. data/lib/danarchy_sys/openstack/compute/tests/images_test.rb +14 -0
  34. data/lib/danarchy_sys/openstack/compute/tests/instance_create_test.rb +14 -0
  35. data/lib/danarchy_sys/openstack/compute/tests/instance_manage_test.rb +24 -0
  36. data/lib/danarchy_sys/openstack/compute/tests/keypairs_prompt_test.rb +12 -0
  37. data/lib/danarchy_sys/openstack/compute/tests/keypairs_test.rb +38 -0
  38. data/lib/danarchy_sys/openstack/compute/tests/manage_test.rb +16 -0
  39. data/lib/danarchy_sys/printformats.rb +49 -0
  40. data/lib/danarchy_sys/version.rb +3 -0
  41. metadata +151 -0
@@ -0,0 +1,50 @@
1
+
2
+ class InstanceStatus
3
+ def self.all_instances(os_compute, instances)
4
+ istats = {}
5
+
6
+ id = 1
7
+ instances.each do |instance|
8
+ istats[id] = single_instance(os_compute, instance)
9
+ id += 1
10
+ end
11
+
12
+ fields = %w[name state image vcpus ram disk keypair]
13
+ format = PrintFormats.printf_numhash_values(istats, fields)
14
+ _header(format)
15
+
16
+ istats.each do |id, i|
17
+ printf("#{format}\n", "#{id}.",
18
+ i['name'],
19
+ i['state'],
20
+ i['image'],
21
+ i['vcpus'],
22
+ i['ram'],
23
+ i['disk'],
24
+ i['keypair'],
25
+ )
26
+ end
27
+ end
28
+
29
+ def self.single_instance(os_compute, instance)
30
+ comp_inst = os_compute.compute_instances
31
+ comp_imgs = os_compute.compute_images
32
+ comp_flvs = os_compute.compute_flavors
33
+
34
+ image = comp_imgs.get_image_by_id(instance.image['id'])
35
+ flavor = comp_flvs.get_flavor_by_id(instance.flavor['id'])
36
+
37
+ istats = { 'name' => instance.name,
38
+ 'state' => instance.state,
39
+ 'image' => image.name,
40
+ 'vcpus' => flavor.vcpus,
41
+ 'ram' => flavor.ram,
42
+ 'disk' => flavor.disk,
43
+ 'keypair' => instance.key_name,
44
+ }
45
+ end
46
+
47
+ def self._header(format)
48
+ printf("#{format}\n", 'Id', 'Name', 'State', 'Image', 'VCPUS', 'RAM', 'Disk', 'KeyPair')
49
+ end
50
+ end
@@ -0,0 +1,182 @@
1
+
2
+ # CLI Prompt to create a new instance
3
+ class PromptsCreateInstance
4
+ def self.create_instance(os_compute, instance_name)
5
+ comp_inst = os_compute.compute_instances
6
+ comp_imgs = os_compute.compute_images
7
+ comp_flvs = os_compute.compute_flavors
8
+ comp_keys = os_compute.compute_keypairs
9
+
10
+ # Prompt for and check that instance_name is unused
11
+ if instance_name == 'nil'
12
+ print "\nWhat should we name the instance?: "
13
+ instance_name = gets.chomp
14
+ end
15
+
16
+ # Make sure instance_name isn't already in use
17
+ until comp_inst.check_instance(instance_name) == false
18
+ print "\n#{instance_name} already exists! Try another name: "
19
+ instance_name = gets.chomp
20
+ end
21
+
22
+ puts "Creating instance: #{instance_name}"
23
+
24
+ # Prompt for image
25
+ puts "\nSelect an image (operating system) for #{instance_name}"
26
+ image = PromptsCreateInstance.image(comp_imgs)
27
+
28
+ # Prompt for flavor
29
+ puts "\nSelect a flavor (instance size) for #{instance_name}"
30
+ flavor = PromptsCreateInstance.flavor(comp_flvs)
31
+
32
+ # Prompt for keypair
33
+ puts "\nSelect a keypair (SSH key) for #{instance_name}"
34
+ keypair = PromptsCreateInstance.keypair(comp_keys)
35
+
36
+ # Print summary and prompt to continue
37
+ puts "\nInstance Name: #{instance_name}"
38
+ puts " Linux: #{image.name}"
39
+ puts "Instance Size: #{flavor.name}"
40
+ puts " Keypair: #{keypair.name}"
41
+
42
+ print 'Should we continue with creating the instance? (Y/N): '
43
+ instance = 'nil'
44
+ continue = gets.chomp
45
+
46
+ if continue =~ /^y(es)?$/i
47
+ puts "Creating instance: #{instance_name}"
48
+ instance = comp_inst.create_instance(instance_name, image.id, flavor.id, keypair.name)
49
+ else
50
+ puts "Abandoning creation of #{instance_name}"
51
+ return false
52
+ end
53
+
54
+ instance_check = comp_inst.check_instance(instance_name)
55
+
56
+ if instance_check == true
57
+ puts "Instance #{instance.name} is ready!"
58
+ return instance
59
+ else
60
+ raise "Error: Could not create instance: #{instance_name}" if instance_check == false
61
+ end
62
+ end
63
+
64
+ def self.image(comp_imgs)
65
+ images_numbered = Helpers.array_to_numhash(comp_imgs.list_images)
66
+ image_name = 'nil'
67
+
68
+ # List available images in a numbered hash.
69
+ puts "\nAvailable Images:"
70
+ i_name_length = Helpers.hash_largest_value(images_numbered).length
71
+ printf("%0s %-#{i_name_length}s\n", 'Id', 'Image')
72
+ images_numbered.each do |id, i_name|
73
+ printf("%0s %-#{i_name_length}s\n", "#{id}.", i_name)
74
+ end
75
+
76
+ # Loop input until existing image is selected
77
+ print 'Which image should we use for this instance?: '
78
+ until images_numbered.values.include?(image_name)
79
+ image_name = gets.chomp
80
+
81
+ if image_name =~ /^[0-9]*$/
82
+ until images_numbered.keys.include?(image_name)
83
+ print "#{image_name} is not a valid Id. Enter an Id from above: "
84
+ image_name = gets.chomp
85
+ end
86
+
87
+ image_name = images_numbered[image_name.to_s]
88
+ end
89
+
90
+ image_check = images_numbered.values.include?(image_name)
91
+ print "#{image_name} is not a valid image. Please enter an option from above: " if image_check == false
92
+ end
93
+
94
+ print "Image Name: #{image_name}\n"
95
+ comp_imgs.get_image_by_name(image_name)
96
+ end
97
+
98
+ def self.flavor(comp_flvs)
99
+ flavors = Helpers.objects_to_numhash(comp_flvs.all_flavors.sort_by(&:ram))
100
+ flavor_name = 'nil'
101
+
102
+ puts "\nAvailable Instance Flavors:"
103
+ puts sprintf("%0s %-15s %-10s %-10s %0s", 'Id', 'Name', 'RAM', 'VCPUs', 'Disk')
104
+ flavors.each do |id, flavor|
105
+ print sprintf("%0s %-15s %-10s %-10s %0s\n",
106
+ "#{id}.", flavor[:name].split('.')[1], flavor[:ram], flavor[:vcpus], flavor[:disk])
107
+ end
108
+
109
+ print 'Which flavor should we use for this instance?: '
110
+ flavor_check = false
111
+
112
+ until flavor_check == true
113
+ flavor_name = gets.chomp
114
+
115
+ if flavor_name =~ /^[0-9]*$/
116
+ until flavors.keys.include?(flavor_name.to_i)
117
+ print "#{flavor_name} is not a valid Id. Enter an Id from above: "
118
+ flavor_name = gets.chomp
119
+ end
120
+
121
+ flavor_name = flavors[flavor_name.to_i][:name].split('.')[1]
122
+ end
123
+
124
+ flavors.each_value do |flavor|
125
+ flavor_check = true if flavor[:name].end_with?(flavor_name)
126
+ end
127
+
128
+ print "#{flavor_name} is not a valid flavor. Please enter an option from above: " if flavor_check == false
129
+ end
130
+
131
+ print "Flavor Name: #{flavor_name}\n"
132
+ comp_flvs.get_flavor(flavor_name)
133
+ end
134
+
135
+ def self.keypair(comp_keys)
136
+ keypairs = Helpers.objects_to_numhash(comp_keys.all_keypairs)
137
+ keypair_name = 'nil'
138
+
139
+ # List available keypairs
140
+ puts "\nAvailable Keypairs:"
141
+ print sprintf("%0s %-15s\n", 'Id', 'KeyPair Name')
142
+ keypairs.each do |id, key|
143
+ print sprintf("%0s %-15s\n", "#{id}.", key[:name])
144
+ end
145
+
146
+ # Loop input until existing flavor is selected or create a new one
147
+ print 'Enter a keypair to use for this instance or enter a name for a new keypair : '
148
+ keypair_check = false
149
+
150
+ until keypair_check == true
151
+ keypair_name = gets.chomp
152
+
153
+ # Accept keypair Id as an entry
154
+ if keypair_name =~ /^[0-9]*$/
155
+ until keypairs.keys.include?(keypair_name.to_i)
156
+ print "#{keypair_name} is not a valid Id.
157
+ Enter an Id from above, or \'return\' to restart keypair selection. : "
158
+ keypair_name = gets.chomp
159
+ return keypair(settings, compute) if keypair_name == 'return'
160
+ end
161
+
162
+ keypair_name = keypairs[keypair_name.to_i][:name]
163
+ end
164
+
165
+ keypair_check = Helpers.check_nested_hash_value(keypairs, :name, keypair_name)
166
+
167
+ if keypair_check == false
168
+ print "#{keypair_name} is not an existing keypair.
169
+ Should we create a new keypair named #{keypair_name}? (Y/N): "
170
+
171
+ if gets.chomp =~ /^y(es)?$/i
172
+ puts "Creating keypair: #{keypair_name}!"
173
+ return comp_keys.create_keypair(keypair_name)
174
+ else
175
+ print 'Please enter an option from above: '
176
+ end
177
+ end
178
+ end
179
+
180
+ comp_keys.get_keypair(keypair_name)
181
+ end
182
+ end
@@ -0,0 +1,60 @@
1
+
2
+ class Menus
3
+ def self.get_menu(menu)
4
+ menus = { 'main' => { 'instance' => 'Instance Manager',
5
+ 'keypair' => 'Keypair Manager (Not yet implemented!)',
6
+ 'help' => 'Outputs commands for current the menu level',
7
+ 'exit' => 'Exit dAnarchy_sys'},
8
+ 'instance' => { 'status' => 'Current running status of instance',
9
+ 'connect' => 'Connect to instance through SSH',
10
+ 'start' => 'Start a currently stopped instance',
11
+ 'stop' => 'Stop a currently running instance',
12
+ 'pause' => 'Pause instance (to RAM)',
13
+ 'unpause' => 'Unpause instance from paused state',
14
+ 'suspend' => 'Suspend Instance (to disk)',
15
+ 'resume' => 'Resume instance from suspended state',
16
+ 'create' => 'Create a new instance',
17
+ 'delete' => 'Delete this instance'}
18
+ }
19
+
20
+ menus[menu]
21
+ end
22
+
23
+ def self.numbered_menu(menu)
24
+ numbered_menu = Helpers.hash_to_numhash(get_menu(menu))
25
+ end
26
+
27
+ def self.print_menu(menu)
28
+ if menu == 'main'
29
+ puts 'dAnarchy_sys main menu commands:'
30
+ puts 'Enter \'help\' to view available commands or \'exit\' to leave.'
31
+ # print_menu(menu)
32
+ elsif menu == 'instance'
33
+ puts 'Instance Manager commands: '
34
+ puts 'Enter \'help\' to view available commands or \'back\' for the main menu.'
35
+ # print_menu(menu)
36
+ elsif menu == 'keypair'
37
+ puts 'Keypair Manager commands: '
38
+ puts 'Not yet implemented!'
39
+ return
40
+ # print_menu(menu)
41
+ elsif menu == 'storage'
42
+ puts 'Storage Manager commands: '
43
+ puts 'Not yet implemented!'
44
+ return
45
+ # print_menu(menu)
46
+ end
47
+
48
+ # numbered_menu = Helpers.hash_to_numhash(menu)
49
+ numbered_menu = numbered_menu(menu)
50
+ menu = get_menu(menu)
51
+
52
+ fields = PrintFormats.printf_numhash(numbered_menu)
53
+
54
+ numbered_menu.each do |id, v|
55
+ v.each do |name, info|
56
+ printf("#{fields}\n", "#{id}.", "#{name}:", info)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,33 @@
1
+
2
+ class Providers
3
+ def self.chooser
4
+ config = ConfigMgr.new
5
+ danarchysys_config = config.load
6
+ providers = Helpers.array_to_numhash(danarchysys_config[:connections].keys)
7
+ provider = 'nil'
8
+
9
+ if providers.count == 1
10
+ provider = providers['1']
11
+ return provider
12
+ end
13
+
14
+ fields = PrintFormats.printf_hash(providers)
15
+ printf("#{fields}\n", 'Id', 'Provider')
16
+ providers.each do |id, provider|
17
+ printf("#{fields}\n", "#{id}.", provider)
18
+ end
19
+
20
+ until providers.values.include?(provider)
21
+ print 'Which provider should we use? (enter \'exit\' to leave): '
22
+ provider = gets.chomp
23
+
24
+ abort('Exiting') if provider == 'exit'
25
+
26
+ if provider =~ /^[0-9]*$/ # select by Id
27
+ provider = providers[provider.to_s]
28
+ end
29
+ end
30
+
31
+ provider
32
+ end
33
+ end
@@ -0,0 +1,66 @@
1
+
2
+ require 'yaml'
3
+
4
+ # dAnarchy_sys config management
5
+ class ConfigMgr
6
+ def initialize
7
+ @danarchysys_path = File.realpath(File.join(File.dirname(__FILE__), '..', '..'))
8
+ @config_file = File.join(@danarchysys_path, 'config', 'danarchysys.yml')
9
+ end
10
+
11
+ def config_template
12
+ config_template = {
13
+ :connections => {},
14
+ :settings => {}
15
+ }
16
+ end
17
+
18
+ def load
19
+ if File.exists?(@config_file)
20
+ return YAML.load_file(@config_file)
21
+ else
22
+ return config_template
23
+ end
24
+ end
25
+
26
+ def save(param_hash)
27
+ File.write(@config_file, param_hash.to_yaml)
28
+ end
29
+
30
+ def connection_add(provider, openstack_auth_url, openstack_username, openstack_api_key, openstack_tenant)
31
+ danarchysys_config = load
32
+
33
+ danarchysys_config[:connections][provider.to_sym] = {
34
+ openstack_auth_url: openstack_auth_url,
35
+ openstack_username: openstack_username,
36
+ openstack_api_key: openstack_api_key,
37
+ openstack_tenant: openstack_tenant
38
+ }
39
+
40
+ danarchysys_config
41
+ end
42
+
43
+ def connection_delete(provider)
44
+ danarchysys_config = load
45
+
46
+ danarchysys_config[:connections].delete(provider.to_sym)
47
+
48
+ danarchysys_config
49
+ end
50
+
51
+ def setting_add(name, value)
52
+ danarchysys_config = load
53
+
54
+ danarchysys_config[:settings][name.to_sym] = value
55
+
56
+ danarchysys_config
57
+ end
58
+
59
+ def setting_delete(name)
60
+ danarchysys_config = load
61
+
62
+ danarchysys_config[:settings].delete(name.to_sym)
63
+
64
+ danarchysys_config
65
+ end
66
+ end
@@ -0,0 +1,61 @@
1
+
2
+ # Routine methods for DanarchySys
3
+ class Helpers
4
+ def self.array_to_numhash(array)
5
+ numbered_hash = {}
6
+
7
+ count = 1
8
+ array.sort.each do |item|
9
+ numbered_hash[count.to_s] = item
10
+ count += 1
11
+ end
12
+
13
+ numbered_hash
14
+ end
15
+
16
+ def self.hash_to_numhash(hash)
17
+ numbered_hash = {}
18
+
19
+ hash.map.with_index(1) do | (k, v), index |
20
+ numbered_hash[index] = {k => v}
21
+ end
22
+
23
+ numbered_hash
24
+ end
25
+
26
+ def self.objects_to_numhash(objects)
27
+ numbered_object_hash = {}
28
+
29
+ objects.map.with_index(1) do | obj, index |
30
+ numbered_object_hash[index] = obj.all_attributes
31
+ end
32
+
33
+ numbered_object_hash
34
+ end
35
+
36
+ def self.hash_largest_key(hash)
37
+ hash.keys.map(&:to_s).max_by(&:size)
38
+ end
39
+
40
+ def self.hash_largest_value(hash)
41
+ hash.values.map(&:to_s).max_by(&:size)
42
+ end
43
+
44
+ def self.hash_largest_nested_key(hash)
45
+ hash.each_value.flat_map(&:keys).max_by(&:size)
46
+ end
47
+
48
+ def self.hash_largest_nested_value(hash)
49
+ hash.each_value.flat_map(&:values).max_by(&:size)
50
+ end
51
+
52
+ def self.check_nested_hash_value(hash, key, value)
53
+ check = false
54
+
55
+ hash.each_value do |val|
56
+ check = true if val[key].end_with?(value)
57
+ end
58
+
59
+ check
60
+ end
61
+ end