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 ${features.repo}
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>
    <features.repo>mvn:org.o-ran-sc.oam.features/devicemanager-oran-ru-fh-feature/${o-ran-sc.features.version}/xml/features</features.repo>
    <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.
  • No labels