pec 0.1.2 → 0.1.3
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 +4 -4
- data/.coveralls.yml +1 -0
- data/.travis.yml +3 -1
- data/Gemfile +3 -0
- data/README.md +47 -34
- data/Rakefile +4 -0
- data/lib/pec.rb +1 -0
- data/lib/pec/cli.rb +33 -9
- data/lib/pec/compute/security_group.rb +0 -3
- data/lib/pec/compute/server.rb +2 -17
- data/lib/pec/configure.rb +2 -2
- data/lib/pec/configure/ethernet.rb +5 -9
- data/lib/pec/configure/host.rb +2 -3
- data/lib/pec/configure/user_data.rb +15 -22
- data/lib/pec/errors.rb +12 -0
- data/lib/pec/network/port.rb +1 -8
- data/lib/pec/network/subnet.rb +3 -1
- data/lib/pec/query.rb +2 -0
- data/lib/pec/version.rb +1 -1
- data/lib/pec/vm_director.rb +13 -32
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 409aebdf8468165b18f5bf9e130a64c0e8d52e89
|
4
|
+
data.tar.gz: 79635469bbd61536714e08715cfafe4a9c5ab77e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 683b49175521024e1a3d617678efd3fdc4896a3905c1d25827c6fb0eb2b2be055ba6d971b1468b0572cb0d0f7c0437ee953ff2bec9ef51470ba875b61143c0da
|
7
|
+
data.tar.gz: 58be8b103ec3b6353d0eba896d31b1c4738dec33a6fc8f0b85f3710c5f3f70a63fd04b942306f9435901ad9349194fbf4b6bfaedbeba025f84dae8abe2ed1380
|
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
service_name: travis-ci
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,25 +1,33 @@
|
|
1
1
|
# Pec
|
2
|
-
|
2
|
+
[](https://travis-ci.org/pyama86/pec)
|
3
3
|
OpenStackにおいて複数サーバの起動や、
|
4
4
|
DHCPサーバがない状況でのIP自動採番を実現します。
|
5
5
|
|
6
|
-
##
|
6
|
+
## Install
|
7
7
|
|
8
8
|
|
9
9
|
$ gem install pec
|
10
10
|
|
11
|
-
##
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
定義ファイル作成
|
14
|
+
|
15
|
+
$ pec init
|
16
|
+
|
17
|
+
```
|
18
|
+
create - /Pec.yaml
|
19
|
+
create - /user_datas/web_server.yaml.sample
|
20
|
+
```
|
21
|
+
|
22
|
+
Pec.yamlに基づきホストを作成します。
|
23
|
+
ホスト名が指定された場合はそのホストのみ作成、削除します。
|
15
24
|
|
16
25
|
$ pec up <hostname>
|
17
26
|
|
18
27
|
$ pec destroy <hostname>
|
19
28
|
|
20
|
-
###
|
21
|
-
|
22
|
-
|
29
|
+
### Configure
|
30
|
+
#### ~/.fog
|
23
31
|
```
|
24
32
|
% cat ~/.fog
|
25
33
|
default:
|
@@ -30,7 +38,7 @@ default:
|
|
30
38
|
```
|
31
39
|
|
32
40
|
|
33
|
-
|
41
|
+
#### Pec.yaml
|
34
42
|
```
|
35
43
|
pyama-test001:
|
36
44
|
image: centos-7.1_chef-12.3_puppet-3.7
|
@@ -43,10 +51,13 @@ pyama-test001:
|
|
43
51
|
dns1: 8.8.8.8
|
44
52
|
dns2: 8.8.8.8
|
45
53
|
eth1:
|
46
|
-
bootproto:
|
47
|
-
|
48
|
-
|
49
|
-
|
54
|
+
bootproto: dhcp
|
55
|
+
security_group:
|
56
|
+
- default
|
57
|
+
- ssh
|
58
|
+
templates:
|
59
|
+
- base.yaml
|
60
|
+
- webserver.yaml
|
50
61
|
user_data:
|
51
62
|
hostname: pyama-test001
|
52
63
|
fqdn: pyama-test001.ikemen.com
|
@@ -54,28 +65,30 @@ pyama-test001:
|
|
54
65
|
pyama-test002:
|
55
66
|
image: centos-7.1_chef-12.3_puppet-3.7
|
56
67
|
flavor: m1.midium
|
57
|
-
|
58
|
-
|
59
|
-
bootproto: static
|
60
|
-
ip_address: 10.0.0.64/26
|
61
|
-
gateway: 10.0.0.127
|
62
|
-
dns1: 8.8.8.8
|
63
|
-
dns2: 8.8.8.8
|
64
|
-
path: /etc/sysconfig/network-scripts/ifcfg-bond0
|
65
|
-
eth1:
|
66
|
-
bootproto: dhcp
|
67
|
-
user_data:
|
68
|
-
hostname: pyama-test002
|
69
|
-
fqdn: pyama-test002.ikemen.com
|
70
|
-
repo_releasever: 7.1.1503
|
68
|
+
・・・
|
69
|
+
|
71
70
|
```
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
71
|
+
##### Detail
|
72
|
+
|
73
|
+
| 項目名 | 説明 | 必須 | 例示 |
|
74
|
+
| -------------- | ---------------------------------------------- | ---- | ------------------------------- |
|
75
|
+
| instance_name| インスタンス名 | ○ | pyama-test001 |
|
76
|
+
| image | イメージ名 | ○ | centos-7.1_chef-12.3_puppet-3.7 |
|
77
|
+
| flavor | フレーバー名 | ○ | m1.small |
|
78
|
+
| networks | ネットワーク定義 | - | [] |
|
79
|
+
| security_group | セキュリティグループ名 | - | [default,ssh] |
|
80
|
+
| templates | `user_data`のテンプレート.`./user_datas`に配置 | - | [base.yaml,webserver.yaml] |
|
81
|
+
| user_data | cloud-init記法に準拠 | - | - |
|
78
82
|
|
83
|
+
##### Networks
|
84
|
+
| 項目名 | 説明 | 必須 | 例示 |
|
85
|
+
| ------------ | ---------------- | ---- | -------------- |
|
86
|
+
| device_name | デバイス名 | ○ | eth0 |
|
87
|
+
| bootproto | 設定方式 | ○ | static or dhcp |
|
88
|
+
| ip_address | IPアドレス(CIDR) | ※ | 10.1.1.1/24 |
|
89
|
+
| path | NW設定保存パス | | default:/etc/sysconfig/network-scripts/ifcfg-[device_name] |
|
90
|
+
※ bootproto=staticの場合必須
|
91
|
+
上記以外の項目は設定ファイルに`KEY=value`形式で出力されます。
|
79
92
|
|
80
93
|
## Author
|
81
94
|
* pyama86
|
data/Rakefile
CHANGED
data/lib/pec.rb
CHANGED
data/lib/pec/cli.rb
CHANGED
@@ -6,12 +6,16 @@ module Pec
|
|
6
6
|
desc 'init', 'create sample config'
|
7
7
|
def init
|
8
8
|
dirname = "user_datas"
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
unless FileTest.exist?(dirname)
|
10
|
+
FileUtils.mkdir_p(dirname)
|
11
|
+
puts "create directry user_datas"
|
12
|
+
end
|
13
|
+
unless File.exist?("Pec.yaml")
|
14
|
+
open("Pec.yaml","w") do |e|
|
15
|
+
YAML.dump(Pec::Configure::Sample.pec_file, e)
|
16
|
+
end
|
17
|
+
puts "create configure file Pec.yaml"
|
18
|
+
end
|
15
19
|
open("#{dirname}/web_server.yaml.sample","w") do |e|
|
16
20
|
YAML.dump(Pec::Configure::Sample.user_data, e)
|
17
21
|
end if FileTest.exist?(dirname)
|
@@ -24,21 +28,41 @@ module Pec
|
|
24
28
|
config.load("Pec.yaml")
|
25
29
|
|
26
30
|
director = Pec::VmDirector.new
|
31
|
+
|
27
32
|
config.each do |host|
|
28
33
|
next if !host_name.nil? && host.name != host_name
|
29
|
-
|
34
|
+
|
35
|
+
begin
|
36
|
+
director.make(host)
|
37
|
+
rescue Pec::Errors::Error => e
|
38
|
+
puts e
|
39
|
+
puts "can't create server:#{host.name}"
|
40
|
+
rescue Excon::Errors::Error => e
|
41
|
+
JSON.parse(e.response[:body]).each { |e,m| puts "#{e}:#{m["message"]}" }
|
42
|
+
end
|
30
43
|
end if config
|
44
|
+
rescue Errno::ENOENT => e
|
45
|
+
puts e
|
46
|
+
rescue Pec::Errors::Configure => e
|
47
|
+
puts "configure can't load"
|
31
48
|
end
|
49
|
+
|
32
50
|
option :force , type: :boolean, aliases: "-f"
|
33
51
|
desc "destroy", "delete vm"
|
34
52
|
def destroy(name = nil)
|
35
53
|
config = Pec::Configure.new
|
36
54
|
config.load("Pec.yaml")
|
37
|
-
|
38
55
|
config.each do |host|
|
39
56
|
next if !name.nil? && host.name != name
|
40
|
-
|
57
|
+
begin
|
58
|
+
Pec::Compute::Server.new.destroy!(host.name) if options[:force] || yes?("#{host.name}: Are you sure you want to destroy the '#{host.name}' VM? [y/N]")
|
59
|
+
rescue Pec::Errors::Error => e
|
60
|
+
puts e
|
61
|
+
puts "can't create server:#{host.name}"
|
62
|
+
end
|
41
63
|
end if config
|
64
|
+
rescue Errno::ENOENT => e
|
65
|
+
puts e
|
42
66
|
end
|
43
67
|
end
|
44
68
|
end
|
@@ -6,9 +6,6 @@ module Pec
|
|
6
6
|
security_groups.each do |sg_name|
|
7
7
|
response = Fog::Compute[:openstack].add_security_group(server_id, sg_name)
|
8
8
|
end if security_groups
|
9
|
-
rescue Excon::Errors::Error => e
|
10
|
-
JSON.parse(e.response[:body]).each { |e,m| puts "#{e}:#{m["message"]}" }
|
11
|
-
false
|
12
9
|
end
|
13
10
|
end
|
14
11
|
end
|
data/lib/pec/compute/server.rb
CHANGED
@@ -5,10 +5,7 @@ module Pec
|
|
5
5
|
include Query
|
6
6
|
def create(name, image_ref, flavor_ref, ports, options)
|
7
7
|
networks = ports.map do |port|
|
8
|
-
if port.used?
|
9
|
-
puts "port-id:#{port.id} ip-addr:#{port.ip_address} in used"
|
10
|
-
return false
|
11
|
-
end
|
8
|
+
raise(Pec::Errors::Port, "port-id:#{port.id} ip-addr:#{port.ip_address} in used") if port.used?
|
12
9
|
puts "#{name}: assingn ip #{port.ip_address}"
|
13
10
|
{ port_id: port.id }
|
14
11
|
end if ports
|
@@ -22,10 +19,6 @@ module Pec
|
|
22
19
|
end
|
23
20
|
|
24
21
|
response.data[:body]["server"]["id"]
|
25
|
-
|
26
|
-
rescue Excon::Errors::Error => e
|
27
|
-
JSON.parse(e.response[:body]).each { |e,m| puts "#{e}:#{m["message"]}" }
|
28
|
-
false
|
29
22
|
end
|
30
23
|
|
31
24
|
def exists?(server_name)
|
@@ -34,20 +27,12 @@ module Pec
|
|
34
27
|
|
35
28
|
def destroy!(server_name)
|
36
29
|
server = fetch(server_name)
|
37
|
-
unless server
|
38
|
-
puts "server_name:#{server_name} is not fond!"
|
39
|
-
return
|
40
|
-
end
|
41
|
-
|
30
|
+
raise(Pec::Errors::Host, "server_name:#{server_name} is not fond!") unless server
|
42
31
|
response = Fog::Compute[:openstack].delete_server(server["id"]) if server
|
43
32
|
|
44
33
|
if response && response[:status] == 204
|
45
34
|
puts "server_name:#{server_name} is deleted!"
|
46
35
|
end
|
47
|
-
|
48
|
-
rescue Excon::Errors::Error => e
|
49
|
-
JSON.parse(e.response[:body]).each { |e,m| puts "#{e}:#{m["message"]}" }
|
50
|
-
false
|
51
36
|
end
|
52
37
|
end
|
53
38
|
end
|
data/lib/pec/configure.rb
CHANGED
@@ -18,23 +18,19 @@ module Pec
|
|
18
18
|
|
19
19
|
def check_require_key(name, config)
|
20
20
|
err = %w(bootproto).find {|k| !config[1].key?(k)}
|
21
|
-
|
22
|
-
|
23
|
-
false
|
21
|
+
raise(Pec::Errors::Ethernet, "skip! #{name}: #{err} is required!") unless err.nil?
|
22
|
+
true
|
24
23
|
end
|
25
24
|
|
26
25
|
def check_network_key(name, config)
|
27
26
|
net = config[1]
|
28
27
|
case
|
29
28
|
when (net["bootproto"] == "static" && net["ip_address"].nil?)
|
30
|
-
|
31
|
-
return false
|
29
|
+
raise(Pec::Errors::Ethernet, "skip! #{name}: ip_address is required by bootproto static")
|
32
30
|
when (!net["bootproto"] == "static" && !net["bootproto"] == "dhcp")
|
33
|
-
|
34
|
-
return false
|
31
|
+
raise(Pec::Errors::Ethernet, "skip! #{name}: bootproto set the value dhcp or static")
|
35
32
|
when (!net["bootproto"] == "static" && !net["bootproto"] == "dhcp")
|
36
|
-
|
37
|
-
return false
|
33
|
+
raise(Pec::Errors::Ethernet, "skip! #{name}: bootproto set the value dhcp or static")
|
38
34
|
end
|
39
35
|
true
|
40
36
|
end
|
data/lib/pec/configure/host.rb
CHANGED
@@ -28,9 +28,8 @@ module Pec
|
|
28
28
|
|
29
29
|
def check_require_key(config)
|
30
30
|
err = %w(image flavor).find {|r| !config[1].key?(r)}
|
31
|
-
|
32
|
-
|
33
|
-
false
|
31
|
+
raise(Pec::Errors::Host,"skip! #{config[0]}: #{err} is required!") unless err.nil?
|
32
|
+
true
|
34
33
|
end
|
35
34
|
end
|
36
35
|
end
|
@@ -12,43 +12,36 @@ module Pec
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def get_template(config)
|
15
|
-
merge_template
|
16
|
-
|
17
|
-
|
18
|
-
merge_template.merge!(YAML.load_file("user_datas/#{template}").to_hash)
|
19
|
-
else
|
20
|
-
puts "template:#{temlate} is not fond!"
|
21
|
-
end
|
15
|
+
config.templates.inject({}) do |merge_template, template|
|
16
|
+
raise(Pec::Errors::UserData, "template:#{template} is not fond!") unless FileTest.exist?("user_datas/#{template}")
|
17
|
+
merge_template.merge!(YAML.load_file("user_datas/#{template}").to_hash)
|
22
18
|
end if config.templates
|
23
|
-
merge_template
|
24
19
|
end
|
25
20
|
|
26
21
|
def make_port_content(config, ports)
|
27
22
|
config.networks.map do |ether|
|
28
23
|
port_content = {}
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
port_content["device"] = ether.name unless ether.options.key?('device')
|
33
|
-
port_content["type"] = 'Ethernet' unless ether.options.key?('type')
|
34
|
-
port_content["onboot"] = "yes" unless ether.options.key?('onboot')
|
24
|
+
%w(name device).each do |k|
|
25
|
+
port_content[k] = ether.name unless ether.options.key?(k)
|
26
|
+
end
|
35
27
|
|
36
|
-
|
28
|
+
port_content["bootproto"] = ether.bootproto
|
29
|
+
port_content["type"] = ether.options['type'] ||'Ethernet'
|
30
|
+
port_content["onboot"] = ether.options['onboot'] || 'yes'
|
31
|
+
path = ether.options['path'] || "/etc/sysconfig/network-scripts/ifcfg-#{ether.name}"
|
37
32
|
|
38
33
|
port = ports.find {|p| p.name == ether.name}
|
34
|
+
port_content["hwaddr"] = port.mac_address
|
39
35
|
|
40
|
-
if
|
41
|
-
|
42
|
-
|
43
|
-
port_content["ipaddr"] = port.ip_address
|
44
|
-
end
|
45
|
-
port_content["hwaddr"] = port.mac_address
|
36
|
+
if ether.bootproto == "static"
|
37
|
+
port_content["netmask"] = port.netmask
|
38
|
+
port_content["ipaddr"] = port.ip_address
|
46
39
|
end
|
47
40
|
port_content.merge!(ether.options)
|
48
41
|
{
|
49
42
|
'content' => port_content.map {|k,v| "#{k.upcase}=#{v}"}.join("\n"),
|
50
43
|
'owner' => "root:root",
|
51
|
-
'path' =>
|
44
|
+
'path' => path,
|
52
45
|
'permissions' => "0644"
|
53
46
|
}
|
54
47
|
end
|
data/lib/pec/errors.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
module Pec
|
2
|
+
module Errors
|
3
|
+
class Error < StandardError; end
|
4
|
+
class Ethernet < Error; end
|
5
|
+
class Subnet < Error; end
|
6
|
+
class Port < Error; end
|
7
|
+
class Host < Error; end
|
8
|
+
class Query < Error; end
|
9
|
+
class UserData < Error; end
|
10
|
+
class Configure < Error; end
|
11
|
+
end
|
12
|
+
end
|
data/lib/pec/network/port.rb
CHANGED
@@ -28,7 +28,7 @@ module Pec
|
|
28
28
|
when !exists?
|
29
29
|
create(ip)
|
30
30
|
when used?
|
31
|
-
|
31
|
+
raise(Pec::Errors::Port, "ip:#{ip.to_addr} is used!")
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -89,18 +89,11 @@ module Pec
|
|
89
89
|
@@use_ip_list << response.data[:body]["port"]["fixed_ips"][0]["ip_address"]
|
90
90
|
response.data[:body]["port"]["id"]
|
91
91
|
end
|
92
|
-
|
93
|
-
rescue Excon::Errors::Error => e
|
94
|
-
JSON.parse(e.response[:body]).each { |e,m| puts "#{e}:#{m["message"]}" }
|
95
|
-
false
|
96
92
|
end
|
97
93
|
|
98
94
|
def delete(ip)
|
99
95
|
port = fetch(ip.to_addr)
|
100
96
|
response = Fog::Network[:openstack].delete_port(port["id"]) if port
|
101
|
-
rescue Excon::Errors::Error => e
|
102
|
-
JSON.parse(e.response[:body]).each { |e,m| puts "#{e}:#{m["message"]}" }
|
103
|
-
false
|
104
97
|
end
|
105
98
|
|
106
99
|
def replace(ip)
|
data/lib/pec/network/subnet.rb
CHANGED
data/lib/pec/query.rb
CHANGED
data/lib/pec/version.rb
CHANGED
data/lib/pec/vm_director.rb
CHANGED
@@ -15,47 +15,28 @@ module Pec
|
|
15
15
|
end
|
16
16
|
|
17
17
|
ports = get_ports(config)
|
18
|
-
flavor_ref =
|
19
|
-
image_ref =
|
18
|
+
flavor_ref = @flavor.get_ref(config.flavor)
|
19
|
+
image_ref = @image.get_ref(config.image)
|
20
|
+
options = { "user_data" => Pec::Configure::UserData.make(config, ports) }
|
20
21
|
|
21
|
-
return false unless flavor_ref && image_ref
|
22
|
-
|
23
|
-
options = {
|
24
|
-
"user_data" => Pec::Configure::UserData.make(config, ports),
|
25
|
-
}
|
26
22
|
@compute.create(config.name, image_ref, flavor_ref, ports, options)
|
27
23
|
end
|
28
24
|
|
29
25
|
def get_ports(config)
|
30
26
|
config.networks.map do |ether|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
unless _port.assign!(ip)
|
36
|
-
puts "ip addess:#{ip.to_addr} can't create port!"
|
37
|
-
return false
|
27
|
+
begin
|
28
|
+
ip = IP.new(ether.ip_address)
|
29
|
+
rescue ArgumentError => e
|
30
|
+
raise(Pec::Errors::Port, "ip:#{ether.ip_address} #{e}")
|
38
31
|
end
|
39
|
-
_port
|
40
|
-
end if config.networks
|
41
|
-
end
|
42
32
|
|
43
|
-
|
44
|
-
|
45
|
-
puts "ip addess:#{ip.to_addr} subnet not fond!" if _subnet.nil?
|
46
|
-
_subnet
|
47
|
-
end
|
48
|
-
|
49
|
-
def get_flavor(name)
|
50
|
-
flavor_ref = @flavor.get_ref(name)
|
51
|
-
puts "flavor:#{name} not fond!" if flavor_ref.nil?
|
52
|
-
flavor_ref
|
53
|
-
end
|
33
|
+
subnet = @subnet.fetch(ip.network.to_s)
|
34
|
+
raise(Pec::Errors::Subnet, "subnet:#{ip.network.to_s} is not fond!") unless subnet
|
54
35
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
36
|
+
port = Pec::Network::Port.new(ether.name, ip.to_addr, subnet, get_security_group_id(config.security_group))
|
37
|
+
raise(Pec::Errors::Port, "ip addess:#{ip.to_addr} can't create port!") unless port.assign!(ip)
|
38
|
+
port
|
39
|
+
end if config.networks
|
59
40
|
end
|
60
41
|
|
61
42
|
def get_security_group_id(security_groups)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kazuhiko yamashita
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06-
|
11
|
+
date: 2015-06-10 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: openstac vm booter.
|
14
14
|
email:
|
@@ -20,6 +20,7 @@ executables:
|
|
20
20
|
extensions: []
|
21
21
|
extra_rdoc_files: []
|
22
22
|
files:
|
23
|
+
- ".coveralls.yml"
|
23
24
|
- ".gitignore"
|
24
25
|
- ".travis.yml"
|
25
26
|
- Gemfile
|
@@ -40,6 +41,7 @@ files:
|
|
40
41
|
- lib/pec/configure/host.rb
|
41
42
|
- lib/pec/configure/sample.rb
|
42
43
|
- lib/pec/configure/user_data.rb
|
44
|
+
- lib/pec/errors.rb
|
43
45
|
- lib/pec/network/port.rb
|
44
46
|
- lib/pec/network/subnet.rb
|
45
47
|
- lib/pec/query.rb
|
@@ -66,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
66
68
|
version: '0'
|
67
69
|
requirements: []
|
68
70
|
rubyforge_project:
|
69
|
-
rubygems_version: 2.4.
|
71
|
+
rubygems_version: 2.4.7
|
70
72
|
signing_key:
|
71
73
|
specification_version: 4
|
72
74
|
summary: openstack vm booter.
|