pec 0.4.4 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +4 -1
- data/lib/pec.rb +35 -32
- data/lib/pec/builder/port.rb +120 -0
- data/lib/pec/builder/server.rb +28 -0
- data/lib/pec/builder/user_data.rb +39 -0
- data/lib/pec/cli.rb +3 -3
- data/lib/pec/configure.rb +17 -26
- data/lib/pec/director.rb +103 -44
- data/lib/pec/init.rb +1 -1
- data/lib/pec/logger.rb +21 -0
- data/lib/pec/version.rb +1 -1
- data/pec.gemspec +1 -1
- metadata +8 -24
- data/lib/pec/compute/flavor.rb +0 -7
- data/lib/pec/compute/image.rb +0 -7
- data/lib/pec/compute/server.rb +0 -30
- data/lib/pec/compute/tenant.rb +0 -16
- data/lib/pec/configure/ethernet.rb +0 -81
- data/lib/pec/configure/host.rb +0 -40
- data/lib/pec/configure/sample.rb +0 -55
- data/lib/pec/configure/user_data.rb +0 -36
- data/lib/pec/director/destroy_director.rb +0 -23
- data/lib/pec/director/helper.rb +0 -51
- data/lib/pec/director/make_director.rb +0 -35
- data/lib/pec/director/vm_status_director.rb +0 -41
- data/lib/pec/network/port.rb +0 -104
- data/lib/pec/network/port_state.rb +0 -40
- data/lib/pec/network/security_group.rb +0 -7
- data/lib/pec/network/subnet.rb +0 -14
- data/lib/pec/query.rb +0 -24
- data/lib/pec/resource.rb +0 -26
- data/lib/pec/resource/mock.rb +0 -172
- data/lib/pec/resource/openstack.rb +0 -60
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8a7355209a3c35e40ac68d514cae1e0ed75e8102
|
4
|
+
data.tar.gz: ea45ced7c65397076d2c7496eb5efe44ffa6d41a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f40e9678fbd05ffeac16fac0ca9eb1832185a38526a188149a473dee6d8e397d1250b1c081a30b687262fb02e7ebab83b02c53dcca3d9b03f7cb4f15daffdb8
|
7
|
+
data.tar.gz: 57feae3668f00d475f1b1be8871294caa4fb7ac72ace25a78a9af76e57220cf1dd70dcf58e4aa7e5b5392e20db6c782cf49fd11459c664c44046697d56accc1d
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -37,6 +37,7 @@ _default_: &def
|
|
37
37
|
tenant: your_tenant
|
38
38
|
image: centos-7.1_chef-12.3_puppet-3.7
|
39
39
|
flavor: m1.small
|
40
|
+
availability_zone: nova
|
40
41
|
|
41
42
|
pyama-test001:
|
42
43
|
<<: *def
|
@@ -74,8 +75,10 @@ pyama-test002:
|
|
74
75
|
| flavor | フレーバー名 | ○ | m1.small |
|
75
76
|
| networks | ネットワーク定義 | - | [] |
|
76
77
|
| security_group | セキュリティグループ名 | - | [default,ssh] |
|
77
|
-
| templates | `user_data
|
78
|
+
| templates | `user_data`のテンプレート `./user_data` に配置 | - | [base.yaml,webserver.yaml] |
|
78
79
|
| user_data | cloud-init記法に準拠 | - | - |
|
80
|
+
| availability_zone | アベイラビリティゾーン | - | nova |
|
81
|
+
|
79
82
|
* 先頭が_で開始されるインスタンス名はyaml merge記法用途と認識し、スキップします
|
80
83
|
|
81
84
|
##### Networks
|
data/lib/pec.rb
CHANGED
@@ -2,42 +2,45 @@ require 'fog'
|
|
2
2
|
require 'ip'
|
3
3
|
require 'colorator'
|
4
4
|
require "pec/version"
|
5
|
-
require "pec/
|
6
|
-
require "pec/errors"
|
7
|
-
require "pec/init"
|
8
|
-
require "pec/resource"
|
9
|
-
require "pec/resource/openstack"
|
10
|
-
require "pec/resource/mock"
|
11
|
-
require "pec/director"
|
12
|
-
require "pec/director/helper"
|
13
|
-
require "pec/director/make_director"
|
14
|
-
require "pec/director/destroy_director"
|
15
|
-
require "pec/director/vm_status_director"
|
5
|
+
require "pec/logger"
|
16
6
|
require "pec/configure"
|
17
|
-
require "pec/
|
18
|
-
require "pec/
|
19
|
-
require "pec/
|
20
|
-
require "pec/
|
21
|
-
require "pec/compute/server"
|
22
|
-
require "pec/compute/flavor"
|
23
|
-
require "pec/compute/image"
|
24
|
-
require "pec/compute/tenant"
|
25
|
-
require "pec/network/security_group"
|
26
|
-
require "pec/network/port"
|
27
|
-
require "pec/network/port_state"
|
28
|
-
require "pec/network/subnet"
|
7
|
+
require "pec/director"
|
8
|
+
require "pec/builder/server"
|
9
|
+
require "pec/builder/port"
|
10
|
+
require "pec/builder/user_data"
|
29
11
|
require "pec/cli"
|
30
12
|
|
31
13
|
module Pec
|
32
|
-
|
14
|
+
def self.compute
|
15
|
+
@_compute ||= Fog::Compute.new({
|
16
|
+
provider: 'openstack'
|
17
|
+
})
|
18
|
+
@_compute
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.neutron
|
22
|
+
@_neutron ||= Fog::Network.new({
|
23
|
+
provider: 'openstack'
|
24
|
+
})
|
25
|
+
@_neutron
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.identity
|
29
|
+
@_identity ||= Fog::Identity.new({
|
30
|
+
provider: 'openstack'
|
31
|
+
})
|
32
|
+
@_identity
|
33
|
+
end
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
def deep_merge!(second)
|
40
|
-
merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : Array === v1 && Array === v2 ? v1 | v2 : [:undefined, nil, :nil].include?(v2) ? v1 : v2 }
|
41
|
-
self.merge!(second.to_h, &merger)
|
35
|
+
def self.load_config(file_name=nil)
|
36
|
+
file_name ||= 'Pec.yaml'
|
37
|
+
@_configure = []
|
38
|
+
YAML.load_file(file_name).to_hash.reject {|c| c[0].to_s.match(/^_/)}.each do |host|
|
39
|
+
@_configure << Pec::Configure.new(host)
|
42
40
|
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.configure
|
44
|
+
@_configure
|
45
|
+
end
|
43
46
|
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module Pec
|
2
|
+
module Builder
|
3
|
+
class Port
|
4
|
+
attr_reader :user_data
|
5
|
+
def build(host)
|
6
|
+
ports = []
|
7
|
+
@user_data = []
|
8
|
+
|
9
|
+
host.networks.each do |network|
|
10
|
+
validate(network)
|
11
|
+
Pec::Logger.notice "port create start : #{network[0]}"
|
12
|
+
port = create_port(host, network)
|
13
|
+
Pec::Logger.notice "assgin ip : #{port.fixed_ips.first["ip_address"]}"
|
14
|
+
ports << port
|
15
|
+
@user_data << gen_user_data(network, port)
|
16
|
+
end
|
17
|
+
{
|
18
|
+
nics: ports.map {|port| { port_id: port.id }}
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def validate(network)
|
23
|
+
%w(
|
24
|
+
bootproto
|
25
|
+
ip_address
|
26
|
+
).each do |k|
|
27
|
+
raise "network key #{k} is require" unless network[1][k]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def create_port(host, network)
|
32
|
+
ip = IP.new(network[1]['ip_address'])
|
33
|
+
subnet = Pec.neutron.subnets.find {|s|s.cidr == ip.network.to_s}
|
34
|
+
attribute = gen_port_attribute(host, network, subnet, ip)
|
35
|
+
Pec.neutron.ports.create(attribute)
|
36
|
+
end
|
37
|
+
|
38
|
+
def gen_port_attribute(host, network, subnet, ip)
|
39
|
+
attribute = {
|
40
|
+
name: network[0],
|
41
|
+
network_id: subnet.network_id
|
42
|
+
}
|
43
|
+
|
44
|
+
attribute.merge!(
|
45
|
+
fixed_ip(subnet, ip)
|
46
|
+
) if ip.to_s != subnet.cidr
|
47
|
+
|
48
|
+
attribute.merge!(
|
49
|
+
security_group(host)
|
50
|
+
) if host.security_group
|
51
|
+
|
52
|
+
attribute.merge!(
|
53
|
+
allowed_address_pairs(network)
|
54
|
+
) if network[1]['allowed_address_pairs']
|
55
|
+
attribute
|
56
|
+
end
|
57
|
+
|
58
|
+
def gen_user_data(network, port)
|
59
|
+
path = network[1]['path'] || "/etc/sysconfig/network-scripts/ifcfg-#{port.name}"
|
60
|
+
{
|
61
|
+
'content' => ifcfg_config(network, port),
|
62
|
+
'owner' => "root:root",
|
63
|
+
'path' => path,
|
64
|
+
'permissions' => "0644"
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
def ifcfg_config(network, port)
|
69
|
+
base = {
|
70
|
+
"name" => port.name,
|
71
|
+
"device" => port.name,
|
72
|
+
"type" => 'Ethernet',
|
73
|
+
"onboot" => 'yes',
|
74
|
+
"hwaddr" => port.mac_address
|
75
|
+
}
|
76
|
+
|
77
|
+
base.merge!(
|
78
|
+
{
|
79
|
+
"netmask" => IP.new(network[1]['ip_address']).netmask.to_s,
|
80
|
+
"ipaddr" => port.fixed_ips.first['ip_address'].split("/").first
|
81
|
+
}
|
82
|
+
) if network[1]['bootproto'] == "static"
|
83
|
+
|
84
|
+
# delete options
|
85
|
+
%w(allowed_address_pairs ip_address).each {|name| network[1].delete(name)}
|
86
|
+
|
87
|
+
base.merge!(
|
88
|
+
network[1]
|
89
|
+
)
|
90
|
+
|
91
|
+
base.map {|k,v| "#{k.upcase}=#{v}"}.join("\n")
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# after port options
|
96
|
+
#
|
97
|
+
def fixed_ip(subnet, ip)
|
98
|
+
{
|
99
|
+
fixed_ips: [
|
100
|
+
{ subnet_id: subnet.id, ip_address: ip.to_addr}
|
101
|
+
]
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
def security_group(host)
|
106
|
+
ids = host.security_group.map do |name|
|
107
|
+
Pec.neutron.security_groups.find {|sg| sg.name == name}.id
|
108
|
+
end
|
109
|
+
{ security_groups: ids }
|
110
|
+
end
|
111
|
+
|
112
|
+
def allowed_address_pairs(network)
|
113
|
+
pairs = network[1]['allowed_address_pairs'].map do |pair|
|
114
|
+
{ ip_address: pair['ip_address'] }
|
115
|
+
end
|
116
|
+
{ allowed_address_pairs: pairs }
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Pec
|
2
|
+
module Builder
|
3
|
+
class Server
|
4
|
+
def build(host)
|
5
|
+
Pec::Logger.notice "flavor is #{host.flavor}"
|
6
|
+
Pec::Logger.notice "image is #{host.image}"
|
7
|
+
hash = {
|
8
|
+
name: host.name,
|
9
|
+
flavor_ref: fetch_flavor(host).id,
|
10
|
+
image_ref: fetch_image(host).id
|
11
|
+
}
|
12
|
+
hash[:availability_zone] = host.availability_zone if host.availability_zone
|
13
|
+
hash
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.resource(name)
|
17
|
+
define_method("fetch_#{name}", -> (host) {
|
18
|
+
r = Pec.compute.send("#{name}s").find {|val|val.name == host.send(name)}
|
19
|
+
raise "not fond #{name} #{host.send(name)}" unless r
|
20
|
+
r
|
21
|
+
})
|
22
|
+
end
|
23
|
+
|
24
|
+
resource 'flavor'
|
25
|
+
resource 'image'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Pec
|
2
|
+
module Builder
|
3
|
+
class UserData
|
4
|
+
def build(host, port_user_data)
|
5
|
+
user_data = default(host)
|
6
|
+
user_data["write_files"] = port_user_data if port_user_data
|
7
|
+
if template = load_template(host)
|
8
|
+
user_data.deep_merge!(template)
|
9
|
+
end
|
10
|
+
{ user_data: "#cloud-config\n" + user_data.to_yaml }
|
11
|
+
end
|
12
|
+
|
13
|
+
def load_template(host)
|
14
|
+
host.templates.inject({}) do |merge_template, template|
|
15
|
+
template.to_s.concat('.yaml') unless template.to_s.match(/.*\.yaml/)
|
16
|
+
raise "#{template} not fond!" unless FileTest.exist?("user_data/#{template}")
|
17
|
+
merge_template.deep_merge!(YAML.load_file("user_data/#{template}").to_hash)
|
18
|
+
end if host.templates
|
19
|
+
end
|
20
|
+
|
21
|
+
def default(host)
|
22
|
+
_def = host.user_data || {}
|
23
|
+
_def['fqdn'] = host.name if host.user_data && !host.user_data['fqdn']
|
24
|
+
_def
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class ::Hash
|
31
|
+
def deep_merge(second)
|
32
|
+
merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : Array === v1 && Array === v2 ? v1 | v2 : [:undefined, nil, :nil].include?(v2) ? v1 : v2 }
|
33
|
+
self.merge(second.to_h, &merger)
|
34
|
+
end
|
35
|
+
def deep_merge!(second)
|
36
|
+
merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : Array === v1 && Array === v2 ? v1 | v2 : [:undefined, nil, :nil].include?(v2) ? v1 : v2 }
|
37
|
+
self.merge!(second.to_h, &merger)
|
38
|
+
end
|
39
|
+
end
|
data/lib/pec/cli.rb
CHANGED
@@ -12,19 +12,19 @@ module Pec
|
|
12
12
|
|
13
13
|
desc 'up', 'create vm by Pec.yaml'
|
14
14
|
def up(host_name = nil)
|
15
|
-
Pec::Director.
|
15
|
+
Pec::Director.make(host_name)
|
16
16
|
end
|
17
17
|
|
18
18
|
option :force , type: :boolean, aliases: "-f"
|
19
19
|
desc "destroy", "delete vm"
|
20
20
|
def destroy(host_name = nil)
|
21
|
-
Pec::Director.
|
21
|
+
Pec::Director.destroy(host_name, options)
|
22
22
|
end
|
23
23
|
|
24
24
|
desc "status", "vm status"
|
25
25
|
def status(host_name = nil)
|
26
26
|
say("Current machine stasus:", :yellow)
|
27
|
-
Pec::Director.
|
27
|
+
Pec::Director.status(host_name)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
data/lib/pec/configure.rb
CHANGED
@@ -1,36 +1,27 @@
|
|
1
|
-
require 'yaml'
|
2
1
|
module Pec
|
3
2
|
class Configure
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
if file_name.is_a?(Hash)
|
10
|
-
hash = file_name
|
11
|
-
else
|
12
|
-
hash = YAML.load_file(file_name).to_hash
|
13
|
-
end
|
14
|
-
|
15
|
-
hash.reject {|c| c[0].to_s.match(/^_/)}.each do |config|
|
16
|
-
|
17
|
-
config[1]['user_data'] ||= {}
|
18
|
-
config[1]['user_data']['fqdn'] ||= config[0].to_s
|
3
|
+
def initialize(config)
|
4
|
+
validate(config)
|
5
|
+
@_config = config
|
6
|
+
end
|
19
7
|
|
20
|
-
|
21
|
-
|
22
|
-
end
|
23
|
-
rescue Psych::SyntaxError,NoMethodError => e
|
24
|
-
raise(Pec::Errors::Configure, e)
|
8
|
+
def name
|
9
|
+
@_config[0]
|
25
10
|
end
|
26
11
|
|
27
|
-
def
|
28
|
-
|
12
|
+
def method_missing(method, *args)
|
13
|
+
nil unless @_config[1][method.to_s]
|
14
|
+
@_config[1][method.to_s]
|
29
15
|
end
|
30
16
|
|
31
|
-
def
|
32
|
-
|
33
|
-
|
17
|
+
def validate(host)
|
18
|
+
%w(
|
19
|
+
tenant
|
20
|
+
image
|
21
|
+
flavor
|
22
|
+
networks
|
23
|
+
).each do |k|
|
24
|
+
raise "host key #{k} is require" unless host[1][k]
|
34
25
|
end
|
35
26
|
end
|
36
27
|
end
|
data/lib/pec/director.rb
CHANGED
@@ -1,57 +1,116 @@
|
|
1
1
|
module Pec
|
2
|
-
class Director
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
err_message(e)
|
2
|
+
class Director
|
3
|
+
def self.make(host_name)
|
4
|
+
Pec.load_config
|
5
|
+
Pec.configure.each do |host|
|
6
|
+
next if host_name && host.name != host_name
|
7
|
+
Pec::Logger.info "make start #{host.name}"
|
8
|
+
|
9
|
+
Pec.compute.set_tenant(host.tenant)
|
10
|
+
Pec.neutron.set_tenant_patch(host.tenant)
|
11
|
+
|
12
|
+
port_builder = Pec::Builder::Port.new
|
13
|
+
server_builder = Pec::Builder::Server.new
|
14
|
+
user_data_builder = Pec::Builder::UserData.new
|
15
|
+
|
16
|
+
attribute = {}
|
17
|
+
attribute.merge!(server_builder.build(host))
|
18
|
+
attribute.merge!(port_builder.build(host))
|
19
|
+
|
20
|
+
if user_data = user_data_builder.build(host, port_builder.user_data)
|
21
|
+
attribute.merge!(user_data)
|
22
|
+
end
|
23
|
+
|
24
|
+
Pec::Logger.info "create success! #{host.name}" if Pec.compute.servers.create(attribute)
|
26
25
|
end
|
27
26
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
27
|
+
rescue Excon::Errors::Error => e
|
28
|
+
excon_err_message(e)
|
29
|
+
rescue => e
|
30
|
+
Pec::Logger.critical(e)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.destroy(host_name, options)
|
34
|
+
Pec.load_config
|
35
|
+
Pec.configure.each do |host|
|
36
|
+
next if host_name && host.name != host_name
|
37
|
+
Pec.compute.set_tenant(host.tenant)
|
38
|
+
|
39
|
+
server = Pec.compute.servers.find {|s|s.name == host.name}
|
40
|
+
unless server
|
41
|
+
Pec::Logger.notice "not be created #{host.name}"
|
42
|
+
next
|
43
|
+
end
|
44
|
+
|
45
|
+
if options[:force] || Thor.new.yes?("#{host.name}: Are you sure you want to destroy the '#{host.name}' VM? [y/N]")
|
46
|
+
Pec::Logger.info "#{host.name} is deleted!" if Pec.compute.servers.destroy(server.id)
|
38
47
|
end
|
39
48
|
end
|
49
|
+
rescue Excon::Errors::Error => e
|
50
|
+
excon_err_message(e)
|
51
|
+
rescue => e
|
52
|
+
Pec::Logger.critical(e)
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.status(host_name)
|
56
|
+
Pec.load_config
|
57
|
+
Pec.configure.each do |host|
|
58
|
+
next if host_name && host.name != host_name
|
59
|
+
server = Pec.compute.servers.find {|s|s.name == host.name}
|
60
|
+
if server
|
61
|
+
puts sprintf(" %-35s %-10s %-10s %-10s %-10s %-35s %-48s",
|
62
|
+
host.name,
|
63
|
+
server.state,
|
64
|
+
Pec.identity.tenants.find_by_id(server.tenant_id),
|
65
|
+
Pec.compute.flavors.get(server.flavor['id']).name,
|
66
|
+
server.availability_zone,
|
67
|
+
server.os_ext_srv_attr_host,
|
68
|
+
server.addresses.map do |net, ethers|
|
69
|
+
ethers.map do |ether|
|
70
|
+
ether["addr"]
|
71
|
+
end
|
72
|
+
end.flatten.join(",")
|
73
|
+
)
|
40
74
|
|
41
|
-
|
42
|
-
|
75
|
+
else
|
76
|
+
puts sprintf(" %-35s %-10s",
|
77
|
+
host.name,
|
78
|
+
"uncreated"
|
79
|
+
)
|
80
|
+
end
|
43
81
|
end
|
44
82
|
|
45
|
-
|
46
|
-
|
47
|
-
|
83
|
+
rescue Excon::Errors::Error => e
|
84
|
+
excon_err_message(e)
|
85
|
+
rescue => e
|
86
|
+
Pec::Logger.critical(e)
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.excon_err_message(e)
|
90
|
+
if e.response
|
91
|
+
JSON.parse(e.response[:body]).each { |e,m| Pec::Logger.critical("#{e}:#{m["message"]}") }
|
92
|
+
else
|
93
|
+
Pec::Logger.critical(e)
|
48
94
|
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
49
98
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
99
|
+
module Fog
|
100
|
+
module Network
|
101
|
+
class OpenStack
|
102
|
+
class Real
|
103
|
+
def set_tenant_patch(tenant)
|
104
|
+
@openstack_must_reauthenticate = true
|
105
|
+
@openstack_tenant = tenant.to_s
|
106
|
+
authenticate
|
107
|
+
@path.sub!(/\/$/, '')
|
108
|
+
unless @path.match(SUPPORTED_VERSIONS)
|
109
|
+
@path = "/" + Fog::OpenStack.get_supported_version(SUPPORTED_VERSIONS,
|
110
|
+
@openstack_management_uri,
|
111
|
+
@auth_token,
|
112
|
+
@connection_options)
|
113
|
+
end
|
55
114
|
end
|
56
115
|
end
|
57
116
|
end
|