Replacing karaf-assembly bash script with python script

Also, removing self-referencing repo from:
apps/openstackswitching/app/features.xml

Change-Id: I041325a1a114ee4d5ef01afd24f73db4f92b30b3
diff --git a/tools/package/karaf-assembly/onos-assembly b/tools/package/karaf-assembly/onos-assembly
deleted file mode 100755
index ece4409..0000000
--- a/tools/package/karaf-assembly/onos-assembly
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/bash
-# -----------------------------------------------------------------------------
-# Assembles together all bundles required to run ONOS off-line.
-# -----------------------------------------------------------------------------
-
-mkdir -p target
-
-features=target/features-list.xml
-repos=target/staged-repos.xml
-
-echo "<features>" > $repos
-echo "    <repository>mvn:org.onosproject/onos-features/1.4.0-SNAPSHOT/xml/features</repository>" >> $repos
-
-# Find all app feature files
-find $ONOS_ROOT -name '*-features.xml' | grep -v features-repo > $features
-
-# Produce repository entry for each file
-cat $features | while read feature; do
-    echo "    <repository>file:$feature</repository>" >> $repos
-done
-
-# Create a synthetic feature that depends on all other ONOS features
-echo "   <feature name=\"foo\">" >> $repos
-grep "feature name=" $ONOS_ROOT/features/features.xml | cut -d\" -f2 | while read f; do
-    echo "        <feature>$f</feature>" >> $repos
-done
-
-cat $features | while read feature; do
-    grep "feature name=" $feature | cut -d\" -f2 | while read f; do
-        echo "        <feature>$f</feature>" >> $repos
-    done
-done
-echo "   </feature>" >> $repos
-
-echo "</features>" >> $repos
\ No newline at end of file
diff --git a/tools/package/karaf-assembly/onos-assembly.py b/tools/package/karaf-assembly/onos-assembly.py
new file mode 100755
index 0000000..1e394bf
--- /dev/null
+++ b/tools/package/karaf-assembly/onos-assembly.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+'''
+  Builds synthetic feature file that includes all core, provider, and application
+  features, so that we can pre-stage all bundles required to run ONOS off-line.
+'''
+
+import os
+import xml.etree.ElementTree as ET
+
+FEATURE_TAG = '{http://karaf.apache.org/xmlns/features/v1.2.0}feature'
+STAGED_REPOS = 'target/staged-repos.xml'
+
+if 'ONOS_ROOT' in os.environ:
+    ONOS_ROOT = os.environ['ONOS_ROOT']
+else:
+    # fallback to working directory if ONOS_ROOT is not set
+    ONOS_ROOT = os.getcwd()
+
+def findFeatureFiles(path=ONOS_ROOT):
+    #only descend into target directories that have pom
+    for root, dirs, files in os.walk(path):
+        if 'pom.xml' not in files:
+            if 'target' in dirs:
+                #pruning target dir with no pom.xml
+                dirs.remove('target')
+        if '/target' in root:
+            if '/classes/' in root:
+                #filter out features.xml for maven-plugin
+                continue
+            for f in files:
+                if f.endswith('features.xml'):
+                    yield os.path.join(root, f)
+
+def featuresFromFile(file):
+    features = []
+    tree = ET.parse(file)
+    root = tree.getroot()
+    for feature in root.findall(FEATURE_TAG):
+        features.append(feature.attrib['name'])
+    return features
+
+if __name__ == '__main__':
+    outputTree = ET.Element('features')
+    uberFeature = ET.Element('feature', attrib={'name' : 'onos-uber-synthetic'})
+    for file in findFeatureFiles():
+        features = featuresFromFile(file)
+        if len(features) > 0:
+            ET.SubElement(outputTree, 'repository').text = 'file:%s' % file
+            for feature in features:
+                ET.SubElement(uberFeature, 'feature').text = feature
+    outputTree.append(uberFeature)
+
+    outputFile = os.path.join(os.path.dirname(os.path.realpath(__file__)), STAGED_REPOS)
+    outputDir = os.path.dirname(outputFile)
+    if not os.path.exists(outputDir):
+        os.mkdir(outputDir)
+    ET.ElementTree(outputTree).write(outputFile)
+
+    import sys
+    if '-d' in sys.argv:
+        # -------- TODO for debug only --------
+        def indent(elem, level=0):
+            #function borrowed from: http://effbot.org/zone/element-lib.htm#prettyprint
+            i = "\n" + level*"  "
+            if len(elem):
+                if not elem.text or not elem.text.strip():
+                    elem.text = i + "  "
+                if not elem.tail or not elem.tail.strip():
+                    elem.tail = i
+                for elem in elem:
+                    indent(elem, level+1)
+                if not elem.tail or not elem.tail.strip():
+                    elem.tail = i
+            else:
+                if level and (not elem.tail or not elem.tail.strip()):
+                    elem.tail = i
+
+        print 'Writing to file:', outputFile
+        indent(outputTree)
+        ET.dump(outputTree)
diff --git a/tools/package/karaf-assembly/pom.xml b/tools/package/karaf-assembly/pom.xml
index 5dcf539..38a3df4 100644
--- a/tools/package/karaf-assembly/pom.xml
+++ b/tools/package/karaf-assembly/pom.xml
@@ -42,8 +42,8 @@
                         <phase>generate-sources</phase>
                         <configuration>
                             <target>
-                                <exec executable="bash">
-                                    <arg value="${basedir}/onos-assembly"/>
+                                <exec executable="python">
+                                    <arg value="${basedir}/onos-assembly.py"/>
                                 </exec>
                             </target>
                         </configuration>
@@ -70,7 +70,7 @@
                                 <descriptor>file:${basedir}/target/staged-repos.xml</descriptor>
                             </descriptors>
                             <features>
-                                <feature>foo</feature>
+                                <feature>onos-uber-synthetic</feature>
                             </features>
                             <repository>target/repo</repository>
                         </configuration>