示例#1
0
        public NetworkInterface(Asm.VirtualMachine virtualMachine, Asm.NetworkInterface networkInterface, List <VirtualNetwork> virtualNetworks, List <NetworkSecurityGroup> networkSecurityGroups, TargetSettings targetSettings)
        {
            _SourceNetworkInterface = networkInterface;
            this.SetTargetName(networkInterface.Name, targetSettings);
            this.IsPrimary          = networkInterface.IsPrimary;
            this.EnableIPForwarding = networkInterface.EnableIpForwarding;

            foreach (Asm.NetworkInterfaceIpConfiguration asmNetworkInterfaceIpConfiguration in networkInterface.NetworkInterfaceIpConfigurations)
            {
                NetworkInterfaceIpConfiguration migrationNetworkInterfaceIpConfiguration = new NetworkInterfaceIpConfiguration(asmNetworkInterfaceIpConfiguration, virtualNetworks, targetSettings);
                this.TargetNetworkInterfaceIpConfigurations.Add(migrationNetworkInterfaceIpConfiguration);
            }

            if (virtualMachine.NetworkSecurityGroup != null)
            {
                this.NetworkSecurityGroup = NetworkSecurityGroup.SeekNetworkSecurityGroup(networkSecurityGroups, virtualMachine.NetworkSecurityGroup.ToString());
            }
        }
示例#2
0
        public NetworkInterface(AzureContext azureContext, Arm.NetworkInterface networkInterface, List <VirtualNetwork> virtualNetworks, List <NetworkSecurityGroup> networkSecurityGroups)
        {
            _AzureContext           = azureContext;
            _SourceNetworkInterface = networkInterface;
            this.TargetName         = networkInterface.Name;
            this.IsPrimary          = networkInterface.IsPrimary;

            foreach (Arm.NetworkInterfaceIpConfiguration armNetworkInterfaceIpConfiguration in networkInterface.NetworkInterfaceIpConfigurations)
            {
                MigrationTarget.NetworkInterfaceIpConfiguration targetNetworkInterfaceIpConfiguration = new NetworkInterfaceIpConfiguration(azureContext, armNetworkInterfaceIpConfiguration, virtualNetworks);
                this.TargetNetworkInterfaceIpConfigurations.Add(targetNetworkInterfaceIpConfiguration);
            }

            if (networkInterface.NetworkSecurityGroup != null)
            {
                this.NetworkSecurityGroup = NetworkSecurityGroup.SeekNetworkSecurityGroup(networkSecurityGroups, networkInterface.NetworkSecurityGroup.ToString());
            }
        }
示例#3
0
        public NetworkInterface(AzureContext azureContext, Asm.VirtualMachine virtualMachine, Asm.NetworkInterface networkInterface, List <VirtualNetwork> virtualNetworks, List <NetworkSecurityGroup> networkSecurityGroups)
        {
            _AzureContext           = azureContext;
            _SourceNetworkInterface = networkInterface;
            this.TargetName         = networkInterface.Name;
            this.IsPrimary          = networkInterface.IsPrimary;

            foreach (Asm.NetworkInterfaceIpConfiguration asmNetworkInterfaceIpConfiguration in networkInterface.NetworkInterfaceIpConfigurations)
            {
                Azure.MigrationTarget.NetworkInterfaceIpConfiguration migrationNetworkInterfaceIpConfiguration = new Azure.MigrationTarget.NetworkInterfaceIpConfiguration(_AzureContext, asmNetworkInterfaceIpConfiguration, virtualNetworks);
                this.TargetNetworkInterfaceIpConfigurations.Add(migrationNetworkInterfaceIpConfiguration);
            }

            if (virtualMachine.NetworkSecurityGroup != null)
            {
                this.NetworkSecurityGroup = NetworkSecurityGroup.SeekNetworkSecurityGroup(networkSecurityGroups, virtualMachine.NetworkSecurityGroup.ToString());
            }
        }
示例#4
0
        public NetworkInterface(Arm.NetworkInterface networkInterface, List <MigrationTarget.VirtualNetwork> armVirtualNetworks, List <MigrationTarget.NetworkSecurityGroup> armNetworkSecurityGroups, TargetSettings targetSettings)
        {
            _SourceNetworkInterface = networkInterface;
            this.SetTargetName(networkInterface.Name, targetSettings);
            this.IsPrimary          = networkInterface.IsPrimary;
            this.EnableIPForwarding = networkInterface.EnableIPForwarding;

            foreach (Arm.NetworkInterfaceIpConfiguration armNetworkInterfaceIpConfiguration in networkInterface.NetworkInterfaceIpConfigurations)
            {
                NetworkInterfaceIpConfiguration targetNetworkInterfaceIpConfiguration = new NetworkInterfaceIpConfiguration(armNetworkInterfaceIpConfiguration, armVirtualNetworks, targetSettings);
                this.TargetNetworkInterfaceIpConfigurations.Add(targetNetworkInterfaceIpConfiguration);
            }

            if (networkInterface.NetworkSecurityGroup != null)
            {
                this.NetworkSecurityGroup = NetworkSecurityGroup.SeekNetworkSecurityGroup(armNetworkSecurityGroups, networkInterface.NetworkSecurityGroup.ToString());
            }
        }
示例#5
0
        public NetworkInterface(AzureContext azureContext, Arm.NetworkInterface networkInterface)
        {
            _AzureContext           = azureContext;
            _SourceNetworkInterface = networkInterface;

            this.TargetName         = networkInterface.Name;
            this.IsPrimary          = networkInterface.IsPrimary;
            this.EnableIPForwarding = networkInterface.EnableIPForwarding;

            foreach (Arm.NetworkInterfaceIpConfiguration armNetworkInterfaceIpConfiguration in networkInterface.NetworkInterfaceIpConfigurations)
            {
                MigrationTarget.NetworkInterfaceIpConfiguration targetNetworkInterfaceIpConfiguration = new NetworkInterfaceIpConfiguration(azureContext, armNetworkInterfaceIpConfiguration, azureContext.AzureRetriever.ArmTargetVirtualNetworks);
                this.TargetNetworkInterfaceIpConfigurations.Add(targetNetworkInterfaceIpConfiguration);
            }

            if (networkInterface.NetworkSecurityGroup != null)
            {
                this.NetworkSecurityGroup = NetworkSecurityGroup.SeekNetworkSecurityGroup(azureContext.AzureRetriever.ArmTargetNetworkSecurityGroups, networkInterface.NetworkSecurityGroup.ToString());
            }
        }
示例#6
0
        public async Task ValidateAzureResources()
        {
            Alerts.Clear();

            if (this.TargetSubscription == null)
            {
                this.AddAlert(AlertType.Error, "Target Azure Subscription must be provided for template generation.", this.ResourceGroup);
            }
            else
            {
                if (this.TargetSubscription.Locations == null || this.TargetSubscription.Locations.Count() == 0)
                {
                    this.AddAlert(AlertType.Error, "Target Azure Subscription must have one or more Locations instantiated.", this.ResourceGroup);
                }
            }

            if (this.ResourceGroup == null)
            {
                this.AddAlert(AlertType.Error, "Target Resource Group must be provided for template generation.", this.ResourceGroup);
            }
            else
            {
                if (this.ResourceGroup.TargetLocation == null)
                {
                    this.AddAlert(AlertType.Error, "Target Resource Group Location must be provided for template generation.", this.ResourceGroup);
                }
                else
                {
                    // It is possible that the Target Location is no longer in the Target Subscription
                    // Sample case, user first connected to Azure Commercial as source (and set as initial target)
                    // but then logged into a different account for the target and target is now USGov.
                    if (this.TargetSubscription != null && this.TargetSubscription.Locations != null)
                    {
                        if (!this.TargetSubscription.Locations.Contains(this.ResourceGroup.TargetLocation))
                        {
                            this.AddAlert(AlertType.Error, "Target Resource Group Location '" + this.ResourceGroup.TargetLocation.ToString() + "' is not available in Subscription '" + this.TargetSubscription.ToString() + "'.  Select a new Target Location.", this.ResourceGroup);
                        }
                    }
                }
            }

            foreach (MigrationTarget.StorageAccount targetStorageAccount in this.StorageAccounts)
            {
                await targetStorageAccount.CheckNameAvailability(this.TargetSubscription);

                if (!targetStorageAccount.IsNameAvailable)
                {
                    this.AddAlert(AlertType.Error, "Target Name for Storage Account '" + targetStorageAccount.ToString() + "' already exists within Azure Environment " + this.TargetSubscription.AzureEnvironment.ToString() + ".  A new (available) target name must be specified.", targetStorageAccount);
                }

                if (targetStorageAccount.BlobStorageNamespace == null || targetStorageAccount.BlobStorageNamespace.Trim().Length <= 0)
                {
                    this.AddAlert(AlertType.Error, "Blob Storage Namespace for Target Storage Account '" + targetStorageAccount.ToString() + "' must be specified.", targetStorageAccount);
                }

                if (!this.IsStorageAccountVmDiskTarget(targetStorageAccount))
                {
                    this.AddAlert(AlertType.Warning, "Target Storage Account '" + targetStorageAccount.ToString() + "' is not utilized within this Resource Group Deployment as a Virtual Machine Disk Target.  Consider removing to avoid creation of a non-utilized Storage Account.", targetStorageAccount);
                }
            }

            foreach (MigrationTarget.VirtualNetwork targetVirtualNetwork in this.VirtualNetworks)
            {
                foreach (MigrationTarget.Subnet targetSubnet in targetVirtualNetwork.TargetSubnets)
                {
                    if (targetSubnet.NetworkSecurityGroup != null)
                    {
                        MigrationTarget.NetworkSecurityGroup networkSecurityGroupInMigration = this.SeekNetworkSecurityGroup(targetSubnet.NetworkSecurityGroup.ToString());

                        if (networkSecurityGroupInMigration == null)
                        {
                            this.AddAlert(AlertType.Error, "Virtual Network '" + targetVirtualNetwork.ToString() + "' Subnet '" + targetSubnet.ToString() + "' utilizes Network Security Group (NSG) '" + targetSubnet.NetworkSecurityGroup.ToString() + "', but the NSG resource is not added into the migration template.", targetSubnet);
                        }
                    }
                }
            }

            foreach (MigrationTarget.NetworkSecurityGroup targetNetworkSecurityGroup in this.NetworkSecurityGroups)
            {
                if (targetNetworkSecurityGroup.TargetName == string.Empty)
                {
                    this.AddAlert(AlertType.Error, "Target Name for Network Security Group must be specified.", targetNetworkSecurityGroup);
                }
            }

            foreach (MigrationTarget.LoadBalancer targetLoadBalancer in this.LoadBalancers)
            {
                if (targetLoadBalancer.TargetName == string.Empty)
                {
                    this.AddAlert(AlertType.Error, "Target Name for Load Balancer must be specified.", targetLoadBalancer);
                }

                if (targetLoadBalancer.FrontEndIpConfigurations.Count == 0)
                {
                    this.AddAlert(AlertType.Error, "Load Balancer must have a FrontEndIpConfiguration.", targetLoadBalancer);
                }
                else
                {
                    if (targetLoadBalancer.LoadBalancerType == MigrationTarget.LoadBalancerType.Internal)
                    {
                        if (targetLoadBalancer.FrontEndIpConfigurations.Count > 0)
                        {
                            if (targetLoadBalancer.FrontEndIpConfigurations[0].TargetSubnet == null)
                            {
                                this.AddAlert(AlertType.Error, "Internal Load Balancer must have an internal Subnet association.", targetLoadBalancer);
                            }
                            else
                            {
                                // russell
                                if (targetLoadBalancer.FrontEndIpConfigurations[0].TargetPrivateIPAllocationMethod == IPAllocationMethodEnum.Static)
                                {
                                    if (!IPv4CIDR.IsIpAddressInAddressPrefix(targetLoadBalancer.FrontEndIpConfigurations[0].TargetSubnet.AddressPrefix, targetLoadBalancer.FrontEndIpConfigurations[0].TargetPrivateIpAddress))
                                    {
                                        this.AddAlert(AlertType.Error, "Load Balancer '" + targetLoadBalancer.ToString() + "' IP Address '" + targetLoadBalancer.FrontEndIpConfigurations[0].TargetPrivateIpAddress + "' is not valid within Subnet '" + targetLoadBalancer.FrontEndIpConfigurations[0].TargetSubnet.ToString() + "' Address Prefix '" + targetLoadBalancer.FrontEndIpConfigurations[0].TargetSubnet.AddressPrefix + "'.", targetLoadBalancer);
                                    }
                                    else
                                    {
                                        if (targetLoadBalancer.FrontEndIpConfigurations[0].TargetVirtualNetwork != null &&
                                            targetLoadBalancer.FrontEndIpConfigurations[0].TargetVirtualNetwork.GetType() == typeof(Azure.Arm.VirtualNetwork) &&
                                            IPv4CIDR.IsValidIpAddress(targetLoadBalancer.FrontEndIpConfigurations[0].TargetPrivateIpAddress) // Only worth passing to Azure for Availability validation if the IP address is valid.
                                            )
                                        {
                                            Arm.VirtualNetwork armVirtualNetwork = (Arm.VirtualNetwork)targetLoadBalancer.FrontEndIpConfigurations[0].TargetVirtualNetwork;
                                            (bool isAvailable, List <String> availableIps) = await armVirtualNetwork.IsIpAddressAvailable(targetLoadBalancer.FrontEndIpConfigurations[0].TargetPrivateIpAddress);

                                            if (!isAvailable)
                                            {
                                                this.AddAlert(AlertType.Error, "Load Balancer '" + targetLoadBalancer.ToString() + "' IP Address '" + targetLoadBalancer.FrontEndIpConfigurations[0].TargetPrivateIpAddress + "' is not available within Virtual Network '" + targetLoadBalancer.FrontEndIpConfigurations[0].TargetVirtualNetwork.ToString() + "'.", targetLoadBalancer);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        if (targetLoadBalancer.FrontEndIpConfigurations[0].PublicIp == null)
                        {
                            this.AddAlert(AlertType.Error, "Public Load Balancer must have either a Public IP association.", targetLoadBalancer);
                        }
                        else
                        {
                            // Ensure the selected Public IP Address is "in the migration" as a target new Public IP Object
                            bool publicIpExistsInMigration = false;
                            foreach (Azure.MigrationTarget.PublicIp publicIp in this.PublicIPs)
                            {
                                if (publicIp.TargetName == targetLoadBalancer.FrontEndIpConfigurations[0].PublicIp.TargetName)
                                {
                                    publicIpExistsInMigration = true;
                                    break;
                                }
                            }

                            if (!publicIpExistsInMigration)
                            {
                                this.AddAlert(AlertType.Error, "Public IP '" + targetLoadBalancer.FrontEndIpConfigurations[0].PublicIp.TargetName + "' specified for Load Balancer '" + targetLoadBalancer.ToString() + "' is not included in the migration template.", targetLoadBalancer);
                            }
                        }
                    }
                }
            }

            foreach (Azure.MigrationTarget.AvailabilitySet availablitySet in this.AvailablitySets)
            {
                if (availablitySet.TargetVirtualMachines.Count == 0)
                {
                    this.AddAlert(AlertType.Error, "Availability Set '" + availablitySet.ToString() + "' does not contain any Virtual Machines.  Remove the Availability Set from the Target Resources for export or associate Virtual Machines to the Availability Set.", availablitySet);
                }
                else if (availablitySet.TargetVirtualMachines.Count == 1)
                {
                    this.AddAlert(AlertType.Warning, "Availability Set '" + availablitySet.ToString() + "' only contains a single VM.  Only utilize an Availability Set if additional VMs will be added; otherwise, a single VM instance should not reside within an Availability Set.", availablitySet);
                }

                if (!availablitySet.IsManagedDisks && !availablitySet.IsUnmanagedDisks)
                {
                    this.AddAlert(AlertType.Error, "All OS and Data Disks for Virtual Machines contained within Availablity Set '" + availablitySet.ToString() + "' should be either Unmanaged Disks or Managed Disks for consistent deployment.", availablitySet);
                }
            }

            foreach (Azure.MigrationTarget.VirtualMachine virtualMachine in this.VirtualMachines)
            {
                if (virtualMachine.TargetName == string.Empty)
                {
                    this.AddAlert(AlertType.Error, "Target Name for Virtual Machine '" + virtualMachine.ToString() + "' must be specified.", virtualMachine);
                }

                if (virtualMachine.TargetAvailabilitySet == null)
                {
                    if (virtualMachine.OSVirtualHardDisk.TargetStorage != null && virtualMachine.OSVirtualHardDisk.TargetStorage.StorageAccountType != StorageAccountType.Premium_LRS)
                    {
                        this.AddAlert(AlertType.Warning, "Virtual Machine '" + virtualMachine.ToString() + "' is not part of an Availability Set.  OS Disk should be migrated to Azure Premium Storage to receive an Azure SLA for single server deployments.  Existing configuration will receive no (0%) Service Level Agreement (SLA).", virtualMachine.OSVirtualHardDisk);
                    }

                    foreach (Azure.MigrationTarget.Disk dataDisk in virtualMachine.DataDisks)
                    {
                        if (dataDisk.TargetStorage != null && dataDisk.TargetStorage.StorageAccountType != StorageAccountType.Premium_LRS)
                        {
                            this.AddAlert(AlertType.Warning, "Virtual Machine '" + virtualMachine.ToString() + "' is not part of an Availability Set.  Data Disk '" + dataDisk.ToString() + "' should be migrated to Azure Premium Storage to receive an Azure SLA for single server deployments.  Existing configuration will receive no (0%) Service Level Agreement (SLA).", dataDisk);
                        }
                    }
                }
                else
                {
                    bool virtualMachineAvailabitySetExists = false;
                    foreach (MigrationTarget.AvailabilitySet targetAvailabilitySet in this.AvailablitySets)
                    {
                        if (targetAvailabilitySet.ToString() == virtualMachine.TargetAvailabilitySet.ToString())
                        {
                            virtualMachineAvailabitySetExists = true;
                        }
                    }

                    if (!virtualMachineAvailabitySetExists)
                    {
                        this.AddAlert(AlertType.Error, "Virtual Machine '" + virtualMachine.ToString() + "' utilizes Availability Set '" + virtualMachine.TargetAvailabilitySet.ToString() + "'; however, the Availability Set is not included in the Export.", virtualMachine);
                    }
                }

                if (virtualMachine.TargetSize == null)
                {
                    this.AddAlert(AlertType.Error, "Target Size for Virtual Machine '" + virtualMachine.ToString() + "' must be specified.", virtualMachine);
                }
                else
                {
                    // Ensure that the selected target size is available in the target Azure Location
                    if (this.ResourceGroup != null && this.ResourceGroup.TargetLocation != null)
                    {
                        if (this.ResourceGroup.TargetLocation.VMSizes == null || this.ResourceGroup.TargetLocation.VMSizes.Count == 0)
                        {
                            this.AddAlert(AlertType.Error, "No ARM VM Sizes are available for Azure Location '" + this.ResourceGroup.TargetLocation.DisplayName + "'.", virtualMachine);
                        }
                        else
                        {
                            // Ensure selected target VM Size is available in the Target Azure Location
                            Arm.VMSize matchedVmSize = this.ResourceGroup.TargetLocation.SeekVmSize(virtualMachine.TargetSize.Name);
                            if (matchedVmSize == null)
                            {
                                this.AddAlert(AlertType.Error, "Specified VM Size '" + virtualMachine.TargetSize.Name + "' for Virtual Machine '" + virtualMachine.ToString() + "' is invalid as it is not available in Azure Location '" + this.ResourceGroup.TargetLocation.DisplayName + "'.", virtualMachine);
                            }
                        }
                    }

                    if (virtualMachine.OSVirtualHardDisk.TargetStorage.StorageAccountType == StorageAccountType.Premium_LRS && !virtualMachine.TargetSize.IsStorageTypeSupported(virtualMachine.OSVirtualHardDisk.StorageAccountType))
                    {
                        this.AddAlert(AlertType.Error, "Premium Disk based Virtual Machines must be of VM Series 'B', 'DS', 'DS v2', 'DS v3', 'GS', 'GS v2', 'Ls' or 'Fs'.", virtualMachine);
                    }
                }

                foreach (Azure.MigrationTarget.NetworkInterface networkInterface in virtualMachine.NetworkInterfaces)
                {
                    // Seek the inclusion of the Network Interface in the export object
                    bool networkInterfaceExistsInExport = false;
                    foreach (Azure.MigrationTarget.NetworkInterface targetNetworkInterface in this.NetworkInterfaces)
                    {
                        if (String.Compare(networkInterface.SourceName, targetNetworkInterface.SourceName, true) == 0)
                        {
                            networkInterfaceExistsInExport = true;
                            break;
                        }
                    }

                    if (!networkInterfaceExistsInExport)
                    {
                        this.AddAlert(AlertType.Error, "Network Interface Card (NIC) '" + networkInterface.ToString() + "' is used by Virtual Machine '" + virtualMachine.ToString() + "', but is not included in the exported resources.", virtualMachine);
                    }

                    if (virtualMachine.TargetSize != null)
                    {
                        if (networkInterface.EnableAcceleratedNetworking && !virtualMachine.TargetSize.IsAcceleratedNetworkingSupported)
                        {
                            this.AddAlert(AlertType.Error, "Network Interface Card (NIC) '" + networkInterface.ToString() + "' has Accelerated Networking enabled, but the Virtual Machine must be of VM Series 'D', 'DSv2', 'DSv3', 'E', 'ESv3', 'F', 'FS', 'FSv2', 'Ms' or 'Mms' to support Accelerated Networking.", networkInterface);
                        }
                        else if (!networkInterface.EnableAcceleratedNetworking && virtualMachine.TargetSize.IsAcceleratedNetworkingSupported)
                        {
                            this.AddAlert(AlertType.Recommendation, "Network Interface Card (NIC) '" + networkInterface.ToString() + "' has Accelerated Networking disabled and the Virtual Machine Size '" + virtualMachine.TargetSize.ToString() + "' can support Accelerated Networking.  Consider enabling Accelerated Networking.", networkInterface);
                        }
                    }

                    if (networkInterface.NetworkSecurityGroup != null)
                    {
                        MigrationTarget.NetworkSecurityGroup networkSecurityGroupInMigration = this.SeekNetworkSecurityGroup(networkInterface.NetworkSecurityGroup.ToString());

                        if (networkSecurityGroupInMigration == null)
                        {
                            this.AddAlert(AlertType.Error, "Network Interface Card (NIC) '" + networkInterface.ToString() + "' utilizes Network Security Group (NSG) '" + networkInterface.NetworkSecurityGroup.ToString() + "', but the NSG resource is not added into the migration template.", networkInterface);
                        }
                    }

                    foreach (Azure.MigrationTarget.NetworkInterfaceIpConfiguration ipConfiguration in networkInterface.TargetNetworkInterfaceIpConfigurations)
                    {
                        if (ipConfiguration.TargetVirtualNetwork == null)
                        {
                            this.AddAlert(AlertType.Error, "Target Virtual Network for Virtual Machine '" + virtualMachine.ToString() + "' Network Interface '" + networkInterface.ToString() + "' must be specified.", networkInterface);
                        }
                        else
                        {
                            if (ipConfiguration.TargetVirtualNetwork.GetType() == typeof(MigrationTarget.VirtualNetwork))
                            {
                                MigrationTarget.VirtualNetwork virtualMachineTargetVirtualNetwork = (MigrationTarget.VirtualNetwork)ipConfiguration.TargetVirtualNetwork;
                                bool targetVNetExists = false;

                                foreach (MigrationTarget.VirtualNetwork targetVirtualNetwork in this.VirtualNetworks)
                                {
                                    if (targetVirtualNetwork.TargetName == virtualMachineTargetVirtualNetwork.TargetName)
                                    {
                                        targetVNetExists = true;
                                        break;
                                    }
                                }

                                if (!targetVNetExists)
                                {
                                    this.AddAlert(AlertType.Error, "Target Virtual Network '" + virtualMachineTargetVirtualNetwork.ToString() + "' for Virtual Machine '" + virtualMachine.ToString() + "' Network Interface '" + networkInterface.ToString() + "' is invalid, as it is not included in the migration / template.  Either include the source Virtual Network in the Migration Template (if this is the first time migration needing a new ARM Virtual Network), or select an existing ARM Virtual Network and Subnet to migrate the Virtual Machine into.", networkInterface);
                                }
                            }
                        }

                        if (ipConfiguration.TargetSubnet == null)
                        {
                            this.AddAlert(AlertType.Error, "Target Subnet for Virtual Machine '" + virtualMachine.ToString() + "' Network Interface '" + networkInterface.ToString() + "' must be specified.", networkInterface);
                        }
                        else
                        {
                            if (!IPv4CIDR.IsValidCIDR(ipConfiguration.TargetSubnet.AddressPrefix))
                            {
                                this.AddAlert(AlertType.Error, "Target Subnet '" + ipConfiguration.TargetSubnet.ToString() + "' used by Virtual Machine '" + virtualMachine.ToString() + "' has an invalid IPv4 Address Prefix: " + ipConfiguration.TargetSubnet.AddressPrefix, ipConfiguration.TargetSubnet);
                            }
                            else
                            {
                                if (ipConfiguration.TargetPrivateIPAllocationMethod == IPAllocationMethodEnum.Static)
                                {
                                    if (!IPv4CIDR.IsIpAddressInAddressPrefix(ipConfiguration.TargetSubnet.AddressPrefix, ipConfiguration.TargetPrivateIpAddress))
                                    {
                                        this.AddAlert(AlertType.Error, "Target IP Address '" + ipConfiguration.TargetPrivateIpAddress + "' is not valid in Subnet '" + ipConfiguration.TargetSubnet.ToString() + "' Address Prefix '" + ipConfiguration.TargetSubnet.AddressPrefix + "'.", networkInterface);
                                    }
                                }
                            }
                        }

                        if (ipConfiguration.TargetPublicIp != null)
                        {
                            MigrationTarget.PublicIp publicIpInMigration = this.SeekPublicIp(ipConfiguration.TargetPublicIp.ToString());

                            if (publicIpInMigration == null)
                            {
                                this.AddAlert(AlertType.Error, "Network Interface Card (NIC) '" + networkInterface.ToString() + "' IP Configuration '" + ipConfiguration.ToString() + "' utilizes Public IP '" + ipConfiguration.TargetPublicIp.ToString() + "', but the Public IP resource is not added into the migration template.", networkInterface);
                            }
                        }
                    }
                }

                ValidateVMDisk(virtualMachine.OSVirtualHardDisk);
                foreach (MigrationTarget.Disk dataDisk in virtualMachine.DataDisks)
                {
                    ValidateVMDisk(dataDisk);

                    if (!dataDisk.Lun.HasValue || dataDisk.Lun.Value == -1)
                    {
                        this.AddAlert(AlertType.Error, "Data Disk '" + dataDisk.ToString() + "' must have a valid LUN Index assigned.", dataDisk);
                    }
                    else
                    {
                        if (dataDisk.Lun > virtualMachine.TargetSize.maxDataDiskCount - 1)
                        {
                            this.AddAlert(AlertType.Error, "Data Disk '" + dataDisk.ToString() + "' LUN index " + dataDisk.Lun.Value.ToString() + " exceeds the maximum LUN of " + (virtualMachine.TargetSize.maxDataDiskCount - 1).ToString() + " allowed by VM Size '" + virtualMachine.TargetSize.ToString() + "'.", dataDisk);
                        }

                        int lunCount = virtualMachine.DataDisks.Where(a => a.Lun == dataDisk.Lun).Count();
                        if (lunCount > 1)
                        {
                            this.AddAlert(AlertType.Error, "Multiple data disks are assigned to LUN " + dataDisk.Lun.ToString() + " on Virtual Machine '" + virtualMachine.ToString() + "'.  Data Disk LUNs must be unique.", dataDisk);
                        }
                    }
                }

                if (!virtualMachine.IsManagedDisks && !virtualMachine.IsUnmanagedDisks)
                {
                    this.AddAlert(AlertType.Error, "All OS and Data Disks for Virtual Machine '" + virtualMachine.ToString() + "' should be either Unmanaged Disks or Managed Disks for consistent deployment.", virtualMachine);
                }
            }

            foreach (Azure.MigrationTarget.Disk targetDisk in this.Disks)
            {
                ValidateDiskStandards(targetDisk);
            }

            // todo now asap - Add test for NSGs being present in Migration
            //MigrationTarget.NetworkSecurityGroup targetNetworkSecurityGroup = (MigrationTarget.NetworkSecurityGroup)this.SeekNetworkSecurityGroup(targetSubnet.NetworkSecurityGroup.ToString());
            //if (targetNetworkSecurityGroup == null)
            //{
            //    this.AddAlert(AlertType.Error, "Subnet '" + subnet.name + "' utilized ASM Network Security Group (NSG) '" + targetSubnet.NetworkSecurityGroup.ToString() + "', which has not been added to the ARM Subnet as the NSG was not included in the ARM Template (was not selected as an included resources for export).", targetNetworkSecurityGroup);
            //}

            // todo add error if existing target disk storage is not in the same data center / region as vm.

            if (AfterResourceValidation != null)
            {
                await AfterResourceValidation.Invoke();
            }
        }