Merge pull request #138 from monstermunchkin/issues/134-oracle-linux

Support Oracle Linux
This commit is contained in:
Stéphane Graber 2019-02-25 17:18:18 +01:00 committed by GitHub
commit 8462517742
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 344 additions and 0 deletions

156
doc/examples/oraclelinux Normal file
View File

@ -0,0 +1,156 @@
image:
distribution: oraclelinux
release: 7
source:
downloader: oraclelinux-http
url: https://mirror.aarnet.edu.au/pub/oraclelinux
targets:
lxc:
create-message: |
You just created a {{ image.description }} container.
config:
- type: all
before: 5
content: |-
lxc.include = LXC_TEMPLATE_CONFIG/oraclelinux.common.conf
- type: user
before: 5
content: |-
lxc.include = LXC_TEMPLATE_CONFIG/oraclelinux.userns.conf
- type: all
after: 4
content: |-
lxc.include = LXC_TEMPLATE_CONFIG/common.conf
- type: user
after: 4
content: |-
lxc.include = LXC_TEMPLATE_CONFIG/userns.conf
- type: all
content: |-
lxc.arch = {{ image.architecture_kernel }}
files:
- name: hostname
path: /etc/hostname
generator: hostname
- name: hosts
path: /etc/hosts
generator: hosts
- name: ifcfg-eth0
path: /etc/sysconfig/network-scripts/ifcfg-eth0
generator: dump
templated: true
content: |-
DEVICE=eth0
BOOTPROTO=dhcp
ONBOOT=yes
HOSTNAME=LXC_NAME
NM_CONTROLLED=no
TYPE=Ethernet
MTU=
DHCP_HOSTNAME=`hostname`
- name: network
path: /etc/sysconfig/network
generator: dump
templated: true
content: |-
NETWORKING=yes
HOSTNAME=LXC_NAME
- name: ifcfg-eth0.lxd
path: /etc/sysconfig/network-scripts/ifcfg-eth0
generator: template
content: |-
DEVICE=eth0
BOOTPROTO=dhcp
ONBOOT=yes
HOSTNAME={{ container.name }}
NM_CONTROLLED=no
TYPE=Ethernet
MTU=
DHCP_HOSTNAME=`hostname`
- name: network.lxd
path: /etc/sysconfig/network
generator: template
content: |-
NETWORKING=yes
HOSTNAME={{ container.name }}
- name: lxc-sysinit
path: /etc/init/lxc-sysinit.conf
generator: dump
content: |-
start on startup
env container
pre-start script
if [ "x$container" != "xlxc" -a "x$container" != "xlibvirt" ]; then
stop;
fi
rm -f /var/lock/subsys/*
rm -f /var/run/*.pid
[ -e /etc/mtab ] || ln -s /proc/mounts /etc/mtab
mkdir -p /dev/shm
mount -t tmpfs -o nosuid,nodev tmpfs /dev/shm
initctl start tty TTY=console
telinit 3
exit 0
end script
releases:
- 6
- name: sigpwr.conf
path: /etc/init/power-status-changed.conf
generator: dump
content: |-
start on power-status-changed
exec /sbin/shutdown -h now "SIGPWR received"
releases:
- 6
packages:
manager: yum
update: true
cleanup: true
sets:
- packages:
- cronie
- cronie-noanacron
- curl
- dhclient
- initscripts
- openssh-clients
- passwd
- policycoreutils
- rootfiles
- rsyslog
- vim-minimal
action: install
actions:
- trigger: post-packages
action: |-
#!/bin/sh
set -eux
# Disable SELinux
mkdir -p /selinux
echo 0 > /selinux/enforce
# Disable loginuid in PAM stack
sed -i '/^session.*pam_loginuid.so/s/^session/# session/' /etc/pam.d/*

View File

@ -239,6 +239,7 @@ func (d *Definition) Validate() error {
"ubuntu-http",
"sabayon-http",
"docker-http",
"oraclelinux-http",
}
if !shared.StringInSlice(strings.TrimSpace(d.Source.Downloader), validDownloaders) {
return fmt.Errorf("source.downloader must be one of %v", validDownloaders)

185
sources/oraclelinux-http.go Normal file
View File

@ -0,0 +1,185 @@
package sources
import (
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"syscall"
"gopkg.in/antchfx/htmlquery.v1"
"github.com/lxc/distrobuilder/shared"
)
// OracleLinuxHTTP represents the Oracle Linux downloader.
type OracleLinuxHTTP struct {
majorVersion string
}
// NewOracleLinuxHTTP creates a new OracleLinuxHTTP instance.
func NewOracleLinuxHTTP() *OracleLinuxHTTP {
return &OracleLinuxHTTP{}
}
// Run downloads Oracle Linux.
func (s *OracleLinuxHTTP) Run(definition shared.Definition, rootfsDir string) error {
s.majorVersion = definition.Image.Release
fname := "x86_64-boot.iso"
baseURL := fmt.Sprintf("%s/OL%s", definition.Source.URL, definition.Image.Release)
latestUpdate, err := s.getLatestUpdate(baseURL)
if err != nil {
return err
}
err = shared.DownloadHash(fmt.Sprintf("%s/u%s/x86_64/%s", baseURL, latestUpdate, fname),
"", nil)
if err != nil {
return fmt.Errorf("Error downloading Oracle Linux image: %s", err)
}
return s.unpackISO(latestUpdate, filepath.Join(os.TempDir(), fname), rootfsDir)
}
func (s *OracleLinuxHTTP) unpackISO(latestUpdate, filePath, rootfsDir string) error {
isoDir := filepath.Join(os.TempDir(), "distrobuilder", "iso")
squashfsDir := filepath.Join(os.TempDir(), "distrobuilder", "squashfs")
roRootDir := filepath.Join(os.TempDir(), "distrobuilder", "rootfs.ro")
tempRootDir := filepath.Join(os.TempDir(), "distrobuilder", "rootfs")
os.MkdirAll(isoDir, 0755)
os.MkdirAll(squashfsDir, 0755)
os.MkdirAll(roRootDir, 0755)
defer os.RemoveAll(filepath.Join(os.TempDir(), "distrobuilder"))
// this is easier than doing the whole loop thing ourselves
err := shared.RunCommand("mount", "-o", "ro", filePath, isoDir)
if err != nil {
return err
}
defer syscall.Unmount(isoDir, 0)
var rootfsImage string
squashfsImage := filepath.Join(isoDir, "LiveOS", "squashfs.img")
// The squashfs.img contains an image containing the rootfs, so first
// mount squashfs.img
err = shared.RunCommand("mount", "-o", "ro", squashfsImage, squashfsDir)
if err != nil {
return err
}
defer syscall.Unmount(squashfsDir, 0)
rootfsImage = filepath.Join(squashfsDir, "LiveOS", "rootfs.img")
err = shared.RunCommand("mount", "-o", "ro", rootfsImage, roRootDir)
if err != nil {
return err
}
defer syscall.Unmount(roRootDir, 0)
// Remove rootfsDir otherwise rsync will copy the content into the directory
// itself
err = os.RemoveAll(rootfsDir)
if err != nil {
return err
}
// Since roRootDir is read-only, we need to copy it to a temporary rootfs
// directory in order to create the minimal rootfs.
err = shared.RunCommand("rsync", "-qa", roRootDir+"/", tempRootDir)
if err != nil {
return err
}
// Setup the mounts and chroot into the rootfs
exitChroot, err := shared.SetupChroot(tempRootDir, shared.DefinitionEnv{})
if err != nil {
return fmt.Errorf("Failed to setup chroot: %s", err)
}
err = shared.RunScript(fmt.Sprintf(`
#!/bin/sh
set -eux
version="%s"
update="%s"
# Create required files
touch /etc/mtab /etc/fstab
# Fetch and install rpm and yum from the Oracle repo
_rpm=$(curl -s https://yum.oracle.com/repo/OracleLinux/OL${version}/${update}/base/x86_64/index.html | grep -Eo '>rpm-[[:digit:]][^ ]+\.rpm<' | tail -1 | tr -d '<>')
_yum=$(curl -s https://yum.oracle.com/repo/OracleLinux/OL${version}/${update}/base/x86_64/index.html | grep -Eo '>yum-[[:digit:]][^ ]+\.rpm<' | tail -1 | tr -d '<>')
wget https://yum.oracle.com/repo/OracleLinux/OL${version}/${update}/base/x86_64/getPackage/${_rpm}
wget https://yum.oracle.com/repo/OracleLinux/OL${version}/${update}/base/x86_64/getPackage/${_yum}
# There's no OL7 key!
wget https://oss.oracle.com/ol6/RPM-GPG-KEY-oracle
rpm -ivh --nodeps "${_rpm}" "${_yum}"
rpm --import RPM-GPG-KEY-oracle
# Add repo
mkdir -p /etc/yum.repos.d
cat <<- EOF > /etc/yum.repos.d/base.repo
[base]
name=Oracle Linux
baseurl=https://yum.oracle.com/repo/OracleLinux/OL${version}/${update}/base/x86_64
enabled=1
gpgcheck=1
gpgkey=file:///RPM-GPG-KEY-oracle
EOF
mkdir /rootfs
yum --installroot=/rootfs -y --releasever=${version} install basesystem oraclelinux-release yum
rm -rf /rootfs/var/cache/yum
cp RPM-GPG-KEY-oracle /rootfs
mkdir -p /rootfs/etc/yum.repos.d
cat <<- EOF > /rootfs/etc/yum.repos.d/base.repo
[base]
name=Oracle Linux
baseurl=https://yum.oracle.com/repo/OracleLinux/OL${version}/${update}/base/x86_64
enabled=1
gpgcheck=1
gpgkey=file:///RPM-GPG-KEY-oracle
EOF
`, s.majorVersion, latestUpdate))
if err != nil {
exitChroot()
return err
}
exitChroot()
return shared.RunCommand("rsync", "-qa", tempRootDir+"/rootfs/", rootfsDir)
}
func (s *OracleLinuxHTTP) getLatestUpdate(URL string) (string, error) {
re := regexp.MustCompile(`^u\d+/$`)
doc, err := htmlquery.LoadURL(URL)
if err != nil {
return "", err
}
var latestUpdate string
for _, a := range htmlquery.Find(doc, "//a/@href") {
if re.MatchString(a.FirstChild.Data) {
latestUpdate = a.FirstChild.Data
}
}
if latestUpdate == "" {
return "", fmt.Errorf("No update found")
}
latestUpdate = strings.TrimPrefix(latestUpdate, "u")
return strings.TrimSuffix(latestUpdate, "/"), nil
}

View File

@ -28,6 +28,8 @@ func Get(name string) Downloader {
return NewSabayonHTTP()
case "docker-http":
return NewDockerHTTP()
case "oraclelinux-http":
return NewOracleLinuxHTTP()
}
return nil