How do I create ONOS application?
using HostToHostIntent
"ONOS 기반의 어플리케이션 개발은 어떻게 하면 되는지요?" 라는 질문을 참 많이 받는다.
어찌보면 그만큼 관심이 많다라고 생각이 되어진다.
그 동안 SDN Controller 관련 과제를 하면서 SDN Controller의 성패는 다양한 Application의 지원여부 라는 생각을 항상 하였다.
아무래도 실제 SDN Controller를 사용하는 사람들이 필요에 의해 작성한 Application이 결과가 아닐까?
SDN Controller가 크게 두개의 진영(?)으로 나뉘어 졌다고 해도...
사용자들이 필요로하는 Application은 ODL 이건 ONOS 이건 바뀌지 않을 것 이다.
결국 어떤 Controller가 Application을 작성하는데 쉽고 간편한지가 키포인트가 될 것 이다.
본 포스팅에서는 ONOS의 특징이라 할 수 있는 Intent를 사용한 번들을 생성하는 방법에 대하여 알아보고자 한다.
사용할 Intent는 HostToHostIntent 이다.
디렉토리 생성
작성하고자 하는 Application 구상이 완료되었다면 소스파일이 위치할 디렉토리를 지정해 보도록 하자.
(본 샘플에서는 HostToHostIntent를 활용하는 Application을 작성할 것 이다.)
적당한 위치에 작업할 디렉토리를 생성하도록 하자.
$ mkdir etri
디렉토리가 생성되었으면 해당 디렉토리로 이동한다.
$ cd etri
Application 생성
이제 머리속으로 구상한 Application을 생성하는 단계로 들어가보자.
ONOS는 Maven 번들로 구성이 되어 있다.
즉, Maven 번들을 생성하여야 한다.
$ mvn archetype:generate -Dfilter=org.onosproject: -DarchetypeGroupId=org.onosproject -DarchetypeArtifactId=onos-bundle-archetype -DarchetypeVersion=1.2.2
Maven Stub file Building 중에 다음과 같은 내용을 작성한다.
(원하는 내용을 작성하면 된다.)
- Defined value for propetry 'groupId' : : org.iris4sdn.mesh
- Defined value for propetry 'artifactId': : iris-mesh
이후 내용은 default 설정으로 한다. (prompt에서 Enter)
디렉토리의 artifactId 를 확인하고 artifactId 디렉토리로 접근하면 pom.xml을 확인할 수 있다.
Intellij Import
확인한 pom.xml 파일을 Intellij에 import 한다.
그외 내용은 ONOS import 과정과 동일하다.
이제 HostToHostIntent를 활용한 간단한 Application을 작성하여보자.
소스파일은 다음과 같다.
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.iris4sdn.mesh;
import com.google.common.collect.Lists;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.Host;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.onosproject.net.intent.HostToHostIntent;
import org.onosproject.net.intent.IntentService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
/**
* Skeletal ONOS application component.
*/
@Component(immediate = true)
public class MeshInstaller {
private final Logger log = LoggerFactory.getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected IntentService intentService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostService hostService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private CoreService coreService;
private InternalHostListener hostListener = new InternalHostListener();
private List<Host> hosts = Lists.newArrayList();
private ApplicationId appId;
@Activate
protected void activate() {
appId = coreService.registerApplication("org.iris4sdn.mesh");
hostService.addListener(hostListener);
log.info("Started");
}
@Deactivate
protected void deactivate() {
hostService.removeListener(hostListener);
log.info("Stopped");
}
private class InternalHostListener implements HostListener {
@Override
public void event(HostEvent hostEvent) {
switch (hostEvent.type()) {
case HOST_ADDED:
addConnectivity(hostEvent.subject());
hosts.add(hostEvent.subject());
break;
case HOST_REMOVED:
break;
case HOST_UPDATED:
break;
case HOST_MOVED:
break;
}
}
}
private void addConnectivity(Host host) {
for (Host dst : hosts) {
HostToHostIntent intent = HostToHostIntent.builder().appId(appId).one(host.id()).two(dst.id()).build();
intentService.submit(intent);
}
}
}
Maven Install
pom.xml을 확인한다. (ONOS Version 등에 주의하고 원하는 버전으로 수정한다.)
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2014 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<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>
<groupId>org.iris4sdn.mesh</groupId>
<artifactId>iris-mesh</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<description>ONOS OSGi bundle archetype</description>
<url>http://onosproject.org</url>
<properties>
<onos.version>1.2.3-SNAPSHOT</onos.version>
<!-- Uncomment to generate ONOS app from this module.
<onos.app.name>org.foo.app</onos.app.name>
<onos.app.origin>Foo, Inc.</onos.app.origin>
-->
</properties>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
<version>${onos.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-osgi</artifactId>
<version>${onos.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
<version>${onos.version}</version>
<scope>test</scope>
<classifier>tests</classifier>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
<version>1.9.8</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.5.3</version>
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.20.0</version>
<executions>
<execution>
<id>generate-scr-srcdescriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
<configuration>
<supportedProjectTypes>
<supportedProjectType>bundle</supportedProjectType>
<supportedProjectType>war</supportedProjectType>
</supportedProjectTypes>
</configuration>
</plugin>
<plugin>
<groupId>org.onosproject</groupId>
<artifactId>onos-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<id>cfg</id>
<phase>generate-resources</phase>
<goals>
<goal>cfg</goal>
</goals>
</execution>
<execution>
<id>app</id>
<phase>package</phase>
<goals>
<goal>app</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
$ mvn clean install
ERROR가 발생하면 소스에서 test 부분을 삭제한다.
(test 관련 소스를 만들지 않았기에 발생하는 오류이다.)
test 부분을 나중에 작성할 경우 skipTests 옵션을 사용한다.
$ mvn clean install -DskipTests
ONOS 시스템을 시작한다.
$ karaf clean
번들 내용을 install 한다.
onos> bundle:install mvn:org.iris4sdn.mesh/iris-mesh/1.0-SNAPSHOT
onos> start mesh-app
mininet을 실행한다.
$ sudo mn --topo linear,4 --controller remote,ip=192.168.56.101 --mac
intent 적용을 확인하기 위하여 host간 ping을 한다.
mininet> pingall
intent 적용이 되었는지 확인한다.
onos> intents
'Software Defined Network > Develop_SDN' 카테고리의 다른 글
OpenStack Summit 2016 Barcelona Presentation (0) | 2016.10.27 |
---|