Skip to content

Commit

Permalink
Merge 09e56c3 into 3221bc5
Browse files Browse the repository at this point in the history
  • Loading branch information
rgooch committed Jul 26, 2019
2 parents 3221bc5 + 09e56c3 commit 384ea5c
Show file tree
Hide file tree
Showing 25 changed files with 530 additions and 139 deletions.
1 change: 1 addition & 0 deletions cmd/dominator/required-methods
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
FileGenerator.Connect
ImageServer.GetImage
ImageServer.GetImageExpiration
ObjectServer.AddObjects
Subd.*
87 changes: 77 additions & 10 deletions cmd/hyper-control/rolloutImage.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"fmt"
"io"
"math"
"net"
"os"
"os/exec"
Expand Down Expand Up @@ -56,6 +57,34 @@ func rolloutImageSubcommand(args []string, logger log.DebugLogger) error {
return nil
}

func checkCertificates(predictedDuration time.Duration) error {
predictedFinish := time.Now().Add(predictedDuration)
if srpc.GetEarliestClientCertExpiration().Before(predictedFinish) {
return fmt.Errorf("a certificate expires before: %s", predictedFinish)
}
return nil
}

func extendImageLifetime(imageServerClientResource *srpc.ClientResource,
imageName string, expiresAt time.Time, predictedDuration time.Duration,
logger log.DebugLogger) error {
if expiresAt.IsZero() {
return nil
}
if time.Until(expiresAt) >= predictedDuration {
return nil
}
newExpiration := time.Now().Add(predictedDuration)
logger.Debugf(0, "extending image lifetime by %s\n",
format.Duration(time.Until(newExpiration)))
client, err := imageServerClientResource.GetHTTP(nil, 0)
if err != nil {
return err
}
defer client.Put()
return imageclient.ChangeImageExpiration(client, imageName, newExpiration)
}

func gitCommand(repositoryDirectory string, command ...string) ([]byte, error) {
cmd := exec.Command("git", command...)
cmd.Dir = repositoryDirectory
Expand Down Expand Up @@ -84,10 +113,12 @@ func rolloutImage(imageName string, logger log.DebugLogger) error {
}
}
logger.Debugln(0, "checking image")
if foundImage, err := checkImage(imageName); err != nil {
imageServerClientResource := srpc.NewClientResource("tcp",
fmt.Sprintf("%s:%d", *imageServerHostname, *imageServerPortNum))
defer imageServerClientResource.ScheduleClose()
expiresAt, err := checkImage(imageServerClientResource, imageName)
if err != nil {
return err
} else if !foundImage {
return fmt.Errorf("image: %s not found", imageName)
}
fleetManagerClientResource := srpc.NewClientResource("tcp",
fmt.Sprintf("%s:%d", *fleetManagerHostname, *fleetManagerPortNum))
Expand Down Expand Up @@ -138,6 +169,17 @@ func rolloutImage(imageName string, logger log.DebugLogger) error {
cpuSharer)
logger.Debugf(0, "%d unused, %d used Hypervisors\n",
len(unusedHypervisors), len(usedHypervisors))
numSteps := math.Sqrt(float64(len(unusedHypervisors)*2)) +
math.Sqrt(float64(len(usedHypervisors)*2))
predictedDuration := time.Minute * 5 * time.Duration(numSteps)
if err := checkCertificates(predictedDuration); err != nil {
return err
}
err = extendImageLifetime(imageServerClientResource, imageName, expiresAt,
predictedDuration, logger)
if err != nil {
return err
}
logger.Debugln(0, "upgrading unused Hypervisors")
err = upgradeOneThenAll(fleetManagerClientResource, imageName,
unusedHypervisors, cpuSharer, uint(len(unusedHypervisors)))
Expand All @@ -158,6 +200,10 @@ func rolloutImage(imageName string, logger log.DebugLogger) error {
if err != nil {
return err
}
err = releaseImage(imageServerClientResource, imageName, expiresAt, logger)
if err != nil {
return err
}
if *topologyDir != "" {
var tgs tags.Tags
tagsFilename := filepath.Join(*topologyDir, *location, "tags.json")
Expand Down Expand Up @@ -196,15 +242,22 @@ func rolloutImage(imageName string, logger log.DebugLogger) error {
return nil
}

func checkImage(imageName string) (bool, error) {
clientName := fmt.Sprintf("%s:%d",
*imageServerHostname, *imageServerPortNum)
client, err := srpc.DialHTTP("tcp", clientName, 0)
func checkImage(imageServerClientResource *srpc.ClientResource,
imageName string) (time.Time, error) {
client, err := imageServerClientResource.GetHTTP(nil, 0)
if err != nil {
return false, err
return time.Time{}, err
}
defer client.Close()
return imageclient.CheckImage(client, imageName)
defer client.Put()
expiresAt, err := imageclient.GetImageExpiration(client, imageName)
if err != nil {
return time.Time{}, err
}
if expiresAt.IsZero() {
return expiresAt, nil
}
return expiresAt,
imageclient.ChangeImageExpiration(client, imageName, expiresAt)
}

func closeHypervisors(hypervisors []*hypervisorType) {
Expand Down Expand Up @@ -318,6 +371,20 @@ func markUnusedHypervisors(hypervisors []*hypervisorType,
return unusedHypervisors, usedHypervisors
}

func releaseImage(imageServerClientResource *srpc.ClientResource,
imageName string, expiresAt time.Time, logger log.DebugLogger) error {
if expiresAt.IsZero() {
return nil
}
logger.Debugln(0, "releasing image")
client, err := imageServerClientResource.GetHTTP(nil, 0)
if err != nil {
return err
}
defer client.Put()
return imageclient.ChangeImageExpiration(client, imageName, time.Time{})
}

func setupHypervisor(hostname string, imageName string, tgs tags.Tags,
cpuSharer *cpusharer.FifoCpuSharer,
logger log.DebugLogger) *hypervisorType {
Expand Down
21 changes: 19 additions & 2 deletions cmd/imagetool/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,36 @@ Some of the sub-commands available are:

- **add**: add an image using a compressed tarfile for image data
- **addi**: add an image using an existing image for image data
- **adds**: add an image using files from a running *subd* for image data (this
allows "snapshotting" of a golden machine)
- **addrep**: add an image using an existing image and layer files from
compressed tarfiles on top of existing files
- **adds**: add an image using files from a running *subd* for image data (this
allows "snapshotting" of a golden machine)
- **bulk-addrep**: perform addrep operation for all images
- **change-image-expiration**: change or remove the expiration time for an image
- **check**: check if an image exists
- **check-directory**: check if a directory exists
- **chown**: change the owner group of an image directory
- **copy**: copy an image
- **delete**: delete an image
- **delunrefobj**: delete (garbage collect) unreferenced objects
- **diff**: compare two images
- **estimate-usage**: estimate the file-system space needed to unpack an image
- **find-latest-image**: find the latest image in a directory
- **get**: get and unpack an image
- **get-archive-data**: get archive (audit) data for an image
- **get-image-expiration**: get the expiration time for an image
- **list**: list all images
- **listdirs**: list all directories
- **listunrefobj**: list the unreferenced objects on the server
- **make-raw-image**: make a bootable RAW image from an image
- **match-triggers**: match a path to a triggers file
- **merge-filters**: merge filter files
- **merge-triggers**: merge trigger files
- **mkdir**: make a directory
- **show**: show (list) an image
- **showunrefobj**: list the unreferenced objects on the server and their sizes
- **tar**: create a tarfile from an image
- **test-download-speed**: test the speed for downloading objects for an image

## Security
*[Imageserver](../imageserver/README.md)* restricts RPC access using TLS client
Expand Down
55 changes: 55 additions & 0 deletions cmd/imagetool/expiration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package main

import (
"fmt"
"os"
"time"

"github.com/Symantec/Dominator/imageserver/client"
"github.com/Symantec/Dominator/lib/format"
"github.com/Symantec/Dominator/lib/srpc"
)

func changeImageExpirationSubcommand(args []string) {
imageSClient, _ := getClients()
err := changeImageExpiration(imageSClient, args[0])
if err != nil {
fmt.Fprintf(os.Stderr, "Error changing image expiration: %s\n", err)
os.Exit(1)
}
os.Exit(0)
}

func changeImageExpiration(imageSClient *srpc.Client, name string) error {
var expiresAt time.Time
if *expiresIn > 0 {
expiresAt = time.Now().Add(*expiresIn)
}
return client.ChangeImageExpiration(imageSClient, name, expiresAt)
}

func getImageExpirationSubcommand(args []string) {
imageSClient, _ := getClients()
if err := getImageExpiration(imageSClient, args[0]); err != nil {
fmt.Fprintf(os.Stderr, "Error getting image expiration: %s\n", err)
os.Exit(1)
}
os.Exit(0)
}

func getImageExpiration(imageSClient *srpc.Client, name string) error {
expiresAt, err := client.GetImageExpiration(imageSClient, name)
if err != nil {
return err
}
if expiresAt.IsZero() {
fmt.Println("image does not expire")
} else if timeLeft := time.Until(expiresAt); timeLeft < 0 {
fmt.Printf("image expired at %s (%s ago)\n", expiresAt,
format.Duration(-timeLeft))
} else {
fmt.Printf("image expires at %s (in %s)\n", expiresAt,
format.Duration(timeLeft))
}
return nil
}
30 changes: 0 additions & 30 deletions cmd/imagetool/listImages.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
"fmt"
"os"
"path"

"github.com/Symantec/Dominator/imageserver/client"
"github.com/Symantec/Dominator/lib/srpc"
Expand All @@ -30,32 +29,3 @@ func listImages(imageSClient *srpc.Client) error {
}
return nil
}

func listLatestImageSubcommand(args []string) {
imageClient, _ := getClients()
if err := listLatestImage(imageClient, args[0]); err != nil {
fmt.Fprintf(os.Stderr, "Error listing latest image: %s\n", err)
os.Exit(1)
}
os.Exit(0)
}

func listLatestImage(imageSClient *srpc.Client, directory string) error {
imageNames, err := client.ListImages(imageSClient)
if err != nil {
return err
}
namesInDirectory := make([]string, 0)
pattern := path.Join(directory, "*")
for _, name := range imageNames {
if matched, _ := path.Match(pattern, name); matched {
namesInDirectory = append(namesInDirectory, name)
}
}
if len(namesInDirectory) < 1 {
return nil
}
verstr.Sort(namesInDirectory)
fmt.Println(namesInDirectory[len(namesInDirectory)-1])
return nil
}
10 changes: 6 additions & 4 deletions cmd/imagetool/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,10 @@ func printUsage() {
fmt.Fprintln(os.Stderr, "Commands:")
fmt.Fprintln(os.Stderr, " add name imagefile filterfile triggerfile")
fmt.Fprintln(os.Stderr, " addi name imagename filterfile triggerfile")
fmt.Fprintln(os.Stderr, " adds name subname filterfile triggerfile")
fmt.Fprintln(os.Stderr, " addrep name baseimage layerimage...")
fmt.Fprintln(os.Stderr, " adds name subname filterfile triggerfile")
fmt.Fprintln(os.Stderr, " bulk-addrep layerimage...")
fmt.Fprintln(os.Stderr, " change-image-expiration name")
fmt.Fprintln(os.Stderr, " check name")
fmt.Fprintln(os.Stderr, " check-directory dirname")
fmt.Fprintln(os.Stderr, " chown dirname ownerGroup")
Expand All @@ -100,10 +101,10 @@ func printUsage() {
fmt.Fprintln(os.Stderr, " find-latest-image directory")
fmt.Fprintln(os.Stderr, " get name directory")
fmt.Fprintln(os.Stderr, " get-archive-data name outfile")
fmt.Fprintln(os.Stderr, " get-image-expiration name")
fmt.Fprintln(os.Stderr, " list")
fmt.Fprintln(os.Stderr, " listdirs")
fmt.Fprintln(os.Stderr, " listunrefobj")
fmt.Fprintln(os.Stderr, " list-latest-image directory")
fmt.Fprintln(os.Stderr, " make-raw-image name rawfile")
fmt.Fprintln(os.Stderr, " match-triggers name triggers-file")
fmt.Fprintln(os.Stderr, " merge-filters filter-file...")
Expand Down Expand Up @@ -135,10 +136,11 @@ type subcommand struct {

var subcommands = []subcommand{
{"add", 4, 4, addImagefileSubcommand},
{"adds", 4, 4, addImagesubSubcommand},
{"addi", 4, 4, addImageimageSubcommand},
{"addrep", 3, -1, addReplaceImageSubcommand},
{"adds", 4, 4, addImagesubSubcommand},
{"bulk-addrep", 1, -1, bulkAddReplaceImagesSubcommand},
{"change-image-expiration", 1, 1, changeImageExpirationSubcommand},
{"check", 1, 1, checkImageSubcommand},
{"check-directory", 1, 1, checkDirectorySubcommand},
{"chown", 2, 2, chownDirectorySubcommand},
Expand All @@ -150,10 +152,10 @@ var subcommands = []subcommand{
{"find-latest-image", 1, 1, findLatestImageSubcommand},
{"get", 2, 2, getImageSubcommand},
{"get-archive-data", 2, 2, getImageArchiveDataSubcommand},
{"get-image-expiration", 1, 1, getImageExpirationSubcommand},
{"list", 0, 0, listImagesSubcommand},
{"listdirs", 0, 0, listDirectoriesSubcommand},
{"listunrefobj", 0, 0, listUnreferencedObjectsSubcommand},
{"list-latest-image", 1, 1, listLatestImageSubcommand},
{"make-raw-image", 2, 2, makeRawImageSubcommand},
{"match-triggers", 2, 2, matchTriggersSubcommand},
{"merge-filters", 1, -1, mergeFiltersSubcommand},
Expand Down
5 changes: 5 additions & 0 deletions dom/herd/sub.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,11 @@ func (sub *Sub) poll(srpcClient *srpc.Client, previousStatus subStatus) {
haveImage := false
if sub.requiredImage == nil {
request.ShortPollOnly = true
// Ensure a full poll when the image becomes available later. This will
// cover the special case when an image expiration is extended, which
// leads to the sub showing "image not ready" until the next generation
// increment.
sub.generationCount = 0
} else {
haveImage = true
}
Expand Down
1 change: 1 addition & 0 deletions dom/images/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func (m *Manager) manager(imageInterestChannel <-chan map[string]struct{},
case name := <-imageExpireChannel:
m.Lock()
delete(m.imagesByName, name)
m.missingImages[name] = nil // Try to get it again (expire extended)
m.Unlock()
m.rebuildDeDuper()
case <-timer.C:
Expand Down
9 changes: 9 additions & 0 deletions imageserver/client/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ func AddImageTrusted(client *srpc.Client, name string, img *image.Image) error {
return addImageTrusted(client, name, img)
}

func ChangeImageExpiration(client *srpc.Client, name string,
expiresAt time.Time) error {
return changeImageExpiration(client, name, expiresAt)
}

func CheckDirectory(client *srpc.Client, name string) (bool, error) {
return checkDirectory(client, name)
}
Expand Down Expand Up @@ -46,6 +51,10 @@ func GetImage(client *srpc.Client, name string) (*image.Image, error) {
return getImage(client, name, 0)
}

func GetImageExpiration(client *srpc.Client, name string) (time.Time, error) {
return getImageExpiration(client, name)
}

func GetImageWithTimeout(client *srpc.Client, name string,
timeout time.Duration) (*image.Image, error) {
return getImage(client, name, timeout)
Expand Down
Loading

0 comments on commit 384ea5c

Please sign in to comment.