Browse Source

Puppet providers added

Change-Id: I67ad59731df43423dd210150c2b68dfec9cff8b4
Nikita Koshikov 4 years ago
parent
commit
ea6188c9c0
33 changed files with 2013 additions and 0 deletions
  1. 22
    0
      deployment_scripts/puppet/modules/heat/lib/puppet/provider/heat_api_cfn_config/ini_setting.rb
  2. 23
    0
      deployment_scripts/puppet/modules/heat/lib/puppet/provider/heat_api_cfn_paste_ini/ini_setting.rb
  3. 22
    0
      deployment_scripts/puppet/modules/heat/lib/puppet/provider/heat_api_cloudwatch_config/ini_setting.rb
  4. 23
    0
      deployment_scripts/puppet/modules/heat/lib/puppet/provider/heat_api_cloudwatch_paste_ini/ini_setting.rb
  5. 23
    0
      deployment_scripts/puppet/modules/heat/lib/puppet/provider/heat_api_config/ini_setting.rb
  6. 23
    0
      deployment_scripts/puppet/modules/heat/lib/puppet/provider/heat_api_paste_ini/ini_setting.rb
  7. 22
    0
      deployment_scripts/puppet/modules/heat/lib/puppet/provider/heat_config/ini_setting.rb
  8. 22
    0
      deployment_scripts/puppet/modules/heat/lib/puppet/provider/heat_engine_config/ini_setting.rb
  9. 19
    0
      deployment_scripts/puppet/modules/heat/lib/puppet/type/heat_api_cfn_config.rb
  10. 19
    0
      deployment_scripts/puppet/modules/heat/lib/puppet/type/heat_api_cfn_paste_ini.rb
  11. 19
    0
      deployment_scripts/puppet/modules/heat/lib/puppet/type/heat_api_cloudwatch_config.rb
  12. 19
    0
      deployment_scripts/puppet/modules/heat/lib/puppet/type/heat_api_cloudwatch_paste_ini.rb
  13. 19
    0
      deployment_scripts/puppet/modules/heat/lib/puppet/type/heat_api_config.rb
  14. 19
    0
      deployment_scripts/puppet/modules/heat/lib/puppet/type/heat_api_paste_ini.rb
  15. 19
    0
      deployment_scripts/puppet/modules/heat/lib/puppet/type/heat_config.rb
  16. 20
    0
      deployment_scripts/puppet/modules/heat/lib/puppet/type/heat_engine_config.rb
  17. 272
    0
      deployment_scripts/puppet/modules/neutron/lib/puppet/provider/neutron.rb
  18. 22
    0
      deployment_scripts/puppet/modules/neutron/lib/puppet/provider/neutron_config/ini_setting.rb
  19. 140
    0
      deployment_scripts/puppet/modules/neutron/lib/puppet/provider/neutron_network/neutron.rb
  20. 22
    0
      deployment_scripts/puppet/modules/neutron/lib/puppet/provider/neutron_plugin_ml2/ini_setting.rb
  21. 22
    0
      deployment_scripts/puppet/modules/neutron/lib/puppet/provider/neutron_plugin_ml2_cisco/ini_setting.rb
  22. 192
    0
      deployment_scripts/puppet/modules/neutron/lib/puppet/provider/neutron_port/neutron.rb
  23. 139
    0
      deployment_scripts/puppet/modules/neutron/lib/puppet/provider/neutron_router/neutron.rb
  24. 93
    0
      deployment_scripts/puppet/modules/neutron/lib/puppet/provider/neutron_router_interface/neutron.rb
  25. 220
    0
      deployment_scripts/puppet/modules/neutron/lib/puppet/provider/neutron_subnet/neutron.rb
  26. 47
    0
      deployment_scripts/puppet/modules/neutron/lib/puppet/type/neutron_config.rb
  27. 90
    0
      deployment_scripts/puppet/modules/neutron/lib/puppet/type/neutron_network.rb
  28. 20
    0
      deployment_scripts/puppet/modules/neutron/lib/puppet/type/neutron_plugin_ml2.rb
  29. 47
    0
      deployment_scripts/puppet/modules/neutron/lib/puppet/type/neutron_plugin_ml2_cisco.rb
  30. 98
    0
      deployment_scripts/puppet/modules/neutron/lib/puppet/type/neutron_port.rb
  31. 91
    0
      deployment_scripts/puppet/modules/neutron/lib/puppet/type/neutron_router.rb
  32. 51
    0
      deployment_scripts/puppet/modules/neutron/lib/puppet/type/neutron_router_interface.rb
  33. 114
    0
      deployment_scripts/puppet/modules/neutron/lib/puppet/type/neutron_subnet.rb

+ 22
- 0
deployment_scripts/puppet/modules/heat/lib/puppet/provider/heat_api_cfn_config/ini_setting.rb View File

@@ -0,0 +1,22 @@
1
+Puppet::Type.type(:heat_api_cfn_config).provide(
2
+  :ini_setting,
3
+  :parent => Puppet::Type.type(:ini_setting).provider(:ruby)
4
+) do
5
+
6
+  def section
7
+    resource[:name].split('/', 2).first
8
+  end
9
+
10
+  def setting
11
+    resource[:name].split('/', 2).last
12
+  end
13
+
14
+  def separator
15
+    '='
16
+  end
17
+
18
+  def file_path
19
+    '/etc/heat/heat-api-cfn.conf'
20
+  end
21
+
22
+end

+ 23
- 0
deployment_scripts/puppet/modules/heat/lib/puppet/provider/heat_api_cfn_paste_ini/ini_setting.rb View File

@@ -0,0 +1,23 @@
1
+Puppet::Type.type(:heat_api_cfn_paste_ini).provide(
2
+  :ini_setting,
3
+  :parent => Puppet::Type.type(:ini_setting).provider(:ruby)
4
+) do
5
+
6
+  def section
7
+    resource[:name].split('/', 2).first
8
+
9
+  end
10
+
11
+  def setting
12
+    resource[:name].split('/', 2).last
13
+  end
14
+
15
+  def separator
16
+    '='
17
+  end
18
+
19
+  def file_path
20
+    '/etc/heat/heat-api-cfn-paste.ini'
21
+  end
22
+
23
+end

+ 22
- 0
deployment_scripts/puppet/modules/heat/lib/puppet/provider/heat_api_cloudwatch_config/ini_setting.rb View File

@@ -0,0 +1,22 @@
1
+Puppet::Type.type(:heat_api_cloudwatch_config).provide(
2
+  :ini_setting,
3
+  :parent => Puppet::Type.type(:ini_setting).provider(:ruby)
4
+) do
5
+
6
+  def section
7
+    resource[:name].split('/', 2).first
8
+  end
9
+
10
+  def setting
11
+    resource[:name].split('/', 2).last
12
+  end
13
+
14
+  def separator
15
+    '='
16
+  end
17
+
18
+  def file_path
19
+    '/etc/heat/heat-api-cloudwatch.conf'
20
+  end
21
+
22
+end

+ 23
- 0
deployment_scripts/puppet/modules/heat/lib/puppet/provider/heat_api_cloudwatch_paste_ini/ini_setting.rb View File

@@ -0,0 +1,23 @@
1
+Puppet::Type.type(:heat_api_cloudwatch_paste_ini).provide(
2
+  :ini_setting,
3
+  :parent => Puppet::Type.type(:ini_setting).provider(:ruby)
4
+) do
5
+
6
+  def section
7
+    resource[:name].split('/', 2).first
8
+
9
+  end
10
+
11
+  def setting
12
+    resource[:name].split('/', 2).last
13
+  end
14
+
15
+  def separator
16
+    '='
17
+  end
18
+
19
+  def file_path
20
+    '/etc/heat/heat-api-cloudwatch-paste.ini'
21
+  end
22
+
23
+end

+ 23
- 0
deployment_scripts/puppet/modules/heat/lib/puppet/provider/heat_api_config/ini_setting.rb View File

@@ -0,0 +1,23 @@
1
+Puppet::Type.type(:heat_api_config).provide(
2
+  :ini_setting,
3
+  :parent => Puppet::Type.type(:ini_setting).provider(:ruby)
4
+) do
5
+
6
+  def section
7
+    resource[:name].split('/', 2).first
8
+
9
+  end
10
+
11
+  def setting
12
+    resource[:name].split('/', 2).last
13
+  end
14
+
15
+  def separator
16
+    '='
17
+  end
18
+
19
+  def file_path
20
+    '/etc/heat/heat-api.conf'
21
+  end
22
+
23
+end

+ 23
- 0
deployment_scripts/puppet/modules/heat/lib/puppet/provider/heat_api_paste_ini/ini_setting.rb View File

@@ -0,0 +1,23 @@
1
+Puppet::Type.type(:heat_api_paste_ini).provide(
2
+  :ini_setting,
3
+  :parent => Puppet::Type.type(:ini_setting).provider(:ruby)
4
+) do
5
+
6
+  def section
7
+    resource[:name].split('/', 2).first
8
+
9
+  end
10
+
11
+  def setting
12
+    resource[:name].split('/', 2).last
13
+  end
14
+
15
+  def separator
16
+    '='
17
+  end
18
+
19
+  def file_path
20
+    '/etc/heat/heat-api-paste.ini'
21
+  end
22
+
23
+end

+ 22
- 0
deployment_scripts/puppet/modules/heat/lib/puppet/provider/heat_config/ini_setting.rb View File

@@ -0,0 +1,22 @@
1
+Puppet::Type.type(:heat_config).provide(
2
+  :ini_setting,
3
+  :parent => Puppet::Type.type(:ini_setting).provider(:ruby)
4
+) do
5
+
6
+  def section
7
+    resource[:name].split('/', 2).first
8
+  end
9
+
10
+  def setting
11
+    resource[:name].split('/', 2).last
12
+  end
13
+
14
+  def separator
15
+    '='
16
+  end
17
+
18
+  def file_path
19
+    '/etc/heat/heat.conf'
20
+  end
21
+
22
+end

+ 22
- 0
deployment_scripts/puppet/modules/heat/lib/puppet/provider/heat_engine_config/ini_setting.rb View File

@@ -0,0 +1,22 @@
1
+Puppet::Type.type(:heat_engine_config).provide(
2
+  :ini_setting,
3
+  :parent => Puppet::Type.type(:ini_setting).provider(:ruby)
4
+) do
5
+
6
+  def section
7
+    resource[:name].split('/', 2).first
8
+  end
9
+
10
+  def setting
11
+    resource[:name].split('/', 2).last
12
+  end
13
+
14
+  def separator
15
+    '='
16
+  end
17
+
18
+  def file_path
19
+    '/etc/heat/heat-engine.conf'
20
+  end
21
+
22
+end

+ 19
- 0
deployment_scripts/puppet/modules/heat/lib/puppet/type/heat_api_cfn_config.rb View File

@@ -0,0 +1,19 @@
1
+Puppet::Type.newtype(:heat_api_cfn_config) do
2
+
3
+  ensurable
4
+
5
+  newparam(:name, :namevar => true) do
6
+    desc 'Section/setting name to manage from heat_api_cfn.conf'
7
+    newvalues(/\S+\/\S+/)
8
+  end
9
+
10
+  newproperty(:value) do
11
+    desc 'The value of the setting to be defined.'
12
+    munge do |value|
13
+      value = value.to_s.strip
14
+      value.capitalize! if value =~ /^(true|false)$/i
15
+      value
16
+    end
17
+  end
18
+
19
+end

+ 19
- 0
deployment_scripts/puppet/modules/heat/lib/puppet/type/heat_api_cfn_paste_ini.rb View File

@@ -0,0 +1,19 @@
1
+Puppet::Type.newtype(:heat_api_cfn_paste_ini) do
2
+
3
+  ensurable
4
+
5
+  newparam(:name, :namevar => true) do
6
+    desc 'Section/setting name to manage from heat-api.conf'
7
+    newvalues(/\S+\/\S+/)
8
+  end
9
+
10
+  newproperty(:value) do
11
+    desc 'The value of the setting to be defined.'
12
+    munge do |value|
13
+      value = value.to_s.strip
14
+      value.capitalize! if value =~ /^(true|false)$/i
15
+      value
16
+    end
17
+  end
18
+
19
+end

+ 19
- 0
deployment_scripts/puppet/modules/heat/lib/puppet/type/heat_api_cloudwatch_config.rb View File

@@ -0,0 +1,19 @@
1
+Puppet::Type.newtype(:heat_api_cloudwatch_config) do
2
+
3
+  ensurable
4
+
5
+  newparam(:name, :namevar => true) do
6
+    desc 'Section/setting name to manage from heat-api-cloudwatch.conf'
7
+    newvalues(/\S+\/\S+/)
8
+  end
9
+
10
+  newproperty(:value) do
11
+    desc 'The value of the setting to be defined.'
12
+    munge do |value|
13
+      value = value.to_s.strip
14
+      value.capitalize! if value =~ /^(true|false)$/i
15
+      value
16
+    end
17
+  end
18
+
19
+end

+ 19
- 0
deployment_scripts/puppet/modules/heat/lib/puppet/type/heat_api_cloudwatch_paste_ini.rb View File

@@ -0,0 +1,19 @@
1
+Puppet::Type.newtype(:heat_api_cloudwatch_paste_ini) do
2
+
3
+  ensurable
4
+
5
+  newparam(:name, :namevar => true) do
6
+    desc 'Section/setting name to manage from heat-api.conf'
7
+    newvalues(/\S+\/\S+/)
8
+  end
9
+
10
+  newproperty(:value) do
11
+    desc 'The value of the setting to be defined.'
12
+    munge do |value|
13
+      value = value.to_s.strip
14
+      value.capitalize! if value =~ /^(true|false)$/i
15
+      value
16
+    end
17
+  end
18
+
19
+end

+ 19
- 0
deployment_scripts/puppet/modules/heat/lib/puppet/type/heat_api_config.rb View File

@@ -0,0 +1,19 @@
1
+Puppet::Type.newtype(:heat_api_config) do
2
+
3
+  ensurable
4
+
5
+  newparam(:name, :namevar => true) do
6
+    desc 'Section/setting name to manage from heat-api.conf'
7
+    newvalues(/\S+\/\S+/)
8
+  end
9
+
10
+  newproperty(:value) do
11
+    desc 'The value of the setting to be defined.'
12
+    munge do |value|
13
+      value = value.to_s.strip
14
+      value.capitalize! if value =~ /^(true|false)$/i
15
+      value
16
+    end
17
+  end
18
+
19
+end

+ 19
- 0
deployment_scripts/puppet/modules/heat/lib/puppet/type/heat_api_paste_ini.rb View File

@@ -0,0 +1,19 @@
1
+Puppet::Type.newtype(:heat_api_paste_ini) do
2
+
3
+  ensurable
4
+
5
+  newparam(:name, :namevar => true) do
6
+    desc 'Section/setting name to manage from heat-api.conf'
7
+    newvalues(/\S+\/\S+/)
8
+  end
9
+
10
+  newproperty(:value) do
11
+    desc 'The value of the setting to be defined.'
12
+    munge do |value|
13
+      value = value.to_s.strip
14
+      value.capitalize! if value =~ /^(true|false)$/i
15
+      value
16
+    end
17
+  end
18
+
19
+end

+ 19
- 0
deployment_scripts/puppet/modules/heat/lib/puppet/type/heat_config.rb View File

@@ -0,0 +1,19 @@
1
+Puppet::Type.newtype(:heat_config) do
2
+
3
+  ensurable
4
+
5
+  newparam(:name, :namevar => true) do
6
+    desc 'Section/setting name to manage from heat.conf'
7
+    newvalues(/\S+\/\S+/)
8
+  end
9
+
10
+  newproperty(:value) do
11
+    desc 'The value of the setting to be defined.'
12
+    munge do |value|
13
+      value = value.to_s.strip
14
+      value.capitalize! if value =~ /^(true|false)$/i
15
+      value
16
+    end
17
+  end
18
+
19
+end

+ 20
- 0
deployment_scripts/puppet/modules/heat/lib/puppet/type/heat_engine_config.rb View File

@@ -0,0 +1,20 @@
1
+Puppet::Type.newtype(:heat_engine_config) do
2
+
3
+  ensurable
4
+
5
+  newparam(:name, :namevar => true) do
6
+    desc 'Section/setting name to manage from heat-engine.conf'
7
+    newvalues(/\S+\/\S+/)
8
+  end
9
+
10
+  newproperty(:value) do
11
+    desc 'The value of the setting to be defined.'
12
+    munge do |value|
13
+      puts value
14
+      value = value.to_s.strip
15
+      value.capitalize! if value =~ /^(true|false)$/i
16
+      value
17
+    end
18
+  end
19
+
20
+end

+ 272
- 0
deployment_scripts/puppet/modules/neutron/lib/puppet/provider/neutron.rb View File

@@ -0,0 +1,272 @@
1
+require 'csv'
2
+require 'puppet/util/inifile'
3
+
4
+class Puppet::Provider::Neutron < Puppet::Provider
5
+
6
+  #NOTE(xenolog): self.prefetch was removed with comment:
7
+  # FIXME:(xarses) needs to be abstraced from subresources and re-written here
8
+
9
+  def self.conf_filename
10
+    '/etc/neutron/neutron.conf'
11
+  end
12
+
13
+  def self.withenv(hash, &block)
14
+    saved = ENV.to_hash
15
+    hash.each do |name, val|
16
+      ENV[name.to_s] = val
17
+    end
18
+
19
+    yield
20
+  ensure
21
+    ENV.clear
22
+    saved.each do |name, val|
23
+      ENV[name] = val
24
+    end
25
+  end
26
+
27
+  def self.neutron_credentials
28
+    @neutron_credentials ||= get_neutron_credentials
29
+  end
30
+
31
+  def self.get_neutron_credentials
32
+    auth_keys = ['auth_host', 'auth_port', 'auth_protocol',
33
+                 'admin_tenant_name', 'admin_user', 'admin_password']
34
+    conf = neutron_conf
35
+    if conf and conf['keystone_authtoken'] and
36
+        auth_keys.all?{|k| !conf['keystone_authtoken'][k].nil?}
37
+      creds = Hash[ auth_keys.map \
38
+                   { |k| [k, conf['keystone_authtoken'][k].strip] } ]
39
+      if conf['DEFAULT'] and !conf['DEFAULT']['nova_region_name'].nil?
40
+        creds['nova_region_name'] = conf['DEFAULT']['nova_region_name']
41
+      end
42
+      return creds
43
+    else
44
+      raise(Puppet::Error, "File: #{conf_filename} does not contain all \
45
+required sections.  Neutron types will not work if neutron is not \
46
+correctly configured.")
47
+    end
48
+  end
49
+
50
+  def neutron_credentials
51
+    self.class.neutron_credentials
52
+  end
53
+
54
+  def self.auth_endpoint
55
+    @auth_endpoint ||= get_auth_endpoint
56
+  end
57
+
58
+  def self.get_auth_endpoint
59
+    q = neutron_credentials
60
+    "#{q['auth_protocol']}://#{q['auth_host']}:#{q['auth_port']}/v2.0/"
61
+  end
62
+
63
+  def self.neutron_conf
64
+    return @neutron_conf if @neutron_conf
65
+    @neutron_conf = Puppet::Util::IniConfig::File.new
66
+    @neutron_conf.read(conf_filename)
67
+    @neutron_conf
68
+  end
69
+
70
+  def self.auth_neutron(*args)
71
+    q = neutron_credentials
72
+    authenv = {
73
+      :OS_AUTH_URL    => self.auth_endpoint,
74
+      :OS_USERNAME    => q['admin_user'],
75
+      :OS_TENANT_NAME => q['admin_tenant_name'],
76
+      :OS_PASSWORD    => q['admin_password']
77
+    }
78
+    if q.key?('nova_region_name')
79
+      authenv[:OS_REGION_NAME] = q['nova_region_name']
80
+    end
81
+    # NOTE(bogdando) contribute change to upstream #1384097:
82
+    #   enhanced message checks within a given time frame
83
+    rv = nil
84
+    timeout = 120
85
+    end_time = Time.now.to_i + timeout
86
+    loop do
87
+      begin
88
+        withenv authenv do
89
+          rv = neutron(args)
90
+        end
91
+        break
92
+      rescue Puppet::ExecutionFailure => e
93
+        if ! e.message =~ /(\(HTTP\s+400\))|
94
+              (400-\{\'message\'\:\s+\'\'\})|
95
+              (\[Errno 111\]\s+Connection\s+refused)|
96
+              (503\s+Service\s+Unavailable)|
97
+              (504\s+Gateway\s+Time-out)|
98
+              (\:\s+Maximum\s+attempts\s+reached)|
99
+              (Unauthorized\:\s+bad\s+credentials)|
100
+              (Max\s+retries\s+exceeded)/
101
+          raise(e)
102
+        end
103
+        current_time = Time.now.to_i
104
+        if current_time > end_time
105
+          break
106
+        else
107
+          wait = end_time - current_time
108
+          Puppet::debug("Non-fatal error: \"#{e.message}\"")
109
+          notice("Neutron API not avalaible. Wait up to #{wait} sec.")
110
+        end
111
+        sleep(2)
112
+        # Note(xarses): Don't remove, we know that there is one of the
113
+        # Recoverable erros above, So we will retry a few more times
114
+      end
115
+    end
116
+    return rv
117
+  end
118
+
119
+  def auth_neutron(*args)
120
+    self.class.auth_neutron(args)
121
+  end
122
+
123
+  def self.reset
124
+    @neutron_conf        = nil
125
+    @neutron_credentials = nil
126
+  end
127
+
128
+  def self.list_neutron_resources(type)
129
+    ids = []
130
+    list = auth_neutron("#{type}-list", '--format=csv',
131
+                        '--column=id', '--quote=none')
132
+    # NOTE(bogdando) contribute change to upstream #1384101:
133
+    #   raise Puppet exception, if resources list is empty
134
+    if list.nil?
135
+      raise(Puppet::ExecutionFailure, "Can't prefetch #{type}-list Neutron or Keystone API is not avalaible.")
136
+    end
137
+
138
+    (list.split("\n")[1..-1] || []).compact.collect do |line|
139
+      ids << line.strip
140
+    end
141
+    return ids
142
+  end
143
+
144
+  def self.get_neutron_resource_attrs(type, id)
145
+    attrs = {}
146
+    net = auth_neutron("#{type}-show", '--format=shell', id)
147
+    # NOTE(bogdando) contribute change to upstream #1384101:
148
+    #   raise Puppet exception, if list of resources' attributes is empty
149
+    if net.nil?
150
+      raise(Puppet::ExecutionFailure, "Can't prefetch #{type}-show Neutron or Keystone API is not avalaible.")
151
+    end
152
+    last_key = nil
153
+    (net.split("\n") || []).compact.collect do |line|
154
+      if line.include? '='
155
+        k, v = line.split('=', 2)
156
+        attrs[k] = v.gsub(/\A"|"\Z/, '')
157
+        last_key = k
158
+      else
159
+        # Handle the case of a list of values
160
+        v = line.gsub(/\A"|"\Z/, '')
161
+        attrs[last_key] = [attrs[last_key], v].flatten
162
+      end
163
+    end
164
+    return attrs
165
+  end
166
+
167
+  def self.list_router_ports(router_name_or_id)
168
+    results = []
169
+    cmd_output = auth_neutron("router-port-list",
170
+                              '--format=csv',
171
+                              router_name_or_id)
172
+    if ! cmd_output
173
+      return results
174
+    end
175
+
176
+    headers = nil
177
+    CSV.parse(cmd_output) do |row|
178
+      if headers == nil
179
+        headers = row
180
+      else
181
+        result = Hash[*headers.zip(row).flatten]
182
+        match_data = /.*"subnet_id": "(.*)", .*/.match(result['fixed_ips'])
183
+        if match_data
184
+          result['subnet_id'] = match_data[1]
185
+        end
186
+        results << result
187
+      end
188
+    end
189
+    return results
190
+  end
191
+
192
+  def self.auth_keystone(*args)
193
+    q = neutron_credentials
194
+    authenv = {
195
+      :OS_AUTH_URL    => self.auth_endpoint,
196
+      :OS_USERNAME    => q['admin_user'],
197
+      :OS_TENANT_NAME => q['admin_tenant_name'],
198
+      :OS_PASSWORD    => q['admin_password']
199
+    }
200
+    if q.key?('nova_region_name')
201
+      authenv[:OS_REGION_NAME] = q['nova_region_name']
202
+    end
203
+
204
+    rv = nil
205
+    timeout = 120
206
+    end_time = Time.now.to_i + timeout
207
+    loop do
208
+      begin
209
+        withenv authenv do
210
+          rv = keystone(args)
211
+        end
212
+        break
213
+      rescue Puppet::ExecutionFailure => e
214
+        if ! e.message =~ /(\(HTTP\s+400\))|
215
+              (400-\{\'message\'\:\s+\'\'\})|
216
+              (\[Errno 111\]\s+Connection\s+refused)|
217
+              (503\s+Service\s+Unavailable)|
218
+              (504\s+Gateway\s+Time-out)|
219
+              (\:\s+Maximum\s+attempts\s+reached)|
220
+              (Unauthorized\:\s+bad\s+credentials)|
221
+              (Max\s+retries\s+exceeded)/
222
+          raise(e)
223
+        end
224
+        current_time = Time.now.to_i
225
+        if current_time > end_time
226
+          #raise(e)
227
+          break
228
+        else
229
+          wait = end_time - current_time
230
+          Puppet::debug("Non-fatal error: \"#{e.message}\"")
231
+          notice("Keystone API not avalaible. Wait up to #{wait} sec.")
232
+        end
233
+        sleep(2)
234
+        # Note(xarses): Don't remove, we know that there is one of the
235
+        # Recoverable erros above, So we will retry a few more times
236
+      end
237
+    end
238
+    return rv
239
+  end
240
+
241
+  def auth_keystone(*args)
242
+    self.class.auth_neutron(args)
243
+  end
244
+
245
+  def self.get_tenant_id(catalog, name)
246
+    rv = nil
247
+    auth_keystone('tenant-list').each do |line|
248
+      fields=line.split(/\s*\|\s*/)
249
+      if fields[1] and fields[1].size == 32
250
+        if fields[2] == name
251
+          rv = fields[1]
252
+          break
253
+        end
254
+      end
255
+    end
256
+    if rv.nil?
257
+      fail("Unable to get tenant-ID for tenant '#{name}'")
258
+    end
259
+    return rv
260
+  end
261
+
262
+  def self.parse_creation_output(data)
263
+    hash = {}
264
+    data.split("\n").compact.each do |line|
265
+      if line.include? '='
266
+        hash[line.split('=').first] = line.split('=', 2)[1].gsub(/\A"|"\Z/, '')
267
+      end
268
+    end
269
+    hash
270
+  end
271
+
272
+end

+ 22
- 0
deployment_scripts/puppet/modules/neutron/lib/puppet/provider/neutron_config/ini_setting.rb View File

@@ -0,0 +1,22 @@
1
+Puppet::Type.type(:neutron_config).provide(
2
+  :ini_setting,
3
+  :parent => Puppet::Type.type(:ini_setting).provider(:ruby)
4
+) do
5
+
6
+  def section
7
+    resource[:name].split('/', 2).first
8
+  end
9
+
10
+  def setting
11
+    resource[:name].split('/', 2).last
12
+  end
13
+
14
+  def separator
15
+    '='
16
+  end
17
+
18
+  def file_path
19
+    '/etc/neutron/neutron.conf'
20
+  end
21
+
22
+end

+ 140
- 0
deployment_scripts/puppet/modules/neutron/lib/puppet/provider/neutron_network/neutron.rb View File

@@ -0,0 +1,140 @@
1
+require File.join(File.dirname(__FILE__), '..','..','..',
2
+                  'puppet/provider/neutron')
3
+
4
+Puppet::Type.type(:neutron_network).provide(
5
+  :neutron,
6
+  :parent => Puppet::Provider::Neutron
7
+) do
8
+  desc <<-EOT
9
+    Neutron provider to manage neutron_network type.
10
+
11
+    Assumes that the neutron service is configured on the same host.
12
+  EOT
13
+
14
+  commands :neutron => 'neutron'
15
+  commands :keystone => 'keystone'
16
+
17
+  mk_resource_methods
18
+
19
+  def self.neutron_type
20
+    'net'
21
+  end
22
+
23
+  def self.instances
24
+    list_neutron_resources(neutron_type).collect do |id|
25
+      attrs = get_neutron_resource_attrs(neutron_type, id)
26
+      new(
27
+        :ensure                    => :present,
28
+        :name                      => attrs['name'],
29
+        :id                        => attrs['id'],
30
+        :admin_state_up            => attrs['admin_state_up'],
31
+        :provider_network_type     => attrs['provider:network_type'],
32
+        :provider_physical_network => attrs['provider:physical_network'],
33
+        :provider_segmentation_id  => attrs['provider:segmentation_id'],
34
+        :router_external           => attrs['router:external'],
35
+        :shared                    => attrs['shared'],
36
+        :tenant_id                 => attrs['tenant_id']
37
+      )
38
+    end
39
+  end
40
+
41
+  def self.prefetch(resources)
42
+    networks = instances
43
+    resources.keys.each do |name|
44
+      if provider = networks.find{ |net| net.name == name }
45
+        resources[name].provider = provider
46
+      end
47
+    end
48
+  end
49
+
50
+  def exists?
51
+    @property_hash[:ensure] == :present
52
+  end
53
+
54
+  def create
55
+    network_opts = Array.new
56
+
57
+    if @resource[:shared] =~ /true/i
58
+      network_opts << '--shared'
59
+    end
60
+
61
+    if @resource[:tenant_name]
62
+      tenant_id = self.class.get_tenant_id(model.catalog,
63
+                                           @resource[:tenant_name])
64
+      notice("***N*** neutron_network::create *** tenant_id='#{tenant_id.inspect}'")
65
+
66
+      network_opts << "--tenant_id=#{tenant_id}"
67
+    elsif @resource[:tenant_id]
68
+      network_opts << "--tenant_id=#{@resource[:tenant_id]}"
69
+    end
70
+
71
+    if @resource[:provider_network_type]
72
+      network_opts << \
73
+        "--provider:network_type=#{@resource[:provider_network_type]}"
74
+    end
75
+
76
+    if @resource[:provider_physical_network]
77
+      network_opts << \
78
+        "--provider:physical_network=#{@resource[:provider_physical_network]}"
79
+    end
80
+
81
+    if @resource[:provider_segmentation_id]
82
+      network_opts << \
83
+        "--provider:segmentation_id=#{@resource[:provider_segmentation_id]}"
84
+    end
85
+
86
+    if @resource[:router_external]
87
+      network_opts << "--router:external=#{@resource[:router_external]}"
88
+    end
89
+
90
+    results = auth_neutron('net-create', '--format=shell',
91
+                           network_opts, resource[:name])
92
+
93
+    if results =~ /Created a new network:/
94
+      attrs = self.class.parse_creation_output(results)
95
+      @property_hash = {
96
+        :ensure                    => :present,
97
+        :name                      => resource[:name],
98
+        :id                        => attrs['id'],
99
+        :admin_state_up            => attrs['admin_state_up'],
100
+        :provider_network_type     => attrs['provider:network_type'],
101
+        :provider_physical_network => attrs['provider:physical_network'],
102
+        :provider_segmentation_id  => attrs['provider:segmentation_id'],
103
+        :router_external           => attrs['router:external'],
104
+        :shared                    => attrs['shared'],
105
+        :tenant_id                 => attrs['tenant_id'],
106
+      }
107
+    else
108
+      fail("did not get expected message on network creation, got #{results}")
109
+    end
110
+  end
111
+
112
+  def destroy
113
+    auth_neutron('net-delete', name)
114
+    @property_hash[:ensure] = :absent
115
+  end
116
+
117
+  def admin_state_up=(value)
118
+    auth_neutron('net-update', "--admin_state_up=#{value}", name)
119
+  end
120
+
121
+  def shared=(value)
122
+    auth_neutron('net-update', "--shared=#{value}", name)
123
+  end
124
+
125
+  def router_external=(value)
126
+    auth_neutron('net-update', "--router:external=#{value}", name)
127
+  end
128
+
129
+  [
130
+   :provider_network_type,
131
+   :provider_physical_network,
132
+   :provider_segmentation_id,
133
+   :tenant_id,
134
+  ].each do |attr|
135
+     define_method(attr.to_s + "=") do |value|
136
+       fail("Property #{attr.to_s} does not support being updated")
137
+     end
138
+  end
139
+
140
+end

+ 22
- 0
deployment_scripts/puppet/modules/neutron/lib/puppet/provider/neutron_plugin_ml2/ini_setting.rb View File

@@ -0,0 +1,22 @@
1
+Puppet::Type.type(:neutron_plugin_ml2).provide(
2
+  :ini_setting,
3
+  :parent => Puppet::Type.type(:ini_setting).provider(:ruby)
4
+) do
5
+
6
+  def section
7
+    resource[:name].split('/', 2).first
8
+  end
9
+
10
+  def setting
11
+    resource[:name].split('/', 2).last
12
+  end
13
+
14
+  def separator
15
+    '='
16
+  end
17
+
18
+  def file_path
19
+    '/etc/neutron/plugins/ml2/ml2_conf.ini'
20
+  end
21
+
22
+end

+ 22
- 0
deployment_scripts/puppet/modules/neutron/lib/puppet/provider/neutron_plugin_ml2_cisco/ini_setting.rb View File

@@ -0,0 +1,22 @@
1
+Puppet::Type.type(:neutron_plugin_ml2_cisco).provide(
2
+  :ini_setting,
3
+  :parent => Puppet::Type.type(:ini_setting).provider(:ruby)
4
+) do
5
+
6
+  def section
7
+    resource[:name].split('/', 2).first
8
+  end
9
+
10
+  def setting
11
+    resource[:name].split('/', 2).last
12
+  end
13
+
14
+  def separator
15
+    '='
16
+  end
17
+
18
+  def file_path
19
+    '/etc/neutron/plugins/ml2/ml2_conf_cisco.ini'
20
+  end
21
+
22
+end

+ 192
- 0
deployment_scripts/puppet/modules/neutron/lib/puppet/provider/neutron_port/neutron.rb View File

@@ -0,0 +1,192 @@
1
+require File.join(File.dirname(__FILE__), "..","..","..",
2
+                  "puppet/provider/neutron")
3
+
4
+Puppet::Type.type(:neutron_port).provide(
5
+  :neutron,
6
+  :parent => Puppet::Provider::Neutron
7
+) do
8
+  desc <<-EOT
9
+    Neutron provider to manage neutron_port type.
10
+
11
+    Assumes that the neutron service is configured on the same host.
12
+  EOT
13
+  #TODO No security group support
14
+
15
+  commands :neutron => "neutron"
16
+  commands :keystone => 'keystone'
17
+
18
+  mk_resource_methods
19
+
20
+  def self.instances
21
+    list_neutron_resources("port").collect do |id|
22
+      attrs = get_neutron_resource_attrs("port", id)
23
+      attrs["name"] = attrs["id"] if attrs["name"].empty?
24
+      new(
25
+        :ensure         => :present,
26
+        :name           => attrs["name"],
27
+        :id             => attrs["id"],
28
+        :status         => attrs["status"],
29
+        :tenant_id      => attrs["tenant_id"],
30
+        :network_id     => attrs["network_id"],
31
+        :admin_state_up => attrs["admin_state_up"],
32
+        :network_name   => get_network_name(attrs["network_id"]),
33
+        :subnet_name    => get_subnet_name(parse_subnet_id(attrs["fixed_ips"])),
34
+        :subnet_id      => parse_subnet_id(attrs["fixed_ips"]),
35
+        :ip_address     => parse_ip_address(attrs["fixed_ips"])
36
+      )
37
+    end
38
+  end
39
+
40
+  def self.prefetch(resources)
41
+    instances_ = instances
42
+    resources.keys.each do |name|
43
+      if provider = instances_.find{ |instance| instance.name == name }
44
+        resources[name].provider = provider
45
+      end
46
+    end
47
+  end
48
+
49
+  def exists?
50
+    @property_hash[:ensure] == :present
51
+  end
52
+
53
+  def create
54
+    opts = Array.new
55
+
56
+    if @resource[:admin_state_up] == "False"
57
+      opts << "--admin-state-down"
58
+    end
59
+
60
+    if @resource[:ip_address]
61
+      # The spec says that multiple ip addresses may be specified, but this
62
+      # doesn't seem to work yet.
63
+      opts << "--fixed-ip"
64
+      opts << @resource[:ip_address].map{|ip|"ip_address=#{ip}"}.join(',')
65
+    end
66
+
67
+    if @resource[:subnet_name]
68
+      # The spec says that multiple subnets may be specified, but this doesn't
69
+      # seem to work yet.
70
+      opts << "--fixed-ip"
71
+      opts << @resource[:subnet_name].map{|s|"subnet_id=#{s}"}.join(',')
72
+    end
73
+
74
+    if @resource[:tenant_name]
75
+      tenant_id = self.class.get_tenant_id(
76
+        model.catalog,
77
+        @resource[:tenant_name]
78
+      )
79
+      opts << "--tenant_id=#{tenant_id}"
80
+    elsif @resource[:tenant_id]
81
+      opts << "--tenant_id=#{@resource[:tenant_id]}"
82
+    end
83
+
84
+    results = auth_neutron(
85
+      "port-create",
86
+      "--format=shell",
87
+      "--name=#{resource[:name]}",
88
+      opts,
89
+      resource[:network_name]
90
+    )
91
+
92
+    if results =~ /Created a new port:/
93
+      attrs = self.class.parse_creation_output(results)
94
+      @property_hash = {
95
+        :ensure         => :present,
96
+        :name           => resource[:name],
97
+        :id             => attrs["id"],
98
+        :status         => attrs["status"],
99
+        :tenant_id      => attrs["tenant_id"],
100
+        :network_id     => attrs["network_id"],
101
+        :admin_state_up => attrs["admin_state_up"],
102
+        :network_name   => resource[:network_name],
103
+        :subnet_name    => resource[:subnet_name],
104
+        :subnet_id      => self.class.parse_subnet_id(attrs["fixed_ips"]),
105
+        :ip_address     => self.class.parse_ip_address(attrs["fixed_ips"])
106
+      }
107
+    else
108
+      fail("did not get expected message on port creation, got #{results}")
109
+    end
110
+  end
111
+
112
+  def destroy
113
+    auth_neutron("port-delete", name)
114
+    @property_hash[:ensure] = :absent
115
+  end
116
+
117
+  def admin_state_up=(value)
118
+    auth_neutron("port-update", "--admin-state-up=#{value}", name)
119
+  end
120
+
121
+  private
122
+
123
+  def self.get_network_name(network_id_)
124
+    if network_id_
125
+      network_instances = Puppet::Type.type("neutron_network").instances
126
+      network_name = network_instances.find do |instance|
127
+        instance.provider.id == network_id_
128
+      end.provider.name
129
+    end
130
+    network_name
131
+  end
132
+
133
+  def get_network_name(network_id_)
134
+    @get_network_name ||= self.class.get_network_name(network_id_)
135
+  end
136
+
137
+  def self.get_subnet_name(subnet_id_)
138
+    if subnet_id_
139
+      subnet_ids = Array(subnet_id_)
140
+      subnet_instances = Puppet::Type.type("neutron_subnet").instances
141
+      subnet_names = subnet_instances.collect do |instance|
142
+        if subnet_ids.include?(instance.provider.id)
143
+          instance.provider.name
144
+        else
145
+          nil
146
+        end
147
+      end.compact
148
+      if subnet_names.length > 1
149
+        subnet_names
150
+      else
151
+        subnet_names.first
152
+      end
153
+    end
154
+  end
155
+
156
+  def get_subnet_name(subnet_id_)
157
+    @subnet_name ||= self.class.subnet_name(subnet_id_)
158
+  end
159
+
160
+  def self.parse_subnet_id(fixed_ips_)
161
+    subnet_ids = Array(fixed_ips_).collect do |json|
162
+      match_data = /\{"subnet_id": "(.*)", /.match(json)
163
+      if match_data
164
+        match_data[1]
165
+      else
166
+        nil
167
+      end
168
+    end.compact
169
+    if subnet_ids.length > 1
170
+      subnet_ids
171
+    else
172
+      subnet_ids.first
173
+    end
174
+  end
175
+
176
+  def self.parse_ip_address(fixed_ips_)
177
+    ip_addresses = Array(fixed_ips_).collect do |json|
178
+      match_data = /"ip_address": "(.*)"\}/.match(json)
179
+      if match_data
180
+        match_data[1]
181
+      else
182
+        nil
183
+      end
184
+    end.compact
185
+    if ip_addresses.length > 1
186
+      ip_addresses
187
+    else
188
+      ip_addresses.first
189
+    end
190
+  end
191
+
192
+end

+ 139
- 0
deployment_scripts/puppet/modules/neutron/lib/puppet/provider/neutron_router/neutron.rb View File

@@ -0,0 +1,139 @@
1
+require File.join(File.dirname(__FILE__), '..','..','..',
2
+                  'puppet/provider/neutron')
3
+
4
+Puppet::Type.type(:neutron_router).provide(
5
+  :neutron,
6
+  :parent => Puppet::Provider::Neutron
7
+) do
8
+  desc <<-EOT
9
+    Neutron provider to manage neutron_router type.
10
+
11
+    Assumes that the neutron service is configured on the same host.
12
+  EOT
13
+
14
+  commands :neutron => 'neutron'
15
+  commands :keystone => 'keystone'
16
+
17
+  mk_resource_methods
18
+
19
+  def self.instances
20
+    list_neutron_resources('router').collect do |id|
21
+      attrs = get_neutron_resource_attrs('router', id)
22
+      new(
23
+        :ensure                    => :present,
24
+        :name                      => attrs['name'],
25
+        :id                        => attrs['id'],
26
+        :admin_state_up            => attrs['admin_state_up'],
27
+        :external_gateway_info     => attrs['external_gateway_info'],
28
+        :status                    => attrs['status'],
29
+        :tenant_id                 => attrs['tenant_id']
30
+      )
31
+    end
32
+  end
33
+
34
+  def self.prefetch(resources)
35
+    instances_ = instances
36
+    resources.keys.each do |name|
37
+      if provider = instances_.find{ |instance| instance.name == name }
38
+        resources[name].provider = provider
39
+      end
40
+    end
41
+  end
42
+
43
+  def exists?
44
+    @property_hash[:ensure] == :present
45
+  end
46
+
47
+  def create
48
+    opts = Array.new
49
+
50
+    if @resource[:admin_state_up] == 'False'
51
+      opts << '--admin-state-down'
52
+    end
53
+
54
+    if @resource[:tenant_name]
55
+      tenant_id = self.class.get_tenant_id(model.catalog,
56
+                                           @resource[:tenant_name])
57
+      opts << "--tenant_id=#{tenant_id}"
58
+    elsif @resource[:tenant_id]
59
+      opts << "--tenant_id=#{@resource[:tenant_id]}"
60
+    end
61
+
62
+    results = auth_neutron("router-create", '--format=shell',
63
+                           opts, resource[:name])
64
+
65
+    if results =~ /Created a new router:/
66
+      attrs = self.class.parse_creation_output(results)
67
+      @property_hash = {
68
+        :ensure                    => :present,
69
+        :name                      => resource[:name],
70
+        :id                        => attrs['id'],
71
+        :admin_state_up            => attrs['admin_state_up'],
72
+        :external_gateway_info     => attrs['external_gateway_info'],
73
+        :status                    => attrs['status'],
74
+        :tenant_id                 => attrs['tenant_id'],
75
+      }
76
+
77
+      if @resource[:gateway_network_name]
78
+        results = auth_neutron('router-gateway-set',
79
+                               @resource[:name],
80
+                               @resource[:gateway_network_name])
81
+        if results =~ /Set gateway for router/
82
+          attrs = self.class.get_neutron_resource_attrs('router',
83
+                                                        @resource[:name])
84
+          @property_hash[:external_gateway_info] = \
85
+            attrs['external_gateway_info']
86
+        else
87
+          fail(<<-EOT
88
+did not get expected message on setting router gateway, got #{results}
89
+EOT
90
+               )
91
+        end
92
+      end
93
+    else
94
+      fail("did not get expected message on router creation, got #{results}")
95
+    end
96
+  end
97
+
98
+  def destroy
99
+    auth_neutron('router-delete', name)
100
+    @property_hash[:ensure] = :absent
101
+  end
102
+
103
+  def gateway_network_name
104
+    if @gateway_network_name == nil and gateway_network_id
105
+      Puppet::Type.type('neutron_network').instances.each do |instance|
106
+        if instance.provider.id == gateway_network_id
107
+          @gateway_network_name = instance.provider.name
108
+        end
109
+      end
110
+    end
111
+    @gateway_network_name
112
+  end
113
+
114
+  def gateway_network_name=(value)
115
+    if value == ''
116
+      auth_neutron('router-gateway-clear', name)
117
+    else
118
+      auth_neutron('router-gateway-set', name, value)
119
+    end
120
+  end
121
+
122
+  def parse_gateway_network_id(external_gateway_info_)
123
+    match_data = /\{"network_id": "(.*?)"/.match(external_gateway_info_)
124
+    if match_data
125
+      match_data[1]
126
+    else
127
+      ''
128
+    end
129
+  end
130
+
131
+  def gateway_network_id
132
+    @gateway_network_id ||= parse_gateway_network_id(external_gateway_info)
133
+  end
134
+
135
+  def admin_state_up=(value)
136
+    auth_neutron('router-update', "--admin-state-up=#{value}", name)
137
+  end
138
+
139
+end

+ 93
- 0
deployment_scripts/puppet/modules/neutron/lib/puppet/provider/neutron_router_interface/neutron.rb View File

@@ -0,0 +1,93 @@
1
+require File.join(File.dirname(__FILE__), '..','..','..',
2
+                  'puppet/provider/neutron')
3
+
4
+Puppet::Type.type(:neutron_router_interface).provide(
5
+  :neutron,
6
+  :parent => Puppet::Provider::Neutron
7
+) do
8
+  desc <<-EOT
9
+    Neutron provider to manage neutron_router_interface type.
10
+
11
+    Assumes that the neutron service is configured on the same host.
12
+
13
+    It is not possible to manage an interface for the subnet used by
14
+    the gateway network, and such an interface will appear in the list
15
+    of resources ('puppet resource [type]').  Attempting to manage the
16
+    gateway interfae will result in an error.
17
+
18
+  EOT
19
+
20
+  commands :neutron => 'neutron'
21
+
22
+  mk_resource_methods
23
+
24
+  def self.instances
25
+    subnet_name_hash = {}
26
+    Puppet::Type.type('neutron_subnet').instances.each do |instance|
27
+      subnet_name_hash[instance.provider.id] = instance.provider.name
28
+    end
29
+    instances_ = []
30
+    Puppet::Type.type('neutron_router').instances.each do |instance|
31
+      list_router_ports(instance.provider.id).each do |port_hash|
32
+        router_name = instance.provider.name
33
+        subnet_name = subnet_name_hash[port_hash['subnet_id']]
34
+        name = "#{router_name}:#{subnet_name}"
35
+        instances_ << new(
36
+            :ensure                    => :present,
37
+            :name                      => name,
38
+            :id                        => port_hash['id'],
39
+            :port                      => port_hash['name']
40
+            )
41
+      end
42
+    end
43
+    return instances_
44
+  end
45
+
46
+  def self.prefetch(resources)
47
+    instances_ = instances
48
+    resources.keys.each do |name|
49
+      if provider = instances_.find{ |instance| instance.name == name }
50
+        resources[name].provider = provider
51
+      end
52
+    end
53
+  end
54
+
55
+  def exists?
56
+    @property_hash[:ensure] == :present
57
+  end
58
+
59
+  def create
60
+    router,subnet = resource[:name].split(':', 2)
61
+    port = resource[:port]
62
+    args = ["router-interface-add", "--format=shell", router]
63
+    if port
64
+      args << "port=#{port}"
65
+    else
66
+      args << "subnet=#{subnet}"
67
+    end
68
+    results = auth_neutron(args)
69
+
70
+    if results =~ /Added interface.* to router/
71
+      @property_hash = {
72
+        :ensure => :present,
73
+        :name   => resource[:name],
74
+      }
75
+    else
76
+      fail("did not get expected message on interface addition, got #{results}")
77
+    end
78
+  end
79
+
80
+  def router_name
81
+    name.split(':', 2).first
82
+  end
83
+
84
+  def subnet_name
85
+    name.split(':', 2).last
86
+  end
87
+
88
+  def destroy
89
+    auth_neutron('router-interface-delete', router_name, subnet_name)
90
+    @property_hash[:ensure] = :absent
91
+  end
92
+
93
+end

+ 220
- 0
deployment_scripts/puppet/modules/neutron/lib/puppet/provider/neutron_subnet/neutron.rb View File

@@ -0,0 +1,220 @@
1
+require File.join(File.dirname(__FILE__), '..','..','..',
2
+                  'puppet/provider/neutron')
3
+
4
+Puppet::Type.type(:neutron_subnet).provide(
5
+  :neutron,
6
+  :parent => Puppet::Provider::Neutron
7
+) do
8
+  desc <<-EOT
9
+    Neutron provider to manage neutron_subnet type.
10
+
11
+    Assumes that the neutron service is configured on the same host.
12
+  EOT
13
+
14
+  commands :neutron => 'neutron'
15
+  commands :keystone => 'keystone'
16
+
17
+  mk_resource_methods
18
+
19
+  def self.neutron_type
20
+    'subnet'
21
+  end
22
+
23
+  def self.instances
24
+    list_neutron_resources(neutron_type).collect do |id|
25
+      attrs = get_neutron_resource_attrs(neutron_type, id)
26
+      new(
27
+        :ensure                    => :present,
28
+        :name                      => attrs['name'],
29
+        :id                        => attrs['id'],
30
+        :cidr                      => attrs['cidr'],
31
+        :ip_version                => attrs['ip_version'],
32
+        :gateway_ip                => parse_gateway_ip(attrs['gateway_ip']),
33
+        :allocation_pools          => parse_allocation_pool(attrs['allocation_pools']),
34
+        :host_routes               => parse_host_routes(attrs['host_routes']),
35
+        :dns_nameservers           => parse_dns_nameservers(attrs['dns_nameservers']),
36
+        :enable_dhcp               => attrs['enable_dhcp'],
37
+        :network_id                => attrs['network_id'],
38
+        :tenant_id                 => attrs['tenant_id']
39
+      )
40
+    end
41
+  end
42
+
43
+  def self.prefetch(resources)
44
+    subnets = instances
45
+    resources.keys.each do |name|
46
+      if provider = subnets.find{ |subnet| subnet.name == name }
47
+        resources[name].provider = provider
48
+      end
49
+    end
50
+  end
51
+
52
+  def self.parse_gateway_ip(value)
53
+    return '' if value.nil?
54
+    return value
55
+  end
56
+
57
+  def self.parse_allocation_pool(values)
58
+    allocation_pools = []
59
+    return [] if values.empty?
60
+    for value in Array(values)
61
+      matchdata = /\{\s*"start"\s*:\s*"(.*)"\s*,\s*"end"\s*:\s*"(.*)"\s*\}/.match(value.gsub(/\\"/,'"'))
62
+      start_ip = matchdata[1]
63
+      end_ip = matchdata[2]
64
+      allocation_pools << "start=#{start_ip},end=#{end_ip}"
65
+    end
66
+    return allocation_pools
67
+  end
68
+
69
+  def self.parse_host_routes(values)
70
+    host_routes = []
71
+    return [] if values.empty?
72
+    for value in Array(values)
73
+      matchdata = /\{\s*"destination"\s*:\s*"(.*)"\s*,\s*"nexthop"\s*:\s*"(.*)"\s*\}/.match(value)
74
+      destination = matchdata[1]
75
+      nexthop = matchdata[2]
76
+      host_routes << "destination=#{destination},nexthop=#{nexthop}"
77
+    end
78
+    return host_routes
79
+  end
80
+
81
+  def self.parse_dns_nameservers(values)
82
+    # just enforce that this is actually an array
83
+    return Array(values)
84
+  end
85
+
86
+  def exists?
87
+    @property_hash[:ensure] == :present
88
+  end
89
+
90
+  def create
91
+    opts = ["--name=#{@resource[:name]}"]
92
+
93
+    if @resource[:ip_version]
94
+      opts << "--ip-version=#{@resource[:ip_version]}"
95
+    end
96
+
97
+    if @resource[:gateway_ip]
98
+      if @resource[:gateway_ip] == ''
99
+        opts << '--no-gateway'
100
+      else
101
+        opts << "--gateway-ip=#{@resource[:gateway_ip]}"
102
+      end
103
+    end
104
+
105
+    if @resource[:enable_dhcp] == 'False'
106
+      opts << "--disable-dhcp"
107
+    else
108
+      opts << "--enable-dhcp"
109
+    end
110
+
111
+    if @resource[:allocation_pools]
112
+      Array(@resource[:allocation_pools]).each do |allocation_pool|
113
+        opts << "--allocation-pool=#{allocation_pool}"
114
+      end
115
+    end
116
+
117
+    if @resource[:dns_nameservers]
118
+      Array(@resource[:dns_nameservers]).each do |nameserver|
119
+        opts << "--dns-nameserver=#{nameserver}"
120
+      end
121
+    end
122
+
123
+    if @resource[:host_routes]
124
+      Array(@resource[:host_routes]).each do |host_route|
125
+        opts << "--host-route=#{host_route}"
126
+      end
127
+    end
128
+
129
+    if @resource[:tenant_name]
130
+      tenant_id = self.class.get_tenant_id(model.catalog,
131
+                                           @resource[:tenant_name])
132
+      opts << "--tenant_id=#{tenant_id}"
133
+    elsif @resource[:tenant_id]
134
+      opts << "--tenant_id=#{@resource[:tenant_id]}"
135
+    end
136
+
137
+    if @resource[:network_name]
138
+      opts << resource[:network_name]
139
+    elsif @resource[:network_id]
140
+      opts << resource[:network_id]
141
+    end
142
+
143
+    results = auth_neutron('subnet-create', '--format=shell',
144
+                           opts, resource[:cidr])
145
+
146
+    if results =~ /Created a new subnet:/
147
+      attrs = self.class.parse_creation_output(results)
148
+      @property_hash = {
149
+        :ensure                    => :present,
150
+        :name                      => resource[:name],
151
+        :id                        => attrs['id'],
152
+        :cidr                      => attrs['cidr'],
153
+        :ip_version                => attrs['ip_version'],
154
+        :gateway_ip                => self.class.parse_gateway_ip(attrs['gateway_ip']),
155
+        :allocation_pools          => self.class.parse_allocation_pool(attrs['allocation_pools']),
156
+        :host_routes               => self.class.parse_host_routes(attrs['host_routes']),
157
+        :dns_nameservers           => self.class.parse_dns_nameservers(attrs['dns_nameservers']),
158
+        :enable_dhcp               => attrs['enable_dhcp'],
159
+        :network_id                => attrs['network_id'],
160
+        :tenant_id                 => attrs['tenant_id'],
161
+      }
162
+    else
163
+      fail("did not get expected message on subnet creation, got #{results}")
164
+    end
165
+  end
166
+
167
+  def destroy
168
+    auth_neutron('subnet-delete', name)
169
+    @property_hash[:ensure] = :absent
170
+  end
171
+
172
+  def gateway_ip=(value)
173
+    if value == ''
174
+      auth_neutron('subnet-update', '--no-gateway', name)
175
+    else
176
+      auth_neutron('subnet-update', "--gateway-ip=#{value}", name)
177
+    end
178
+  end
179
+
180
+  def enable_dhcp=(value)
181
+    if value == 'False'
182
+      auth_neutron('subnet-update', "--disable-dhcp", name)
183
+    else
184
+      auth_neutron('subnet-update', "--enable-dhcp", name)
185
+    end
186
+  end
187
+
188
+  def dns_nameservers=(values)
189
+    unless values.empty?
190
+      opts = ["#{name}", "--dns-nameservers", "list=true"]
191
+      for value in values
192
+        opts << value
193
+      end
194
+      auth_neutron('subnet-update', opts)
195
+    end
196
+  end
197
+
198
+  def host_routes=(values)
199
+    unless values.empty?
200
+      opts = ["#{name}", "--host-routes", "type=dict", "list=true"]
201
+      for value in values
202
+        opts << value
203
+      end
204
+      auth_neutron('subnet-update', opts)
205
+    end
206
+  end
207
+
208
+  [
209
+   :cidr,
210
+   :ip_version,
211
+   :network_id,
212
+   :allocation_pools,
213
+   :tenant_id,
214
+  ].each do |attr|
215
+     define_method(attr.to_s + "=") do |value|
216
+       fail("Property #{attr.to_s} does not support being updated")
217
+     end
218
+  end
219
+
220
+end

+ 47
- 0
deployment_scripts/puppet/modules/neutron/lib/puppet/type/neutron_config.rb View File

@@ -0,0 +1,47 @@
1
+Puppet::Type.newtype(:neutron_config) do
2
+
3
+  ensurable
4
+
5
+  newparam(:name, :namevar => true) do
6
+    desc 'Section/setting name to manage from neutron.conf'
7
+    newvalues(/\S+\/\S+/)
8
+  end
9
+
10
+  newproperty(:value) do
11
+    desc 'The value of the setting to be defined.'
12
+    munge do |value|
13
+      value = value.to_s.strip
14
+      value.capitalize! if value =~ /^(true|false)$/i
15
+      value
16
+    end
17
+
18
+    def is_to_s( currentvalue )
19
+      if resource.secret?
20
+        return '[old secret redacted]'
21
+      else
22
+        return currentvalue
23
+      end
24
+    end
25
+
26
+    def should_to_s( newvalue )
27
+      if resource.secret?
28
+        return '[new secret redacted]'
29
+      else
30
+        return newvalue
31
+      end
32
+    end
33
+  end
34
+
35
+  newparam(:secret, :boolean => true) do
36
+    desc 'Whether to hide the value from Puppet logs. Defaults to `false`.'
37
+
38
+    newvalues(:true, :false)
39
+
40
+    defaultto false
41
+  end
42
+
43
+  def create
44
+      provider.create
45
+  end
46
+
47
+end

+ 90
- 0
deployment_scripts/puppet/modules/neutron/lib/puppet/type/neutron_network.rb View File

@@ -0,0 +1,90 @@
1
+Puppet::Type.newtype(:neutron_network) do
2
+
3
+  ensurable
4
+
5
+  newparam(:name, :namevar => true) do
6
+    desc 'Symbolic name for the network'
7
+    newvalues(/.*/)
8
+  end
9
+
10
+  newproperty(:id) do
11
+    desc 'The unique id of the network'
12
+    validate do |v|
13
+      raise(Puppet::Error, 'This is a read only property')
14
+    end
15
+  end
16
+
17
+  newproperty(:admin_state_up) do
18
+    desc 'The administrative status of the network'
19
+    newvalues(/(t|T)rue/, /(f|F)alse/)
20
+    munge do |v|
21
+      v.to_s.capitalize
22
+    end
23
+  end
24
+
25
+  newproperty(:shared) do
26
+    desc 'Whether this network should be shared across all tenants or not'
27
+    newvalues(/(t|T)rue/, /(f|F)alse/)
28
+    munge do |v|
29
+      v.to_s.capitalize
30
+    end
31
+  end
32
+
33
+  newparam(:tenant_name) do
34
+    desc 'The name of the tenant which will own the network.'
35
+  end
36
+
37
+  newproperty(:tenant_id) do
38
+    desc 'A uuid identifying the tenant which will own the network.'
39
+  end
40
+
41
+  newproperty(:provider_network_type) do
42
+    desc 'The physical mechanism by which the virtual network is realized.'
43
+    newvalues(:flat, :vlan, :local, :gre)
44
+  end
45
+
46
+  newproperty(:provider_physical_network) do
47
+    desc <<-EOT
48
+      The name of the physical network over which the virtual network
49
+      is realized for flat and VLAN networks.
50
+    EOT
51
+    newvalues(/\S+/)
52
+  end
53
+
54
+  newproperty(:provider_segmentation_id) do
55
+    desc 'Identifies an isolated segment on the physical network.'
56
+    munge do |v|
57
+      Integer(v)
58
+    end
59
+  end
60
+
61
+  newproperty(:router_external) do
62
+    desc 'Whether this router will route traffic to an external network'
63
+    newvalues(/(t|T)rue/, /(f|F)alse/)
64
+    munge do |v|
65
+      v.to_s.capitalize
66
+    end
67
+  end
68
+
69
+  # Require the neutron-server service to be running
70
+  autorequire(:service) do
71
+    ['neutron-server']
72
+  end
73
+
74
+  autorequire(:keystone_tenant) do
75
+    [self[:tenant_name]] if self[:tenant_name]
76
+  end
77
+
78
+  validate do
79
+    if self[:ensure] != :present
80
+      return
81
+    end
82
+    if self[:tenant_id] && self[:tenant_name]
83
+      raise(Puppet::Error, <<-EOT
84
+Please provide a value for only one of tenant_name and tenant_id.
85
+EOT
86
+            )
87
+    end
88
+  end
89
+
90
+end

+ 20
- 0
deployment_scripts/puppet/modules/neutron/lib/puppet/type/neutron_plugin_ml2.rb View File

@@ -0,0 +1,20 @@
1
+Puppet::Type.newtype(:neutron_plugin_ml2) do
2
+
3
+  ensurable
4
+
5
+  newparam(:name, :namevar => true) do
6
+    desc 'Section/setting name to manage from ml2_conf.ini'
7
+    newvalues(/\S+\/\S+/)
8
+  end
9
+
10
+  autorequire(:package) do ['neutron'] end
11
+
12
+  newproperty(:value) do
13
+    desc 'The value of the setting to be defined.'
14
+    munge do |value|
15
+      value = value.to_s.strip
16
+      value.capitalize! if value =~ /^(true|false)$/i
17
+      value
18
+    end
19
+  end
20
+end

+ 47
- 0
deployment_scripts/puppet/modules/neutron/lib/puppet/type/neutron_plugin_ml2_cisco.rb View File

@@ -0,0 +1,47 @@
1
+Puppet::Type.newtype(:neutron_plugin_ml2_cisco) do
2
+
3
+  ensurable
4
+
5
+  newparam(:name, :namevar => true) do
6
+    desc 'Section/setting name to manage from cisco_plugins.ini'
7
+    newvalues(/\S+\/\S+/)
8
+  end
9
+
10
+  autorequire(:file) do
11
+    ['/etc/neutron/plugins/ml2/ml2_conf_cisco.ini']
12
+  end
13
+
14
+  newproperty(:value) do
15
+    desc 'The value of the setting to be defined.'
16
+    munge do |value|
17
+      value = value.to_s.strip
18
+      value.capitalize! if value =~ /^(true|false)$/i
19
+      value
20
+    end
21
+
22
+    def is_to_s( currentvalue )
23
+      if resource.secret?
24
+        return '[old secret redacted]'
25
+      else
26
+        return currentvalue
27
+      end
28
+    end
29
+
30
+    def should_to_s( newvalue )
31
+      if resource.secret?
32
+        return '[new secret redacted]'
33
+      else
34
+        return newvalue
35
+      end
36
+    end
37
+  end
38
+
39
+  newparam(:secret, :boolean => true) do
40
+    desc 'Whether to hide the value from Puppet logs. Defaults to `false`.'
41
+
42
+    newvalues(:true, :false)
43
+
44
+    defaultto false
45
+  end
46
+
47
+end

+ 98
- 0
deployment_scripts/puppet/modules/neutron/lib/puppet/type/neutron_port.rb View File

@@ -0,0 +1,98 @@
1
+Puppet::Type.newtype(:neutron_port) do
2
+  desc <<-EOT
3
+    This is currently used to model the creation of neutron ports.
4
+
5
+    Ports are used when associating a network and a router interface.
6
+  EOT
7
+
8
+  ensurable
9
+
10
+  newparam(:name, :namevar => true) do
11
+    desc 'Symbolic name for the port'
12
+    newvalues(/.*/)
13
+  end
14
+
15
+  newproperty(:id) do
16
+    desc 'The unique id of the port'
17
+    validate do |v|
18
+      raise(Puppet::Error, 'This is a read only property')
19
+    end
20
+  end
21
+
22
+  newproperty(:admin_state_up) do
23
+    desc 'The administrative status of the router'
24
+    newvalues(/(t|T)rue/, /(f|F)alse/)
25
+    munge do |v|
26
+      v.to_s.capitalize
27
+    end
28
+  end
29
+
30
+  newproperty(:network_name) do
31
+    desc <<-EOT
32
+      The name of the network that this port is assigned to on creation.
33
+    EOT
34
+  end
35
+
36
+  newproperty(:network_id) do
37
+    desc <<-EOT
38
+      The uuid of the network that this port is assigned to on creation.
39
+    EOT
40
+    validate do |v|
41
+      raise(Puppet::Error, 'This is a read only property')
42
+    end
43
+  end
44
+
45
+  newproperty(:subnet_name) do
46
+    desc 'A subnet to which the port is assigned on creation.'
47
+  end
48
+
49
+  newproperty(:subnet_id) do
50
+    desc <<-EOT
51
+      The uuid of the subnet on which this ports ip exists.
52
+    EOT
53
+    validate do |v|
54
+      raise(Puppet::Error, 'This is a read only property')
55
+    end
56
+  end
57
+
58
+  newproperty(:ip_address) do
59
+    desc 'A static ip address given to the port on creation.'
60
+  end
61
+
62
+  newproperty(:status) do
63
+    desc 'Whether the port is currently operational or not.'
64
+    validate do |v|
65
+      raise(Puppet::Error, 'This is a read only property')
66
+    end
67
+  end
68
+
69
+  newparam(:tenant_name) do
70
+    desc 'The name of the tenant which will own the port.'
71
+  end
72
+
73
+  newproperty(:tenant_id) do
74
+    desc 'A uuid identifying the tenant which will own the port.'
75
+  end
76
+
77
+  autorequire(:service) do
78
+    ['neutron-server']
79
+  end
80
+
81
+  autorequire(:keystone_tenant) do
82
+    [self[:tenant_name]] if self[:tenant_name]
83
+  end
84
+
85
+  autorequire(:neutron_network) do
86
+    [self[:name]]
87
+  end
88
+
89
+  validate do
90
+    if self[:tenant_id] && self[:tenant_name]
91
+      raise(Puppet::Error, 'Please provide a value for only one of tenant_name and tenant_id.')
92
+    end
93
+    if self[:ip_address] && self[:subnet_name]
94
+      raise(Puppet::Error, 'Please provide a value for only one of ip_address and subnet_name.')
95
+    end
96
+  end
97
+
98
+end

+ 91
- 0
deployment_scripts/puppet/modules/neutron/lib/puppet/type/neutron_router.rb View File

@@ -0,0 +1,91 @@
1
+Puppet::Type.newtype(:neutron_router) do
2
+
3
+  ensurable
4
+
5
+  newparam(:name, :namevar => true) do
6
+    desc 'Symbolic name for the router'
7
+    newvalues(/.*/)
8
+  end
9
+
10
+  newproperty(:id) do
11
+    desc 'The unique id of the router'
12
+    validate do |v|
13
+      raise(Puppet::Error, 'This is a read only property')
14
+    end
15
+  end
16
+
17
+  newproperty(:admin_state_up) do
18
+    desc 'The administrative status of the router'
19
+    newvalues(/(t|T)rue/, /(f|F)alse/)
20
+    munge do |v|
21
+      v.to_s.capitalize
22
+    end
23
+  end
24
+
25
+  newproperty(:external_gateway_info) do
26
+    desc <<-EOT
27
+      External network that this router connects to for gateway services
28
+      (e.g., NAT).
29
+    EOT
30
+    validate do |v|
31
+      raise(Puppet::Error, 'This is a read only property')
32
+    end
33
+  end
34
+
35
+  newproperty(:gateway_network_name) do
36
+    desc <<-EOT
37
+      The name of the external network that this router connects to
38
+      for gateway services (e.g. NAT).
39
+    EOT
40
+  end
41
+
42
+  newproperty(:gateway_network_id) do
43
+    desc <<-EOT
44
+      The uuid of the external network that this router connects to
45
+      for gateway services (e.g. NAT).
46
+    EOT
47
+    validate do |v|
48
+      raise(Puppet::Error, 'This is a read only property')
49
+    end
50
+  end
51
+
52
+  newproperty(:status) do
53
+    desc 'Whether the router is currently operational or not.'
54
+    validate do |v|
55
+      raise(Puppet::Error, 'This is a read only property')
56
+    end
57
+  end
58
+
59
+  newparam(:tenant_name) do
60
+    desc 'The name of the tenant which will own the router.'
61
+  end
62
+
63
+  newproperty(:tenant_id) do
64
+    desc 'A uuid identifying the tenant which will own the router.'
65
+  end
66
+
67
+  autorequire(:service) do
68
+    ['neutron-server']
69
+  end
70
+
71
+  autorequire(:keystone_tenant) do
72
+    [self[:tenant_name]] if self[:tenant_name]
73
+  end
74
+
75
+  autorequire(:neutron_network) do
76
+    [self[:gateway_network_name]] if self[:gateway_network_name]
77
+  end
78
+
79
+  validate do
80
+    if self[:ensure] != :present
81
+      return
82
+    end
83
+    if self[:tenant_id] && self[:tenant_name]
84
+      raise(Puppet::Error, <<-EOT
85
+Please provide a value for only one of tenant_name and tenant_id.
86
+EOT
87
+            )
88
+    end
89
+  end
90
+
91
+end

+ 51
- 0
deployment_scripts/puppet/modules/neutron/lib/puppet/type/neutron_router_interface.rb View File

@@ -0,0 +1,51 @@
1
+Puppet::Type.newtype(:neutron_router_interface) do
2
+
3
+  desc <<-EOT
4
+    This is currently used to model the creation of
5
+    neutron router interfaces.
6
+
7
+    Router interfaces are an association between a router and a
8
+    subnet.
9
+  EOT
10
+
11
+  ensurable
12
+
13
+  newparam(:name, :namevar => true) do
14
+    newvalues(/^\S+:\S+$/)
15
+  end
16
+
17
+  newproperty(:id) do
18
+    validate do |v|
19
+      raise(Puppet::Error, 'This is a read only property')
20
+    end
21
+  end
22
+
23
+  newproperty(:router_name) do
24
+    validate do |v|
25
+      raise(Puppet::Error, 'This is a read only property')
26
+    end
27
+  end
28
+
29
+  newproperty(:subnet_name) do
30
+    validate do |v|
31
+      raise(Puppet::Error, 'This is a read only property')
32
+    end
33
+  end
34
+
35
+  newproperty(:port) do
36
+    desc 'An existing neutron port to which a rounter interface should be assigned'
37
+  end
38
+
39
+  autorequire(:service) do
40
+    ['neutron-server']
41
+  end
42
+
43
+  autorequire(:neutron_router) do
44
+    self[:name].split(':', 2).first
45
+  end
46
+
47
+  autorequire(:neutron_subnet) do
48
+    self[:name].split(':', 2).last
49
+  end
50
+
51
+end

+ 114
- 0
deployment_scripts/puppet/modules/neutron/lib/puppet/type/neutron_subnet.rb View File

@@ -0,0 +1,114 @@
1
+Puppet::Type.newtype(:neutron_subnet) do
2
+
3
+  ensurable
4
+
5
+  newparam(:name, :namevar => true) do
6
+    desc 'Symbolic name for the subnet'
7
+    newvalues(/.*/)
8
+  end
9
+
10
+  newproperty(:id) do
11
+    desc 'The unique id of the subnet'
12
+    validate do |v|
13
+      raise(Puppet::Error, 'This is a read only property')
14
+    end
15
+  end
16
+
17
+  newproperty(:cidr) do
18
+    desc 'CIDR representing IP range for this subnet, based on IP version'
19
+  end
20
+
21
+  newproperty(:ip_version) do
22
+    desc 'The IP version of the CIDR'
23
+    newvalues('4', '6')
24
+  end
25
+
26
+  newproperty(:allocation_pools, :array_matching => :all) do
27
+    desc <<-EOT
28
+    Array of Sub-ranges of cidr available for dynamic allocation to ports.
29
+    Syntax:["start=IPADDR,end=IPADDR", ...]
30
+    EOT
31
+  end
32
+
33
+  newproperty(:gateway_ip) do
34
+    desc <<-EOT
35
+    The default gateway provided by DHCP to devices in this subnet.  If set to
36
+    '' then no gateway IP address will be provided via DHCP.
37
+    EOT
38
+  end
39
+
40
+  newproperty(:enable_dhcp) do
41
+    desc 'Whether DHCP is enabled for this subnet or not.'
42
+    newvalues(/(t|T)rue/, /(f|F)alse/)
43
+    munge do |v|
44
+      v.to_s.capitalize
45
+    end
46
+  end
47
+
48
+  newproperty(:host_routes, :array_matching => :all) do
49
+    desc <<-EOT
50
+    Array of routes that should be used by devices with IPs from this subnet
51
+    (not including local subnet route).
52
+    Syntax:["destination=CIDR,nexhop=IP_ADDR", ...]
53
+    EOT
54
+  end
55
+
56
+  newproperty(:dns_nameservers, :array_matching => :all) do
57
+    desc <<-EOT
58
+    'Array of DNS name servers used by hosts in this subnet.'
59
+    EOT
60
+  end
61
+
62
+  newproperty(:network_id) do
63
+    desc 'A uuid identifying the network this subnet is associated with.'
64
+  end
65
+
66
+  newparam(:network_name) do
67
+    desc 'The name of the network this subnet is associated with.'
68
+  end
69
+
70
+  newparam(:tenant_name) do
71
+    desc 'The name of the tenant which will own the subnet.'
72
+  end
73
+
74
+  newproperty(:tenant_id) do
75
+    desc 'A uuid identifying the tenant which will own the subnet.'
76
+  end
77
+
78
+  autorequire(:service) do
79
+    ['neutron-server']
80
+  end
81
+
82
+  autorequire(:keystone_tenant) do
83
+    [self[:tenant_name]] if self[:tenant_name]
84
+  end
85
+
86
+  autorequire(:neutron_network) do
87
+    [self[:network_name]] if self[:network_name]
88
+  end
89
+
90
+  validate do
91
+    if self[:ensure] != :present
92
+      return
93
+    end
94
+    if ! self[:cidr]
95
+      raise(Puppet::Error, 'Please provide a valid CIDR')
96
+    elsif ! (self[:network_id] || self[:network_name])
97
+      raise(Puppet::Error, <<-EOT
98
+A value for one of network_name or network_id must be provided.
99
+EOT
100
+            )
101
+    elsif self[:network_id] && self[:network_name]
102
+      raise(Puppet::Error, <<-EOT
103
+Please provide a value for only one of network_name and network_id.
104
+EOT
105
+            )
106
+    elsif self[:tenant_id] && self[:tenant_name]
107
+      raise(Puppet::Error, <<-EOT
108
+Please provide a value for only one of tenant_name and tenant_id.
109
+EOT
110
+            )
111
+    end
112
+  end
113
+
114
+end

Loading…
Cancel
Save