package com.bocloud.ims.service.builder;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.compute.ServerDriver;
import com.bocloud.cmp.driver.storage.VolumeDriver;
import com.bocloud.cmp.entity.enums.BocloudStatus;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.cmp.model.*;
import com.bocloud.common.enums.ResourceCatalog;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.RequestContext;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.ListTool;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.repository.resource.*;
import com.bocloud.ims.service.utils.PwdRandom;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 华为私有云虚拟机创建类
 *
 * @author wangyu
 * @version 4.1.0-SNAPSHOT
 * @since 2018/9/26
 */
public class HuaweiServerBuilder implements ServerBuilder {

	private static Logger logger = LoggerFactory.getLogger(HuaweiServerBuilder.class);
	private CloudServerRepository cloudServerRepository;
	private NetworkRepository networkRepository;
	private SubnetRepository subnetRepository;
	private ImageRepository imageRepository;
	private FlavorRepository flavorRepository;
	private VolumeRepository volumeRepository;
	private PortRepository portRepository;
	private PortFixedIpRepository portFixedIpRepository;
	private IpRepository ipRepository;
	private IpPoolRepository ipPoolRepository;
	private ResourceRepository resourceRepository;
	private ResourceEventRepository resourceEventRepository;
	private SecurityGroupRepository securityGroupRepository;
	private ServerSgroupRepository serverSgroupRepository;
	private KeypairRepository keypairRepository;
	private ServerLabelRepository serverLabelRepository;
	private RegionRepository regionRepository;
	private ServerDriver serverDriver;
	private VolumeDriver volumeDriver;
	private RequestContext context;
	private CloudVendor vendor;
	private ServerModel model;
	private VpcRepository vpcRepository;
	private ElasticIpRepository elasticIpRepository;

	public HuaweiServerBuilder(CloudServerRepository cloudServerRepository, NetworkRepository networkRepository,
			SubnetRepository subnetRepository, ImageRepository imageRepository, FlavorRepository flavorRepository,
			VolumeRepository volumeRepository, PortRepository portRepository,
			PortFixedIpRepository portFixedIpRepository, IpRepository ipRepository, IpPoolRepository ipPoolRepository,
			ResourceRepository resourceRepository, ResourceEventRepository resourceEventRepository,
			SecurityGroupRepository securityGroupRepository, ServerSgroupRepository serverSgroupRepository,
			KeypairRepository keypairRepository, ServerLabelRepository serverLabelRepository,
			RegionRepository regionRepository, ServerDriver serverDriver, VolumeDriver volumeDriver,
			RequestContext context, CloudVendor vendor, ZoneRepository zoneRepository, VpcRepository vpcRepository,
			ElasticIpRepository elasticIpRepository) {
		this.cloudServerRepository = cloudServerRepository;
		this.networkRepository = networkRepository;
		this.subnetRepository = subnetRepository;
		this.imageRepository = imageRepository;
		this.flavorRepository = flavorRepository;
		this.volumeRepository = volumeRepository;
		this.portRepository = portRepository;
		this.portFixedIpRepository = portFixedIpRepository;
		this.ipRepository = ipRepository;
		this.ipPoolRepository = ipPoolRepository;
		this.resourceRepository = resourceRepository;
		this.resourceEventRepository = resourceEventRepository;
		this.securityGroupRepository = securityGroupRepository;
		this.serverSgroupRepository = serverSgroupRepository;
		this.keypairRepository = keypairRepository;
		this.serverLabelRepository = serverLabelRepository;
		this.regionRepository = regionRepository;
		this.serverDriver = serverDriver;
		this.volumeDriver = volumeDriver;
		this.context = context;
		this.vendor = vendor;
		this.vpcRepository = vpcRepository;
		this.elasticIpRepository = elasticIpRepository;
	}

	@Override
	public BocloudResult<ServerModel> prepare(JSONObject object) throws Exception {
		try {
			String groups = object.getString("groups");// 安全组
			Long imageId = object.getLong("imageId");// 镜像
			String password = object.getString("password");// 密码
			String keypairName = object.getString("keypairName");// 密钥
			String name = object.getString("name");// 虚拟机名称
			String zoneId = object.getString("zoneId");
			Integer rootSize = object.getInteger("rootSize");// 根磁盘大小
			String rootVolumeType = object.getString("rootVolumeType");// 根磁盘类型
			Integer bandWidth = object.getInteger("bandWidth");// 带宽
			String vpcUuid = object.getString("vpcUuid");
			String regionId = object.getString("regionId");
			String ipv6Address = object.getString("ipv6Address");
			String publicIps = object.getString("publicIps");

			if ("PrePaid".equalsIgnoreCase(object.getString("instanceChargeType"))) {
				return new BocloudResult<>(false, "包年包月暂不支持");
			}
			// 自服务端申请
			Long diskSize = object.getLong("disk");
			String remark = object.getString("remark");// 描述
			model = new ServerModel(name, remark);
			model.setRegionId(regionId);
			model.setCount(1);
			if (StringUtils.isEmpty(vpcUuid)) {
				Long vpcId = object.getLong("networkId");
				Vpc vpc = vpcRepository.query(vpcId);
				if (null == vpc) {
					return new BocloudResult<>(false, model, "VPC网络数据异常！");
				}
				vpcUuid = vpc.getVpcId();
			}
			model.setVpcId(vpcUuid);
			model.setSubnetUuid(object.getString("subnetUuid"));
			model.setVpcUuid(object.getString("vpcUuid"));

			// 初始化第一块网卡
			List<NetworkInterfaceModel> networkInterfaceModels = new ArrayList<>();
			NetworkInterfaceModel networkInterfaceModel = new NetworkInterfaceModel();
			networkInterfaceModel.setSubnetUuid(model.getSubnetUuid());
			if (!StringUtils.isEmpty(ipv6Address)) {
				networkInterfaceModel.setIpv6Address(ipv6Address);
			}
			networkInterfaceModels.add(networkInterfaceModel);

			JSONArray nics = object.getJSONArray("networkInterfaces");
			if (null != nics && nics.size() > 0) {
				List<NetworkInterfaceModel> interfaceModels = JSONArray.parseArray(JSON.toJSONString(nics),
						NetworkInterfaceModel.class);
				if (ListTool.isEmpty(interfaceModels)) {
					return new BocloudResult<>(false, model, "参数格式不正确");
				}
				networkInterfaceModels.addAll(interfaceModels);
			}
			model.setNetworkInterfaces(networkInterfaceModels);
			model.setBandWidth(bandWidth);
			if(!StringUtils.isEmpty(publicIps)) {
				model.setPublicIps(publicIps);
			}

			Image image = null;
			String account = "root";
			if (null != imageId && 0L != imageId) {
				image = imageRepository.query(imageId);
				if (null == image) {
					return new BocloudResult<>(false, model, "镜像不存在");
				}
				model.setOsName(image.getOsName());
				model.setOsCategory(image.getOsType());
				model.setBootFromVolume(true);
				model.setImageUuid(image.getImageUuid());
				if ("Windows".equalsIgnoreCase(image.getOsType())) {
					account = "Administrator";
				}
			}

			int imageMinDisk = image.getMinDisk().intValue();

			if (null == rootSize || rootSize <= 0) {
				rootSize = imageMinDisk;
			}
			if (rootSize < imageMinDisk) {
				return new BocloudResult<>(false, model, "系统盘大小不允许小于镜像盘大小");
			}

			if (null != diskSize && diskSize > 0) {
				if (diskSize < imageMinDisk) {
					return new BocloudResult<>(false, model, "系统盘大小不允许小于镜像盘大小");
				} else {
					rootSize = Integer.parseInt(diskSize + "");
				}
			}

			model.setRootSize(rootSize);
			model.setRootVolumeType(rootVolumeType);
			model.setDisk(rootSize);
			model.setZone(zoneId);

			// 数据盘
			JSONArray dataDisks = object.getJSONArray("dataDisk");
			if (null != dataDisks && dataDisks.size() > 0) {
				List<VolumeModel> volumeModels = JSONArray.parseArray(JSON.toJSONString(dataDisks), VolumeModel.class);
				if (ListTool.isEmpty(volumeModels)) {
					return new BocloudResult<>(false, model, "参数格式不正确");
				}
				for (VolumeModel volumeModel : volumeModels) {
					if(StringUtils.isEmpty(volumeModel.getType())) {
						volumeModel.setType(volumeModel.getDataDiskCategory());
					}
					if(null == volumeModel.getSize()) {
						volumeModel.setSize(Integer.parseInt(volumeModel.getDataDiskSize()));
					}
				}
				model.setDiskDevices(volumeModels);
			}

			// 如果未设置密码则随机生成并保存
			if (StringUtils.isEmpty(keypairName) && StringUtils.isEmpty(password)) {
				password = randomStr(12);
			}
			if (!StringUtils.isEmpty(keypairName)) {
				// 查询密钥是否存在
				Keypair keypair = keypairRepository.getByName(keypairName, vendor.getId());
				if (null == keypair) {
					return new BocloudResult<>(false, model, "密钥不存在");
				}
			}
			model.setKeypairName(keypairName);
			// 规格
			String flavorUuid = object.getString("instanceType");
			Flavor flavor = flavorRepository.getByFlavorId(flavorUuid);
			if (null == flavor) {
				flavor = flavorRepository.query(object.getLong("flavorId"));
			}
			if (null == flavor) {
				return new BocloudResult<>(false, model, "规格不存在");
			}
			flavorUuid = flavor.getFlavorUuid();
			model.setCpu(flavor.getCpu());
			model.setMemory(flavor.getMemory());
			List<String> securityGroups = Lists.newArrayList();
			if (!StringUtils.isEmpty(groups)) {
				securityGroups = JSONArray.parseArray(groups, String.class);
			}
			model.prepareData(name, account, password, flavorUuid, null, securityGroups);
		} catch (Exception e) {
			logger.error("Get error Message:", e);
			return new BocloudResult<>(false, model, "fail");
		}
		return new BocloudResult<>(true, model, "success");
	}

	/**
	 * 回收IP
	 *
	 * @param networkBeans
	 * @param vendorId
	 * @return
	 */
	private void recycleIp(List<NetworkBean> networkBeans, Long vendorId) {
		try {
			if (!ListTool.isEmpty(networkBeans)) {
				for (NetworkBean networkBean : networkBeans) {
					List<AddressBean> addresses = networkBean.getAddresses();
					if (ListTool.isEmpty(addresses)) {
						continue;
					}
					for (AddressBean address : addresses) {
						ipRepository.delete(address.getAddress(), address.getSubnetId(), vendor.getId());
					}
				}
			}
		} catch (Exception e) {
			logger.error("recycle ip error:", e);
		}
	}

	@Override
	public BocloudResult<CloudServer> builder(CloudServer cloudServer) throws Exception {
		// 创建虚拟机
		BocloudResult result = null;
		try {
			// 操作记录
			Long userId = context.getTarget();
			String handler = "虚拟机创建";
			ResourceEvent event = null;
			Resource resource = null;
			// 创建虚拟机
			result = serverDriver.create(vendor.getUuid(), cloudServer.getRegionId(), model);
			if (result.isSuccess()) {
				event = new ResourceEvent(cloudServer.getId(), handler, "成功", userId, new Date(), "VM", vendor.getId(),
						context.getCatalog());
				String content = JSONObject.toJSONString(result.getData());
				CloudServer server = JSONObject.parseObject(content, CloudServer.class);
				List<Volume> diskDevices = server.getDiskDevices();
				Integer diskSize = 0;
				for (Volume volume : diskDevices) {
					BocloudResult volumeResult = volumeDriver.detail(volume.getVolumeUuid(), vendor.getUuid(),
							server.getRegionId());
					if (volumeResult.isSuccess()) {
						volume = JSONObject.parseObject(JSONObject.toJSONString(volumeResult.getData()), Volume.class);
					}
					List<ServerVolumeModel> models = volume.getModels();
					Map<String, ServerVolumeModel> serverVolumeMap = Maps.newHashMap();
					if (!ListTool.isEmpty(models)) {
						for (ServerVolumeModel model : models) {
							serverVolumeMap.put(model.getInstanceId(), model);
						}
					}
					diskSize += volume.getSize();
					ServerVolumeModel model = serverVolumeMap.get(server.getInstanceId());
					String device = null;
					if (null != model) {
						device = model.getDevice();
					}
					Volume existVolume = volumeRepository.getByVolumeUuid(volume.getVolumeUuid());
					Region region = regionRepository.getByRegionId(volume.getRegionId(), vendor.getId());
					if (null != region) {
						volume.setRegion(region.getRegionId());
					}

					if (null == existVolume) {
						volume.setCreatorId(userId);
						volume.setGmtCreate(new Date());
						volume.setVendorId(vendor.getId());
						volume.setDevice(device);
						volume.setServerId(cloudServer.getId());
						volume.setRegionId(cloudServer.getRegionId());
						volume.setTenantId(cloudServer.getTenantId());
						volume.setProjectId(cloudServer.getProjectId());
						volume.setCreatorId(cloudServer.getCreatorId());
						volume.setBusinessId(cloudServer.getBusinessId());
						volume.setMenderId(cloudServer.getMenderId());
						volume.setInstanceId(server.getInstanceId());
						if ("/dev/vda".equals(device) || "/dev/sda".equals(device)) {
							volume.setBootVolume(true);
						}
						volumeRepository.save(volume);
					} else {
						// 更新
						existVolume.setStatus("IN_USE");
						existVolume.setDevice(device);
						existVolume.setGmtModify(new Date());
						existVolume.setMenderId(cloudServer.getMenderId());
						existVolume.setServerId(cloudServer.getId());
						existVolume.setTenantId(cloudServer.getTenantId());
						existVolume.setBusinessId(cloudServer.getBusinessId());
						existVolume.setProjectId(cloudServer.getProjectId());
						existVolume.setInstanceId(server.getInstanceId());
						existVolume.setRegionId(cloudServer.getRegionId());
						existVolume.setBootVolume(true);
						volumeRepository.update(existVolume);
					}
				}
				cloudServer.setDisk(model.getDisk());

				List<Volume> listByServerId = volumeRepository.listByServerId(cloudServer.getId());
				if (null != listByServerId && listByServerId.size() > 0) {
					cloudServer.setDiskDevices(listByServerId);
				}

				cloudServer.setAccount(model.getAccount());
				cloudServer.setPswd(model.getPassword());
				cloudServer.setImageUuid(server.getImageUuid());
				cloudServer.setGroups(server.getGroups());
				cloudServer.setInstanceId(server.getInstanceId());
				cloudServer.setSubnetUuid(model.getSubnetUuid());
				cloudServer.setUuid(server.getUuid());
				cloudServer.setZone(server.getZone());
				cloudServer.setHostName(server.getHostName());
				cloudServer.setOsCategory(server.getOsCategory());
				cloudServer.setOsName(server.getOsName());
				cloudServer.setOsVersion(server.getOsVersion());
				cloudServer.setRegionId(server.getRegionId());
				cloudServer.setNetworkUuid(server.getNetworkUuid());
				cloudServer.setPublicIps(server.getPublicIps());
				String flavorUuid = server.getFlavorUuid();
				if (!StringUtils.isEmpty(flavorUuid)) {
					Flavor flavor = flavorRepository.getByFlavorUuid(flavorUuid);
					if (null != flavor) {
						cloudServer.setCpu(flavor.getCpu());
						cloudServer.setMemory(flavor.getMemory());
					}
				}
				cloudServer.setKeypairName(server.getKeypairName());
				cloudServer.setFlavorUuid(flavorUuid);
				cloudServer.setGmtVmCreate(server.getGmtVmCreate());
				cloudServer.setManagerIp(server.getManagerIp());
				cloudServer.setRegion(server.getRegion());
				cloudServer.setRecycle(false);
				String state = server.getStatus();
				logger.info("Start to update vm status...");
				updateStatus(cloudServer, state);
				logger.info("End to update vm status...");
				if (state.equalsIgnoreCase(BocloudStatus.Server.EXCEPTION.name())
						|| state.equalsIgnoreCase(BocloudStatus.Server.SUSPENDED.name())) {
					event = new ResourceEvent(cloudServer.getId(), handler, "失败", userId, new Date(), "VM",
							vendor.getId(), context.getCatalog());
				}
				logger.info("Start to sync vm port...");
				List<PortModel> ports = server.getPorts();
				// 保存端口
//				Map<String, List<PortModel>> portMap = Maps.newHashMap();
//				Map<String, NetworkBean> networkMap = Maps.newHashMap();
//				Map<String, AddressBean> subnetMap = Maps.newHashMap();
				if (null != ports && ports.size() > 0) {
					for (PortModel portModel : ports) {
						Port port = new Port();
						BeanUtils.copyProperties(portModel, port);
//						Network network = networkRepository.getByNetId(portModel.getNetworkUuid());
//						NetworkBean networkBean = new NetworkBean(network.getId(), network.getName(),
//								network.getNetworkUuid());
//						networkMap.put(portModel.getNetworkUuid(), networkBean);
//						port.preSave(userId, userId, vendor.getId(), network.getId());
						port.preSave(userId, userId, vendor.getId(), null);
//						port.setStatus(BocloudStatus.Network.RUNNING.name());
//						port.setDeviceOwner("compute:None");
						port.setDeviceUuid(server.getInstanceId());
						portRepository.save(port);
						// 保存fixedip
						List<PortFixedIpModel> fixedIpModels = portModel.getPortFixedIps();
						if (!ListTool.isEmpty(fixedIpModels)) {
							for (PortFixedIpModel fixedIpModel : fixedIpModels) {
								PortFixedIp portFixedIp = new PortFixedIp();
								BeanUtils.copyProperties(fixedIpModel, portFixedIp);
								portFixedIp.setPortId(port.getId());
								portFixedIp.setPortUuid(portModel.getPortUuid());
								Subnet subnet = subnetRepository.getBySubId(fixedIpModel.getSubnetUuid());
								if (null != subnet) {
									portFixedIp.setSubnetId(subnet.getId());
								}
								portFixedIpRepository.save(portFixedIp);
//								AddressBean addressBean = new AddressBean(subnet.getId(), subnet.getName(),
//										network.getId(), subnet.getSubnetUuid(), port.getId(), port.getPortUuid(),
//										portFixedIp.getIpAddress());
//								subnetMap.put(addressBean.getSubnetUuid(), addressBean);
//								// 更新IP
//								Ip ip = ipRepository.checkExist(fixedIpModel.getIpAddress(), subnet.getId(),
//										vendor.getId());
//								// IP不存在，则添加IP记录
//								if (null == ip) {
//									String mask = IPAddress.getIPAddress(fixedIpModel.getIpAddress()).getMask(
//											subnet.getCidr());
//									ip = new Ip(fixedIpModel.getIpAddress(), mask, subnet.getGateway(),
//											subnet.getDnsNames(), vendor.getId(), IDFactory.instance().uuid(), null);
//									ip.setSubnetId(subnet.getId());
//									ip.setNetworkId(port.getNetworkId());
//									ip.setCatalog("PORT");
//									ip.setTarget(port.getId());
//									IpPool pool = ipPoolRepository.queryBySubnet(subnet.getId(), vendor.getId());
//									if (null != pool) {
//										ip.setPoolId(pool.getId());
//									}
//									ipRepository.save(ip);
//								} else {
//									ip.setTarget(port.getId());
//									ipRepository.update(ip);
//								}
							}
						}
//						portModel.setPortId(port.getId());
//						if (portMap.containsKey(portModel.getNetworkUuid())) {
//							List<PortModel> models = portMap.get(portModel.getNetworkUuid());
//							models.add(portModel);
//						} else {
//							List<PortModel> models = Lists.newArrayList();
//							models.add(portModel);
//							portMap.put(portModel.getNetworkUuid(), models);
//						}
					}
				}
//				logger.info("Start to sync vm port...");
//				List<NetworkBean> beans = Lists.newArrayList();
//				for (String key : portMap.keySet()) {
//					List<PortModel> portList = portMap.get(key);
//					if (!portList.isEmpty()) {
//						NetworkBean networkBean = networkMap.get(key);
//						List<AddressBean> addresses = Lists.newArrayList();
//						for (PortModel pModel : portList) {
//							AddressBean address = subnetMap.get(pModel.getPortFixedIps().get(0).getSubnetUuid());
//							address.setAddress(pModel.getPortFixedIps().get(0).getIpAddress());
//							address.setPortId(pModel.getPortId());
//							address.setPortUuid(pModel.getPortUuid());
//							addresses.add(address);
//						}
//						networkBean.setAddresses(addresses);
//						beans.add(networkBean);
//					}
//				}
				// 设置内网所有ip
				String privateIps = server.getPrivateIps();
				if (!StringUtils.isEmpty(privateIps)) {
					cloudServer.setPrivateIps(server.getPrivateIps());
					List<JSONObject> publicArrays = JSONObject.parseArray(privateIps, JSONObject.class);
					if (!ListTool.isEmpty(publicArrays)) {
						for (JSONObject poblicIpObject : publicArrays) {
							String type = poblicIpObject.getString("type");
							if ("floating".equalsIgnoreCase(type)) {
								ElasticIp elasticIp = elasticIpRepository
										.queryByPublicIp(poblicIpObject.getString("address"), vendor.getId());
								if (null != elasticIp) {
									elasticIp.setInstanceId(poblicIpObject.getString("portId"));
									elasticIp.setAssociationId(cloudServer.getInstanceId());
									elasticIp.setStatus("ACTIVE");
									elasticIpRepository.update(elasticIp);
								}
							}
						}
					}
				}
				// 保存安全组信息
				if (!StringUtils.isEmpty(server.getGroups())) {
					logger.info("Start to sync vm security group...");
					// 删除旧安全组与虚拟机的关系
					serverSgroupRepository.removeBySid(cloudServer.getId());
					List<String> groups = JSONObject.parseArray(server.getGroups(), String.class);
					for (String group : groups) {
						SecurityGroup securityGroup = securityGroupRepository.getByName(group, server.getRegionId(),
								vendor.getId());
						if (null == securityGroup) {
							continue;
						}
						ServerSgroup serverSgroupInfo = serverSgroupRepository.getByServerGroup(cloudServer.getId(),
								securityGroup.getId());
						// 保存虚拟机和安全组关系
						if (null == serverSgroupInfo) {
							serverSgroupRepository.save(new ServerSgroup(cloudServer.getId(), securityGroup.getId()));
						}
					}
					logger.info("End to sync vm security group...");
				}
				if (BocloudStatus.Server.ERROR.name().equals(cloudServer.getStatus())) {
					cloudServer.setStatus(BocloudStatus.Server.EXCEPTION.name());
				}
				cloudServerRepository.update(cloudServer);
				// 保存标签信息
				List<Long> labelIds = model.getLabelIds();
				if (!ListTool.isEmpty(labelIds)) {
					List<ServerLabel> serverLabels = Lists.newArrayList();
					for (Long labelId : labelIds) {
						serverLabels.add(new ServerLabel(cloudServer.getId(), labelId, "VM", vendor.getId()));
					}
					if (!ListTool.isEmpty(serverLabels)) {
						serverLabelRepository.batchSave(serverLabels);
					}
				}
				// 保存资源
				List<String> ips = Lists.newArrayList();
				if (!StringUtils.isEmpty(cloudServer.getPrivateIps())) {
					List<JSONObject> objects = JSONObject.parseArray(cloudServer.getPrivateIps(), JSONObject.class);
					for (JSONObject object : objects) {
						String address = (String) object.get("address");
						ips.add(address);
					}
				}
				resource = resourceRepository.query(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
						cloudServer.getId());
				if (null == resource) {
					resource = new Resource(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
							cloudServer.getId(), JSONObject.toJSONString(ips), cloudServer.getOsCategory(),
							vendor.getId());
					resource.preSave(cloudServer.getName(), cloudServer.getStatus(), userId, context.getTenant(),
							context.getProject());
					resource.setRegionId(cloudServer.getRegionId());
					resource.setInventory(JSONObject.toJSONString(cloudServer));
					resourceRepository.save(resource);
				} else {
					resource.setInventory(JSONObject.toJSONString(cloudServer));
					resource.setStatus(cloudServer.getStatus());
					resource.setMenderId(userId);
					resource.setCreatorId(userId);
					resource.setGmtModify(new Date());
					resource.setGmtCreate(new Date());
					resource.setPrivateIps(JSONObject.toJSONString(ips));
					resource.setRegionId(cloudServer.getRegionId());
					resourceRepository.update(resource);
				}
			} else {
				logger.info("Remove the cloned virtual machine failure");
				event = new ResourceEvent(cloudServer.getId(), handler, "失败", userId, new Date(), "VM", vendor.getId(),
						context.getCatalog());
				cloudServerRepository.remove(cloudServer.getId(), userId);
				// 回收IP
//				recycleIp(model.getNetworkBeans(), vendor.getId());
				serverLabelRepository.deleteByTarget(cloudServer.getId(), "VM");
			}
			resourceEventRepository.save(event);
		} catch (Exception e) {
			logger.error("Get error message:", e);
			// 回收IP
//			recycleIp(model.getNetworkBeans(), vendor.getId());
			return new BocloudResult<>(false, cloudServer, "create fail");
		}
		return result.isSuccess() ? new BocloudResult<>(true, cloudServer, result.getMessage())
				: new BocloudResult<>(false, cloudServer, result.getMessage());
	}

	/**
	 * 更新状态
	 *
	 * @param server
	 * @throws Exception
	 */
	public void updateStatus(CloudServer server, String status) throws Exception {
		if (!status.equalsIgnoreCase(BocloudStatus.Server.BUILDING.name())) {
			server.setStatus(status);
			return;
		}
		Long start = System.currentTimeMillis();
		boolean running = true;
		while (running) {
			// 超时和延时
			if (System.currentTimeMillis() - start > 1000 * 60 * 10) {
				server.setStatus(BocloudStatus.Server.EXCEPTION.name());
				running = false;
			}
			BocloudResult result = serverDriver.detail(server.getInstanceId(), vendor.getUuid(), null);
			if (result.isSuccess()) {
				VMBean bean = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), VMBean.class);
				String state = bean.getStatus();
				// 虚拟机为错误状态
				if (state.equalsIgnoreCase(BocloudStatus.Server.ERROR.name())) {
					server.setStatus(BocloudStatus.Server.EXCEPTION.name());
					running = false;
					break;
				} else if (server.getStatus().equalsIgnoreCase(BocloudStatus.Server.BUILDING.name())) {
					Thread.sleep(3000L);
				} else {
					server.setStatus(state);
					server.setGmtVmCreate(bean.getGmtVmCreate());
					running = false;
				}
			} else {
				server.setStatus(BocloudStatus.Server.EXCEPTION.name());
				running = false;
			}
		}
	}

	/**
	 * 返回随机字符串，同时包含数字、大小写字母
	 *
	 * @param len 字符串长度，不能小于3
	 * @return String 随机字符串
	 */
	public static String randomStr(int len) {
		if (len < 3) {
			throw new IllegalArgumentException("字符串长度不能小于3");
		}
		// 数组，用于存放随机字符
		char[] chArr = new char[len];
		// 为了保证必须包含数字、大小写字母
		chArr[0] = (char) ('0' + PwdRandom.uniform(0, 10));
		chArr[1] = (char) ('A' + PwdRandom.uniform(0, 26));
		chArr[2] = (char) ('a' + PwdRandom.uniform(0, 26));

		char[] codes = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
				'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
				'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
				'z' };
		// charArr[3..len-1]随机生成codes中的字符
		for (int i = 3; i < len; i++) {
			chArr[i] = codes[PwdRandom.uniform(0, codes.length)];
		}

		// 将数组chArr随机排序
		for (int i = 0; i < len; i++) {
			int r = i + PwdRandom.uniform(len - i);
			char temp = chArr[i];
			chArr[i] = chArr[r];
			chArr[r] = temp;
		}

		return new String(chArr);
	}

}
