-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Mathieu Tortuyaux <mtortuyaux@microsoft.com>
- Loading branch information
Showing
5 changed files
with
277 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
// Copyright The Mantle Authors. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package brightbox | ||
|
||
import ( | ||
"crypto/rand" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/flatcar/mantle/platform" | ||
"github.com/flatcar/mantle/platform/conf" | ||
) | ||
|
||
type cluster struct { | ||
*platform.BaseCluster | ||
flight *flight | ||
} | ||
|
||
func (bc *cluster) NewMachine(userdata *conf.UserData) (platform.Machine, error) { | ||
conf, err := bc.RenderUserData(userdata, map[string]string{ | ||
"$public_ipv4": "${COREOS_OPENSTACK_IPV4_PUBLIC}", | ||
"$private_ipv4": "${COREOS_OPENSTACK_IPV4_LOCAL}", | ||
}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var keyname string | ||
if !bc.RuntimeConf().NoSSHKeyInMetadata { | ||
keyname = bc.flight.Name() | ||
} | ||
instance, err := bc.flight.api.CreateServer(bc.vmname(), keyname, conf.String()) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
mach := &machine{ | ||
cluster: bc, | ||
mach: instance, | ||
} | ||
|
||
mach.dir = filepath.Join(bc.RuntimeConf().OutputDir, mach.ID()) | ||
if err := os.Mkdir(mach.dir, 0777); err != nil { | ||
mach.Destroy() | ||
return nil, err | ||
} | ||
|
||
confPath := filepath.Join(mach.dir, "user-data") | ||
if err := conf.WriteFile(confPath); err != nil { | ||
mach.Destroy() | ||
return nil, err | ||
} | ||
|
||
if mach.journal, err = platform.NewJournal(mach.dir); err != nil { | ||
mach.Destroy() | ||
return nil, err | ||
} | ||
|
||
if err := platform.StartMachine(mach, mach.journal); err != nil { | ||
mach.Destroy() | ||
return nil, err | ||
} | ||
|
||
bc.AddMach(mach) | ||
|
||
return mach, nil | ||
} | ||
|
||
func (bc *cluster) vmname() string { | ||
b := make([]byte, 5) | ||
rand.Read(b) | ||
return fmt.Sprintf("%s-%x", bc.Name()[0:13], b) | ||
} | ||
|
||
func (bc *cluster) Destroy() { | ||
bc.BaseCluster.Destroy() | ||
bc.flight.DelCluster(bc) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// Copyright The Mantle Authors. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package brightbox | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/coreos/pkg/capnslog" | ||
ctplatform "github.com/flatcar/container-linux-config-transpiler/config/platform" | ||
|
||
"github.com/flatcar/mantle/platform" | ||
"github.com/flatcar/mantle/platform/api/brightbox" | ||
) | ||
|
||
const ( | ||
Platform platform.Name = "brightbox" | ||
) | ||
|
||
var ( | ||
plog = capnslog.NewPackageLogger("github.com/flatcar/mantle", "platform/machine/brightbox") | ||
) | ||
|
||
type flight struct { | ||
*platform.BaseFlight | ||
api *brightbox.API | ||
} | ||
|
||
func NewFlight(opts *brightbox.Options) (platform.Flight, error) { | ||
api, err := brightbox.New(opts) | ||
if err != nil { | ||
return nil, fmt.Errorf("creating brightbox API client: %w", err) | ||
} | ||
|
||
base, err := platform.NewBaseFlight(opts.Options, Platform, ctplatform.OpenStackMetadata) | ||
if err != nil { | ||
return nil, fmt.Errorf("creating base flight: %w", err) | ||
} | ||
|
||
bf := &flight{ | ||
BaseFlight: base, | ||
api: api, | ||
} | ||
|
||
return bf, nil | ||
} | ||
|
||
// NewCluster creates an instance of a Cluster suitable for spawning | ||
// instances on the OpenStack platform. | ||
func (bf *flight) NewCluster(rconf *platform.RuntimeConfig) (platform.Cluster, error) { | ||
bc, err := platform.NewBaseCluster(bf.BaseFlight, rconf) | ||
if err != nil { | ||
return nil, fmt.Errorf("creating brightbox base cluster: %w", err) | ||
} | ||
|
||
c := &cluster{ | ||
BaseCluster: bc, | ||
flight: bf, | ||
} | ||
|
||
bf.AddCluster(c) | ||
|
||
return c, nil | ||
} | ||
|
||
func (bf *flight) Destroy() { | ||
bf.BaseFlight.Destroy() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
// Copyright The Mantle Authors. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
package brightbox | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
|
||
"golang.org/x/crypto/ssh" | ||
|
||
"github.com/flatcar/mantle/platform" | ||
"github.com/flatcar/mantle/platform/api/brightbox" | ||
) | ||
|
||
type machine struct { | ||
cluster *cluster | ||
mach *brightbox.Server | ||
dir string | ||
journal *platform.Journal | ||
console string | ||
} | ||
|
||
// ID returns the ID of the machine. | ||
func (bm *machine) ID() string { | ||
return bm.mach.Server.ID | ||
} | ||
|
||
// IP returns the IP of the machine. | ||
// The machine should only get one "cloud" IP. | ||
func (bm *machine) IP() string { | ||
if bm.mach.Server != nil && len(bm.mach.Server.CloudIPs) >= 0 { | ||
return bm.mach.Server.CloudIPs[0].PublicIPv4 | ||
} | ||
|
||
return "" | ||
} | ||
|
||
func (bm *machine) PrivateIP() string { | ||
// TODO: We can see a Private IP from the dasbhboard but I don't know how to get it | ||
// from the API. | ||
return "" | ||
} | ||
|
||
func (bm *machine) RuntimeConf() *platform.RuntimeConfig { | ||
return bm.cluster.RuntimeConf() | ||
} | ||
|
||
func (bm *machine) SSHClient() (*ssh.Client, error) { | ||
return bm.cluster.SSHClient(bm.IP()) | ||
} | ||
|
||
func (bm *machine) PasswordSSHClient(user string, password string) (*ssh.Client, error) { | ||
return bm.cluster.PasswordSSHClient(bm.IP(), user, password) | ||
} | ||
|
||
func (bm *machine) SSH(cmd string) ([]byte, []byte, error) { | ||
return bm.cluster.SSH(bm, cmd) | ||
} | ||
|
||
func (bm *machine) Reboot() error { | ||
return platform.RebootMachine(bm, bm.journal) | ||
} | ||
|
||
func (bm *machine) Destroy() { | ||
if err := bm.saveConsole(); err != nil { | ||
plog.Errorf("Error saving console for instance %v: %v", bm.ID(), err) | ||
} | ||
|
||
if err := bm.cluster.flight.api.DeleteServer(bm.ID()); err != nil { | ||
plog.Errorf("deleting server %v: %v", bm.ID(), err) | ||
} | ||
|
||
if bm.journal != nil { | ||
bm.journal.Destroy() | ||
} | ||
|
||
bm.cluster.DelMach(bm) | ||
} | ||
|
||
func (bm *machine) ConsoleOutput() string { | ||
return bm.console | ||
} | ||
|
||
func (bm *machine) saveConsole() error { | ||
var err error | ||
bm.console, err = bm.cluster.flight.api.GetConsoleOutput(bm.ID()) | ||
if err != nil { | ||
return fmt.Errorf("Error retrieving console log for %v: %v", bm.ID(), err) | ||
} | ||
|
||
path := filepath.Join(bm.dir, "console.txt") | ||
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0644) | ||
if err != nil { | ||
return err | ||
} | ||
defer f.Close() | ||
f.WriteString(bm.console) | ||
|
||
return nil | ||
} | ||
|
||
func (bm *machine) JournalOutput() string { | ||
if bm.journal == nil { | ||
return "" | ||
} | ||
|
||
data, err := bm.journal.Read() | ||
if err != nil { | ||
plog.Errorf("Reading journal for instance %v: %v", bm.ID(), err) | ||
} | ||
return string(data) | ||
} | ||
|
||
func (bm *machine) Board() string { | ||
return bm.cluster.flight.Options().Board | ||
} |