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