Skip to content

Commit

Permalink
Support multiple CDROMS in metadata
Browse files Browse the repository at this point in the history
This checks if any CDROM in the system has metadata. Useful if
you boot off CDROM and also have a metadata CDROM.

Also switch the metadata container to read only, as it is only
writing to bind mounted in directories, and /tmp.

Signed-off-by: Justin Cormack <justin.cormack@docker.com>
  • Loading branch information
justincormack committed Aug 3, 2017
1 parent b886cd0 commit 4434ecc
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 38 deletions.
5 changes: 4 additions & 1 deletion pkg/metadata/Dockerfile
Expand Up @@ -6,10 +6,13 @@ ENV GOPATH=/go PATH=$PATH:/go/bin
COPY . /go/src/metadata/
RUN go-compile.sh /go/src/metadata

RUN mkdir -p out/tmp out/var out/dev out/etc

FROM scratch
ENTRYPOINT []
CMD []
WORKDIR /
COPY --from=mirror /go/bin/metadata /usr/bin/metadata
COPY --from=mirror /out/ /
CMD ["/usr/bin/metadata"]
LABEL org.mobyproject.config='{"binds": ["/dev:/dev", "/var:/var", "/etc/resolv.conf:/etc/resolv.conf"], "capabilities": ["CAP_SYS_ADMIN"]}'
LABEL org.mobyproject.config='{"binds": ["/dev:/dev", "/var:/var", "/etc/resolv.conf:/etc/resolv.conf"], "tmpfs": ["/tmp"], "readonly": true, "capabilities": ["CAP_SYS_ADMIN"]}'
28 changes: 2 additions & 26 deletions pkg/metadata/main.go
Expand Up @@ -14,17 +14,11 @@ const (
// ConfigPath is where the data is extracted to
ConfigPath = "/var/config"

// MountPoint is where the CDROM is mounted
MountPoint = "/cdrom"

// Hostname is the filename in configPath where the hostname is stored
Hostname = "hostname"

// SSH is the path where sshd configuration from the provider is stored
SSH = "ssh"

// TODO(rneugeba): Need to check this is the same everywhere
cdromDev = "/dev/sr0"
)

// Provider is a generic interface for metadata/userdata providers.
Expand All @@ -48,7 +42,7 @@ var cdromProviders []Provider

func init() {
netProviders = []Provider{NewGCP(), NewVultr(), NewAWS()}
cdromProviders = []Provider{NewCDROM()}
cdromProviders = ListCDROMs()
}

func main() {
Expand All @@ -69,19 +63,8 @@ func main() {
}
}
if !found {
log.Printf("Trying CDROM")
if err := os.MkdirAll(MountPoint, 0755); err != nil {
log.Printf("CDROM: Failed to create %s: %s", MountPoint, err)
goto ErrorOut
}
if err := mountCDROM(cdromDev, MountPoint); err != nil {
log.Printf("Failed to mount cdrom: %s", err)
goto ErrorOut
}
defer syscall.Unmount(MountPoint, 0)
// Don't worry about removing MountPoint. We are in a container

for _, p = range cdromProviders {
log.Printf("Trying %s", p.String())
if p.Probe() {
log.Printf("%s: Probe succeeded", p)
userdata, err = p.Extract()
Expand All @@ -91,7 +74,6 @@ func main() {
}
}

ErrorOut:
if !found {
log.Printf("No metadata/userdata found. Bye")
return
Expand Down Expand Up @@ -202,9 +184,3 @@ func processUserData(data []byte) error {

return nil
}

// mountCDROM mounts a CDROM/DVD device under mountPoint
func mountCDROM(device, mountPoint string) error {
// We may need to poll a little for device ready
return syscall.Mount(device, mountPoint, "iso9660", syscall.MS_RDONLY, "")
}
56 changes: 45 additions & 11 deletions pkg/metadata/provider_cdrom.go
Expand Up @@ -3,39 +3,73 @@ package main
import (
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"syscall"
)

const (
configFile = "config"
cdromDevs = "/dev/sr[0-9]*"
)

// ProviderCDROM is the type implementing the Provider interface for CDROMs
// It looks for a file called 'configFile' in the root
type ProviderCDROM struct {
device string
mountPoint string
err error
data []byte
}

// ListCDROMs lists all the cdroms in the system
func ListCDROMs() []Provider {
cdroms, err := filepath.Glob(cdromDevs)
if err != nil {
// Glob can only error on invalid pattern
panic(fmt.Sprintf("Invalid glob pattern: %s", cdromDevs))
}
providers := []Provider{}
for _, device := range cdroms {
providers = append(providers, NewCDROM(device))
}
return providers
}

// NewCDROM returns a new ProviderCDROM
func NewCDROM() *ProviderCDROM {
return &ProviderCDROM{}
func NewCDROM(device string) *ProviderCDROM {
mountPoint, err := ioutil.TempDir("", "cd")
p := ProviderCDROM{device, mountPoint, err, []byte{}}
if err == nil {
if p.err = p.mount(); p.err == nil {
p.data, p.err = ioutil.ReadFile(path.Join(p.mountPoint, configFile))
p.unmount()
}
}
return &p
}

func (p *ProviderCDROM) String() string {
return "CDROM"
return "CDROM " + p.device
}

// Probe checks if the CD has the right file
func (p *ProviderCDROM) Probe() bool {
_, err := os.Stat(path.Join(MountPoint, configFile))
return (!os.IsNotExist(err))
return len(p.data) != 0
}

// Extract gets both the CDROM specific and generic userdata
func (p *ProviderCDROM) Extract() ([]byte, error) {
data, err := ioutil.ReadFile(path.Join(MountPoint, configFile))
if err != nil {
return nil, fmt.Errorf("CDROM: Error reading file: %s", err)
}
return data, nil
return p.data, p.err
}

// mount mounts a CDROM/DVD device under mountPoint
func (p *ProviderCDROM) mount() error {
// We may need to poll a little for device ready
return syscall.Mount(p.device, p.mountPoint, "iso9660", syscall.MS_RDONLY, "")
}

// unmount removes the mount
func (p *ProviderCDROM) unmount() {
_ = syscall.Unmount(p.mountPoint, 0)
}

0 comments on commit 4434ecc

Please sign in to comment.