package com.bocloud.ims.service.utils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.telnet.TelnetClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.common.FlavorDriver;
import com.bocloud.cmp.driver.common.TaskMsgDriver;
import com.bocloud.cmp.driver.compute.ServerDriver;
import com.bocloud.cmp.driver.network.GwQosDriver;
import com.bocloud.cmp.driver.network.NetworkDriver;
import com.bocloud.cmp.driver.network.NetworkInterfaceDriver;
import com.bocloud.cmp.driver.network.PortDriver;
import com.bocloud.cmp.driver.network.PublicIPAddressDriver;
import com.bocloud.cmp.driver.network.SecurityGroupDriver;
import com.bocloud.cmp.driver.storage.StorageDriver;
import com.bocloud.cmp.driver.storage.VolumeDriver;
import com.bocloud.cmp.driver.storage.VolumePoolDriver;
import com.bocloud.cmp.entity.enums.AlarmLevel;
import com.bocloud.cmp.entity.enums.BocloudStatus;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.entity.enums.NetworkType;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.cmp.model.AddressBean;
import com.bocloud.cmp.model.FlavorModel;
import com.bocloud.cmp.model.IpModel;
import com.bocloud.cmp.model.NetcardOperation;
import com.bocloud.cmp.model.NetworkBean;
import com.bocloud.cmp.model.ServerModel;
import com.bocloud.cmp.model.VMBean;
import com.bocloud.cmp.model.VolumeModel;
import com.bocloud.cmp.model.h3c.entity.RsDomain;
import com.bocloud.cmp.vm.model.VmGenericParam;
import com.bocloud.common.encrypt.AESEncrptor;
import com.bocloud.common.encrypt.Encryptor;
import com.bocloud.common.enums.OSCategory;
import com.bocloud.common.enums.ResourceCatalog;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.OperateResult;
import com.bocloud.common.model.OperateResult.OperateCategory;
import com.bocloud.common.model.Param;
import com.bocloud.common.model.RequestContext;
import com.bocloud.common.model.RequestContext.Catalog;
import com.bocloud.common.model.Sign;
import com.bocloud.common.ssh.SshClient;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.IDFactory;
import com.bocloud.common.utils.ListTool;
import com.bocloud.common.utils.MapTools;
import com.bocloud.ims.common.enums.AzureIpRelationType;
import com.bocloud.ims.common.enums.AzureTaskStatus;
import com.bocloud.ims.common.enums.ServerAction;
import com.bocloud.ims.entity.resource.CloudServer;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.DataStore;
import com.bocloud.ims.entity.resource.ElasticIp;
import com.bocloud.ims.entity.resource.Flavor;
import com.bocloud.ims.entity.resource.FloatingIp;
import com.bocloud.ims.entity.resource.Image;
import com.bocloud.ims.entity.resource.Ip;
import com.bocloud.ims.entity.resource.Ip.IpStatus;
import com.bocloud.ims.entity.resource.Label;
import com.bocloud.ims.entity.resource.Network;
import com.bocloud.ims.entity.resource.NetworkCard;
import com.bocloud.ims.entity.resource.NetworkInterface;
import com.bocloud.ims.entity.resource.ObjectRelation;
import com.bocloud.ims.entity.resource.Port;
import com.bocloud.ims.entity.resource.PortFixedIp;
import com.bocloud.ims.entity.resource.PortGroup;
import com.bocloud.ims.entity.resource.Resource;
import com.bocloud.ims.entity.resource.ResourceAlarm;
import com.bocloud.ims.entity.resource.ResourceEvent;
import com.bocloud.ims.entity.resource.ResourceQuota;
import com.bocloud.ims.entity.resource.Server;
import com.bocloud.ims.entity.resource.ServerConfig;
import com.bocloud.ims.entity.resource.StoreHost;
import com.bocloud.ims.entity.resource.Subnet;
import com.bocloud.ims.entity.resource.Switcher;
import com.bocloud.ims.entity.resource.Volume;
import com.bocloud.ims.entity.resource.Zone;
import com.bocloud.ims.entity.resource.azure.monitor.MetricAlertResourceRelation;
import com.bocloud.ims.entity.resource.azure.network.NicIpConfiguration;
import com.bocloud.ims.entity.resource.azure.network.PublicIPAddress;
import com.bocloud.ims.entity.resource.azure.network.ResourcePublicIPAddressRelation;
import com.bocloud.ims.entity.resource.hmc.HmcPartition;
import com.bocloud.ims.entity.resource.hmc.HmcProfile;
import com.bocloud.ims.entity.resource.manageone.ManageOneAccount;
import com.bocloud.ims.entity.resource.nsx.NsxLogicalRouter;
import com.bocloud.ims.entity.resource.nsx.NsxRouterPort;
import com.bocloud.ims.entity.resource.nsx.NsxSwitchPort;
import com.bocloud.ims.interfaces.h3c.H3cCloudServerService;
import com.bocloud.ims.interfaces.h3c.H3cNetworkService;
import com.bocloud.ims.interfaces.manageone.ManageOneAccountService;
import com.bocloud.ims.interfaces.resource.ElasticIpService;
import com.bocloud.ims.interfaces.resource.IpService;
import com.bocloud.ims.interfaces.resource.LabelService;
import com.bocloud.ims.interfaces.resource.NameRuleService;
import com.bocloud.ims.interfaces.resource.VendorProjectService;
import com.bocloud.ims.interfaces.resource.VolumeService;
import com.bocloud.ims.interfaces.resource.azure.NetworkInterfaceService;
import com.bocloud.ims.interfaces.resource.azure.monitor.MetricAlertService;
import com.bocloud.ims.interfaces.resource.azure.network.NicIpConfigurationService;
import com.bocloud.ims.interfaces.resource.azure.network.PublicIPAddressService;
import com.bocloud.ims.interfaces.resource.hmc.HmcPartitionService;
import com.bocloud.ims.interfaces.scheduler.SnapshotTaskService;
import com.bocloud.ims.repository.common.NsxRouterPortRepository;
import com.bocloud.ims.repository.common.NsxRouterRepository;
import com.bocloud.ims.repository.common.NsxSwitchPortRepository;
import com.bocloud.ims.repository.resource.CloudServerRepository;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.ClusterRepository;
import com.bocloud.ims.repository.resource.DataStoreFileRepository;
import com.bocloud.ims.repository.resource.DataStoreRepository;
import com.bocloud.ims.repository.resource.ElasticIpRepository;
import com.bocloud.ims.repository.resource.FlavorExtraSpecsRepository;
import com.bocloud.ims.repository.resource.FlavorRepository;
import com.bocloud.ims.repository.resource.FloatingIpRepository;
import com.bocloud.ims.repository.resource.ImageRepository;
import com.bocloud.ims.repository.resource.ImageVolumeRepository;
import com.bocloud.ims.repository.resource.IpPoolRepository;
import com.bocloud.ims.repository.resource.IpRepository;
import com.bocloud.ims.repository.resource.KeypairRepository;
import com.bocloud.ims.repository.resource.LbMemberRepository;
import com.bocloud.ims.repository.resource.NetworkCardRepository;
import com.bocloud.ims.repository.resource.NetworkHostRepository;
import com.bocloud.ims.repository.resource.NetworkInterfaceRepository;
import com.bocloud.ims.repository.resource.NetworkRepository;
import com.bocloud.ims.repository.resource.ObjectRelationRepository;
import com.bocloud.ims.repository.resource.PortFixedIpRepository;
import com.bocloud.ims.repository.resource.PortGroupRepository;
import com.bocloud.ims.repository.resource.PortRepository;
import com.bocloud.ims.repository.resource.QosPolicyRepository;
import com.bocloud.ims.repository.resource.RegionRepository;
import com.bocloud.ims.repository.resource.ResourceAlarmRepository;
import com.bocloud.ims.repository.resource.ResourceEventRepository;
import com.bocloud.ims.repository.resource.ResourceGroupRepository;
import com.bocloud.ims.repository.resource.ResourceRepository;
import com.bocloud.ims.repository.resource.RouterRepository;
import com.bocloud.ims.repository.resource.SecurityGroupRepository;
import com.bocloud.ims.repository.resource.SecurityGroupRuleRepository;
import com.bocloud.ims.repository.resource.ServerConfigRepository;
import com.bocloud.ims.repository.resource.ServerKeypairRepository;
import com.bocloud.ims.repository.resource.ServerLabelRepository;
import com.bocloud.ims.repository.resource.ServerRepository;
import com.bocloud.ims.repository.resource.ServerSgroupRepository;
import com.bocloud.ims.repository.resource.ServerVolumeRepository;
import com.bocloud.ims.repository.resource.SnapshotRepository;
import com.bocloud.ims.repository.resource.StorageRepository;
import com.bocloud.ims.repository.resource.StoreHostRepository;
import com.bocloud.ims.repository.resource.SubnetRepository;
import com.bocloud.ims.repository.resource.SwitcherRepository;
import com.bocloud.ims.repository.resource.TagRepository;
import com.bocloud.ims.repository.resource.VdcRepository;
import com.bocloud.ims.repository.resource.VolumePoolRepository;
import com.bocloud.ims.repository.resource.VolumeRepository;
import com.bocloud.ims.repository.resource.VolumeTemplateRepository;
import com.bocloud.ims.repository.resource.VpcRepository;
import com.bocloud.ims.repository.resource.ZoneRepository;
import com.bocloud.ims.repository.resource.azure.AvailabilitySetRepository;
import com.bocloud.ims.repository.resource.azure.monitor.MetricAlertResourceRelationRepository;
import com.bocloud.ims.repository.resource.azure.network.NicIpConfigurationRepository;
import com.bocloud.ims.repository.resource.azure.network.PublicIPAddressRepository;
import com.bocloud.ims.repository.resource.azure.network.ResourcePublicIPAddressRelationRepository;
import com.bocloud.ims.repository.resource.hmc.HmcPartitionRepository;
import com.bocloud.ims.repository.resource.hmc.HmcProfileRepository;
import com.bocloud.ims.service.builder.AliServerBuilder;
import com.bocloud.ims.service.builder.AwsServerBuilder;
import com.bocloud.ims.service.builder.AzureServerBuilder;
import com.bocloud.ims.service.builder.FusionCloudServerBuilder;
import com.bocloud.ims.service.builder.H3cServerBuilder;
import com.bocloud.ims.service.builder.HuaweiServerBuilder;
import com.bocloud.ims.service.builder.JcloudServerBuilder;
import com.bocloud.ims.service.builder.KingCloudServerBuilder;
import com.bocloud.ims.service.builder.ManageOneServerBuilder;
import com.bocloud.ims.service.builder.OSServerBuilder;
import com.bocloud.ims.service.builder.PowervcServerBuilder;
import com.bocloud.ims.service.builder.QcloudServerBuilder;
import com.bocloud.ims.service.builder.ServerBuilder;
import com.bocloud.ims.service.builder.TceServerBuilder;
import com.bocloud.ims.service.builder.TencentServerBuilder;
import com.bocloud.ims.service.builder.TianyiServerBuilder;
import com.bocloud.ims.service.builder.VMServerBuilder;
import com.bocloud.ims.service.internal.CosInternalService;
import com.bocloud.ims.service.internal.SmsProjectService;
import com.bocloud.ims.service.internal.SmsTenantService;
import com.bocloud.ims.service.internal.worker.LvmService;
import com.bocloud.ims.service.model.ProcessResult;
import com.bocloud.ims.service.transportor.H3cTransportor;
import com.bocloud.ims.service.transportor.PowervcTransportor;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

@Component("serverOperationHelper")
public class ServerOperationHelper {

    private static final Logger logger = LoggerFactory.getLogger(ServerOperationHelper.class);
    private static final OperateCategory OPERATE_CATEGORY = OperateResult.OperateCategory.ResourceEvent;
    @Autowired
    private HmcPartitionService hmcPartitionService;
    @Autowired
    private HmcProfileRepository hmcProfileRepository;
    @Autowired
    private HmcPartitionRepository hmcPartitionRepository;
    @Autowired
    private CloudServerRepository cloudServerRepository;
    @Autowired
    private CloudVendorRepository cloudVendorRepository;
    @Autowired
    private ResourceEventRepository resourceEventRepository;
    @Autowired
    private ImageRepository imageRepository;
    @Autowired
    private DataStoreRepository dataStoreRepository;
    @Autowired
    private ServerRepository serverRepository;
    @Autowired
    private StoreHostRepository storeHostRepository;
    @Autowired
    private ServerVolumeRepository serverVolumeRepository;
    @Autowired
    private NetworkRepository networkRepository;
    @Autowired
    private PortGroupRepository portGroupRepository;
    @Autowired
    private Environment environment;
    @Autowired
    private ImageVolumeRepository imageVolumeRepository;
    @Autowired
    private FlavorExtraSpecsRepository flavorExtraSpecsRepository;
    @Autowired
    private StorageRepository storageRepository;
    @Autowired
    private ServerConfigRepository serverConfigRepository;
    @Autowired
    private VolumeTemplateRepository volumeTemplateRepository;
    @Autowired
    private VolumePoolRepository volumePoolRepository;
    @Autowired
    private ClusterRepository clusterRepository;
    @Autowired
    private PowervcTransportor powervcTransportor;
    @Autowired
    private StorageDriver storageDriver;
    @Autowired
    private VolumePoolDriver volumePoolDriver;
    @Autowired
    private SwitcherRepository switcherRepository;
    @Autowired
    private NetworkHostRepository networkHostRepository;
    @Autowired
    private NetworkCardRepository networkCardRepository;
    @Autowired
    private ResourceEventPublisher resourceEventPublisher;
    @Autowired
    private ResourceRepository resourceRepository;
    @Autowired
    private TagRepository tagRepository;
    @Autowired
    private IpService ipService;
    @Autowired
    private IpRepository ipRepository;
    @Autowired
    private IpPoolRepository ipPoolRepository;
    @Autowired
    private VolumeRepository volumeRepository;
    @Autowired
    private FloatingIpRepository floatingIpRepository;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private ResourceAlarmRepository alarmRepository;
    @Autowired
    private ObjectRelationRepository objectRelationRepository;
    @Autowired
    private SnapshotRepository snapshotRepository;
    @Autowired
    private ServerLabelRepository serverLabelRepository;
    @Autowired
    private NsxRouterRepository nsxRouterRepository;
    @Autowired
    private NsxRouterPortRepository routerPortRepository;
    @Autowired
    private NsxSwitchPortRepository switchPortRepository;
    @Autowired
    private LbMemberRepository lbMemberRepository;
    @Autowired
    private LockFactory lockFactory;
    @Autowired
    private ServerDriver serverDriver;
    @Autowired
    private NameRuleService nameRuleService;
    @Autowired
    private SmsTenantService smsTenantService;
    @Autowired
    private CosInternalService cosInternalService;
    @Autowired
    private SubnetRepository subnetRepository;
    @Autowired
    private FlavorRepository flavorRepository;
    @Autowired
    private PortRepository portRepository;
    @Autowired
    private PortFixedIpRepository portFixedIpRepository;
    @Autowired
    private SecurityGroupRepository securityGroupRepository;
    @Autowired
    private ServerSgroupRepository serverSgroupRepository;
    @Autowired
    private KeypairRepository keypairRepository;
    @Autowired
    private RegionRepository regionRepository;
    @Autowired
    private GwQosDriver gwQosDriver;
    @Autowired
    private VendorProjectService vendorProjectService;
    @Autowired
    private QosPolicyRepository qosPolicyRepository;
    @Autowired
    private H3cNetworkService h3cNetworkService;
    @Autowired
    private TaskMsgDriver taskMsgDriver;
    @Autowired
    private NetworkDriver networkDriver;
    @Autowired
    private DataStoreFileRepository dataStoreFileRepository;
    @Autowired
    private VdcRepository vdcRepository;
    @Autowired
    private ZoneRepository zoneRepository;
    @Autowired
    private FlavorDriver flavorDriver;
    @Autowired
    private PortDriver portDriver;
    @Autowired
    private H3cCloudServerService h3cCloudServerService;
    @Autowired
    private VolumeDriver volumeDriver;
    @Autowired
    private VpcRepository vpcRepository;
    @Autowired
    private ServerKeypairRepository serverKeypairRepository;
    @Autowired
    private NetworkInterfaceRepository networkInterfaceRepository;
    @Autowired
    private NetworkInterfaceDriver interfaceDriver;
    @Autowired
    private RouterRepository routerRepository;
    @Autowired
    private ManageOneAccountService accountService;
    @Autowired
    private SmsProjectService smsProjectService;
    @Autowired
    private LvmService lvmService;
    @Autowired
    private SecurityGroupDriver securityGroupDriver;
    @Autowired
    private SecurityGroupRuleRepository securityGroupRuleRepository;
    @Autowired
    private LabelService labelService;
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    private ResourceGroupRepository resourceGroupRepository;
    @Autowired
    private AvailabilitySetRepository availabilitySetRepository;
    @Autowired
    private H3cTransportor h3cTransportor;
    @Autowired
    private ElasticIpRepository elasticIpRepository;
    @Autowired
    private ElasticIpService elasticIpService;
    @Autowired
    private PublicIPAddressRepository publicIPAddressRepository;
    @Autowired
    private ResourcePublicIPAddressRelationRepository resourcePublicIPAddressRelationRepository;
    @Autowired
    private PublicIPAddressDriver publicIPAddressDriver;
    @Autowired
    private NicIpConfigurationRepository nicIpConfigurationRepository;
    @Autowired
    private VolumeService volumeService;
    @Autowired
    private NicIpConfigurationService nicIpConfigurationService;
    @Autowired
    private PublicIPAddressService publicIPAddressService;
    @Autowired
    private NetworkInterfaceService networkInterfaceService;
    @Autowired
    private MetricAlertResourceRelationRepository metricAlertResourceRelationRepository;
    @Autowired
    private MetricAlertService metricAlertService;
    @Autowired
    private SnapshotTaskService snapshotTaskService;

    /**
     * 获取虚拟机builder器
     *
     * @param type
     * @param vendor
     * @param context
     * @return
     */
    public BocloudResult<ServerBuilder> getProcess(CloudProvider type, CloudVendor vendor, RequestContext context) {
        ServerBuilder process = null;
        switch (type) {
            case OPENSTACK:
                process = new OSServerBuilder(cloudServerRepository, serverRepository, networkRepository,
                    subnetRepository, imageRepository, volumeRepository, flavorRepository, portRepository,
                    portFixedIpRepository, ipRepository, ipPoolRepository, resourceRepository, resourceEventRepository,
                    securityGroupRepository, serverSgroupRepository, keypairRepository, snapshotRepository,
                    serverLabelRepository, regionRepository, serverDriver, context, vendor, gwQosDriver,
                    vendorProjectService, qosPolicyRepository);
                break;
            case FUSIONCLOUD:
                process = new FusionCloudServerBuilder(cloudServerRepository, networkRepository, subnetRepository,
                    imageRepository, flavorRepository, volumeRepository, portRepository, portFixedIpRepository,
                    ipRepository, ipPoolRepository, resourceRepository, resourceEventRepository,
                    securityGroupRepository, serverSgroupRepository, keypairRepository, serverLabelRepository,
                    regionRepository, serverDriver, volumeDriver, context, vendor);
                break;
            case VMWARE:
                process =
                    new VMServerBuilder(cloudServerRepository, serverRepository, dataStoreRepository, networkRepository,
                        networkCardRepository, portGroupRepository, switcherRepository, storeHostRepository,
                        networkHostRepository, ipRepository, resourceRepository, resourceEventRepository,
                        volumeRepository, serverLabelRepository, serverDriver, context, vendor, resourceEventPublisher,
                        ipPoolRepository, smsTenantService, lockFactory, smsProjectService, lvmService, amqpTemplate);
                break;
            case H3C:
                process = new H3cServerBuilder(cloudServerRepository, resourceRepository, resourceEventRepository,
                    serverDriver, context, vendor, serverRepository, vdcRepository, switcherRepository,
                    dataStoreRepository, dataStoreFileRepository, volumeRepository, h3cNetworkService, ipRepository,
                    taskMsgDriver, networkDriver, serverRepository, clusterRepository, h3cTransportor,
                    serverLabelRepository);
                break;
            case MANAGEONE:
                process = new ManageOneServerBuilder(cloudServerRepository, networkRepository, subnetRepository,
                    imageRepository, flavorRepository, volumeRepository, portRepository, portFixedIpRepository,
                    ipRepository, ipPoolRepository, resourceRepository, resourceEventRepository,
                    securityGroupRepository, serverSgroupRepository, keypairRepository, serverLabelRepository,
                    regionRepository, serverDriver, volumeDriver, context, vendor, routerRepository, accountService,
                    serverRepository);
                break;
            case POWERVC:
                process = new PowervcServerBuilder(taskExecutor, environment, imageRepository, imageVolumeRepository,
                    flavorRepository, networkRepository, subnetRepository, serverRepository, serverConfigRepository,
                    cloudServerRepository, storageRepository, volumeRepository, flavorExtraSpecsRepository,
                    volumeTemplateRepository, volumePoolRepository, clusterRepository, portRepository,
                    portFixedIpRepository, ipPoolRepository, ipRepository, powervcTransportor, serverDriver,
                    storageDriver, volumeDriver, volumePoolDriver, portDriver, context, vendor);

                break;
            case AZURE:
                process = new AzureServerBuilder(cloudServerRepository, flavorRepository, imageRepository,
                    volumeRepository, securityGroupRepository, vpcRepository, subnetRepository, keypairRepository,
                    serverKeypairRepository, serverSgroupRepository, serverLabelRepository, resourceRepository,
                    resourceEventRepository, serverDriver, networkInterfaceRepository, interfaceDriver,
                    securityGroupDriver, securityGroupRuleRepository, availabilitySetRepository, volumeDriver, vendor,
                    context, publicIPAddressRepository, resourcePublicIPAddressRelationRepository,
                    resourceGroupRepository, publicIPAddressDriver, nicIpConfigurationRepository);
                break;
            case AWS:
                process = new AwsServerBuilder(cloudServerRepository, flavorRepository, imageRepository,
                    volumeRepository, securityGroupRepository, vpcRepository, subnetRepository, keypairRepository,
                    networkInterfaceRepository, serverKeypairRepository, serverSgroupRepository, serverLabelRepository,
                    resourceRepository, resourceEventRepository, interfaceDriver, serverDriver, volumeDriver,
                    tagRepository, vendor, context);
                break;
            case TENCENT:
                process = new TencentServerBuilder(cloudServerRepository, resourceRepository, resourceEventRepository,
                    imageRepository, volumeRepository, serverDriver, context, vendor, vpcRepository, flavorRepository,
                    subnetRepository, keypairRepository, securityGroupRepository, serverSgroupRepository,
                    serverKeypairRepository, networkCardRepository);
                break;
            case HUAWEI:
                process = new HuaweiServerBuilder(cloudServerRepository, networkRepository, subnetRepository,
                    imageRepository, flavorRepository, volumeRepository, portRepository, portFixedIpRepository,
                    ipRepository, ipPoolRepository, resourceRepository, resourceEventRepository,
                    securityGroupRepository, serverSgroupRepository, keypairRepository, serverLabelRepository,
                    regionRepository, serverDriver, volumeDriver, context, vendor, zoneRepository, vpcRepository,
                    elasticIpRepository);
                break;
            case ALIYUN:
                process = new AliServerBuilder(cloudServerRepository, resourceRepository, resourceEventRepository,
                    imageRepository, volumeRepository, serverDriver, context, vendor, keypairRepository,
                    securityGroupRepository, serverSgroupRepository, serverKeypairRepository, flavorRepository,
                    subnetRepository, tagRepository, networkInterfaceRepository, interfaceDriver,
                    resourceEventPublisher, elasticIpService, elasticIpRepository, serverLabelRepository);
                break;
            case JDCLOUD:
                process = new JcloudServerBuilder(cloudServerRepository, resourceRepository, resourceEventRepository,
                    imageRepository, flavorRepository, serverDriver, context, vendor, securityGroupRepository,
                    serverSgroupRepository, volumeRepository);
                break;
            case KINGCLOUD:
                process = new KingCloudServerBuilder(cloudServerRepository, resourceRepository, resourceEventRepository,
                    imageRepository, volumeRepository, serverDriver, context, vendor, keypairRepository,
                    securityGroupRepository, serverSgroupRepository, serverKeypairRepository);
                break;
            case QCLOUD:
                process =
                    new QcloudServerBuilder(cloudServerRepository, networkRepository, subnetRepository, imageRepository,
                        flavorRepository, volumeRepository, portRepository, portFixedIpRepository, ipRepository,
                        ipPoolRepository, resourceRepository, resourceEventRepository, securityGroupRepository,
                        serverSgroupRepository, keypairRepository, serverLabelRepository, regionRepository,
                        serverDriver, volumeDriver, context, vendor, zoneRepository, serverKeypairRepository);
                break;
            case TCE:
                process = new TceServerBuilder(cloudServerRepository, resourceRepository, resourceEventRepository,
                    imageRepository, volumeRepository, serverDriver, context, vendor, vpcRepository, flavorRepository,
                    subnetRepository, keypairRepository, securityGroupRepository, serverSgroupRepository,
                    serverKeypairRepository, serverLabelRepository);
                break;
            case TIANYI:
                process = new TianyiServerBuilder(cloudServerRepository, resourceRepository, resourceEventRepository,
                    imageRepository, volumeRepository, serverDriver, context, vendor, keypairRepository,
                    securityGroupRepository, serverSgroupRepository, serverKeypairRepository, flavorRepository,
                    subnetRepository, floatingIpRepository, resourceGroupRepository, networkCardRepository,
                    serverLabelRepository);
                break;
            default:
                return new BocloudResult<>(false, "暂不支持该平台类型");
        }
        return new BocloudResult<>(true, process, "");
    }

    /**
     * 分配宿主机和存储
     *
     * @param pmLabelIds
     * @param vendorId
     * @param diskCategory
     * @param params
     * @return
     * @throws Exception
     */
    private BocloudResult<ProcessResult> assignHostAndDatastore(List<Long> pmLabelIds, Long vendorId,
        String diskCategory, VmGenericParam params) throws Exception {
        // 通过标签随机分配宿主机
        // List<Long> pmLabels = new ArrayList<>();
        // if (!StringUtils.isEmpty(pmLabelIds)) {
        // pmLabels = JSONArray.parseArray(pmLabelIds, Long.class);
        // }
        // List<Server> servers = serverRepository.listByLabelIds(pmLabels,
        // vendorId);
        // if (ListTool.isEmpty(servers)) {
        // return new BocloudResult<>(false, "未找到合适的宿主机!");
        // }
        List<Server> filterHosts = new ArrayList<>();
        List<Server> servers = serverRepository.listByLabelIds(null, vendorId);
        for (Server host : servers) {
            if (!StringUtils.isEmpty(host.getResourceLabel()) && host.getResourceLabel().contains("Available")) {
                filterHosts.add(host);
            }
        }
        if (ListTool.isEmpty(filterHosts)) {
            return new BocloudResult<>(false, "未找到合适的宿主机!");
        }
        Server server = filterHosts.get(new Random().nextInt(filterHosts.size()));
        Long hostId = server.getId();
        // 分配存储
        List<StoreHost> storeHosts = storeHostRepository.list(hostId, "PM");
        if (ListTool.isEmpty(storeHosts)) {
            return new BocloudResult<>(false, "未找到合适的存储器!");
        }
        Long storeId = null;
        // 如果设置了磁盘类型，则需要过滤
        // if (!StringUtils.isEmpty(diskCategory)) {
        // logger.info("需要为系统盘过滤类型为【" + diskCategory + "】的数据存储");
        // for (StoreHost storeHost : storeHosts) {
        // DataStore store = dataStoreRepository.query(storeHost.getStoreId());
        // if (null != store) {
        // String resourceLabel = store.getResourceLabel();
        // if (!StringUtils.isEmpty(resourceLabel) && resourceLabel.contains(diskCategory)) {
        // storeId = store.getId();
        // break;
        // }
        // }
        // }
        // if (null == storeId) {
        // return new BocloudResult<>(false, "根据磁盘类型未找到合适的数据存储!");
        // }
        // } else {
        // storeId = storeHosts.get(new Random().nextInt(storeHosts.size())).getStoreId();
        // }
        storeId = storeHosts.get(new Random().nextInt(storeHosts.size())).getStoreId();
        params.setStoreId(storeId);
        params.setHostId(hostId);
        // 虚拟机数据盘
        String dataDisks = params.getDataDisks();
        if (!StringUtils.isEmpty(dataDisks)) {
            List<JSONObject> dataDiskList = JSONArray.parseArray(dataDisks, JSONObject.class);
            List<Integer> disks = new ArrayList<>();
            List<String> dataStoreNames = new ArrayList<>();
            for (JSONObject dataDisk : dataDiskList) {
                String category = dataDisk.getString("category");
                Integer disk = dataDisk.getInteger("disk");
                String dataDiskStore = null;
                Long randomStoreId = storeHosts.get(new Random().nextInt(storeHosts.size())).getStoreId();
                DataStore store = dataStoreRepository.query(randomStoreId);
                if (null != store) {
                    dataDiskStore = store.getName();
                }
                // logger.info("需要为数据盘过滤类型为【" + category + "】的数据存储");
                // for (StoreHost storeHost : storeHosts) {
                // DataStore store = dataStoreRepository.query(storeHost.getStoreId());
                // if (null != store) {
                // String resourceLabel = store.getResourceLabel();
                // if (!StringUtils.isEmpty(resourceLabel) && resourceLabel.contains(category)) {
                // dataDiskStore = store.getName();
                // break;
                // }
                // }
                // }
                if (StringUtils.isEmpty(dataDiskStore)) {
                    return new BocloudResult<>(false, "根据数据盘磁盘类型未找到合适的数据存储!");
                }
                disks.add(disk);
                dataStoreNames.add(dataDiskStore);
            }
            params.setDisks(disks);
            params.setDataStoreNames(dataStoreNames);
        }
        return new BocloudResult<>(true, "success");
    }

    /**
     * 创建规格
     *
     * @param cpu
     * @param memory
     * @param disk
     * @param context
     * @param vendor
     * @return
     * @throws Exception
     */
    public Flavor createFlavor(Integer cpu, BigDecimal memory, Integer disk, RequestContext context, CloudVendor vendor)
        throws Exception {
        FlavorModel flavorModel =
            new FlavorModel("flavor" + Calendar.getInstance().getTime().getTime(), cpu, memory, disk);
        BocloudResult bocloudResult = null;
        if (CloudProvider.MANAGEONE.name().equals(vendor.getType()) && null != context.getTenant()
            && 0L != context.getTenant()) {
            ManageOneAccount account = accountService.queryAccount(vendor.getId(), context.getTenant());
            Assert.notNull(account, "认证失败！");
            bocloudResult = flavorDriver.create(vendor.getUuid(), flavorModel, account.getUsername(),
                account.getPassword(), account.getProjectId(), account.getDomainName());
        } else {
            bocloudResult = flavorDriver.create(vendor.getUuid(), flavorModel);
        }
        if (bocloudResult.isFailed()) {
            logger.error("no have flavor to adaptation, Apply virtual machine failed");
            return null;
        }
        Flavor flavor = parseObject(bocloudResult.getData(), Flavor.class);
        flavor.setVendorId(vendor.getId());
        flavorRepository.save(flavor);
        return flavor;
    }

    /**
     * 匹配虚拟机实例规格ID
     *
     * @param vendorId
     * @param provider
     * @param object
     * @return
     * @throws Exception
     */
    public Flavor getFlavorId(Long vendorId, CloudProvider provider, VmGenericParam object) throws Exception {
        // 获取规格
        Flavor flavor = null;
        // cpu大小
        Long cpu = Long.valueOf(object.getCpu());
        // 内存大小
        Long memory = object.getMemory().longValue();
        // 磁盘大小
        Long disk = Long.valueOf(object.getDisk() == null ? 0 : object.getDisk());
        List<Param> params = Lists.newArrayList();
        switch (provider) {
            case TENCENT:
            case TCE:
                params.add(new Param(MapTools.simpleMap(Common.REGIONID, object.getRegionId()), Sign.EQ));
                params.add(new Param(MapTools.simpleMap("zone", object.getZoneId()), Sign.EQ));
                // 售卖中
                params.add(new Param(MapTools.simpleMap("status", "SELL"), Sign.EQ));
                // 按量计费
                params.add(new Param(MapTools.simpleMap("instanceChargeType", "POSTPAID_BY_HOUR"), Sign.EQ));
                break;
            case OPENSTACK:
                params.add(new Param(MapTools.simpleMap("disk", disk), Sign.EQ));
                break;
            case FUSIONCLOUD:
            case MANAGEONE:
                break;
            case ALIYUN:
            case QCLOUD:
            case PQCLOUD:
                params.add(new Param(MapTools.simpleMap(Common.REGIONID, object.getRegionId()), Sign.EQ));
                params.add(new Param(MapTools.simpleMap("zone", object.getZoneId()), Sign.EQ));
                break;
            case JDCLOUD:
            case AZURE:
            case AWS:
                params.add(new Param(MapTools.simpleMap(Common.REGIONID, object.getRegionId()), Sign.EQ));
                break;
            default:
                break;
        }
        // 匹配
        params.add(new Param(MapTools.simpleMap("cpu", cpu), Sign.EQ));
        params.add(new Param(MapTools.simpleMap("memory", memory), Sign.EQ));
        params.add(new Param(MapTools.simpleMap(Common.VENDORID, vendorId), Sign.EQ));
        // 排序
        Map<String, String> sorter = new HashMap<>(8);
        sorter.put("cpu", "0");
        List<Flavor> flavors = flavorRepository.list(params, sorter);
        if (null != flavors && flavors.size() > 0) {
            // aliyun
            switch (provider) {
                case ALIYUN:
                    List<String> instanceTypesList = new ArrayList<>();
                    String aliyunZoneId = object.getZoneId();
                    List<Zone> zoneList = zoneRepository.listByZoneId(aliyunZoneId, vendorId);
                    if (null != zoneList && zoneList.size() > 0) {
                        Zone zone = zoneList.get(0);
                        JSONObject zoneResourceInfo = JSONObject.parseObject(zone.getResources(), JSONObject.class);
                        List<JSONObject> resourcesList =
                            JSON.parseArray(zoneResourceInfo.getString("resourcesInfo"), JSONObject.class);
                        if (null != resourcesList && resourcesList.size() > 0) {
                            JSONObject jsonObject = resourcesList.get(0);
                            // 规格名称过滤
                            JSONObject instanceTypesObject = jsonObject.getJSONObject("instanceTypes");
                            String instanceTypes = instanceTypesObject.getString("supportedInstanceType");
                            instanceTypesList = JSON.parseArray(instanceTypes, String.class);
                        }
                    }
                    for (Flavor cloudFlavor : flavors) {
                        if (instanceTypesList.contains(cloudFlavor.getFlavorUuid())) {
                            flavor = cloudFlavor;
                            break;
                        }
                    }
                    break;
                case HUAWEI:
                case JDCLOUD:
                    String hwZoneId = object.getZoneId();
                    for (Flavor cloudFlavor : flavors) {
                        List<String> zoneArray = JSONObject.parseArray(cloudFlavor.getZone(), String.class);
                        if (zoneArray.contains(hwZoneId)) {
                            flavor = cloudFlavor;
                            break;
                        }
                    }
                    break;
                default:
                    flavor = flavors.get(0);
                    break;
            }
        }
        return flavor;
    }

    public <T> T parseObject(Object object, Class<T> clazz) {
        return JSONObject.parseObject(JSONObject.toJSONString(object), clazz);
    }

    /**
     * vcenter数据预处理
     *
     * @param object
     * @param context
     * @param vendor
     * @param process
     * @param ipMap
     *            网卡id和ip对应关系
     * @param nsxNetworkName
     * @return
     */
    public BocloudResult<ProcessResult> prepareVcenter(JSONObject object, RequestContext context, CloudVendor vendor,
        ServerBuilder process, Map<Long, Ip> ipMap, Map<Long, Long> portGroupConfig, String nsxNetworkName) {
        // 虚拟机名
        String name = object.getString("name");
        object.put("vendorId", vendor.getId());
        // 操作系统类型(Linux/Windows)
        String osCategory = object.getString("osCategory");
        // 操作系统版本
        String osVersion = object.getString("osVersion");
        // 服务类型id
        Long categoryId = object.getLong("categoryId");
        // ip池id
        Long poolId = object.getLong("ipPoolId");
        // 模板id
        Long templateId = object.getLong("templateId");
        // 模板名称
        String templateName = object.getString("templateName");
        // 业务ID
        Long businessId = object.getLong("businessId");
        // 资源池ID
        Long poolGroupId = object.getLong("poolGroupId");
        // 项目ID
        Long projectId = object.getLong("projectId");
        // 申请人ID
        Long creatorId = object.getLong("creatorId");
        // 所属人ID
        Long ownerId = object.getLong("ownerId");
        // 维护人ID
        Long menderId = object.getLong("menderId");
        // 软件类型
        String software = object.getString("software");
        Boolean isAddShterm = object.getBoolean("isAddShterm");
        try {
            Long hostId = object.getLong("hostId");
            if (null == templateId || 0L == templateId) {
                List<Image> images = imageRepository.listByVendorId(vendor.getId());
                Image targetImage = images.stream()
                    .filter(image -> !StringUtils.isEmpty(image.getImageLabel())
                        && image.getImageLabel().contains(osCategory) && image.getImageLabel().contains(osVersion))
                    .findFirst().orElseThrow(() -> new Exception("未找到合适的镜像"));
                templateId = targetImage.getTemplateId();
            }
            CloudServer template = cloudServerRepository.query(templateId);
            Assert.notNull(template, "未找到合适的虚拟机模板");
            templateId = template.getId();
            object.put("templateId", templateId);
            List<NetworkCard> cards = networkCardRepository.listByHost(templateId, "VM");
            Assert.notEmpty(cards, "虚拟机模板【" + template.getName() + "】上未找到网卡信息，申请虚拟机失败");
            // 模板上的网卡
            List<NetcardOperation> operations = new ArrayList<>();
            for (NetworkCard card : cards) {
                NetcardOperation operation = new NetcardOperation();
                operation.setOperation("EDIT");
                operation.setLabel(card.getLabel());
                Long portGroupId = portGroupConfig.get(card.getId());
                PortGroup portGroup = null;
                if (null != portGroupId && 0L != portGroupId) {
                    portGroup = portGroupRepository.query(portGroupId);
                    Assert.notNull(portGroup, "所选的IP池绑定的端口组不存在");
                }
                if (!StringUtils.isEmpty(nsxNetworkName)) {
                    operation.setName(nsxNetworkName);
                    operation.setPortType("VIRTUAL");
                } else if (null != portGroup) {
                    operation.setName(portGroup.getName());
                    operation.setPortType(portGroup.getType());
                } else {
                    operation.setName(card.getName());
                    operation.setPortType(card.getPortType());
                }
                operation.setMac(card.getMac());
                // 处理新虚拟机网卡，查找对应网卡的IP 分配IP
                Ip ip = ipMap.get(card.getId());
                operation.setIp(JSONObject.parseObject(JSONObject.toJSONString(ip), IpModel.class));
                operations.add(operation);
            }
            logger.info("Start to assign ip to new vm：" + name);
            // BocloudResult bocloudResult = assignVcenterIp(vendor, poolId, operations,
            // address, assignIp);
            // if (bocloudResult.isFailed()) {
            // 回收IP
            // recycleIp(ips, null, vendor.getId());
            // return new BocloudResult<>(false, bocloudResult.getMessage());
            // }
            List<Ip> ips = new ArrayList<>(ipMap.values());
            logger.info(JSONObject.toJSONString(operations));
            logger.info("End to assign ip to new vm：" + name);
            object.put("operations", JSONObject.toJSON(operations));
            BocloudResult<ServerModel> modelResult = process.prepare(object);
            if (modelResult.isFailed()) {
                // 回收IP
                recycleIp(ips, null, vendor.getId());
                return new BocloudResult<>(false, modelResult.getMessage());
            }
            if (!ListTool.isEmpty(ips)) {
                modelResult.getData().setIps(JSONArray.parseArray(JSONObject.toJSONString(ips), IpModel.class));
            }
            ServerModel model = modelResult.getData();
            // 设置地域可用于域名
            CloudServer cloudServer = JSONObject.parseObject(JSONObject.toJSONString(object), CloudServer.class);
            cloudServer.setCpu(model.getCpu());
            cloudServer.setMemory(model.getMemory() == null ? new BigDecimal(0) : model.getMemory());
            cloudServer.setDisk(model.getDisk() == null ? 0 : model.getDisk());
            cloudServer.setPswd(model.getPassword());
            cloudServer.setAccount(model.getAccount());
            cloudServer.setZone(model.getZone());
            cloudServer.setStatus(BocloudStatus.Server.BUILDING.name());
            cloudServer.setIsTemplate(false);
            cloudServer.setResourceId(IDFactory.instance().uuid());
            cloudServer.setVendorType(vendor.getType());
            cloudServer.setRecycle(false);
            cloudServer.setImageUuid(model.getImageUuid());
            cloudServer.setVendorId(vendor.getId());
            cloudServer.setHostId(hostId);
            cloudServer.setVdcId(model.getVdcId());
            cloudServer.setTemplateId(templateId);
            cloudServer.setCreatorId(creatorId);
            cloudServer.setOwnerId(ownerId);
            cloudServer.setMenderId(menderId);
            cloudServer.setCatalog(context.getCatalog());
            cloudServer.setTenantId(context.getTenant());
            cloudServer.setBusinessId(businessId);
            cloudServer.setProjectId(projectId);
            cloudServer.setIsAddShterm(isAddShterm);
            cloudServer.setPoolGroupId(poolGroupId);
            cloudServer.setCategoryId(categoryId);
            cloudServer.setSoftware(software);
            cloudServerRepository.save(cloudServer);
            ProcessResult processResult = new ProcessResult(model, process, cloudServer);
            return new BocloudResult<>(true, processResult, "success");
        } catch (Exception e) {
            logger.error("Get error message:{}", e.getMessage());
            return new BocloudResult<>(false, e.getMessage());
        }
    }

    public BocloudResult<ProcessResult> prepare(VmGenericParam params, RequestContext context, CloudVendor vendor,
        ServerBuilder process) {
        // cpu大小
        Long cpu = Long.valueOf(params.getCpu() == null ? 0 : params.getCpu());
        // // 内存大小
        BigDecimal memory = params.getMemory();
        // // 磁盘大小
        Long disk = Long.valueOf(params.getDisk() == null ? 0 : params.getDisk());
        // 主机ID
        Long hostId = params.getHostId();
        // 模板ID
        Long templateId = params.getTemplateId();
        // 模板名称
        String templateName = params.getTemplateName();
        // 虚拟机名
        String name = params.getName();
        // 云平台id
        Long vendorId = params.getVendorId();
        // 项目id
        Long projectId = params.getProjectId() == null ? 0 : params.getProjectId();
        // 单位id
        Long tenantId = params.getTenantId() == null ? 0 : params.getTenantId();
        // 业务id
        Long businessId = params.getBusinessId() == null ? 0 : params.getBusinessId();
        Long creatorId = params.getCreatorId() == null ? 0 : params.getCreatorId();
        Long ownerId = params.getOwnerId() == null ? 0 : params.getOwnerId();
        Long menderId = params.getMenderId() == null ? 0 : params.getMenderId();
        Date expiredTime = params.getExpiredTime();
        if (null == vendorId) {
            vendorId = vendor.getId();
            params.setVendorId(vendorId);
        }
        // 子网id(逻辑交换机id)
        Long subnetId = params.getSubnetId();
        // 磁盘类型
        String diskCategory = params.getDiskCategory();
        // 操作系统类型(Linux/Windows)
        String osCategory = params.getOsCategory();
        // 操作系统版本
        String osVersion = params.getOsVersion();
        JSONObject inputObject = null;
        try {
            // Powervc允许重名
            if (cloudServerRepository.exists(name, vendor.getId())
                && !CloudProvider.POWERVC.name().equals(vendor.getType())) {
                return new BocloudResult<>(false, "此名称已存在!");
            }
            Server server = null;
            if (null != hostId) {
                server = serverRepository.query(hostId);
                if (null == server) {
                    return new BocloudResult<>(false, "宿主机不存在!");
                }
            } else if (CloudProvider.VMWARE.name().equals(vendor.getType())) {
                BocloudResult<ProcessResult> result =
                    this.assignHostAndDatastore(params.getLabels(), vendorId, diskCategory, params);
                if (result.isFailed()) {
                    return result;
                }
                server = serverRepository.query(params.getHostId());
                if (null == server) {
                    return new BocloudResult<>(false, "宿主机不存在!");
                }
            }
            if (!StringUtils.isEmpty(templateName)) {
                CloudServer template = cloudServerRepository.getByName(templateName, server.getVendorId());
                if (null == template) {
                    return new BocloudResult<>(false, "未找到合适的模板!");
                }
                templateId = template.getId();
                params.setTemplateId(templateId);
            } else if (!StringUtils.isEmpty(osCategory) && !StringUtils.isEmpty(osVersion)) {
                List<Image> images = imageRepository.listByVendorId(vendor.getId());
                Image targetImage = null;
                if (CloudProvider.MANAGEONE.name().equals(vendor.getType())) {
                    Long imageId = params.getImageId();
                    if (null != imageId) {
                        targetImage = imageRepository.query(imageId);
                    } else {
                        targetImage = images.stream().filter(image -> !StringUtils.isEmpty(image.getImageLabel())
                            && image.getImageLabel().contains(osCategory) && image.getImageLabel().contains(osVersion)
                            && "public".equalsIgnoreCase(image.getImageType())).findFirst()
                            .orElseThrow(() -> new Exception("未找到合适的镜像"));
                    }
                    if (null == targetImage) {
                        return new BocloudResult<>(false, "未找到合适的镜像!");
                    }
                } else {
                    targetImage = images.stream()
                        .filter(image -> !StringUtils.isEmpty(image.getImageLabel())
                            && image.getImageLabel().contains(osCategory) && image.getImageLabel().contains(osVersion))
                        .findFirst().orElseThrow(() -> new Exception("未找到合适的镜像"));
                }
                if (null != targetImage.getTemplateId() && 0L != targetImage.getTemplateId()) {
                    CloudServer template = cloudServerRepository.query(targetImage.getTemplateId());
                    if (null == template) {
                        return new BocloudResult<>(false, "未找到合适的模板!");
                    }
                    templateId = template.getId();
                    params.setTemplateId(templateId);
                } else {
                    params.setImageId(targetImage.getId());
                }
            }
            CloudProvider type = CloudProvider.valueOf(vendor.getType());
            BocloudResult<ServerModel> modelResult = new BocloudResult<>();
            switch (type) {
                case FUSIONCLOUD:
                case MANAGEONE:
                case OPENSTACK:
                    Long flavorId = params.getFlavorId();
                    if (null == flavorId) {
                        Flavor flavor = getFlavorId(vendorId, type, params);
                        if (null == flavor) {
                            flavor = this.createFlavor(cpu.intValue(), memory, disk.intValue(), context, vendor);
                            if (null == flavor) {
                                return new BocloudResult<>(false, "该平台没有适配的规格");
                            }
                        }
                        flavorId = flavor.getId();
                        params.setFlavorId(flavorId);
                        if (CloudProvider.OPENSTACK == type) {
                            // 是否从卷启动
                            Boolean bootFromVolume = params.getBootFromVolume();
                            if (null == bootFromVolume) {
                                params.setBootFromVolume(true);
                            }
                            // 是否创建卷
                            if (params.getBootFromVolume()) {
                                params.setRootSize(disk.intValue());
                            }
                        } else {
                            params.setBootFromVolume(true);
                            params.setRootSize(disk.intValue());
                        }
                    }
                    inputObject = JSONObject.parseObject(JSONObject.toJSONString(params));
                    modelResult = process.prepare(inputObject);
                    if (modelResult.isFailed()) {
                        List<NetworkBean> networkBeans = modelResult.getData().getNetworkBeans();
                        // 回收IP
                        logger.info("Start to recovery failed IP address");
                        recycleIp(null, networkBeans, vendor.getId());
                        logger.info("End to recovery failed IP address");
                        return new BocloudResult<>(false, modelResult.getMessage());
                    }
                    break;
                case VMWARE:
                    // 路由器id
                    Long vpcId = params.getVpcId();
                    // 要新增，删除或编辑的网卡
                    List<NetcardOperation> operations = params.getOperations();
                    if (ListTool.isEmpty(operations)) {
                        operations = new ArrayList<>();
                        List<NetworkCard> cards = networkCardRepository.listByHost(templateId, "VM");
                        if (ListTool.isEmpty(cards)) {
                            return new BocloudResult<>(false, "选择的虚拟机模板上无网卡，申请虚拟机失败");
                        }
                        for (NetworkCard card : cards) {
                            NetcardOperation operation = new NetcardOperation();
                            operation.setName(card.getName());
                            operation.setOperation("EDIT");
                            operation.setLabel(card.getLabel());
                            operation.setPortType(card.getPortType());
                            operation.setMac(card.getMac());
                            operation.setVpcId(vpcId);
                            operation.setSubnetId(subnetId);
                            operations.add(operation);
                        }
                    }
                    List<Ip> ips = new ArrayList<>();
                    // 软件安装需要两块网卡，一块连接管理网，一块连接业务网
                    if (!StringUtils.isEmpty(templateName) || !StringUtils.isEmpty(osCategory)) {
                        logger.info("Start to assign ip to new vm：" + name);
                        // 处理新虚拟机网卡，分配IP
                        BocloudResult bocloudResult = assignNsxIp(vendor, operations, vpcId, subnetId);
                        ips = JSONArray.parseArray(JSONObject.toJSONString(bocloudResult.getData()), Ip.class);
                        if (bocloudResult.isFailed()) {
                            // 回收IP
                            recycleIp(ips, null, vendor.getId());
                            return new BocloudResult<>(false, bocloudResult.getMessage());
                        }
                        logger.info(JSONObject.toJSONString(operations));
                        logger.info("End to assign ip to new vm：" + name);
                    } else {
                        logger.info("Start to assign ip to new vm：" + name);
                        // 处理新虚拟机网卡，分配IP
                        BocloudResult bocloudResult = assignIp(vendor, operations);
                        ips = JSONArray.parseArray(JSONObject.toJSONString(bocloudResult.getData()), Ip.class);
                        if (bocloudResult.isFailed()) {
                            // 回收IP
                            recycleIp(ips, null, vendor.getId());
                            return new BocloudResult<>(false, bocloudResult.getMessage());
                        }
                        logger.info(JSONObject.toJSONString(operations));
                        logger.info("End to assign ip to new vm：" + name);
                    }
                    params.setOperations(operations);
                    inputObject = JSONObject.parseObject(JSONObject.toJSONString(params));
                    modelResult = process.prepare(inputObject);
                    if (modelResult.isFailed()) {
                        // saveAlarm(name);
                        return new BocloudResult<>(false, modelResult.getMessage());
                    }
                    if (!ListTool.isEmpty(ips)) {
                        modelResult.getData().setIps(JSONArray.parseArray(JSONObject.toJSONString(ips), IpModel.class));
                    }
                    break;
                case TIANYI:
                    Long tianyiflavorId = params.getFlavorId();
                    if (null == tianyiflavorId) {
                        Flavor flavor = getFlavorId(vendorId, type, params);
                        if (null == flavor) {
                            return new BocloudResult<>(false, "该平台暂无匹配的规格");
                        }
                        tianyiflavorId = flavor.getId();
                        params.setFlavorId(tianyiflavorId);
                    }
                    inputObject = JSONObject.parseObject(JSONObject.toJSONString(params));
                    modelResult = process.prepare(inputObject);
                    if (modelResult.isFailed()) {
                        return new BocloudResult<>(false, modelResult.getMessage());
                    }
                    break;
                case ALIYUN:
                    Long aliyunFlavorId = params.getFlavorId();
                    String instanceType = params.getInstanceType();
                    if (null == aliyunFlavorId && StringUtils.isEmpty(instanceType)) {
                        Flavor flavor = getFlavorId(vendorId, type, params);
                        if (null == flavor) {
                            return new BocloudResult<>(false, "该平台暂无匹配的规格");
                        }
                        aliyunFlavorId = flavor.getId();
                        params.setFlavorId(aliyunFlavorId);
                        params.setInstanceType(flavor.getFlavorUuid());
                    }
                    inputObject = JSONObject.parseObject(JSONObject.toJSONString(params));
                    inputObject.put("securityGroups", params.getGroups());
                    inputObject.put("groups", params.getGroups().get(0));
                    modelResult = process.prepare(inputObject);
                    if (modelResult.isFailed()) {
                        return new BocloudResult<>(false, modelResult.getMessage());
                    }
                    break;
                case HUAWEI:
                case TENCENT:
                case JDCLOUD:
                case H3C:
                case POWERVC:
                case TCE:
                case AZURE:
                case QCLOUD:
                case PQCLOUD:
                case AWS:
                    Long huaweiFlavorId = params.getFlavorId();
                    String huaweiInstanceType = params.getInstanceType();
                    if (null == huaweiFlavorId && StringUtils.isEmpty(huaweiInstanceType)) {
                        Flavor flavor = getFlavorId(vendorId, type, params);
                        if (null == flavor) {
                            return new BocloudResult<>(false, "该平台暂无匹配的规格");
                        }
                        huaweiFlavorId = flavor.getId();
                        params.setFlavorId(huaweiFlavorId);
                        params.setInstanceType(flavor.getFlavorUuid());
                    }
                    inputObject = JSONObject.parseObject(JSONObject.toJSONString(params));
                    modelResult = process.prepare(inputObject);
                    if (modelResult.isFailed()) {
                        return new BocloudResult<>(false, modelResult.getMessage());
                    }
                    break;
                default:
                    break;
            }
            ServerModel model = modelResult.getData();
            CloudServer cloudServer = JSONObject.parseObject(inputObject.toJSONString(), CloudServer.class);
            cloudServer.setCpu(model.getCpu() == null ? 0 : model.getCpu());
            cloudServer.setMemory(model.getMemory() == null ? new BigDecimal(0) : model.getMemory());
            cloudServer.setDisk(model.getDisk() == null ? 0 : model.getDisk());
            cloudServer.setPswd(model.getPassword());
            cloudServer.setAccount(model.getAccount());
            cloudServer.setZone(model.getZone());
            cloudServer.setStatus(BocloudStatus.Server.BUILDING.name());
            cloudServer.setIsTemplate(false);
            cloudServer.setResourceId(IDFactory.instance().uuid());
            cloudServer.setVendorType(vendor.getType());
            cloudServer.setRecycle(false);
            cloudServer.setImageUuid(model.getImageUuid());
            cloudServer.setCatalog(context.getCatalog());
            cloudServer.setRegionId(model.getRegionId());
            cloudServer.setSecurityGroups(model.getSecurityGroups());
            cloudServer.setInstanceChargeType(model.getInstanceChargeType());
            cloudServer.setVendorId(vendor.getId());
            cloudServer.setHostId(hostId);
            cloudServer.setVdcId(model.getVdcId());
            cloudServer.setTemplateId(templateId);
            cloudServer.setCreatorId(creatorId);
            cloudServer.setOwnerId(ownerId);
            cloudServer.setMenderId(menderId);
            cloudServer.setTenantId(context.getTenant());
            cloudServer.setBusinessId(businessId);
            cloudServer.setProjectId(projectId);
            cloudServer.setPoolGroupId(params.getPoolGroupId());
            cloudServer.setExpiredTime(expiredTime);
            cloudServerRepository.save(cloudServer);
            ProcessResult processResult = new ProcessResult(model, process, cloudServer);
            return new BocloudResult<>(true, processResult, "success");
        } catch (Exception e) {
            logger.error("create server error:", e.getMessage());
            return new BocloudResult<>(false, "创建失败：" + e.getMessage());
        }
    }

    public BocloudResult vcPrepare(JSONObject object, RequestContext context, CloudVendor vendor) {
        // cpu大小
        Long cpu = object.getLong("cpu");
        // // 内存大小
        BigDecimal memory = object.getBigDecimal("memory");
        // // 磁盘大小
        Long disk = object.getLong("disk");
        // 主机ID
        Long hostId = object.getLong("hostId");
        // 模板ID
        Long templateId = object.getLong("templateId");
        // 模板名称
        String templateName = object.getString("templateName");
        // 虚拟机名
        String name = object.getString("name");
        // 宿主机标签
        String pmLabelIds = object.getString("labels");
        // 云平台id
        Long vendorId = object.getLong("vendorId");
        // 项目id
        Long projectId = object.getLong("projectId");
        // 单位id
        Long tenantId = object.getLong("tenantId");
        if (null == vendorId) {
            vendorId = vendor.getId();
            object.put("vendorId", vendorId);
        }
        // 子网id(逻辑交换机id)
        Long subnetId = object.getLong("subnetId");
        // 磁盘类型
        String diskCategory = object.getString("diskCategory");
        // 操作系统类型(Linux/Windows)
        String osCategory = object.getString("osCategory");
        // 操作系统版本
        String osVersion = object.getString("osVersion");
        try {
            // Powervc允许重名
            if (cloudServerRepository.exists(name, vendor.getId())
                && !CloudProvider.POWERVC.name().equals(vendor.getType())) {
                return new BocloudResult<>(false, "此名称已存在!");
            }
            Server server = null;
            if (null != hostId) {
                server = serverRepository.query(hostId);
                if (null == server) {
                    return new BocloudResult<>(false, "宿主机不存在!");
                }
            } else if (CloudProvider.VMWARE.name().equals(vendor.getType())) {
                BocloudResult<ProcessResult> result = this.assignHostAndDatastore(
                    StringUtils.isEmpty(pmLabelIds) ? new ArrayList<>() : JSONArray.parseArray(pmLabelIds, Long.class),
                    vendorId, diskCategory, JSONObject.parseObject(object.toJSONString(), VmGenericParam.class));
                if (result.isFailed()) {
                    return new BocloudResult<>(result.isSuccess(), result.getMessage());
                }
                server = serverRepository.query(object.getLong("hostId"));
                if (null == server) {
                    return new BocloudResult<>(false, "宿主机不存在!");
                }
            }
            if (!StringUtils.isEmpty(templateName)) {
                CloudServer template = cloudServerRepository.getByName(templateName, server.getVendorId());
                if (null == template) {
                    return new BocloudResult<>(false, "未找到合适的模板!");
                }
                templateId = template.getId();
                object.put("templateId", templateId);
            } else if (!StringUtils.isEmpty(osCategory) && !StringUtils.isEmpty(osVersion)) {
                List<Image> images = imageRepository.listByVendorId(vendor.getId());
                Image targetImage = images.stream()
                    .filter(image -> !StringUtils.isEmpty(image.getImageLabel())
                        && image.getImageLabel().contains(osCategory) && image.getImageLabel().contains(osVersion))
                    .findFirst().orElseThrow(() -> new Exception("未找到合适的镜像"));

                if (null != targetImage.getTemplateId() && 0L != targetImage.getTemplateId()) {
                    CloudServer template = cloudServerRepository.query(targetImage.getTemplateId());
                    if (null == template) {
                        return new BocloudResult<>(false, "未找到合适的模板!");
                    }
                    templateId = template.getId();
                    object.put("templateId", templateId);
                } else {
                    object.put("imageId", targetImage.getId());
                }
            }
            CloudProvider type = CloudProvider.valueOf(vendor.getType());
            BocloudResult<ServerModel> modelResult = new BocloudResult<>();
            // 路由器id
            Long vpcId = object.getLong("vpcId");
            // 要新增，删除或编辑的网卡
            List<NetcardOperation> operations = new ArrayList<>();
            if (StringUtils.isEmpty(object.getString("operations"))) {
                List<NetworkCard> cards = networkCardRepository.listByHost(templateId, "VM");
                if (ListTool.isEmpty(cards)) {
                    return new BocloudResult<>(false, "选择的虚拟机模板上无网卡，申请虚拟机失败");
                }
                for (NetworkCard card : cards) {
                    NetcardOperation operation = new NetcardOperation();
                    operation.setName(card.getName());
                    operation.setOperation("EDIT");
                    operation.setLabel(card.getLabel());
                    operation.setPortType(card.getPortType());
                    operation.setMac(card.getMac());
                    operation.setVpcId(vpcId);
                    operation.setSubnetId(subnetId);
                    operations.add(operation);
                }
            } else {
                operations = JSONObject.parseArray(object.getString("operations"), NetcardOperation.class);
            }
            List<Ip> ips = new ArrayList<>();
            // 软件安装需要两块网卡，一块连接管理网，一块连接业务网
            if (!StringUtils.isEmpty(templateName) || !StringUtils.isEmpty(osCategory)) {
                logger.info("Start to assign ip to new vm：" + name);
                // 处理新虚拟机网卡，分配IP
                BocloudResult bocloudResult = assignNsxIp(vendor, operations, vpcId, subnetId);
                ips = JSONArray.parseArray(JSONObject.toJSONString(bocloudResult.getData()), Ip.class);
                if (bocloudResult.isFailed()) {
                    // 回收IP
                    recycleIp(ips, null, vendor.getId());
                    return new BocloudResult<>(false, bocloudResult.getMessage());
                }
                logger.info(JSONObject.toJSONString(operations));
                logger.info("End to assign ip to new vm：" + name);
            } else {
                logger.info("Start to assign ip to new vm：" + name);
                // 处理新虚拟机网卡，分配IP
                BocloudResult bocloudResult = assignIp(vendor, operations);
                ips = JSONArray.parseArray(JSONObject.toJSONString(bocloudResult.getData()), Ip.class);
                if (bocloudResult.isFailed()) {
                    // 回收IP
                    recycleIp(ips, null, vendor.getId());
                    return new BocloudResult<>(false, bocloudResult.getMessage());
                }
                logger.info(JSONObject.toJSONString(operations));
                logger.info("End to assign ip to new vm：" + name);
            }
            object.put("operations", JSONObject.toJSON(operations));
            return new BocloudResult<>(true, "success");
        } catch (Exception e) {
            logger.error("create server error:", e.getMessage());
            return new BocloudResult<>(false, "创建失败：" + e.getMessage());
        }
    }

    public BocloudResult<CloudServer> builder(String type, Long vendorId, CloudServer server, RequestContext context,
        ServerBuilder builder, String callback) {
        Long userId = context.getTarget();
        String operate = type.toLowerCase() + ".vm";
        String content = "虚拟机【" + server.getName() + "】创建失败";
        BocloudResult<CloudServer> result = new BocloudResult<>(false, content);
        try {
            result = builder.builder(server);
            if (result.isSuccess()) {
                content = "虚拟机【" + server.getName() + "】创建成功，\n详情：【" + result.getMessage() + "】";
            } else {
                // 如果这里将来要删除创建失败的虚拟机，注意powervc创建失败的虚拟机不会删除。不知道为什么5.0这里少了
            	if (!CloudProvider.POWERVC.name().equalsIgnoreCase(server.getVendorType())) {
            		 cloudServerRepository.remove(server.getId(), userId);
            	}
                content = "虚拟机【" + server.getName() + "】创建失败，\n详情：【" + result.getMessage() + "】";
            }
            Long templateId = server.getTemplateId();
            if (null != templateId) {
                ResourceEvent event = null;
                if (result.isSuccess()) {
                    event = new ResourceEvent(templateId, "虚拟机创建", "成功", userId, new Date(), "VM", vendorId,
                        context.getCatalog());
                } else {
                    event = new ResourceEvent(templateId, "虚拟机创建", "失败", userId, new Date(), "VM", vendorId,
                        context.getCatalog());
                }
                resourceEventRepository.save(event);
            }
            if (null != context.getCatalog()) {
                resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
                    MapTools.simpleMap(Common.VENDORID, vendorId), OPERATE_CATEGORY, context));
            }
        } catch (Exception e) {
            logger.error("Get Message Exception:", e);
            if (null != context.getCatalog()) {
                resourceEventPublisher.send(new OperateResult(false, content, operate,
                    MapTools.simpleMap(Common.VENDORID, vendorId), OPERATE_CATEGORY, context));
            }
        }
        if (!StringUtils.isEmpty(callback)) {
            BocloudResult bocloudResult = new BocloudResult(result.isSuccess(), result.getData(), result.getMessage());
            if (result.isSuccess()) {
                Long start = System.currentTimeMillis();
                CloudServer cloudServer = null;
                boolean success = false;
                try {
                    while (true) {
                        // 设置等待超时时间为20分钟
                        if (System.currentTimeMillis() - start > 20 * 1000 * 60) {
                            break;
                        }
                        cloudServer = cloudServerRepository.query(server.getId());
                        if (null != cloudServer && !StringUtils.isEmpty(cloudServer.getPrivateIps())) {
                            success = true;
                            break;
                        }
                        Thread.sleep(10 * 1000L);
                    }
                    if (success) {
                        List<String> ips = new ArrayList<>();
                        if (CloudProvider.VMWARE.name().equalsIgnoreCase(cloudServer.getVendorType())) {
                            List<JSONObject> objects =
                                JSONArray.parseArray(cloudServer.getPrivateIps(), JSONObject.class);
                            for (JSONObject object : objects) {
                                if (!StringUtils.isEmpty(object.getString("address"))) {
                                    ips.add(object.getString("address"));
                                }
                            }
                            if (StringUtils.isEmpty(cloudServer.getAccount())) {
                                if (OSCategory.WINDOWS.name().equalsIgnoreCase(cloudServer.getOsCategory())) {
                                    cloudServer.setAccount("Administrator");
                                } else {
                                    cloudServer.setAccount("root");
                                }
                            }
                            boolean flag = true;
                            start = System.currentTimeMillis();
                            while (flag) {
                                // 设置等待超时时间为5分钟
                                if (System.currentTimeMillis() - start > 5 * 1000 * 60L) {
                                    break;
                                }
                                for (String ip : ips) {
                                    // 只找ipv4地址
                                    if (!StringUtils.isEmpty(ip) && IPAddress.ipv4Validate(ip)) {
                                        SshClient sshClient = null;
                                        TelnetClient telnetClient = null;
                                        try {
                                            if (OSCategory.LINUX.name().equalsIgnoreCase(cloudServer.getOsCategory())) {
                                                sshClient = new SshClient(ip, cloudServer.getAccount(),
                                                    cloudServer.receivePswd(), null == cloudServer.getManagerPort() ? 22
                                                        : cloudServer.getManagerPort());
                                                if (sshClient.connect()) {
                                                    cloudServer.setManagerIp(ip);
                                                    cloudServerRepository.update(cloudServer);
                                                    flag = false;
                                                    break;
                                                }
                                            } else if (OSCategory.WINDOWS.name()
                                                .equalsIgnoreCase(cloudServer.getOsCategory())) {
                                                telnetClient = new TelnetClient();
                                                telnetClient.connect(ip, 5986);
                                                if (telnetClient.isConnected()) {
                                                    cloudServer.setManagerIp(ip);
                                                    cloudServerRepository.update(cloudServer);
                                                    flag = false;
                                                    break;
                                                }
                                            }
                                        } catch (Exception e) {
                                            logger.error("连接虚拟机出现错误继续进行连接，错误信息{}", e);
                                            Thread.sleep(5 * 1000L);
                                        } finally {
                                            if (null != sshClient) {
                                                sshClient.close();
                                            }
                                            if (null != telnetClient) {
                                                telnetClient.disconnect();
                                            }
                                        }
                                    }
                                }
                                Thread.sleep(2 * 1000L);
                            }
                        }
                        logger.info("虚拟机{}网络连接成功，连接IP：{}，耗时：{}毫秒", cloudServer.getName(), cloudServer.getManagerIp(),
                            System.currentTimeMillis() - start);
                        // 数据库是DES加密，传给cop之前做解密，然后用AES加密传输，底层worker使用AES解密
                        CloudServer copServer =
                            JSONObject.parseObject(JSONObject.toJSONString(cloudServer), CloudServer.class);
                        String pswd = copServer.receivePswd();
                        if (!StringUtils.isEmpty(pswd)) {
                            Encryptor encryptor = new AESEncrptor();
                            copServer.setPassword(encryptor.encrypt(pswd, null));
                        } else {
                            copServer.setPassword(null);
                        }
                        logger.info("编排传给cop的密码AES密文：{}", copServer.getPassword());
                        bocloudResult.setMessage("虚拟机创建成功");
                        bocloudResult.setData(copServer);
                        result.setMessage("虚拟机创建成功");
                        result.setData(cloudServer);
                    } else {
                        bocloudResult.setSuccess(success);
                        bocloudResult.setMessage("虚拟机创建失败：无法获取到IP地址");
                        bocloudResult.setData(result.getData());
                        result.setSuccess(success);
                        result.setMessage("虚拟机创建失败：无法获取到IP地址");
                        result.setData(cloudServer);
                    }
                } catch (Exception e) {
                    logger.error("Get error message：", e);
                }
            }
            if (!"k8s.callback".equals(callback)) {
                this.amqpTemplate.convertAndSend(callback, bocloudResult);
            }
        }
        return result;
    }

    /**
     * 保存告警
     *
     * @param name
     * @throws Exception
     */
    @SuppressWarnings("unused")
    private void saveAlarm(String name) throws Exception {
        // 创建告警
        ResourceAlarm alarm = new ResourceAlarm(AlarmLevel.WARN.name(), "VM", Long.parseLong(name), null, new Date(),
            true, false, "虚拟机模板不存在");
        alarm.setCreatorId(1L);
        alarm.setGmtCreate(new Date());
        alarm.setStatus("UNCONFIRMED");
        alarm.setDeleted(false);
        alarm.setName("虚拟机【" + name + "】创建失败");
        alarmRepository.save(alarm);
    }

    /**
     * 删除虚拟机
     *
     * @param id
     *            虚拟机id
     * @param volumeIds
     *            要跟随虚拟机删除的卷
     * @param vendor
     * @param server
     * @param event
     * @param context
     * @return
     */
    public BocloudResult remove(Long id, List<Long> volumeIds, CloudVendor vendor, CloudServer server,
        ResourceEvent event, RequestContext context, Boolean isDeletePublicIp) {
        try {
            if (null == event) {
                event = new ResourceEvent();
            }
            // 更新虚拟机挂载的磁盘
            List<Volume> volumes = volumeRepository.listByServerId(id, vendor.getId(), false);
            // 根磁盘ID
            Long rootVolumeId = null;
            if (CloudProvider.VMWARE.name().equals(server.getVendorType())) {
                for (Volume volume : volumes) {
                    volumeRepository.remove(volume.getId(), context.getTarget());
                }
            } else if (CloudProvider.POWERVC.name().equals(server.getVendorType())) {
                // 先把需要删除的卷执行删除操作
                if (volumeIds != null && volumeIds.size() > 0) {
                    for (Long volumeId : volumeIds) {
                        volumeRepository.remove(volumeId, context.getTarget());
                        serverVolumeRepository.removeByVid(volumeId);
                    }
                }
                // 剩下不需要删除的卷，重新同步下数据，并删除该卷和虚拟机的关联关系
                volumes = volumeRepository.listVolumeByServerId(id);
                for (Volume volume : volumes) {
                    BocloudResult bocloudResult = volumeDriver.detail(volume.getVolumeUuid(), vendor.getUuid(), null);
                    if (bocloudResult.isFailed()) {
                        return bocloudResult;
                    }
                    VolumeModel volumeModel = (VolumeModel)bocloudResult.getData();
                    powervcTransportor.insertOrUpdate(vendor, volumeModel, context.getTarget());

                    serverVolumeRepository.removeBySid(id);
                }
                // 更新下主机资源数据
                ServerConfig hostConfig = serverConfigRepository.getBySid(server.getHostId());
                if (hostConfig != null) {
                    hostConfig.setHmcCpuUsed(hostConfig.getHmcCpuUsed() - server.getHmcCpu());
                    hostConfig.setMemUsed(hostConfig.getMemUsed() - server.getMemory().doubleValue());
                    serverConfigRepository.update(hostConfig);
                }
            } else if (CloudProvider.OPENSTACK.name().equals(server.getVendorType())
                || CloudProvider.FUSIONCLOUD.name().equals(server.getVendorType())
                || CloudProvider.MANAGEONE.name().equals(server.getVendorType())
                || CloudProvider.TENCENT.name().equals(server.getVendorType())
                || CloudProvider.JDCLOUD.name().equals(server.getVendorType())
                || CloudProvider.ALIYUN.name().equals(server.getVendorType())
                || CloudProvider.TCE.name().equals(server.getVendorType())
                || CloudProvider.AWS.name().equals(server.getVendorType())
                || CloudProvider.QCLOUD.name().equals(server.getVendorType())
                || CloudProvider.TIANYI.name().equals(server.getVendorType())) {
                for (Volume volume : volumes) {
                    if ((null != volume.getBootVolume() && volume.getBootVolume())
                        || (null != volume.getDeleteWithInstance() && volume.getDeleteWithInstance())) {
                        rootVolumeId = volume.getId();
                        volumeRepository.remove(rootVolumeId, context.getTarget());
                        objectRelationRepository.deleteByRid(rootVolumeId, ResourceCategory.Storage.name());
                        tagRepository.removeByRid(volume.getVolumeUuid());
                    } else {
                        volume.setStatus("AVAILABLE");
                        volume.setDevice(null);
                        volume.setInstanceId(null);
                        volume.setServerId(null);
                        volumeRepository.update(volume);
                    }
                }
            } else if (CloudProvider.HUAWEI.name().equals(server.getVendorType())) {
                Boolean deleteVolume = server.getDeleteVolume() == null ? false : server.getDeleteVolume();
                for (Volume volume : volumes) {
                    if (deleteVolume) {
                        volumeRepository.remove(volume.getId(), context.getTarget());
                        continue;
                    }
                    if ((null != volume.getBootVolume() && volume.getBootVolume())
                        || (null != volume.getDeleteWithInstance() && volume.getDeleteWithInstance())) {
                        rootVolumeId = volume.getId();
                        volumeRepository.remove(rootVolumeId, context.getTarget());
                        tagRepository.removeByRid(volume.getVolumeUuid());
                    } else {
                        volume.setStatus("AVAILABLE");
                        volume.setDevice(null);
                        volume.setInstanceId(null);
                        volume.setServerId(null);
                        volumeRepository.update(volume);
                    }
                }
                Boolean deletePublicip = server.getDeletePublicip() == null ? false : server.getDeletePublicip();
                String privateIps = 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)) {
                            List<ElasticIp> elasticIps =
                                elasticIpRepository.listByIid(poblicIpObject.getString("portId"), vendor.getId());
                            if (!ListTool.isEmpty(elasticIps)) {
                                for (ElasticIp elasticIp : elasticIps) {
                                    if (deletePublicip) {
                                        elasticIpRepository.remove(elasticIp.getId(), context.getTarget());
                                    } else {
                                        elasticIpService.disassociate(elasticIp.getId(), context);
                                    }
                                }
                            }
                        }
                    }
                }
            } else if (CloudProvider.AZURE.name().equals(server.getVendorType())) {
                for (Volume volume : volumes) {
                    volume.setStatus(AzureTaskStatus.AVAILABLE.name());
                    volumeRepository.update(volume);
                    logger.info("系统盘重置状态成功");
                    rootVolumeId = volume.getId();
                    if ((null != volume.getBootVolume() && volume.getBootVolume())) {
                        logger.info("执行系统盘删除......");
                        BocloudResult volumeResult = volumeService.remove(rootVolumeId, null, context);
                        if (volumeResult.isFailed()) {
                            volume.setTenantId(0L);
                            volume.setProjectId(0L);
                            volume.setBootVolume(false);
                            volume.setStatus(AzureTaskStatus.AVAILABLE.name());
                            volume.setDevice(null);
                            volume.setInstanceId(null);
                            volume.setServerId(null);
                            volumeRepository.update(volume);
                        }
                    } else {
                        volume.setBootVolume(false);
                        volume.setStatus(AzureTaskStatus.AVAILABLE.name());
                        volume.setDevice(null);
                        volume.setInstanceId(null);
                        volume.setServerId(null);
                        volumeRepository.update(volume);
                    }
                }
            }
            // 网络接口
            CloudProvider type = CloudProvider.valueOf(server.getVendorType());
            if (CloudProvider.AWS.name().equals(server.getVendorType())
                || CloudProvider.AZURE.name().equals(server.getVendorType())
                || CloudProvider.ALIYUN.name().equals(server.getVendorType())) {
                List<Param> nicsParams = Lists.newArrayList();
                Map<String, Object> simpleMap = MapTools.simpleMap(Common.VENDORID, vendor.getId());
                simpleMap.put("serverId", id);
                nicsParams.add(new Param(simpleMap, Sign.EQ));
                List<NetworkInterface> networkInterfaces = networkInterfaceRepository.list(nicsParams);
                for (NetworkInterface networkInterface : networkInterfaces) {
                    switch (type) {
                        case AWS:
                            // 如果为true 代表随实例终止了
                            if (networkInterface.isDeleteOnTermination()) {
                                networkInterfaceRepository.delete(networkInterface.getId(), context.getTarget());
                            } else {
                                networkInterface.setMenderId(context.getTarget());
                                networkInterface.setGmtModify(new Date());
                                networkInterface.setServerId(null);
                                networkInterface.setAttachedTime(null);
                                networkInterface.setAttachmentUuid(null);
                                networkInterface.setDeviceIndex(-1);
                                networkInterface.setDeleteOnTermination(false);
                                networkInterface.setDetachedTime(new Date());
                                networkInterfaceRepository.update(networkInterface);
                            }
                            break;
                        case ALIYUN:
                            networkInterfaceRepository.delete(networkInterface.getId(), context.getTarget());
                            break;
                        case AZURE:
                            // 获取网卡所有IP配置
                            List<NicIpConfiguration> nicIpConfigurations =
                                nicIpConfigurationRepository.listByNetworkInterfaceId(networkInterface.getId());
                            // 配置操作
                            for (NicIpConfiguration nicIpConfiguration : nicIpConfigurations) {
                                List<ResourcePublicIPAddressRelation> addressRelations =
                                    resourcePublicIPAddressRelationRepository.listByResourceId(
                                        nicIpConfiguration.getId(), AzureIpRelationType.NICIPCONFIGURATION.name());
                                List<PublicIPAddress> publicIPAddresses = new ArrayList<>();
                                for (ResourcePublicIPAddressRelation relation : addressRelations) {
                                    PublicIPAddress publicIPAddress =
                                        publicIPAddressRepository.query(relation.getIpId());
                                    if (!ObjectUtils.isEmpty(publicIPAddress)) {
                                        publicIPAddresses.add(publicIPAddress);
                                    }
                                }
                                // todo
                                logger.info("执行IP配置解绑弹性IP......");
                                BocloudResult result01 = nicIpConfigurationService
                                    .detachPublicIpAddress(nicIpConfiguration.getId(), context);
                                logger.info("执行结果：{} - 消息：{}", result01.isSuccess(), result01.getMessage());

                                logger.info("执行弹性IP归属关系操作......");
                                for (PublicIPAddress publicIPAddress : publicIPAddresses) {
                                    if (null != isDeletePublicIp && isDeletePublicIp) {
                                        logger.info("执行弹性IP删除......");
                                        publicIPAddressService.removeCourse(publicIPAddress.getId(), context);
                                    } else {
                                        // 重置状态
                                        publicIPAddress.setStatus(AzureTaskStatus.AVAILABLE.name());
                                        publicIPAddressRepository.update(publicIPAddress);
                                        // 删除绑定关系
                                        resourcePublicIPAddressRelationRepository.removeByIpId(publicIPAddress.getId());
                                    }
                                }
                            }
                            // 删除网卡
                            logger.info("执行网络接口删除......");
                            BocloudResult networkInterfaceResult =
                                networkInterfaceService.remove(networkInterface.getId(), context);
                            if (networkInterfaceResult.isFailed()) {
                                networkInterface.setMenderId(context.getTarget());
                                networkInterface.setGmtModify(new Date());
                                networkInterface.setServerId(null);
                                networkInterfaceRepository.update(networkInterface);
                            }
                            break;
                        default:
                            break;
                    }

                }
            }

            // 删除监控规则
            if (CloudProvider.AZURE.name().equals(server.getVendorType())) {
                List<MetricAlertResourceRelation> metricAlertResourceRelations =
                    metricAlertResourceRelationRepository.listByResourceId(id, "Microsoft.Compute/virtualMachines");
                for (MetricAlertResourceRelation resourceRelation : metricAlertResourceRelations) {
                    logger.info("执行监控规则删除......");
                    metricAlertService.remove(resourceRelation.getMetricAlertId(), context);
                }
                metricAlertResourceRelationRepository.removeByResourceId(id, "Microsoft.Compute/virtualMachines");
            }

            // 回收IP
            String privateIps = server.getPrivateIps();
            if (!StringUtils.isEmpty(privateIps)) {
                switch (CloudProvider.valueOf(server.getVendorType())) {
                    case OPENSTACK:
                        break;
                    case VMWARE:
                        ipRepository.makeFreeByTarget(server.getId(), "VM", server.getVendorId());
                        break;
                    case H3C:
                        ipRepository.delete(server.getId(), "VM");
                        break;
                    case JDCLOUD:
                        break;
                    case ALIYUN:
                        break;
                    default:
                        break;
                }
            }
            // 删除端口，回收与虚拟机绑定端口的IP
            List<Port> ports = portRepository.listByDeviceId(server.getInstanceId(), vendor.getId());
            if (!ListTool.isEmpty(ports)) {
                for (Port port : ports) {
                    // 删除端口
                    portDriver.remove(port.getPortUuid(), vendor.getUuid(), "");
                    List<PortFixedIp> portFixedIps = portFixedIpRepository.listByPortId(port.getId());
                    for (PortFixedIp fixedIp : portFixedIps) {
                        ipRepository.delete(fixedIp.getIpAddress(), fixedIp.getSubnetId(), server.getVendorId());
                        // 如果该虚拟机为负载均衡器下的成员，则需要删除对应成员记录
                        lbMemberRepository.remove(fixedIp.getIpAddress(), fixedIp.getSubnetId(), port.getVendorId(),
                            context.getTarget());
                    }
                    portFixedIpRepository.deleteByPortId(port.getId());
                    // 更新端口绑定的浮动IP
                    List<FloatingIp> fips = floatingIpRepository.listByPortId(port.getId());
                    for (FloatingIp fip : fips) {
                        fip.setFixedIpAddress(null);
                        fip.setPortUuid(null);
                        fip.setPortId(null);
                        fip.setRouterUuid(null);
                        fip.setRouterId(null);
                        fip.setMenderId(context.getTarget());
                        if (CloudProvider.FUSIONCLOUD.name().equals(server.getVendorType())) {
                            fip.setStatus("DOWN");
                        } else {
                            fip.setStatus("STOPPED");
                        }
                        floatingIpRepository.update(fip);
                    }
                    // 删除端口本地记录
                    portRepository.remove(port.getId(), context.getTarget());
                }
            }
            // 如果虚拟机是租户端创建，需要更新租户配额
            ObjectRelation objectRelation = objectRelationRepository.get(id, ResourceCategory.Computer.name());
            if (null != objectRelation && server.getTenantId() > 0L) {
                // 更新配额信息
                if (CloudProvider.OPENSTACK.name().equals(server.getVendorType())
                    || CloudProvider.FUSIONCLOUD.name().equals(server.getVendorType())) {
                    if (null != rootVolumeId) {
                        // 删除根磁盘关系表
                        objectRelationRepository.deleteByRid(rootVolumeId, ResourceCategory.Storage.name());
                    }
                } else if (CloudProvider.VMWARE.name().equals(server.getVendorType())
                    || CloudProvider.TENCENT.name().equals(server.getVendorType())
                    || CloudProvider.JDCLOUD.name().equals(server.getVendorType())
                    || CloudProvider.ALIYUN.name().equals(server.getVendorType())
                    || CloudProvider.TCE.name().equals(server.getVendorType())
                    || CloudProvider.AZURE.name().equals(server.getVendorType())
                    || CloudProvider.QCLOUD.name().equals(server.getVendorType())
                    || CloudProvider.AWS.name().equals(server.getVendorType())) {
                } else if (CloudProvider.HUAWEI.name().equals(server.getVendorType())) {
                    if (null != rootVolumeId) {
                        // 删除根磁盘关系表
                        objectRelationRepository.deleteByRid(rootVolumeId, ResourceCategory.Storage.name());
                    }
                }
                // 删除关系表
                objectRelationRepository.deleteByRid(id, ResourceCategory.Computer.name());
                // 从管理端删除回滚配额
                if (Catalog.Manager == context.getCatalog() && null != server.getTenantId()
                    && server.getTenantId() > 0L) {
                    this.callbackQuotas(server, vendor.getType());
                }
            }
            event.setResourceId(id);
            event.setContent("DELETE");
            event.setResult("success");
            event.setVendorId(vendor.getId());
            event.setOperatorId(context.getTarget());
            event.setGmtOperate(new Date());
            event.setObject("VM");
            if (null != server.getIsTemplate() && server.getIsTemplate()) {
                imageRepository.removeByTemplate(server.getId(), context.getTarget());
            }
            // 删除安全组和虚拟机关系表
            serverSgroupRepository.removeBySid(id);
            // 删除虚拟机 秘钥关系
            serverKeypairRepository.removeBySid(id);
            // 删除快照 阿里云快照不删除
            if (!CloudProvider.ALIYUN.name().equals(server.getVendorType())) {
                snapshotRepository.removeByVm(id, context.getTarget());
            }
            storeHostRepository.deleteByHost(server.getId(), "VM");
            networkHostRepository.deleteByHost(server.getId(), "VM");
            networkCardRepository.removeByHost(server.getId(), "VM", context.getTarget());
            // 公有云删除网卡
            networkCardRepository.removeByServerId(server.getInstanceId(), context.getTarget());
            // 更新已绑定网卡
            List<NetworkCard> networkList =
                networkCardRepository.listByInstanceId(server.getInstanceId(), server.getVendorId());
            if (null != networkList && networkList.size() > 0) {
                for (NetworkCard networkCard : networkList) {
                    networkCard.setLabel(null);
                    networkCard.setUsed(false);
                    networkCard.setMenderId(context.getTarget());
                    networkCard.setGmtModify(new Date());
                    networkCardRepository.update(networkCard);
                }
            }
            // 更新浮动IP状态
            FloatingIp floatingIp = floatingIpRepository.listByInstanceId(server.getInstanceId(), server.getVendorId());
            if (null != floatingIp) {
                floatingIp.setStatus("UNBIND");
                floatingIp.setFixedIpAddress(null);
                floatingIp.setInstanceId(null);
                floatingIp.setNetworkCardUuid(null);
                floatingIp.setGmtModify(new Date());
                floatingIp.setMenderId(context.getTarget());
                floatingIpRepository.update(floatingIp);
            }
            List<ElasticIp> elasticIps = elasticIpRepository.listByIid(server.getInstanceId());
            if (!ListTool.isEmpty(elasticIps)) {
                for (ElasticIp elasticIp : elasticIps) {
                    elasticIp.setAssociationId(null);
                    elasticIp.setInstanceType(null);
                    elasticIp.setInstanceId(null);
                    elasticIp.setMenderId(context.getTarget());
                    elasticIp.setGmtModify(new Date());
                    elasticIpRepository.update(elasticIp);
                }
            }
            // 删除虚机的定时快照任务
            snapshotTaskService.removeByVmId(server.getId());
            // 删除TAG
            tagRepository.removeByRid(server.getInstanceId());
            resourceRepository.remove(server.getId(), ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
                context.getTarget());
            // 删除标签
            serverLabelRepository.deleteByTarget(id, "VM");
            // 如果当前机器在回收站中 则删除回收站数据
            Boolean recycle = server.getRecycle();
    		String orderItemSn = server.getUuid();
            if (null != recycle && recycle && !StringUtils.isEmpty(orderItemSn)) {
    			cosInternalService.recycle(orderItemSn);
    		}
            
            cloudServerRepository.remove(id, context.getTarget());
            if (CloudProvider.VMWARE.name().equalsIgnoreCase(vendor.getType())
                || CloudProvider.OPENSTACK.name().equalsIgnoreCase(vendor.getType())) {
                JSONObject object = new JSONObject();
                object.put("type", CloudServer.class.getSimpleName());
                object.put("data", server);
                amqpTemplate.convertAndSend("cmp.resource.deleted.queue", object);
            }
            // 向堡垒机发动删除消息
            if (server.getVendorType().equals(CloudProvider.VMWARE.name())) {
                if (null != server.getPrivateIps()) {
                    sendRemoveMsgToShterm(server.getName(), server.getPrivateIps());
                }
            }
        } catch (Exception e) {
            logger.error("remove CloudServer fail:", e);
            event.setResult("fail");
            return new BocloudResult(false, event, "删除失败");
        }
        return new BocloudResult(true, event, "删除成功");
    }

    /**
     * @param privateIps
     *            虚拟机ip
     * @return void
     * @Author: lxy
     * @Description: 向堡垒机发动删除消息
     * @Date 2021/5/15 18:04
     * @Param name 虚拟机名称
     * @throws:
     **/
    private void sendRemoveMsgToShterm(String name, String privateIps) {
        List<String> ips = new ArrayList<>();
        getIps(privateIps, ips);
        for (String ip : ips) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("name", name);
            jsonObject.put("privateIps", ip);
            amqpTemplate.convertAndSend("delete.shterm.queue", jsonObject);
            logger.info("send rabbitmq topic is : {} success ，message is ：{}", "delete.shterm.queue",
                jsonObject.toJSONString());
        }
    }

    /**
     * @param ips
     * @return void
     * @Author: lxy
     * @Description: privateIps 中获取所有ip
     * @Date 2021/5/16 17:30
     * @Param privateIps
     * @throws:
     **/
    private void getIps(String privateIps, List<String> ips) {
        List<JSONObject> privateIpsLsit = JSONArray.parseArray(privateIps, JSONObject.class);
        if (ListTool.isEmpty(privateIpsLsit)) {
            return;
        }
        for (JSONObject json : privateIpsLsit) {
            String address = json.getString("address");
            if (StringUtils.isEmpty(address)) {
                continue;
            }
            ips.add(address);
        }
    }

    /**
     * 回滚配额
     *
     * @param server
     */
    private void callbackQuotas(CloudServer server, String vendorType) {
        List<ResourceQuota> quotas = new ArrayList<>();
        quotas.add(new ResourceQuota("meta.cpu", Long.valueOf(server.getCpu())));
        quotas.add(new ResourceQuota("meta.mem", server.getMemory().longValue()));
        quotas.add(new ResourceQuota("meta.disk", Long.valueOf(server.getDisk())));
        quotas.add(new ResourceQuota(vendorType.toLowerCase() + ".standard.server", 1L));
        cosInternalService.updateQuotas(quotas, ResourceQuota.Action.Callback, server.getProjectId());
    }

    /**
     * 从网络资源池分配IP
     *
     * @param netPoolId
     * @param vendorId
     * @param operations
     * @return
     * @throws Exception
     */
    public BocloudResult assignIp(Long netPoolId, Long vendorId, List<NetcardOperation> operations) throws Exception {
        int newNetCardNum = 0;
        List<Ip> ips = Lists.newArrayList();
        for (NetcardOperation operation : operations) {
            switch (operation.getOperation()) {
                // 新添加或编辑的网卡分配IP地址
                case "ADD":
                case "EDIT":
                    BocloudResult<Ip> result = this.getIp(netPoolId, vendorId, operation, ips);
                    if (result.isFailed()) {
                        return new BocloudResult(false, ips, result.getMessage());
                    }
                    operation.setIp(JSONObject.parseObject(JSONObject.toJSONString(result.getData()), IpModel.class));
                    newNetCardNum++;
                    break;
                default:
                    break;
            }
        }
        if (newNetCardNum == 0) {
            return new BocloudResult(false, ips, "请编辑网络设备，为机器选择IP池");
        }
        return new BocloudResult(true, ips, "success");
    }

    /**
     * 网络资源池分配IP
     *
     * @param netPoolId
     * @param vendorId
     * @param operation
     * @param ips
     * @return
     * @throws Exception
     */
    private BocloudResult<Ip> getIp(Long netPoolId, Long vendorId, NetcardOperation operation, List<Ip> ips)
        throws Exception {
        String address = operation.getAddress();
        Ip assignIp = null;
        // 管理端设置的IP
        if (null != operation && null != operation.getIp()) {
            assignIp = JSONObject.parseObject(JSONObject.toJSONString(operation.getIp()), Ip.class);
        } else if (!StringUtils.isEmpty(address)) {
            Ip ip = ipRepository.checkExist(address, null, vendorId);
            if (null == ip || null == ip.getPoolId()) {
                return new BocloudResult<Ip>(false, "网卡名称为：【" + operation.getName() + "】指定的IP不存在于IP池中");
            }
            if (ip.getStatus() != IpStatus.free) {
                return new BocloudResult<Ip>(false, "网卡名称为：【" + operation.getName() + "】指定的IP已被使用或锁定");
            }
            if ("V6".equals(IPAddress.getVersion(address))) {
                address = new IPv6Address().compress(address);
            }
            ip.setCatalog("VM");
            ip.setStatus(IpStatus.lock);
            ipRepository.update(ip);
            // List<IpPool> pools = ipPoolRepository.listByVendor(vendorId, "V4");
            // if (ListTool.isEmpty(pools)) {
            // logger.warn("This vendor does not exist ip!");
            // return new BocloudResult<>(false, "此平台下无IP可分配!");
            // }
            // for (IpPool pool : pools) {
            // String dns = JSONArray.parseArray(pool.getDnsNames(), String.class).get(0);
            // List<String> poolList = JSONArray.parseArray(pool.getPools(), String.class);
            // IPAddress ipAddress = IPAddress.getIPAddress(address);
            // boolean flag = ipAddress.isInPools(address, poolList);
            // if (flag) {
            // ip = new Ip(address, ipAddress.getMask(pool.getCidr()), pool.getGateway(), dns, vendorId,
            // IDFactory.instance().uuid(), pool.getId());
            // ip.setCatalog("VM");
            // ipRepository.save(ip);
            // break;
            // }
            // }
            // if (null == ip) {
            // return new BocloudResult<>(false, "此平台分配的IP池不包含该IP");
            // }
            assignIp = ip;
        } else {
            BocloudResult<List<Ip>> achieveIps = ipService.achieveIps(vendorId, netPoolId, 1);
            if (achieveIps.isFailed()) {
                return new BocloudResult<>(false, "分配IP地址失败，可能原因是剩余可用IP不足");
            }
            assignIp = achieveIps.getData().get(0);
        }
        ips.add(assignIp);
        return new BocloudResult<>(true, assignIp, "分配成功");
    }

    /**
     * 分配nsxIP
     *
     * @param vendor
     * @param operations
     * @param vpcId
     * @param subnetId
     * @return
     * @throws Exception
     */
    public BocloudResult assignNsxIp(CloudVendor vendor, List<NetcardOperation> operations, Long vpcId, Long subnetId)
        throws Exception {
        logger.info("选择的VPC ID：{}", vpcId);
        logger.info("选择的SUBNET ID：{}", subnetId);
        List<Ip> ips = new ArrayList<>();
        if (operations.size() > 1) {
            for (int i = 0; i < operations.size(); i++) {
                NetcardOperation operation = operations.get(i);
                if (null != vpcId || null != subnetId) {
                    // 第一块网卡分配管理网，第二块网卡分配业务网
                    if (i == 0) {
                        List<NsxLogicalRouter> managerRouters =
                            nsxRouterRepository.listManagementNetwork(vendor.getId());
                        if (ListTool.isEmpty(managerRouters)) {
                            return new BocloudResult(false, "未找到管理网路由器");
                        }
                        NsxLogicalRouter managerRouter = managerRouters.get(0);
                        BocloudResult ipResult = this.getNsxIp(ips, managerRouter.getId(), null, operation, vendor);
                        if (ipResult.isFailed()) {
                            return ipResult;
                        }
                    } else {
                        BocloudResult ipResult = this.getNsxIp(ips, vpcId, subnetId, operation, vendor);
                        if (ipResult.isFailed()) {
                            return ipResult;
                        }
                    }
                } else {
                    BocloudResult<Ip> result = this.getIp(operation.getIpv4PoolId(), operation.getName(),
                        operation.getAddress(), vendor.getId(), ips, "V4");
                    if (result.isFailed()) {
                        return new BocloudResult(false, ips, result.getMessage());
                    }
                    operation.setIp(JSONObject.parseObject(JSONObject.toJSONString(result.getData()), IpModel.class));
                    ips.add(result.getData());
                }
            }
        } else if (operations.size() == 1) {
            NetcardOperation operation = operations.get(0);
            if (null != vpcId || null != subnetId) {
                BocloudResult ipResult = this.getNsxIp(ips, vpcId, subnetId, operation, vendor);
                if (ipResult.isFailed()) {
                    return ipResult;
                }
            } else {
                BocloudResult<Ip> result = this.getIp(operation.getIpv4PoolId(), operation.getName(),
                    operation.getAddress(), vendor.getId(), ips, "V4");
                if (result.isFailed()) {
                    return new BocloudResult(false, ips, result.getMessage());
                }
                operation.setIp(JSONObject.parseObject(JSONObject.toJSONString(result.getData()), IpModel.class));
                ips.add(result.getData());
            }

        }
        return new BocloudResult(true, ips, "success");
    }

    /**
     * @param ips
     * @param vpcId
     * @param subnetId
     * @param operation
     * @param vendor
     * @return
     * @throws Exception
     */
    private BocloudResult getNsxIp(List<Ip> ips, Long vpcId, Long subnetId, NetcardOperation operation,
        CloudVendor vendor) throws Exception {
        NsxLogicalRouter router = nsxRouterRepository.query(vpcId);
        if (null == router) {
            return new BocloudResult(false, "VPC不存在");
        }
        List<NsxRouterPort> ports = routerPortRepository.listByRouterId(router.getId());
        if (ListTool.isEmpty(ports)) {
            return new BocloudResult(false, "VPC下子网不存在");
        }
        Ip assignIp = null;
        String networkName = null;
        String message = "";
        for (NsxRouterPort port : ports) {
            if (StringUtils.isEmpty(port.getLinkedLogicalSwitchPortId())) {
                continue;
            }
            NsxSwitchPort switchPort =
                switchPortRepository.getByPortId(port.getLinkedLogicalSwitchPortId(), port.getVendorId());
            if (null == switchPort) {
                continue;
            }
            if (null != subnetId && 0L != subnetId) {
                if (!subnetId.equals(switchPort.getSwitchId())) {
                    continue;
                }
            }
            networkName = switchPort.getSwitchName();
            BocloudResult<List<Ip>> achieveIps = ipService.achieveNsxIps(port.getId(), 1, "V4");
            if (achieveIps.isFailed()) {
                message = achieveIps.getMessage();
                continue;
            }
            assignIp = achieveIps.getData().get(0);
            break;
        }
        if (null == assignIp) {
            return new BocloudResult(false, "【" + router.getName() + "】分配IP地址失败：" + message);
        }
        if (null != router.getManagementNetwork() && router.getManagementNetwork()) {
            assignIp.setGateway(null);
        }
        ips.add(assignIp);
        operation.setIp(JSONObject.parseObject(JSONObject.toJSONString(assignIp), IpModel.class));
        if (!StringUtils.isEmpty(networkName)) {
            operation.setName(networkName);
            Network network = networkRepository.getNsxNetwork(networkName, vendor.getId());
            if (null != network) {
                if (NetworkType.SwitchType.VSWITCH.name().equals(network.getType())) {
                    operation.setPortType(NetworkType.PortGroupType.VIRTUAL.name());
                } else {
                    operation.setPortType(NetworkType.PortGroupType.DVPORT.name());
                }
            }
        }
        return new BocloudResult(true, "success");
    }

    /**
     * 获取nsxIP
     *
     * @param vpcId
     * @param subnetId
     * @param vendor
     * @param count
     * @return
     */
    public List<Ip> getNsxIp(Long vpcId, Long subnetId, CloudVendor vendor, Integer count) {
        try {
            List<Ip> ips = new ArrayList<>();
            NsxLogicalRouter router = null;
            if (null == vpcId || 0L == vpcId) {
                List<NsxLogicalRouter> managerRouters = nsxRouterRepository.listManagementNetwork(vendor.getId());
                if (ListTool.isEmpty(managerRouters)) {
                    BocloudResult<List<Ip>> achieveIps = ipService.achieveIps(1L, "V4");
                    if (achieveIps.isFailed()) {
                        return ips;
                    }
                    ips = achieveIps.getData();
                    return ips;
                }
                router = managerRouters.get(0);
            } else {
                router = nsxRouterRepository.query(vpcId);
                if (null == router) {
                    return ips;
                }
            }
            List<NsxRouterPort> ports = routerPortRepository.listByRouterId(router.getId());
            if (ListTool.isEmpty(ports)) {
                return ips;
            }
            for (NsxRouterPort port : ports) {
                if (StringUtils.isEmpty(port.getLinkedLogicalSwitchPortId())) {
                    continue;
                }
                NsxSwitchPort switchPort =
                    switchPortRepository.getByPortId(port.getLinkedLogicalSwitchPortId(), port.getVendorId());
                if (null == switchPort) {
                    continue;
                }
                if (null != subnetId && 0L != subnetId) {
                    if (!subnetId.equals(switchPort.getSwitchId())) {
                        continue;
                    }
                }
                BocloudResult<List<Ip>> achieveIps = ipService.achieveNsxIps(port.getId(), count, "V4");
                if (achieveIps.isFailed()) {
                    continue;
                }
                ips = achieveIps.getData();
                break;
            }
            if (null != router.getManagementNetwork() && router.getManagementNetwork()) {
                for (Ip ip : ips) {
                    ip.setGateway(null);
                }
            }
            return ips;
        } catch (Exception e) {
            logger.error("Get error message：{}", e.getMessage());
            return new ArrayList<>();
        }
    }

    /**
     * 分配vcenter虚拟机IP地址
     *
     * @param vendor
     * @param poolId
     * @param operations
     * @param address
     * @param assignIp
     * @return
     * @throws Exception
     */
    public BocloudResult assignVcenterIp(CloudVendor vendor, Long poolId, List<NetcardOperation> operations,
        String address, Ip assignIp) throws Exception {
        // List<Ip> ips = Lists.newArrayList();
        // for (NetcardOperation operation : operations) {
        // if (!StringUtils.isEmpty(address)) {
        // // 校验IP地址是否被占用
        // Ip ip = ipRepository.checkExist(address, null, vendor.getId());
        // if (null != ip) {
        // return new BocloudResult(false, ips, "指定的IP【" + address + "】已被使用");
        // }
        // IpPool pool = ipPoolRepository.query(poolId);
        // if (null == pool) {
        // return new BocloudResult(false, ips, "选择的IP池不存在");
        // }
        // String dns = JSONArray.parseArray(pool.getDnsNames(), String.class).get(0);
        // List<String> poolList = JSONArray.parseArray(pool.getPools(), String.class);
        // IPAddress ipAddress = IPAddress.getIPAddress(address);
        // boolean flag = ipAddress.isInPools(address, poolList);
        // if (flag) {
        // ip = new Ip(address, ipAddress.getMask(pool.getCidr()), pool.getGateway(), dns, vendor.getId(),
        // IDFactory.instance().uuid(), pool.getId());
        // ip.setCatalog("VM");
        // ipRepository.save(ip);
        // }
        // if (null == ip) {
        // return new BocloudResult(false, ips, "选择的IP池不包含【" + address + "】");
        // }
        // String version = IPAddress.getVersion(address);
        // if ("V6".equalsIgnoreCase(version)) {
        // operation.setIpv6Enabled(true);
        // operation.setIpv6(ip);
        // } else {
        // operation.setIp(ip);
        // }
        // ips.add(ip);
        // } else {
        // String version = IPAddress.getVersion(assignIp.getIp());
        // if ("V6".equalsIgnoreCase(version)) {
        // operation.setIpv6Enabled(true);
        // operation.setIpv6(assignIp);
        // } else {
        // operation.setIp(assignIp);
        // }
        // ips.add(assignIp);
        // }
        // break;
        // }
        // return new BocloudResult(true, ips, "success");
        List<Ip> ips = Lists.newArrayList();
        for (NetcardOperation operation : operations) {
            operation.setIp(JSONObject.parseObject(JSONObject.toJSONString(assignIp), IpModel.class));
            ips.add(assignIp);
            break;
        }
        return new BocloudResult(true, ips, "success");
    }

    /**
     * 分配IP到每个网卡
     *
     * @param vendor
     * @param operations
     * @return
     * @throws Exception
     */
    public BocloudResult assignIp(CloudVendor vendor, List<NetcardOperation> operations) throws Exception {
        int newNetCardNum = 0;
        List<Ip> ips = Lists.newArrayList();
        for (NetcardOperation operation : operations) {
            switch (operation.getOperation()) {
                // 新添加或编辑的网卡分配IP地址
                case "ADD":
                case "EDIT":
                    // 从nsx下网络分配IP
                    if (null != operation.getVpcId() && 0L != operation.getVpcId()) {
                        Long vpcId = operation.getVpcId();
                        BocloudResult ipResult = this.getNsxIp(ips, vpcId, operation.getSubnetId(), operation, vendor);
                        if (ipResult.isFailed()) {
                            return ipResult;
                        }
                        newNetCardNum++;
                        continue;
                    }
                    if (NetworkType.PortGroupType.VIRTUAL.name().equals(operation.getPortType())) {
                        String address = null;
                        List<String> parseArray = JSON.parseArray(operation.getAddress(), String.class);
                        if (!ListTool.isEmpty(parseArray)) {
                            address = parseArray.get(0);
                        }
                        BocloudResult<Ip> result = this.getIp(operation.getIpv4PoolId(), operation.getName(), address,
                            vendor.getId(), ips, "V4");
                        if (result.isFailed()) {
                            return new BocloudResult(false, ips, result.getMessage());
                        }
                        if (!ListTool.isEmpty(parseArray)) {
                            parseArray.remove(address);
                        }
                        operation.setAddress(JSON.toJSONString(parseArray));
                        operation
                            .setIp(JSONObject.parseObject(JSONObject.toJSONString(result.getData()), IpModel.class));
                        ips.add(result.getData());
                        if (operation.isIpv6Enabled()) {
                            String ipv6Address = null;
                            List<String> ipv6ParseArray = JSON.parseArray(operation.getIpv6Address(), String.class);
                            if (!ListTool.isEmpty(ipv6ParseArray)) {
                                ipv6Address = ipv6ParseArray.get(0);
                            }
                            result = this.getIp(operation.getIpv6PoolId(), operation.getName(), ipv6Address,
                                vendor.getId(), ips, "V6");
                            if (result.isFailed()) {
                                return new BocloudResult(false, ips, result.getMessage());
                            }
                            if (!ListTool.isEmpty(ipv6ParseArray)) {
                                ipv6ParseArray.remove(ipv6Address);
                            }
                            operation.setIpv6Address(JSON.toJSONString(ipv6ParseArray));
                            operation.setIpv6(
                                JSONObject.parseObject(JSONObject.toJSONString(result.getData()), IpModel.class));
                        }
                    } else if (NetworkType.PortGroupType.DVPORT.name().equals(operation.getPortType())) {
                        Long ciscoSubnetId = operation.getCiscoSubnetId();
                        // 从IP地址池获取IP
                        if (null == ciscoSubnetId || 0L == ciscoSubnetId) {
                            String address = null;
                            List<String> parseArray = JSON.parseArray(operation.getAddress(), String.class);
                            if (!ListTool.isEmpty(parseArray)) {
                                address = parseArray.get(0);
                            }
                            BocloudResult<Ip> result = this.getIp(operation.getIpv4PoolId(), operation.getName(),
                                address, vendor.getId(), ips, "V4");
                            if (result.isFailed()) {
                                return new BocloudResult(false, ips, result.getMessage());
                            }
                            if (!ListTool.isEmpty(parseArray)) {
                                parseArray.remove(address);
                            }
                            operation.setAddress(JSON.toJSONString(parseArray));
                            operation.setIp(
                                JSONObject.parseObject(JSONObject.toJSONString(result.getData()), IpModel.class));
                            ips.add(result.getData());
                            if (operation.isIpv6Enabled()) {
                                String ipv6Address = null;
                                List<String> ipv6ParseArray = JSON.parseArray(operation.getIpv6Address(), String.class);
                                if (!ListTool.isEmpty(ipv6ParseArray)) {
                                    ipv6Address = ipv6ParseArray.get(0);
                                }
                                result = this.getIp(operation.getIpv6PoolId(), operation.getName(), ipv6Address,
                                    vendor.getId(), ips, "V6");
                                if (result.isFailed()) {
                                    return new BocloudResult(false, ips, result.getMessage());
                                }
                                if (!ListTool.isEmpty(ipv6ParseArray)) {
                                    ipv6ParseArray.remove(ipv6Address);
                                }
                                operation.setIpv6Address(JSON.toJSONString(ipv6ParseArray));
                                operation.setIpv6(
                                    JSONObject.parseObject(JSONObject.toJSONString(result.getData()), IpModel.class));
                            }
                        }
                    }
                    newNetCardNum++;
                    break;
                default:
                    break;
            }
        }
        if (newNetCardNum == 0) {
            return new BocloudResult(false, ips, "请编辑网络设备，为机器选择IP池");
        }
        return new BocloudResult(true, ips, "success");
    }

    /**
     * 获取IP
     *
     * @param name
     * @param address
     * @param vendorId
     * @param ips
     * @param version
     * @return
     * @throws Exception
     */
    private BocloudResult<Ip> getIp(Long ipPoolId, String name, String address, Long vendorId, List<Ip> ips,
        String version) throws Exception {
        Ip assignIp = null;
        if (!StringUtils.isEmpty(address)) {
            if ("V6".equals(version)) {
                address = new IPv6Address().compress(address);
            }
            Ip ip = ipRepository.checkExist(address, null, null);
            if (null == ip || null == ip.getPoolId()) {
                return new BocloudResult<Ip>(false, "网卡名称为：【" + name + "】指定的IP不存在于IP池中");
            }
            if (ip.getStatus() != IpStatus.free) {
                return new BocloudResult<Ip>(false, "网卡名称为：【" + name + "】指定的IP已被使用或锁定");
            }
            ip.setCatalog("VM");
            ip.setStatus(IpStatus.lock);
            ipRepository.update(ip);
            assignIp = ip;
        } else {
            BocloudResult<List<Ip>> achieveIps = ipService.assginIps(ipPoolId, 1L, version);
            if (achieveIps.isFailed()) {
                return new BocloudResult<>(false, "分配IP地址失败，可能原因是剩余可用IP不足");
            }
            assignIp = achieveIps.getData().get(0);
        }
        ips.add(assignIp);
        return new BocloudResult<>(true, assignIp, "分配成功");
    }

    /**
     * 回收申请虚拟机失败的IP
     *
     * @param ips
     * @param networkBeans
     * @param vendorId
     */
    public void recycleIp(List<Ip> ips, List<NetworkBean> networkBeans, Long vendorId) {
        try {
            logger.info("Start to recovery failed IP address");
            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(), vendorId);
                    }
                }
            }
            if (!ListTool.isEmpty(ips)) {
                for (Ip ip : ips) {
                    // if (null != ip.getId() && 0L != ip.getId()) {
                    // ipRepository.delete(ip.getId());
                    // } else if (null != ip.getSubnetId()) {
                    // ipRepository.delete(ip.getIp(), ip.getSubnetId(), ip.getVendorId());
                    // } else if (null != ip.getPoolId()) {
                    // ipRepository.delete(ip.getPoolId(), ip.getIp());
                    // } else {
                    // ipRepository.delete(ip.getTarget(), "VM", vendorId);
                    // }
                    ipRepository.makeFreeById(ip.getId());
                }
            }
            logger.info("End to recovery failed IP address");
        } catch (Exception e) {
            logger.error("Get error Message:", e);
        }
    }

    /**
     * 处理虚拟机状态
     *
     * @param serverId
     * @param context
     * @param action
     * @return
     */
    public BocloudResult handleAction(Long serverId, RequestContext context, ServerAction action) {
        String path = CloudServer.class.getSimpleName() + "_" + serverId;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            CloudServer server = cloudServerRepository.get(serverId);
            Assert.notNull(server, "虚拟机不存在");
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            CloudProvider type = CloudProvider.valueOf(vendor.getType());
            switch (type) {
                case TENCENT:
                case ALIYUN:
                case AZURE:
                case KINGCLOUD:
                case QCLOUD:
                case PQCLOUD:
                case TCE:
                case AWS:
                case TIANYI:
                case H3C:
                    switch (action) {
                        case START:
                            if (server.getStatus().equals(BocloudStatus.Server.RUNNING.name())) {
                                logger.warn("CloudServer is running,can not start");
                                return new BocloudResult(false, "虚拟机正在运行中，开机失败");
                            } else if (server.getStatus().equals(BocloudStatus.Server.STARTING.name())) {
                                logger.warn("CloudServer is starting,can not start");
                                return new BocloudResult(false, "虚拟机正在开机中");
                            } else if (server.getStatus().equals(BocloudStatus.Server.EXCEPTION.name())) {
                                logger.warn("CloudServer is exception,can not start");
                                return new BocloudResult(false, "虚拟机异常，开机失败");
                            }
                            break;
                        case STOP:
                            if (server.getStatus().equals(BocloudStatus.Server.STOPPED.name())) {
                                logger.warn("CloudServer is stopped");
                                return new BocloudResult(false, "虚拟机已经关机");
                            } else if (server.getStatus().equals(BocloudStatus.Server.STOPPING.name())) {
                                logger.warn("CloudServer is stopping");
                                return new BocloudResult(false, "虚拟机正在关机中");
                            } else if (server.getStatus().equals(BocloudStatus.Server.EXCEPTION.name())) {
                                logger.warn("CloudServer is exception,can not stop");
                                return new BocloudResult(false, "虚拟机异常，关机失败");
                            }
                            break;
                        case REBOOT:
                            if (server.getStatus().equals(BocloudStatus.Server.RESTARTING.name())) {
                                logger.warn("CloudServer is restarting");
                                return new BocloudResult(false, "虚拟机正在重启中");
                            } else if (server.getStatus().equals(BocloudStatus.Server.EXCEPTION.name())) {
                                logger.warn("CloudServer is exception,can not reboot");
                                return new BocloudResult(false, "虚拟机异常，重启失败");
                            } else if (server.getStatus().equals(BocloudStatus.Server.STOPPED.name())) {
                                logger.warn("CloudServer is stopped,can not reboot");
                                return new BocloudResult(false, "虚拟机为关机状态，重启失败");
                            }
                            break;
                        default:
                            break;
                    }
                    break;
                case POWERVC:
                    JSONObject props =
                        StringUtils.isEmpty(server.getProps()) ? new JSONObject() : JSON.parseObject(server.getProps());
                    switch (action) {
                        case START:
                            props.put("taskStatus", "powering-on");
                            break;
                        case STOP:
                            props.put("taskStatus", "powering-off");
                            break;
                        case REBOOT:
                            props.put("taskStatus", "rebooting_hard");
                            break;
                        case SOFTREBOOT:
                            props.put("taskStatus", "rebooting");
                            break;
                        default:
                            break;
                    }
                    server.setProps(props.toJSONString());
                    cloudServerRepository.update(server);
                    break;
                case JDCLOUD:
                    switch (action) {
                        case START:
                            if (server.getStatus().equals(BocloudStatus.Server.RUNNING.name())) {
                                logger.warn("CloudServer is running,can not start");
                                return new BocloudResult(false, "虚拟机正在运行中，开机失败");
                            } else if (server.getStatus().equals(BocloudStatus.Server.STARTING.name())) {
                                logger.warn("CloudServer is starting,can not start");
                                return new BocloudResult(false, "虚拟机正在开机中");
                            } else if (server.getStatus().equals(BocloudStatus.Server.EXCEPTION.name())) {
                                logger.warn("CloudServer is exception,can not start");
                                return new BocloudResult(false, "虚拟机异常，开机失败");
                            }
                            break;
                        case STOP:
                            if (server.getStatus().equals(BocloudStatus.Server.STOPPED.name())) {
                                logger.warn("CloudServer is stopped");
                                return new BocloudResult(false, "虚拟机已经关机");
                            } else if (server.getStatus().equals(BocloudStatus.Server.STOPPING.name())) {
                                logger.warn("CloudServer is stopping");
                                return new BocloudResult(false, "虚拟机正在关机中");
                            } else if (server.getStatus().equals(BocloudStatus.Server.EXCEPTION.name())) {
                                logger.warn("CloudServer is exception,can not stop");
                                return new BocloudResult(false, "虚拟机异常，关机失败");
                            }
                            break;
                        case REBOOT:
                            if (server.getStatus().equals(BocloudStatus.Server.RESTARTING.name())) {
                                logger.warn("CloudServer is restarting");
                                return new BocloudResult(false, "虚拟机正在重启中");
                            } else if (server.getStatus().equals(BocloudStatus.Server.EXCEPTION.name())) {
                                logger.warn("CloudServer is exception,can not reboot");
                                return new BocloudResult(false, "虚拟机异常，重启失败");
                            } else if (server.getStatus().equals(BocloudStatus.Server.STOPPED.name())) {
                                logger.warn("CloudServer is stopped,can not reboot");
                                return new BocloudResult(false, "虚拟机为关机状态，重启失败");
                            }
                            break;
                        default:
                            break;
                    }
                    break;
                case VMWARE:
                    switch (action) {
                        case START:
                            Server host = serverRepository.query(server.getHostId());
                            Assert.notNull(host, "宿主机不存在");
                            if (null != host.getMaintained() && host.getMaintained()) {
                                return new BocloudResult(false, "该虚拟机所在宿主机处于维护模式下，无法执行开机任务");
                            }
                            break;
                        case REBOOT:
                            if (!server.getToolsInstalled()) {
                                logger.warn("CloudServer's vmwareTools not running");
                                return new BocloudResult(false, "该虚拟机没有安装VMTools，无法执行重启任务");
                            } else if (!server.getToolsRunning()) {
                                return new BocloudResult(false, "该虚拟机VMTools没有启动，无法执行重启任务");
                            } else if (server.getStatus().equals(BocloudStatus.Server.STOPPED.name())) {
                                logger.warn("CloudServer is stopped,can not reboot");
                                return new BocloudResult(false, "虚拟机为关机状态，重启失败");
                            }
                            break;
                        case PAUSE:
                            if (!server.getToolsInstalled()) {
                                logger.warn("CloudServer's vmwareTools not running");
                                return new BocloudResult(false, "该虚拟机没有安装VMTools，无法执行休眠任务");
                            }
                            break;
                        default:
                            break;
                    }
                    break;
                case OPENSTACK:
                case FUSIONCLOUD:
                    switch (action) {
                        case PAUSE:
                            if (server.getStatus().equals(BocloudStatus.Server.STOPPED.name())) {
                                logger.warn("CloudServer is stopped,can not pause");
                                return new BocloudResult(false, "虚拟机已经关闭，休眠失败");
                            } else if (server.getStatus().equals(BocloudStatus.Server.STOPPING.name())) {
                                logger.warn("CloudServer is stopping,can not pause");
                                return new BocloudResult(false, "虚拟机关闭中，休眠失败");
                            } else if (server.getStatus().equals(BocloudStatus.Server.BUILDING.name())) {
                                logger.warn("CloudServer is building,can not pause");
                                return new BocloudResult(false, "虚拟机创建中，休眠失败");
                            }
                            break;
                        case SUSPEND:
                            if (server.getStatus().equals(BocloudStatus.Server.STOPPED.name())) {
                                logger.warn("CloudServer is stopped,can not suspend");
                                return new BocloudResult(false, "虚拟机已经关闭，睡眠失败");
                            } else if (server.getStatus().equals(BocloudStatus.Server.STOPPING.name())) {
                                logger.warn("CloudServer is stopping,can not suspend");
                                return new BocloudResult(false, "虚拟机关闭中，睡眠失败");
                            } else if (server.getStatus().equals(BocloudStatus.Server.BUILDING.name())) {
                                logger.warn("CloudServer is building,can not suspend");
                                return new BocloudResult(false, "虚拟机创建中，睡眠失败");
                            }
                            break;
                        case RECOVERY:
                            if (!server.getStatus().equals(BocloudStatus.Server.PAUSED.name())) {
                                logger.warn("CloudServer is not paused,can not recovery");
                                return new BocloudResult(false, "取消休眠失败");
                            }
                            break;
                        case RESUME:
                            if (!server.getStatus().equals(BocloudStatus.Server.SUSPENDED.name())) {
                                logger.warn("CloudServer is not suspended,can not resume");
                                return new BocloudResult(false, "恢复虚拟机失败");
                            }
                            break;
                        case REBOOT:
                            if (server.getStatus().equals(BocloudStatus.Server.RESTARTING.name())) {
                                logger.warn("CloudServer is restarting");
                                return new BocloudResult(false, "虚拟机正在重启中");
                            } else if (server.getStatus().equals(BocloudStatus.Server.EXCEPTION.name())) {
                                logger.warn("CloudServer is exception,can not reboot");
                                return new BocloudResult(false, "虚拟机异常，重启失败");
                            } else if (server.getStatus().equals(BocloudStatus.Server.STOPPED.name())) {
                                logger.warn("CloudServer is stopped,can not reboot");
                                return new BocloudResult(false, "虚拟机为关机状态，重启失败");
                            }
                            break;
                        default:
                            break;
                    }

                    break;
                case HUAWEI:
                    switch (action) {
                        case PAUSE:
                            if (server.getStatus().equals(BocloudStatus.Server.STOPPED.name())) {
                                logger.warn("CloudServer is stopped,can not pause");
                                return new BocloudResult(false, "虚拟机已经关闭，休眠失败");
                            } else if (server.getStatus().equals(BocloudStatus.Server.STOPPING.name())) {
                                logger.warn("CloudServer is stopping,can not pause");
                                return new BocloudResult(false, "虚拟机关闭中，休眠失败");
                            } else if (server.getStatus().equals(BocloudStatus.Server.BUILDING.name())) {
                                logger.warn("CloudServer is building,can not pause");
                                return new BocloudResult(false, "虚拟机创建中，休眠失败");
                            }
                            break;
                        case SUSPEND:
                            if (server.getStatus().equals(BocloudStatus.Server.STOPPED.name())) {
                                logger.warn("CloudServer is stopped,can not suspend");
                                return new BocloudResult(false, "虚拟机已经关闭，睡眠失败");
                            } else if (server.getStatus().equals(BocloudStatus.Server.STOPPING.name())) {
                                logger.warn("CloudServer is stopping,can not suspend");
                                return new BocloudResult(false, "虚拟机关闭中，睡眠失败");
                            } else if (server.getStatus().equals(BocloudStatus.Server.BUILDING.name())) {
                                logger.warn("CloudServer is building,can not suspend");
                                return new BocloudResult(false, "虚拟机创建中，睡眠失败");
                            }
                            break;
                        case RECOVERY:
                            if (!server.getStatus().equals(BocloudStatus.Server.PAUSED.name())) {
                                logger.warn("CloudServer is not paused,can not recovery");
                                return new BocloudResult(false, "取消休眠失败");
                            }
                            break;
                        case RESUME:
                            if (!server.getStatus().equals(BocloudStatus.Server.SUSPENDED.name())) {
                                logger.warn("CloudServer is not suspended,can not resume");
                                return new BocloudResult(false, "恢复虚拟机失败");
                            }
                            break;
                        case REBOOT:
                            if (server.getStatus().equals(BocloudStatus.Server.RESTARTING.name())) {
                                logger.warn("CloudServer is restarting");
                                return new BocloudResult(false, "虚拟机正在重启中");
                            } else if (server.getStatus().equals(BocloudStatus.Server.EXCEPTION.name())) {
                                logger.warn("CloudServer is exception,can not reboot");
                                return new BocloudResult(false, "虚拟机异常，重启失败");
                            } else if (server.getStatus().equals(BocloudStatus.Server.STOPPED.name())) {
                                logger.warn("CloudServer is stopped,can not reboot");
                                return new BocloudResult(false, "虚拟机为关机状态，重启失败");
                            }
                            break;
                        default:
                            break;
                    }

                    break;
                case HMC:
                    HmcPartition partition = hmcPartitionRepository.getByUuid(server.getUuid());
                    if (partition == null) {
                        return new BocloudResult(false, "获取逻辑分区失败");
                    }
                    switch (action) {
                        case START:
                            // 查询上次激活的概要文件
                            HmcProfile profile = hmcProfileRepository.getActiveProfile(partition.getId());
                            if (profile == null) {
                                profile = hmcProfileRepository.getDefaultProfile(partition.getId());
                                if (profile == null) {
                                    return new BocloudResult(false, "获取概要文件失败");
                                }
                            }
                            return hmcPartitionService.powerOn(profile.getId(), context);
                        case STOP:
                            return hmcPartitionService.powerOff(partition.getId(), context);
                        case REBOOT:
                            return hmcPartitionService.restart(partition.getId(), context);
                        default:
                            return new BocloudResult(false, "HMC暂不支持此操作");
                    }
                default:
                    break;
            }
            this.serverAction(action, server, vendor, context,
                server.getRegionId() == null ? "" : server.getRegionId());
            return new BocloudResult(true, "虚拟机操作任务已下发，正在执行中……");
        } catch (Exception e) {
            logger.error("handle server fail:", e);
            return new BocloudResult(false, e.getMessage());
        }
    }

    /**
     * 云操作处理
     *
     * @param action
     * @param server
     * @param vendor
     * @param context
     * @param region
     * @throws Exception
     */
    private void serverAction(ServerAction action, CloudServer server, CloudVendor vendor, RequestContext context,
        String region) throws Exception {
        String uuid = vendor.getUuid();
        String instanceName = server.getName();
        String instanceId = server.getInstanceId();
        String oldStatus = server.getStatus();
        String status = null;
        String azureResourceGroupName = server.getAzureResourceGroupName();
        String actionName = "";
        switch (action) {
            case START:
                status = BocloudStatus.Server.STARTING.name();
                actionName = "开机";
                break;
            case STOP:
                status = BocloudStatus.Server.STOPPING.name();
                actionName = "关机";
                break;
            case REBOOT:
                status = BocloudStatus.Server.RESTARTING.name();
                actionName = "重启";
                break;
            case SOFTREBOOT:
                status = BocloudStatus.Server.SOFTRESTARTING.name();
                actionName = "软重启";
                break;
            case PAUSE:
                actionName = "暂停";
                status = BocloudStatus.Server.PAUSING.name();
                break;
            case SUSPEND:
                actionName = "挂起";
                status = BocloudStatus.Server.SUSPENDING.name();
                break;
            case RECOVERY:
                actionName = "恢复";
                status = BocloudStatus.Server.RECOVERING.name();
                break;
            case RESUME:
                actionName = "恢复";
                status = BocloudStatus.Server.ACTIVING.name();
                break;
            case DEALLOCATE:
                actionName = "解除分配";
                status = BocloudStatus.Server.DEALLOCATEING.name();
                break;
            default:
                break;
        }
        server.setStatus(status);
        cloudServerRepository.update(server);
        final String finalActionName = actionName;
        taskExecutor.submit(() -> {
            BocloudResult result = new BocloudResult(false, "暂不支持该操作");
            String state = null;
            String message = "虚拟机【" + server.getName() + "】";
            switch (action) {
                case START:
                    if (vendor.getType().equals(CloudProvider.AZURE.name())) {
                        result = serverDriver.start(instanceName, uuid, region, azureResourceGroupName);
                    } else {
                        result = serverDriver.start(instanceId, uuid, region);
                    }
                    state = BocloudStatus.Server.STARTING.name();
                    message += "启动";
                    break;
                case STOP:
                    if (vendor.getType().equals(CloudProvider.AZURE.name())) {
                        result = serverDriver.stop(instanceName, uuid, region, azureResourceGroupName);
                    } else {
                        result = serverDriver.stop(instanceId, uuid, region);
                    }
                    state = BocloudStatus.Server.STOPPING.name();
                    message += "关机";
                    break;
                case REBOOT:
                    if (vendor.getType().equals(CloudProvider.AZURE.name())) {
                        result = serverDriver.reboot(instanceName, uuid, region, azureResourceGroupName);
                    } else {
                        result = serverDriver.reboot(instanceId, uuid, region);
                    }
                    state = BocloudStatus.Server.RESTARTING.name();
                    message += "重启";
                    break;
                case DEALLOCATE:
                    if (vendor.getType().equals(CloudProvider.AZURE.name())) {
                        result = serverDriver.deallocate(instanceName, uuid, region, azureResourceGroupName);
                    }
                    state = BocloudStatus.Server.DEALLOCATEING.name();
                    message += "解除释放";
                    break;
                case SOFTREBOOT:
                    result = serverDriver.reboot(instanceId, uuid, region);
                    state = BocloudStatus.Server.SOFTRESTARTING.name();
                    message += "软重启";
                    break;
                case PAUSE:
                    result = serverDriver.pause(instanceId, uuid, region);
                    state = BocloudStatus.Server.PAUSING.name();
                    message += "停止";
                    break;
                case SUSPEND:
                    result = serverDriver.suspend(instanceId, uuid, region);
                    state = BocloudStatus.Server.SUSPENDING.name();
                    message += "挂起";
                    break;
                case RECOVERY:
                    result = serverDriver.unPause(instanceId, uuid, region);
                    state = BocloudStatus.Server.RECOVERING.name();
                    message += "恢复";
                    break;
                case RESUME:
                    result = serverDriver.resume(instanceId, uuid, region);
                    state = BocloudStatus.Server.ACTIVING.name();
                    message += "恢复";
                    break;
                default:
                    break;
            }
            String operate = vendor.getType().toLowerCase() + ".vm";
            ResourceEvent event = null;
            try {
                if (result.isSuccess()) {
                    updateStatus(region, action, vendor, server, state);
                    event = new ResourceEvent(server.getId(), finalActionName, "成功", context.getTarget(), new Date(),
                        "VM", vendor.getId(), context.getCatalog());
                } else {
                    server.setStatus(oldStatus);
                    event = new ResourceEvent(server.getId(), finalActionName, "失败", context.getTarget(), new Date(),
                        "VM", vendor.getId(), context.getCatalog());
                }
                if (CloudProvider.POWERVC.name().equals(vendor.getType())) {
                    // 更新任务状态
                    BocloudResult detailResult = serverDriver.detail(server.getInstanceId(), vendor.getUuid(), null);
                    if (detailResult.isSuccess()) {
                        ServerModel serverModel = (ServerModel)detailResult.getData();
                        server.setProps(serverModel.getProps());
                        server.setStatus(serverModel.getStatus());
                    }
                }
                if (CloudProvider.H3C.name().equals(vendor.getType())) {
                    RsDomain rsDomain = (RsDomain)result.getData();
                    server.setStatus(statusConvertor(rsDomain.getStatus()));
                }
                cloudServerRepository.update(server);
                // 更新资源表
                Resource resource = resourceRepository.query(ResourceCategory.Computer.name(),
                    ResourceCatalog.LOGICAL.name(), server.getId());
                if (null != resource) {
                    resource.setStatus(server.getStatus());
                    List<String> ips = Lists.newArrayList();
                    if (!StringUtils.isEmpty(server.getPrivateIps())) {
                        List<JSONObject> objects = Lists.newArrayList();
                        switch (CloudProvider.valueOf(server.getVendorType())) {
                            case OPENSTACK:
                                objects = JSONObject.parseArray(server.getPrivateIps(), JSONObject.class);
                                for (JSONObject object : objects) {
                                    List<Object> addresses = object.getJSONArray("addresses");
                                    for (Object address : addresses) {
                                        if (StringUtils.isEmpty(JSONObject.parseObject(JSONObject.toJSONString(address))
                                            .getString("address"))) {
                                            continue;
                                        }
                                        ips.add(JSONObject.parseObject(JSONObject.toJSONString(address))
                                            .getString("address"));
                                    }
                                }
                                break;
                            case VMWARE:
                                objects = JSONObject.parseArray(server.getPrivateIps(), JSONObject.class);
                                for (JSONObject object : objects) {
                                    String address = object.getString("address");
                                    if (!StringUtils.isEmpty(address)) {
                                        ips.add(address);
                                    }
                                }
                                break;
                            case JDCLOUD:
                                ips.add(server.getPrivateIps());
                                break;
                            case HUAWEI:
                                if (!StringUtils.isEmpty(server.getPrivateIps())) {
                                    objects = JSONObject.parseArray(server.getPrivateIps(), JSONObject.class);
                                    for (JSONObject object : objects) {
                                        String address = (String)object.get("address");
                                        ips.add(address);
                                    }
                                }
                                break;
                            case TENCENT:
                                if (!StringUtils.isEmpty(server.getPrivateIps())) {
                                    List<String> tencentIps =
                                        JSONObject.parseArray(server.getPrivateIps(), String.class);
                                    for (String ip : tencentIps) {
                                        ips.add(ip);
                                    }
                                }
                                break;
                            case ALIYUN:

                                break;
                            case AZURE:
                                if (!StringUtils.isEmpty(server.getPrivateIps())) {
                                    List<String> azureIps = JSONObject.parseArray(server.getPrivateIps(), String.class);
                                    for (String ip : azureIps) {
                                        ips.add(ip);
                                    }
                                }
                                break;
                            case TCE:
                                if (!StringUtils.isEmpty(server.getPrivateIps())) {
                                    List<String> tceIps = JSONObject.parseArray(server.getPrivateIps(), String.class);
                                    for (String ip : tceIps) {
                                        ips.add(ip);
                                    }
                                }
                                break;
                            case AWS:
                                if (!StringUtils.isEmpty(server.getPrivateIps())) {
                                    List<String> awsIps = JSONObject.parseArray(server.getPrivateIps(), String.class);
                                    for (String ip : awsIps) {
                                        ips.add(ip);
                                    }
                                }
                                break;
                            case H3C:
                                resource.setStatus(server.getStatus());
                                List<String> h3cIps = Lists.newArrayList();
                                if (!StringUtils.isEmpty(server.getPrivateIps())) {
                                    List<JSONObject> h3cObjects =
                                        JSONObject.parseArray(server.getPrivateIps(), JSONObject.class);
                                    if (!ListTool.isEmpty(h3cObjects)) {
                                        for (JSONObject ipObject : objects) {
                                            ips.add(ipObject.getString("address"));
                                        }
                                    }
                                }
                                break;
                            default:
                                break;
                        }
                    }
                    resource.setPrivateIps(JSONObject.toJSONString(ips));
                    resource.setMenderId(context.getTarget());
                    resourceRepository.update(resource);
                }
                resourceEventRepository.save(event);
                if (CloudProvider.POWERVC.name().equals(vendor.getType())) {
                    message = result.isSuccess() ? message + "成功" : message + "失败：" + result.getMessage();
                } else {
                    message = result.isSuccess() ? message + "成功" : message + "失败：" + result.getMessage();
                }
                resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                    MapTools.simpleMap(Common.VENDORID, vendor.getId()), OPERATE_CATEGORY, context));
                if (result.isFailed()) {
                    logger.error(message + "：" + result.getMessage());
                }
            } catch (Exception e) {
                logger.error("update status failure:", e);
                resourceEventPublisher.send(new OperateResult(false, "虚拟机操作失败", operate,
                    MapTools.simpleMap(Common.VENDORID, vendor.getId()), OPERATE_CATEGORY, context));
            }
        });
    }

    // 虚拟机状态。 2：运行 3：关闭 4：暂停。
    public String statusConvertor(Integer statusNum) {
        String status = BocloudStatus.Server.EXCEPTION.name();
        switch (statusNum) {
            case 1:
            case 2:
                status = BocloudStatus.Server.RUNNING.name();
                break;
            case 0:
            case 3:
                status = BocloudStatus.Server.STOPPED.name();
                break;
            case 4:
                status = BocloudStatus.Server.PAUSED.name();
                break;
            default:
                break;
        }
        return status;
    }

    /**
     * 更新状态
     *
     * @param region
     * @param action
     * @param vendor
     * @param server
     * @param status
     * @throws Exception
     */
    private void updateStatus(String region, ServerAction action, CloudVendor vendor, CloudServer server, String status)
        throws Exception {
        String type = vendor.getType();
        Long start = System.currentTimeMillis();
        boolean running = true;
        Long timeout = 1000 * 60 * 10L;
        while (running) {
            BocloudResult result = null;
            // azure 虚拟机如果停止后在启动后，状态正常，但数据延迟查不到
            if (type.equals(CloudProvider.AZURE.name()) && action == ServerAction.START) {
                Thread.sleep(30000L);
            }
            result = serverDriver.detail(server.getInstanceId(), vendor.getUuid(), region);
            // 超时和延时
            if (System.currentTimeMillis() - start > timeout) {
                server.setStatus(BocloudStatus.Server.EXCEPTION.name());
                running = false;
            }
            if (result.isSuccess()) {
                VMBean bean = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), VMBean.class);
                if (!bean.getInstanceId().equals(server.getInstanceId())) {
                    continue;
                }
                if (type.equals(CloudProvider.ALIYUN.name()) || type.equals(CloudProvider.TENCENT.name())
                    || type.equals(CloudProvider.QCLOUD.name()) || type.equals(CloudProvider.JDCLOUD.name())
                    || type.equals(CloudProvider.TCE.name()) || type.equals(CloudProvider.PQCLOUD.name())
                    || type.equals(CloudProvider.AWS.name()) || type.equals(CloudProvider.TIANYI.name())) {
                    switch (action) {
                        case START:
                            if ("Running".equalsIgnoreCase(bean.getStatus())) {
                                server.setStatus(BocloudStatus.Server.RUNNING.name());
                            }
                            break;
                        case STOP:
                            if ("Stopped".equalsIgnoreCase(bean.getStatus())) {
                                server.setStatus(BocloudStatus.Server.STOPPED.name());
                            }
                            break;
                        case REBOOT:
                            if ("Running".equalsIgnoreCase(bean.getStatus())) {
                                server.setStatus(BocloudStatus.Server.RUNNING.name());
                            }
                            break;
                        case DEALLOCATE:
                            if ("DEALLOCATE".equalsIgnoreCase(bean.getStatus())) {
                                server.setStatus(BocloudStatus.Server.DEALLOCATE.name());
                            }
                            break;
                        default:
                            break;
                    }
                } else if (type.equals(CloudProvider.OPENSTACK.name()) || type.equals(CloudProvider.FUSIONCLOUD.name())
                    || type.equals(CloudProvider.MANAGEONE.name()) || type.equals(CloudProvider.HUAWEI.name())) {
                    // 如果虚拟机为错误状态，则直接返回
                    if (bean.getStatus().equalsIgnoreCase(BocloudStatus.Server.ERROR.name())) {
                        server.setStatus(BocloudStatus.Server.EXCEPTION.name());
                        server.setHostName(bean.getHostName());
                        running = false;
                        break;
                    }
                    switch (action) {
                        case START:
                            if (bean.getStatus().equalsIgnoreCase(BocloudStatus.Server.RUNNING.name())) {
                                server.setStatus(BocloudStatus.Server.RUNNING.name());
                                server.setHostName(bean.getHostName());
                                server.setManagerIp(bean.getManagerIp());
                            }
                            break;
                        case STOP:
                            if (bean.getStatus().equalsIgnoreCase(BocloudStatus.Server.STOPPED.name())) {
                                server.setStatus(BocloudStatus.Server.STOPPED.name());
                                server.setHostName(bean.getHostName());
                            }
                            break;
                        case PAUSE:
                            if (bean.getStatus().equalsIgnoreCase(BocloudStatus.Server.PAUSED.name())) {
                                server.setStatus(BocloudStatus.Server.PAUSED.name());
                                server.setHostName(bean.getHostName());
                            }
                            break;
                        case RECOVERY:
                            if (bean.getStatus().equalsIgnoreCase(BocloudStatus.Server.RUNNING.name())) {
                                server.setStatus(BocloudStatus.Server.RUNNING.name());
                                server.setHostName(bean.getHostName());
                            }
                            break;
                        case RESUME:
                            if (bean.getStatus().equalsIgnoreCase(BocloudStatus.Server.RUNNING.name())) {
                                server.setStatus(BocloudStatus.Server.RUNNING.name());
                                server.setHostName(bean.getHostName());
                            }
                            break;
                        case SUSPEND:
                            if (bean.getStatus().equalsIgnoreCase(BocloudStatus.Server.SUSPENDED.name())) {
                                server.setStatus(BocloudStatus.Server.SUSPENDED.name());
                                server.setHostName(bean.getHostName());
                            }
                            break;
                        case REBOOT:
                            if (bean.getStatus().equalsIgnoreCase(BocloudStatus.Server.RUNNING.name())) {
                                server.setStatus(BocloudStatus.Server.RUNNING.name());
                                server.setHostName(bean.getHostName());
                            }
                            break;
                        case SOFTREBOOT:
                            if (bean.getStatus().equalsIgnoreCase(BocloudStatus.Server.RUNNING.name())) {
                                server.setStatus(BocloudStatus.Server.RUNNING.name());
                                server.setHostName(bean.getHostName());
                            }
                            break;
                        default:
                            break;
                    }
                } else if (type.equals(CloudProvider.VMWARE.name())) {
                    switch (action) {
                        case START:
                            if ("poweredOn".equalsIgnoreCase(bean.getStatus())) {
                                server.setPrivateIps(bean.getPrivateIps());
                                server.setManagerIp(bean.getManagerIp());
                                server.setStatus(BocloudStatus.Server.RUNNING.name());
                                if (null != server.getToolsRunning() && null != server.getToolsInstalled()
                                    && server.getToolsInstalled() && !server.getToolsRunning()) {
                                    server.setToolsRunning(true);
                                }
                            }
                            break;
                        case STOP:
                            if ("poweredOff".equalsIgnoreCase(bean.getStatus())) {
                                server.setStatus(BocloudStatus.Server.STOPPED.name());
                                if (null != server.getToolsRunning() && null != server.getToolsInstalled()
                                    && server.getToolsInstalled() && server.getToolsRunning()) {
                                    server.setToolsRunning(false);
                                }
                            }
                            break;
                        case REBOOT:
                            if ("poweredOn".equalsIgnoreCase(bean.getStatus())) {
                                server.setStatus(BocloudStatus.Server.RUNNING.name());
                            }
                            break;
                        case SUSPEND:
                        case PAUSE:
                            if ("suspended".equalsIgnoreCase(bean.getStatus())) {
                                server.setStatus(BocloudStatus.Server.SUSPENDED.name());
                            }
                            break;
                        default:
                            break;
                    }
                } else if (type.equals(CloudProvider.POWERVC.name())) {
                    switch (action) {
                        case START:
                            if ("Running".equalsIgnoreCase(bean.getStatus())) {
                                server.setStatus(BocloudStatus.Server.RUNNING.name());
                            }
                            break;
                        case STOP:
                            if ("Stopped".equalsIgnoreCase(bean.getStatus())) {
                                server.setStatus(BocloudStatus.Server.STOPPED.name());
                            }
                            break;
                        case REBOOT:
                            if ("Running".equalsIgnoreCase(bean.getStatus())) {
                                server.setStatus(BocloudStatus.Server.RUNNING.name());
                            }
                            break;
                        default:
                            break;
                    }
                    JSONObject props =
                        StringUtils.isEmpty(server.getProps()) ? new JSONObject() : JSON.parseObject(server.getProps());
                    props.remove("taskStatus");
                    server.setProps(props.toJSONString());
                } else if (type.equals(CloudProvider.AZURE.name())) {
                    switch (action) {
                        case START:
                            if ("Running".equalsIgnoreCase(bean.getStatus())) {
                                server.setStatus(BocloudStatus.Server.RUNNING.name());
                                server.setPublicIps(bean.getPublicIps());
                                server.setPrivateIps(bean.getPrivateIps());
                                server.setDisk(bean.getDisk());
                                server.setOsName(bean.getOsName());
                                server.setOsVersion(bean.getOsVersion());
                                server.setSystemDiskSize(bean.getSystemDiskSize());
                                server.setSystemDiskCategory(bean.getSystemDiskCategory());
                            }
                            break;
                        case STOP:
                            if ("Stopped".equalsIgnoreCase(bean.getStatus())) {
                                server.setStatus(BocloudStatus.Server.STOPPED.name());
                            }
                            break;
                        case REBOOT:
                            if ("Running".equalsIgnoreCase(bean.getStatus())) {
                                server.setStatus(BocloudStatus.Server.RUNNING.name());
                            }
                            break;
                        case DEALLOCATE:
                            if ("DEALLOCATE".equalsIgnoreCase(bean.getStatus())) {
                                server.setStatus(BocloudStatus.Server.DEALLOCATE.name());
                                server.setPublicIps(bean.getPublicIps());
                                server.setPrivateIps(bean.getPrivateIps());
                                server.setDisk(bean.getDisk());
                                server.setOsName(bean.getOsName());
                                server.setOsVersion(bean.getOsVersion());
                                server.setSystemDiskSize(bean.getSystemDiskSize());
                                server.setSystemDiskCategory(bean.getSystemDiskCategory());
                            }
                            break;
                        default:
                            break;
                    }
                }
                if (!server.getStatus().equalsIgnoreCase(status)) {
                    running = false;
                }
                Thread.sleep(3000L);
            } else {
                server.setStatus(BocloudStatus.Server.EXCEPTION.name());
                running = false;
            }
        }
    }

    /**
     * 获取虚拟机的内网IP
     *
     * @param server
     * @param vendor
     * @return
     * @throws Exception
     */
    public String getPrivateIps(CloudServer server, CloudVendor vendor) throws Exception {
        // 更新内网IP
        String privateIps = null;
        // 设置内网IP
        List<NetworkBean> newNetBeans = Lists.newArrayList();
        // key networkUuid
        Map<String, List<Port>> portMap = Maps.newHashMap();
        List<Port> newPorts = portRepository.listByDeviceId(server.getInstanceId(), vendor.getId());
        if (!ListTool.isEmpty(newPorts)) {
            for (Port port : newPorts) {
                port.setPortFixedIps(portFixedIpRepository.listByPortUuid(port.getPortUuid()));
                if (portMap.containsKey(port.getNetworkUuid())) {
                    List<Port> list = portMap.get(port.getNetworkUuid());
                    list.add(port);
                } else {
                    List<Port> list = Lists.newArrayList();
                    list.add(port);
                    portMap.put(port.getNetworkUuid(), list);
                }
            }
        }
        for (String key : portMap.keySet()) {
            List<Port> portList = portMap.get(key);
            if (ListTool.isEmpty(portList)) {
                continue;
            }
            Network network = networkRepository.getByNetId(key);
            if (null == network) {
                continue;
            }
            NetworkBean networkBean = new NetworkBean(network.getId(), network.getName(), network.getNetworkUuid());
            List<AddressBean> addresses = Lists.newArrayList();
            for (Port port : portList) {
                List<PortFixedIp> portFixedIps = port.getPortFixedIps();
                if (ListTool.isEmpty(portFixedIps)) {
                    continue;
                }
                for (PortFixedIp portFixedIp : portFixedIps) {
                    Subnet subnet = subnetRepository.getBySubId(portFixedIp.getSubnetUuid());
                    if (null != subnet) {
                        AddressBean address = new AddressBean(subnet.getId(), subnet.getName(), network.getId(),
                            subnet.getSubnetUuid(), port.getId(), port.getPortUuid(), portFixedIp.getIpAddress());
                        address.setQosPolicyUuid(port.getQosPolicyUuid());
                        address.setMaxKbps(port.getMaxKbps());
                        addresses.add(address);
                    }
                }
            }
            networkBean.setAddresses(addresses);
            if (!ListTool.isEmpty(addresses)) {
                newNetBeans.add(networkBean);
            }
        }
        if (!ListTool.isEmpty(newNetBeans)) {
            privateIps = JSONObject.toJSONString(newNetBeans);
        }
        return privateIps;
    }

    /**
     * 同步新虚拟机下的各对象信息
     *
     * @param vdcId
     * @param vendorId
     * @param datastores
     * @param networks
     * @throws Exception
     */
    public void syncSubObject(Long vdcId, Long vendorId, Long serverId, List<String> datastores, List<Network> networks,
        List<NetworkCard> cards, Long userId) throws Exception {
        // 数据中心的存储信息
        Map<String, DataStore> storeMap = new HashMap<>(8);
        List<DataStore> stores = dataStoreRepository.listByVdc(vdcId);
        for (DataStore store : stores) {
            storeMap.put(store.getStoreVal(), store);
        }
        // 数据中心的网络信息
        Map<String, Network> networkMap = Maps.newHashMap();
        Map<String, String> groupMap = Maps.newHashMap();
        List<Network> oldNetworks = networkRepository.listByVdc(vdcId);
        for (Network network : oldNetworks) {
            networkMap.put(network.getNetworkVal(), network);
        }
        List<Switcher> switchers = switcherRepository.listByVdc(vdcId, "DVSWITCH");
        for (Switcher switcher : switchers) {
            List<PortGroup> groups = portGroupRepository.listBySwitcher(switcher.getId());
            for (PortGroup group : groups) {
                groupMap.put(group.getGroupVal(), switcher.getSwitcherVal());
            }
        }
        SyncVmwareUtils utils = new SyncVmwareUtils(dataStoreRepository, serverRepository, networkRepository,
            storeHostRepository, networkCardRepository, portGroupRepository, networkHostRepository);
        // 同步存储
        logger.info("Start to sync store......");
        utils.addStore(vendorId, serverId, userId, "VM", datastores, storeMap);
        logger.info("End to sync store......");
        // 同步网络
        logger.info("Start to sync network......");
        utils.addNetwork(vendorId, serverId, userId, "VM", networks, networkMap, groupMap);
        logger.info("End to sync network......");
        // 同步网卡
        logger.info("Start to sync network card......");
        utils.addCard(vendorId, serverId, userId, "VM", cards, Maps.newHashMap());
        logger.info("End to sync network card......");
    }

    /**
     * 更新资源表
     *
     * @param cloudServer
     * @param vendor
     * @param context
     * @throws Exception
     */
    public void updateResource(CloudServer cloudServer, CloudVendor vendor, RequestContext context) throws Exception {
        Resource resource = resourceRepository.queryByTargetId(cloudServer.getId());
        List<String> ips = Lists.newArrayList();
        List<JSONObject> objects = Lists.newArrayList();
        switch (CloudProvider.valueOf(cloudServer.getVendorType())) {
            case OPENSTACK:
                if (!StringUtils.isEmpty(cloudServer.getPrivateIps())) {
                    objects = JSONObject.parseArray(cloudServer.getPrivateIps(), JSONObject.class);
                    for (JSONObject object : objects) {
                        List<Object> addresses = object.getJSONArray("addresses");
                        for (Object address : addresses) {
                            if (StringUtils.isEmpty(
                                JSONObject.parseObject(JSONObject.toJSONString(address)).getString("address"))) {
                                continue;
                            }
                            ips.add(JSONObject.parseObject(JSONObject.toJSONString(address)).getString("address"));
                        }
                    }
                }
                break;
            case VMWARE:
                if (!StringUtils.isEmpty(cloudServer.getPrivateIps())) {
                    objects = JSONObject.parseArray(cloudServer.getPrivateIps(), JSONObject.class);
                    for (JSONObject object : objects) {
                        String address = object.getString("address");
                        if (StringUtils.isEmpty(address)) {
                            continue;
                        }
                        ips.add(address);
                    }
                }
                break;
            case JDCLOUD:
                if (!StringUtils.isEmpty(cloudServer.getPrivateIps())) {
                    ips.add(cloudServer.getPrivateIps());
                }
                break;
            case ALIYUN:
                break;
            default:
                break;
        }
        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(), context.getTarget(), context.getTenant(),
                context.getProject());
            resource.setInventory(JSONObject.toJSONString(cloudServer));
            resourceRepository.save(resource);
        } else {
            resource.setName(cloudServer.getName());
            resource.setStatus(cloudServer.getStatus());
            resource.setGmtModify(new Date());
            resource.setMenderId(context.getTarget());
            resource.setPrivateIps(JSONObject.toJSONString(ips));
            resource.setInventory(JSONObject.toJSONString(cloudServer));
            resource.setOsCategory(cloudServer.getOsCategory());
            resourceRepository.update(resource);
        }
    }

    public Resource syncOsVResource(Long vendorId, CloudServer server, Long userId) throws Exception {
        List<String> ips = Lists.newArrayList();
        if (!StringUtils.isEmpty(server.getPrivateIps())) {
            List<JSONObject> objects = JSONObject.parseArray(server.getPrivateIps(), JSONObject.class);
            for (JSONObject jsonObject : objects) {
                List<Object> addresses = jsonObject.getJSONArray("addresses");
                for (Object address : addresses) {
                    if (StringUtils
                        .isEmpty(JSONObject.parseObject(JSONObject.toJSONString(address)).getString("address"))) {
                        continue;
                    }
                    ips.add(JSONObject.parseObject(JSONObject.toJSONString(address)).getString("address"));
                }
            }
        }
        // 设置浮动IP
        FloatingIp floatingIp = floatingIpRepository.listByServerId(server.getInstanceId());
        if (null != floatingIp) {
            ips.add(floatingIp.getFloatingIpAddress());
        }
        Resource resource =
            resourceRepository.query(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(), server.getId());
        if (null != resource) {
            resource.setStatus(server.getStatus());
            resource.setPrivateIps(JSONObject.toJSONString(ips));
            resource.setMenderId(userId);
            resourceRepository.update(resource);
        } else {
            resource = new Resource(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(), server.getId(),
                JSONObject.toJSONString(ips), server.getOsCategory(), vendorId);
            resource.preSave(server.getName(), server.getStatus(), userId, 0L, 0L);
            resource.setInventory(JSONObject.toJSONString(server));
            resourceRepository.save(resource);
        }
        return resource;
    }

    /**
     * 根据命名规则生成虚拟机名称
     *
     * @param nameRuleId
     * @param vendorId
     * @param context
     * @return
     * @throws Exception
     */
    public String generateName(Long nameRuleId, Long vendorId, RequestContext context) throws Exception {
        JSONObject params = new JSONObject();
        params.put("userId", context.getTarget());
        params.put("tenantId", context.getTenant());
        params.put("projectId", context.getProject());
        String name = null;
        while (true) {
            BocloudResult result = nameRuleService.generate(nameRuleId, params);
            if (result.isFailed()) {
                break;
            }
            name = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), String.class);
            if (StringUtils.isEmpty(name)) {
                break;
            }
            // 校验命名规则生成的名称是否已经存在，如果已存在，则重新获取命名
            boolean existsflag = cloudServerRepository.exists(name, vendorId);
            if (!existsflag) {
                break;
            }
        }
        return name;
    }

}
