tdl 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,133 @@
1
+ #!/usr/bin/ruby
2
+ # Utility to proxy a tdl to cloud instance / image services
3
+ #
4
+ # Part of the Aeolus suite http://aeolusproject.org
5
+ # Licensed under the MIT license
6
+ # Copyright (C) 2012 Red Hat, Inc.
7
+ # Written By Mo Morsi <mmorsi@redhat.com>
8
+ #
9
+ ###########################################################
10
+
11
+ require 'thor'
12
+ require 'yaml'
13
+ require 'colored'
14
+ require 'tempfile'
15
+ require 'nokogiri'
16
+
17
+ VERSION = "0.0.2"
18
+
19
+ class TDLApply < Thor
20
+ desc "instance", "create a new instance from the tdl"
21
+ def instance(tdl)
22
+ # get cloud config
23
+ config = get_config
24
+
25
+ # convert tdl to etdl
26
+ etdl = `tdl-convert.rb convert #{tdl}`
27
+
28
+ # swap config into etdl
29
+ xml = Nokogiri::XML(etdl)
30
+ xml.xpath('/template/cloud/type').first.content = config['type']
31
+ xml.xpath('/template/cloud/provider').first.content = config['provider']
32
+ xml.xpath('/template/cloud/username').first.content = config['username']
33
+ xml.xpath('/template/cloud/password').first.content = config['password']
34
+ xml.xpath('/template/cloud/image').first.content = config['image']
35
+ xml.xpath('/template/cloud/keyname').first.content = config['keyname']
36
+ xml.xpath('/template/cloud/ssh_cmd').first.content = config['ssh_cmd']
37
+ xml.xpath('/template/cloud/scp_cmd').first.content = config['scp_cmd']
38
+ etdl = xml.to_s
39
+
40
+ tetdl = Tempfile.new(tdl)
41
+ tetdl.write etdl
42
+ tetdl.close
43
+
44
+ # launch etdl
45
+ puts 'Launching tdl...'
46
+ puts `tdl-launch.rb launch #{tetdl.path}`
47
+ end
48
+
49
+ desc "image", "create a new image from the tdl"
50
+ def image(tdl)
51
+ # TODO ensure euid of this process is 0
52
+ config = get_config
53
+
54
+ # convert config to imagefactory cloud credentials to provider/credentials config
55
+ provider_config, credential_config = config2imgfac(config)
56
+
57
+ # build tdl
58
+ puts 'Building tdl...'
59
+
60
+ base_output = `imagefactory base_image #{tdl}`
61
+ puts base_output
62
+
63
+ base_output =~ /UUID: (.*)\n/
64
+ base_image = $1
65
+
66
+ target_output = `imagefactory target_image --id #{base_image} #{config[:type]}`
67
+ puts target_output
68
+
69
+ target_output =~ /UUID: (.*)\n/
70
+ target_image = $1
71
+
72
+ provider_output `imagefactory provider_image --id #{target_image} #{config[:type]} #{provider_config.path} #{credential_config.path}`
73
+ puts provider_output
74
+ end
75
+
76
+ map "--server" => :__server
77
+ desc "--server", "Run Server"
78
+ def __server
79
+ # TODO use sinatra to listen for rest requests on /images /instances w/ tdl
80
+ end
81
+
82
+ map "--version" => :__version
83
+ desc "--version", "Version information"
84
+ def __version
85
+ say "tdl-tools apply #{VERSION}"
86
+ end
87
+
88
+ desc "help", "Command usage and other information"
89
+ def help
90
+ say 'Proxy a tdl to cloud instance / image services'
91
+ super
92
+ end
93
+
94
+ private
95
+
96
+ def get_config
97
+ config = {}
98
+ ["/etc/tdl-config.yml", "~/.tdl-config.yml", "./tdl-config.yml"].each { |c|
99
+ begin
100
+ config.merge!(YAML.load(open(File.expand_path(c))))
101
+ puts "Loaded config #{c}".green
102
+ rescue Exception => e
103
+ puts "Cannot load config #{c}".red
104
+ end
105
+ }
106
+ config
107
+ end
108
+
109
+ def config2imgfac(config)
110
+ provider_config = Tempfile.new('provider_config')
111
+ credentials_config = Tempfile.new('credentials_config')
112
+
113
+ if config['type'] == 'ec2'
114
+ #provider_config.write
115
+ credentials_config.write "<provider_credentials><ec2_credentials><account_number>#{config['account']}</account_number><access_key>#{config['access_key']}</access_key><secret_access_key>#{config['secret_access_key']}</secret_access_key><certificate>#{config['certificate']}</certificate><key>#{config['key']}</key></ec2_credentials></provider_credentials>"
116
+ elsif config['type'] == 'openstack'
117
+ provider_config.write "{ 'glance-host' : '#{config['glance_host']}', 'glance_port' : '#{config['glance_port']}' }";
118
+ credentials_config.write "<provider_credentials><openstack_credentials><username>#{config['username']}</username><password>#{config['password']}</password><strategy>#{config['strategy']}</strategy><auth_url>#{config['auth_url']}</auth_url></openstack_credentials></provider_credentials>"
119
+ elsif config['type'] == 'rhevm'
120
+ provider_config.write "{ 'api-url' : '#{config['api_url']}', 'username' : '#{config['username']}', 'password' : '#{config['password']}', 'nfs-path' : '#{config['nfs_path']}', 'nfs-host' : '#{config['nfs_host']}', 'cluster' : '#{config['cluster']}', 'timeout' : '#{config['timeout']}' }";
121
+ credentials_config.write "<provider_credentials><rhevm_credentials><username>#{config['username']}</username><password>#{config['password']}</password></rhevm_credentials></provider_credentials>"
122
+ elsif config['type'] == 'vsphere'
123
+ provider_config.write "{ 'api-url' : '#{config['api_url']}', 'username' : '#{config['username']}', 'password' : '#{config['password']}', 'datastore' : '#{config['datastore']}', 'computer_resource' : '#{config['compute_resource']}', 'network_name' : '#{config['network_name']}' }";
124
+ credentials_config.write "<provider_credentials><vsphere_credentials><username>#{config['username']}</username><password>#{config['password']}</password></vsphere_credentials></provider_credentials>"
125
+ end
126
+
127
+ provider_config.close
128
+ credentials_config.close
129
+ [provider_config, credentials_config]
130
+ end
131
+ end
132
+
133
+ TDLApply.start(ARGV)
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/ruby
2
+ # Utility to create a new tdl-config file in the user's home dir
3
+ #
4
+ # Part of the Aeolus suite http://aeolusproject.org
5
+ # Licensed under the MIT license
6
+ # Copyright (C) 2012 Red Hat, Inc.
7
+ # Written By Mo Morsi <mmorsi@redhat.com>
8
+ #
9
+ ###########################################################
10
+
11
+ require 'thor'
12
+ require 'yaml'
13
+ require 'colored'
14
+
15
+ require 'tdl_gem_path'
16
+
17
+ VERSION = "0.0.2"
18
+
19
+ class TDLConfig < Thor
20
+ desc "create", "create a new tdl config file"
21
+ method_options :interactive => :boolean
22
+ def create
23
+ config = get_config
24
+ config.merge!(run_interactive) if options[:interactive]
25
+ File.open(File.expand_path('~/.tdl-config.yml'), 'w') { |f| f.write config.to_yaml }
26
+ FileUtils.chmod(0600, File.expand_path('~/.tdl-config.yml'))
27
+ puts '~/.tdl-config.yml created'.green
28
+ puts 'Note ~/.tdl-config.yml may contain cloud credentials, ensure to properly secure'.bold
29
+ end
30
+
31
+ map "--version" => :__version
32
+ desc "--version", "Version information"
33
+ def __version
34
+ say "tdl-tools config #{VERSION}"
35
+ end
36
+
37
+ desc "help", "Command usage and other information"
38
+ def help
39
+ say 'Create a new tdl config file'
40
+ super
41
+ end
42
+
43
+ private
44
+ def get_config
45
+ config = {}
46
+ [TDLTools.gem_path + 'tdl-config.yml', '/etc/tdl-config.yml',
47
+ '~/.tdl-config.yml', './tdl-config.yml'].each { |c|
48
+ begin
49
+ config.merge!(YAML.load(open(File.expand_path(c))))
50
+ rescue Exception => e
51
+ end
52
+ }
53
+ config
54
+ end
55
+
56
+ def run_interactive(output, options = {})
57
+ end
58
+ end
59
+
60
+ TDLConfig.start(ARGV)
@@ -11,7 +11,7 @@
11
11
  require 'thor'
12
12
  require 'nokogiri'
13
13
 
14
- VERSION = "0.1.0"
14
+ VERSION = "0.0.2"
15
15
 
16
16
  class TDLConvert < Thor
17
17
  desc "convert", "convert tdl to/from etdl"
@@ -14,16 +14,16 @@ require 'nokogiri'
14
14
  # use fedora api to verify packages
15
15
  require 'pkgwat'
16
16
 
17
- VERSION = "0.1.0"
18
- SAMPLE_TDL = 'data/sample.tdl'
19
- SAMPLE_ETDL = 'data/sample.etdl'
17
+ require 'tdl_gem_path'
18
+
19
+ VERSION = "0.0.2"
20
20
 
21
21
  class TDLCreate < Thor
22
22
  desc "tdl", "create a new TDL"
23
23
  method_options :interactive => :boolean
24
24
  method_options :verify => :boolean
25
25
  def tdl
26
- output = File.read(SAMPLE_TDL)
26
+ output = get_sample_tdl
27
27
  output = run_interactive(output, options) if options[:interactive]
28
28
  puts output
29
29
  end
@@ -32,7 +32,7 @@ class TDLCreate < Thor
32
32
  method_options :interactive => :boolean
33
33
  method_options :verify => :boolean
34
34
  def etdl
35
- output = File.read(SAMPLE_ETDL)
35
+ output = get_sample_etdl
36
36
  output = run_interactive(output, options) if options[:interactive]
37
37
  puts output
38
38
  end
@@ -94,6 +94,29 @@ class TDLCreate < Thor
94
94
  output = xml.to_s
95
95
  end
96
96
 
97
+ private
98
+ def get_sample_tdl
99
+ tdl = nil
100
+ [TDLTools.gem_path + 'data/sample.tdl', './data/sample.tdl'].each { |t|
101
+ begin
102
+ tdl = File.read(t)
103
+ rescue Exception => e
104
+ end
105
+ }
106
+ tdl
107
+ end
108
+
109
+ def get_sample_etdl
110
+ etdl = nil
111
+ [TDLTools.gem_path + 'data/sample.etdl', './data/sample.etdl'].each { |t|
112
+ begin
113
+ etdl = File.read(t)
114
+ rescue Exception => e
115
+ end
116
+ }
117
+ etdl
118
+ end
119
+
97
120
  end
98
121
 
99
122
  TDLCreate.start(ARGV)
@@ -18,7 +18,7 @@
18
18
  #
19
19
  ###########################################################
20
20
 
21
- require 'pp'
21
+ require 'thor'
22
22
  require 'colored'
23
23
  require 'nokogiri'
24
24
  require 'tempfile'
@@ -26,26 +26,39 @@ require 'tempfile'
26
26
  require 'etdl'
27
27
  require 'etdl_processor'
28
28
 
29
- ###############################################################
30
- # Read in configuration from cmd line and xml file
29
+ VERSION = "0.0.2"
31
30
 
32
- if ARGV.size != 1
33
- puts "Usage: tdl-launch.rb <path-to-tdl>".red
34
- exit 1
35
- end
31
+ class TDLLaunch < Thor
32
+ desc "launch [path-to-etdl]", "Launch etdl specified on the command line"
33
+ def launch(path)
34
+ say "Launching eTDL #{path}".bold
36
35
 
37
- ETDL = ARGV.first
36
+ unless File.readable?(path)
37
+ puts "eTDL #{path} is not readable".red
38
+ exit 1
39
+ end
38
40
 
39
- unless File.readable?(ETDL)
40
- puts "eTDL #{ETDL} is not readable".red
41
- exit 1
42
- end
41
+ doc = Nokogiri::XML(open(path))
42
+ etdl = TDLTools::ETDL.parse(doc)
43
+
44
+ launch = ETDLProcessor.new
43
45
 
44
- doc = Nokogiri::XML(open(ARGV.first))
45
- etdl = TDLTools::ETDL.parse(doc)
46
+ etdl.process(launch)
46
47
 
47
- launch = ETDLProcessor.new
48
+ puts "Done!".bold
49
+ end
48
50
 
49
- etdl.process(launch)
51
+ map "--version" => :__version
52
+ desc "--version", "Version information"
53
+ def __version
54
+ say "tdl-tools launch #{VERSION}"
55
+ end
56
+
57
+ desc "help", "Command usage and other information"
58
+ def help
59
+ say 'Launch an eTDL'
60
+ super
61
+ end
62
+ end
50
63
 
51
- puts "Done!".bold
64
+ TDLLaunch.start(ARGV)
@@ -12,16 +12,16 @@ require 'thor'
12
12
  require 'nokogiri'
13
13
  require 'colored'
14
14
 
15
- VERSION = "0.1.0"
16
- TDL_RNG = 'data/tdl.rng'
17
- ETDL_RNG = 'data/etdl.rng'
15
+ require 'tdl_gem_path'
16
+
17
+ VERSION = "0.0.2"
18
18
 
19
19
  class TDLVerify < Thor
20
20
  desc "verify [path-to-tdl]", "Verify the tdl (or etdl) specified on the command line"
21
21
  def verify(path)
22
22
  say "Validating (e)TDL".bold
23
- rng = (File.extname(path) == ".etdl" ? ETDL_RNG : TDL_RNG)
24
- xsd = Nokogiri::XML::RelaxNG(File.read(rng))
23
+ rng = get_rng_for(path)
24
+ xsd = Nokogiri::XML::RelaxNG(rng)
25
25
  doc = Nokogiri::XML(File.open(path))
26
26
  errs = xsd.validate(doc)
27
27
  if errs.empty?
@@ -49,6 +49,19 @@ class TDLVerify < Thor
49
49
  say 'Verify a TDL'
50
50
  super
51
51
  end
52
+
53
+ private
54
+ def get_rng_for(path)
55
+ rng = nil
56
+ rngf = (File.extname(path) == ".etdl" ? 'etdl.rng' : 'tdl.rng')
57
+ dirs = [TDLTools.gem_path + 'data/', './'].each { |d|
58
+ begin
59
+ rng = File.read(d + rngf)
60
+ rescue Exception => e
61
+ end
62
+ }
63
+ rng
64
+ end
52
65
  end
53
66
 
54
- TDLVerify.start(ARGV) if __FILE__ == $0
67
+ TDLVerify.start(ARGV)
@@ -0,0 +1,311 @@
1
+ <?xml version="1.0"?>
2
+ <!-- A Relax NG schema for the TDL (template description language) format -->
3
+ <grammar xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
4
+ <start>
5
+ <ref name='template'/>
6
+ </start>
7
+
8
+ <define name='template'>
9
+ <element name='template'>
10
+ <optional>
11
+ <attribute name='version'>
12
+ <choice>
13
+ <value>1.0</value>
14
+ </choice>
15
+ </attribute>
16
+ </optional>
17
+ <interleave>
18
+ <element name='name'>
19
+ <text/>
20
+ </element>
21
+ <element name='cloud'>
22
+ <interleave>
23
+ <element name='type'>
24
+ <text/>
25
+ </element>
26
+ <element name='provider'>
27
+ <text/>
28
+ </element>
29
+ <element name='username'>
30
+ <text/>
31
+ </element>
32
+ <element name='password'>
33
+ <text/>
34
+ </element>
35
+ <element name='image'>
36
+ <text/>
37
+ </element>
38
+ <element name='keyname'>
39
+ <text/>
40
+ </element>
41
+ <element name='ssh_cmd'>
42
+ <text/>
43
+ </element>
44
+ <element name='scp_cmd'>
45
+ <text/>
46
+ </element>
47
+ </interleave>
48
+ </element>
49
+ <element name='os'>
50
+ <interleave>
51
+ <element name='name'>
52
+ <text/>
53
+ </element>
54
+ <element name='version'>
55
+ <text/>
56
+ </element>
57
+ <element name='arch'>
58
+ <choice>
59
+ <value>i386</value>
60
+ <value>x86_64</value>
61
+ </choice>
62
+ </element>
63
+ <element name='install'>
64
+ <choice>
65
+ <ref name='url'/>
66
+ <ref name='iso'/>
67
+ </choice>
68
+ </element>
69
+ <optional>
70
+ <element name='rootpw'>
71
+ <text/>
72
+ </element>
73
+ </optional>
74
+ <optional>
75
+ <element name='key'>
76
+ <text/>
77
+ </element>
78
+ </optional>
79
+ </interleave>
80
+ </element>
81
+ <optional>
82
+ <element name='description'>
83
+ <text/>
84
+ </element>
85
+ </optional>
86
+ <optional>
87
+ <element name='packages'>
88
+ <zeroOrMore>
89
+ <element name='package'>
90
+ <attribute name='name'>
91
+ <text/>
92
+ </attribute>
93
+ <interleave>
94
+ <optional>
95
+ <element name='repository'>
96
+ <text/>
97
+ </element>
98
+ </optional>
99
+ <optional>
100
+ <element name='file'>
101
+ <text/>
102
+ </element>
103
+ </optional>
104
+ <optional>
105
+ <element name='arguments'>
106
+ <text/>
107
+ </element>
108
+ </optional>
109
+ </interleave>
110
+ </element>
111
+ </zeroOrMore>
112
+ </element>
113
+ </optional>
114
+ <optional>
115
+ <element name='files'>
116
+ <zeroOrMore>
117
+ <element name='file'>
118
+ <attribute name='name'>
119
+ <text/>
120
+ </attribute>
121
+ <choice>
122
+ <ref name='rawtype'/>
123
+ <ref name='base64_or_emptytype'/>
124
+ </choice>
125
+ </element>
126
+ </zeroOrMore>
127
+ </element>
128
+ </optional>
129
+ <optional>
130
+ <element name='commands'>
131
+ <zeroOrMore>
132
+ <element name='command'>
133
+ <attribute name='name'>
134
+ <text/>
135
+ </attribute>
136
+ <optional>
137
+ <attribute name='position'>
138
+ <ref name='number'/>
139
+ </attribute>
140
+ </optional>
141
+ <choice>
142
+ <ref name='rawtype'/>
143
+ <ref name='base64type'/>
144
+ </choice>
145
+ </element>
146
+ </zeroOrMore>
147
+ </element>
148
+ </optional>
149
+ <optional>
150
+ <element name='repositories'>
151
+ <zeroOrMore>
152
+ <element name='repository'>
153
+ <attribute name='name'>
154
+ <text/>
155
+ </attribute>
156
+ <interleave>
157
+ <element name='url'>
158
+ <text/>
159
+ </element>
160
+ <optional>
161
+ <element name='signed'>
162
+ <ref name='bool'/>
163
+ </element>
164
+ </optional>
165
+ <optional>
166
+ <element name='persisted'>
167
+ <ref name='bool'/>
168
+ </element>
169
+ </optional>
170
+ <optional>
171
+ <interleave>
172
+ <element name='clientcert'>
173
+ <text/>
174
+ </element>
175
+ <optional>
176
+ <element name='clientkey'>
177
+ <text/>
178
+ </element>
179
+ </optional>
180
+ </interleave>
181
+ </optional>
182
+ <optional>
183
+ <interleave>
184
+ <element name='sslverify'>
185
+ <ref name='bool'/>
186
+ </element>
187
+ <element name='cacert'>
188
+ <text/>
189
+ </element>
190
+ </interleave>
191
+ </optional>
192
+ </interleave>
193
+ </element>
194
+ </zeroOrMore>
195
+ </element>
196
+ </optional>
197
+ <optional>
198
+ <element name='disk'>
199
+ <element name='size'>
200
+ <ref name='number'/>
201
+ </element>
202
+ </element>
203
+ </optional>
204
+ <optional>
205
+ <element name='verify'>
206
+ <zeroOrMore>
207
+ <element name='command'>
208
+ <attribute name='name'>
209
+ <text/>
210
+ </attribute>
211
+ </element>
212
+ </zeroOrMore>
213
+ </element>
214
+ </optional>
215
+ </interleave>
216
+ </element>
217
+ </define>
218
+
219
+ <define name='url'>
220
+ <attribute name='type'>
221
+ <value>url</value>
222
+ </attribute>
223
+ <element name='url'>
224
+ <text/>
225
+ </element>
226
+ </define>
227
+
228
+ <define name='iso'>
229
+ <attribute name='type'>
230
+ <value>iso</value>
231
+ </attribute>
232
+ <interleave>
233
+ <element name='iso'>
234
+ <text/>
235
+ </element>
236
+ <optional>
237
+ <choice>
238
+ <element name='md5sum'>
239
+ <text/>
240
+ </element>
241
+ <element name='sha1sum'>
242
+ <text/>
243
+ </element>
244
+ <element name='sha256sum'>
245
+ <text/>
246
+ </element>
247
+ </choice>
248
+ </optional>
249
+ </interleave>
250
+ </define>
251
+
252
+ <define name='bool'>
253
+ <choice>
254
+ <data type="string">
255
+ <param name="pattern">[Tt][Rr][Uu][Ee]</param>
256
+ </data>
257
+ <data type="string">
258
+ <param name="pattern">[Ff][Aa][Ll][Ss][Ee]</param>
259
+ </data>
260
+ <data type="string">
261
+ <param name="pattern">[Yy][Ee][Ss]</param>
262
+ </data>
263
+ <data type="string">
264
+ <param name="pattern">[Nn][Oo]</param>
265
+ </data>
266
+ </choice>
267
+ </define>
268
+
269
+ <define name='rawtype'>
270
+ <optional>
271
+ <attribute name='type'>
272
+ <value>raw</value>
273
+ </attribute>
274
+ </optional>
275
+ <text/>
276
+ </define>
277
+
278
+ <define name='base64'>
279
+ <data type="string">
280
+ <param name="pattern">[a-zA-Z0-9+/]+={0,2}</param>
281
+ </data>
282
+ </define>
283
+
284
+ <define name='base64_or_empty'>
285
+ <choice>
286
+ <ref name='base64'/>
287
+ <empty/>
288
+ </choice>
289
+ </define>
290
+
291
+ <define name='base64_or_emptytype'>
292
+ <attribute name='type'>
293
+ <value>base64</value>
294
+ </attribute>
295
+ <ref name='base64_or_empty'/>
296
+ </define>
297
+
298
+ <define name='base64type'>
299
+ <attribute name='type'>
300
+ <value>base64</value>
301
+ </attribute>
302
+ <ref name='base64'/>
303
+ </define>
304
+
305
+ <define name='number'>
306
+ <data type="string">
307
+ <param name="pattern">[0-9]*</param>
308
+ </data>
309
+ </define>
310
+
311
+ </grammar>