November 17-21, 2008, Santa Clara Marriott, Santa Clara, CA

ActiveWSMan Applying the active record pattern to WS-Management

Klaus Kämpf Web Services for Management

• 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 or , 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. – 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), (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 tty1 ActiveRecord Ruby is dynamic

• 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 ?