merged cont.
[opensuse:yast-rest-service.git] / webyast / lib / yast_service.rb
1 #--
2 # Webyast Webservice framework
3 #
4 # Copyright (C) 2009, 2010 Novell, Inc. 
5 #   This library is free software; you can redistribute it and/or modify
6 # it only under the terms of version 2.1 of the GNU Lesser General Public
7 # License as published by the Free Software Foundation. 
8 #
9 #   This library is distributed in the hope that it will be useful, but WITHOUT
10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 
12 # details. 
13 #
14 #   You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software 
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 #++
18
19 require 'exceptions'
20
21 class YastService
22     require "dbus"
23
24     # cache the importer object, avoid recreation in every Import call
25     @@importer = nil
26
27     # avoid race conditions while accessing YaST
28     #
29     @@yast_mutex = Mutex.new
30
31     # cache for imported namespaces, avoid importing an Yast name space
32     # and introspecting the DBus object in every call
33     # key: name space name, value: DBus object
34     @@imported = {}
35
36     #
37     # YastService.lock
38     #
39     # Lock YastService for single use
40     #
41     def YastService.lock
42       Rails.logger.info "DBUS locking"
43       @@yast_mutex.lock
44       Rails.logger.info "DBUS locked"
45     end
46
47     #
48     # YastService.unlock
49     #
50     # Unlock YastService
51     #
52     def YastService.unlock
53       if @@yast_mutex.locked?
54         begin
55           @@yast_mutex.unlock 
56         rescue Exception => e
57           Rails.logger.debug "DBUS is not locked"
58         end
59         Rails.logger.info "DBUS unlocked"
60       end
61     end
62
63     # call a Yast function using DBus service
64     def YastService.Call(function, *arguments)
65
66         YastService.lock #locking for other thread
67
68         # connect to the system bus
69         system_bus = DBus::SystemBus.instance # RORSCAN_ITL
70
71         # get the Yast namespace service
72         yast = system_bus.service('org.opensuse.YaST.modules') # RORSCAN_ITL
73
74         # parse the function name
75         parts = function.split('::')
76
77         # get the last item (the function name)
78         fce = parts.pop
79         # format the namespace object name
80         object = parts.join('/')
81         namespace = parts.join('::')
82
83         # has been the namespace already imported?
84         if @@imported.has_key?(namespace)
85             dbusobj = @@imported[namespace]
86         else
87             # lazy initialization of the importer object
88             if @@importer.nil?
89                 @@importer = yast.object('/org/opensuse/YaST/modules')
90                 @@importer.introspect
91                 @@importer.default_iface = 'org.opensuse.YaST.modules.ModuleManager'
92             end
93
94             # import the module
95             imported = @@importer.Import(namespace)
96
97             if imported
98                 dbusobj = yast.object('/org/opensuse/YaST/modules/' + object)
99                 dbusobj.introspect
100                 dbusobj.default_iface = 'org.opensuse.YaST.Values'
101
102                 @@imported[namespace] = dbusobj
103              end
104         end
105
106         return dbusobj.send(fce, *arguments)[0]
107
108
109     # handle DBus and PolicyKit errors
110     rescue DBus::Error => dbe
111
112         # handle org.freedesktop.PolicyKit.Error.NotAuthorized DBus Error
113         if dbe.dbus_message.error_name == 'org.freedesktop.PolicyKit.Error.NotAuthorized' && dbe.dbus_message.params.size == 1
114             parms = dbe.dbus_message.params[0].split(' ')
115             
116             # Etc helps to retrieve the login of the REST service
117             require 'etc'
118             # throw a PolicyKit exception instead of the DBus exception
119             raise NoPermissionException.new(parms[0], Etc.getlogin)
120         end
121
122         # rethrow other DBus Errors
123         raise dbe
124
125     # handle generic errors (e.g. non existing yast function)
126     rescue Exception => e
127
128         # rethow generic exceptions
129         raise e
130     ensure
131       YastService.unlock #unlocking for other thread
132     end
133 end
134