github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/provider/vsphere/instance.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  // +build !gccgo
     5  
     6  package vsphere
     7  
     8  import (
     9  	"github.com/juju/errors"
    10  	"github.com/juju/govmomi/vim25/mo"
    11  
    12  	"github.com/juju/juju/instance"
    13  	"github.com/juju/juju/network"
    14  )
    15  
    16  type environInstance struct {
    17  	base *mo.VirtualMachine
    18  	env  *environ
    19  }
    20  
    21  var _ instance.Instance = (*environInstance)(nil)
    22  
    23  func newInstance(base *mo.VirtualMachine, env *environ) *environInstance {
    24  	return &environInstance{
    25  		base: base,
    26  		env:  env,
    27  	}
    28  }
    29  
    30  // Id implements instance.Instance.
    31  func (inst *environInstance) Id() instance.Id {
    32  	return instance.Id(inst.base.Name)
    33  }
    34  
    35  // Status implements instance.Instance.
    36  func (inst *environInstance) Status() string {
    37  	//return inst.base.Status()
    38  	return ""
    39  }
    40  
    41  // Addresses implements instance.Instance.
    42  func (inst *environInstance) Addresses() ([]network.Address, error) {
    43  	if inst.base.Guest == nil || inst.base.Guest.IpAddress == "" {
    44  		return nil, nil
    45  	}
    46  	res := make([]network.Address, 0)
    47  	for _, net := range inst.base.Guest.Net {
    48  		for _, ip := range net.IpAddress {
    49  			scope := network.ScopeCloudLocal
    50  			if net.Network == inst.env.ecfg.externalNetwork() {
    51  				scope = network.ScopePublic
    52  			}
    53  			res = append(res, network.NewScopedAddress(ip, scope))
    54  		}
    55  	}
    56  	return res, nil
    57  }
    58  
    59  func findInst(id instance.Id, instances []instance.Instance) instance.Instance {
    60  	for _, inst := range instances {
    61  		if id == inst.Id() {
    62  			return inst
    63  		}
    64  	}
    65  	return nil
    66  }
    67  
    68  // firewall stuff
    69  
    70  // OpenPorts opens the given ports on the instance, which
    71  // should have been started with the given machine id.
    72  func (inst *environInstance) OpenPorts(machineID string, ports []network.PortRange) error {
    73  	return inst.changePorts(true, ports)
    74  }
    75  
    76  // ClosePorts closes the given ports on the instance, which
    77  // should have been started with the given machine id.
    78  func (inst *environInstance) ClosePorts(machineID string, ports []network.PortRange) error {
    79  	return inst.changePorts(false, ports)
    80  }
    81  
    82  // Ports returns the set of ports open on the instance, which
    83  // should have been started with the given machine id.
    84  func (inst *environInstance) Ports(machineID string) ([]network.PortRange, error) {
    85  	_, sshClient, err := inst.getSshClient()
    86  	if err != nil {
    87  		return nil, errors.Trace(err)
    88  	}
    89  	return sshClient.findOpenPorts()
    90  }
    91  
    92  func (inst *environInstance) changePorts(insert bool, ports []network.PortRange) error {
    93  	if inst.env.ecfg.externalNetwork() == "" {
    94  		return errors.New("Can't close/open ports without external network")
    95  	}
    96  	addresses, sshClient, err := inst.getSshClient()
    97  	if err != nil {
    98  		return errors.Trace(err)
    99  	}
   100  
   101  	for _, addr := range addresses {
   102  		if addr.Scope == network.ScopePublic {
   103  			err = sshClient.changePorts(addr.Value, insert, ports)
   104  			if err != nil {
   105  				return errors.Trace(err)
   106  			}
   107  		}
   108  	}
   109  	return nil
   110  }
   111  
   112  func (inst *environInstance) getSshClient() ([]network.Address, *sshClient, error) {
   113  	addresses, err := inst.Addresses()
   114  	if err != nil {
   115  		return nil, nil, errors.Trace(err)
   116  	}
   117  
   118  	var localAddr string
   119  	for _, addr := range addresses {
   120  		if addr.Scope == network.ScopeCloudLocal {
   121  			localAddr = addr.Value
   122  			break
   123  		}
   124  	}
   125  
   126  	client := newSshClient(localAddr)
   127  	return addresses, client, err
   128  }