Salome HOME
Synchronize adm files
[modules/kernel.git] / bin / appliskel / update_catalogs.py
1 #!/usr/bin/env python
2 #  -*- coding: utf-8 -*-
3 # Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
4 #
5 # Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
6 # CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
7 #
8 # This library is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU Lesser General Public
10 # License as published by the Free Software Foundation; either
11 # version 2.1 of the License, or (at your option) any later version.
12 #
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 # Lesser General Public License for more details.
17 #
18 # You should have received a copy of the GNU Lesser General Public
19 # License along with this library; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21 #
22 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #
24
25 """
26 """
27 import sys,os,shutil,glob,socket
28 import optparse
29
30 import getAppliPath
31 appli_local=os.path.realpath(os.path.dirname(__file__))
32 APPLI=getAppliPath.relpath(appli_local,os.path.realpath(os.getenv('HOME')))
33
34 usage="""usage: %prog [options]
35 Typical use is:
36   python update_catalogs.py
37
38 You need to have a well installed SALOME application with a CatalogResources.base.xml file.
39 This file is used (parsed) to collect all module catalogs from distant resources and
40 put them in the directory "remote_catalogs" with sub-directories with same name as the distant resource.
41 Distant resources are all the resources except the main SALOME application.
42 Module catalogs from distant resources are copied by the remote protocol declared in the catalog (rcp or rsh)
43 except for the user resources on the local machine (local copy: cp).
44
45 In a second time, this procedure generates a ready to use CatalogResources.xml with all available components
46 for each resource.
47 """
48
49 try:
50   # cElementTree from Python 2.5+
51   import xml.etree.cElementTree as etree_
52 except ImportError:
53   try:
54     import xml.etree.ElementTree as etree_
55   except ImportError:
56     try:
57       import cElementTree as etree_
58     except ImportError:
59       try:
60         # normal ElementTree install
61         import elementtree.ElementTree as etree_
62       except ImportError:
63         raise
64
65 class ParseError(Exception):
66   pass
67
68 catalog_file_base=os.path.join(appli_local,"CatalogResources.base.xml")
69 catalog_file=os.path.join(appli_local,"CatalogResources.xml")
70
71 cata_dir=os.path.join(appli_local,"remote_catalogs")
72 cata_dir_bak=os.path.join(appli_local,"remote_catalogs.bak")
73
74 SEP=":"
75 if sys.platform == "win32":SEP=";"
76
77 def get_hostname():
78   return socket.gethostname().split('.')[0]
79
80 class Component:
81   """Define a SALOME component
82       - name : component name
83       - moduleName : module name
84   """
85   def __init__(self,name,moduleName):
86     self.name=name
87     self.moduleName=moduleName
88
89 class Resource:
90   """Define a SALOME resource
91      - components : the list of available components of the resource
92   """
93   def __init__(self,node):
94     self.node=node
95     self.components=[]
96     self.resource_dir=None
97     self.build()
98
99   def build(self):
100     self.attrs=self.node.attrib
101     #remove all children (components and modules)
102     for child in list(self.node):
103       self.node.remove(child)
104
105   def update(self):
106     for compo in self.components:
107       child=etree_.Element("component",name=compo.name,moduleName=compo.moduleName)
108       child.tail="\n"
109       self.node.append(child)
110
111   def get_rcp(self):
112     protocol= self.node.get("protocol")
113     if protocol and protocol[0]=='s':return "scp"
114     else:return "rcp"
115
116   def get_user(self):
117     userName= self.node.get("userName")
118     if not userName:
119       userName=os.getenv('USER')
120     return userName
121
122   def get_host(self):
123     hostname= self.node.get("hostname")
124     return hostname
125
126   def get_name(self):
127     name= self.node.get("name")
128     if name:return name
129     return self.get_host()
130
131   def get_appliPath(self):
132     appliPath= self.node.get("appliPath")
133     if appliPath is None:
134       appliPath=APPLI
135     return appliPath
136
137   def get_catalogs(self):
138     """Get module catalogs file from the resource and copy them locally in remote_catalogs/<resource name>"""
139     hostname=self.get_host()
140     appliPath= self.get_appliPath()
141     userName = self.get_user()
142     rcopy=self.get_rcp()
143
144     resource_dir=os.path.join(cata_dir,self.get_name())
145
146     if hostname == "localhost" or hostname == get_hostname() and userName == os.getenv("USER"):
147       #local machine, use cp
148       if appliPath[0]!='/':
149         #relative path
150         appliPath=os.path.join(os.getenv("HOME"),appliPath)
151
152       if appliPath == appli_local:
153         return
154       os.mkdir(resource_dir)
155       cata_path=os.path.join(appliPath,"share","salome","resources","*Catalog.xml")
156       cmd="cp %s %s" % (cata_path,resource_dir)
157       print cmd
158       os.system(cmd)
159       cata_path=os.path.join(appliPath,"share","salome","resources","*","*Catalog.xml")
160       cmd="cp %s %s" % (cata_path,resource_dir)
161       print cmd
162       os.system(cmd)
163     else:
164       #remote machine, use rcopy
165       os.mkdir(resource_dir)
166       cata_path=os.path.join(appliPath,"share","salome","resources","*Catalog.xml")
167       cmd="%s %s@%s:%s %s"
168       cmd= cmd%(rcopy,userName,hostname,cata_path,resource_dir)
169       print cmd
170       os.system(cmd)
171       cata_path=os.path.join(appliPath,"share","salome","resources","*","*Catalog.xml")
172       cmd="%s %s@%s:%s %s"
173       cmd= cmd%(rcopy,userName,hostname,cata_path,resource_dir)
174       print cmd
175       os.system(cmd)
176
177     schema_cata=os.path.join(resource_dir,"*SchemaCatalog.xml")
178     os.system("rm %s"% schema_cata)
179
180     self.resource_dir=os.path.abspath(resource_dir)
181
182   def get_components(self):
183     """Retrieve all components declared in module catalogs of the resource"""
184     appliPath= self.get_appliPath()
185     userName = self.get_user()
186     hostname=self.get_host()
187     resource_dir=os.path.join(cata_dir,self.get_name())
188     catalogs_list=glob.glob(os.path.join(resource_dir,"*Catalog.xml"))
189
190     if hostname == "localhost" or hostname == get_hostname() and userName == os.getenv("USER"):
191       #user local resource
192       if appliPath[0]!='/':
193         appliPath=os.path.join(os.getenv("HOME"),appliPath)
194       if appliPath == appli_local:
195         #main local resource: get catalogs in share/salome/resources
196         catalogs_list=glob.glob(os.path.join(appliPath,"share","salome","resources","*","*Catalog.xml"))
197         catalogs_list=catalogs_list + glob.glob(os.path.join(appliPath,"share","salome","resources","*Catalog.xml"))
198
199     for cata in catalogs_list:
200       moduleName= os.path.basename(cata)[:-11]
201       #Parse module catalog
202       doc = etree_.parse(cata)
203       rootNode = doc.getroot()
204       for componentName in rootNode.findall("component-list/component/component-name"):
205         self.components.append(Component(componentName.text,moduleName))
206
207
208 def main():
209   parser = optparse.OptionParser(usage=usage)
210
211   options, args = parser.parse_args()
212
213   if not os.path.exists(catalog_file_base):
214     print "ERROR: the base catalog file %s is mandatory" % catalog_file_base
215     sys.exit(1)
216
217   #Parse CatalogResource.xml
218   doc = etree_.parse(catalog_file_base)
219
220   rootNode = doc.getroot()
221   if rootNode.tag != "resources":
222     raise  ParseError("First level tag must be resources not %s" % rootNode.tag)
223
224   resources=[]
225
226   #Extract resources
227   for child in rootNode:
228     if child.tag != "machine":
229       raise  ParseError("Second level tag must be machine not %s" % child.tag)
230     resources.append(Resource(child))
231
232   # Remove remote_catalogs directory and create a new empty one
233   if os.path.exists(cata_dir):
234     if os.path.exists(cata_dir_bak):
235       shutil.rmtree(cata_dir_bak)
236     os.rename(cata_dir,cata_dir_bak)
237
238   os.mkdir(cata_dir)
239
240   #Get catalogs from remote resources and copy them in remote_catalogs
241   for mach in resources:
242     mach.get_catalogs()
243
244   #Get the list of SALOME components that are defined in catalogs
245   for mach in resources:
246     mach.get_components()
247
248   #Update the resource catalog dom object for further dump
249   for mach in resources:
250     mach.update()
251
252   #dump new CatalogResources.xml
253   f=open(catalog_file,'w')
254   f.write('<?xml version="1.0" ?>\n')
255   doc.write(f)
256   f.write('\n')
257   f.close()
258   print "%s updated" % catalog_file
259
260   #update configRemote.sh in env.d directory (environment variable SALOME_CATALOGS_PATH)
261   path=[]
262   for mach in resources:
263     if mach.resource_dir:
264       path.append(mach.resource_dir)
265
266   f=open(os.path.join(appli_local,"env.d","configRemote.sh"),'w')
267   f.write("export SALOME_CATALOGS_PATH=%s\n" % SEP.join(path))
268   f.close()
269
270
271 if __name__ == '__main__':
272   main()
273