forj 0.0.48 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,306 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+
19
+ class BaseDefinition
20
+
21
+ private
22
+ # ------------------------------------------------------
23
+ # Class Definition internal function.
24
+ # ------------------------------------------------------
25
+
26
+ def _ask_encrypted(sDesc, sDefault)
27
+ # Checking key file used to encrypt/decrypt passwords
28
+ key_file = File.join($FORJ_CREDS_PATH, '.key')
29
+ if not File.exists?(key_file)
30
+ # Need to create a random key.
31
+ entr = {
32
+ :key => rand(36**10).to_s(36),
33
+ :salt => Time.now.to_i.to_s,
34
+ :iv => Base64::strict_encode64(OpenSSL::Cipher::Cipher.new('aes-256-cbc').random_iv)
35
+ }
36
+
37
+ ForjLib.debug(2, "Writing '%s' key file" % key_file)
38
+ File.open(key_file, 'w') do |out|
39
+ out.write(Base64::encode64(entr.to_yaml))
40
+ end
41
+ else
42
+ ForjLib.debug(2, "Loading '%s' key file" % key_file)
43
+ encoded_key = IO.read(key_file)
44
+ entr = YAML.load(Base64::decode64(encoded_key))
45
+ end
46
+
47
+ enc_value = sDefault
48
+
49
+ if not enc_value.nil?
50
+ begin
51
+ value_hidden = '*' * Encryptor.decrypt(
52
+ :value => Base64::strict_decode64(enc_value),
53
+ :key => entr[:key],
54
+ :iv => Base64::strict_decode64(entr[:iv]),
55
+ :salt => entr[:salt]
56
+ ).length
57
+ rescue => e
58
+ Logging.error("Unable to decrypt your %s. You will need to re-enter it." % sDesc)
59
+ enc_value = ""
60
+ else
61
+ value_hidden="[%s]" % value_hidden
62
+ Logging.message("%s is already set. If you want to keep it, just press Enter" % [sDesc])
63
+ end
64
+ else
65
+ value_hidden = ""
66
+ end
67
+
68
+ value_free = ""
69
+ while value_free == ""
70
+ # ask for encrypted data.
71
+ value_free = ask("Enter %s: [%s]" % [sDesc, value_hidden]) do |q|
72
+ q.echo = '*'
73
+ end
74
+ if value_free == "" and enc_value
75
+ value_free = Encryptor.decrypt(
76
+ :value => Base64::strict_decode64(enc_value),
77
+ :key => entr[:key],
78
+ :iv => Base64::strict_decode64(entr[:iv]),
79
+ :salt => entr[:salt]
80
+ )
81
+ else
82
+ Logging.message("%s cannot be empty." % sDesc) if value_free == ""
83
+ end
84
+ end
85
+ enc_value = Base64::strict_encode64(
86
+ Encryptor.encrypt(
87
+ :value => value_free,
88
+ :key => entr[:key],
89
+ :iv => Base64::strict_decode64(entr[:iv]),
90
+ :salt => entr[:salt]
91
+ )
92
+ )
93
+ end
94
+
95
+ def _ask(sDesc, sDefault, rValidate, bEncrypted, bRequired)
96
+ if bEncrypted
97
+ value = _ask_encrypted(sDesc, sDefault)
98
+ if bRequired and value == ""
99
+ say "%sThis information is required!%s" % [ANSI.bold, ANSI.clear]
100
+ while value == ""
101
+ value = _ask_encrypted(sDesc, sDefault)
102
+ end
103
+ end
104
+ else
105
+ value = ask('Enter %s:' % [sDesc]) do |q|
106
+ q.default = sDefault unless sDefault.nil?
107
+ q.validate = rValidate unless rValidate.nil?
108
+ end
109
+ if bRequired and value == ""
110
+ say "%sThis information is required!%s" % [ANSI.bold, ANSI.clear]
111
+ while value == ""
112
+ value = ask('Enter %s:[%s]' % [sDesc, sDefault]) do |q|
113
+ q.default = sDefault unless sDefault.nil?
114
+ q.validate = rValidate unless rValidate.nil?
115
+ end
116
+ end
117
+ end
118
+ end
119
+ value.to_s
120
+ end
121
+
122
+ # return Object data meta data.
123
+ def _get_meta_data(sKey)
124
+
125
+ hMetaDefault = ForjDefault.get_meta(sKey)
126
+ return nil if hMetaDefault.nil?
127
+ hMetaDefault = hMetaDefault.clone
128
+
129
+ sSection = ForjDefault.get_meta_section(sKey)
130
+ return hMetaDefault if sSection.nil?
131
+ hMeta = rhGet(@@meta_data, sSection, sKey)
132
+ return hMetaDefault if hMeta.nil?
133
+
134
+ hMetaDefault.merge!(hMeta)
135
+ end
136
+
137
+ def _return_map(sCloudObj, oControlerObject)
138
+ return nil if oControlerObject.nil?
139
+
140
+ attr_value = {}
141
+
142
+ pProc = rhGet(@@meta_obj, sCloudObj, :lambdas, :get_attr_e)
143
+ bController = rhGet(@@meta_obj, sCloudObj, :options, :controller)
144
+ return nil if not pProc and not bController
145
+
146
+ hMap = rhGet(@@meta_obj, sCloudObj, :returns)
147
+ hMap.each { |key, map|
148
+ oKeyPath = KeyPath.new(key)
149
+ oMapPath = KeyPath.new(map)
150
+ next if not map
151
+ if pProc
152
+ ForjLib::debug(4, "Calling process function '%s' to retrieve/map Controller object '%s' data " % [pProc, sCloudObj])
153
+ controller_attr_value = @oForjProcess.method(pProc).call(sCloudObj, oControlerObject)
154
+ else
155
+ ForjLib::debug(4, "Calling controller function 'get_attr' to retrieve/map Controller object '%s' data " % [sCloudObj])
156
+ controller_attr_value = @oProvider.get_attr(oControlerObject, oMapPath.aTree) if bController
157
+ end
158
+
159
+ hValueMapping = rhGet(@@meta_obj, sCloudObj, :value_mapping, oKeyPath.sFullPath)
160
+ if hValueMapping and not controller_attr_value.nil?
161
+ hValueMapping.each { | map_key, map_value |
162
+ if controller_attr_value == map_value
163
+ rhSet(attr_value, map_key ,oKeyPath.aTree)
164
+ ForjLib::debug(5, "Object '%s' value mapped '%s': '%s' => '%s'" % [sCloudObj, oKeyPath.aTree, controller_attr_value, map_value])
165
+ break
166
+ end
167
+ }
168
+ raise ForjError.new(), "'%s.%s': No controller value mapping for '%s'." % [sCloudObj, oKeyPath.sKey, controller_attr_value] if attr_value.nil?
169
+ else
170
+ ForjLib::debug(5, "Object '%s' value '%s' extracted: '%s'" % [sCloudObj, oKeyPath.aTree, controller_attr_value])
171
+ rhSet(attr_value, controller_attr_value ,oKeyPath.aTree)
172
+ end
173
+ }
174
+ attr_value
175
+ end
176
+
177
+ def _build_data(sCloudObj, oParam, oKeyPath, hParams, bController = false)
178
+
179
+ sKey = oKeyPath.sKey
180
+ sDefault = rhGet(hParams, :default_value)
181
+ if rhExist?(hParams, :extract_from) == 1
182
+ value = oParam[hParams[:extract_from]]
183
+ end
184
+ value = @oForjConfig.get(sKey, sDefault) if not value
185
+
186
+ if bController
187
+ hValueMapping = rhGet(@@meta_obj, sCloudObj, :value_mapping, oKeyPath.sFullPath)
188
+
189
+ # Mapping from Object/data definition
190
+ if hValueMapping
191
+ raise ForjError.new(), "'%s.%s': No value mapping for '%s'" % [sCloudObj, sKey, value] if rhExist?(hValueMapping, value) != 1
192
+ value = hValueMapping[value]
193
+ # Will be moved to the setup section or while setting it for a controller attached account.
194
+ #~ else
195
+ #~ # Or mapping from Config/data definition
196
+ #~ section = ForjDefault.get_meta_section(sKey)
197
+ #~ section = :runtime if section.nil?
198
+ #~ hValueMapping = rhGet(@@meta_data, section, sKey, :value_mapping)
199
+ #~ if hValueMapping
200
+ #~ raise ForjError.new(), "'%s.%s': No Config value mapping for '%s'" % [section, sKey, value] if rhExist?(hValueMapping, value) != 1
201
+ #~ value = hValueMapping[value]
202
+ #~ end
203
+ end
204
+ if rhExist?(hParams, :mapping) == 1
205
+ # NOTE: if mapping is set, the definition subtree
206
+ # is ignored.
207
+ # if key map to mykey
208
+ # [:section1][subsect][key] = value
209
+ # oParam => [:hdata][mykey] = value
210
+ # not oParam => [:hdata][:section1][subsect][mykey] = value
211
+ oParam[:hdata][rhGet(hParams, :mapping)] = value
212
+ end
213
+ end
214
+ oParam[oKeyPath.aTree] = value
215
+ end
216
+
217
+ def _get_object_params(sCloudObj, sEventType, fname, bController = false)
218
+
219
+ oParams = ObjectData.new(not(bController)) # hdata is built for controller. ie, ObjectData is NOT internal.
220
+
221
+ hTopParams= rhGet(@@meta_obj,sCloudObj, :params)
222
+ hkeyPaths = rhGet(hTopParams, :keys)
223
+ raise ForjError.new(), "'%s' Object data needs not set. Forgot obj_needs?" % [sCloudObj] if hkeyPaths.nil?
224
+
225
+ hkeyPaths.each { | sKeypath, hParams|
226
+ next if not hParams[:for].include?(sEventType)
227
+ oKeyPath = KeyPath.new(sKeypath)
228
+ sKey = oKeyPath.sKey
229
+ case hParams[:type]
230
+ when :data
231
+ _build_data(sCloudObj, oParams, oKeyPath, hParams, bController)
232
+ when :CloudObject
233
+ #~ if hParams[:required] and rhExist?(@CloudData, sKey, :object) != 2
234
+ if hParams[:required] and @ObjectData.type?(sKey) != :DataObject
235
+ raise ForjError.new(), "Object '%s/%s' is not defined. '%s' requirement failed." % [ self.class, sKey, fname]
236
+ end
237
+ if @ObjectData.exist?(sKey)
238
+ oParams.add(@ObjectData[sKey, :ObjectData])
239
+ else
240
+ ForjLib::debug(2, "The optional '%s' was not loaded" % sKey)
241
+ end
242
+ else
243
+ raise ForjError.new(), "Undefined ObjectData '%s'." % [ hParams[:type]]
244
+ end
245
+ }
246
+ oParams
247
+ end
248
+
249
+ def _get_controller_map_value(keypath, sProcessValue)
250
+ section = ForjDefault.get_meta_section(sData)
251
+ section = :runtime if section.nil?
252
+ oKeypath = KeyPath.new(keypath)
253
+ sKeyPath = oKeypath.sKeyPath
254
+ return nil if rhExist?(@@meta_data, section, sKeyPath, :controller, sProcessValue) != 4
255
+ rhGet(@@meta_data, section, sKeyPath, :controller, sProcessValue)
256
+ end
257
+
258
+ def _get_process_map_value(keypath, sControllerValue)
259
+ section = ForjDefault.get_meta_section(sData)
260
+ section = :runtime if section.nil?
261
+ oKeypath = KeyPath.new(keypath)
262
+ sKeyPath = oKeypath.sKeyPath
263
+ return nil if rhExist?(@@meta_data, section, sKeyPath, :process, sControllerValue) != 4
264
+ rhGet(@@meta_data, section, sKeyPath, :process, sControllerValue)
265
+ end
266
+
267
+ def _check_required(sCloudObj, sEventType, fname)
268
+ aCaller = caller
269
+ aCaller.pop
270
+
271
+ oObjMissing=[]
272
+
273
+ hTopParams= rhGet(@@meta_obj,sCloudObj, :params)
274
+ hkeyPaths = rhGet(hTopParams, :keys)
275
+ raise ForjError.new(), "'%s' Object data needs not set. Forgot obj_needs?" % [sCloudObj] if hkeyPaths.nil?
276
+
277
+ hkeyPaths.each { | sKeypath, hParams|
278
+ next if not hParams[:for].include?(sEventType)
279
+ oKeyPath = KeyPath.new(sKeypath)
280
+
281
+ sKey = oKeyPath.sKey
282
+ case hParams[:type]
283
+ when :data
284
+ sDefault = rhGet(hParams, :default_value)
285
+ if hParams[:required]
286
+ if hParams.key?(:extract_from)
287
+ if not @ObjectData.exist?(hParams[:extract_from])
288
+ raise ForjError.new(), "key '%s' was not extracted from '%s'. '%s' requirement failed." % [ sKey, hParams[:extract_from], fname], aCaller
289
+ end
290
+ elsif @oForjConfig.get(sKey, sDefault).nil?
291
+ sSection = ForjDefault.get_meta_section(sKey)
292
+ sSection = 'runtime' if not sSection
293
+ raise ForjError.new(), "key '%s/%s' is not set. '%s' requirement failed." % [ sSection, sKey, fname], aCaller
294
+ end
295
+ end
296
+ when :CloudObject
297
+ #~ if hParams[:required] and rhExist?(@CloudData, sKey, :object) != 2
298
+ if hParams[:required] and @ObjectData.type?(sKey) != :DataObject
299
+ oObjMissing << sKey
300
+ end
301
+ end
302
+ }
303
+ return oObjMissing
304
+ end
305
+
306
+ end
@@ -0,0 +1,311 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ # It requires Core objects to be defined + default ForjProcess functions.
19
+
20
+ require File.join($CORE_PROCESS_PATH, "global_process.rb")
21
+ require File.join($CORE_PROCESS_PATH, "network_process.rb")
22
+
23
+ # Define framework object on BaseDefinition
24
+ class BaseDefinition
25
+
26
+ # All objects used by this process are built from a Controller
27
+ process_default :use_controller => true
28
+
29
+ # predefined list of objects.
30
+ # Links between objects is not predefined. To do it, use needs declaration in your provider class.
31
+
32
+ # object to get list of services
33
+ # Defines Process handler to call
34
+ define_obj(:services,
35
+ {
36
+ :create_e => :connect
37
+ })
38
+ obj_needs :data, :auth_uri
39
+ obj_needs :data, :account_id
40
+ obj_needs :data, :account_key
41
+ obj_needs :data, :tenant
42
+
43
+ undefine_attribute :id # Do not return any predefined ID
44
+ undefine_attribute :name # Do not return any predefined NAME
45
+
46
+
47
+ # compute_connection
48
+ define_obj(:compute_connection,
49
+ {
50
+ :create_e => :connect # Will call ForjProcess connect
51
+ })
52
+ obj_needs :data, :account_id
53
+ obj_needs :data, :account_key
54
+ obj_needs :data, :auth_uri
55
+ obj_needs :data, :tenant
56
+ obj_needs :data, :compute
57
+
58
+ undefine_attribute :id # Do not return any predefined ID
59
+ undefine_attribute :name # Do not return any predefined NAME
60
+
61
+ # network_connection
62
+ define_obj(:network_connection,
63
+ {
64
+ :create_e => :connect
65
+ })
66
+ obj_needs :data, :account_id
67
+ obj_needs :data, :account_key
68
+ obj_needs :data, :auth_uri
69
+ obj_needs :data, :tenant
70
+ obj_needs :data, :network
71
+
72
+ undefine_attribute :id # Do not return any predefined ID
73
+ undefine_attribute :name # Do not return any predefined NAME
74
+
75
+ # ************************************ Network Object
76
+ # Identify the network
77
+
78
+ define_obj(:network,
79
+ :create_e => :forj_get_or_create_network,
80
+ :query_e => :forj_query_network,
81
+ :get_e => :forj_get_network,
82
+ :delete_e => :forj_delete_network
83
+ )
84
+ obj_needs :CloudObject, :network_connection
85
+ obj_needs :data, :network_name, { :for => [:create_e] }
86
+
87
+ obj_needs_optional
88
+ obj_needs :data, :subnetwork_name, { :for => [:create_e] }
89
+
90
+ def_query_attribute :external # true if network is external or not.
91
+
92
+ # ************************************ SubNetwork Object
93
+ # Identify subnetwork as part of network.
94
+ define_obj(:subnetwork, :nohandler => true)
95
+
96
+ obj_needs :CloudObject, :network_connection
97
+ obj_needs :CloudObject, :network
98
+
99
+ def_query_attribute :network_id
100
+
101
+ # ************************************ Port Object
102
+ # Identify port attached to network
103
+ define_obj :port, :nohandler => true
104
+
105
+ def_attribute :device_id
106
+
107
+ def_query_attribute :network_id
108
+ def_query_attribute :device_owner
109
+
110
+ # ************************************ Router Object
111
+ # Identify the router of a network.
112
+ define_obj(:router,
113
+ {
114
+ :create_e => :forj_get_or_create_router,
115
+ # :query_e => :forj_query_router,
116
+ # :get_e => :forj_get_router,
117
+ :update_e => :forj_update_router
118
+ # :delete_e => :forj_delete_router
119
+ })
120
+ obj_needs :CloudObject, :network_connection
121
+ obj_needs :CloudObject, :network, { :for => [:create_e] }
122
+ obj_needs :CloudObject, :subnetwork, { :for => [:create_e] }
123
+ obj_needs_optional
124
+ obj_needs :data, :router_name, { :for => [:create_e] }
125
+
126
+ def_attribute :gateway_network_id
127
+
128
+ # Identify an external network thanks to the network router.
129
+ define_obj(:external_network,
130
+ {
131
+ :create_e => :forj_get_or_create_ext_net,
132
+ :query_e => :forj_query_external_network
133
+ })
134
+
135
+ obj_needs :CloudObject, :network_connection
136
+ obj_needs :CloudObject, :router
137
+
138
+
139
+ # ************************************ Security groups Object
140
+ # Identify security_groups
141
+ define_obj(:security_groups,
142
+ {
143
+ :create_e => :forj_get_or_create_sg,
144
+ :query_e => :forj_query_sg,
145
+ :delete_e => :forj_delete_sg
146
+ })
147
+
148
+ obj_needs :CloudObject, :network_connection
149
+ obj_needs :data, :security_group, { :for => [:create_e] }
150
+ obj_needs_optional
151
+ obj_needs :data, :sg_desc, { :for => [:create_e] }
152
+
153
+ # ************************************ Security group rules Object
154
+ # Identify Rules attached to the security group
155
+ define_obj(:rule,
156
+ {
157
+ :create_e => :forj_get_or_create_rule,
158
+ :query_e => :forj_query_rule
159
+ # :delete_e => :forj_delete_rule
160
+ })
161
+
162
+ undefine_attribute :name # Do not return any predefined name attribute
163
+
164
+ obj_needs :CloudObject, :network_connection
165
+ obj_needs :CloudObject, :security_groups, { :for => [:create_e] }
166
+ obj_needs :data, :sg_id, { :for => [:create_e], :extract_from => [:security_groups, :attrs, :id] }
167
+ obj_needs :data, :dir, { :for => [:create_e] }
168
+ predefine_data_value :IN, { :desc => "Input NAT/firewall rule map type" }
169
+ predefine_data_value :OUT, { :desc => "Output NAT/firewall rule map type" }
170
+ obj_needs :data, :proto, { :for => [:create_e] }
171
+ obj_needs :data, :port_min, { :for => [:create_e] }
172
+ obj_needs :data, :port_max, { :for => [:create_e] }
173
+ obj_needs :data, :addr_map, { :for => [:create_e] }
174
+
175
+ # ************************************ keypairs Object
176
+ # Identify keypairs
177
+ define_obj(:keypairs,
178
+ {
179
+ :create_e => :forj_get_or_create_keypair,
180
+ :query_e => :forj_query_keypair
181
+ # :delete_e => :forj_delete_keypair
182
+ })
183
+
184
+ obj_needs :CloudObject, :compute_connection
185
+ obj_needs :data, :keypair_name, { :for => [:create_e] }
186
+ obj_needs :data, :keypair_path, { :for => [:create_e] }
187
+
188
+ def_attribute :public_key
189
+
190
+ # ************************************ Image Object
191
+ # Identify image
192
+ define_obj(:image,
193
+ {
194
+ :create_e => :forj_get_or_create_image,
195
+ :query_e => :forj_query_image
196
+ # :get_e => :forj_get_image
197
+ # :update_e => :forj_update_image
198
+ # :delete_e => :forj_delete_image
199
+ })
200
+
201
+ obj_needs :CloudObject, :compute_connection
202
+ obj_needs :data, :image_name, { :for => [:create_e] }
203
+
204
+ # ************************************ Flavor Object
205
+ # Identify flavor
206
+ define_obj(:flavor,
207
+ {
208
+ :create_e => :forj_get_or_create_flavor,
209
+ :query_e => :forj_query_flavor
210
+ # :get_e => :forj_get_flavor,
211
+ # :update_e => :forj_update_flavor,
212
+ # :delete_e => :forj_delete_flavor
213
+ })
214
+
215
+ obj_needs :CloudObject, :compute_connection
216
+ obj_needs :data, :flavor_name, { :for => [:create_e] }
217
+ # Cloud provider will need to map to one of those predefined flavors.
218
+ # limitation values may match exactly or at least ensure those limitation
219
+ # are under provider limitation
220
+ # ie, at least the CloudProcess limitation can less than the Cloud provider defines.
221
+ # CloudProcess EHD = 160, then Provider EHD = 200 is ok
222
+ # but Provider EHD = 150 is not ok.
223
+ predefine_data_value('tiny', { :desc => "VCU: 1, RAM:512M, HD:1G, EHD: 0G, Swap: 0G" })
224
+ predefine_data_value('xsmall', { :desc => "VCU: 1, RAM:1G, HD:10G, EHD: 10G, Swap: 0G" })
225
+ predefine_data_value('small', { :desc => "VCU: 2, RAM:2G, HD:30G, EHD: 10G, Swap: 0G" })
226
+ predefine_data_value('medium', { :desc => "VCU: 2, RAM:4G, HD:30G, EHD: 50G, Swap: 0G" })
227
+ predefine_data_value('large', { :desc => "VCU: 4, RAM:8G, HD:30G, EHD: 100G, Swap: 0G" })
228
+ predefine_data_value('xlarge', { :desc => "VCU: 8, RAM:16G, HD:30G, EHD: 200G, Swap: 0G" })
229
+
230
+ # ************************************ Internet network Object
231
+ # Define Internet network
232
+ #
233
+ # This object contains the logic to ensure the router's network has a gateway to the external network (internet)
234
+ # is capable to connect to internet
235
+ # And to create this connection if possible.
236
+
237
+ define_obj(:internet_network, :nohandler => true )
238
+
239
+ obj_needs :CloudObject, :external_network # External network to connect if needed.
240
+
241
+ # ************************************ SERVER Object
242
+ # Identify the server to use/build on the network/...
243
+ define_obj(:server,
244
+ {
245
+ :create_e => :forj_get_or_create_server,
246
+ :query_e => :forj_query_server,
247
+ :get_e => :forj_get_server
248
+ # :update_e => :forj_update_server,
249
+ # :delete_e => :forj_delete_server
250
+ })
251
+
252
+ obj_needs :CloudObject, :compute_connection
253
+ obj_needs :CloudObject, :flavor, { :for => [:create_e] }
254
+ obj_needs :CloudObject, :network, { :for => [:create_e] }
255
+ obj_needs :CloudObject, :security_groups, { :for => [:create_e] }
256
+ obj_needs :CloudObject, :keypairs, { :for => [:create_e] }
257
+ obj_needs :CloudObject, :image, { :for => [:create_e] }
258
+ obj_needs :data, :server_name, { :for => [:create_e] }
259
+
260
+ obj_needs_optional
261
+ obj_needs :data, :user_data, { :for => [:create_e] }
262
+ obj_needs :data, :meta_data, { :for => [:create_e] }
263
+
264
+ def_attribute :status
265
+ predefine_data_value :create, { :desc => "Server is creating." }
266
+ predefine_data_value :boot, { :desc => "Server is booting." }
267
+ predefine_data_value :active, { :desc => "Server is started." }
268
+ def_attribute :private_ip_address
269
+ def_attribute :public_ip_address
270
+
271
+ # ************************************ SERVER Addresses Object
272
+ # Object representing the list of IP addresses attached to a server.
273
+ define_obj(:public_ip,
274
+ :create_e => :forj_get_or_assign_public_address,
275
+ :query_e => :forj_query_public_address
276
+ # :get_e => :forj_get_address
277
+ # :update_e => :forj_update_address
278
+ # :delete_e => :forj_delete_address
279
+ )
280
+
281
+ obj_needs :CloudObject, :compute_connection
282
+ obj_needs :CloudObject, :server
283
+
284
+ def_attribute :server_id
285
+ def_attribute :public_ip
286
+ undefine_attribute :name # No name to extract
287
+
288
+ # ************************************ SERVER Console Object
289
+ # Object representing the console log attached to a server
290
+
291
+ define_obj(:server_log,
292
+ {
293
+ :get_e => :forj_get_server_log
294
+ })
295
+
296
+ obj_needs :CloudObject, :server
297
+ obj_needs :data, :log_lines
298
+ undefine_attribute :name
299
+ undefine_attribute :id
300
+ def_attribute :output
301
+
302
+ # ************************************ Internet SERVER Object
303
+ # internet server is a server connected to the internet network.
304
+ define_obj(:internet_server, :nohandler => true )
305
+
306
+ obj_needs :CloudObject, :internet_network
307
+ obj_needs :CloudObject, :server
308
+ obj_needs :CloudObject, :public_ip
309
+
310
+
311
+ end