@Override
  public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl) {
    List<NicVO> nics = _nicDao.listByVmId(vm.getId());
    if (nics.size() != 1) {
      throw new CloudRuntimeException("Wrong nic number " + nics.size() + " of vm " + vm.getId());
    }

    /* use last host id when VM stopped */
    Long hostId = (vm.getHostId() == null ? vm.getLastHostId() : vm.getHostId());
    HostVO host = _hostDao.findById(hostId);
    DataCenterVO dc = _dcDao.findById(host.getDataCenterId());
    NicVO nic = nics.get(0);
    String mask = nic.getNetmask();
    String mac = nic.getMacAddress();
    String ip = nic.getIp4Address();
    String gateway = nic.getGateway();
    String dns = dc.getDns1();
    if (dns == null) {
      dns = dc.getDns2();
    }

    try {
      prepareCreateTemplateCommand cmd =
          new prepareCreateTemplateCommand(ip, mac, mask, gateway, dns, templateUrl);
      Answer ans = _agentMgr.send(pxeServerId, cmd);
      return ans.getResult();
    } catch (Exception e) {
      s_logger.debug("Prepare for creating baremetal template failed", e);
      return false;
    }
  }
  @Override
  public Network design(
      NetworkOffering offering, DeploymentPlan plan, Network network, Account owner) {
    if (offering.getTrafficType() != TrafficType.Public
        || (offering.getGuestIpType() != null
            && offering.getGuestIpType() != GuestIpType.Virtual)) {
      s_logger.trace("We only take care of Public Virtual Network");
      return null;
    }

    if (offering.getTrafficType() == TrafficType.Public) {
      NetworkVO ntwk =
          new NetworkVO(
              offering.getTrafficType(),
              offering.getGuestIpType(),
              Mode.Static,
              BroadcastDomainType.Vlan,
              offering.getId(),
              plan.getDataCenterId());
      DataCenterVO dc = _dcDao.findById(plan.getDataCenterId());
      ntwk.setDns1(dc.getDns1());
      ntwk.setDns2(dc.getDns2());
      return ntwk;
    } else {
      return null;
    }
  }
  @Override
  public boolean finalizeVirtualMachineProfile(
      VirtualMachineProfile<SecondaryStorageVmVO> profile,
      DeployDestination dest,
      ReservationContext context) {

    SecondaryStorageVmVO vm = profile.getVirtualMachine();
    Map<String, String> details = _vmDetailsDao.findDetails(vm.getId());
    vm.setDetails(details);

    HostVO secHost = _hostDao.findSecondaryStorageHost(dest.getDataCenter().getId());
    assert (secHost != null);

    StringBuilder buf = profile.getBootArgsBuilder();
    buf.append(" template=domP type=secstorage");
    buf.append(" host=").append(_mgmt_host);
    buf.append(" port=").append(_mgmt_port);
    buf.append(" name=").append(profile.getVirtualMachine().getHostName());

    buf.append(" zone=").append(dest.getDataCenter().getId());
    buf.append(" pod=").append(dest.getPod().getId());

    buf.append(" guid=").append(profile.getVirtualMachine().getHostName());

    if (_configDao.isPremium()) {
      if (profile.getHypervisorType() == HypervisorType.Hyperv) {
        buf.append(" resource=com.cloud.storage.resource.CifsSecondaryStorageResource");
      } else {
        buf.append(" resource=com.cloud.storage.resource.PremiumSecondaryStorageResource");
      }
    } else {
      buf.append(" resource=com.cloud.storage.resource.NfsSecondaryStorageResource");
    }
    buf.append(" instance=SecStorage");
    buf.append(" sslcopy=").append(Boolean.toString(_useSSlCopy));
    buf.append(" role=").append(profile.getVirtualMachine().getRole().toString());

    boolean externalDhcp = false;
    String externalDhcpStr =
        _configDao.getValue("direct.attach.network.externalIpAllocator.enabled");
    if (externalDhcpStr != null && externalDhcpStr.equalsIgnoreCase("true")) {
      externalDhcp = true;
    }

    for (NicProfile nic : profile.getNics()) {
      int deviceId = nic.getDeviceId();
      if (nic.getIp4Address() == null) {
        buf.append(" eth").append(deviceId).append("mask=").append("0.0.0.0");
        buf.append(" eth").append(deviceId).append("ip=").append("0.0.0.0");
      } else {
        buf.append(" eth").append(deviceId).append("ip=").append(nic.getIp4Address());
        buf.append(" eth").append(deviceId).append("mask=").append(nic.getNetmask());
      }

      buf.append(" eth").append(deviceId).append("mask=").append(nic.getNetmask());
      if (nic.isDefaultNic()) {
        buf.append(" gateway=").append(nic.getGateway());
      }
      if (nic.getTrafficType() == TrafficType.Management) {
        String mgmt_cidr = _configDao.getValue(Config.ManagementNetwork.key());
        if (NetUtils.isValidCIDR(mgmt_cidr)) {
          buf.append(" mgmtcidr=").append(mgmt_cidr);
        }
        buf.append(" localgw=").append(dest.getPod().getGateway());
        buf.append(" private.network.device=").append("eth").append(deviceId);
      } else if (nic.getTrafficType() == TrafficType.Public) {
        buf.append(" public.network.device=").append("eth").append(deviceId);
      }
    }

    /* External DHCP mode */
    if (externalDhcp) {
      buf.append(" bootproto=dhcp");
    }

    DataCenterVO dc = _dcDao.findById(profile.getVirtualMachine().getDataCenterIdToDeployIn());
    buf.append(" internaldns1=").append(dc.getInternalDns1());
    if (dc.getInternalDns2() != null) {
      buf.append(" internaldns2=").append(dc.getInternalDns2());
    }
    buf.append(" dns1=").append(dc.getDns1());
    if (dc.getDns2() != null) {
      buf.append(" dns2=").append(dc.getDns2());
    }

    String bootArgs = buf.toString();
    if (s_logger.isDebugEnabled()) {
      s_logger.debug("Boot Args for " + profile + ": " + bootArgs);
    }

    return true;
  }