// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you 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 com.cloud.network.resource; import java.util.List; import java.util.Map; import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import com.cloud.agent.IAgentControl; import com.cloud.agent.api.Answer; import com.cloud.agent.api.AssociateMacToNetworkAnswer; import com.cloud.agent.api.AssociateMacToNetworkCommand; import com.cloud.agent.api.Command; import com.cloud.agent.api.CreateNetworkAnswer; import com.cloud.agent.api.CreateNetworkCommand; import com.cloud.agent.api.DeleteNetworkAnswer; import com.cloud.agent.api.DeleteNetworkCommand; import com.cloud.agent.api.DisassociateMacFromNetworkAnswer; import com.cloud.agent.api.DisassociateMacFromNetworkCommand; import com.cloud.agent.api.MaintainAnswer; import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.ReadyAnswer; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.StartupBrocadeVcsCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.host.Host; import com.cloud.host.Host.Type; import com.cloud.network.brocade.BrocadeVcsApi; import com.cloud.network.brocade.BrocadeVcsApiException; import com.cloud.network.schema.showvcs.Output; import com.cloud.network.schema.showvcs.VcsNodeInfo; import com.cloud.resource.ServerResource; public class BrocadeVcsResource implements ServerResource { private static final Logger s_logger = Logger.getLogger(BrocadeVcsResource.class); private String _name; private String _guid; private String _zoneId; private int _numRetries; private BrocadeVcsApi _brocadeVcsApi; protected BrocadeVcsApi createBrocadeVcsApi(String ip, String username, String password) { return new BrocadeVcsApi(ip, username, password); } @Override public boolean configure(String name, Map<String, Object> params) throws ConfigurationException { _name = (String)params.get("name"); if (_name == null) { throw new ConfigurationException("Unable to find name"); } _guid = (String)params.get("guid"); if (_guid == null) { throw new ConfigurationException("Unable to find the guid"); } _zoneId = (String)params.get("zoneId"); if (_zoneId == null) { throw new ConfigurationException("Unable to find zone"); } _numRetries = 2; String ip = (String)params.get("ip"); if (ip == null) { throw new ConfigurationException("Unable to find IP"); } String adminuser = (String)params.get("adminuser"); if (adminuser == null) { throw new ConfigurationException("Unable to find admin username"); } String adminpass = (String)params.get("adminpass"); if (adminpass == null) { throw new ConfigurationException("Unable to find admin password"); } _brocadeVcsApi = createBrocadeVcsApi(ip, adminuser, adminpass); return true; } @Override public boolean start() { return true; } @Override public boolean stop() { return true; } @Override public String getName() { return _name; } @Override public Type getType() { return Host.Type.L2Networking; } @Override public StartupCommand[] initialize() { StartupBrocadeVcsCommand sc = new StartupBrocadeVcsCommand(); sc.setGuid(_guid); sc.setName(_name); sc.setDataCenter(_zoneId); sc.setPrivateIpAddress(""); sc.setStorageIpAddress(""); sc.setVersion(BrocadeVcsResource.class.getPackage().getImplementationVersion()); return new StartupCommand[] {sc}; } @Override public PingCommand getCurrentStatus(long id) { Output output; try { output = _brocadeVcsApi.getSwitchStatus(); } catch (BrocadeVcsApiException e) { s_logger.error("getSwitchStatus failed", e); return null; } List<VcsNodeInfo> vcsNodes = output.getVcsNodes().getVcsNodeInfo(); if (vcsNodes != null && !vcsNodes.isEmpty()) { for (VcsNodeInfo vcsNodeInfo : vcsNodes) { if (!"Online".equals(vcsNodeInfo.getNodeState())) { s_logger.error("Brocade Switch is not ready: " + id); return null; } } } return new PingCommand(Host.Type.L2Networking, id); } @Override public Answer executeRequest(Command cmd) { return executeRequest(cmd, _numRetries); } public Answer executeRequest(Command cmd, int numRetries) { if (cmd instanceof ReadyCommand) { return executeRequest((ReadyCommand)cmd); } else if (cmd instanceof MaintainCommand) { return executeRequest((MaintainCommand)cmd); } else if (cmd instanceof CreateNetworkCommand) { return executeRequest((CreateNetworkCommand)cmd, numRetries); } else if (cmd instanceof AssociateMacToNetworkCommand) { return executeRequest((AssociateMacToNetworkCommand)cmd, numRetries); } else if (cmd instanceof DisassociateMacFromNetworkCommand) { return executeRequest((DisassociateMacFromNetworkCommand)cmd, numRetries); } else if (cmd instanceof DeleteNetworkCommand) { return executeRequest((DeleteNetworkCommand)cmd, numRetries); } s_logger.debug("Received unsupported command " + cmd.toString()); return Answer.createUnsupportedCommandAnswer(cmd); } @Override public void disconnected() { } @Override public IAgentControl getAgentControl() { return null; } @Override public void setAgentControl(IAgentControl agentControl) { } private Answer executeRequest(CreateNetworkCommand cmd, int numRetries) { try { boolean result = _brocadeVcsApi.createNetwork(cmd.getVlanId(), cmd.getNetworkId()); return new CreateNetworkAnswer(cmd, result, "Port Profile " + cmd.getNetworkId() + " created"); } catch (BrocadeVcsApiException e) { if (numRetries > 0) { return retry(cmd, --numRetries); } else { return new CreateNetworkAnswer(cmd, e); } } } private Answer executeRequest(AssociateMacToNetworkCommand cmd, int numRetries) { try { String mac = macReformat64To32(cmd.getInterfaceMac()); boolean result = _brocadeVcsApi.associateMacToNetwork(cmd.getNetworkId(), mac); return new AssociateMacToNetworkAnswer(cmd, result, "Association of mac " + cmd.getInterfaceMac() + " to network " + cmd.getNetworkId() + " done"); } catch (BrocadeVcsApiException e) { if (numRetries > 0) { return retry(cmd, --numRetries); } else { return new AssociateMacToNetworkAnswer(cmd, e); } } } private Answer executeRequest(DisassociateMacFromNetworkCommand cmd, int numRetries) { try { String mac = macReformat64To32(cmd.getInterfaceMac()); boolean result = _brocadeVcsApi.disassociateMacFromNetwork(cmd.getNetworkId(), mac); return new DisassociateMacFromNetworkAnswer(cmd, result, "Disassociation of mac " + cmd.getInterfaceMac() + " from network " + cmd.getNetworkId() + " done"); } catch (BrocadeVcsApiException e) { if (numRetries > 0) { return retry(cmd, --numRetries); } else { return new DisassociateMacFromNetworkAnswer(cmd, e); } } } private Answer executeRequest(DeleteNetworkCommand cmd, int numRetries) { try { boolean result = _brocadeVcsApi.deleteNetwork(cmd.getVlanId(), cmd.getNetworkId()); return new DeleteNetworkAnswer(cmd, result, "Port Profile " + cmd.getNetworkId() + " deleted"); } catch (BrocadeVcsApiException e) { if (numRetries > 0) { return retry(cmd, --numRetries); } else { return new DeleteNetworkAnswer(cmd, e); } } } private String macReformat64To32(String interfaceMac) { String mac = interfaceMac.replace(":", ""); mac = mac.substring(0, 4) + "." + mac.substring(4, 8) + "." + mac.subSequence(8, 12); return mac; } private Answer executeRequest(ReadyCommand cmd) { return new ReadyAnswer(cmd); } private Answer executeRequest(MaintainCommand cmd) { return new MaintainAnswer(cmd); } private Answer retry(Command cmd, int numRetries) { s_logger.warn("Retrying " + cmd.getClass().getSimpleName() + ". Number of retries remaining: " + numRetries); return executeRequest(cmd, numRetries); } @Override public void setName(String name) { } @Override public void setConfigParams(Map<String, Object> params) { } @Override public Map<String, Object> getConfigParams() { return null; } @Override public int getRunLevel() { return 0; } @Override public void setRunLevel(int level) { } }