第6部分:通知Notification

8 篇文章 0 订阅
8 篇文章 0 订阅

6部分:通知

这部分将利用MD-SAL的主动通知服务,当重大事件发生时使OpenDaylightToaster发送通知。通知可以被注册监听实现或者外部netconf客户使用。如果有一个面包放入的话,一个烤面包机可以只做烤面包。目前,我们的OpenDaylightToaster可以无限供应面包,这在现实世界中这是不现实的。我们将修改OpenDaylightToaster使其可以有限供应烤面包。我们将保持简单和维护一个总体限制,包括所有类型的面包,而不是限制每个面包的类型。

当开始制作面包时,如果没有面包,一个toasterOutOfBread通知将会被发送。

我们还会添加一个RPC调用——restock-toaster,可以用来设置面包存货的数量。除此之外将会发送一个toasterRestocked通知。

当我们收到通知时KitchenService将会为notifications and act accordingly注册。

1.1 定义notifications 和 RPC

toaster.yang文件中,我们将定义2notifications和RPC

1. module toaster {

1.    ... 

2.    rpc restock-toaster {

3.        description

4.          "Restocks the toaster with the amount of bread specified.";

5.        

6.   

7.        input {

8.            leaf amountOfBreadToStock {

9.                type uint32;

10.                description

11.                  "Indicates the amount of bread to re-stock";

12.            }

13.        }

14.    }

15.    

16.  

17.    notification toasterOutOfBread {

18.      description

19.        "Indicates that the toaster has run of out bread.";

20.    }  // notification toasterOutOfStock

21.    

22.  

23.    notification toasterRestocked {

24.      description

25.        "Indicates that the toaster has run of out bread.";

26.      leaf amountOfBread {

27.        type uint32;

28.        description

29.          "Indicates the amount of bread that was re-stocked";

30.      }

31.    }  // notification toasterRestocked

32.    

33.  }  // module toaster

之后运行以下代码,会生成几个新的类。

1. mvn clean install

l ToasterOutOfBread - 一个接口,为toasterOutOfBread notification定义一个DTO

l ToasterOutOfBreadBuilder -一个具体类,为创建ToasterOutOfBread实例。

l ToasterRestocked -一个接口,为toasterRestocked notification定义一个DTO

l ToasterRestockedBuilder -一个具体类,为创建ToasterRestocked实例。

l ToasterListener - 一个接口,该接口用来接受定义在Module中的Notifications,该类继承自包org.opendaylight.yangtools.yang.binding中的NotificationListener接口,并在接口中声明了对Notification进行处理的方法。

1.2 在OpenDaylightToaster实现notifications 和RPC 

接下来我们在OpenDaylightToaster添加一段代码用来实现restockToaster RPC并发送通知。

1. public class OpendaylightToaster implements ToasterService, ToasterProviderRuntimeMXBean, AutoCloseable, DataChangeListener {

34.    ...

35.    private NotificationProviderService notificationProvider;

36.    ...

37.    private final AtomicLong amountOfBreadInStock = new AtomicLong( 100 );

38.    ...

39.    public void setNotificationProvider(NotificationProviderService salService) {

40.        this.notificationProvider = salService;

41.    }

42.    ...

43.    

44.  

45.    private void checkStatusAndMakeToast( final MakeToastInput input,

46.                                          final SettableFuture<RpcResult<Void>> futureResult ) {

47.   

48.        ...  

49.        final ListenableFuture<RpcResult<TransactionStatus>> commitFuture =

50.            Futures.transform( readFuture, new AsyncFunction<Optional<DataObject>,

51.                                                                    RpcResult<TransactionStatus>>() {

52.  

53.                @Override

54.                public ListenableFuture<RpcResult<TransactionStatus>> apply(

55.                        Optional<DataObject> toasterData ) throws Exception {

56.  

57.                    ...

58.                    if( toasterStatus == ToasterStatus.Up ) {

59.  

60.                       if( outOfBread() ) {

61.                           LOG.debug( "Toaster is out of bread" );

62.  

63.                           return Futures.immediateFuture( Rpcs.<TransactionStatus>getRpcResult(

64.                                       false, null, makeToasterOutOfBreadError() ) );

65.                       }

66.  

67.                       ...

68.                   }

69.                   ...

70.               }

71.       } );

72.       ...  

73.   }

74.   ...

75.    /**

76.     * RestConf RPC call implemented from the ToasterService interface.

77.     * Restocks the bread for the toaster and sends a ToasterRestocked notification.

78.     */

79.    @Override

80.    public Future<RpcResult<java.lang.Void>> restockToaster(RestockToasterInput input) {

81.        LOG.info( "restockToaster: " + input );

82.        

83.        amountOfBreadInStock.set( input.getAmountOfBreadToStock() );

84.        

85.        if( amountOfBreadInStock.get() > 0 ) {

86.            ToasterRestocked reStockedNotification =

87.                new ToasterRestockedBuilder().setAmountOfBread( input.getAmountOfBreadToStock() ).build();

88.            notificationProvider.publish( reStockedNotification );

89.        }

90.        

91.        return Futures.immediateFuture(Rpcs.<Void> getRpcResult(true, Collections.<RpcError> emptySet()));

92.    }

93.    ...

94.    private boolean outOfBread()

95.    {

96.        return amountOfBreadInStock.get() == 0;

97.    }

98.    

99.  

100.    private class MakeToastTask implements Callable<Void> {

101.        ...

102.        @Override

103.        public Void call() throws InterruptedException {

104.            ...

105.            amountOfBreadInStock.getAndDecrement();

106.            if( outOfBread() ) {

107.                LOG.info( "Toaster is out of bread!" );

108.                

109.                notificationProvider.publish( new ToasterOutOfBreadBuilder().build() );

110.            }

111.            ...

112.        }

113.    }

1.3 把notifications连接到OpenDaylightToaster

OpenDaylightToaster需要访问MD-SAL的 NotificationProviderService以发送通知。我们需要指定the NotificationProviderService,作为一个在toaster-provider-impl模块中的依赖通过向config:configuration添加一个条目:

1.   augment "/config:modules/config:module/config:configuration" {

114.        case toaster-consumer-impl {

115.            when "/config:modules/config:module/config:type = 'toaster-consumer-impl'";

116.            ...

117.            

118.  

119.            container notification-service {

120.                uses config:service-ref {

121.                    refine type {

122.                        mandatory true;

123.                        config:required-identity mdsal:binding-notification-service;

124.                    }

125.                }

126.            }

127.        }

128.    }

运行mvn clean install的产生源代码。

生成的AbstractToasterProviderModule类现在应该有一个getNotificationServiceDependency()方法。在ToasterProviderModule.createInstance()方法中,我们可以访问该方法,去把NotificationProviderService注入到OpenDaylightToaster中。

1. opendaylightToaster.setNotificationProvider(getNotificationServiceDependency());

最后我们需要为notification-service添加依赖到初始化配置XML文件中的toaster-provider-impl模块,正如我们之前对'rpc-registry'所做的:

1. <snapshot>

129.    <configuration>

130.        

131.            <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">

132.                <module>

133.                    ...

134.                    <notification-service>

135.                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">

136.                            binding:binding-notification-service

137.                        </type>

138.                        <name>binding-notification-broker</name>

139.                    </notification-service>

140.                </module>

141.            </modules>

142.            ...

143.        

144.    </configuration>

145.    ...

146. </snapshot>

1.4 在KitchenServiceImpl中实现notifications

接下来我们修改KitchenServiceImpl去实现ToasterListener接口和notification方法。

1. public class KitchenServiceImpl implements KitchenService, KitchenServiceRuntimeMXBean, ToasterListener {

147.    ...

148.    private volatile boolean toasterOutOfBread;

149.    

150.  

151.    private Future<RpcResult<Void>> makeToast( Class<? extends ToastType> toastType,

152.                                               int toastDoneness ) {

153.  

154.        if( toasterOutOfBread )

155.        {

156.            log.info( "We're out of toast but we can make eggs" );

157.            return Futures.immediateFuture( Rpcs.<Void> getRpcResult( true,

158.                       Arrays.asList( RpcErrors.getRpcError( "", "partial-operation", null,

159.                                          ErrorSeverity.WARNING,

160.                                          "Toaster is out of bread but we can make you eggs",

161.                                          ErrorType.APPLICATION, null ) ) ) );

162.        }

163.  

164.        // Access the ToasterService to make the toast.

165.  

166.        MakeToastInput toastInput = new MakeToastInputBuilder()

167.            .setToasterDoneness( (long) toastDoneness )

168.            .setToasterToastType( toastType )

169.            .build();

170.  

171.        return toaster.makeToast( toastInput );

172.    }

173.    ...

174.    /**

175.     * Implemented from the ToasterListener interface.

176.     */

177.    @Override

178.    public void onToasterOutOfBread( ToasterOutOfBread notification ) {

179.        log.info( "ToasterOutOfBread notification" );

180.        toasterOutOfBread = true;

181.    }

182.    

183.  

184.    /**

185.     * Implemented from the ToasterListener interface.

186.     */

187.    @Override

188.    public void onToasterRestocked( ToasterRestocked notification ) {

189.        log.info( "ToasterRestocked notification - amountOfBread: " + notification.getAmountOfBread() );

190.        toasterOutOfBread = false;

191.    }

192. }

onToasterOutOfBread 和onToasterRestocked notification方法简单地设置和清除toasterOutOfBread。当开始做早餐时,如果toasterOutOfBread,我们不能做面包但试图去做鸡蛋,所以有人至少可以吃早餐。

1.5 为notifications连接KitchenServiceImpl  

KitchenServiceImpl需要通过MD-SAL's NotificationProviderService注册,用来接收通知。我们需要去指定notification-service作为一个在kitchen-service-impl 模块中的依赖通过向config:configuration添加一个条目:

1.  augment "/config:modules/config:module/config:configuration" {

193.        case kitchen-service-impl {

194.            when "/config:modules/config:module/config:type = 'kitchen-service-impl'";

195.            ...

196.            

197.  

198.            container notification-service {

199.                uses config:service-ref {

200.                    refine type {

201.                        mandatory true;

202.                        config:required-identity mdsal:binding-notification-service;

203.                    }

204.                }

205.            }

206.        }

207.    }

运行mvn clean install的产生源代码。

生成的AbstractKitchenServiceModule类现在应该有一个getNotificationServiceDependency()方法。

我们可以访问在KitchenServiceModule.createInstance()方法中的该方法,来通过NotificationProviderService注册KitchenServiceImpl 

1.  public java.lang.AutoCloseable createInstance() {

208.        ...

209.        final Registration<NotificationListener> toasterListenerReg =

210.                getNotificationServiceDependency().registerNotificationListener( kitchenService );

211.        

212.  

213.        final KitchenServiceRuntimeRegistration runtimeReg =

214.                getRootRuntimeBeanRegistratorWrapper().register( kitchenService );

215.        

216.  

217.        final class AutoCloseableKitchenService implements KitchenService, AutoCloseable  {

218.            @Override

219.            public void close() throws Exception {

220.                toasterListenerReg.close();

221.                runtimeReg.close();

222.                log.info("Toaster consumer (instance {}) torn down.", this);

223.            }

224.            ...

225.        }

226.        ...

227.    }

最后,我们需要为'notification-service'添加依赖到初始化配置XML文件中的kitchen-service-impl模块。

1. <snapshot>

228.   <configuration>

229.       

230.           <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">

231.               ...

232.               <module>

233.                   ...

234.                   <notification-service>

235.                       <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">

236.                           binding:binding-notification-service

237.                       </type>

238.                       <name>binding-notification-broker</name>

239.                   </notification-service>

240.               </module>

241.           </modules>

242.           ...

243.       

244.   </configuration>

245.   ...

246. </snapshot>

1.6 测试notifications

我们将首先在没有面包的情况下运行烤面包机。默认现有面包数是100。而不是花时间去制作100个面包,我们首先会调用restock-toaster RPC通过restconf去把这个数值降低到3

1. HTTP Method => POST

247. URL => http://localhost:8080/restconf/operations/toaster:restock-toaster 

248. Header => Content-Type: application/yang.data+json  

249. Body =>  

250. {

251.   "input" :

252.   {

253.      "toaster:amountOfBreadToStock" : "3"

254.   }

255. }

接下来,我们将做3份早餐订单耗尽现有的面包。

l 打开JConsole

l 导航到MBeans选项卡

l 展开org.opendaylight.controller->RuntimeBean->kitchen-service-impl->kitchen-service-imp->Operations结点

l 点击makeScrambledWithWheat按钮三次

在完成最后一份早餐后,烤面包机将没有面包并发送toasterOutOfBread通知kitchen服务。你可以在controllerlog/console中看到这个消息:

1.  ...KitchenServiceImpl - ToasterOutOfBread notification

再次点击makeScrambledWithWheat——结果应该是真实的,你应该会看到这个消息在日志中:

1. ...KitchenServiceImpl - We're out of toast but we can make eggs

再次调用restock-toaster——您应该看到这个消息在日志中:

1.   ...KitchenServiceImpl - ToasterRestocked notification - amountOfBread: 3

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值