November 17-21, 2008, Santa Clara Marriott, Santa Clara, CA
ActiveWSMan Applying the active record pattern to WS-Management
Klaus Kämpf
• WS-Management (WS-Man) – First truly universal protocol for remote systems management – Allows interoperable (Windows/Linux/Unix) systems management – Available for Windows (Vista, Server 2003, XP) – openwsman provides open source implementation for client and server
2 Writing WS-Man applications
• Scripting – winrm (Windows) – wsmancli (Openwsman) • Language bindings – C – C++ – Ruby – Python – Perl – Java Enumerating resources
• Enumerating resources needs – Client connection – Connection options – Resource URI – Filters – Enumerate call – Retrieve context – Pull context (repeated) – Release context Enumerating resources Code example (Ruby) include Rbwsman c = Client.new( “http://server.linux.org” ) opt = ClientOptions.new uri = “http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_Process” result = client.enumerate( opt, nil, uri ) if result loop do context = result.context result = client.pull( uri, context, options ) break unless result node = result.body.find( XML_NS_ENUMERATION, "Items" ) node.each_child do |child| # operate on XML representation end end end client.release( options, uri, context ) if context Downsides of the client API
• API exposes WS-Management internals – Protocol – Encoding • Resources are available as XML trees • Manual fault processing
But I just want to work with resources ! It should be like this include Rbwsman include ActiveWsman class Process < ActiveWsman::CIM end processes = Process.find_all processes.each do |proc| puts proc.name, proc.state, proc.owner, proc.state end
Active record Active record
• Active record is a programming pattern – Object oriented programming – Coined by Martin Fowler • Patterns of Enterprise Application Architecture • http://martinfowler.com/eaaCatalog/activeRecord.html
“An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.” Standard active record
• Direct mapping to the database – Class to table – Object to row • Simple, no relationships between objects – Finder – Getters – Setters Active record implementations
• Popular open source implementations – ActiveRecord (Ruby) • http://ar.rubyonrails.com/ • used in e.g. Ruby on Rails – Castle ActiveRecord (C# / .NET) • http://www.castleproject.org/activerecord/index.html • part of CastleProject – Django (Python) • http://www.djangoproject.com Ruby ActiveRecord
• Library built for Ruby on Rails • Make CRUD easy – (Create, Read, Update, Delete)
“I have never seen an Active Record implementation as complete or as useful as Rails” – Martin Fowler ActiveRecord Automated mapping
• Automated mapping between classes and tables, attributes and columns.
class Product < ActiveRecord::Base; end
CREATE TABLE products ( id int(11) NOT NULL auto_increment, name varchar(255), vendor varchar(255), PRIMARY KEY (id) ); ActiveWsman Automated mapping
• Automated mapping between classes, properties and methods.
class Process < ActiveWsman::CIM; end
class CIM_Process : CIM_EnabledLogicalElement { string CSCreationClassName; string CSName; string OSCreationClassName; string OSName; ... } ActiveRecord Find
• Find is the primary method of Active Record
Product.find(42) Product.find(:first) Product.find(:all, :offset => 7, :limit => 5)
• What find does – Generates SQL – Executes SQL – Returns enumerable (array like)
ActiveWsman Find
• Effectively hides protocol details
UnixProcess.find(42) UnixProcess.find(:first) UnixProcess.find(:all, :offset => 7, :limit => 5)
• Map find to – WS-Man 'get' – WS-Man 'enumerate'
ActiveRecord Find with conditions
• Adding conditions
Product.find(:first, :conditions => { :name => “acme” })
• Maps to SQL SELECT * FROM products WHERE ( name = 'acme' ) ActiveWsman Find with conditions
• Adding conditions
UnixProcess.find(:first, :conditions => { :ProcessTTY => “tty1” })
• Maps to filters
• Leverage dynamic properties of the Ruby language
Product.find_by_name( “acme” ) Product.find_by_name_and_vendor( “robot”, “buy'n large”)
• Dynamically evaluated at runtime Bare bones find
• ActiveRecord – Drop down to SQL Product.find_by_sql(“SELECT * FROM products WHERE(...)”)
• ActiveWsman – Use WQL UnixProcess.find_by_wql(“SELECT * FROM CIM_UnixProcess ...”) – Alternative: CQL ActiveRecord Object associations
• Associations between objects controlled by simple meta-programming macros.
class Firm < ActiveRecord::Base has_many :clients has_one :account belongs_to :conglomorate end ActiveWsman Object associations
• Associations between objects controlled by model information.
class CIM_Mount : CIM_Dependency { [Max ( 1 ), Description("The Directory mounted.")] CIM_Directory REF Antecedent;
[Description("The FileSystem the Directory is mounted on.")] CIM_FileSystem REF Dependent; }; ActiveRecord Validation
• Validation rules that can differ for new or existing objects.
class Account < ActiveRecord::Base validates_presence_of :subdomain, :name, :password validates_uniqueness_of :subdomain validates_acceptance_of :terms_of_service, :on => :create end ActiveWsman Validation
• Validate application data
class Process < ActiveWsman::Win32 validates_presence_of :CommandLine, :CurrentDirectory, :on => :create end ActiveRecord Reflections
• Reflections on columns, associations, and aggregations
reflection = Firm.reflect_on_association(:clients) reflection.klass # => Client (class) Firm.columns # Returns an array of column descriptors for the firms table ActiveWsman Reflections
• Reflections on properties, associations, and aggregations
reflection = Directory.reflect_on_association(:filesystems) reflection.klass # => Filesystem (class) Directory.properties # Returns an array of property descriptors for the Directory class ActiveRecord Database connection • Database abstraction through simple adapters (~100 lines) with a shared connector
ActiveRecord::Base.establish_connection(:adapter => "sqlite", :database => "dbfile")
ActiveRecord::Base.establish_connection( :adapter => "mysql", :host => "localhost", :username => "me", :password => "secret", :database => "activerecord" ) ActiveWsman Client connection • Hide (openwsman) client connection details
ActiveWsman::Base.establish_connection( “https://wsman:[email protected]:8889”)
ActiveWsman::Base.establish_connection( :schema => "https", :host => "client.openwsman.org", :username => "wsman", :password => "secret", :port => 8889 ) Status
• Research project – Feasibility study • Based on Ruby ActiveRecord – Most complete – Rails as application platform • Goal: ActiveWsman as application API standard – Feedback welcome ! Outlook
• Complete openwsman client bindings – See “WS-Management Client in your Favorite Programming Language” • Provide model information – Extend openwsman cim plugin • Publish source – Follow www.openwsman.org • Extend to other languages – Python as primary candidate References
• Martin Fowlers “Patterns of Enterprise Application Architecture” – http://martinfowler.com/eaaCatalog/ • Ruby ActiveRecord – http://ar.rubyonrails.com • Ruby on Rails – http://www.rubyonrails.com • Web Services for Management – http://www.dmtf.org/standards/wsman • openwsman project – http://www.openwsman.org Thank you !
Questions ?