func (p *DeployService) CreateCluster(request entity.Request) (servers []entity.Server, errorCode string, err error) {
	logrus.Infof("start to Deploy Docker Cluster...")
	sshUser := request.ProviderInfo.Provider.SshUser
	//Call the Docker Machines to create machines, change /etc/hosts and Replace PubKey File
	servers, swarmServers, mgmtServers, _, sharedServers, _, err := dockerMachineCreateCluster(request)

	if err != nil {
		logrus.Errorf("Call docker-machine to create cluster failed , err is %v", err)
		return
	}

	storagePath := DOCKERMACHINE_STORAGEPATH_PREFIX + request.UserName + "/" + request.ClusterName

	//TODO prepare ".env" file for new Cluster, need to understand whether 'slave on master'
	//call docker-compose to deploy the management clusters and slave clusters
	clusterSlaveSize := request.ClusterNumber - 1
	if request.IsLinkerMgmt == false {
		clusterSlaveSize = request.ClusterNumber - 4
	}

	logrus.Infof("start to Call Docker Compose")

	err = dockerComposeCreateCluster(request.UserName, request.ClusterName, swarmServers, clusterSlaveSize)

	if err != nil {
		logrus.Errorf("Call docker-compose to create cluster failed , err is %v", err)
		return
	}

	//get the first ip of mgmtServer as marathon Ip
	marathonEndpoint := fmt.Sprintf("%s:8080", mgmtServers[0].IpAddress)
	logrus.Debugf("marathon endpoint is %s", marathonEndpoint)

	//Start create Linker Components
	if request.IsLinkerMgmt {
		//copy the key for mongo db
		for _, server := range mgmtServers {
			commandStr := fmt.Sprintf("sudo mkdir -p /linker/key && sudo chown -R %s:%s /linker", sshUser, sshUser)
			_, _, err = command.ExecCommandOnMachine(server.Hostname, commandStr, storagePath)
			if err != nil {
				errorCode = DEPLOY_ERROR_COPY_CONFIG_FILE
				logrus.Errorf("mkdir /linker/config failed when copy dns config file", err)
				return
			}
			_, _, err = command.ScpToMachine(server.Hostname, "/linker/key/mongodb-keyfile", "/linker/key/mongodb-keyfile", storagePath)
			if err != nil {
				errorCode = DEPLOY_ERROR_COPY_CONFIG_FILE
				logrus.Errorf("copy mongodb key file to target server %s fail, err is %v", server.Hostname, err)
				return
			}
		}

		//call the marathon to deploy the linker service containers for Linker-Management Cluster
		payload := prepareLinkerComponents(mgmtServers, swarmServers[0])
		deploymentId, _ := GetMarathonService().CreateGroup(payload, marathonEndpoint)
		flag, errDeploy := waitForMarathon(deploymentId, marathonEndpoint)
		if flag {
			if errDeploy != nil {
				errorCode = DEPLOY_ERROR_CREATE
				err = errDeploy
				logrus.Errorf("deploy the linker management components fail, err is %v", errDeploy)
				return
			} else {
				logrus.Infof("deploy the linker management components finished successfully...")
			}
		} else {
			errorCode = DEPLOY_ERROR_CREATE
			err = errDeploy
			logrus.Errorf("deploy the linker management components fail because of timeout, err is %v", errDeploy)
			return
		}
	}

	//call the marathon to deploy the mesos-UI for Linker-Management Cluster and User-Management Cluster
	logrus.Infof("Start to deploy the linker ui ...")
	payload := prepareMesosUI(mgmtServers, sharedServers[0], request.IsLinkerMgmt)
	deploymentId, _ := GetMarathonService().CreateGroup(payload, marathonEndpoint)
	logrus.Infof("Start to deploy the linker ui with deployment Id: %s", deploymentId)
	flag, errDeploy := waitForMarathon(deploymentId, marathonEndpoint)
	if flag {
		if errDeploy != nil {
			errorCode = DEPLOY_ERROR_CREATE
			err = errDeploy
			logrus.Errorf("deploy the linker ui and user mgmt components fail, err is %v", errDeploy)
			return
		} else {
			logrus.Infof("deploy the linker ui and user mgmt components finished successfully...")
		}
	} else {
		errorCode = DEPLOY_ERROR_CREATE
		err = errDeploy
		logrus.Errorf("deploy the linker ui and user mgmt components fail because of timeout, err is %v", errDeploy)
		return
	}
	return
}
func dockerMachineCreateCluster(request entity.Request) (servers, swarmServers, mgmtServers, dnsServers, sharedServers []entity.Server, errorCode string, err error) {
	sshUser := request.ProviderInfo.Provider.SshUser
	storagePath := DOCKERMACHINE_STORAGEPATH_PREFIX + request.UserName + "/" + request.ClusterName
	var slaveServers []entity.Server
	isLinkerMgmt := request.IsLinkerMgmt
	requestIdLabel := entity.Label{Key: "requestId", Value: request.RequestId}
	masterLabel := entity.Label{Key: "master", Value: "true"}
	slaveLabel := entity.Label{Key: "slave", Value: "true"}

	//create Server and install consule
	labels := []entity.Label{}
	labels = append(labels, requestIdLabel)
	consuleServer, _, err := GetDockerMachineService().Create(request.UserName, request.ClusterName, false, false, "", request.ProviderInfo, labels)
	consuleServer.IsConsul = true
	_, _, err = command.BootUpConsul(consuleServer.Hostname, consuleServer.StoragePath)
	if err != nil {
		err = errors.New("Bootup Consul server error!")
		return
	}
	servers = append(servers, consuleServer)

	if isLinkerMgmt {
		labels := []entity.Label{}
		labels = append(labels, masterLabel)
		labels = append(labels, slaveLabel)
		labels = append(labels, requestIdLabel)
		//create Server, install Swarm Master and Label as Mgmt and Slave Node
		swarmMasterServer, _, _ := GetDockerMachineService().Create(request.UserName, request.ClusterName, true, true, consuleServer.Hostname, request.ProviderInfo, labels)
		swarmMasterServer.IsMaster = true
		swarmMasterServer.IsSlave = true
		swarmMasterServer.IsSwarmMaster = true
		swarmServers = append(swarmServers, swarmMasterServer)
		mgmtServers = append(mgmtServers, swarmMasterServer)
		dnsServers = append(dnsServers, swarmMasterServer)
		servers = append(servers, swarmMasterServer)

		//create Server, install Swarm Slave and Label as Mgmt and Slave Node
		for i := 0; i < request.ClusterNumber-2; i++ {
			server, _, _ := GetDockerMachineService().Create(request.UserName, request.ClusterName, true, false, consuleServer.Hostname, request.ProviderInfo, labels)
			server.IsMaster = true
			server.IsSlave = true
			swarmServers = append(swarmServers, server)
			mgmtServers = append(mgmtServers, server)
			dnsServers = append(dnsServers, server)
			servers = append(servers, server)
		}
	} else {
		labels := []entity.Label{}
		labels = append(labels, masterLabel)
		labels = append(labels, requestIdLabel)
		//create Server, install Swarm Master and Label as MgmtOnly Node
		swarmMasterServer, _, _ := GetDockerMachineService().Create(request.UserName, request.ClusterName, true, true, consuleServer.Hostname, request.ProviderInfo, labels)
		swarmMasterServer.IsMaster = true
		swarmMasterServer.IsSwarmMaster = true
		swarmMasterServer.IsDnsServer = true
		swarmServers = append(swarmServers, swarmMasterServer)
		mgmtServers = append(mgmtServers, swarmMasterServer)
		servers = append(servers, swarmMasterServer)
		dnsServers = append(dnsServers, swarmMasterServer)

		//create Server, install Swarm Slave and Label as Mgmt Node
		for i := 0; i < 2; i++ {
			server, _, _ := GetDockerMachineService().Create(request.UserName, request.ClusterName, true, false, consuleServer.Hostname, request.ProviderInfo, labels)
			server.IsMaster = true
			server.IsDnsServer = true //TODO : install lb and dns on the master by swarm
			swarmServers = append(swarmServers, server)
			mgmtServers = append(mgmtServers, server)
			servers = append(servers, server)
			dnsServers = append(dnsServers, server)
		}

		slavelabels := []entity.Label{}
		slavelabels = append(slavelabels, slaveLabel)
		slavelabels = append(slavelabels, requestIdLabel)
		//create Server, install Swarm Slave and Label as Slave Node
		for i := 0; i < request.ClusterNumber-4; i++ {
			server, _, _ := GetDockerMachineService().Create(request.UserName, request.ClusterName, true, false, consuleServer.Hostname, request.ProviderInfo, slavelabels)
			server.IsSlave = true
			swarmServers = append(swarmServers, server)
			servers = append(servers, server)
			slaveServers = append(slaveServers, server)
			//choose the first slave server as shared server
		}
	}

	//prepare the dns config and copy to all managements nodes
	logrus.Infof("start to prepare the dns config ")
	err = changeDnsConfig(mgmtServers)
	if err != nil {
		errorCode = DEPLOY_ERROR_CHANGE_DNSCONFIG
		return
	}

	//copy the dns config file to target dns server
	logrus.Infof("start to copy the dns config file to target dns server")
	for _, server := range dnsServers {
		commandStr := fmt.Sprintf("sudo mkdir -p /linker/config && sudo chown -R %s:%s /linker", sshUser, sshUser)
		_, _, err = command.ExecCommandOnMachine(server.Hostname, commandStr, storagePath)
		if err != nil {
			errorCode = DEPLOY_ERROR_COPY_CONFIG_FILE
			logrus.Errorf("mkdir /linker/config failed when copy dns config file", err)
			return
		}
		_, _, err = command.ScpToMachine(server.Hostname, "/linker/config/config.json", "/linker/config/config.json", storagePath)
		if err != nil {
			errorCode = DEPLOY_ERROR_COPY_CONFIG_FILE
			logrus.Errorf("copy dns config file to target server %s fail, err is %v", server.Hostname, err)
			return
		}
	}

	//Change "/etc/resolve.conf" if Linker Management Cluster
	logrus.Infof("start to change name server for all nodes")
	err = changeNameserver(swarmServers, dnsServers, storagePath, request.IsLinkerMgmt)
	if err != nil {
		errorCode = DEPLOY_ERROR_CHANGE_NAMESERVER
		return
	}

	//weave should be boot after dns configured
	var weaveServer entity.Server
	for i, server := range slaveServers {
		if i == 0 {
			weaveServer = server
			sharedServers = append(sharedServers, weaveServer)
		}
		_, _, err = command.BootUpWeave(server.Hostname, server.StoragePath, weaveServer.PrivateIpAddress)
		if err != nil {
			err = errors.New("Bootup Weave error!")
			return
		}
	}

	return
}