@Override
  @DB
  public boolean prepare(
      Network network,
      NicProfile nic,
      VirtualMachineProfile<? extends VirtualMachine> vm,
      DeployDestination dest,
      ReservationContext context)
      throws ConcurrentOperationException, ResourceUnavailableException,
          InsufficientCapacityException {
    Host host = dest.getHost();
    if (host == null || host.getHypervisorType() != HypervisorType.BareMetal) {
      return true;
    }

    Transaction txn = Transaction.currentTxn();
    txn.start();
    nic.setMacAddress(host.getPrivateMacAddress());
    NicVO vo = _nicDao.findById(nic.getId());
    assert vo != null : "Where ths nic " + nic.getId() + " going???";
    vo.setMacAddress(nic.getMacAddress());
    _nicDao.update(vo.getId(), vo);
    txn.commit();
    s_logger.debug(
        "Bare Metal changes mac address of nic " + nic.getId() + " to " + nic.getMacAddress());

    return _dhcpMgr.addVirtualMachineIntoNetwork(network, nic, vm, dest, context);
  }
Exemplo n.º 2
0
  @Override
  public Boolean fenceOff(VirtualMachine vm, Host host) {
    if (host.getHypervisorType() != HypervisorType.KVM
        && host.getHypervisorType() != HypervisorType.LXC) {
      s_logger.warn("Don't know how to fence non kvm hosts " + host.getHypervisorType());
      return null;
    }

    List<HostVO> hosts = _resourceMgr.listAllHostsInCluster(host.getClusterId());
    FenceCommand fence = new FenceCommand(vm, host);

    int i = 0;
    for (HostVO h : hosts) {
      if (h.getHypervisorType() == HypervisorType.KVM
          || h.getHypervisorType() == HypervisorType.LXC) {
        if (h.getStatus() != Status.Up) {
          continue;
        }

        i++;

        if (h.getId() == host.getId()) {
          continue;
        }
        FenceAnswer answer;
        try {
          answer = (FenceAnswer) _agentMgr.send(h.getId(), fence);
        } catch (AgentUnavailableException e) {
          s_logger.info("Moving on to the next host because " + h.toString() + " is unavailable");
          continue;
        } catch (OperationTimedoutException e) {
          s_logger.info("Moving on to the next host because " + h.toString() + " is unavailable");
          continue;
        }
        if (answer != null && answer.getResult()) {
          return true;
        }
      }
    }

    _alertMgr.sendAlert(
        AlertManager.AlertType.ALERT_TYPE_HOST,
        host.getDataCenterId(),
        host.getPodId(),
        "Unable to fence off host: " + host.getId(),
        "Fencing off host "
            + host.getId()
            + " did not succeed after asking "
            + i
            + " hosts. "
            + "Check Agent logs for more information.");

    s_logger.error("Unable to fence off " + vm.toString() + " on " + host.toString());

    return false;
  }
 @Override
 public TrafficMonitorResponse getApiResponse(Host trafficMonitor) {
   Map<String, String> tmDetails = _detailsDao.findDetails(trafficMonitor.getId());
   TrafficMonitorResponse response = new TrafficMonitorResponse();
   response.setId(trafficMonitor.getUuid());
   response.setIpAddress(trafficMonitor.getPrivateIpAddress());
   response.setNumRetries(tmDetails.get("numRetries"));
   response.setTimeout(tmDetails.get("timeout"));
   return response;
 }
Exemplo n.º 4
0
  @DB
  private void updateClusterNativeHAState(Host host, StartupCommand cmd) {
    ClusterVO cluster = _clusterDao.findById(host.getClusterId());
    if (cluster.getClusterType() == ClusterType.ExternalManaged) {
      if (cmd instanceof StartupRoutingCommand) {
        StartupRoutingCommand hostStartupCmd = (StartupRoutingCommand) cmd;
        Map<String, String> details = hostStartupCmd.getHostDetails();

        if (details.get("NativeHA") != null && details.get("NativeHA").equalsIgnoreCase("true")) {
          _clusterDetailsDao.persist(host.getClusterId(), "NativeHA", "true");
        } else {
          _clusterDetailsDao.persist(host.getClusterId(), "NativeHA", "false");
        }
      }
    }
  }
Exemplo n.º 5
0
 @Override
 public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) {
   if (cmd instanceof StartupCommand) {
     if (host.getHypervisorType() == HypervisorType.VMware) {
       updateClusterNativeHAState(host, cmd);
     } else {
       return;
     }
   }
 }
    public boolean shouldAvoid(Host host) {
      if (_dcIds != null && _dcIds.contains(host.getDataCenterId())) {
        return true;
      }

      if (_podIds != null && _podIds.contains(host.getPodId())) {
        return true;
      }

      if (_clusterIds != null && _clusterIds.contains(host.getClusterId())) {
        return true;
      }

      if (_hostIds != null && _hostIds.contains(host.getId())) {
        return true;
      }

      return false;
    }
  @Override
  public Status isAgentAlive(Host agent) {
    if (s_logger.isDebugEnabled()) {
      s_logger.debug("checking if agent (" + agent.getId() + ") is alive");
    }

    if (agent.getPodId() == null) {
      return null;
    }

    List<Long> otherHosts = findHostByPod(agent.getPodId(), agent.getId());

    for (Long hostId : otherHosts) {

      if (s_logger.isDebugEnabled()) {
        s_logger.debug(
            "sending ping from ("
                + hostId
                + ") to agent's host ip address ("
                + agent.getPrivateIpAddress()
                + ")");
      }
      Status hostState = testIpAddress(hostId, agent.getPrivateIpAddress());
      if (hostState == null) {
        continue;
      }
      if (hostState == Status.Up) {
        if (s_logger.isDebugEnabled()) {
          s_logger.debug(
              "ping from ("
                  + hostId
                  + ") to agent's host ip address ("
                  + agent.getPrivateIpAddress()
                  + ") successful, returning that agent is disconnected");
        }
        return Status
            .Disconnected; // the computing host ip is ping-able, but the computing agent is down,
        // report that the agent is disconnected
      } else if (hostState == Status.Down) {
        if (s_logger.isDebugEnabled()) {
          s_logger.debug("returning host state: " + hostState);
        }
        return hostState;
      }
    }

    // could not reach agent, could not reach agent's host, unclear what the problem is but it'll
    // require more investigation...
    if (s_logger.isDebugEnabled()) {
      s_logger.debug(
          "could not reach agent, could not reach agent's host, returning that we don't have enough information");
    }
    return null;
  }
  @Override
  public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) {
    if (s_logger.isInfoEnabled()) s_logger.info("Received a host startup notification");

    if (cmd instanceof StartupRoutingCommand) {
      // if (Boolean.toString(true).equals(host.getDetail("can_bridge_firewall"))) {
      try {
        int interval =
            MIN_TIME_BETWEEN_CLEANUPS + _cleanupRandom.nextInt(MIN_TIME_BETWEEN_CLEANUPS / 2);
        CleanupNetworkRulesCmd cleanupCmd = new CleanupNetworkRulesCmd(interval);
        Commands c = new Commands(cleanupCmd);
        _agentMgr.send(host.getId(), c, this);
        if (s_logger.isInfoEnabled())
          s_logger.info("Scheduled network rules cleanup, interval=" + cleanupCmd.getInterval());
      } catch (AgentUnavailableException e) {
        // usually hypervisors that do not understand sec group rules.
        s_logger.debug("Unable to schedule network rules cleanup for host " + host.getId(), e);
      }
      if (_workTracker != null) {
        _workTracker.processConnect(host.getId());
      }
    }
  }
    @Override
    protected void runInContext() {
      // 1. Select all entries with download_state = Not_Downloaded or Download_In_Progress
      // 2. Get corresponding volume
      // 3. Get EP using _epSelector
      // 4. Check if SSVM is owned by this MS
      // 5. If owned by MS then send command to appropriate SSVM
      // 6. In listener check for the answer and update DB accordingly
      List<VolumeDataStoreVO> volumeDataStores =
          _volumeDataStoreDao.listByVolumeState(
              Volume.State.NotUploaded, Volume.State.UploadInProgress);
      for (VolumeDataStoreVO volumeDataStore : volumeDataStores) {
        try {
          DataStore dataStore =
              storeMgr.getDataStore(volumeDataStore.getDataStoreId(), DataStoreRole.Image);
          EndPoint ep = _epSelector.select(dataStore, volumeDataStore.getExtractUrl());
          if (ep == null) {
            s_logger.warn(
                "There is no secondary storage VM for image store " + dataStore.getName());
            continue;
          }
          VolumeVO volume = _volumeDao.findById(volumeDataStore.getVolumeId());
          if (volume == null) {
            s_logger.warn("Volume with id " + volumeDataStore.getVolumeId() + " not found");
            continue;
          }
          Host host = _hostDao.findById(ep.getId());
          UploadStatusCommand cmd = new UploadStatusCommand(volume.getUuid(), EntityType.Volume);
          if (host != null && host.getManagementServerId() != null) {
            if (_nodeId == host.getManagementServerId().longValue()) {
              Answer answer = null;
              try {
                answer = ep.sendMessage(cmd);
              } catch (CloudRuntimeException e) {
                s_logger.warn(
                    "Unable to get upload status for volume "
                        + volume.getUuid()
                        + ". Error details: "
                        + e.getMessage());
                answer = new UploadStatusAnswer(cmd, UploadStatus.UNKNOWN, e.getMessage());
              }
              if (answer == null || !(answer instanceof UploadStatusAnswer)) {
                s_logger.warn(
                    "No or invalid answer corresponding to UploadStatusCommand for volume "
                        + volumeDataStore.getVolumeId());
                continue;
              }
              handleVolumeStatusResponse((UploadStatusAnswer) answer, volume, volumeDataStore);
            }
          } else {
            String error =
                "Volume "
                    + volume.getUuid()
                    + " failed to upload as SSVM is either destroyed or SSVM agent not in 'Up' state";
            handleVolumeStatusResponse(
                new UploadStatusAnswer(cmd, UploadStatus.ERROR, error), volume, volumeDataStore);
          }
        } catch (Throwable th) {
          s_logger.warn(
              "Exception while checking status for uploaded volume "
                  + volumeDataStore.getExtractUrl()
                  + ". Error details: "
                  + th.getMessage());
          if (s_logger.isTraceEnabled()) {
            s_logger.trace("Exception details: ", th);
          }
        }
      }

      // Handle for template upload as well
      List<TemplateDataStoreVO> templateDataStores =
          _templateDataStoreDao.listByTemplateState(
              VirtualMachineTemplate.State.NotUploaded,
              VirtualMachineTemplate.State.UploadInProgress);
      for (TemplateDataStoreVO templateDataStore : templateDataStores) {
        try {
          DataStore dataStore =
              storeMgr.getDataStore(templateDataStore.getDataStoreId(), DataStoreRole.Image);
          EndPoint ep = _epSelector.select(dataStore, templateDataStore.getExtractUrl());
          if (ep == null) {
            s_logger.warn(
                "There is no secondary storage VM for image store " + dataStore.getName());
            continue;
          }
          VMTemplateVO template = _templateDao.findById(templateDataStore.getTemplateId());
          if (template == null) {
            s_logger.warn("Template with id " + templateDataStore.getTemplateId() + " not found");
            continue;
          }
          Host host = _hostDao.findById(ep.getId());
          UploadStatusCommand cmd =
              new UploadStatusCommand(template.getUuid(), EntityType.Template);
          if (host != null && host.getManagementServerId() != null) {
            if (_nodeId == host.getManagementServerId().longValue()) {
              Answer answer = null;
              try {
                answer = ep.sendMessage(cmd);
              } catch (CloudRuntimeException e) {
                s_logger.warn(
                    "Unable to get upload status for template "
                        + template.getUuid()
                        + ". Error details: "
                        + e.getMessage());
                answer = new UploadStatusAnswer(cmd, UploadStatus.UNKNOWN, e.getMessage());
              }
              if (answer == null || !(answer instanceof UploadStatusAnswer)) {
                s_logger.warn(
                    "No or invalid answer corresponding to UploadStatusCommand for template "
                        + templateDataStore.getTemplateId());
                continue;
              }
              handleTemplateStatusResponse(
                  (UploadStatusAnswer) answer, template, templateDataStore);
            }
          } else {
            String error =
                "Template "
                    + template.getUuid()
                    + " failed to upload as SSVM is either destroyed or SSVM agent not in 'Up' state";
            handleTemplateStatusResponse(
                new UploadStatusAnswer(cmd, UploadStatus.ERROR, error),
                template,
                templateDataStore);
          }
        } catch (Throwable th) {
          s_logger.warn(
              "Exception while checking status for uploaded template "
                  + templateDataStore.getExtractUrl()
                  + ". Error details: "
                  + th.getMessage());
          if (s_logger.isTraceEnabled()) {
            s_logger.trace("Exception details: ", th);
          }
        }
      }
    }
  @Override
  public final void processConnect(
      final Host agent, final StartupCommand cmd, final boolean forRebalance)
      throws ConnectionException {
    // Limit the commands we can process
    if (!(cmd instanceof StartupRoutingCommand)) {
      return;
    }

    StartupRoutingCommand startup = (StartupRoutingCommand) cmd;

    // assert
    if (startup.getHypervisorType() != HypervisorType.Hyperv) {
      s_logger.debug("Not Hyper-V hypervisor, so moving on.");
      return;
    }

    long agentId = agent.getId();
    HostVO host = _hostDao.findById(agentId);

    // Our Hyper-V machines are not participating in pools, and the pool id
    // we provide them is not persisted.
    // This means the pool id can vary.
    ClusterVO cluster = _clusterDao.findById(host.getClusterId());
    if (cluster.getGuid() == null) {
      cluster.setGuid(startup.getPool());
      _clusterDao.update(cluster.getId(), cluster);
    }

    if (s_logger.isDebugEnabled()) {
      s_logger.debug("Setting up host " + agentId);
    }

    HostEnvironment env = new HostEnvironment();
    SetupCommand setup = new SetupCommand(env);
    if (!host.isSetup()) {
      setup.setNeedSetup(true);
    }

    try {
      SetupAnswer answer = (SetupAnswer) _agentMgr.send(agentId, setup);
      if (answer != null && answer.getResult()) {
        host.setSetup(true);
        // TODO: clean up magic numbers below
        host.setLastPinged((System.currentTimeMillis() >> 10) - 5 * 60);
        _hostDao.update(host.getId(), host);
        if (answer.needReconnect()) {
          throw new ConnectionException(false, "Reinitialize agent after setup.");
        }
        return;
      } else {
        String reason = answer.getDetails();
        if (reason == null) {
          reason = " details were null";
        }
        s_logger.warn("Unable to setup agent " + agentId + " due to " + reason);
      }
      // Error handling borrowed from XcpServerDiscoverer, may need to be
      // updated.
    } catch (AgentUnavailableException e) {
      s_logger.warn("Unable to setup agent " + agentId + " because it became unavailable.", e);
    } catch (OperationTimedoutException e) {
      s_logger.warn("Unable to setup agent " + agentId + " because it timed out", e);
    }
    throw new ConnectionException(true, "Reinitialize agent after setup.");
  }
  @Override
  @DB
  public BaremetalPxeVO addPxeServer(AddBaremetalPxeCmd cmd) {
    AddBaremetalKickStartPxeCmd kcmd = (AddBaremetalKickStartPxeCmd) cmd;
    PhysicalNetworkVO pNetwork = null;
    long zoneId;

    if (cmd.getPhysicalNetworkId() == null
        || cmd.getUrl() == null
        || cmd.getUsername() == null
        || cmd.getPassword() == null) {
      throw new IllegalArgumentException(
          "At least one of the required parameters(physical network id, url, username, password) is null");
    }

    pNetwork = _physicalNetworkDao.findById(cmd.getPhysicalNetworkId());
    if (pNetwork == null) {
      throw new IllegalArgumentException(
          "Could not find phyical network with ID: " + cmd.getPhysicalNetworkId());
    }
    zoneId = pNetwork.getDataCenterId();

    PhysicalNetworkServiceProviderVO ntwkSvcProvider =
        _physicalNetworkServiceProviderDao.findByServiceProvider(
            pNetwork.getId(), BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER.getName());
    if (ntwkSvcProvider == null) {
      throw new CloudRuntimeException(
          "Network Service Provider: "
              + BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER.getName()
              + " is not enabled in the physical network: "
              + cmd.getPhysicalNetworkId()
              + "to add this device");
    } else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) {
      throw new CloudRuntimeException(
          "Network Service Provider: "
              + ntwkSvcProvider.getProviderName()
              + " is in shutdown state in the physical network: "
              + cmd.getPhysicalNetworkId()
              + "to add this device");
    }

    List<HostVO> pxes = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, zoneId);
    if (!pxes.isEmpty()) {
      throw new IllegalArgumentException("Already had a PXE server zone: " + zoneId);
    }

    String tftpDir = kcmd.getTftpDir();
    if (tftpDir == null) {
      throw new IllegalArgumentException("No TFTP directory specified");
    }

    URI uri;
    try {
      uri = new URI(cmd.getUrl());
    } catch (Exception e) {
      s_logger.debug(e);
      throw new IllegalArgumentException(e.getMessage());
    }
    String ipAddress = uri.getHost();
    if (ipAddress == null) {
      ipAddress = cmd.getUrl();
    }

    String guid =
        getPxeServerGuid(Long.toString(zoneId), BaremetalPxeType.KICK_START.toString(), ipAddress);

    ServerResource resource = null;
    Map params = new HashMap<String, String>();
    params.put(BaremetalPxeService.PXE_PARAM_ZONE, Long.toString(zoneId));
    params.put(BaremetalPxeService.PXE_PARAM_IP, ipAddress);
    params.put(BaremetalPxeService.PXE_PARAM_USERNAME, cmd.getUsername());
    params.put(BaremetalPxeService.PXE_PARAM_PASSWORD, cmd.getPassword());
    params.put(BaremetalPxeService.PXE_PARAM_TFTP_DIR, tftpDir);
    params.put(BaremetalPxeService.PXE_PARAM_GUID, guid);
    resource = new BaremetalKickStartPxeResource();
    try {
      resource.configure("KickStart PXE resource", params);
    } catch (Exception e) {
      throw new CloudRuntimeException(e.getMessage(), e);
    }

    Host pxeServer = _resourceMgr.addHost(zoneId, resource, Host.Type.BaremetalPxe, params);
    if (pxeServer == null) {
      throw new CloudRuntimeException("Cannot add PXE server as a host");
    }

    BaremetalPxeVO vo = new BaremetalPxeVO();
    vo.setHostId(pxeServer.getId());
    vo.setNetworkServiceProviderId(ntwkSvcProvider.getId());
    vo.setPhysicalNetworkId(kcmd.getPhysicalNetworkId());
    vo.setDeviceType(BaremetalPxeType.KICK_START.toString());
    _pxeDao.persist(vo);
    return vo;
  }
  @Override
  public CiscoVnmcController addCiscoVnmcResource(AddCiscoVnmcResourceCmd cmd) {
    String deviceName = Provider.CiscoVnmc.getName();
    NetworkDevice networkDevice = NetworkDevice.getNetworkDevice(deviceName);
    Long physicalNetworkId = cmd.getPhysicalNetworkId();
    CiscoVnmcController ciscoVnmcResource = null;

    PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
    if (physicalNetwork == null) {
      throw new InvalidParameterValueException(
          "Could not find phyical network with ID: " + physicalNetworkId);
    }
    long zoneId = physicalNetwork.getDataCenterId();

    PhysicalNetworkServiceProviderVO ntwkSvcProvider =
        _physicalNetworkServiceProviderDao.findByServiceProvider(
            physicalNetwork.getId(), networkDevice.getNetworkServiceProvder());
    if (ntwkSvcProvider == null) {
      throw new CloudRuntimeException(
          "Network Service Provider: "
              + networkDevice.getNetworkServiceProvder()
              + " is not enabled in the physical network: "
              + physicalNetworkId
              + "to add this device");
    } else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) {
      throw new CloudRuntimeException(
          "Network Service Provider: "
              + ntwkSvcProvider.getProviderName()
              + " is in shutdown state in the physical network: "
              + physicalNetworkId
              + "to add this device");
    }

    if (_ciscoVnmcDao.listByPhysicalNetwork(physicalNetworkId).size() != 0) {
      throw new CloudRuntimeException(
          "A Cisco Vnmc device is already configured on this physical network");
    }

    Map<String, String> params = new HashMap<String, String>();
    params.put("guid", UUID.randomUUID().toString());
    params.put("zoneId", String.valueOf(physicalNetwork.getDataCenterId()));
    params.put("physicalNetworkId", String.valueOf(physicalNetwork.getId()));
    params.put("name", "Cisco VNMC Controller - " + cmd.getHost());
    params.put("ip", cmd.getHost());
    params.put("username", cmd.getUsername());
    params.put("password", cmd.getPassword());

    Map<String, Object> hostdetails = new HashMap<String, Object>();
    hostdetails.putAll(params);

    ServerResource resource = new CiscoVnmcResource();
    Transaction txn = Transaction.currentTxn();
    try {
      resource.configure(cmd.getHost(), hostdetails);

      Host host = _resourceMgr.addHost(zoneId, resource, Host.Type.ExternalFirewall, params);
      if (host != null) {
        txn.start();

        ciscoVnmcResource =
            new CiscoVnmcControllerVO(
                host.getId(), physicalNetworkId, ntwkSvcProvider.getProviderName(), deviceName);
        _ciscoVnmcDao.persist((CiscoVnmcControllerVO) ciscoVnmcResource);

        DetailVO detail =
            new DetailVO(host.getId(), "deviceid", String.valueOf(ciscoVnmcResource.getId()));
        _hostDetailsDao.persist(detail);

        txn.commit();
        return ciscoVnmcResource;
      } else {
        throw new CloudRuntimeException("Failed to add Cisco Vnmc device due to internal error.");
      }
    } catch (ConfigurationException e) {
      txn.rollback();
      throw new CloudRuntimeException(e.getMessage());
    }
  }
  @Override
  @DB
  public BaremetalPxeVO addPxeServer(AddBaremetalPxeCmd cmd) {
    AddBaremetalPxePingServerCmd pcmd = (AddBaremetalPxePingServerCmd) cmd;

    PhysicalNetworkVO pNetwork = null;
    long zoneId;

    if (cmd.getPhysicalNetworkId() == null
        || cmd.getUrl() == null
        || cmd.getUsername() == null
        || cmd.getPassword() == null) {
      throw new IllegalArgumentException(
          "At least one of the required parameters(physical network id, url, username, password) is null");
    }

    pNetwork = _physicalNetworkDao.findById(cmd.getPhysicalNetworkId());
    if (pNetwork == null) {
      throw new IllegalArgumentException(
          "Could not find phyical network with ID: " + cmd.getPhysicalNetworkId());
    }
    zoneId = pNetwork.getDataCenterId();

    PhysicalNetworkServiceProviderVO ntwkSvcProvider =
        _physicalNetworkServiceProviderDao.findByServiceProvider(
            pNetwork.getId(), BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER.getName());
    if (ntwkSvcProvider == null) {
      throw new CloudRuntimeException(
          "Network Service Provider: "
              + BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER.getName()
              + " is not enabled in the physical network: "
              + cmd.getPhysicalNetworkId()
              + "to add this device");
    } else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) {
      throw new CloudRuntimeException(
          "Network Service Provider: "
              + ntwkSvcProvider.getProviderName()
              + " is in shutdown state in the physical network: "
              + cmd.getPhysicalNetworkId()
              + "to add this device");
    }

    HostPodVO pod = _podDao.findById(cmd.getPodId());
    if (pod == null) {
      throw new IllegalArgumentException("Could not find pod with ID: " + cmd.getPodId());
    }

    List<HostVO> pxes =
        _resourceMgr.listAllUpAndEnabledHosts(Host.Type.BaremetalPxe, null, cmd.getPodId(), zoneId);
    if (pxes.size() != 0) {
      throw new IllegalArgumentException(
          "Already had a PXE server in Pod: " + cmd.getPodId() + " zone: " + zoneId);
    }

    String storageServerIp = pcmd.getPingStorageServerIp();
    if (storageServerIp == null) {
      throw new IllegalArgumentException("No IP for storage server specified");
    }
    String pingDir = pcmd.getPingDir();
    if (pingDir == null) {
      throw new IllegalArgumentException("No direcotry for storage server specified");
    }
    String tftpDir = pcmd.getTftpDir();
    if (tftpDir == null) {
      throw new IllegalArgumentException("No TFTP directory specified");
    }

    String cifsUsername = pcmd.getPingStorageServerUserName();
    if (cifsUsername == null || cifsUsername.equalsIgnoreCase("")) {
      cifsUsername = "******";
    }
    String cifsPassword = pcmd.getPingStorageServerPassword();
    if (cifsPassword == null || cifsPassword.equalsIgnoreCase("")) {
      cifsPassword = "******";
    }

    URI uri;
    try {
      uri = new URI(cmd.getUrl());
    } catch (Exception e) {
      s_logger.debug(e);
      throw new IllegalArgumentException(e.getMessage());
    }
    String ipAddress = uri.getHost();

    String guid =
        getPxeServerGuid(
            Long.toString(zoneId) + "-" + pod.getId(), BaremetalPxeType.PING.toString(), ipAddress);

    ServerResource resource = null;
    Map params = new HashMap<String, String>();
    params.put(BaremetalPxeService.PXE_PARAM_ZONE, Long.toString(zoneId));
    params.put(BaremetalPxeService.PXE_PARAM_POD, String.valueOf(pod.getId()));
    params.put(BaremetalPxeService.PXE_PARAM_IP, ipAddress);
    params.put(BaremetalPxeService.PXE_PARAM_USERNAME, cmd.getUsername());
    params.put(BaremetalPxeService.PXE_PARAM_PASSWORD, cmd.getPassword());
    params.put(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_IP, storageServerIp);
    params.put(BaremetalPxeService.PXE_PARAM_PING_ROOT_DIR, pingDir);
    params.put(BaremetalPxeService.PXE_PARAM_TFTP_DIR, tftpDir);
    params.put(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_USERNAME, cifsUsername);
    params.put(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_PASSWORD, cifsPassword);
    params.put(BaremetalPxeService.PXE_PARAM_GUID, guid);

    resource = new BaremetalPingPxeResource();
    try {
      resource.configure("PING PXE resource", params);
    } catch (Exception e) {
      s_logger.debug(e);
      throw new CloudRuntimeException(e.getMessage());
    }

    Host pxeServer = _resourceMgr.addHost(zoneId, resource, Host.Type.BaremetalPxe, params);
    if (pxeServer == null) {
      throw new CloudRuntimeException("Cannot add PXE server as a host");
    }

    BaremetalPxeVO vo = new BaremetalPxeVO();
    Transaction txn = Transaction.currentTxn();
    vo.setHostId(pxeServer.getId());
    vo.setNetworkServiceProviderId(ntwkSvcProvider.getId());
    vo.setPodId(pod.getId());
    vo.setPhysicalNetworkId(pcmd.getPhysicalNetworkId());
    vo.setDeviceType(BaremetalPxeType.PING.toString());
    txn.start();
    _pxeDao.persist(vo);
    txn.commit();
    return vo;
  }