/* * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.lispflowmapping.netconf.impl; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; import org.opendaylight.lispflowmapping.netconf.impl.LispNetconfConnector; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lispflowmapping.netconf.rev140706.BuildConnectorInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lispflowmapping.netconf.rev140706.LfmNetconfConnectorService; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lispflowmapping.netconf.rev140706.RemoveConnectorInput; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcError.ErrorType; import org.opendaylight.controller.config.api.ConflictingVersionException; import org.opendaylight.controller.config.api.ValidationException; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.slf4j.LoggerFactory; import org.slf4j.Logger; import com.google.common.util.concurrent.SettableFuture; public class LispDeviceNetconfConnector implements AutoCloseable, LfmNetconfConnectorService { private static final Logger logger = LoggerFactory.getLogger(LispDeviceNetconfConnector.class); private final ExecutorService executor; private LispNetconfConnector nconfConnector; public static LispDeviceNetconfConnector createLispDeviceNetconfConnector() { return new LispDeviceNetconfConnector(Executors.newFixedThreadPool(1), new LispNetconfConnector()); } public LispDeviceNetconfConnector(ExecutorService executor, LispNetconfConnector nconfConnector) { this.executor = executor; this.nconfConnector = nconfConnector; logger.info( "LispDeviceNetconfConnector constructed" ); } /** * Implemented from the AutoCloseable interface. */ @Override public void close() throws ExecutionException, InterruptedException { executor.shutdown(); } /** * RestConf RPC call implemented from the LfmNetconfConnectorService interface. */ @Override public Future> buildConnector(final BuildConnectorInput input) { SettableFuture> futureResult = SettableFuture.create(); logger.trace("Received RPC to buildConnector: " + input); if (verifyBuildInput(input, futureResult) != true) { return futureResult; } return executor.submit(new MakeConnector(input)); } @Override public Future> removeConnector(final RemoveConnectorInput input) { SettableFuture> futureResult = SettableFuture.create(); if (verifyRemoveInput(input, futureResult) != true) { return futureResult; } return executor.submit(new RemoveConnector(input) ); } private boolean verifyBuildInput(final BuildConnectorInput req, SettableFuture> futureResult ) { if (req.getInstance() == null) { logger.error("Instance name not initialized"); futureResult.set(RpcResultBuilder. failed() .withError(ErrorType.APPLICATION, "exception", "Instance name not initialized") .build()); return false; } if (req.getAddress() == null) { logger.error("IP address not initialized"); futureResult.set(RpcResultBuilder. failed() .withError(ErrorType.APPLICATION, "exception", "IP address not initialized") .build()); return false; } if (req.getPort() == null) { logger.error("Port not initialized"); futureResult.set(RpcResultBuilder. failed() .withError(ErrorType.APPLICATION, "exception", "Port not initialized") .build()); return false; } if (req.getUsername() == null) { logger.error("Username not initialized"); futureResult.set(RpcResultBuilder. failed() .withError(ErrorType.APPLICATION, "exception", "Username not initialized") .build()); return false; } if (req.getPassword() == null) { logger.error("Password not initialized"); futureResult.set(RpcResultBuilder. failed() .withError(ErrorType.APPLICATION, "exception", "Password not initialized") .build()); return false; } return true; } private boolean verifyRemoveInput(final RemoveConnectorInput conn, SettableFuture> futureResult) { if (conn.getInstance() == null) { logger.error("Instance name not initialized"); futureResult.set(RpcResultBuilder. failed() .withError(ErrorType.APPLICATION, "exception", "Instance name not initialized") .build()); return false; } return true; } private class MakeConnector implements Callable> { final BuildConnectorInput buildConnectorInput; public MakeConnector(final BuildConnectorInput buildConnectorInput) { this.buildConnectorInput = buildConnectorInput; } @Override public RpcResult call() { try { nconfConnector.createNetconfConnector(buildConnectorInput.getInstance(), buildConnectorInput.getAddress(), buildConnectorInput.getPort().getValue(), buildConnectorInput.getUsername(), buildConnectorInput.getPassword()); logger.info("LispNetconfConnector {} built", buildConnectorInput.getInstance()); return RpcResultBuilder.success().build(); } catch( InstanceAlreadyExistsException e ) { logger.error("LispNetconfConnector {} already exists!", buildConnectorInput.getInstance()); return RpcResultBuilder. failed() .withError(ErrorType.APPLICATION, "exists", "LispNetconfConnector exists") .build(); } catch (ConflictingVersionException ex) { logger.error("LispNetconfConnector {} version exception", buildConnectorInput.getInstance()); return RpcResultBuilder. failed() .withError(ErrorType.APPLICATION, "exception", "LispNetconfConnector version exception") .build(); } catch ( ValidationException ex) { logger.error("LispNetconfConnector {} validation exception", buildConnectorInput.getInstance()); return RpcResultBuilder. failed() .withError(ErrorType.APPLICATION, "exception", "LispNetconfConnector validation exception") .build(); } } } private class RemoveConnector implements Callable> { final RemoveConnectorInput removeConnectorInput; public RemoveConnector(final RemoveConnectorInput connectorInput) { this.removeConnectorInput = connectorInput; } @Override public RpcResult call() { try { nconfConnector.removeNetconfConnector(removeConnectorInput.getInstance()); logger.info("LispNetconfConnector {} removed!", removeConnectorInput.getInstance()); return RpcResultBuilder. success().build(); } catch( InstanceNotFoundException e ) { logger.info("LispNetconfConnector {} doesn't exists!", removeConnectorInput.getInstance()); return RpcResultBuilder. failed() .withError(ErrorType.APPLICATION, "no-exist", "LispNetconfConnector doesn't exist") .build(); } catch( ValidationException e ) { logger.info("LispNetconfConnector {}: Could not validate remove transactions!", removeConnectorInput.getInstance()); return RpcResultBuilder. failed() .withError(ErrorType.APPLICATION, "fail", "LispNetconfConnector doesn't exist") .build(); } catch (ConflictingVersionException e) { logger.error("LispNetconfConnector {}: Cannot remove due to conflicting version", removeConnectorInput.getInstance() ); return RpcResultBuilder. failed() .withError(ErrorType.APPLICATION, "fail", "Conflicting version exception") .build(); } catch (Exception e) { logger.error("LispNetconfConnector {} exception while removing: {}", removeConnectorInput.getInstance(), e.getClass()); return RpcResultBuilder. failed() .withError(ErrorType.APPLICATION, "fail", "Cannot remove LispNetconfConnector: " + removeConnectorInput.getInstance()) .build(); } } } }