/**
   * This method roll-outs Etcd nodes. On successful rollout, the methods moves the task sub-stage
   * to SETUP_MASTER.
   *
   * @param currentState
   */
  private void setupEtcds(KubernetesClusterCreateTask currentState) {
    NodeRolloutInput rolloutInput = new NodeRolloutInput();
    rolloutInput.projectId = currentState.projectId;
    rolloutInput.imageId = currentState.imageId;
    rolloutInput.vmFlavorName = currentState.otherVmFlavorName;
    rolloutInput.diskFlavorName = currentState.diskFlavorName;
    rolloutInput.vmNetworkId = currentState.vmNetworkId;
    rolloutInput.clusterId = currentState.clusterId;
    rolloutInput.nodeCount = currentState.etcdIps.size();
    rolloutInput.nodeType = NodeType.KubernetesEtcd;
    rolloutInput.nodeProperties =
        EtcdNodeTemplate.createProperties(
            currentState.dns, currentState.gateway, currentState.netmask, currentState.etcdIps);

    NodeRollout rollout = new BasicNodeRollout();
    rollout.run(
        this,
        rolloutInput,
        new FutureCallback<NodeRolloutResult>() {
          @Override
          public void onSuccess(@Nullable NodeRolloutResult result) {
            TaskUtils.sendSelfPatch(
                KubernetesClusterCreateTaskService.this,
                buildPatch(
                    KubernetesClusterCreateTask.TaskState.TaskStage.STARTED,
                    KubernetesClusterCreateTask.TaskState.SubStage.SETUP_MASTER));
          }

          @Override
          public void onFailure(Throwable t) {
            failTaskAndPatchDocument(currentState, NodeType.SwarmEtcd, t);
          }
        });
  }
  /**
   * This method roll-outs Kubernetes Master Nodes. On successful roll-out, the methods moves the
   * task sub-stage to SETUP_SLAVES.
   *
   * @param currentState
   */
  private void setupMaster(final KubernetesClusterCreateTask currentState) {
    NodeRolloutInput rolloutInput = new NodeRolloutInput();
    rolloutInput.clusterId = currentState.clusterId;
    rolloutInput.projectId = currentState.projectId;
    rolloutInput.imageId = currentState.imageId;
    rolloutInput.diskFlavorName = currentState.diskFlavorName;
    rolloutInput.vmFlavorName = currentState.masterVmFlavorName;
    rolloutInput.vmNetworkId = currentState.vmNetworkId;
    rolloutInput.nodeCount = ClusterManagerConstants.Kubernetes.MASTER_COUNT;
    rolloutInput.nodeType = NodeType.KubernetesMaster;
    rolloutInput.nodeProperties =
        KubernetesMasterNodeTemplate.createProperties(
            currentState.etcdIps,
            currentState.dns,
            currentState.gateway,
            currentState.netmask,
            currentState.masterIp,
            currentState.containerNetwork);

    NodeRollout rollout = new BasicNodeRollout();
    rollout.run(
        this,
        rolloutInput,
        new FutureCallback<NodeRolloutResult>() {
          @Override
          public void onSuccess(@Nullable NodeRolloutResult result) {
            TaskUtils.sendSelfPatch(
                KubernetesClusterCreateTaskService.this,
                buildPatch(TaskState.TaskStage.STARTED, TaskState.SubStage.SETUP_SLAVES));
          }

          @Override
          public void onFailure(Throwable t) {
            failTaskAndPatchDocument(currentState, NodeType.KubernetesMaster, t);
          }
        });
  }
  /**
   * This method roll-outs Kubernetes Slave Nodes. On successful roll-out, the method sets the
   * task's state as Finished.
   *
   * @param currentState
   */
  private void setupInitialSlaves(final KubernetesClusterCreateTask currentState) {
    NodeRolloutInput rolloutInput = new NodeRolloutInput();
    rolloutInput.clusterId = currentState.clusterId;
    rolloutInput.projectId = currentState.projectId;
    rolloutInput.imageId = currentState.imageId;
    rolloutInput.diskFlavorName = currentState.diskFlavorName;
    rolloutInput.vmFlavorName = currentState.otherVmFlavorName;
    rolloutInput.vmNetworkId = currentState.vmNetworkId;
    rolloutInput.nodeCount = MINIMUM_INITIAL_SLAVE_COUNT;
    rolloutInput.nodeType = NodeType.KubernetesSlave;
    rolloutInput.serverAddress = currentState.masterIp;
    rolloutInput.nodeProperties =
        KubernetesSlaveNodeTemplate.createProperties(
            currentState.etcdIps, currentState.containerNetwork, currentState.masterIp);

    NodeRollout rollout = new SlavesNodeRollout();
    rollout.run(
        this,
        rolloutInput,
        new FutureCallback<NodeRolloutResult>() {
          @Override
          public void onSuccess(@Nullable NodeRolloutResult result) {
            setupRemainingSlaves(currentState);
          }

          @Override
          public void onFailure(Throwable t) {
            failTaskAndPatchDocument(currentState, NodeType.KubernetesSlave, t);
          }
        });
  }