1
// Copyright 2013 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
11
"github.com/juju/loggo"
13
"launchpad.net/juju-core/environs"
14
"launchpad.net/juju-core/environs/config"
17
// Register the Azure provider with Juju.
19
environs.RegisterProvider("azure", azureEnvironProvider{})
22
// Logger for the Azure provider.
23
var logger = loggo.GetLogger("juju.provider.azure")
25
type azureEnvironProvider struct{}
27
// azureEnvironProvider implements EnvironProvider.
28
var _ environs.EnvironProvider = (*azureEnvironProvider)(nil)
30
// Open is specified in the EnvironProvider interface.
31
func (prov azureEnvironProvider) Open(cfg *config.Config) (environs.Environ, error) {
32
logger.Debugf("opening environment %q.", cfg.Name())
33
// We can't return NewEnviron(cfg) directly here because otherwise,
34
// when err is not nil, we end up with a non-nil returned environ and
35
// this breaks the loop in cmd/jujud/upgrade.go:run() (see
36
// http://golang.org/doc/faq#nil_error for the gory details).
37
environ, err := NewEnviron(cfg)
44
// Prepare is specified in the EnvironProvider interface.
45
func (prov azureEnvironProvider) Prepare(ctx environs.BootstrapContext, cfg *config.Config) (environs.Environ, error) {
46
// TODO prepare environment as necessary
50
// PublicAddress is specified in the EnvironProvider interface.
51
func (prov azureEnvironProvider) PublicAddress() (string, error) {
52
config, err := parseWALAConfig()
54
logger.Errorf("error parsing Windows Azure Linux Agent config file (%q): %v", _WALAConfigPath, err)
57
return config.getDeploymentFQDN(), nil
60
// PrivateAddress is specified in the EnvironProvider interface.
61
func (prov azureEnvironProvider) PrivateAddress() (string, error) {
62
config, err := parseWALAConfig()
64
logger.Errorf("error parsing Windows Azure Linux Agent config file (%q): %v", _WALAConfigPath, err)
67
return config.getInternalIP(), nil
70
// The XML Windows Azure Linux Agent (WALA) is the agent which runs on all
71
// the Linux Azure VMs. The hostname of the VM is the service name and the
72
// juju instanceId is (by design), the deployment's name.
74
// See https://github.com/windows-azure/walinuxagent for more details.
76
// Here is an example content of such a config file:
77
// <?xml version="1.0" encoding="utf-8"?>
78
// <SharedConfig version="1.0.0.0" goalStateIncarnation="1">
79
// <Deployment name="b6de4c4c7d4a49c39270e0c57481fd9b" guid="{495985a8-8e5a-49aa-826f-d1f7f51045b6}" incarnation="0">
80
// <Service name="gwaclmachineex95rsek" guid="{00000000-0000-0000-0000-000000000000}" />
81
// <ServiceInstance name="b6de4c4c7d4a49c39270e0c57481fd9b.0" guid="{9806cac7-e566-42b8-9ecb-de8da8f69893}" />
84
// <Instance id="gwaclroleldc1o5p" address="10.76.200.59">
91
// Structures used to parse the XML Windows Azure Linux Agent (WALA)
92
// configuration file.
94
type WALASharedConfig struct {
95
XMLName xml.Name `xml:"SharedConfig"`
96
Deployment WALADeployment `xml:"Deployment"`
97
Instances []WALAInstance `xml:"Instances>Instance"`
100
// getDeploymentName returns the deployment name referenced by the
102
// Confusingly, this is stored in the 'name' attribute of the 'Service'
104
func (config *WALASharedConfig) getDeploymentName() string {
105
return config.Deployment.Service.Name
108
// getDeploymentFQDN returns the FQDN of this deployment.
109
// The hostname is taken from the 'name' attribute of the Service element
110
// embedded in the Deployment element. The domain name is Azure's fixed
111
// domain name: 'cloudapp.net'.
112
func (config *WALASharedConfig) getDeploymentFQDN() string {
113
return fmt.Sprintf("%s.%s", config.getDeploymentName(), AZURE_DOMAIN_NAME)
116
// getInternalIP returns the internal IP for this deployment.
117
// The internalIP is the internal IP of the only instance in this deployment.
118
func (config *WALASharedConfig) getInternalIP() string {
119
return config.Instances[0].Address
122
type WALADeployment struct {
123
Name string `xml:"name,attr"`
124
Service WALADeploymentService `xml:"Service"`
127
type WALADeploymentService struct {
128
Name string `xml:"name,attr"`
131
type WALAInstance struct {
132
Address string `xml:"address,attr"`
135
// Path to the WALA configuration file.
136
var _WALAConfigPath = "/var/lib/waagent/SharedConfig.xml"
138
func parseWALAConfig() (*WALASharedConfig, error) {
139
data, err := ioutil.ReadFile(_WALAConfigPath)
143
config := &WALASharedConfig{}
144
err = xml.Unmarshal(data, config)