This tutorial shows how you can test your custom feature by creating and starting a minimal distribution. As example we will do it for the o-ran-sc for a o-ran radio unit front haul(ru-fh) devicemanager for ONAP Frankfurt.
Odl feature
To create an odl/ONAP feature you have to create at least three parts:
- provider with your code
- feature which defines the odl bundles to startup
- installer which brings the artifacts into the container
A good example is the SDN-R helpserver which has only these parts or the o-ran ru-fh devicemanager.
Distribution
To create a distribution within our custom feature based on sdnc-image we need three files.
├── pom.xml ├── src │ └── main │ ├── docker │ │ └── Dockerfile │ └── scripts │ └── TagVersion.groovy
- TagVersion.groovy
package org.oransc.oam.distribution def versionArray; if ( project.properties['o-ran-sc.project.version'] != null ) { versionArray = project.properties['o-ran-sc.project.version'].split('\\.'); } if ( project.properties['o-ran-sc.project.version'].endsWith("-SNAPSHOT") ) { patchArray = versionArray[2].split('-'); project.properties['project.docker.latestminortag.version']=versionArray[0] + '.' + versionArray[1] + "-SNAPSHOT-latest"; project.properties['project.docker.latestfulltag.version']=versionArray[0] + '.' + versionArray[1] + '.' + patchArray[0] + "-SNAPSHOT-latest"; project.properties['project.docker.latesttagtimestamp.version']=versionArray[0] + '.' + versionArray[1] + '.' + patchArray[0] + "-SNAPSHOT-"+project.properties['ccsdk.build.timestamp']; } else { project.properties['project.docker.latestminortag.version']=versionArray[0] + '.' + versionArray[1] + "-STAGING-latest"; project.properties['project.docker.latestfulltag.version']=versionArray[0] + '.' + versionArray[1] + '.' + versionArray[2] + "-STAGING-latest"; project.properties['project.docker.latesttagtimestamp.version']=versionArray[0] + '.' + versionArray[1] + '.' + versionArray[2] + "-STAGING-"+project.properties['ccsdk.build.timestamp']; }
- Dockerfile
# Base odl alpine with added packages needed for FROM ${base.image.repo} ENV SDNR_ORAN_REPO ${o-ran-sc.features} RUN sed -i -e "\|featuresRepositories|s|$|,${SDNR_ORAN_REPO}|" $ODL_HOME/etc/org.apache.karaf.features.cfg ENV SDNRWT_BOOTFEATURES ${features.boot} USER root # copy CCSDK mvn artifacts to ODL repository COPY system /tmp/system RUN rsync -a /tmp/system $ODL_HOME && rm -rf /tmp/system RUN chown -R odl:odl $ODL_HOME USER odl
- pom file
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.parent</groupId> <artifactId>odlparent-lite</artifactId> <version>1.5.2-SNAPSHOT</version> <relativePath /> </parent> <groupId>org.o-ran-sc.distribution</groupId> <artifactId>distribution-ru-fh-controller</artifactId> <version>0.7.1-SNAPSHOT</version> <packaging>pom</packaging> <name>sdnc-distribution :: o-ran-sc :: ru-fh-controller</name> <description>SDNC Docker container with rh-fh-devicemanager controller</description> <organization> <name>openECOMP</name> </organization> <properties> <base.image.repo>nexus3.onap.org:10001/onap/sdnc-image:1.8.0-STAGING-20200225T124813Z</base.image.repo> <image.name>o-ran-sc/sdnc-ru-fh-image</image.name> <ccsdk.build.timestamp>${maven.build.timestamp}</ccsdk.build.timestamp> <o-ran-sc.project.version>${project.version}</o-ran-sc.project.version> <o-ran-sc.features.version>${project.version}</o-ran-sc.features.version> <o-ran-sc.features>mvn:org.o-ran-sc.oam.features/devicemanager-oran-ru-fh-feature/${o-ran-sc.features.version}/xml/features</o-ran-sc.features> <features.boot>sdnr-wt-feature-aggregator,devicemanager-oran-ru-fh-feature</features.boot> <platform-logic-installer.version>${project.version}</platform-logic-installer.version> <docker.buildArg.https_proxy>${https_proxy}</docker.buildArg.https_proxy> <maven.build.timestamp.format>yyyyMMdd'T'HHmmss'Z'</maven.build.timestamp.format> <opendaylight.root>opt/opendaylight</opendaylight.root> <docker.push.phase>deploy</docker.push.phase> <docker.verbose>true</docker.verbose> </properties> <dependencies> <dependency> <groupId>org.o-ran-sc.oam.features</groupId> <artifactId>devicemanager-oran-ru-fh-installer</artifactId> <version>${o-ran-sc.features.version}</version> <classifier>repo</classifier> <type>zip</type> </dependency> </dependencies> <build> <extensions> <extension> <!-- this extension is required by wagon in order to pass the proxy --> <groupId>org.apache.maven.wagon</groupId> <artifactId>wagon-http-lightweight</artifactId> <version>2.2</version> </extension> </extensions> <plugins> <plugin> <groupId>org.codehaus.groovy.maven</groupId> <artifactId>gmaven-plugin</artifactId> <version>1.0</version> <executions> <execution> <phase>validate</phase> <goals> <goal>execute</goal> </goals> <configuration> <source>${basedir}/src/main/scripts/TagVersion.groovy</source> </configuration> </execution> </executions> </plugin> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>2.6</version> <executions> <execution> <id>copy-dockerfile</id> <goals> <goal>copy-resources</goal> </goals> <!-- here the phase you need --> <phase>validate</phase> <configuration> <outputDirectory>${basedir}/target/docker-stage</outputDirectory> <resources> <resource> <directory>src/main/docker</directory> <includes> <include>Dockerfile</include> </includes> <filtering>true</filtering> </resource> </resources> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>unpack features</id> <phase>generate-sources</phase> <goals> <goal>unpack-dependencies</goal> </goals> <configuration> <outputDirectory>${basedir}/target/docker-stage</outputDirectory> <excludeTransitive>true</excludeTransitive> <overWriteReleases>false</overWriteReleases> <overWriteSnapshots>true</overWriteSnapshots> <overWriteIfNewer>true</overWriteIfNewer> </configuration> </execution> </executions> </plugin> <plugin> <groupId>io.fabric8</groupId> <artifactId>docker-maven-plugin</artifactId> <version>0.28.0</version> <inherited>false</inherited> <configuration> <images> <image> <name>${image.name}</name> <build> <cleanup>try</cleanup> <dockerFileDir>${basedir}/target/docker-stage</dockerFileDir> <tags> <tag>${project.docker.latestminortag.version}</tag> <tag>${project.docker.latestfulltag.version}</tag> <tag>${project.docker.latesttagtimestamp.version}</tag> </tags> </build> </image> </images> </configuration> <executions> <execution> <id>generate-images</id> <phase>package</phase> <goals> <goal>build</goal> </goals> </execution> <execution> <id>push-images</id> <phase>${docker.push.phase}</phase> <goals> <goal>build</goal> <goal>push</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
The only thing you have to do is to manipulate the properties and the dependencies in the pom.xml.
- base-image: on which you want to run your custom feature
- o-ran-sc.features: which is the feature repo you have to add (should look like this mvn:org.something.more/myartifact-feature/version/xml/features
- features.boot: which will add the features to the odl boot features on startup
- and you have to add the dependency (in this case devicemanager-oran-ru-fh-installer) to inject the artifacts into the container during build process.