|
1 # |
|
2 # CDDL HEADER START |
|
3 # |
|
4 # The contents of this file are subject to the terms of the |
|
5 # Common Development and Distribution License (the "License"). |
|
6 # You may not use this file except in compliance with the License. |
|
7 # |
|
8 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
|
9 # or http://www.opensolaris.org/os/licensing. |
|
10 # See the License for the specific language governing permissions |
|
11 # and limitations under the License. |
|
12 # |
|
13 # When distributing Covered Code, include this CDDL HEADER in each |
|
14 # file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
|
15 # If applicable, add the following below this CDDL HEADER, with the |
|
16 # fields enclosed by brackets "[]" replaced with your own identifying |
|
17 # information: Portions Copyright [yyyy] [name of copyright owner] |
|
18 # |
|
19 # CDDL HEADER END |
|
20 # |
|
21 |
|
22 # |
|
23 # Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. |
|
24 # |
|
25 |
|
26 |
|
27 Puppet::Type.type(:evs_properties).provide(:evs_properties) do |
|
28 desc "Provider for managing Oracle Solaris EVS properties" |
|
29 confine :operatingsystem => [:solaris] |
|
30 defaultfor :osfamily => :solaris, :kernelrelease => ["5.11", "5.12"] |
|
31 commands :evsadm => "/usr/sbin/evsadm" |
|
32 |
|
33 mk_resource_methods |
|
34 |
|
35 def initialize(value={}) |
|
36 super(value) |
|
37 @property_flush = {} |
|
38 end |
|
39 |
|
40 def self.get_client_property |
|
41 client_property = {} |
|
42 begin |
|
43 p = evsadm("show-prop", "-c", "-o", "property,value") |
|
44 rescue Puppet::ExecutionFailure => e |
|
45 raise Puppet::Error, "Failed to prefetch client property: \n" \ |
|
46 "#{e.inspect}" |
|
47 end |
|
48 |
|
49 property, value = p.strip.split(":", 2) |
|
50 value.gsub! "\\:", ":" |
|
51 client_property[:name] = "client_property" |
|
52 client_property[:controller] = value |
|
53 |
|
54 Puppet.debug "Client Property: #{client_property.inspect}" |
|
55 client_property |
|
56 |
|
57 end |
|
58 |
|
59 def self.get_control_properties |
|
60 control_props = {} |
|
61 uplink_ports = [] |
|
62 uri_templates = [] |
|
63 vxlan_addrs = [] |
|
64 begin |
|
65 evsadm("show-controlprop", "-c", "-o", |
|
66 "property,value,vlan_range,vxlan_range,host,flat").\ |
|
67 split("\n").collect do |each_prop| |
|
68 each_prop.gsub! "\\:", "\\" |
|
69 property, value, vlan_range, vxlan_range, host, flat = \ |
|
70 each_prop.strip().split(":") |
|
71 case property |
|
72 when "l2-type" |
|
73 control_props[:l2_type] = value |
|
74 when "uplink-port" |
|
75 next if value.empty? |
|
76 host = "" if host == nil |
|
77 val = "#{value};#{vlan_range};#{vxlan_range};#{host};"\ |
|
78 "#{flat}" |
|
79 uplink_ports << val |
|
80 when "uri-template" |
|
81 value.gsub! "\\", ":" |
|
82 host = "" if host == nil |
|
83 val = "#{value};#{host}" |
|
84 uri_templates << val |
|
85 when "vlan-range" |
|
86 control_props[:vlan_range] = value |
|
87 when "vxlan-addr" |
|
88 host = "" if host == nil |
|
89 val = "#{value};#{vxlan_range};#{host}" |
|
90 vxlan_addrs << val |
|
91 when "vxlan-ipvers" |
|
92 control_props[:vxlan_ipvers] = value |
|
93 when "vxlan-mgroup" |
|
94 control_props[:vxlan_mgroup] = value |
|
95 when "vxlan-range" |
|
96 control_props[:vxlan_range] = value |
|
97 end |
|
98 end |
|
99 rescue Puppet::ExecutionFailure => e |
|
100 # EVS controller is not set or valid |
|
101 # Handle the exception at upper level |
|
102 raise |
|
103 end |
|
104 control_props[:name] = "controller_property" |
|
105 control_props[:uplink_port] = uplink_ports |
|
106 control_props[:uri_template] = uri_templates |
|
107 control_props[:vxlan_addr] = vxlan_addrs |
|
108 Puppet.debug "Control Properties: #{control_props.inspect}" |
|
109 control_props |
|
110 end |
|
111 |
|
112 def self.instances |
|
113 prop_instance = [] |
|
114 client_property = get_client_property |
|
115 prop_instance << new(client_property) |
|
116 |
|
117 begin |
|
118 controller_property = get_control_properties |
|
119 rescue Puppet::ExecutionFailure => e |
|
120 # EVS controller is not set or invalid |
|
121 prop_instance << new({:name => "controller_property"}) |
|
122 else |
|
123 # controller_property values are fetched |
|
124 prop_instance << new(controller_property) |
|
125 end |
|
126 prop_instance |
|
127 end |
|
128 |
|
129 def self.prefetch(resources) |
|
130 instances.each do |inst| |
|
131 if resource = resources[inst.name] |
|
132 resource.provider = inst |
|
133 end |
|
134 end |
|
135 end |
|
136 |
|
137 ### Define Setters ### |
|
138 ## Controller side property setup ## |
|
139 |
|
140 def l2_type=(value) |
|
141 @property_flush[:l2_type] = value |
|
142 end |
|
143 |
|
144 def uplink_port=(value) |
|
145 @property_flush[:uplink_port] = value |
|
146 end |
|
147 |
|
148 def uri_template=(value) |
|
149 @property_flush[:uri_template] = value |
|
150 end |
|
151 |
|
152 def vlan_range=(value) |
|
153 @property_flush[:vlan_range] = value |
|
154 end |
|
155 |
|
156 def vxlan_addr=(value) |
|
157 @property_flush[:vxlan_addr] = value |
|
158 end |
|
159 |
|
160 def vxlan_ipvers=(value) |
|
161 @property_flush[:vxlan_ipvers] = value |
|
162 end |
|
163 |
|
164 def vxlan_mgroup=(value) |
|
165 @property_flush[:vxlan_mgroup] = value |
|
166 end |
|
167 |
|
168 def vxlan_range=(value) |
|
169 @property_flush[:vxlan_range] = value |
|
170 end |
|
171 |
|
172 ## Client side property setup: the pointer to the EVS controller ## |
|
173 def controller=(value) |
|
174 @property_flush[:controller] = value |
|
175 end |
|
176 |
|
177 def set_controller_property(host, property) |
|
178 begin |
|
179 evsadm("set-controlprop", host, property) |
|
180 rescue Puppet::ExecutionFailure => e |
|
181 # Pass up the exception to upper level |
|
182 raise |
|
183 end |
|
184 end |
|
185 |
|
186 def set_client_property(property) |
|
187 begin |
|
188 evsadm("set-prop", "-p", property) |
|
189 rescue Puppet::ExecutionFailure => e |
|
190 # Pass up the exception to upper level |
|
191 raise |
|
192 end |
|
193 end |
|
194 |
|
195 def flush |
|
196 case @resource[:name] |
|
197 when "controller_property" |
|
198 if @property_flush.has_key?(:controller) |
|
199 puts "foo" |
|
200 raise Puppet::Error, "controller_property does not have "\ |
|
201 "'controller' property. Try client_property" |
|
202 puts "bar" |
|
203 end |
|
204 |
|
205 props = [] |
|
206 @property_flush.each do |key, value| |
|
207 # Change symbol to string |
|
208 k = key.to_s.gsub! "_", "-" |
|
209 case k |
|
210 # uplink-port property takes up to five values: |
|
211 # link, [vlan-range], [vxlan-range], [host] and [flat] |
|
212 when "uplink-port" |
|
213 link, vlan, vxlan, host, flat = \ |
|
214 value.strip().split(";", -1) |
|
215 |
|
216 # store host parameter if exists |
|
217 host = host != "" ? ["-h", host] : [] |
|
218 |
|
219 # Concatenate the parameters of uplink-port |
|
220 link = "uplink-port=#{link}" |
|
221 vlan = vlan != "" ? ",vlan-range=#{vlan}" : "" |
|
222 vxlan = vxlan != "" ? ",vxlan-range=#{vxlan}" : "" |
|
223 flat = flat != "" ? ",flat=#{flat}" : "" |
|
224 |
|
225 p = ["-p", "#{link}#{vlan}#{vxlan}#{flat}"] |
|
226 |
|
227 props << [host, p] |
|
228 |
|
229 # uri-template property takes up to two values: |
|
230 # uri and [host] |
|
231 when "uri-template" |
|
232 uri, host = value.strip().split(";", -1) |
|
233 |
|
234 # store host parameter if exists |
|
235 host = host != "" ? ["-h", host] : [] |
|
236 uri = ["-p", "uri-template=#{uri}"] |
|
237 |
|
238 props << [host, uri] |
|
239 |
|
240 # vxlan_addr property takes up to three values: |
|
241 # vxlan-addr, [vxlan-range] and [host] |
|
242 when "vxlan-addr" |
|
243 addr, range, host = value.strip().split(";", -1) |
|
244 |
|
245 # store host parameter if exists |
|
246 host = host != "" ? ["-h", host] : [] |
|
247 addr = "vxlan-addr=#{addr}" |
|
248 range = range != "" ? ",vxlan-range=#{range}" : "" |
|
249 |
|
250 p = ["-p", "#{addr}#{range}"] |
|
251 |
|
252 props << [host, p] |
|
253 |
|
254 # l2-type, vlan-range, vxlan-range, vxlan-ipvers |
|
255 # and vxlan-mgroup properties just need values |
|
256 else |
|
257 host = [] |
|
258 p = ["-p", "#{k}=#{value}"] |
|
259 props << [host, p] |
|
260 end |
|
261 end |
|
262 |
|
263 # Reverse the array so that l2-type, vlan-range, vxlan-range |
|
264 # vxlan-ipvers and vxlan-mgroups are set before the others |
|
265 props.reverse! |
|
266 # iteratively set controller property |
|
267 props.each do |p| |
|
268 begin |
|
269 set_controller_property(p[0], p[1]) |
|
270 # Do not terminate the script even if there is an error |
|
271 # Just continue to next script |
|
272 rescue Puppet::ExecutionFailure => e |
|
273 Puppet.err "Cannot apply the property: \n#{e.inspect}" |
|
274 end |
|
275 end |
|
276 |
|
277 when "client_property" |
|
278 unless @property_flush.has_key?(:controller) |
|
279 raise Puppet::Error, |
|
280 "'controller' property must be specified" |
|
281 end |
|
282 prop = "controller=#{@property_flush[:controller]}" |
|
283 begin |
|
284 set_client_property(prop) |
|
285 rescue Puppet::ExecutionFailure => e |
|
286 raise Puppet::Error, "Cannot apply the property:\n #{e.inspect}" |
|
287 end |
|
288 end |
|
289 |
|
290 # Synchronize all the SHOULD values to IS values |
|
291 @property_hash = resource.to_hash |
|
292 end |
|
293 end |
|
294 |