xen-ruby 0.7

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.
data/README ADDED
@@ -0,0 +1,74 @@
1
+ A simple ruby module to admin xen instances
2
+ This gem includes a log mechanism (log4r) with various modes (DEBUG, INFO, WARN ...).
3
+
4
+
5
+ How to use it :
6
+
7
+ ###########################
8
+ # To get instance informations
9
+ instance = Xen::Instance.find_by_name(name)
10
+
11
+ # To get all instaces
12
+ puts Xen::Instance.all
13
+
14
+ ###########################
15
+ # To start an instance
16
+
17
+ instance.start(name)
18
+
19
+ # or
20
+ instance = Xen::Instance.find_by_name(name)
21
+ instance.start
22
+
23
+ # or
24
+ instance = Xen::Instance.new(name)
25
+ instance.start
26
+
27
+ ###########################
28
+ # To create a new instance
29
+ # attributes includes {:mem => "", :size => "", :name => "", :ip => "", :vcpus: => "",
30
+ # :arch => "", :dist => ""}
31
+ # mem = Memory
32
+ # size = HDD size
33
+ # name = Hostname
34
+ # ip = Ip address
35
+ # vcpus = Virtual cpu's
36
+ # arch = System architecture [i386|amd64]
37
+ # dist = distribution [lucid, hardy, etc.]
38
+ Xen::Instance.create(attributes)
39
+
40
+ ##########################
41
+ # Instance actions
42
+ instance = Xen::Instance.find_by_name(name)
43
+
44
+ # start
45
+ instance.start
46
+
47
+ # stop
48
+ instance.shutdown
49
+
50
+ # reboot
51
+ instance.reboot
52
+
53
+ # pause
54
+ instance.pause
55
+
56
+ # unpause
57
+ instance.unpause
58
+
59
+ # kill
60
+ instance.destroy
61
+
62
+
63
+
64
+ ##################################
65
+ Creating & installing the gem :
66
+
67
+ gem build xen.gemspec
68
+ sudo gem install xen-<version>.gem
69
+
70
+
71
+ todo:
72
+ - Xen::Instance.create have a small bug (timeout)
73
+ - Tests
74
+
data/Rakefile ADDED
@@ -0,0 +1,55 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
15
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
16
+ gem.name = "xen-ruby"
17
+ gem.homepage = "http://github.com/foexle/ruby-xen"
18
+ gem.license = "GPL"
19
+ gem.summary = %Q{simple gem to controle xen dom0}
20
+ gem.description = %Q{simple gem to controle xen dom0}
21
+ gem.email = "kraemer@avarteq.de"
22
+ gem.authors = ["Heiko Krämer","Clemens Kofler"]
23
+ gem.version = "#{version}"
24
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
25
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
26
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
27
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
28
+ end
29
+ Jeweler::RubygemsDotOrgTasks.new
30
+
31
+ require 'rake/testtask'
32
+ Rake::TestTask.new(:test) do |test|
33
+ test.libs << 'lib' << 'test'
34
+ test.pattern = 'test/**/test_*.rb'
35
+ test.verbose = true
36
+ end
37
+
38
+ require 'rcov/rcovtask'
39
+ Rcov::RcovTask.new do |test|
40
+ test.libs << 'test'
41
+ test.pattern = 'test/**/test_*.rb'
42
+ test.verbose = true
43
+ end
44
+
45
+ task :default => :test
46
+
47
+ require 'rake/rdoctask'
48
+ Rake::RDocTask.new do |rdoc|
49
+ version = File.exist?('VERSION') ? File.read('VERSION') : "0.7"
50
+
51
+ rdoc.rdoc_dir = 'rdoc'
52
+ rdoc.title = "xen-ruby #{version}"
53
+ rdoc.rdoc_files.include('README*')
54
+ rdoc.rdoc_files.include('lib/**/*.rb')
55
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.7
data/lib/log/logger.rb ADDED
@@ -0,0 +1,53 @@
1
+ require 'log4r'
2
+
3
+ module Log
4
+ # Singleton Class to logging debugging and error states in logfile
5
+ class Logger
6
+ attr_accessor :log
7
+
8
+
9
+ # Check if exists a logging class. If not i'll be create
10
+ # ==Params
11
+ # * +filename+ : Path and filename of logdatei
12
+ # * +log_level+ : Which loglevel are using
13
+ def self.log(options = {:log_level => 1}, filename = "/tmp/xen-gem.log")
14
+ if @log
15
+ return @log
16
+ else
17
+ initialize_logger(filename, options[:log_level])
18
+ return @log
19
+ end
20
+ end
21
+
22
+ # Initializing and configuring the logger object
23
+ def self.initialize_logger(file_name, log_level)
24
+ @log = Log4r::Logger.new("xen_log")
25
+
26
+ @log.outputters = Log4r::Outputter.stdout
27
+
28
+ file = Log4r::FileOutputter.new('fileOutputter', :filename => file_name, :trunc => true)
29
+
30
+
31
+ @log.add(file)
32
+ @log.level = self.convert_loglevel(log_level)
33
+ format = Log4r::PatternFormatter.new(:pattern => "[%l] %d :: %m")
34
+ file.formatter = format
35
+ end
36
+
37
+ private
38
+
39
+ # Converting loglevel configurations for log4r
40
+ def self.convert_loglevel(log_level)
41
+ case log_level
42
+ when 1
43
+ return Log4r::DEBUG
44
+ when 2
45
+ return Log4r::INFO
46
+ when 3
47
+ return Log4r::ERROR
48
+ else
49
+ return Log4r::INFO
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,50 @@
1
+ require 'log/logger'
2
+
3
+ module System
4
+ class Command
5
+ LEVEL_WARN = 1
6
+ LEVEL_FATAL = 2
7
+
8
+ attr_reader :command, :expected_exit_status, :message, :command_level, :output, :exit_status
9
+
10
+ class << self
11
+ def logger
12
+ @@logger ||= Log::Logger.log
13
+ end
14
+ end
15
+
16
+ def initialize(command, options = {})
17
+ @command = command
18
+ @expected_exit = options[:expected_exit_status] || 0
19
+ @message = options[:message] unless options[:message].nil? || options[:message].empty?
20
+ @command_level = options[:command_level] || LEVEL_WARN
21
+ end
22
+
23
+ def execute
24
+ @output = `#{command} 2>&1`
25
+ @exit_status = $?.exitstatus
26
+ log if error?
27
+ end
28
+
29
+ def error?
30
+ ![0, expected_exit_status].include?(exit_status)
31
+ end
32
+
33
+ def error_message
34
+ message || output
35
+ end
36
+
37
+ def log
38
+ case @command_level
39
+ when LEVEL_WARN: logger.warn(error_message)
40
+ when LEVEL_FATAL: logger.fatal(error_message)
41
+ end
42
+ end
43
+
44
+ def logger
45
+ self.class.logger
46
+ end
47
+
48
+
49
+ end
50
+ end
@@ -0,0 +1,194 @@
1
+ require 'log/logger'
2
+ require 'system/command'
3
+ require 'xen/server'
4
+ require 'xen/util'
5
+
6
+ # TODO extract sudo to be used as an option
7
+ module Xen
8
+ class Instance
9
+ STATE_RUNNING = 'r'
10
+ STATE_BLOCKED = 'b'
11
+ STATE_SHUTDOWN = 's'
12
+ STATE_CRASHED = 'c'
13
+ STATE_DYING = 'd'
14
+ STATE_PAUSED = 'p'
15
+
16
+ attr_accessor :dom_id, :name, :memory, :vcpus, :state, :time
17
+
18
+ class << self
19
+
20
+ # Gets all running instances on dom0
21
+ def all
22
+ get_all = System::Command.new("sudo xm list" , :command_level => 1)
23
+ get_all.execute
24
+ return [] unless get_all.exit_status == 0
25
+
26
+ instances_from_output(get_all.output)
27
+ end
28
+
29
+ # Gets an instance object
30
+ # ==Params:
31
+ # => +name+: Name of instance
32
+ def find_by_name(name)
33
+ find = System::Command.new("sudo xm list #{name}", :command_level => 1)
34
+ find.execute
35
+ instance_from_output(find.output.split("\n").last)
36
+ end
37
+ alias :[] :find_by_name
38
+
39
+ # Gets all attributs of an instance
40
+
41
+ def find_attributes_by_name(name)
42
+ find = System::Command.new("sudo xm list #{name}", :command_level => 1)
43
+ find.execute
44
+ attributes_from_output(find.output)
45
+ end
46
+
47
+ # Vars = :id, :name, :memory, :hdd, :cpus, :status
48
+ # Note: debootstrap installation is the slowest, better are copy in xen
49
+ def create(attributes = {})
50
+ logger.info("Creating new Xen instance with name #{attributes[:name]} ...")
51
+
52
+ exist_instance = find_by_name(attributes[:name])
53
+ if exist_instance
54
+ Logger.info("Running instance detected. Shutting down to create a new one")
55
+ exist_instance.shutdown
56
+ end
57
+
58
+ password = Xen::Util.generate_root_password
59
+
60
+ if password.exit_status == 0
61
+ command = <<-cmd.split("\n").map { |l| l.strip }.join(' ').squeeze(' ')
62
+ sudo xen-create-image --hostname=#{attributes[:name]} --ip=#{attributes[:ip]} --password=#{password[:stdout].strip}
63
+ --vcpus=#{attributes[:vcpus]} --memory=#{attributes[:memory]} --size=#{attributes[:size]}
64
+ --arch=#{attributes[:arch]} --dist=#{attributes[:dist]} --force &
65
+ cmd
66
+
67
+ create_image = System::Command.new(command, :command_level => 2)
68
+ create_image.execute
69
+ attributes.merge(:password => password.output.strip)
70
+ end
71
+ end
72
+
73
+ def start(name)
74
+ instance = new(name)
75
+ instance.start
76
+ return instance
77
+ end
78
+
79
+ def instances_from_output(output)
80
+ output.split("\n")[1..-1].map do |line|
81
+ instance_from_output(line)
82
+ end
83
+ end
84
+
85
+ def instance_from_output(output)
86
+ logger.debug("Finding #{output} ...")
87
+
88
+ attributes = attributes_from_output(output)
89
+ return unless attributes
90
+
91
+ Instance.new(attributes[:name], attributes) #:time => $6.strip)
92
+ end
93
+
94
+ def attributes_from_output(output)
95
+ return unless output.match(/(.*)\s+(\d+)\s+(\d+)\s+(\d+)\s+(.*?)\s+(\d+.\d)/)
96
+
97
+ { :name => $1.strip, :dom_id => $2.strip, :memory => $3.strip, :vcpus => $4.strip, :state => $5.strip.gsub("-","") }
98
+ end
99
+
100
+ def logger
101
+ @@logger ||= Log::Logger.log(:log_level => Xen::Server::LOG_LEVEL)
102
+ end
103
+ end
104
+
105
+
106
+
107
+
108
+
109
+ def initialize(name, options = {})
110
+ @name = name
111
+ @memory, @dom_id, @vcpus, @state, @time = options.values_at(:memory, :dom_id, :vcpus, :state, :time)
112
+ end
113
+
114
+ def start
115
+ start = System::Command.new("sudo xm create #{name}.cfg", :command_level => 2)
116
+ start.execute
117
+ update_info
118
+ end
119
+
120
+
121
+ def reboot
122
+ reboot = System::Command.new("sudo xm reboot #{dom_id}", :command_level => 2)
123
+ reboot.execute
124
+ end
125
+
126
+ def shutdown
127
+ shutdown = System::Command.new("sudo xm shutdown #{dom_id}", :command_level => 2)
128
+ shutdown.execute
129
+ end
130
+
131
+ def migrate(destination)
132
+ migrate = System::Command.new("sudo xm migrate --live #{name} #{destination}", :command_level => 2)
133
+ migrate.execute
134
+ end
135
+
136
+ def destroy
137
+ destroy = System::Command.new("sudo xm destroy #{dom_id}", :command_level => 1)
138
+ destroy.execute
139
+ end
140
+
141
+ def pause
142
+ unless paused?
143
+ pause = System::Command.new("sudo xm pause #{dom_id}", :command_level => 1)
144
+ pause.execute
145
+ end
146
+ end
147
+
148
+ def unpause
149
+ if paused?
150
+ unpause = System::Command.new("sudo xm unpause #{dom_id}", :command_level => 1)
151
+ unpause.execute
152
+ end
153
+ end
154
+
155
+ def state_text
156
+ case state
157
+ when STATE_RUNNING: 'running'
158
+ when STATE_BLOCKED: 'blocked'
159
+ when STATE_SHUTDOWN: 'shutdown'
160
+ when STATE_CRASHED: 'crashed'
161
+ when STATE_DYING: 'dying'
162
+ when STATE_PAUSED: 'paused'
163
+ end
164
+ end
165
+
166
+ def running?
167
+ state == STATE_RUNNING
168
+ end
169
+
170
+ def blocked?
171
+ state == STATE_BLOCKED
172
+ end
173
+
174
+ def shutdown?
175
+ state == STATE_SHUTDOWN
176
+ end
177
+
178
+ def crashed?
179
+ state == STATE_CRASHED
180
+ end
181
+
182
+ def dying?
183
+ state == STATE_DYING
184
+ end
185
+
186
+ def paused?
187
+ state == STATE_PAUSED
188
+ end
189
+
190
+ def update_info
191
+ @memory, @dom_id, @vcpus, @state, @time = self.class.find_attributes_by_name(name).values_at(:memory, :dom_id, :vcpus, :state, :time)
192
+ end
193
+ end
194
+ end
data/lib/xen/server.rb ADDED
@@ -0,0 +1,32 @@
1
+ require 'xen/instance'
2
+ require 'log/logger'
3
+ require 'system/command'
4
+
5
+ module Xen
6
+ class Server
7
+ # Loglevel
8
+ # => 1 DEBUG
9
+ # => 2 Info
10
+ # => 3 Warning
11
+ # => 4 Critcal
12
+ LOG_LEVEL = 1
13
+
14
+ class << self
15
+ def logger
16
+ @@logger ||= Log::Logger.log(:log_level => LOG_LEVEL)
17
+ end
18
+ end
19
+
20
+ def initialize
21
+ end
22
+
23
+ def instances
24
+ Xen::Instance.all
25
+ end
26
+
27
+
28
+ def logger
29
+ self.class.logger
30
+ end
31
+ end
32
+ end
data/lib/xen/util.rb ADDED
@@ -0,0 +1,10 @@
1
+ module Xen
2
+ module Util
3
+ class << self
4
+ def generate_root_password
5
+ pwgen = System::Command.new("pwgen 16 1", :command_level => 1)
6
+ return pwgen.execute
7
+ end
8
+ end
9
+ end
10
+ end
data/ruby-xen.gemspec ADDED
@@ -0,0 +1,63 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{ruby-xen}
8
+ s.version = "0.7"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Heiko Kr\303\244mer", "Clemens Kofler"]
12
+ s.date = %q{2011-04-12}
13
+ s.description = %q{simple gem to controle xen dom0}
14
+ s.email = %q{kraemer@avarteq.de}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README"
18
+ ]
19
+ s.files = [
20
+ "Gemfile",
21
+ "Gemfile.lock",
22
+ "LICENSE",
23
+ "README",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/log/logger.rb",
27
+ "lib/system/command.rb",
28
+ "lib/xen/instance.rb",
29
+ "lib/xen/server.rb",
30
+ "lib/xen/util.rb",
31
+ "ruby-xen.gemspec"
32
+ ]
33
+ s.homepage = %q{http://github.com/foexle/ruby-xen}
34
+ s.licenses = ["GPL"]
35
+ s.require_paths = ["lib"]
36
+ s.rubygems_version = %q{1.7.2}
37
+ s.summary = %q{simple gem to controle xen dom0}
38
+
39
+ if s.respond_to? :specification_version then
40
+ s.specification_version = 3
41
+
42
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
43
+ s.add_runtime_dependency(%q<log4r>, [">= 0"])
44
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
45
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
46
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
47
+ s.add_development_dependency(%q<rcov>, [">= 0"])
48
+ else
49
+ s.add_dependency(%q<log4r>, [">= 0"])
50
+ s.add_dependency(%q<shoulda>, [">= 0"])
51
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
52
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
53
+ s.add_dependency(%q<rcov>, [">= 0"])
54
+ end
55
+ else
56
+ s.add_dependency(%q<log4r>, [">= 0"])
57
+ s.add_dependency(%q<shoulda>, [">= 0"])
58
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
59
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
60
+ s.add_dependency(%q<rcov>, [">= 0"])
61
+ end
62
+ end
63
+
metadata ADDED
@@ -0,0 +1,150 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xen-ruby
3
+ version: !ruby/object:Gem::Version
4
+ hash: 5
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 7
9
+ version: "0.7"
10
+ platform: ruby
11
+ authors:
12
+ - "Heiko Kr\xC3\xA4mer"
13
+ - Clemens Kofler
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-04-12 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ version_requirements: &id001 !ruby/object:Gem::Requirement
22
+ none: false
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ hash: 3
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ name: log4r
31
+ prerelease: false
32
+ type: :runtime
33
+ requirement: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ version_requirements: &id002 !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ hash: 3
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ name: shoulda
45
+ prerelease: false
46
+ type: :development
47
+ requirement: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ version_requirements: &id003 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ hash: 23
55
+ segments:
56
+ - 1
57
+ - 0
58
+ - 0
59
+ version: 1.0.0
60
+ name: bundler
61
+ prerelease: false
62
+ type: :development
63
+ requirement: *id003
64
+ - !ruby/object:Gem::Dependency
65
+ version_requirements: &id004 !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ hash: 7
71
+ segments:
72
+ - 1
73
+ - 5
74
+ - 2
75
+ version: 1.5.2
76
+ name: jeweler
77
+ prerelease: false
78
+ type: :development
79
+ requirement: *id004
80
+ - !ruby/object:Gem::Dependency
81
+ version_requirements: &id005 !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ name: rcov
91
+ prerelease: false
92
+ type: :development
93
+ requirement: *id005
94
+ description: simple gem to controle xen dom0
95
+ email: kraemer@avarteq.de
96
+ executables: []
97
+
98
+ extensions: []
99
+
100
+ extra_rdoc_files:
101
+ - LICENSE
102
+ - README
103
+ files:
104
+ - Gemfile
105
+ - Gemfile.lock
106
+ - LICENSE
107
+ - README
108
+ - Rakefile
109
+ - VERSION
110
+ - lib/log/logger.rb
111
+ - lib/system/command.rb
112
+ - lib/xen/instance.rb
113
+ - lib/xen/server.rb
114
+ - lib/xen/util.rb
115
+ - ruby-xen.gemspec
116
+ homepage: http://github.com/foexle/ruby-xen
117
+ licenses:
118
+ - GPL
119
+ post_install_message:
120
+ rdoc_options: []
121
+
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ hash: 3
130
+ segments:
131
+ - 0
132
+ version: "0"
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ none: false
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ hash: 3
139
+ segments:
140
+ - 0
141
+ version: "0"
142
+ requirements: []
143
+
144
+ rubyforge_project:
145
+ rubygems_version: 1.7.2
146
+ signing_key:
147
+ specification_version: 3
148
+ summary: simple gem to controle xen dom0
149
+ test_files: []
150
+