wbem 0.3.0 → 0.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 87b68ff6a2d000a5a3d48ca45b80457b2e09510e
4
- data.tar.gz: 485f24baa3f7b857f23a41c6d083ae335207f6ea
3
+ metadata.gz: a9c0a1ba0bac70d9aa7e910153bf46837a6dd305
4
+ data.tar.gz: 232a5e958d2e5456ba907379228e0304a32ae82c
5
5
  SHA512:
6
- metadata.gz: c0d17fee71e8379c960add9b3d250afa20ff15b06588b701a6a386396d5fa6f263bacb233f531c70955b02e2ce3bdc57025bdbde36cac9db495e85b5bd5c18e6
7
- data.tar.gz: 4d5d1ba803e1a93d2b3802dd1ae44e4fdf5c35788507e5e30d0f06b6042fb5d1569c63fab10784b0d589e86f091e75a40b5dcf90482d4a9ae61f88afa71ed9f1
6
+ metadata.gz: 364d2f6af56cfc32aecf396f546aaa85461d0dbb1f123a5db9d9e2f6c2dfc722da657df5db9378d3f52e8b7ef092b71a8ebbe7406d90113f3739bce5d63539ff
7
+ data.tar.gz: c4d5401ac945660197fa4cb0340da43086a638236d0828be2e3cb61010db996a793fc7d62604d59d678ab0f544437917d33e3d6a1bd7819768dbb0d17c55d332
@@ -1,3 +1,23 @@
1
+ == 0.5.0
2
+
3
+ * Add client.get for fetching instances with keys in Cimxml
4
+
5
+ == 0.4.0
6
+
7
+ * Add bin/genclassinfo to generate Ruby classes from MOF
8
+ * Add client.get for fetching instances with keys in Wsman
9
+ * Properly handle EndpointReferences
10
+ * Add Instance#invoke, based on type information from generated Ruby
11
+ class
12
+
13
+ == 0.3.2
14
+
15
+ * Add Client#get to get an instance by ObjectPath
16
+
17
+ == 0.3.1
18
+
19
+ * Add Client#get to get an instance by EndPointReference
20
+
1
21
  == 0.3.0
2
22
 
3
23
  * Add Client#profiles to enumerate CIM_RegisteredProfile
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
@@ -0,0 +1,22 @@
1
+
2
+ Copyright (c) 2009 Novell Inc.
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Dir['tasks/**/*.rake'].each { |t| load t }
5
+
6
+ task :default => [:test]
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # genclassinfo
4
+ #
5
+ # Generate Ruby class templates
6
+ #
7
+ # Copyright (c) 2015 Klaus Kämpf <kkaempf@suse.de>
8
+ #
9
+ # Licensed under the Ruby license
10
+ #
11
+ # == Usage
12
+ #
13
+ # genclassinfo [-d] [-h] [-q] [-I <includedir>] [-o <output>] <moffile> [<moffile> ...]
14
+ #
15
+ # -d:
16
+ # turn on debugging
17
+ # -h:
18
+ # show (this) help
19
+ # -q:
20
+ # be quiet
21
+ # -I <includedir>
22
+ # additional include directories to search
23
+ # -o <outputdir>
24
+ # directory to write generated files, defaults to 'generated'
25
+ # <moffile>
26
+ # .mof files to read
27
+ #
28
+
29
+ require 'rubygems'
30
+
31
+ require 'mof'
32
+ require 'pathname'
33
+ require 'fileutils'
34
+
35
+ $:.push(File.join(File.dirname(__FILE__), '..', 'lib'))
36
+
37
+ require 'wbem'
38
+
39
+ def usage msg=nil
40
+ STDERR.puts "Err: #{msg}" if msg
41
+ STDERR.puts "Usage: genclassinfo [-d] <class> [ <class> ...]"
42
+ exit (msg)?1:0
43
+ end
44
+
45
+ #--------------------------------------------------------------------
46
+
47
+ @factory = Wbem::ClassFactory.new
48
+
49
+ if ARGV.empty?
50
+ usage
51
+ end
52
+
53
+ ARGV.each do |c|
54
+ if c == "-d"
55
+ Wbem::debug = 1
56
+ next
57
+ end
58
+ @factory.gen_class c
59
+ end
@@ -9,6 +9,10 @@
9
9
  # Licensed under the MIT license
10
10
  #
11
11
  module Wbem
12
+ require 'wbem/class_factory'
13
+ require 'wbem/conversion'
14
+ require 'wbem/wbem'
15
+
12
16
  @@debug = nil
13
17
  def Wbem.debug
14
18
  @@debug
@@ -19,8 +23,6 @@ module Wbem
19
23
 
20
24
  class Client
21
25
  require 'uri'
22
- require 'wbem/wsman'
23
- require 'wbem/cimxml'
24
26
 
25
27
  #
26
28
  # Wbem::Client.connect uri, protocol = nil
@@ -32,7 +34,7 @@ module Wbem
32
34
  # else - probe connection (cim/xml first)
33
35
  #
34
36
  def self.connect uri, protocol = nil, auth_scheme = nil
35
- STDERR.puts "Wbem::Client.connect(#{uri},#{protocol},#{auth_scheme})"
37
+ STDERR.puts "Wbem::Client.connect(#{uri},#{protocol},#{auth_scheme})" if Wbem.debug
36
38
  unless uri.is_a?(URI)
37
39
  u = URI.parse(uri)
38
40
  # u.port will be set in any case, so check the uri for port specification
@@ -46,16 +48,18 @@ module Wbem
46
48
  unless protocol_given
47
49
  u.port = (u.scheme == "http") ? 5985 : 5986
48
50
  end
51
+ require 'wbem/wsman'
49
52
  return WsmanClient.new u, auth_scheme
50
53
  when "cimxml"
51
54
  unless protocol_given
52
55
  u.port = (u.scheme == "http") ? 5988 : 5989
53
56
  end
57
+ require 'wbem/cimxml'
54
58
  return CimxmlClient.new u
55
59
  end
56
60
  # no connect, check known ports
57
61
  case u.port
58
- when 8888, 8889, 5985, 5986
62
+ when 8888, 8889, 5985, 5986, 16992
59
63
  return Wbem::Client.connect u, :wsman, auth_scheme
60
64
  when 5988, 5989
61
65
  return Wbem::Client.connect u, :cimxml, auth_scheme
@@ -51,6 +51,43 @@ private
51
51
 
52
52
  public
53
53
 
54
+ #
55
+ # parse ObjectPath to Sfcc::Cim::ObjectPath
56
+ # 1. root/cimv2:Linux_ComputerSystem.CreationClassName="Linux_ComputerSystem",Name="foo.bar"
57
+ # 2. localhost:5989/root/cimv2:Linux_ComputerSystem.CreationClassName="Linux_ComputerSystem",Name="heron.suse.de"
58
+ #
59
+ #
60
+ def self.parse_object_path s
61
+ op = nil
62
+ front, values = s.split(".",2)
63
+ STDERR.puts "self.parse_object_path >#{front}<(#{values})"
64
+ frontargs = front.split(":")
65
+ if frontargs.size == 2
66
+ # case 1 above
67
+ namespace, classname = frontargs
68
+ op = Sfcc::Cim::ObjectPath.new(namespace, classname)
69
+ elsif frontargs.size == 3
70
+ host, port_and_namespace, classname = frontargs
71
+ port, namespace = port_and_namespace.split("/", 2)
72
+ op = Sfcc::Cim::ObjectPath.new(namespace, classname)
73
+ else
74
+ raise "CimxmlClient.parse_object_path: Can't parse >#{frontargs.inspect}<"
75
+ end
76
+ # add values
77
+ while values && !values.empty?
78
+ puts "Values >#{values.inspect}<"
79
+ name, rest = values.split("=", 2)
80
+ arg, values = if rest[0,1] == '"' # quoted arg
81
+ rest[1..-1].split(/\",?/, 2)
82
+ else # non-quoted arg
83
+ rest.split(",", 2)
84
+ end
85
+ puts "name(#{name}), arg(#{arg})"
86
+ op.add_key(name, arg)
87
+ end
88
+ puts "Op #{op}"
89
+ op
90
+ end
54
91
  #
55
92
  # Initialize a CIMXML client connection
56
93
  #
@@ -125,10 +162,12 @@ public
125
162
  # @param properties : Hash (optional)
126
163
  #
127
164
  def instance_names namespace, classname=nil, properties={}
165
+ # if namespace is unset, sfcc will generate invalid XML
166
+ namespace ||= "root/cimv2"
128
167
  case namespace
129
168
  when Sfcc::Cim::ObjectPath
130
169
  objectpath = namespace
131
- namespace = objectpath.namespace
170
+ namespace = objectpath.namespace
132
171
  else
133
172
  objectpath = objectpath namespace.to_s, classname, properties
134
173
  end
@@ -143,6 +182,32 @@ public
143
182
  ret
144
183
  end
145
184
 
185
+ #
186
+ # get instance by reference
187
+ #
188
+ # call-seq
189
+ # get Sfcc::Cim::ObjectPath -> Wbem::Instance
190
+ # get ObjectPath-as-String -> Wbem::Instance
191
+ # get "ClassName", "key" => "value", :namespace => "root/interop"
192
+ #
193
+ def get instance_reference, keys = nil
194
+ if keys
195
+ namespace = keys.delete(:namespace) || "root/cimv2"
196
+ instance_reference = Sfcc::Cim::ObjectPath.new(namespace, instance_reference)
197
+ keys.each do |k,v|
198
+ instance_reference.add_key k, v
199
+ end
200
+ end
201
+ puts "@client.get #{instance_reference.class}..." if Wbem.debug
202
+ case instance_reference
203
+ when Sfcc::Cim::ObjectPath
204
+ get_by_objectpath instance_reference
205
+ when String
206
+ get_by_objectpath CimxmlClient.parse_object_path(instance_reference)
207
+ else
208
+ raise "Unsupported Wbem::get #{instance_reference.class}"
209
+ end
210
+ end
146
211
  #
147
212
  # Return matching Wbem::Instance for first instance
148
213
  # matching namespace, classname, properties
@@ -190,5 +255,12 @@ public
190
255
  end
191
256
  end
192
257
 
258
+ #
259
+ # get instance by objectpath
260
+ #
261
+ def get_by_objectpath objpath
262
+ STDERR.puts "#{self.class}.get_by_objectpath #{objpath}" if Wbem.debug
263
+ @client.get_instance(objpath)
264
+ end
193
265
  end # class
194
266
  end # module
@@ -0,0 +1,163 @@
1
+ #
2
+ # Class Factory
3
+ #
4
+ #
5
+ # Creates CIM class with ancestry chain
6
+ #
7
+ # Base class: Wbem::Instance
8
+ #
9
+ module Wbem
10
+ class ClassFactory
11
+ MOFBASE = "/usr/share/mof/cim-current"
12
+ AMTBASE = "/usr/share/mof/iAMT/MOF"
13
+ QUALIFIERS = "qualifiers.mof"
14
+ SCHEMATA = { MOFBASE => "CIM_Schema.mof", AMTBASE => "amt.mof" }
15
+ CLASSDIR = "wbem"
16
+ require 'cim'
17
+ require 'mof'
18
+ require 'pathname'
19
+
20
+ #
21
+ # Constructor
22
+ #
23
+ def initialize basepath = nil
24
+ @basedir = File.expand_path(File.join(basepath || Dir.getwd, CLASSDIR))
25
+ end
26
+ private
27
+
28
+ #
29
+ # parse_with_ancestors
30
+ #
31
+ # Find the superclass name of a class, parse its mof file
32
+ # returns Hash of { classname -> CIM::Class }
33
+ #
34
+
35
+ def parse_with_ancestors name
36
+ # find .mof file
37
+ mofdata = classmap()[name]
38
+ unless mofdata
39
+ raise "Can't find MOF for #{name}"
40
+ end
41
+ mofpath = mofdata[:path]
42
+ # parsed before ?
43
+ mof = mofdata[:mof] rescue nil
44
+ unless mof
45
+ # not parsed, parse now
46
+ puts "Reading mof from #{mofpath}" if Wbem.debug
47
+ begin
48
+ mofs = parser().parse [ QUALIFIERS, "qualifiers_intel.mof", mofpath ]
49
+ rescue Exception => e
50
+ parser.error_handler e
51
+ end
52
+ # puts "==> #{mofs.inspect}"
53
+ # Iterate over all parsed classes
54
+ mofs[mofpath].classes.each do |mofclass|
55
+ next unless mofclass.name == name
56
+ classmap()[name] = { :path => mofpath, :mof => mofclass }
57
+ if mofclass.superclass
58
+ parse_with_ancestors mofclass.superclass
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ #
65
+ # generate method parameter information
66
+ # return nil if no parameters
67
+ #
68
+ def gen_method_parameters direction, parameters, file
69
+ return if parameters.empty?
70
+ file.print "#{direction.inspect} => ["
71
+ first = true
72
+ parameters.each do |p|
73
+ if first
74
+ first = false
75
+ else
76
+ file.print ", "
77
+ end
78
+ # [ <name>, <type>, <out>? ]
79
+ file.print "#{p.name.inspect}, #{p.type.to_sym.inspect}"
80
+ end
81
+ file.print "]"
82
+ return true
83
+ end
84
+ #
85
+ # generate .rb class declaration
86
+ #
87
+ def generate name, file
88
+ require 'erb'
89
+ template = File.read(File.join(File.dirname(__FILE__), "class_template.erb"))
90
+ erb = ERB.new(template)
91
+ code = erb.result(binding)
92
+ Dir.mkdir(@basedir) unless File.directory?(@basedir)
93
+ File.open(file, "w+") do |f|
94
+ f.puts code
95
+ end
96
+ end
97
+
98
+ #
99
+ # classmap - generate map of classes and their .mof files
100
+ #
101
+ def classmap
102
+ return @classmap if @classmap
103
+ # read SCHEMA and build class index to find .mof files quickly
104
+ @classmap = Hash.new
105
+ @includes = [ Pathname.new(".") ]
106
+ SCHEMATA.each do |base, file|
107
+ @includes << base
108
+ allow_cim = (file =~ /^CIM_/) # allow CIM_ only for CIM_Schema.mof
109
+ File.open(File.join(base, file)) do |f|
110
+ f.each do |l|
111
+ if l =~ /^\#pragma\sinclude\s?\(\"(([\w\/_]+)\.mof)\"\).*/
112
+ # $1 Foo/Bar.mof
113
+ # $2 Foo/Bar
114
+ path = $1
115
+ names = $2.split("/")
116
+ name = names[1] || names[0]
117
+ next unless name =~ /_/ # class name must have underscore (rules out 'qualifiers.mof')
118
+ # puts "#{path}:#{name}"
119
+ next if !allow_cim && name =~ /^CIM_/ # skip CIM_ mofs unless allowed
120
+ if @classmap[name]
121
+ raise "Dup #{name} : #{@classmap[name]}"
122
+ else
123
+ @classmap[name] = { :path => path }
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ STDERR.puts "Found MOFs for #{@classmap.size} classes" if Wbem.debug
130
+ @classmap
131
+ end
132
+
133
+ #
134
+ # MOF parser access
135
+ #
136
+ def parser
137
+ @parser ||= MOF::Parser.new :style => :cim, :includes => @includes, :quiet => true
138
+ end
139
+ public
140
+ #
141
+ # Class Factory
142
+ #
143
+ def class_for name
144
+ begin
145
+ path = "#{@basedir}/#{name}"
146
+ require path
147
+ return Object.const_get("Wbem").const_get(name)
148
+ rescue LoadError
149
+ raise "'#{path}.rb' not found, use 'genclass' of ruby-wbem to generate class '#{name}'"
150
+ end
151
+ end
152
+ #
153
+ # gen_class
154
+ #
155
+ def gen_class name
156
+ mofname = name + ".mof"
157
+ classpath = File.join(@basedir, "#{name}.rb")
158
+ parse_with_ancestors name
159
+ generate name, classpath
160
+ class_for name
161
+ end # def create
162
+ end # class ClassFactory
163
+ end # module Wbem
@@ -0,0 +1,48 @@
1
+ <%
2
+ # @classes[name] = { :path => mofpath, :mof => mofclass }
3
+
4
+ def collect_superclasses name
5
+ classdata = @classmap[name]
6
+ raise "No such class: #{name}" unless classdata
7
+ mofclass = classdata[:mof]
8
+ superclass = mofclass.superclass
9
+ [mofclass] + ((superclass)?collect_superclasses(superclass):[])
10
+ end
11
+ %>
12
+
13
+ # Class information for <%= name %>
14
+ # Generated by 'wbem' for use with ruby-wbem
15
+
16
+ require 'rubygems'
17
+ require 'cim'
18
+ require 'wbem'
19
+
20
+ module Wbem
21
+
22
+ class <%= name %> < Wbem::Instance
23
+ <% classes = collect_superclasses name %>
24
+ <% known_features = Hash.new %>
25
+ TYPEMAP = {
26
+ <% classes.each do |mofclass|
27
+ mofclass.features.each do |f|
28
+ next if known_features[f.name]
29
+ known_features[f.name] = f
30
+ if f.method? %>
31
+ # <%= mofclass.name %>.<%= f.name %>()
32
+ <%= f.name.inspect %> => [ <%= f.type.to_sym.inspect %>, <% f.parameters.each do |p| %>
33
+ [ <%= p.name.inspect %>, <%= p.type.to_sym.inspect %>, <%= (p.includes?(:out))?":out":":in" %> ], <% end %>
34
+ ],
35
+ <% else %>
36
+ # <%= mofclass.name %>.<%= f.name %>
37
+ <%= f.name.inspect %> => <%= f.type.to_sym.inspect %>,
38
+ <% end
39
+ end
40
+ end %>
41
+ }
42
+
43
+ def _typemap
44
+ TYPEMAP
45
+ end
46
+
47
+ end # class
48
+ end # module