LEFT | RIGHT |
1 // Copyright 2013 Canonical Ltd. | 1 // Copyright 2013 Canonical Ltd. |
2 // Licensed under the AGPLv3, see LICENCE file for details. | 2 // Licensed under the AGPLv3, see LICENCE file for details. |
3 | 3 |
4 package client | 4 package client |
5 | 5 |
6 import ( | 6 import ( |
7 "fmt" | 7 "fmt" |
8 "net/url" | 8 "net/url" |
9 "os" | 9 "os" |
10 "strings" | 10 "strings" |
11 | 11 |
12 » "launchpad.net/loggo" | 12 » "github.com/loggo/loggo" |
13 | 13 |
14 "launchpad.net/juju-core/charm" | 14 "launchpad.net/juju-core/charm" |
15 coreCloudinit "launchpad.net/juju-core/cloudinit" | 15 coreCloudinit "launchpad.net/juju-core/cloudinit" |
16 "launchpad.net/juju-core/cloudinit/sshinit" | 16 "launchpad.net/juju-core/cloudinit/sshinit" |
17 "launchpad.net/juju-core/environs" | 17 "launchpad.net/juju-core/environs" |
18 "launchpad.net/juju-core/environs/cloudinit" | 18 "launchpad.net/juju-core/environs/cloudinit" |
19 "launchpad.net/juju-core/environs/config" | 19 "launchpad.net/juju-core/environs/config" |
20 "launchpad.net/juju-core/errors" | 20 "launchpad.net/juju-core/errors" |
21 "launchpad.net/juju-core/instance" | 21 "launchpad.net/juju-core/instance" |
22 "launchpad.net/juju-core/juju" | 22 "launchpad.net/juju-core/juju" |
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
600 } | 600 } |
601 | 601 |
602 // ProvisioningScript returns a shell script that, when run, | 602 // ProvisioningScript returns a shell script that, when run, |
603 // provisions a machine agent on the machine executing the script. | 603 // provisions a machine agent on the machine executing the script. |
604 func (c *Client) ProvisioningScript(args params.ProvisioningScriptParams) (param
s.ProvisioningScriptResult, error) { | 604 func (c *Client) ProvisioningScript(args params.ProvisioningScriptParams) (param
s.ProvisioningScriptResult, error) { |
605 var result params.ProvisioningScriptResult | 605 var result params.ProvisioningScriptResult |
606 mcfg, err := statecmd.MachineConfig(c.api.state, args.MachineId, args.No
nce, args.DataDir) | 606 mcfg, err := statecmd.MachineConfig(c.api.state, args.MachineId, args.No
nce, args.DataDir) |
607 if err != nil { | 607 if err != nil { |
608 return result, err | 608 return result, err |
609 } | 609 } |
| 610 mcfg.DisablePackageCommands = args.DisablePackageCommands |
610 cloudcfg := coreCloudinit.New() | 611 cloudcfg := coreCloudinit.New() |
611 if err := cloudinit.ConfigureJuju(mcfg, cloudcfg); err != nil { | 612 if err := cloudinit.ConfigureJuju(mcfg, cloudcfg); err != nil { |
612 return result, err | 613 return result, err |
613 } | 614 } |
614 // ProvisioningScript is run on an existing machine; | 615 // ProvisioningScript is run on an existing machine; |
615 // we explicitly disable apt_upgrade so as not to | 616 // we explicitly disable apt_upgrade so as not to |
616 // trample the machine's existing configuration. | 617 // trample the machine's existing configuration. |
617 cloudcfg.SetAptUpgrade(false) | 618 cloudcfg.SetAptUpgrade(false) |
618 result.Script, err = sshinit.ConfigureScript(cloudcfg) | 619 result.Script, err = sshinit.ConfigureScript(cloudcfg) |
619 return result, err | 620 return result, err |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
870 if _, err := archive.Seek(0, 0); err != nil { | 871 if _, err := archive.Seek(0, 0); err != nil { |
871 return fmt.Errorf("cannot rewind charm archive: %v", err) | 872 return fmt.Errorf("cannot rewind charm archive: %v", err) |
872 } | 873 } |
873 | 874 |
874 // Get the environment storage and upload the charm. | 875 // Get the environment storage and upload the charm. |
875 env, err := environs.New(envConfig) | 876 env, err := environs.New(envConfig) |
876 if err != nil { | 877 if err != nil { |
877 return fmt.Errorf("cannot access environment: %v", err) | 878 return fmt.Errorf("cannot access environment: %v", err) |
878 } | 879 } |
879 storage := env.Storage() | 880 storage := env.Storage() |
880 » archiveName, err := state.CharmArchiveName(charmURL.Name, charmURL.Revis
ion) | 881 » archiveName, err := CharmArchiveName(charmURL.Name, charmURL.Revision) |
881 if err != nil { | 882 if err != nil { |
882 return fmt.Errorf("cannot generate charm archive name: %v", err) | 883 return fmt.Errorf("cannot generate charm archive name: %v", err) |
883 } | |
884 storageURL, err := storage.URL(archiveName) | |
885 if err != nil { | |
886 return fmt.Errorf("cannot get storage URL for charm: %v", err) | |
887 } | |
888 bundleURL, err := url.Parse(storageURL) | |
889 if err != nil { | |
890 return fmt.Errorf("cannot parse storage URL: %v", err) | |
891 } | 884 } |
892 if err := storage.Put(archiveName, archive, size); err != nil { | 885 if err := storage.Put(archiveName, archive, size); err != nil { |
893 return fmt.Errorf("cannot upload charm to provider storage: %v",
err) | 886 return fmt.Errorf("cannot upload charm to provider storage: %v",
err) |
| 887 } |
| 888 storageURL, err := storage.URL(archiveName) |
| 889 if err != nil { |
| 890 return fmt.Errorf("cannot get storage URL for charm: %v", err) |
| 891 } |
| 892 bundleURL, err := url.Parse(storageURL) |
| 893 if err != nil { |
| 894 return fmt.Errorf("cannot parse storage URL: %v", err) |
894 } | 895 } |
895 | 896 |
896 // Finally, update the charm data in state and mark it as no longer pend
ing. | 897 // Finally, update the charm data in state and mark it as no longer pend
ing. |
897 _, err = c.api.state.UpdateUploadedCharm(downloadedCharm, charmURL, bund
leURL, bundleSHA256) | 898 _, err = c.api.state.UpdateUploadedCharm(downloadedCharm, charmURL, bund
leURL, bundleSHA256) |
898 if err == state.ErrCharmRevisionAlreadyModified || | 899 if err == state.ErrCharmRevisionAlreadyModified || |
899 state.IsCharmAlreadyUploadedError(err) { | 900 state.IsCharmAlreadyUploadedError(err) { |
900 // This is not an error, it just signifies somebody else | 901 // This is not an error, it just signifies somebody else |
901 // managed to upload and update the charm in state before | 902 // managed to upload and update the charm in state before |
902 // us. This means we have to delete what we just uploaded | 903 // us. This means we have to delete what we just uploaded |
903 // to storage. | 904 // to storage. |
904 if err := storage.Remove(archiveName); err != nil { | 905 if err := storage.Remove(archiveName); err != nil { |
905 logger.Errorf("cannot remove duplicated charm from stora
ge: %v", err) | 906 logger.Errorf("cannot remove duplicated charm from stora
ge: %v", err) |
906 } | 907 } |
907 return nil | 908 return nil |
908 } | 909 } |
909 return err | 910 return err |
910 } | 911 } |
| 912 |
| 913 // CharmArchiveName returns a string that is suitable as a file name |
| 914 // in a storage URL. It is constructed from the charm name, revision |
| 915 // and a random UUID string. |
| 916 func CharmArchiveName(name string, revision int) (string, error) { |
| 917 uuid, err := utils.NewUUID() |
| 918 if err != nil { |
| 919 return "", err |
| 920 } |
| 921 return charm.Quote(fmt.Sprintf("%s-%d-%s", name, revision, uuid)), nil |
| 922 } |
LEFT | RIGHT |