2015-02-21 06:35:42 +00:00
|
|
|
package control
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
2015-03-18 12:34:23 +00:00
|
|
|
"net/url"
|
|
|
|
"strings"
|
2015-02-21 06:35:42 +00:00
|
|
|
|
|
|
|
log "github.com/Sirupsen/logrus"
|
2015-03-18 12:34:23 +00:00
|
|
|
"gopkg.in/yaml.v2"
|
|
|
|
|
|
|
|
dockerClient "github.com/fsouza/go-dockerclient"
|
2015-02-21 06:35:42 +00:00
|
|
|
|
|
|
|
"github.com/codegangsta/cli"
|
|
|
|
"github.com/rancherio/os/cmd/power"
|
|
|
|
"github.com/rancherio/os/config"
|
|
|
|
"github.com/rancherio/os/docker"
|
|
|
|
)
|
|
|
|
|
2015-03-18 12:34:23 +00:00
|
|
|
type Images struct {
|
|
|
|
Current string `yaml:"current,omitempty"`
|
|
|
|
Available []string `yaml:"available,omitempty"`
|
|
|
|
}
|
2015-02-21 06:35:42 +00:00
|
|
|
|
|
|
|
func osSubcommands() []cli.Command {
|
|
|
|
return []cli.Command{
|
|
|
|
{
|
|
|
|
Name: "upgrade",
|
|
|
|
Usage: "upgrade to latest version",
|
|
|
|
Action: osUpgrade,
|
|
|
|
Flags: []cli.Flag{
|
|
|
|
cli.BoolFlag{
|
2015-02-23 19:00:33 +00:00
|
|
|
Name: "stage, s",
|
2015-02-21 06:35:42 +00:00
|
|
|
Usage: "Only stage the new upgrade, don't apply it",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
2015-02-23 19:00:33 +00:00
|
|
|
Name: "image, i",
|
2015-02-21 06:35:42 +00:00
|
|
|
Usage: "upgrade to a certain image",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2015-02-23 19:00:33 +00:00
|
|
|
Name: "list",
|
|
|
|
Usage: "list the current available versions",
|
2015-02-21 06:35:42 +00:00
|
|
|
Action: osMetaDataGet,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-18 12:34:23 +00:00
|
|
|
func getImages() (*Images, error) {
|
|
|
|
upgradeUrl, err := getUpgradeUrl()
|
2015-02-21 06:35:42 +00:00
|
|
|
if err != nil {
|
2015-03-18 12:34:23 +00:00
|
|
|
return nil, err
|
2015-02-21 06:35:42 +00:00
|
|
|
}
|
|
|
|
|
2015-03-18 12:34:23 +00:00
|
|
|
var body []byte
|
|
|
|
|
|
|
|
if strings.HasPrefix(upgradeUrl, "/") {
|
|
|
|
body, err = ioutil.ReadFile(upgradeUrl)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
u, err := url.Parse(upgradeUrl)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
q := u.Query()
|
|
|
|
q.Set("current", config.VERSION)
|
|
|
|
u.RawQuery = q.Encode()
|
|
|
|
upgradeUrl = u.String()
|
|
|
|
|
|
|
|
resp, err := http.Get(upgradeUrl)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
body, err = ioutil.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2015-02-21 06:35:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-18 12:34:23 +00:00
|
|
|
return parseBody(body)
|
2015-02-21 06:35:42 +00:00
|
|
|
}
|
2015-02-23 19:00:33 +00:00
|
|
|
|
2015-02-21 06:35:42 +00:00
|
|
|
func osMetaDataGet(c *cli.Context) {
|
2015-03-18 12:34:23 +00:00
|
|
|
images, err := getImages()
|
2015-02-21 06:35:42 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2015-03-18 12:34:23 +00:00
|
|
|
|
|
|
|
client, err := docker.NewSystemClient()
|
2015-02-21 06:35:42 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2015-03-18 12:34:23 +00:00
|
|
|
|
|
|
|
for _, image := range images.Available {
|
|
|
|
_, err := client.InspectImage(image)
|
|
|
|
if err == dockerClient.ErrNoSuchImage {
|
|
|
|
fmt.Println(image, " remote")
|
|
|
|
} else {
|
|
|
|
fmt.Println(image, " local")
|
|
|
|
}
|
|
|
|
}
|
2015-02-21 06:35:42 +00:00
|
|
|
}
|
|
|
|
|
2015-03-18 12:34:23 +00:00
|
|
|
func getLatestImage() (string, error) {
|
|
|
|
images, err := getImages()
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
2015-02-21 06:35:42 +00:00
|
|
|
|
2015-03-18 12:34:23 +00:00
|
|
|
return images.Current, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func osUpgrade(c *cli.Context) {
|
2015-02-21 06:35:42 +00:00
|
|
|
image := c.String("image")
|
|
|
|
|
|
|
|
if image == "" {
|
|
|
|
var err error
|
2015-03-18 12:34:23 +00:00
|
|
|
image, err = getLatestImage()
|
2015-02-21 06:35:42 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2015-03-18 12:34:23 +00:00
|
|
|
if image == "" {
|
|
|
|
log.Fatal("Failed to find latest image")
|
|
|
|
}
|
2015-02-21 06:35:42 +00:00
|
|
|
}
|
|
|
|
startUpgradeContainer(image, c.Bool("stage"))
|
|
|
|
}
|
|
|
|
|
|
|
|
func startUpgradeContainer(image string, stage bool) {
|
|
|
|
container := docker.NewContainer(config.DOCKER_SYSTEM_HOST, &config.ContainerConfig{
|
2015-03-18 12:34:23 +00:00
|
|
|
Cmd: "--name=os-upgrade " +
|
|
|
|
"--rm " +
|
2015-02-21 06:35:42 +00:00
|
|
|
"--privileged " +
|
|
|
|
"--net=host " +
|
2015-03-18 12:34:23 +00:00
|
|
|
image + " " +
|
|
|
|
"-t rancher-upgrade " +
|
|
|
|
"-r " + config.VERSION,
|
2015-02-21 06:35:42 +00:00
|
|
|
}).Stage()
|
|
|
|
|
|
|
|
if container.Err != nil {
|
|
|
|
log.Fatal(container.Err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !stage {
|
|
|
|
container.StartAndWait()
|
|
|
|
if container.Err != nil {
|
|
|
|
log.Fatal(container.Err)
|
|
|
|
}
|
|
|
|
power.Reboot()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-18 12:34:23 +00:00
|
|
|
func parseBody(body []byte) (*Images, error) {
|
|
|
|
update := &Images{}
|
|
|
|
err := yaml.Unmarshal(body, update)
|
2015-02-21 06:35:42 +00:00
|
|
|
if err != nil {
|
2015-03-18 12:34:23 +00:00
|
|
|
return nil, err
|
2015-02-21 06:35:42 +00:00
|
|
|
}
|
|
|
|
|
2015-03-18 12:34:23 +00:00
|
|
|
return update, nil
|
|
|
|
}
|
2015-02-21 06:35:42 +00:00
|
|
|
|
2015-03-18 12:34:23 +00:00
|
|
|
func getUpgradeUrl() (string, error) {
|
|
|
|
cfg, err := config.LoadConfig()
|
2015-02-21 06:35:42 +00:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
2015-03-18 12:34:23 +00:00
|
|
|
return cfg.Upgrade.Url, nil
|
2015-02-21 06:35:42 +00:00
|
|
|
}
|