Salome HOME
Merge from V5_1_main branch 24/11/2010
[modules/kernel.git] / bin / appliskel / update_catalogs.py
diff --git a/bin/appliskel/update_catalogs.py b/bin/appliskel/update_catalogs.py
new file mode 100644 (file)
index 0000000..eacd6e3
--- /dev/null
@@ -0,0 +1,251 @@
+#!/usr/bin/env python
+#  -*- coding: utf-8 -*-
+"""
+"""
+import sys,os,shutil,glob,socket
+import optparse
+
+import getAppliPath
+appli_local=os.path.realpath(os.path.dirname(__file__))
+APPLI=getAppliPath.relpath(appli_local,os.path.realpath(os.getenv('HOME')))
+
+usage="""usage: %prog [options]
+Typical use is:
+  python update_catalogs.py
+
+You need to have a well installed SALOME application with a CatalogResources.base.xml file.
+This file is used (parsed) to collect all module catalogs from distant resources and
+put them in the directory "remote_catalogs" with sub-directories with same name as the distant resource.
+Distant resources are all the resources except the main SALOME application.
+Module catalogs from distant resources are copied by the remote protocol declared in the catalog (rcp or rsh)
+except for the user resources on the local machine (local copy: cp).
+
+In a second time, this procedure generates a ready to use CatalogResources.xml with all available components
+for each resource.
+"""
+
+try:
+  # cElementTree from Python 2.5+
+  import xml.etree.cElementTree as etree_
+except ImportError:
+  try:
+    import xml.etree.ElementTree as etree_
+  except ImportError:
+    try:
+      import cElementTree as etree_
+    except ImportError:
+      try:
+        # normal ElementTree install
+        import elementtree.ElementTree as etree_
+      except ImportError:
+        raise
+
+class ParseError(Exception):
+  pass
+
+catalog_file_base=os.path.join(appli_local,"CatalogResources.base.xml")
+catalog_file=os.path.join(appli_local,"CatalogResources.xml")
+
+cata_dir=os.path.join(appli_local,"remote_catalogs")
+cata_dir_bak=os.path.join(appli_local,"remote_catalogs.bak")
+
+SEP=":"
+if sys.platform == "win32":SEP=";"
+
+def get_hostname():
+  return socket.gethostname().split('.')[0]
+
+class Component:
+  """Define a SALOME component
+      - name : component name
+      - moduleName : module name
+  """
+  def __init__(self,name,moduleName):
+    self.name=name
+    self.moduleName=moduleName
+
+class Resource:
+  """Define a SALOME resource
+     - components : the list of available components of the resource
+  """
+  def __init__(self,node):
+    self.node=node
+    self.components=[]
+    self.resource_dir=None
+    self.build()
+
+  def build(self):
+    self.attrs=self.node.attrib
+    #remove all children (components and modules)
+    for child in list(self.node):
+      self.node.remove(child)
+
+  def update(self):
+    for compo in self.components:
+      child=etree_.Element("component",name=compo.name,moduleName=compo.moduleName)
+      child.tail="\n"
+      self.node.append(child)
+
+  def get_rcp(self):
+    protocol= self.node.get("protocol")
+    if protocol and protocol[0]=='s':return "scp"
+    else:return "rcp"
+
+  def get_user(self):
+    userName= self.node.get("userName")
+    if not userName:
+      userName=os.getenv('USER')
+    return userName
+
+  def get_host(self):
+    hostname= self.node.get("hostname")
+    return hostname
+
+  def get_name(self):
+    name= self.node.get("name")
+    if name:return name
+    return self.get_host()
+
+  def get_appliPath(self):
+    appliPath= self.node.get("appliPath")
+    if appliPath is None:
+      appliPath=APPLI
+    return appliPath
+
+  def get_catalogs(self):
+    """Get module catalogs file from the resource and copy them locally in remote_catalogs/<resource name>"""
+    hostname=self.get_host()
+    appliPath= self.get_appliPath()
+    userName = self.get_user()
+    rcopy=self.get_rcp()
+
+    resource_dir=os.path.join(cata_dir,self.get_name())
+
+    if hostname == "localhost" or hostname == get_hostname() and userName == os.getenv("USER"):
+      #local machine, use cp
+      if appliPath[0]!='/':
+        #relative path
+        appliPath=os.path.join(os.getenv("HOME"),appliPath)
+
+      if appliPath == appli_local:
+        return
+      os.mkdir(resource_dir)
+      cata_path=os.path.join(appliPath,"share","salome","resources","*Catalog.xml")
+      cmd="cp %s %s" % (cata_path,resource_dir)
+      print cmd
+      os.system(cmd)
+      cata_path=os.path.join(appliPath,"share","salome","resources","*","*Catalog.xml")
+      cmd="cp %s %s" % (cata_path,resource_dir)
+      print cmd
+      os.system(cmd)
+    else:
+      #remote machine, use rcopy
+      os.mkdir(resource_dir)
+      cata_path=os.path.join(appliPath,"share","salome","resources","*Catalog.xml")
+      cmd="%s %s@%s:%s %s"
+      cmd= cmd%(rcopy,userName,hostname,cata_path,resource_dir)
+      print cmd
+      os.system(cmd)
+      cata_path=os.path.join(appliPath,"share","salome","resources","*","*Catalog.xml")
+      cmd="%s %s@%s:%s %s"
+      cmd= cmd%(rcopy,userName,hostname,cata_path,resource_dir)
+      print cmd
+      os.system(cmd)
+
+    schema_cata=os.path.join(resource_dir,"*SchemaCatalog.xml")
+    os.system("rm %s"% schema_cata)
+
+    self.resource_dir=os.path.abspath(resource_dir)
+
+  def get_components(self):
+    """Retrieve all components declared in module catalogs of the resource"""
+    appliPath= self.get_appliPath()
+    userName = self.get_user()
+    hostname=self.get_host()
+    resource_dir=os.path.join(cata_dir,self.get_name())
+    catalogs_list=glob.glob(os.path.join(resource_dir,"*Catalog.xml"))
+
+    if hostname == "localhost" or hostname == get_hostname() and userName == os.getenv("USER"):
+      #user local resource
+      if appliPath[0]!='/':
+        appliPath=os.path.join(os.getenv("HOME"),appliPath)
+      if appliPath == appli_local:
+        #main local resource: get catalogs in share/salome/resources
+        catalogs_list=glob.glob(os.path.join(appliPath,"share","salome","resources","*","*Catalog.xml"))
+        catalogs_list=catalogs_list + glob.glob(os.path.join(appliPath,"share","salome","resources","*Catalog.xml"))
+
+    for cata in catalogs_list:
+      moduleName= os.path.basename(cata)[:-11]
+      #Parse module catalog
+      doc = etree_.parse(cata)
+      rootNode = doc.getroot()
+      for componentName in rootNode.findall("component-list/component/component-name"):
+        self.components.append(Component(componentName.text,moduleName))
+
+
+def main():
+  parser = optparse.OptionParser(usage=usage)
+
+  options, args = parser.parse_args()
+
+  if not os.path.exists(catalog_file_base):
+    print "ERROR: the base catalog file %s is mandatory" % catalog_file_base
+    sys.exit(1)
+
+  #Parse CatalogResource.xml
+  doc = etree_.parse(catalog_file_base)
+
+  rootNode = doc.getroot()
+  if rootNode.tag != "resources":
+    raise  ParseError("First level tag must be resources not %s" % rootNode.tag)
+
+  resources=[]
+
+  #Extract resources
+  for child in rootNode:
+    if child.tag != "machine":
+      raise  ParseError("Second level tag must be machine not %s" % child.tag)
+    resources.append(Resource(child))
+
+  # Remove remote_catalogs directory and create a new empty one
+  if os.path.exists(cata_dir):
+    if os.path.exists(cata_dir_bak):
+      shutil.rmtree(cata_dir_bak)
+    os.rename(cata_dir,cata_dir_bak)
+
+  os.mkdir(cata_dir)
+
+  #Get catalogs from remote resources and copy them in remote_catalogs
+  for mach in resources:
+    mach.get_catalogs()
+
+  #Get the list of SALOME components that are defined in catalogs
+  for mach in resources:
+    mach.get_components()
+
+  #Update the resource catalog dom object for further dump
+  for mach in resources:
+    mach.update()
+
+  #dump new CatalogResources.xml
+  f=open(catalog_file,'w')
+  f.write('<?xml version="1.0" ?>\n')
+  doc.write(f)
+  f.write('\n')
+  f.close()
+  print "%s updated" % catalog_file
+
+  #update configRemote.sh in env.d directory (environment variable SALOME_CATALOGS_PATH)
+  path=[]
+  for mach in resources:
+    if mach.resource_dir:
+      path.append(mach.resource_dir)
+
+  f=open(os.path.join(appli_local,"env.d","configRemote.sh"),'w')
+  f.write("export SALOME_CATALOGS_PATH=%s\n" % SEP.join(path))
+  f.close()
+
+
+if __name__ == '__main__':
+  main()
+