tdl 0.0.1 → 0.0.2

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,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>