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