public boolean isZoneReady(Map<Long, ZoneHostInfo> zoneHostInfoMap, long dataCenterId) {
    ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenterId);
    if (zoneHostInfo != null
        && (zoneHostInfo.getFlags() & RunningHostInfoAgregator.ZoneHostInfo.ROUTING_HOST_MASK)
            != 0) {
      VMTemplateVO template = _templateDao.findSystemVMTemplate(dataCenterId);
      HostVO secHost = _hostDao.findSecondaryStorageHost(dataCenterId);
      if (secHost == null) {
        if (s_logger.isDebugEnabled()) {
          s_logger.debug(
              "No secondary storage available in zone "
                  + dataCenterId
                  + ", wait until it is ready to launch secondary storage vm");
        }
        return false;
      }

      boolean templateReady = false;
      if (template != null) {
        VMTemplateHostVO templateHostRef =
            _vmTemplateHostDao.findByHostTemplate(secHost.getId(), template.getId());
        templateReady =
            (templateHostRef != null) && (templateHostRef.getDownloadState() == Status.DOWNLOADED);
      }

      if (templateReady) {

        List<Pair<Long, Integer>> l =
            _storagePoolHostDao.getDatacenterStoragePoolHostInfo(dataCenterId, !_useLocalStorage);
        if (l != null && l.size() > 0 && l.get(0).second().intValue() > 0) {

          return true;
        } else {
          if (s_logger.isDebugEnabled()) {
            s_logger.debug(
                "Primary storage is not ready, wait until it is ready to launch secondary storage vm");
          }
        }
      } else {
        if (s_logger.isTraceEnabled()) {
          s_logger.trace("Zone host is ready, but secondary storage vm template is not ready");
        }
      }
    }
    return false;
  }
  protected Map<String, Object> createSecStorageVmInstance(
      long dataCenterId, SecondaryStorageVm.Role role) {
    HostVO secHost = _hostDao.findSecondaryStorageHost(dataCenterId);
    if (secHost == null) {
      String msg =
          "No secondary storage available in zone "
              + dataCenterId
              + ", cannot create secondary storage vm";
      s_logger.warn(msg);
      throw new CloudRuntimeException(msg);
    }

    long id = _secStorageVmDao.getNextInSequence(Long.class, "id");
    String name = VirtualMachineName.getSystemVmName(id, _instance, "s").intern();
    Account systemAcct = _accountMgr.getSystemAccount();

    DataCenterDeployment plan = new DataCenterDeployment(dataCenterId);
    DataCenter dc = _dcDao.findById(plan.getDataCenterId());

    List<NetworkOfferingVO> defaultOffering =
        _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemPublicNetwork);

    if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) {
      defaultOffering =
          _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemGuestNetwork);
    }

    List<NetworkOfferingVO> offerings =
        _networkMgr.getSystemAccountNetworkOfferings(
            NetworkOfferingVO.SystemControlNetwork, NetworkOfferingVO.SystemManagementNetwork);
    List<Pair<NetworkVO, NicProfile>> networks =
        new ArrayList<Pair<NetworkVO, NicProfile>>(offerings.size() + 1);
    NicProfile defaultNic = new NicProfile();
    defaultNic.setDefaultNic(true);
    defaultNic.setDeviceId(2);
    try {
      networks.add(
          new Pair<NetworkVO, NicProfile>(
              _networkMgr
                  .setupNetwork(systemAcct, defaultOffering.get(0), plan, null, null, false, false)
                  .get(0),
              defaultNic));
      for (NetworkOfferingVO offering : offerings) {
        networks.add(
            new Pair<NetworkVO, NicProfile>(
                _networkMgr
                    .setupNetwork(systemAcct, offering, plan, null, null, false, false)
                    .get(0),
                null));
      }
    } catch (ConcurrentOperationException e) {
      s_logger.info("Unable to setup due to concurrent operation. " + e);
      return new HashMap<String, Object>();
    }

    VMTemplateVO template = _templateDao.findSystemVMTemplate(dataCenterId);
    if (template == null) {
      s_logger.debug("Can't find a template to start");
      throw new CloudRuntimeException("Insufficient capacity exception");
    }

    SecondaryStorageVmVO secStorageVm =
        new SecondaryStorageVmVO(
            id,
            _serviceOffering.getId(),
            name,
            template.getId(),
            template.getHypervisorType(),
            template.getGuestOSId(),
            dataCenterId,
            systemAcct.getDomainId(),
            systemAcct.getId(),
            role,
            _serviceOffering.getOfferHA());
    try {
      secStorageVm =
          _itMgr.allocate(
              secStorageVm, template, _serviceOffering, networks, plan, null, systemAcct);
    } catch (InsufficientCapacityException e) {
      s_logger.warn("InsufficientCapacity", e);
      throw new CloudRuntimeException("Insufficient capacity exception", e);
    }

    Map<String, Object> context = new HashMap<String, Object>();
    context.put("secStorageVmId", secStorageVm.getId());
    return context;
  }
  @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;
  }