github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/provider/vsphere/instance.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package vsphere 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/vmware/govmomi/vim25/mo" 9 "github.com/vmware/govmomi/vim25/types" 10 11 "github.com/juju/juju/core/instance" 12 corenetwork "github.com/juju/juju/core/network" 13 "github.com/juju/juju/core/network/firewall" 14 "github.com/juju/juju/core/status" 15 "github.com/juju/juju/environs/context" 16 "github.com/juju/juju/environs/instances" 17 "github.com/juju/juju/provider/common" 18 ) 19 20 type environInstance struct { 21 base *mo.VirtualMachine 22 env *environ 23 } 24 25 var _ instances.Instance = (*environInstance)(nil) 26 27 func newInstance(base *mo.VirtualMachine, env *environ) *environInstance { 28 return &environInstance{ 29 base: base, 30 env: env, 31 } 32 } 33 34 // Id implements instances.Instance. 35 func (inst *environInstance) Id() instance.Id { 36 return instance.Id(inst.base.Name) 37 } 38 39 // Status implements instances.Instance. 40 func (inst *environInstance) Status(ctx context.ProviderCallContext) instance.Status { 41 instanceStatus := instance.Status{ 42 Status: status.Empty, 43 Message: string(inst.base.Runtime.PowerState), 44 } 45 switch inst.base.Runtime.PowerState { 46 case types.VirtualMachinePowerStatePoweredOn: 47 instanceStatus.Status = status.Running 48 } 49 return instanceStatus 50 } 51 52 // Addresses implements instances.Instance. 53 func (inst *environInstance) Addresses(ctx context.ProviderCallContext) (corenetwork.ProviderAddresses, error) { 54 if inst.base.Guest == nil { 55 return nil, nil 56 } 57 res := make([]corenetwork.ProviderAddress, 0, len(inst.base.Guest.Net)) 58 for _, net := range inst.base.Guest.Net { 59 for _, ip := range net.IpAddress { 60 res = append(res, corenetwork.NewMachineAddress(ip).AsProviderAddress()) 61 } 62 } 63 return res, nil 64 } 65 66 // firewall stuff 67 68 // OpenPorts opens the given ports on the instance, which 69 // should have been started with the given machine id. 70 func (inst *environInstance) OpenPorts(ctx context.ProviderCallContext, machineID string, rules firewall.IngressRules) error { 71 return inst.changeIngressRules(ctx, true, rules) 72 } 73 74 // ClosePorts closes the given ports on the instance, which 75 // should have been started with the given machine id. 76 func (inst *environInstance) ClosePorts(ctx context.ProviderCallContext, machineID string, rules firewall.IngressRules) error { 77 return inst.changeIngressRules(ctx, false, rules) 78 } 79 80 // IngressRules returns the set of ports open on the instance, which 81 // should have been started with the given machine id. 82 func (inst *environInstance) IngressRules(ctx context.ProviderCallContext, machineID string) (firewall.IngressRules, error) { 83 _, client, err := inst.getInstanceConfigurator(ctx) 84 if err != nil { 85 return nil, errors.Trace(err) 86 } 87 return client.FindIngressRules() 88 } 89 90 func (inst *environInstance) changeIngressRules(ctx context.ProviderCallContext, insert bool, rules firewall.IngressRules) error { 91 if inst.env.ecfg.externalNetwork() == "" { 92 // Open/Close port without an externalNetwork defined is treated as a no-op. 93 // We don't firewall the internal network, and without an external network we don't have any iptables rules 94 // to define. 95 logger.Warningf("ingress rules changing without an external network defined, no changes will be made") 96 return nil 97 } 98 addresses, client, err := inst.getInstanceConfigurator(ctx) 99 if err != nil { 100 return errors.Trace(err) 101 } 102 103 for _, addr := range addresses { 104 if addr.Type == corenetwork.IPv6Address || addr.Scope != corenetwork.ScopePublic { 105 // TODO(axw) support firewalling IPv6 106 continue 107 } 108 if err := client.ChangeIngressRules(addr.Value, insert, rules); err != nil { 109 return errors.Trace(err) 110 } 111 } 112 return nil 113 } 114 115 func (inst *environInstance) getInstanceConfigurator( 116 ctx context.ProviderCallContext, 117 ) ([]corenetwork.ProviderAddress, common.InstanceConfigurator, error) { 118 addresses, err := inst.Addresses(ctx) 119 if err != nil { 120 return nil, nil, errors.Trace(err) 121 } 122 123 var localAddr string 124 for _, addr := range addresses { 125 if addr.Scope == corenetwork.ScopeCloudLocal { 126 localAddr = addr.Value 127 break 128 } 129 } 130 131 client := common.NewSshInstanceConfigurator(localAddr) 132 return addresses, client, err 133 }