func newLauncher(mpiJob *kubeflow.MPIJob, kubectlDeliveryImage string) *batchv1.Job {
	launcherName := mpiJob.Name + launcherSuffix
	labels := map[string]string{
		labelGroupName:   "kubeflow.org",
		labelMPIJobName:  mpiJob.Name,
		labelMPIRoleType: launcher,
	}

	podSpec := mpiJob.Spec.Template.DeepCopy()
	// copy the labels and annotations to pod from PodTemplate
	if len(podSpec.Labels) == 0 {
		podSpec.Labels = make(map[string]string)
	}
	for key, value := range labels {
		podSpec.Labels[key] = value
	}

	podSpec.Spec.ServiceAccountName = launcherName
	podSpec.Spec.InitContainers = append(podSpec.Spec.InitContainers, corev1.Container{
		Name:  kubectlDeliveryName,
		Image: kubectlDeliveryImage,
		Env: []corev1.EnvVar{
			{
				Name:  kubectlTargetDirEnv,
				Value: kubectlMountPath,
			},
		},
		VolumeMounts: []corev1.VolumeMount{
			{
				Name:      kubectlVolumeName,
				MountPath: kubectlMountPath,
			},
		},
	})
	container := podSpec.Spec.Containers[0]
	container.Env = append(container.Env,
		corev1.EnvVar{
			Name:  "OMPI_MCA_plm_rsh_agent",
			Value: fmt.Sprintf("%s/%s", configMountPath, kubexecScriptName),
		},
		corev1.EnvVar{
			Name:  "OMPI_MCA_orte_default_hostfile",
			Value: fmt.Sprintf("%s/%s", configMountPath, hostfileName),
		})
	// Not assign any resource limits and requests to launcher pod
	container.Resources.Limits = nil
	container.Resources.Requests = nil

	// determine if run the launcher on the master node
	if mpiJob.Spec.LauncherOnMaster {

		// support Tolerate
		podSpec.Spec.Tolerations = []corev1.Toleration{
			{
				Key:    LabelNodeRoleMaster,
				Effect: corev1.TaintEffectNoSchedule,
			},
		}
		// prefer to assign pod to master node
		podSpec.Spec.Affinity = &corev1.Affinity{
			NodeAffinity: &corev1.NodeAffinity{
				RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
					NodeSelectorTerms: []corev1.NodeSelectorTerm{
						{
							MatchExpressions: []corev1.NodeSelectorRequirement{
								{
									Key:      LabelNodeRoleMaster,
									Operator: corev1.NodeSelectorOpExists,
								},
							},
						},
					},
				},
			},
		}
	}

	container.VolumeMounts = append(container.VolumeMounts,
		corev1.VolumeMount{
			Name:      kubectlVolumeName,
			MountPath: kubectlMountPath,
		},
		corev1.VolumeMount{
			Name:      configVolumeName,
			MountPath: configMountPath,
		})
	podSpec.Spec.Containers[0] = container
	podSpec.Spec.RestartPolicy = corev1.RestartPolicyOnFailure
	scriptsMode := int32(0555)
	hostfileMode := int32(0444)
	podSpec.Spec.Volumes = append(podSpec.Spec.Volumes,
		corev1.Volume{
			Name: kubectlVolumeName,
			VolumeSource: corev1.VolumeSource{
				EmptyDir: &corev1.EmptyDirVolumeSource{},
			},
		},
		corev1.Volume{
			Name: configVolumeName,
			VolumeSource: corev1.VolumeSource{
				ConfigMap: &corev1.ConfigMapVolumeSource{
					LocalObjectReference: corev1.LocalObjectReference{
						Name: mpiJob.Name + configSuffix,
					},
					Items: []corev1.KeyToPath{
						{
							Key:  kubexecScriptName,
							Path: kubexecScriptName,
							Mode: &scriptsMode,
						},
						{
							Key:  hostfileName,
							Path: hostfileName,
							Mode: &hostfileMode,
						},
					},
				},
			},
		})

	return &batchv1.Job{
		ObjectMeta: metav1.ObjectMeta{
			Name:      launcherName,
			Namespace: mpiJob.Namespace,
			Labels:    labels,
			OwnerReferences: []metav1.OwnerReference{
				*metav1.NewControllerRef(mpiJob, kubeflow.SchemeGroupVersionKind),
			},
		},
		Spec: batchv1.JobSpec{
			BackoffLimit: mpiJob.Spec.BackoffLimit,
			Template:     *podSpec,
		},
	}
}
// newLauncher creates a new launcher Job for an MPIJob resource. It also sets
// the appropriate OwnerReferences on the resource so handleObject can discover
// the MPIJob resource that 'owns' it.
newLauncher creates a new launcher Job for an MPIJob resource. It also sets
the appropriate OwnerReferences on the resource so handleObject can discover
the MPIJob resource that 'owns' it.
// newLauncher creates a new launcher Job for an MPIJob resource . It also sets // the appropriate OwnerReferences on the resource so handleObject can discover // the MPIJob resource that ' owns ' it .
func newLauncher(mpiJob *kubeflow.MPIJob, kubectlDeliveryImage string) *batchv1.Job {
	launcherName := mpiJob.Name + launcherSuffix
	labels := map[string]string{
		labelGroupName:   "kubeflow.org",
		labelMPIJobName:  mpiJob.Name,
		labelMPIRoleType: launcher,
	}
	podSpec := mpiJob.Spec.Template.DeepCopy()
	if len(podSpec.Labels) == 0 {
		podSpec.Labels = make(map[string]string)
	}
	for key, value := range labels {
		podSpec.Labels[key] = value
	}
	podSpec.Spec.ServiceAccountName = launcherName
	podSpec.Spec.InitContainers = append(podSpec.Spec.InitContainers, corev1.Container{
		Name:  kubectlDeliveryName,
		Image: kubectlDeliveryImage,
		Env: []corev1.EnvVar{
			{
				Name:  kubectlTargetDirEnv,
				Value: kubectlMountPath,
			},
		},
		VolumeMounts: []corev1.VolumeMount{
			{
				Name:      kubectlVolumeName,
				MountPath: kubectlMountPath,
			},
		},
	})
	container := podSpec.Spec.Containers[0]
	container.Env = append(container.Env,
		corev1.EnvVar{
			Name:  "OMPI_MCA_plm_rsh_agent",
			Value: fmt.Sprintf("%s/%s", configMountPath, kubexecScriptName),
		},
		corev1.EnvVar{
			Name:  "OMPI_MCA_orte_default_hostfile",
			Value: fmt.Sprintf("%s/%s", configMountPath, hostfileName),
		})
	container.Resources.Limits = nil
	container.Resources.Requests = nil
	if mpiJob.Spec.LauncherOnMaster {
		podSpec.Spec.Tolerations = []corev1.Toleration{
			{
				Key:    LabelNodeRoleMaster,
				Effect: corev1.TaintEffectNoSchedule,
			},
		}
		podSpec.Spec.Affinity = &corev1.Affinity{
			NodeAffinity: &corev1.NodeAffinity{
				RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
					NodeSelectorTerms: []corev1.NodeSelectorTerm{
						{
							MatchExpressions: []corev1.NodeSelectorRequirement{
								{
									Key:      LabelNodeRoleMaster,
									Operator: corev1.NodeSelectorOpExists,
								},
							},
						},
					},
				},
			},
		}
	}
	container.VolumeMounts = append(container.VolumeMounts,
		corev1.VolumeMount{
			Name:      kubectlVolumeName,
			MountPath: kubectlMountPath,
		},
		corev1.VolumeMount{
			Name:      configVolumeName,
			MountPath: configMountPath,
		})
	podSpec.Spec.Containers[0] = container
	podSpec.Spec.RestartPolicy = corev1.RestartPolicyOnFailure
	scriptsMode := int32(0555)
	hostfileMode := int32(0444)
	podSpec.Spec.Volumes = append(podSpec.Spec.Volumes,
		corev1.Volume{
			Name: kubectlVolumeName,
			VolumeSource: corev1.VolumeSource{
				EmptyDir: &corev1.EmptyDirVolumeSource{},
			},
		},
		corev1.Volume{
			Name: configVolumeName,
			VolumeSource: corev1.VolumeSource{
				ConfigMap: &corev1.ConfigMapVolumeSource{
					LocalObjectReference: corev1.LocalObjectReference{
						Name: mpiJob.Name + configSuffix,
					},
					Items: []corev1.KeyToPath{
						{
							Key:  kubexecScriptName,
							Path: kubexecScriptName,
							Mode: &scriptsMode,
						},
						{
							Key:  hostfileName,
							Path: hostfileName,
							Mode: &hostfileMode,
						},
					},
				},
			},
		})
	return &batchv1.Job{
		ObjectMeta: metav1.ObjectMeta{
			Name:      launcherName,
			Namespace: mpiJob.Namespace,
			Labels:    labels,
			OwnerReferences: []metav1.OwnerReference{
				*metav1.NewControllerRef(mpiJob, kubeflow.SchemeGroupVersionKind),
			},
		},
		Spec: batchv1.JobSpec{
			BackoffLimit: mpiJob.Spec.BackoffLimit,
			Template:     *podSpec,
		},
	}
}
func newLauncher ( mpiJob * kubeflow . MPIJob , kubectlDeliveryImage string ) * batchv1 . Job { launcherName := mpiJob . Name + launcherSuffix labels := map [ string ] string { labelGroupName : " " , labelMPIJobName : mpiJob . Name , labelMPIRoleType : launcher , } podSpec := mpiJob . Spec . Template . DeepCopy ( ) if len ( podSpec . Labels ) == 0 { podSpec . Labels = make ( map [ string ] string ) } for key , value := range labels { podSpec . Labels [ key ] = value } podSpec . Spec . ServiceAccountName = launcherName podSpec . Spec . InitContainers = append ( podSpec . Spec . InitContainers , corev1 . Container { Name : kubectlDeliveryName , Image : kubectlDeliveryImage , Env : [ ] corev1 . EnvVar { { Name : kubectlTargetDirEnv , Value : kubectlMountPath , } , } , VolumeMounts : [ ] corev1 . VolumeMount { { Name : kubectlVolumeName , MountPath : kubectlMountPath , } , } , } ) container := podSpec . Spec . Containers [ 0 ] container . Env = append ( container . Env , corev1 . EnvVar { Name : " " , Value : fmt . Sprintf ( " " , configMountPath , kubexecScriptName ) , } , corev1 . EnvVar { Name : " " , Value : fmt . Sprintf ( " " , configMountPath , hostfileName ) , } ) container . Resources . Limits = nil container . Resources . Requests = nil if mpiJob . Spec . LauncherOnMaster { podSpec . Spec . Tolerations = [ ] corev1 . Toleration { { Key : LabelNodeRoleMaster , Effect : corev1 . TaintEffectNoSchedule , } , } podSpec . Spec . Affinity = & corev1 . Affinity { NodeAffinity : & corev1 . NodeAffinity { RequiredDuringSchedulingIgnoredDuringExecution : & corev1 . NodeSelector { NodeSelectorTerms : [ ] corev1 . NodeSelectorTerm { { MatchExpressions : [ ] corev1 . NodeSelectorRequirement { { Key : LabelNodeRoleMaster , Operator : corev1 . NodeSelectorOpExists , } , } , } , } , } , } , } } container . VolumeMounts = append ( container . VolumeMounts , corev1 . VolumeMount { Name : kubectlVolumeName , MountPath : kubectlMountPath , } , corev1 . VolumeMount { Name : configVolumeName , MountPath : configMountPath , } ) podSpec . Spec . Containers [ 0 ] = container podSpec . Spec . RestartPolicy = corev1 . RestartPolicyOnFailure scriptsMode := int32 ( 0555 ) hostfileMode := int32 ( 0444 ) podSpec . Spec . Volumes = append ( podSpec . Spec . Volumes , corev1 . Volume { Name : kubectlVolumeName , VolumeSource : corev1 . VolumeSource { EmptyDir : & corev1 . EmptyDirVolumeSource { } , } , } , corev1 . Volume { Name : configVolumeName , VolumeSource : corev1 . VolumeSource { ConfigMap : & corev1 . ConfigMapVolumeSource { LocalObjectReference : corev1 . LocalObjectReference { Name : mpiJob . Name + configSuffix , } , Items : [ ] corev1 . KeyToPath { { Key : kubexecScriptName , Path : kubexecScriptName , Mode : & scriptsMode , } , { Key : hostfileName , Path : hostfileName , Mode : & hostfileMode , } , } , } , } , } ) return & batchv1 . Job { ObjectMeta : metav1 . ObjectMeta { Name : launcherName , Namespace : mpiJob . Namespace , Labels : labels , OwnerReferences : [ ] metav1 . OwnerReference { * metav1 . NewControllerRef ( mpiJob , kubeflow . SchemeGroupVersionKind ) , } , } , Spec : batchv1 . JobSpec { BackoffLimit : mpiJob . Spec . BackoffLimit , Template : * podSpec , } , } }
newLauncher creates a new launcher Job for an MPIJob resource.
newLauncher creates a new launcher Job for an MPIJob resource .
// copy the labels and annotations to pod from PodTemplate // Not assign any resource limits and requests to launcher pod // determine if run the launcher on the master node // support Tolerate // prefer to assign pod to master node