// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
// 
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.network;

import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;

import com.cloud.agent.AgentManager;
import com.cloud.agent.Listener;
import com.cloud.agent.api.AgentControlAnswer;
import com.cloud.agent.api.AgentControlCommand;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.ModifySshKeysCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.manager.Commands;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConnectionException;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.router.VirtualNetworkApplianceManager;



public class SshKeysDistriMonitor implements Listener {
	  private static final Logger s_logger = Logger.getLogger(SshKeysDistriMonitor.class);
	  	AgentManager _agentMgr;
		private final HostDao _hostDao;
		private ConfigurationDao _configDao;
	    public SshKeysDistriMonitor(AgentManager mgr, HostDao host, ConfigurationDao config) {
	    	this._agentMgr = mgr;
	    	_hostDao = host;
	    	_configDao = config;
	    }
	    
	    
	    @Override
	    public boolean isRecurring() {
	        return false;
	    }
	    
	    @Override
	    public synchronized boolean processAnswers(long agentId, long seq, Answer[] resp) {
	        return true;
	    }
	    
	    @Override
	    public synchronized boolean processDisconnect(long agentId, Status state) {
	    	if(s_logger.isTraceEnabled())
	    		s_logger.trace("Agent disconnected, agent id: " + agentId + ", state: " + state + ". Will notify waiters");
	    	
	    
	        return true;
	    }
	    
	    @Override
	    public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) throws ConnectionException {
	    	if (cmd instanceof StartupRoutingCommand) {
	    		if (((StartupRoutingCommand) cmd).getHypervisorType() == HypervisorType.KVM ||
	    		    ((StartupRoutingCommand) cmd).getHypervisorType() == HypervisorType.XenServer) {
	    			/*TODO: Get the private/public keys here*/
	    			
	    			String pubKey = _configDao.getValue("ssh.publickey");
	    			String prvKey = _configDao.getValue("ssh.privatekey");
	    			
	    			try {
	    				ModifySshKeysCommand cmds = new ModifySshKeysCommand(pubKey, prvKey);
		    			Commands c = new Commands(cmds);
	    				_agentMgr.send(host.getId(), c, this);
	    			} catch (AgentUnavailableException e) {
	    				s_logger.debug("Failed to send keys to agent: " + host.getId());
	    			}
	    		}
	    	}
	    }

		@Override
		public int getTimeout() {
			// TODO Auto-generated method stub
			return -1;
		}


		@Override
		public boolean processCommands(long agentId, long seq, Command[] commands) {
			// TODO Auto-generated method stub
			return false;
		}


		@Override
		public AgentControlAnswer processControlCommand(long agentId,
				AgentControlCommand cmd) {
			// TODO Auto-generated method stub
			return null;
		}


		@Override
		public boolean processTimeout(long agentId, long seq) {
			// TODO Auto-generated method stub
			return false;
		}
}
