// nextSecurityRulePriority returns the next available priority in the given // security group within a specified range. func nextSecurityRulePriority(group network.SecurityGroup, min, max int32) (int32, error) { if group.Properties.SecurityRules == nil { return min, nil } for p := min; p <= max; p++ { var found bool for _, rule := range *group.Properties.SecurityRules { if to.Int32(rule.Properties.Priority) == p { found = true break } } if !found { return p, nil } } return -1, errors.Errorf( "no priorities available in the range [%d, %d]", min, max, ) }
func nextAvailableLUN(vm *compute.VirtualMachine) (int32, error) { // Pick the smallest LUN not in use. We have to choose them in order, // or the disks don't show up. var inUse [32]bool if vm.Properties.StorageProfile.DataDisks != nil { for _, disk := range *vm.Properties.StorageProfile.DataDisks { lun := to.Int32(disk.Lun) if lun < 0 || lun > 31 { logger.Debugf("ignore disk with invalid LUN: %+v", disk) continue } inUse[lun] = true } } for i, inUse := range inUse { if !inUse { return int32(i), nil } } return -1, errors.New("all LUNs are in use") }
// Ports is specified in the Instance interface. func (inst *azureInstance) Ports(machineId string) (ports []jujunetwork.PortRange, err error) { nsgClient := network.SecurityGroupsClient{inst.env.network} securityGroupName := internalSecurityGroupName var nsg network.SecurityGroup if err := inst.env.callAPI(func() (autorest.Response, error) { var err error nsg, err = nsgClient.Get(inst.env.resourceGroup, securityGroupName, "") return nsg.Response, err }); err != nil { return nil, errors.Annotate(err, "querying network security group") } if nsg.Properties.SecurityRules == nil { return nil, nil } vmName := resourceName(names.NewMachineTag(machineId)) prefix := instanceNetworkSecurityRulePrefix(instance.Id(vmName)) for _, rule := range *nsg.Properties.SecurityRules { if rule.Properties.Direction != network.Inbound { continue } if rule.Properties.Access != network.Allow { continue } if to.Int32(rule.Properties.Priority) <= securityRuleInternalMax { continue } if !strings.HasPrefix(to.String(rule.Name), prefix) { continue } var portRange jujunetwork.PortRange if *rule.Properties.DestinationPortRange == "*" { portRange.FromPort = 0 portRange.ToPort = 65535 } else { portRange, err = jujunetwork.ParsePortRange( *rule.Properties.DestinationPortRange, ) if err != nil { return nil, errors.Annotatef( err, "parsing port range for security rule %q", to.String(rule.Name), ) } } var protocols []string switch rule.Properties.Protocol { case network.TCP: protocols = []string{"tcp"} case network.UDP: protocols = []string{"udp"} default: protocols = []string{"tcp", "udp"} } for _, protocol := range protocols { portRange.Protocol = protocol ports = append(ports, portRange) } } return ports, nil }
func (v *azureVolumeSource) attachVolume( vm *compute.VirtualMachine, p storage.VolumeAttachmentParams, storageAccount *armstorage.Account, ) (_ *storage.VolumeAttachment, updated bool, _ error) { storageAccount, err := v.env.getStorageAccount(false) if err != nil { return nil, false, errors.Trace(err) } dataDisksRoot := dataDiskVhdRoot(storageAccount) dataDiskName := p.VolumeId vhdURI := dataDisksRoot + dataDiskName + vhdExtension var dataDisks []compute.DataDisk if vm.Properties.StorageProfile.DataDisks != nil { dataDisks = *vm.Properties.StorageProfile.DataDisks } for _, disk := range dataDisks { if to.String(disk.Name) != p.VolumeId { continue } if to.String(disk.Vhd.URI) != vhdURI { continue } // Disk is already attached. volumeAttachment := &storage.VolumeAttachment{ p.Volume, p.Machine, storage.VolumeAttachmentInfo{ BusAddress: diskBusAddress(to.Int32(disk.Lun)), }, } return volumeAttachment, false, nil } lun, err := nextAvailableLUN(vm) if err != nil { return nil, false, errors.Annotate(err, "choosing LUN") } dataDisk := compute.DataDisk{ Lun: to.Int32Ptr(lun), Name: to.StringPtr(dataDiskName), Vhd: &compute.VirtualHardDisk{to.StringPtr(vhdURI)}, Caching: compute.ReadWrite, CreateOption: compute.Attach, } dataDisks = append(dataDisks, dataDisk) vm.Properties.StorageProfile.DataDisks = &dataDisks volumeAttachment := storage.VolumeAttachment{ p.Volume, p.Machine, storage.VolumeAttachmentInfo{ BusAddress: diskBusAddress(lun), }, } return &volumeAttachment, true, nil }
// newInstanceType creates an InstanceType based on a VirtualMachineSize. func newInstanceType(size compute.VirtualMachineSize) instances.InstanceType { // We're not doing real costs for now; just made-up, relative // costs, to ensure we choose the right VMs given matching // constraints. This was based on the pricing for West US, // and assumes that all regions have the same relative costs. // // DS is the same price as D, but is targeted at Premium Storage. // Likewise for GS and G. We put the premium storage variants // directly after their non-premium counterparts. machineSizeCost := []string{ "Standard_A0", "Standard_A1", "Standard_D1", "Standard_DS1", "Standard_D1_v2", "Standard_A2", "Standard_D2", "Standard_DS2", "Standard_D2_v2", "Standard_D11", "Standard_DS11", "Standard_D11_v2", "Standard_A3", "Standard_D3", "Standard_DS3", "Standard_D3_v2", "Standard_D12", "Standard_DS12", "Standard_D12_v2", "Standard_A5", // Yes, A5 is cheaper than A4. "Standard_A4", "Standard_A6", "Standard_G1", "Standard_GS1", "Standard_D4", "Standard_DS4", "Standard_D4_v2", "Standard_D13", "Standard_DS13", "Standard_D13_v2", "Standard_A7", "Standard_A10", "Standard_G2", "Standard_GS2", "Standard_D5_v2", "Standard_D14", "Standard_DS14", "Standard_D14_v2", "Standard_A8", "Standard_A11", "Standard_G3", "Standard_GS3", "Standard_A9", "Standard_G4", "Standard_GS4", "Standard_GS5", "Standard_G5", // Basic instances are less capable than standard // ones, so we don't want to be providing them as // a default. This is achieved by costing them at // a higher price, even though they are cheaper // in reality. "Basic_A0", "Basic_A1", "Basic_A2", "Basic_A3", "Basic_A4", } // Anything not in the list is more expensive that is in the list. cost := len(machineSizeCost) sizeName := to.String(size.Name) for i, name := range machineSizeCost { if sizeName == name { cost = i break } } if cost == len(machineSizeCost) { logger.Debugf("found unknown VM size %q", sizeName) } vtype := "Hyper-V" return instances.InstanceType{ Id: sizeName, Name: sizeName, Arches: []string{arch.AMD64}, CpuCores: uint64(to.Int32(size.NumberOfCores)), Mem: uint64(to.Int32(size.MemoryInMB)), // NOTE(axw) size.OsDiskSizeInMB is the *maximum* // OS-disk size. When we create a VM, we can create // one that is smaller. RootDisk: mbToMib(uint64(to.Int32(size.OsDiskSizeInMB))), Cost: uint64(cost), VirtType: &vtype, // tags are not currently supported by azure } }