content: // 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.resource;
  
  import java.io.StringReader;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  import javax.naming.ConfigurationException;
  
  
  import com.cloud.agent.api.Answer;
  import com.cloud.agent.api.CheckVirtualMachineAnswer;
  import com.cloud.agent.api.CheckVirtualMachineCommand;
  import com.cloud.agent.api.Command;
  import com.cloud.agent.api.HostVmStateReportEntry;
  import com.cloud.agent.api.PingCommand;
  import com.cloud.agent.api.PingRoutingWithNwGroupsCommand;
  import com.cloud.agent.api.ReadyAnswer;
  import com.cloud.agent.api.ReadyCommand;
  import com.cloud.agent.api.ShutdownCommand;
  import com.cloud.agent.api.StartAnswer;
  import com.cloud.agent.api.StartCommand;
  import com.cloud.agent.api.StartupCommand;
  import com.cloud.agent.api.StartupRoutingCommand;
  import com.cloud.agent.api.StartupStorageCommand;
  import com.cloud.agent.api.StopAnswer;
  import com.cloud.agent.api.StopCommand;
  import com.cloud.agent.api.StoragePoolInfo;
  import com.cloud.agent.api.to.VirtualMachineTO;
  import com.cloud.agent.manager.SimulatorManager;
  import com.cloud.agent.manager.SimulatorManager.AgentType;
  import com.cloud.host.Host;
  import com.cloud.host.Host.Type;
  import com.cloud.hypervisor.Hypervisor.HypervisorType;
  import com.cloud.network.Networks.RouterPrivateIpStrategy;
  import com.cloud.serializer.GsonHelper;
  import com.cloud.simulator.MockConfigurationVO;
  import com.cloud.simulator.MockVMVO;
  import com.cloud.storage.Storage.StorageResourceType;
  import com.cloud.storage.template.TemplateProp;
  import com.cloud.utils.Pair;
  import com.cloud.utils.db.TransactionLegacy;
  import com.cloud.vm.VirtualMachine.PowerState;
  import com.google.gson.Gson;
  import com.google.gson.stream.JsonReader;
  
  public class AgentRoutingResource extends AgentStorageResource {
      private static final Gson s_gson = GsonHelper.getGson();
  
      private Map<String, Pair<Long, Long>> _runningVms = new HashMap<String, Pair<Long, Long>>();
      long usedCpu = 0;
      long usedMem = 0;
      long totalCpu;
      long totalMem;
      protected String _mountParent;
  
      public AgentRoutingResource(long instanceId, AgentType agentType, SimulatorManager simMgr, String hostGuid) {
          super(instanceId, agentType, simMgr, hostGuid);
      }
  
      public AgentRoutingResource() {
          setType(Host.Type.Routing);
      }
  
      @Override
      public Answer executeRequestInContext(Command cmd) {
          try {
              if (cmd instanceof StartCommand) {
                  return execute((StartCommand)cmd);
              } else if (cmd instanceof StopCommand) {
                  return execute((StopCommand)cmd);
              } else if (cmd instanceof CheckVirtualMachineCommand) {
                  return execute((CheckVirtualMachineCommand)cmd);
              } else if (cmd instanceof ReadyCommand) {
                  return new ReadyAnswer((ReadyCommand)cmd);
              } else if (cmd instanceof ShutdownCommand) {
                  return execute((ShutdownCommand)cmd);
              } else {
                  return _simMgr.simulate(cmd, hostGuid);
              }
          } catch (IllegalArgumentException e) {
              return new Answer(cmd, false, e.getMessage());
          }
      }
  
      @Override
      public Type getType() {
          return Host.Type.Routing;
      }
  
      @Override
      public PingCommand getCurrentStatus(long id) {
          TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.SIMULATOR_DB);
          try {
              MockConfigurationVO config = null;
              if (config != null) {
                  Map<String, String> configParameters = config.getParameters();
                  for (Map.Entry<String, String> entry : configParameters.entrySet()) {
                      if (entry.getKey().equalsIgnoreCase("result")) {
                          String value = entry.getValue();
                          if (value.equalsIgnoreCase("fail")) {
                              return null;
                          }
                      }
                  }
              }
  
              config = null;
              if (config != null) {
                  String message = config.getJsonResponse();
                  if (message != null) {
                      // json response looks like {"<Type>":....}
                      String objectType = message.split(":")[0].substring(2).replace("\"", "");
                      String objectData = message.substring(message.indexOf(':') + 1, message.length() - 1);
                      if (objectType != null) {
                          Class<?> clz = null;
                          try {
                              clz = Class.forName(objectType);
                          } catch (ClassNotFoundException e) {
                              logger.info("[ignored] ping returned class", e);
                          }
                          if (clz != null) {
                              StringReader reader = new StringReader(objectData);
                              JsonReader jsonReader = new JsonReader(reader);
                              jsonReader.setLenient(true);
                              return (PingCommand)s_gson.fromJson(jsonReader, clz);
                          }
                      }
                  }
              }
          } catch (Exception e) {
              txn.rollback();
          } finally {
              txn.close();
              txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB);
              txn.close();
          }
  
          if (isStopped()) {
              return null;
          }
          HashMap<String, Pair<Long, Long>> nwGrpStates = _simMgr.syncNetworkGroups(hostGuid);
          return new PingRoutingWithNwGroupsCommand(getType(), id, getHostVmStateReport(), nwGrpStates);
      }
  
      @Override
      public StartupCommand[] initialize() {
          Map<String, MockVMVO> vmsMaps = _simMgr.getVms(this.hostGuid);
          totalCpu = agentHost.getCpuCount() * agentHost.getCpuSpeed();
          totalMem = agentHost.getMemorySize();
          for (Map.Entry<String, MockVMVO> entry : vmsMaps.entrySet()) {
              MockVMVO vm = entry.getValue();
              usedCpu += vm.getCpu();
              usedMem += vm.getMemory();
              _runningVms.put(entry.getKey(), new Pair<Long, Long>(Long.valueOf(vm.getCpu()), vm.getMemory()));
          }
  
          List<Object> info = getHostInfo();
  
          StartupRoutingCommand cmd =
              new StartupRoutingCommand((Integer)info.get(0), (Long)info.get(1), (Long)info.get(2), (Long)info.get(4), (String)info.get(3), HypervisorType.Simulator,
                  RouterPrivateIpStrategy.HostLocal);
          cmd.setCpuArch((String)info.get(5));
  
          Map<String, String> hostDetails = new HashMap<String, String>();
          hostDetails.put(RouterPrivateIpStrategy.class.getCanonicalName(), RouterPrivateIpStrategy.DcGlobal.toString());
  
          cmd.setHostDetails(hostDetails);
          cmd.setAgentTag("agent-simulator");
          cmd.setPrivateIpAddress(agentHost.getPrivateIpAddress());
          cmd.setPrivateNetmask(agentHost.getPrivateNetMask());
          cmd.setPrivateMacAddress(agentHost.getPrivateMacAddress());
          cmd.setStorageIpAddress(agentHost.getStorageIpAddress());
          cmd.setStorageNetmask(agentHost.getStorageNetMask());
          cmd.setStorageMacAddress(agentHost.getStorageMacAddress());
          cmd.setStorageIpAddressDeux(agentHost.getStorageIpAddress());
          cmd.setStorageNetmaskDeux(agentHost.getStorageNetMask());
          cmd.setStorageMacAddressDeux(agentHost.getStorageIpAddress());
  
          cmd.setName(agentHost.getName());
          cmd.setGuid(agentHost.getGuid());
          cmd.setVersion(agentHost.getVersion());
          cmd.setHypervisorVersion(agentHost.getVersion());
          cmd.setAgentTag("agent-simulator");
          cmd.setDataCenter(String.valueOf(agentHost.getDataCenterId()));
          cmd.setPod(String.valueOf(agentHost.getPodId()));
          cmd.setCluster(String.valueOf(agentHost.getClusterId()));
  
          StartupStorageCommand ssCmd = initializeLocalSR();
  
          return new StartupCommand[] {cmd, ssCmd};
      }
  
      private StartupStorageCommand initializeLocalSR() {
          Map<String, TemplateProp> tInfo = new HashMap<String, TemplateProp>();
  
          StoragePoolInfo poolInfo = _simMgr.getLocalStorage(hostGuid);
  
          StartupStorageCommand cmd = new StartupStorageCommand(poolInfo.getHostPath(), poolInfo.getPoolType(), poolInfo.getCapacityBytes(), tInfo);
  
          cmd.setPoolInfo(poolInfo);
          cmd.setGuid(agentHost.getGuid());
          cmd.setResourceType(StorageResourceType.STORAGE_POOL);
          return cmd;
      }
  
      protected synchronized Answer execute(StartCommand cmd) throws IllegalArgumentException {
          VirtualMachineTO vmSpec = cmd.getVirtualMachine();
          String vmName = vmSpec.getName();
          if (this.totalCpu < (vmSpec.getCpus() * vmSpec.getMaxSpeed() + this.usedCpu) || this.totalMem < (vmSpec.getMaxRam() + this.usedMem)) {
              return new StartAnswer(cmd, "Not enough resource to start the vm");
          }
          Answer result = _simMgr.simulate(cmd, hostGuid);
          if (!result.getResult()) {
              return new StartAnswer(cmd, result.getDetails());
          }
  
          this.usedCpu += vmSpec.getCpus() * vmSpec.getMaxSpeed();
          this.usedMem += vmSpec.getMaxRam();
          _runningVms.put(vmName, new Pair<Long, Long>(Long.valueOf(vmSpec.getCpus() * vmSpec.getMaxSpeed()), vmSpec.getMaxRam()));
  
  
          return new StartAnswer(cmd);
  
      }
  
      protected synchronized StopAnswer execute(StopCommand cmd) {
  
          StopAnswer answer = null;
          String vmName = cmd.getVmName();
  
          Answer result = _simMgr.simulate(cmd, hostGuid);
  
          if (!result.getResult()) {
              return new StopAnswer(cmd, result.getDetails(), false);
          }
  
          answer = new StopAnswer(cmd, null, true);
          Pair<Long, Long> data = _runningVms.get(vmName);
          if (data != null) {
              this.usedCpu -= data.first();
              this.usedMem -= data.second();
           }
  
  
          return answer;
      }
  
      protected CheckVirtualMachineAnswer execute(final CheckVirtualMachineCommand cmd) {
          final String vmName = cmd.getVmName();
          CheckVirtualMachineAnswer result = (CheckVirtualMachineAnswer)_simMgr.simulate(cmd, hostGuid);
          return result;
      }
  
      protected List<Object> getHostInfo() {
          ArrayList<Object> info = new ArrayList<Object>();
          long speed = agentHost.getCpuSpeed();
          long cpus = agentHost.getCpuCount();
          long ram = agentHost.getMemorySize();
          long dom0Ram = agentHost.getMemorySize() / 10;
          String arch = agentHost.getArch();
  
          info.add((int)cpus);
          info.add(speed);
          info.add(ram);
          info.add(agentHost.getCapabilities());
          info.add(dom0Ram);
          info.add(arch);
  
          return info;
      }
  
      protected HashMap<String, HostVmStateReportEntry> getHostVmStateReport() {
          HashMap<String, HostVmStateReportEntry> report = new HashMap<String, HostVmStateReportEntry>();
          Map<String, PowerState> states = _simMgr.getVmStates(this.hostGuid);
          for (String vmName : states.keySet()) {
              report.put(vmName, new HostVmStateReportEntry(states.get(vmName), agentHost.getName()));
          }
          return report;
      }
  
      private Answer execute(ShutdownCommand cmd) {
          this.stopped = true;
          return new Answer(cmd);
      }
  
      @Override
      public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
          if (!super.configure(name, params)) {
              logger.warn("Base class was unable to configure");
              return false;
          }
          return true;
      }
  }
  