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  }