func (d *Driver) Remove() error {
	log.Debug("deleting instance...")
	log.Info("Deleting aliyun instance...")
	c := ecs.NewClient(
		d.AccessKeyID,
		d.AccessKeySecret,
	)
	if cstate, _ := d.GetState(); cstate == state.Running {

		if err := c.StopInstance(d.InstanceID, "true"); err != nil {
			return fmt.Errorf(errorOnStopMachine, err.Error())
		}
		//等待虚拟机停机
		for {
			if cstate, _ = d.GetState(); cstate == state.Stopped {
				break
			}
			time.Sleep(3 * time.Second)
		}
	}
	if err := c.DeleteInstance(d.InstanceID); err != nil {
		return fmt.Errorf(errorOnRemoveMachine, err.Error())
	}

	if d.IsTempSecurityGroup {
		for {
			if cstate, _ := d.GetState(); cstate == state.None {
				d.deleteSecurityGroup()
				break
			}
			time.Sleep(1 * time.Second)
		}
	}
	return nil
}
func (d *Driver) Restart() error {
	log.Info("Restarting Aliyun instance...")
	c := ecs.NewClient(
		d.AccessKeyID,
		d.AccessKeySecret,
	)
	if err := c.RebootInstance(d.InstanceID, "false"); err != nil {
		return fmt.Errorf(errorOnRestartMachine, err.Error())
	}
	return nil
}
func (d *Driver) Start() error {
	log.Info("Starting aliyun instance...")
	c := ecs.NewClient(
		d.AccessKeyID,
		d.AccessKeySecret,
	)
	if err := c.StartInstance(d.InstanceID); err != nil {
		return fmt.Errorf(errorOnStartMachine, err.Error())
	}
	return nil
}
func (d *Driver) deleteSecurityGroup() {
	c := ecs.NewClient(
		d.AccessKeyID,
		d.AccessKeySecret,
	)
	_, err := c.DeleteSecurityGroup(&ecs.DeleteSecurityGroupRequest{RegionId: d.RegionId, SecurityGroupId: d.SecurityGroupId})
	if err != nil {
		fmt.Println(err.Error())
		fmt.Println("删除安全组失败,请登录阿里云管理控制台手动删除")
	}
}
func (d *Driver) GetIP() (string, error) {

	c := ecs.NewClient(
		d.AccessKeyID,
		d.AccessKeySecret,
	)

	instance, err := c.DescribeInstanceAttribute(d.RegionId, d.InstanceID)

	if err != nil {
		return "", fmt.Errorf("No IP found for the machine")
	} else {
		return instance.PublicIpAddress.IpAddress[0], nil
	}

	return "", fmt.Errorf("No IP found for the machine")
}
func (d *Driver) createSecurityGroup() error {
	c := ecs.NewClient(
		d.AccessKeyID,
		d.AccessKeySecret,
	)
	req := &ecs.CreateSecurityGroupRequest{RegionId: d.RegionId, SecurityGroupName: "Docker_Machine"}
	response, err := c.CreateSecurityGroup(req)
	if err != nil {
		return fmt.Errorf(errorOnCreateMachine, err.Error())
	} else {
		d.SecurityGroupId = response.SecurityGroupId
		//22端口
		_, err := c.AuthorizeSecurityGroup(d.CreateAuthorizeSecurityGroupRequest(d.SecurityGroupId, "22/22"))
		if err != nil {
			d.deleteSecurityGroup()
			return fmt.Errorf(err.Error())
		}

		//2376端口
		_, err = c.AuthorizeSecurityGroup(d.CreateAuthorizeSecurityGroupRequest(d.SecurityGroupId, "2376/2376"))
		if err != nil {
			d.deleteSecurityGroup()
			return fmt.Errorf(err.Error())
		}

		if d.SwarmMaster {
			//3376端口
			_, err = c.AuthorizeSecurityGroup(d.CreateAuthorizeSecurityGroupRequest(d.SecurityGroupId, "3376/3376"))
			if err != nil {
				d.deleteSecurityGroup()
				return fmt.Errorf(err.Error())
			}
		}

	}
	d.IsTempSecurityGroup = true
	return nil
}
func (d *Driver) GetState() (state.State, error) {
	log.Debug("Get status for aliyun instance...")
	c := ecs.NewClient(
		d.AccessKeyID,
		d.AccessKeySecret,
	)
	if instance, err := c.DescribeInstanceAttribute(d.RegionId, d.InstanceID); err != nil {
		return state.None, err
	} else {
		switch instance.Status {
		case "Running":
			return state.Running, nil
		case "Stopping":
			return state.Paused, nil
		case "Stopped":
			return state.Stopped, nil
		case "Starting":
			return state.Starting, nil
		case "ERROR":
			return state.Error, nil
		}
	}
	return state.None, nil
}
func (d *Driver) Create() error {
	if d.SecurityGroupId == "" {
		log.Info("Begin create SecurityGroup...")
		err := d.createSecurityGroup()
		if err != nil {
			return fmt.Errorf(errorOnCreateSecurityGroup, err.Error())
		}
	}

	log.Info("Begin create aliyun instance...")
	d.createSSHKey()

	c := ecs.NewClient(
		d.AccessKeyID,
		d.AccessKeySecret,
	)
	request := &ecs.CreateInstanceRequest{
		RegionId:                d.RegionId,
		ImageId:                 d.ImageId,
		InstanceType:            d.InstanceType,
		SecurityGroupId:         d.SecurityGroupId,
		Password:                d.Password,
		InternetChargeType:      d.InternetChargeType,
		InternetMaxBandwidthIn:  defaultInternetMaxBandwidthIn,
		InternetMaxBandwidthOut: defaultInternetMaxBandwidthOut,
		VSwitchId:               d.VSwitchId,
	}
	response, err := c.CreateInstanceByRequest(request)
	if err != nil {
		return fmt.Errorf(errorOnCreateMachine, err.Error())
	} else {
		d.InstanceID = response.InstanceId
		//如果分配公网IP失败,那么删除虚拟机
		if publicIPAddress, err := c.AllocatePublicIpAddress(d.InstanceID); err != nil {
			if err := c.DeleteInstance(d.InstanceID); err != nil {
				return fmt.Errorf(errorOnRollback, err.Error())
			}
			return fmt.Errorf(errorOnAllocatePublicIpAddress, err.Error())
		} else {
			d.IPAddress = publicIPAddress
		}
		//如果无法启动实例,那么删除虚拟机,注:目前不知道阿里云是否会出现这种情况
		if err := c.StartInstance(d.InstanceID); err != nil {
			if err := c.DeleteInstance(d.InstanceID); err != nil {
				return fmt.Errorf(errorOnRollback, err.Error())
			}
			return fmt.Errorf(errorOnStartMachine, err.Error())
		}
	}

	//等待启动完成,如果启动失败,删除虚拟机
	if err := d.waitForInstanceActive(); err != nil {
		if err := c.DeleteInstance(d.InstanceID); err != nil {
			return fmt.Errorf(errorOnRollback, err.Error())
		}
		return err
	}
	//上传公钥
	if err := d.pushSSHkeyToServer(); err != nil {
		if err := c.DeleteInstance(d.InstanceID); err != nil {
			return fmt.Errorf(errorOnRollback, err.Error())
		}
		return err
	}

	return nil
}