Compare commits
53 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d41705f90 | ||
|
|
87eab3b1c9 | ||
|
|
b1ba4daf39 | ||
|
|
ee2919cf0f | ||
|
|
0f6aa24626 | ||
|
|
fe1027b1b6 | ||
|
|
814ff56e64 | ||
|
|
bdf5d8538e | ||
|
|
924fc49aff | ||
|
|
c63144fb04 | ||
|
|
affecd02fd | ||
|
|
5b629d0d13 | ||
|
|
6c9be2625e | ||
|
|
7b8c79bbdf | ||
|
|
71623750fc | ||
|
|
67599f352c | ||
|
|
8ad6b10446 | ||
|
|
27d4dd2b8b | ||
|
|
23cc740eae | ||
|
|
29aaadd88c | ||
|
|
88c5b5ef14 | ||
|
|
615a6e4415 | ||
|
|
4a2744e858 | ||
|
|
ebc170def6 | ||
|
|
ce9d497890 | ||
|
|
869559924b | ||
|
|
6a840ff5c8 | ||
|
|
bfa2592538 | ||
|
|
8edb916513 | ||
|
|
7cad727413 | ||
|
|
3fac5f7604 | ||
|
|
a8cf965b2a | ||
|
|
4841467d41 | ||
|
|
3961aa6855 | ||
|
|
1893c7863b | ||
|
|
eccf9554c8 | ||
|
|
5db4908235 | ||
|
|
2f988130e8 | ||
|
|
7b5653473b | ||
|
|
7bff07ed07 | ||
|
|
7a5420e8bb | ||
|
|
0e22f6f06f | ||
|
|
2221445ffe | ||
|
|
ba2cfe89c6 | ||
|
|
f87c5f0b5a | ||
|
|
a37efde319 | ||
|
|
34afa7824e | ||
|
|
b787287190 | ||
|
|
960d0d3bdb | ||
|
|
1ff4f6ebaa | ||
|
|
65c97ea462 | ||
|
|
d9caf6fa20 | ||
|
|
b5bbcdc89e |
@@ -60,7 +60,7 @@ ARG DISTRIB_ID=RancherOS
|
||||
|
||||
ARG SELINUX_POLICY_URL=https://github.com/rancher/refpolicy/releases/download/v0.0.3/policy.29
|
||||
|
||||
ARG KERNEL_VERSION=4.14.122-rancher
|
||||
ARG KERNEL_VERSION=4.14.138-rancher
|
||||
ARG KERNEL_URL_amd64=https://github.com/rancher/os-kernel/releases/download/v${KERNEL_VERSION}/linux-${KERNEL_VERSION}-x86.tar.gz
|
||||
ARG KERNEL_URL_arm64=https://github.com/rancher/os-kernel/releases/download/v${KERNEL_VERSION}/linux-${KERNEL_VERSION}-arm64.tar.gz
|
||||
|
||||
@@ -85,8 +85,8 @@ ARG SYSTEM_DOCKER_VERSION=17.06-ros6
|
||||
ARG SYSTEM_DOCKER_URL_amd64=https://github.com/rancher/os-system-docker/releases/download/${SYSTEM_DOCKER_VERSION}/docker-amd64-${SYSTEM_DOCKER_VERSION}.tgz
|
||||
ARG SYSTEM_DOCKER_URL_arm64=https://github.com/rancher/os-system-docker/releases/download/${SYSTEM_DOCKER_VERSION}/docker-arm64-${SYSTEM_DOCKER_VERSION}.tgz
|
||||
|
||||
ARG USER_DOCKER_VERSION=18.06.3
|
||||
ARG USER_DOCKER_ENGINE_VERSION=docker-${USER_DOCKER_VERSION}-ce
|
||||
ARG USER_DOCKER_VERSION=19.03.15
|
||||
ARG USER_DOCKER_ENGINE_VERSION=docker-${USER_DOCKER_VERSION}
|
||||
|
||||
ARG AZURE_SERVICE=false
|
||||
ARG PROXMOXVE_SERVICE=false
|
||||
@@ -158,7 +158,9 @@ RUN curl -fL ${!BUILD_DOCKER_URL} > /usr/bin/docker && \
|
||||
chmod +x /usr/bin/docker
|
||||
|
||||
# Install dapper
|
||||
RUN curl -sL https://releases.rancher.com/dapper/latest/dapper-`uname -s`-`uname -m | sed 's/arm.*/arm/'` > /usr/bin/dapper && \
|
||||
# sidestep https://github.com/rancher/dapper/issues/92 with v0.5.4
|
||||
ARG DAPPER_VERSION="v0.5.4"
|
||||
RUN curl -sL https://github.com/rancher/dapper/releases/download/${DAPPER_VERSION}/dapper-$(uname -s)-$(uname -m) > /usr/bin/dapper && \
|
||||
chmod +x /usr/bin/dapper
|
||||
|
||||
RUN cd ${DOWNLOADS} && \
|
||||
|
||||
20
Makefile
20
Makefile
@@ -41,42 +41,42 @@ release: .dapper release-build
|
||||
|
||||
release-build:
|
||||
mkdir -p dist
|
||||
./.dapper release 2>&1 | tee dist/release.log
|
||||
./.dapper release
|
||||
|
||||
rpi64: .dapper
|
||||
./scripts/release-rpi64
|
||||
|
||||
vmware: .dapper
|
||||
mkdir -p dist
|
||||
APPEND_SYSTEM_IMAGES="rancher/os-openvmtools:10.3.10-1" \
|
||||
./.dapper release-vmware 2>&1 | tee dist/release.log
|
||||
APPEND_SYSTEM_IMAGES="rancher/os-openvmtools:10.3.10-2" \
|
||||
./.dapper release-vmware
|
||||
|
||||
hyperv: .dapper
|
||||
mkdir -p dist
|
||||
APPEND_SYSTEM_IMAGES="rancher/os-hypervvmtools:v4.14.122-rancher-1" \
|
||||
./.dapper release-hyperv 2>&1 | tee dist/release.log
|
||||
APPEND_SYSTEM_IMAGES="rancher/os-hypervvmtools:v4.14.138-rancher-1" \
|
||||
./.dapper release-hyperv
|
||||
|
||||
azurebase: .dapper
|
||||
mkdir -p dist
|
||||
AZURE_SERVICE="true" \
|
||||
APPEND_SYSTEM_IMAGES="rancher/os-hypervvmtools:v4.14.122-rancher-1 rancher/os-waagent:v2.2.34-1" \
|
||||
./.dapper release-azurebase 2>&1 | tee dist/release.log
|
||||
APPEND_SYSTEM_IMAGES="rancher/os-hypervvmtools:v4.14.138-rancher-1 rancher/os-waagent:v2.2.34-1" \
|
||||
./.dapper release-azurebase
|
||||
|
||||
4glte: .dapper
|
||||
mkdir -p dist
|
||||
APPEND_SYSTEM_IMAGES="rancher/os-modemmanager:v1.6.4-1" \
|
||||
./.dapper release-4glte 2>&1 | tee dist/release.log
|
||||
./.dapper release-4glte
|
||||
|
||||
proxmoxve: .dapper
|
||||
mkdir -p dist
|
||||
PROXMOXVE_SERVICE="true" \
|
||||
APPEND_SYSTEM_IMAGES="rancher/os-qemuguestagent:v2.8.1-2" \
|
||||
./.dapper release-proxmoxve 2>&1 | tee dist/release.log
|
||||
./.dapper release-proxmoxve
|
||||
|
||||
pingan: .dapper
|
||||
mkdir -p dist
|
||||
APPEND_SYSTEM_IMAGES="cnrancher/os-pingan-amc:v0.0.6-1" \
|
||||
./.dapper release-pingan 2>&1 | tee dist/release.log
|
||||
./.dapper release-pingan
|
||||
|
||||
help:
|
||||
@./scripts/help
|
||||
|
||||
96
README.md
96
README.md
@@ -18,68 +18,68 @@ it would really be bad if somebody did `docker rm -f $(docker ps -qa)` and delet
|
||||
|
||||
## Release
|
||||
|
||||
- **v1.5.1 - Docker 18.06.1-ce - Linux 4.14.85**
|
||||
- **v1.5.8 - Docker 19.03.15 - Linux 4.14.138**
|
||||
|
||||
### ISO
|
||||
|
||||
- https://releases.rancher.com/os/v1.5.1/rancheros.iso
|
||||
- https://releases.rancher.com/os/v1.5.1/hyperv/rancheros.iso
|
||||
- https://releases.rancher.com/os/v1.5.1/4glte/rancheros.iso
|
||||
- https://releases.rancher.com/os/v1.5.1/vmware/rancheros.iso
|
||||
- https://releases.rancher.com/os/v1.5.8/rancheros.iso
|
||||
- https://releases.rancher.com/os/v1.5.8/hyperv/rancheros.iso
|
||||
- https://releases.rancher.com/os/v1.5.8/4glte/rancheros.iso
|
||||
- https://releases.rancher.com/os/v1.5.8/vmware/rancheros.iso
|
||||
|
||||
#### Special docker-machine Links
|
||||
|
||||
- https://releases.rancher.com/os/v1.5.1/vmware/rancheros-autoformat.iso
|
||||
- https://releases.rancher.com/os/v1.5.1/proxmoxve/rancheros-autoformat.iso
|
||||
- https://releases.rancher.com/os/v1.5.8/vmware/rancheros-autoformat.iso
|
||||
- https://releases.rancher.com/os/v1.5.8/proxmoxve/rancheros-autoformat.iso
|
||||
|
||||
### Additional Downloads
|
||||
|
||||
#### AMD64 Links
|
||||
|
||||
* https://releases.rancher.com/os/v1.5.1/initrd
|
||||
* https://releases.rancher.com/os/v1.5.1/vmlinuz
|
||||
* https://releases.rancher.com/os/v1.5.1/rancheros.ipxe
|
||||
* https://releases.rancher.com/os/v1.5.1/rootfs.tar.gz
|
||||
* https://releases.rancher.com/os/v1.5.8/initrd
|
||||
* https://releases.rancher.com/os/v1.5.8/vmlinuz
|
||||
* https://releases.rancher.com/os/v1.5.8/rancheros.ipxe
|
||||
* https://releases.rancher.com/os/v1.5.8/rootfs.tar.gz
|
||||
|
||||
#### ARM64 Links
|
||||
|
||||
* https://releases.rancher.com/os/v1.5.1/arm64/initrd
|
||||
* https://releases.rancher.com/os/v1.5.1/arm64/vmlinuz
|
||||
* https://releases.rancher.com/os/v1.5.1/arm64/rootfs_arm64.tar.gz
|
||||
* https://releases.rancher.com/os/v1.5.1/arm64/rancheros-raspberry-pi64.zip
|
||||
* https://releases.rancher.com/os/v1.5.8/arm64/initrd
|
||||
* https://releases.rancher.com/os/v1.5.8/arm64/vmlinuz
|
||||
* https://releases.rancher.com/os/v1.5.8/arm64/rootfs_arm64.tar.gz
|
||||
* https://releases.rancher.com/os/v1.5.8/arm64/rancheros-raspberry-pi64.zip
|
||||
|
||||
#### Cloud Links
|
||||
|
||||
* https://releases.rancher.com/os/v1.5.1/rancheros-openstack.img
|
||||
* https://releases.rancher.com/os/v1.5.1/rancheros-digitalocean.img
|
||||
* https://releases.rancher.com/os/v1.5.1/rancheros-cloudstack.img
|
||||
* https://releases.rancher.com/os/v1.5.1/rancheros-aliyun.vhd
|
||||
* https://releases.rancher.com/os/v1.5.1/rancheros-gce.tar.gz
|
||||
* https://releases.rancher.com/os/v1.5.8/rancheros-openstack.img
|
||||
* https://releases.rancher.com/os/v1.5.8/rancheros-digitalocean.img
|
||||
* https://releases.rancher.com/os/v1.5.8/rancheros-cloudstack.img
|
||||
* https://releases.rancher.com/os/v1.5.8/rancheros-aliyun.vhd
|
||||
* https://releases.rancher.com/os/v1.5.8/rancheros-gce.tar.gz
|
||||
|
||||
#### VMware Links
|
||||
|
||||
* https://releases.rancher.com/os/v1.5.1/vmware/initrd
|
||||
* https://releases.rancher.com/os/v1.5.1/vmware/rancheros.vmdk
|
||||
* https://releases.rancher.com/os/v1.5.1/vmware/rootfs.tar.gz
|
||||
* https://releases.rancher.com/os/v1.5.8/vmware/initrd
|
||||
* https://releases.rancher.com/os/v1.5.8/vmware/rancheros.vmdk
|
||||
* https://releases.rancher.com/os/v1.5.8/vmware/rootfs.tar.gz
|
||||
|
||||
#### Hyper-V Links
|
||||
|
||||
* https://releases.rancher.com/os/v1.5.1/hyperv/initrd
|
||||
* https://releases.rancher.com/os/v1.5.1/hyperv/rootfs.tar.gz
|
||||
* https://releases.rancher.com/os/v1.5.8/hyperv/initrd
|
||||
* https://releases.rancher.com/os/v1.5.8/hyperv/rootfs.tar.gz
|
||||
|
||||
#### Proxmox VE Links
|
||||
|
||||
* https://releases.rancher.com/os/v1.5.1/proxmoxve/initrd
|
||||
* https://releases.rancher.com/os/v1.5.1/proxmoxve/rootfs.tar.gz
|
||||
* https://releases.rancher.com/os/v1.5.8/proxmoxve/initrd
|
||||
* https://releases.rancher.com/os/v1.5.8/proxmoxve/rootfs.tar.gz
|
||||
|
||||
#### 4G-LTE Links
|
||||
|
||||
* https://releases.rancher.com/os/v1.5.1/4glte/initrd
|
||||
* https://releases.rancher.com/os/v1.5.1/4glte/rootfs.tar.gz
|
||||
* https://releases.rancher.com/os/v1.5.8/4glte/initrd
|
||||
* https://releases.rancher.com/os/v1.5.8/4glte/rootfs.tar.gz
|
||||
|
||||
**Note**:
|
||||
1. you can use `http` instead of `https` in the above URLs, e.g. for iPXE.
|
||||
2. you can use `latest` instead of `v1.5.1` in the above URLs if you want to get the latest version.
|
||||
2. you can use `latest` instead of `v1.5.8` in the above URLs if you want to get the latest version.
|
||||
|
||||
### Amazon
|
||||
|
||||
@@ -89,24 +89,22 @@ SSH keys are added to the **`rancher`** user, so you must log in using the **ran
|
||||
|
||||
Region | Type | AMI
|
||||
-------|------|------
|
||||
eu-north-1 | HVM | [ami-0015fc80239e9381e](https://eu-north-1.console.aws.amazon.com/ec2/home?region=eu-north-1#launchInstanceWizard:ami=ami-0015fc80239e9381e)
|
||||
ap-south-1 | HVM | [ami-022c24b20ef4d23df](https://ap-south-1.console.aws.amazon.com/ec2/home?region=ap-south-1#launchInstanceWizard:ami=ami-022c24b20ef4d23df)
|
||||
eu-west-3 | HVM | [ami-0196b012239798b28](https://eu-west-3.console.aws.amazon.com/ec2/home?region=eu-west-3#launchInstanceWizard:ami=ami-0196b012239798b28)
|
||||
eu-west-2 | HVM | [ami-08c80bfb26ba9edbe](https://eu-west-2.console.aws.amazon.com/ec2/home?region=eu-west-2#launchInstanceWizard:ami=ami-08c80bfb26ba9edbe)
|
||||
eu-west-1 | HVM | [ami-0d17a6584d2ef0a25](https://eu-west-1.console.aws.amazon.com/ec2/home?region=eu-west-1#launchInstanceWizard:ami=ami-0d17a6584d2ef0a25)
|
||||
ap-northeast-2 | HVM | [ami-027538d63e7a0113f](https://ap-northeast-2.console.aws.amazon.com/ec2/home?region=ap-northeast-2#launchInstanceWizard:ami=ami-027538d63e7a0113f)
|
||||
ap-northeast-1 | HVM | [ami-08068abb9ae2faafb](https://ap-northeast-1.console.aws.amazon.com/ec2/home?region=ap-northeast-1#launchInstanceWizard:ami=ami-08068abb9ae2faafb)
|
||||
sa-east-1 | HVM | [ami-0d56a6e87e7e80b7c](https://sa-east-1.console.aws.amazon.com/ec2/home?region=sa-east-1#launchInstanceWizard:ami=ami-0d56a6e87e7e80b7c)
|
||||
ca-central-1 | HVM | [ami-0631a990314dfc49d](https://ca-central-1.console.aws.amazon.com/ec2/home?region=ca-central-1#launchInstanceWizard:ami=ami-0631a990314dfc49d)
|
||||
ap-southeast-1 | HVM | [ami-0cfbc54eac1b6ee05](https://ap-southeast-1.console.aws.amazon.com/ec2/home?region=ap-southeast-1#launchInstanceWizard:ami=ami-0cfbc54eac1b6ee05)
|
||||
ap-southeast-2 | HVM | [ami-0829d74b9ed70cb7a](https://ap-southeast-2.console.aws.amazon.com/ec2/home?region=ap-southeast-2#launchInstanceWizard:ami=ami-0829d74b9ed70cb7a)
|
||||
eu-central-1 | HVM | [ami-04c6caa71c063e2a2](https://eu-central-1.console.aws.amazon.com/ec2/home?region=eu-central-1#launchInstanceWizard:ami=ami-04c6caa71c063e2a2)
|
||||
us-east-1 | HVM | [ami-0fe86cb8d9d8e035c](https://us-east-1.console.aws.amazon.com/ec2/home?region=us-east-1#launchInstanceWizard:ami=ami-0fe86cb8d9d8e035c)
|
||||
us-east-2 | HVM | [ami-00769ca587d8e100c](https://us-east-2.console.aws.amazon.com/ec2/home?region=us-east-2#launchInstanceWizard:ami=ami-00769ca587d8e100c)
|
||||
us-west-1 | HVM | [ami-0386c47e4241f6e64](https://us-west-1.console.aws.amazon.com/ec2/home?region=us-west-1#launchInstanceWizard:ami=ami-0386c47e4241f6e64)
|
||||
us-west-2 | HVM | [ami-02722e726f80b7888](https://us-west-2.console.aws.amazon.com/ec2/home?region=us-west-2#launchInstanceWizard:ami=ami-02722e726f80b7888)
|
||||
cn-north-1 | HVM | [ami-0b1be977276a9153e](https://cn-north-1.console.amazonaws.cn/ec2/home?region=cn-north-1#launchInstanceWizard:ami=ami-0b1be977276a9153e)
|
||||
cn-northwest-1 | HVM | [ami-08c6e6474bd4a48d1](https://cn-northwest-1.console.amazonaws.cn/ec2/home?region=cn-northwest-1#launchInstanceWizard:ami=ami-08c6e6474bd4a48d1)
|
||||
eu-north-1 | HVM | [ami-08b189555c5d2d8c3](https://eu-north-1.console.aws.amazon.com/ec2/home?region=eu-north-1#launchInstanceWizard:ami=ami-08b189555c5d2d8c3)
|
||||
ap-south-1 | HVM | [ami-0086964cb1ffc4fdb](https://ap-south-1.console.aws.amazon.com/ec2/home?region=ap-south-1#launchInstanceWizard:ami=ami-0086964cb1ffc4fdb)
|
||||
eu-west-3 | HVM | [ami-088930cafc1ad9f20](https://eu-west-3.console.aws.amazon.com/ec2/home?region=eu-west-3#launchInstanceWizard:ami=ami-088930cafc1ad9f20)
|
||||
eu-west-2 | HVM | [ami-0fdf07cfd187af004](https://eu-west-2.console.aws.amazon.com/ec2/home?region=eu-west-2#launchInstanceWizard:ami=ami-0fdf07cfd187af004)
|
||||
eu-west-1 | HVM | [ami-0cea454c576ececbd](https://eu-west-1.console.aws.amazon.com/ec2/home?region=eu-west-1#launchInstanceWizard:ami=ami-0cea454c576ececbd)
|
||||
ap-northeast-2 | HVM | [ami-0fdb6555f88256d12](https://ap-northeast-2.console.aws.amazon.com/ec2/home?region=ap-northeast-2#launchInstanceWizard:ami=ami-0fdb6555f88256d12)
|
||||
ap-northeast-1 | HVM | [ami-052c75c3e8757bcd9](https://ap-northeast-1.console.aws.amazon.com/ec2/home?region=ap-northeast-1#launchInstanceWizard:ami=ami-052c75c3e8757bcd9)
|
||||
sa-east-1 | HVM | [ami-04e51c9d1edad1bfd](https://sa-east-1.console.aws.amazon.com/ec2/home?region=sa-east-1#launchInstanceWizard:ami=ami-04e51c9d1edad1bfd)
|
||||
ca-central-1 | HVM | [ami-006a1ff3bf21003b3](https://ca-central-1.console.aws.amazon.com/ec2/home?region=ca-central-1#launchInstanceWizard:ami=ami-006a1ff3bf21003b3)
|
||||
ap-southeast-1 | HVM | [ami-03b14c67c74644c2b](https://ap-southeast-1.console.aws.amazon.com/ec2/home?region=ap-southeast-1#launchInstanceWizard:ami=ami-03b14c67c74644c2b)
|
||||
ap-southeast-2 | HVM | [ami-07059c8f12411bfcb](https://ap-southeast-2.console.aws.amazon.com/ec2/home?region=ap-southeast-2#launchInstanceWizard:ami=ami-07059c8f12411bfcb)
|
||||
eu-central-1 | HVM | [ami-0fc1a9332c246bc56](https://eu-central-1.console.aws.amazon.com/ec2/home?region=eu-central-1#launchInstanceWizard:ami=ami-0fc1a9332c246bc56)
|
||||
us-east-1 | HVM | [ami-02fe87f853d560d52](https://us-east-1.console.aws.amazon.com/ec2/home?region=us-east-1#launchInstanceWizard:ami=ami-02fe87f853d560d52)
|
||||
us-east-2 | HVM | [ami-004259f4c48585992](https://us-east-2.console.aws.amazon.com/ec2/home?region=us-east-2#launchInstanceWizard:ami=ami-004259f4c48585992)
|
||||
us-west-1 | HVM | [ami-0b382b76fadc95544](https://us-west-1.console.aws.amazon.com/ec2/home?region=us-west-1#launchInstanceWizard:ami=ami-0b382b76fadc95544)
|
||||
us-west-2 | HVM | [ami-0cdefa6a0646eb511](https://us-west-2.console.aws.amazon.com/ec2/home?region=us-west-2#launchInstanceWizard:ami=ami-0cdefa6a0646eb511)
|
||||
|
||||
Additionally, images are available with support for Amazon EC2 Container Service (ECS) [here](https://rancher.com/docs/os/v1.x/en/installation/amazon-ecs/#amazon-ecs-enabled-amis).
|
||||
|
||||
@@ -130,7 +128,7 @@ Please submit any **Rancher** bugs, issues, and feature requests to [rancher/ran
|
||||
|
||||
## License
|
||||
|
||||
Copyright (c) 2014-2019 [Rancher Labs, Inc.](http://rancher.com)
|
||||
Copyright (c) 2014-2020 [Rancher Labs, Inc.](http://rancher.com)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -36,9 +36,11 @@ import (
|
||||
"github.com/rancher/os/config/cloudinit/datasource/metadata/cloudstack"
|
||||
"github.com/rancher/os/config/cloudinit/datasource/metadata/digitalocean"
|
||||
"github.com/rancher/os/config/cloudinit/datasource/metadata/ec2"
|
||||
"github.com/rancher/os/config/cloudinit/datasource/metadata/exoscale"
|
||||
"github.com/rancher/os/config/cloudinit/datasource/metadata/gce"
|
||||
"github.com/rancher/os/config/cloudinit/datasource/metadata/packet"
|
||||
"github.com/rancher/os/config/cloudinit/datasource/proccmdline"
|
||||
"github.com/rancher/os/config/cloudinit/datasource/proxmox"
|
||||
"github.com/rancher/os/config/cloudinit/datasource/tftp"
|
||||
"github.com/rancher/os/config/cloudinit/datasource/url"
|
||||
"github.com/rancher/os/config/cloudinit/datasource/vmware"
|
||||
@@ -228,7 +230,14 @@ func getDatasources(datasources []string) []datasource.Datasource {
|
||||
|
||||
switch parts[0] {
|
||||
case "*":
|
||||
dss = append(dss, getDatasources([]string{"configdrive", "vmware", "ec2", "digitalocean", "packet", "gce", "cloudstack"})...)
|
||||
dss = append(dss, getDatasources([]string{"configdrive", "vmware", "ec2", "digitalocean", "packet", "gce", "cloudstack", "exoscale", "proxmox"})...)
|
||||
case "proxmox":
|
||||
if root == "" {
|
||||
root = "/media/pve-config"
|
||||
}
|
||||
dss = append(dss, proxmox.NewDataSource(root))
|
||||
case "exoscale":
|
||||
dss = append(dss, exoscale.NewDatasource(root))
|
||||
case "cloudstack":
|
||||
for _, source := range cloudstack.NewDatasource(root) {
|
||||
dss = append(dss, source)
|
||||
|
||||
@@ -137,7 +137,7 @@ func consoleInitFunc() error {
|
||||
}
|
||||
}
|
||||
|
||||
baseSymlink := symLinkEngineBinary(cfg.Rancher.Docker.Engine)
|
||||
baseSymlink := symLinkEngineBinary()
|
||||
|
||||
if _, err := os.Stat(dockerCompletionFile); err == nil {
|
||||
baseSymlink = append(baseSymlink, symlink{
|
||||
|
||||
@@ -86,12 +86,13 @@ func dockerInitAction(c *cli.Context) error {
|
||||
}
|
||||
|
||||
cfg := config.LoadConfig()
|
||||
baseSymlink := symLinkEngineBinary(cfg.Rancher.Docker.Engine)
|
||||
|
||||
for _, link := range baseSymlink {
|
||||
for _, link := range symLinkEngineBinary() {
|
||||
syscall.Unlink(link.newname)
|
||||
if err := os.Symlink(link.oldname, link.newname); err != nil {
|
||||
log.Error(err)
|
||||
if _, err := os.Stat(link.oldname); err == nil {
|
||||
if err := os.Symlink(link.oldname, link.newname); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/rancher/os/pkg/log"
|
||||
"github.com/rancher/os/pkg/util"
|
||||
"github.com/rancher/os/pkg/util/network"
|
||||
"github.com/rancher/os/pkg/util/versions"
|
||||
|
||||
yaml "github.com/cloudfoundry-incubator/candiedyaml"
|
||||
"github.com/codegangsta/cli"
|
||||
@@ -364,8 +365,14 @@ func CurrentEngine() (engine string) {
|
||||
}
|
||||
if t, ok := image.(reference.NamedTagged); ok {
|
||||
tag := t.Tag()
|
||||
if !strings.HasPrefix(tag, "1.") {
|
||||
// TODO: this assumes we only do Docker ce :/
|
||||
|
||||
// compatible with some patch image tags, such as 17.12.1-1,17.06.2-1,...
|
||||
tag = strings.SplitN(tag, "-", 2)[0]
|
||||
|
||||
if !strings.HasPrefix(tag, "1.") && versions.LessThan(tag, "18.09.0") {
|
||||
// >= 18.09.0, docker-<version>
|
||||
// < 18.09.0 and >= 16.03, docker-<version>-ce
|
||||
// < 17.03, docker-<version>
|
||||
tag = tag + "-ce"
|
||||
}
|
||||
return "docker-" + tag
|
||||
|
||||
@@ -86,8 +86,8 @@ var installCommand = cli.Command{
|
||||
Usage: "reboot using kexec",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "stage, s",
|
||||
Usage: "stage services",
|
||||
Name: "save, s",
|
||||
Usage: "save services and images for next booting",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "debug",
|
||||
@@ -179,13 +179,13 @@ func installAction(c *cli.Context) error {
|
||||
cloudConfig = uc
|
||||
}
|
||||
|
||||
stageImages := []string{}
|
||||
if c.Bool("stage") && cloudConfig != "" && installType != "upgrade" {
|
||||
stageImages = install.GetCacheImageList(cloudConfig, cfg)
|
||||
log.Debugf("Will cache these images: %s", stageImages)
|
||||
savedImages := []string{}
|
||||
if c.Bool("save") && cloudConfig != "" && installType != "upgrade" {
|
||||
savedImages = install.GetCacheImageList(cloudConfig, cfg)
|
||||
log.Debugf("Will cache these images: %s", savedImages)
|
||||
}
|
||||
|
||||
if err := runInstall(image, installType, cloudConfig, device, partition, statedir, kappend, force, kexec, isoinstallerloaded, debug, stageImages); err != nil {
|
||||
if err := runInstall(image, installType, cloudConfig, device, partition, statedir, kappend, force, kexec, isoinstallerloaded, debug, savedImages); err != nil {
|
||||
log.WithFields(log.Fields{"err": err}).Fatal("Failed to run install")
|
||||
return err
|
||||
}
|
||||
@@ -198,7 +198,7 @@ func installAction(c *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runInstall(image, installType, cloudConfig, device, partition, statedir, kappend string, force, kexec, isoinstallerloaded, debug bool, stageImages []string) error {
|
||||
func runInstall(image, installType, cloudConfig, device, partition, statedir, kappend string, force, kexec, isoinstallerloaded, debug bool, savedImages []string) error {
|
||||
fmt.Printf("Installing from %s\n", image)
|
||||
|
||||
if !force {
|
||||
@@ -283,8 +283,8 @@ func runInstall(image, installType, cloudConfig, device, partition, statedir, ka
|
||||
if statedir != "" {
|
||||
installerCmd = append(installerCmd, "--statedir", statedir)
|
||||
}
|
||||
if len(stageImages) > 0 {
|
||||
installerCmd = append(installerCmd, "--stage")
|
||||
if len(savedImages) > 0 {
|
||||
installerCmd = append(installerCmd, "--save")
|
||||
}
|
||||
|
||||
// TODO: mount at /mnt for shared mount?
|
||||
@@ -348,8 +348,8 @@ func runInstall(image, installType, cloudConfig, device, partition, statedir, ka
|
||||
return err
|
||||
}
|
||||
|
||||
if len(stageImages) > 0 {
|
||||
return install.RunCacheScript(partition, stageImages)
|
||||
if len(savedImages) > 0 {
|
||||
return install.RunCacheScript(partition, savedImages)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -17,44 +17,86 @@ type ImageConfig struct {
|
||||
Image string `yaml:"image,omitempty"`
|
||||
}
|
||||
|
||||
func GetCacheImageList(cloudconfig string, cfg *config.CloudConfig) []string {
|
||||
stageImages := make([]string, 0)
|
||||
func GetCacheImageList(cloudconfig string, oldcfg *config.CloudConfig) []string {
|
||||
savedImages := make([]string, 0)
|
||||
bytes, err := readConfigFile(cloudconfig)
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{"err": err}).Fatal("Failed to read cloud-config")
|
||||
return stageImages
|
||||
return savedImages
|
||||
}
|
||||
r := make(map[interface{}]interface{})
|
||||
if err := yaml.Unmarshal(bytes, &r); err != nil {
|
||||
log.WithFields(log.Fields{"err": err}).Fatal("Failed to unmarshal cloud-config")
|
||||
return stageImages
|
||||
return savedImages
|
||||
}
|
||||
c := &config.CloudConfig{}
|
||||
if err := util.Convert(r, c); err != nil {
|
||||
newcfg := &config.CloudConfig{}
|
||||
if err := util.Convert(r, newcfg); err != nil {
|
||||
log.WithFields(log.Fields{"err": err}).Fatal("Failed to convert cloud-config")
|
||||
return stageImages
|
||||
return savedImages
|
||||
}
|
||||
for key, value := range c.Rancher.ServicesInclude {
|
||||
|
||||
// services_include
|
||||
for key, value := range newcfg.Rancher.ServicesInclude {
|
||||
if value {
|
||||
bytes, err = network.LoadServiceResource(key, true, cfg)
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{"err": err}).Fatal("Failed to load service resource")
|
||||
return stageImages
|
||||
serviceImage := getServiceImage(key, "", oldcfg, newcfg)
|
||||
if serviceImage != "" {
|
||||
savedImages = append(savedImages, serviceImage)
|
||||
}
|
||||
imageCfg := map[interface{}]ImageConfig{}
|
||||
if err := yaml.Unmarshal(bytes, &imageCfg); err != nil {
|
||||
log.WithFields(log.Fields{"err": err}).Fatal("Failed to unmarshal service")
|
||||
return stageImages
|
||||
}
|
||||
serviceImage := replaceRegistryDomain(imageCfg[key].Image)
|
||||
slice := strings.SplitN(serviceImage, "/", 2)
|
||||
if slice[0] == "${REGISTRY_DOMAIN}" {
|
||||
serviceImage = slice[1]
|
||||
}
|
||||
stageImages = append(stageImages, serviceImage)
|
||||
}
|
||||
}
|
||||
return stageImages
|
||||
|
||||
// console
|
||||
newConsole := newcfg.Rancher.Console
|
||||
if newConsole != "" && newConsole != "default" {
|
||||
consoleImage := getServiceImage(newConsole, "console", oldcfg, newcfg)
|
||||
if consoleImage != "" {
|
||||
savedImages = append(savedImages, consoleImage)
|
||||
}
|
||||
}
|
||||
|
||||
// docker engine
|
||||
newEngine := newcfg.Rancher.Docker.Engine
|
||||
if newEngine != "" && newEngine != oldcfg.Rancher.Docker.Engine {
|
||||
engineImage := getServiceImage(newEngine, "docker", oldcfg, newcfg)
|
||||
if engineImage != "" {
|
||||
savedImages = append(savedImages, engineImage)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return savedImages
|
||||
}
|
||||
|
||||
func getServiceImage(service, svctype string, oldcfg, newcfg *config.CloudConfig) string {
|
||||
var (
|
||||
serviceImage string
|
||||
bytes []byte
|
||||
err error
|
||||
)
|
||||
if len(newcfg.Rancher.Repositories.ToArray()) > 0 {
|
||||
bytes, err = network.LoadServiceResource(service, true, newcfg)
|
||||
} else {
|
||||
bytes, err = network.LoadServiceResource(service, true, oldcfg)
|
||||
}
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{"err": err}).Fatal("Failed to load service resource")
|
||||
return serviceImage
|
||||
}
|
||||
imageConfig := map[interface{}]ImageConfig{}
|
||||
if err = yaml.Unmarshal(bytes, &imageConfig); err != nil {
|
||||
log.WithFields(log.Fields{"err": err}).Fatal("Failed to unmarshal service")
|
||||
return serviceImage
|
||||
}
|
||||
switch svctype {
|
||||
case "console":
|
||||
serviceImage = formatImage(imageConfig["console"].Image, oldcfg, newcfg)
|
||||
case "docker":
|
||||
serviceImage = formatImage(imageConfig["docker"].Image, oldcfg, newcfg)
|
||||
default:
|
||||
serviceImage = formatImage(imageConfig[service].Image, oldcfg, newcfg)
|
||||
}
|
||||
|
||||
return serviceImage
|
||||
}
|
||||
|
||||
func RunCacheScript(partition string, images []string) error {
|
||||
@@ -74,10 +116,14 @@ func readConfigFile(file string) ([]byte, error) {
|
||||
return content, err
|
||||
}
|
||||
|
||||
func replaceRegistryDomain(image string) string {
|
||||
slice := strings.SplitN(image, "/", 2)
|
||||
if slice[0] == "${REGISTRY_DOMAIN}" {
|
||||
return slice[1]
|
||||
func formatImage(image string, oldcfg, newcfg *config.CloudConfig) string {
|
||||
registryDomain := newcfg.Rancher.Environment["REGISTRY_DOMAIN"]
|
||||
if registryDomain == "" {
|
||||
registryDomain = oldcfg.Rancher.Environment["REGISTRY_DOMAIN"]
|
||||
}
|
||||
image = strings.Replace(image, "${REGISTRY_DOMAIN}", registryDomain, -1)
|
||||
|
||||
image = strings.Replace(image, "${SUFFIX}", config.Suffix, -1)
|
||||
|
||||
return image
|
||||
}
|
||||
|
||||
@@ -33,29 +33,27 @@ func formatImage(image string, cfg *config.CloudConfig) string {
|
||||
return image
|
||||
}
|
||||
|
||||
func symLinkEngineBinary(version string) []symlink {
|
||||
func symLinkEngineBinary() []symlink {
|
||||
baseSymlink := []symlink{
|
||||
{"/usr/share/ros/os-release", "/usr/lib/os-release"},
|
||||
{"/usr/share/ros/os-release", "/etc/os-release"},
|
||||
|
||||
{"/var/lib/rancher/engine/docker", "/usr/bin/docker"},
|
||||
{"/var/lib/rancher/engine/dockerd", "/usr/bin/dockerd"},
|
||||
{"/var/lib/rancher/engine/docker-init", "/usr/bin/docker-init"},
|
||||
{"/var/lib/rancher/engine/docker-proxy", "/usr/bin/docker-proxy"},
|
||||
{"/usr/share/ros/os-release", "/usr/lib/os-release"},
|
||||
{"/usr/share/ros/os-release", "/etc/os-release"},
|
||||
}
|
||||
if strings.Contains(version, "18.09") {
|
||||
baseSymlink = append(baseSymlink, []symlink{
|
||||
{"/var/lib/rancher/engine/containerd", "/usr/bin/containerd"},
|
||||
{"/var/lib/rancher/engine/ctr", "/usr/bin/ctr"},
|
||||
{"/var/lib/rancher/engine/containerd-shim", "/usr/bin/containerd-shim"},
|
||||
{"/var/lib/rancher/engine/runc", "/usr/bin/runc"},
|
||||
}...)
|
||||
} else {
|
||||
baseSymlink = append(baseSymlink, []symlink{
|
||||
{"/var/lib/rancher/engine/docker-containerd", "/usr/bin/docker-containerd"},
|
||||
{"/var/lib/rancher/engine/docker-containerd-ctr", "/usr/bin/docker-containerd-ctr"},
|
||||
{"/var/lib/rancher/engine/docker-containerd-shim", "/usr/bin/docker-containerd-shim"},
|
||||
{"/var/lib/rancher/engine/docker-runc", "/usr/bin/docker-runc"},
|
||||
}...)
|
||||
|
||||
// >= 18.09.0
|
||||
{"/var/lib/rancher/engine/containerd", "/usr/bin/containerd"},
|
||||
{"/var/lib/rancher/engine/ctr", "/usr/bin/ctr"},
|
||||
{"/var/lib/rancher/engine/containerd-shim", "/usr/bin/containerd-shim"},
|
||||
{"/var/lib/rancher/engine/runc", "/usr/bin/runc"},
|
||||
|
||||
// < 18.09.0
|
||||
{"/var/lib/rancher/engine/docker-containerd", "/usr/bin/docker-containerd"},
|
||||
{"/var/lib/rancher/engine/docker-containerd-ctr", "/usr/bin/docker-containerd-ctr"},
|
||||
{"/var/lib/rancher/engine/docker-containerd-shim", "/usr/bin/docker-containerd-shim"},
|
||||
{"/var/lib/rancher/engine/docker-runc", "/usr/bin/docker-runc"},
|
||||
}
|
||||
return baseSymlink
|
||||
}
|
||||
|
||||
92
config/cloudinit/datasource/metadata/exoscale/metadata.go
Normal file
92
config/cloudinit/datasource/metadata/exoscale/metadata.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package exoscale
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/rancher/os/config/cloudinit/datasource"
|
||||
"github.com/rancher/os/config/cloudinit/datasource/metadata"
|
||||
"github.com/rancher/os/config/cloudinit/pkg"
|
||||
"github.com/rancher/os/pkg/log"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultAddress = "http://169.254.169.254/"
|
||||
apiVersion = "1.0/"
|
||||
userdataPath = apiVersion + "user-data"
|
||||
metadataPath = apiVersion + "meta-data/"
|
||||
)
|
||||
|
||||
type MetadataService struct {
|
||||
metadata.Service
|
||||
}
|
||||
|
||||
func NewDatasource(root string) *MetadataService {
|
||||
if root == "" {
|
||||
root = defaultAddress
|
||||
}
|
||||
|
||||
return &MetadataService{
|
||||
metadata.NewDatasourceWithCheckPath(
|
||||
root,
|
||||
apiVersion,
|
||||
metadataPath,
|
||||
userdataPath,
|
||||
metadataPath,
|
||||
nil,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func (ms MetadataService) IsAvailable() bool {
|
||||
checkURL := ms.Root + ms.IsAvailableCheckPath
|
||||
var err error
|
||||
_, err = ms.Client.GetRetry(checkURL)
|
||||
if err != nil {
|
||||
log.Errorf("%s: %s (lastError: %v)", "IsAvailable", checkURL, err)
|
||||
}
|
||||
return (err == nil)
|
||||
}
|
||||
|
||||
func (ms MetadataService) AvailabilityChanges() bool {
|
||||
// TODO: if it can't find the network, maybe we can start it?
|
||||
return false
|
||||
}
|
||||
|
||||
func (ms MetadataService) FetchMetadata() (datasource.Metadata, error) {
|
||||
metadata := datasource.Metadata{}
|
||||
|
||||
if sshKeys, err := ms.FetchAttributes("public-keys"); err == nil {
|
||||
metadata.SSHPublicKeys = map[string]string{}
|
||||
for i, sshkey := range sshKeys {
|
||||
log.Printf("Found SSH key %d", i)
|
||||
metadata.SSHPublicKeys[strconv.Itoa(i)] = sshkey
|
||||
}
|
||||
} else if _, ok := err.(pkg.ErrNotFound); !ok {
|
||||
return metadata, err
|
||||
}
|
||||
|
||||
if hostname, err := ms.FetchAttribute("local-hostname"); err == nil {
|
||||
metadata.Hostname = strings.Split(hostname, " ")[0]
|
||||
} else if _, ok := err.(pkg.ErrNotFound); !ok {
|
||||
return metadata, err
|
||||
}
|
||||
|
||||
if localAddr, err := ms.FetchAttribute("local-ipv4"); err == nil {
|
||||
metadata.PrivateIPv4 = net.ParseIP(localAddr)
|
||||
} else if _, ok := err.(pkg.ErrNotFound); !ok {
|
||||
return metadata, err
|
||||
}
|
||||
if publicAddr, err := ms.FetchAttribute("public-ipv4"); err == nil {
|
||||
metadata.PublicIPv4 = net.ParseIP(publicAddr)
|
||||
} else if _, ok := err.(pkg.ErrNotFound); !ok {
|
||||
return metadata, err
|
||||
}
|
||||
|
||||
return metadata, nil
|
||||
}
|
||||
|
||||
func (ms MetadataService) Type() string {
|
||||
return "exoscale-metadata-service"
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package exoscale
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/rancher/os/config/cloudinit/datasource"
|
||||
"github.com/rancher/os/config/cloudinit/datasource/metadata"
|
||||
"github.com/rancher/os/config/cloudinit/datasource/metadata/test"
|
||||
"github.com/rancher/os/config/cloudinit/pkg"
|
||||
)
|
||||
|
||||
func TestType(t *testing.T) {
|
||||
want := "exoscale-metadata-service"
|
||||
if kind := (MetadataService{}).Type(); kind != want {
|
||||
t.Fatalf("bad type: want %q, got %q", want, kind)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFetchMetadata(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
root string
|
||||
metadataPath string
|
||||
resources map[string]string
|
||||
expect datasource.Metadata
|
||||
clientErr error
|
||||
expectErr error
|
||||
}{
|
||||
{
|
||||
root: "/",
|
||||
metadataPath: "1.0/meta-data/",
|
||||
resources: map[string]string{
|
||||
"/1.0/meta-data/local-hostname": "host",
|
||||
"/1.0/meta-data/local-ipv4": "1.2.3.4",
|
||||
"/1.0/meta-data/public-ipv4": "5.6.7.8",
|
||||
"/1.0/meta-data/public-keys": "key\n",
|
||||
},
|
||||
expect: datasource.Metadata{
|
||||
Hostname: "host",
|
||||
PrivateIPv4: net.ParseIP("1.2.3.4"),
|
||||
PublicIPv4: net.ParseIP("5.6.7.8"),
|
||||
SSHPublicKeys: map[string]string{"0": "key"},
|
||||
},
|
||||
},
|
||||
{
|
||||
root: "/",
|
||||
metadataPath: "1.0/meta-data/",
|
||||
resources: map[string]string{
|
||||
"/1.0/meta-data/local-hostname": "host domain another_domain",
|
||||
"/1.0/meta-data/local-ipv4": "21.2.3.4",
|
||||
"/1.0/meta-data/public-ipv4": "25.6.7.8",
|
||||
"/1.0/meta-data/public-keys": "key\n",
|
||||
},
|
||||
expect: datasource.Metadata{
|
||||
Hostname: "host",
|
||||
PrivateIPv4: net.ParseIP("21.2.3.4"),
|
||||
PublicIPv4: net.ParseIP("25.6.7.8"),
|
||||
SSHPublicKeys: map[string]string{"0": "key"},
|
||||
},
|
||||
},
|
||||
{
|
||||
clientErr: pkg.ErrTimeout{Err: fmt.Errorf("test error")},
|
||||
expectErr: pkg.ErrTimeout{Err: fmt.Errorf("test error")},
|
||||
},
|
||||
} {
|
||||
service := &MetadataService{metadata.Service{
|
||||
Root: tt.root,
|
||||
Client: &test.HTTPClient{Resources: tt.resources, Err: tt.clientErr},
|
||||
MetadataPath: tt.metadataPath,
|
||||
}}
|
||||
metadata, err := service.FetchMetadata()
|
||||
if Error(err) != Error(tt.expectErr) {
|
||||
t.Fatalf("bad error (%q): \nwant %q, \ngot %q\n", tt.resources, tt.expectErr, err)
|
||||
}
|
||||
if !reflect.DeepEqual(tt.expect, metadata) {
|
||||
t.Fatalf("bad fetch (%q): \nwant %#v, \ngot %#v\n", tt.resources, tt.expect, metadata)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Error(err error) string {
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
114
config/cloudinit/datasource/proxmox/proxmox.go
Normal file
114
config/cloudinit/datasource/proxmox/proxmox.go
Normal file
@@ -0,0 +1,114 @@
|
||||
package proxmox
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"syscall"
|
||||
|
||||
"github.com/rancher/os/config/cloudinit/datasource"
|
||||
"github.com/rancher/os/pkg/log"
|
||||
"github.com/rancher/os/pkg/util"
|
||||
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
)
|
||||
|
||||
const (
|
||||
configDev = "/dev/sr0"
|
||||
configDevMountPoint = "/media/pve-config"
|
||||
)
|
||||
|
||||
type Proxmox struct {
|
||||
root string
|
||||
readFile func(filename string) ([]byte, error)
|
||||
lastError error
|
||||
availabilityChanges bool
|
||||
}
|
||||
|
||||
func NewDataSource(root string) *Proxmox {
|
||||
return &Proxmox{root, ioutil.ReadFile, nil, true}
|
||||
}
|
||||
|
||||
func (pve *Proxmox) IsAvailable() bool {
|
||||
if pve.root == configDevMountPoint {
|
||||
pve.lastError = MountConfigDrive()
|
||||
if pve.lastError != nil {
|
||||
log.Error(pve.lastError)
|
||||
pve.availabilityChanges = false
|
||||
return false
|
||||
}
|
||||
defer pve.Finish()
|
||||
}
|
||||
|
||||
_, pve.lastError = os.Stat(pve.root)
|
||||
return !os.IsNotExist(pve.lastError)
|
||||
}
|
||||
|
||||
func (pve *Proxmox) Finish() error {
|
||||
return UnmountConfigDrive()
|
||||
}
|
||||
|
||||
func (pve *Proxmox) String() string {
|
||||
if pve.lastError != nil {
|
||||
return fmt.Sprintf("%s: %s (lastError: %v)", pve.Type(), pve.root, pve.lastError)
|
||||
}
|
||||
return fmt.Sprintf("%s: %s", pve.Type(), pve.root)
|
||||
}
|
||||
|
||||
func (pve *Proxmox) AvailabilityChanges() bool {
|
||||
return pve.availabilityChanges
|
||||
}
|
||||
|
||||
func (pve *Proxmox) ConfigRoot() string {
|
||||
return pve.root
|
||||
}
|
||||
|
||||
func (pve *Proxmox) FetchMetadata() (metadata datasource.Metadata, err error) {
|
||||
return datasource.Metadata{}, nil
|
||||
}
|
||||
|
||||
func (pve *Proxmox) FetchUserdata() ([]byte, error) {
|
||||
return pve.tryReadFile(path.Join(pve.root, "user-data"))
|
||||
}
|
||||
|
||||
func (pve *Proxmox) Type() string {
|
||||
return "proxmox"
|
||||
}
|
||||
|
||||
func (pve *Proxmox) tryReadFile(filename string) ([]byte, error) {
|
||||
if pve.root == configDevMountPoint {
|
||||
pve.lastError = MountConfigDrive()
|
||||
if pve.lastError != nil {
|
||||
log.Error(pve.lastError)
|
||||
return nil, pve.lastError
|
||||
}
|
||||
defer pve.Finish()
|
||||
}
|
||||
log.Debugf("Attempting to read from %q\n", filename)
|
||||
data, err := pve.readFile(filename)
|
||||
if os.IsNotExist(err) {
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
log.Errorf("ERROR read cloud-config file(%s) - err: %q", filename, err)
|
||||
}
|
||||
return data, err
|
||||
}
|
||||
|
||||
func MountConfigDrive() error {
|
||||
if err := os.MkdirAll(configDevMountPoint, 700); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fsType, err := util.GetFsType(configDev)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return mount.Mount(configDev, configDevMountPoint, fsType, "ro")
|
||||
}
|
||||
|
||||
func UnmountConfigDrive() error {
|
||||
return syscall.Unmount(configDevMountPoint, 0)
|
||||
}
|
||||
77
config/cloudinit/datasource/proxmox/proxmox_test.go
Normal file
77
config/cloudinit/datasource/proxmox/proxmox_test.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package proxmox
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rancher/os/config/cloudinit/datasource/test"
|
||||
)
|
||||
|
||||
func TestFetchUserdata(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
root string
|
||||
files test.MockFilesystem
|
||||
userdata string
|
||||
}{
|
||||
{
|
||||
root: "/",
|
||||
files: test.NewMockFilesystem(),
|
||||
userdata: "",
|
||||
},
|
||||
{
|
||||
root: "/media/config",
|
||||
files: test.NewMockFilesystem(test.File{Path: "/media/config/user-data", Contents: "userdata"}),
|
||||
userdata: "userdata",
|
||||
},
|
||||
} {
|
||||
pve := Proxmox{tt.root, tt.files.ReadFile, nil, true}
|
||||
userdata, err := pve.FetchUserdata()
|
||||
if err != nil {
|
||||
t.Fatalf("bad error for %+v: want %v, got %q", tt, nil, err)
|
||||
}
|
||||
if string(userdata) != tt.userdata {
|
||||
t.Fatalf("bad userdata for %+v: want %q, got %q", tt, tt.userdata, userdata)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigRoot(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
root string
|
||||
configRoot string
|
||||
}{
|
||||
{
|
||||
root: "/",
|
||||
configRoot: "/",
|
||||
},
|
||||
{
|
||||
root: "/media/pve-config",
|
||||
configRoot: "/media/pve-config",
|
||||
},
|
||||
} {
|
||||
pve := Proxmox{tt.root, nil, nil, true}
|
||||
if configRoot := pve.ConfigRoot(); configRoot != tt.configRoot {
|
||||
t.Fatalf("bad config root for %q: want %q, got %q", tt, tt.configRoot, configRoot)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewDataSource(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
root string
|
||||
expectRoot string
|
||||
}{
|
||||
{
|
||||
root: "",
|
||||
expectRoot: "",
|
||||
},
|
||||
{
|
||||
root: "/media/pve-config",
|
||||
expectRoot: "/media/pve-config",
|
||||
},
|
||||
} {
|
||||
service := NewDataSource(tt.root)
|
||||
if service.root != tt.expectRoot {
|
||||
t.Fatalf("bad root (%q): want %q, got %q", tt.root, tt.expectRoot, service.root)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,11 +18,12 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
neturl "net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/rancher/os/pkg/log"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -120,14 +121,14 @@ func (h *HTTPClient) GetRetry(rawurl string) ([]byte, error) {
|
||||
|
||||
duration := h.InitialBackoff
|
||||
for retry := 1; retry <= h.MaxRetries; retry++ {
|
||||
log.Printf("Fetching data from %s. Attempt #%d", dataURL, retry)
|
||||
log.Debugf("Fetching data from %s. Attempt #%d", dataURL, retry)
|
||||
|
||||
data, err := h.Get(dataURL)
|
||||
switch err.(type) {
|
||||
case ErrNetwork:
|
||||
log.Printf(err.Error())
|
||||
log.Debugf(err.Error())
|
||||
case ErrServer:
|
||||
log.Printf(err.Error())
|
||||
log.Debugf(err.Error())
|
||||
case ErrNotFound:
|
||||
return data, err
|
||||
default:
|
||||
@@ -135,7 +136,7 @@ func (h *HTTPClient) GetRetry(rawurl string) ([]byte, error) {
|
||||
}
|
||||
|
||||
duration = ExpBackoff(duration, h.MaxBackoff)
|
||||
log.Printf("Sleeping for %v...", duration)
|
||||
log.Debugf("Sleeping for %v...", duration)
|
||||
time.Sleep(duration)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package cmdline
|
||||
import (
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/rancher/os/pkg/util"
|
||||
|
||||
@@ -125,11 +126,34 @@ func UnmarshalOrReturnString(value string) (result interface{}) {
|
||||
return
|
||||
}
|
||||
|
||||
//splitCmdLine splits on spaces except when a space is within a quoted or bracketed string.
|
||||
func splitCmdLine(cmdLine string) []string {
|
||||
lastRune := rune(0)
|
||||
f := func(c rune) bool {
|
||||
switch {
|
||||
case c == lastRune:
|
||||
lastRune = rune(0)
|
||||
return false
|
||||
case lastRune != rune(0):
|
||||
return false
|
||||
case unicode.In(c, unicode.Quotation_Mark):
|
||||
lastRune = c
|
||||
return false
|
||||
case c == '[':
|
||||
lastRune = ']'
|
||||
return false
|
||||
default:
|
||||
return c == ' '
|
||||
}
|
||||
}
|
||||
return strings.FieldsFunc(cmdLine, f)
|
||||
}
|
||||
|
||||
func Parse(cmdLine string, parseAll bool) map[interface{}]interface{} {
|
||||
result := map[interface{}]interface{}{}
|
||||
|
||||
outer:
|
||||
for _, part := range strings.Split(cmdLine, " ") {
|
||||
for _, part := range splitCmdLine(cmdLine) {
|
||||
if strings.HasPrefix(part, "cc.") {
|
||||
part = part[3:]
|
||||
} else if !strings.HasPrefix(part, "rancher.") {
|
||||
|
||||
@@ -123,6 +123,12 @@ func TestCmdlineParse(t *testing.T) {
|
||||
},
|
||||
}, cmdline.Parse("rancher.key=a\nb", false), false)
|
||||
|
||||
assert.Equal(map[interface{}]interface{}{
|
||||
"rancher": map[interface{}]interface{}{
|
||||
"key": "a b",
|
||||
},
|
||||
}, cmdline.Parse("rancher.key='a b'", false), false)
|
||||
|
||||
assert.Equal(map[interface{}]interface{}{
|
||||
"rancher": map[interface{}]interface{}{
|
||||
"key": "a:b",
|
||||
@@ -158,6 +164,24 @@ func TestCmdlineParse(t *testing.T) {
|
||||
"strArray": []interface{}{"url:http://192.168.1.100/cloud-config?a=b"},
|
||||
},
|
||||
}, cmdline.Parse("rancher.strArray=[url:http://192.168.1.100/cloud-config?a=b]", false), false)
|
||||
|
||||
assert.Equal(map[interface{}]interface{}{
|
||||
"rancher": map[interface{}]interface{}{
|
||||
"strArray": []interface{}{"part1 part2", "part3"},
|
||||
},
|
||||
}, cmdline.Parse("rancher.strArray=['part1 part2',part3]", false), false)
|
||||
|
||||
assert.Equal(map[interface{}]interface{}{
|
||||
"rancher": map[interface{}]interface{}{
|
||||
"strArray": []interface{}{"part1 part2", "part3"},
|
||||
},
|
||||
}, cmdline.Parse("rancher.strArray=[\"part1 part2\",part3]", false), false)
|
||||
|
||||
assert.Equal(map[interface{}]interface{}{
|
||||
"rancher": map[interface{}]interface{}{
|
||||
"strArray": []interface{}{"part1 part2", "part3"},
|
||||
},
|
||||
}, cmdline.Parse("rancher.strArray=[ \"part1 part2\", part3 ]", false), false)
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
|
||||
@@ -55,6 +55,7 @@ var schema = `{
|
||||
"restart_services": {"type": "array"},
|
||||
"hypervisor_service": {"type": "boolean"},
|
||||
"shutdown_timeout": {"type": "integer"},
|
||||
"http_load_retries": {"type": "integer"},
|
||||
"preload_wait": {"type": "boolean"}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -152,6 +152,7 @@ type RancherConfig struct {
|
||||
RestartServices []string `yaml:"restart_services,omitempty"`
|
||||
HypervisorService bool `yaml:"hypervisor_service,omitempty"`
|
||||
ShutdownTimeout int `yaml:"shutdown_timeout,omitempty"`
|
||||
HTTPLoadRetries int `yaml:"http_load_retries,omitempty"`
|
||||
PreloadWait bool `yaml:"preload_wait,omitempty"`
|
||||
}
|
||||
|
||||
|
||||
@@ -3,46 +3,59 @@ set -e -x
|
||||
|
||||
gateway_address="http://ros.rancher.io/gateway"
|
||||
|
||||
_sigProcess() {
|
||||
sigProcess() {
|
||||
echo "SIGINT/SIGTERM signal..."
|
||||
kill -9 $$
|
||||
}
|
||||
|
||||
trap _sigProcess SIGINT SIGKILL SIGTERM
|
||||
trap sigProcess SIGINT SIGKILL SIGTERM
|
||||
|
||||
__read_policy() {
|
||||
read_policy() {
|
||||
policy=`ros c get rancher.upgrade.policy`
|
||||
if [ -z $policy ]; then
|
||||
if [[ -z ${policy} ]]; then
|
||||
echo "can not read upgrade.policy"
|
||||
exit 1
|
||||
return 1
|
||||
fi
|
||||
return $(($policy))
|
||||
}
|
||||
|
||||
__report_activity() {
|
||||
report_activity() {
|
||||
arch=`uname -m`
|
||||
uuid=`cat /sys/class/dmi/id/product_uuid || true`
|
||||
release=`ros -v | awk '{print $2}'`
|
||||
response=`wget --server-response ${gateway_address}/report --header 'Accept: application/json' --header 'Content-type: application/json' --header "arch: $arch" --header "uuid: $uuid" --header "release: $release" 2>&1 | awk '/^ HTTP/{print $2}'`
|
||||
if [ $response -ge 200 -a $response -le 300 ]; then
|
||||
if [[ -n ${response} && ${response} -ge 200 && ${response} -le 300 ]]; then
|
||||
echo "report activity success"
|
||||
else
|
||||
echo "report activity failed"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
__upgrade_operate() {
|
||||
upgrade_operate() {
|
||||
recommend_version=`wget ${gateway_address}/version -q -O -`
|
||||
case $policy in
|
||||
case ${policy} in
|
||||
download)
|
||||
echo "upgrade.policy is 'download'"
|
||||
__report_activity
|
||||
system-docker pull $recommend_version
|
||||
report_activity
|
||||
if [[ ${recommend_version} ]];
|
||||
then
|
||||
system-docker pull ${recommend_version}
|
||||
else
|
||||
echo "pull recommend image failed"
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
auto)
|
||||
echo "upgrade.policy is 'auto'"
|
||||
__report_activity
|
||||
ros os upgrade -i $recommend_version -f
|
||||
report_activity
|
||||
if [[ ${recommend_version} ]];
|
||||
then
|
||||
ros os upgrade -i ${recommend_version} -f
|
||||
else
|
||||
echo "execute ros os upgrade failed"
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
none)
|
||||
echo "upgrade.policy is 'none'"
|
||||
@@ -53,6 +66,12 @@ __upgrade_operate() {
|
||||
esac
|
||||
}
|
||||
|
||||
__read_policy
|
||||
read_policy
|
||||
|
||||
__upgrade_operate
|
||||
n=0
|
||||
until [[ ${n} -ge 5 ]]
|
||||
do
|
||||
upgrade_operate && break
|
||||
n=$[$n+1]
|
||||
sleep 5
|
||||
done
|
||||
@@ -1,3 +1,4 @@
|
||||
FROM rancher/os-base
|
||||
COPY . /
|
||||
RUN chmod 644 /etc/logrotate.conf
|
||||
ENTRYPOINT ["/usr/bin/entrypoint.sh"]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
rancher:
|
||||
shutdown_timeout: 60
|
||||
http_load_retries: 6
|
||||
environment:
|
||||
VERSION: {{.VERSION}}
|
||||
SUFFIX: {{.SUFFIX}}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/rancher/os/config"
|
||||
"github.com/rancher/os/pkg/log"
|
||||
"github.com/rancher/os/pkg/util/network"
|
||||
|
||||
"github.com/docker/docker/layer"
|
||||
dockerclient "github.com/docker/engine-api/client"
|
||||
@@ -57,6 +58,27 @@ func (s *Service) missingImage() bool {
|
||||
return false
|
||||
}
|
||||
client := s.context.ClientFactory.Create(s)
|
||||
|
||||
// If it is already built-in, we should use tag image
|
||||
// use case: open-vmtools with another REGISTRY_DOMAIN setting
|
||||
registryDomain := config.LoadConfig().Rancher.Environment["REGISTRY_DOMAIN"]
|
||||
if registryDomain != "docker.io" && strings.Index(image, registryDomain) >= 0 {
|
||||
orginImage := strings.SplitN(image, "/", 2)[1]
|
||||
_, _, err := client.ImageInspectWithRaw(context.Background(), orginImage, false)
|
||||
if err == nil {
|
||||
log.Infof("Will tag image %s to %s", orginImage, image)
|
||||
options := types.ImageTagOptions{
|
||||
ImageID: orginImage,
|
||||
RepositoryName: strings.SplitN(image, ":", 2)[0],
|
||||
Tag: strings.SplitN(image, ":", 2)[1],
|
||||
Force: false,
|
||||
}
|
||||
if err := client.ImageTag(context.Background(), options); err != nil {
|
||||
log.Warnf("Failed to tag image from %s to %s: %v", orginImage, image, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_, _, err := client.ImageInspectWithRaw(context.Background(), image, false)
|
||||
return err != nil
|
||||
}
|
||||
@@ -134,6 +156,13 @@ func (s *Service) shouldRebuild(ctx context.Context) (bool, error) {
|
||||
func (s *Service) Up(ctx context.Context, options options.Up) error {
|
||||
labels := s.Config().Labels
|
||||
|
||||
// wait for networking if necessary
|
||||
if after := labels["io.rancher.os.after"]; after == "network" {
|
||||
if err := network.AllDefaultGWOK(network.DefaultRoutesCheckTimeout); err != nil {
|
||||
log.Warnf("Timeout to wait for the networking ready: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.Service.Create(ctx, options.Create); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cloudinit
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
@@ -27,6 +28,22 @@ func CloudInit(cfg *config.CloudConfig) (*config.CloudConfig, error) {
|
||||
cfg.Rancher.CloudInit.Datasources = append(cfg.Rancher.CloudInit.Datasources, hypervisor)
|
||||
}
|
||||
|
||||
exoscale, err := onlyExoscale()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
if exoscale {
|
||||
cfg.Rancher.CloudInit.Datasources = append([]string{"exoscale"}, cfg.Rancher.CloudInit.Datasources...)
|
||||
}
|
||||
|
||||
proxmox, err := onlyProxmox()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
if proxmox {
|
||||
cfg.Rancher.CloudInit.Datasources = append([]string{"proxmox"}, cfg.Rancher.CloudInit.Datasources...)
|
||||
}
|
||||
|
||||
if len(cfg.Rancher.CloudInit.Datasources) == 0 {
|
||||
log.Info("No specific datasources, ignore cloudinit")
|
||||
return cfg, nil
|
||||
@@ -133,3 +150,21 @@ func onlyDigitalOcean(datasources []string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func onlyExoscale() (bool, error) {
|
||||
f, err := ioutil.ReadFile("/sys/class/dmi/id/product_name")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return strings.HasPrefix(string(f), "Exoscale"), nil
|
||||
}
|
||||
|
||||
func onlyProxmox() (bool, error) {
|
||||
f, err := ioutil.ReadFile("/sys/class/dmi/id/product_name")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return strings.Contains(string(f), "Proxmox"), nil
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/hex"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/rancher/os/pkg/log"
|
||||
)
|
||||
@@ -44,7 +45,15 @@ func cacheAdd(location string, data []byte) {
|
||||
os.Rename(tempFile.Name(), cacheFile)
|
||||
}
|
||||
|
||||
func cacheRemove(location string) error {
|
||||
func cacheMove(location string) (string, error) {
|
||||
cacheFile := cacheDirectory + locationHash(location)
|
||||
return os.Remove(cacheFile)
|
||||
tempFile := cacheFile + "_temp"
|
||||
if err := os.Rename(cacheFile, tempFile); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return tempFile, nil
|
||||
}
|
||||
|
||||
func cacheMoveBack(name string) error {
|
||||
return os.Rename(name, strings.TrimRight(name, "_temp"))
|
||||
}
|
||||
|
||||
@@ -4,11 +4,12 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/rancher/os/config"
|
||||
httpRetry "github.com/rancher/os/config/cloudinit/pkg"
|
||||
"github.com/rancher/os/pkg/log"
|
||||
|
||||
yaml "github.com/cloudfoundry-incubator/candiedyaml"
|
||||
@@ -101,30 +102,27 @@ func LoadFromNetworkWithCache(location string) ([]byte, error) {
|
||||
}
|
||||
|
||||
func LoadFromNetwork(location string) ([]byte, error) {
|
||||
SetProxyEnvironmentVariables()
|
||||
|
||||
var err error
|
||||
|
||||
var resp *http.Response
|
||||
log.Debugf("LoadFromNetwork(%s)", location)
|
||||
resp, err = http.Get(location)
|
||||
log.Debugf("LoadFromNetwork(%s) returned %v, %v", location, resp, err)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("non-200 http response: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
bytes, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cacheAdd(location, bytes)
|
||||
return bytes, nil
|
||||
if err = AllDefaultGWOK(DefaultRoutesCheckTimeout); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
SetProxyEnvironmentVariables()
|
||||
|
||||
return nil, err
|
||||
net.DefaultResolver.PreferGo = true
|
||||
cfg := config.LoadConfig()
|
||||
client := httpRetry.NewHTTPClient()
|
||||
client.MaxRetries = cfg.Rancher.HTTPLoadRetries
|
||||
log.Debugf("start trying LoadFromNetwork(%s)", location)
|
||||
bytes, err := client.GetRetry(location)
|
||||
if err != nil {
|
||||
log.Errorf("failed to LoadFromNetwork: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
log.Debugf("LoadFromNetwork(%s) returned", location)
|
||||
cacheAdd(location, bytes)
|
||||
|
||||
return bytes, nil
|
||||
}
|
||||
|
||||
func LoadResource(location string, network bool) ([]byte, error) {
|
||||
@@ -219,12 +217,24 @@ func UpdateCaches(urls []string, key string) error {
|
||||
}
|
||||
|
||||
func UpdateCache(location string) ([]byte, error) {
|
||||
if err := cacheRemove(location); err != nil {
|
||||
return []byte{}, err
|
||||
// move cache file to temp directory
|
||||
tempFile, err := cacheMove(location)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
content, err := LoadResource(location, true)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
// move back old cache file
|
||||
if err := cacheMoveBack(tempFile); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ioutil.ReadFile(location)
|
||||
}
|
||||
// remove old cache file
|
||||
if err := os.Remove(tempFile); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return content, nil
|
||||
}
|
||||
|
||||
111
pkg/util/network/route.go
Normal file
111
pkg/util/network/route.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/rancher/os/pkg/log"
|
||||
"github.com/rancher/os/pkg/util"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultRoutesCheckTimeout = 20000 // 20 second
|
||||
|
||||
ipv4RouteFile = "/proc/net/route"
|
||||
ipv6RouteFile = "/proc/net/ipv6_route"
|
||||
|
||||
ipv4DefaultGWFlags = "0003"
|
||||
ipv6DefaultGWFlags = "00450003"
|
||||
)
|
||||
|
||||
func checkIPv4GW() bool {
|
||||
if _, err := os.Stat(ipv4RouteFile); os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
file, err := os.Open(ipv4RouteFile)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer file.Close()
|
||||
scanner := bufio.NewReader(file)
|
||||
for {
|
||||
line, err := scanner.ReadString('\n')
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
//ignore the headers in the route info
|
||||
if strings.HasPrefix(line, "Iface") {
|
||||
continue
|
||||
}
|
||||
fields := strings.Fields(line)
|
||||
// Interested in fields:
|
||||
// 3 - flags
|
||||
if fields[3] == ipv4DefaultGWFlags {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func checkIPv6GW() bool {
|
||||
if _, err := os.Stat(ipv6RouteFile); os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
file, err := os.Open(ipv6RouteFile)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer file.Close()
|
||||
scanner := bufio.NewReader(file)
|
||||
for {
|
||||
line, err := scanner.ReadString('\n')
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
fields := strings.Fields(line)
|
||||
// Interested in fields:
|
||||
// 3 - flags
|
||||
if fields[3] == ipv6DefaultGWFlags {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func checkAllDefaultGW() bool {
|
||||
return checkIPv4GW() || checkIPv6GW()
|
||||
}
|
||||
|
||||
func AllDefaultGWOK(timeout int) error {
|
||||
backoff := util.Backoff{
|
||||
StartMillis: 100,
|
||||
MaxIntervalMillis: 2000,
|
||||
MaxMillis: timeout,
|
||||
}
|
||||
defer backoff.Close()
|
||||
|
||||
var err error
|
||||
for ok := range backoff.Start() {
|
||||
if !ok {
|
||||
err = fmt.Errorf("Timeout waiting for the default gateway ready")
|
||||
break
|
||||
}
|
||||
if checkAllDefaultGW() {
|
||||
break
|
||||
}
|
||||
log.Debug("Waiting for the default gateway ready")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debug("The default gateway is ready")
|
||||
|
||||
return nil
|
||||
}
|
||||
62
pkg/util/versions/compare.go
Normal file
62
pkg/util/versions/compare.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package versions
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// compare compares two version strings
|
||||
// returns -1 if v1 < v2, 1 if v1 > v2, 0 otherwise.
|
||||
func compare(v1, v2 string) int {
|
||||
var (
|
||||
currTab = strings.Split(v1, ".")
|
||||
otherTab = strings.Split(v2, ".")
|
||||
)
|
||||
|
||||
max := len(currTab)
|
||||
if len(otherTab) > max {
|
||||
max = len(otherTab)
|
||||
}
|
||||
for i := 0; i < max; i++ {
|
||||
var currInt, otherInt int
|
||||
|
||||
if len(currTab) > i {
|
||||
currInt, _ = strconv.Atoi(currTab[i])
|
||||
}
|
||||
if len(otherTab) > i {
|
||||
otherInt, _ = strconv.Atoi(otherTab[i])
|
||||
}
|
||||
if currInt > otherInt {
|
||||
return 1
|
||||
}
|
||||
if otherInt > currInt {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// LessThan checks if a version is less than another
|
||||
func LessThan(v, other string) bool {
|
||||
return compare(v, other) == -1
|
||||
}
|
||||
|
||||
// LessThanOrEqualTo checks if a version is less than or equal to another
|
||||
func LessThanOrEqualTo(v, other string) bool {
|
||||
return compare(v, other) <= 0
|
||||
}
|
||||
|
||||
// GreaterThan checks if a version is greater than another
|
||||
func GreaterThan(v, other string) bool {
|
||||
return compare(v, other) == 1
|
||||
}
|
||||
|
||||
// GreaterThanOrEqualTo checks if a version is greater than or equal to another
|
||||
func GreaterThanOrEqualTo(v, other string) bool {
|
||||
return compare(v, other) >= 0
|
||||
}
|
||||
|
||||
// Equal checks if a version is equal to another
|
||||
func Equal(v, other string) bool {
|
||||
return compare(v, other) == 0
|
||||
}
|
||||
26
pkg/util/versions/compare_test.go
Normal file
26
pkg/util/versions/compare_test.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package versions
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func assertVersion(t *testing.T, a, b string, result int) {
|
||||
if r := compare(a, b); r != result {
|
||||
t.Fatalf("Unexpected version comparison result. Found %d, expected %d", r, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompareVersion(t *testing.T) {
|
||||
assertVersion(t, "1.12", "1.12", 0)
|
||||
assertVersion(t, "1.0.0", "1", 0)
|
||||
assertVersion(t, "1", "1.0.0", 0)
|
||||
assertVersion(t, "1.05.00.0156", "1.0.221.9289", 1)
|
||||
assertVersion(t, "1", "1.0.1", -1)
|
||||
assertVersion(t, "1.0.1", "1", 1)
|
||||
assertVersion(t, "1.0.1", "1.0.2", -1)
|
||||
assertVersion(t, "1.0.2", "1.0.3", -1)
|
||||
assertVersion(t, "1.0.3", "1.1", -1)
|
||||
assertVersion(t, "1.1", "1.1.1", -1)
|
||||
assertVersion(t, "1.1.1", "1.1.2", -1)
|
||||
assertVersion(t, "1.1.2", "1.2", -1)
|
||||
}
|
||||
@@ -10,7 +10,7 @@ if [ "$KERNEL_CHECK" != "0" ]; then
|
||||
echo "Host Kernel: $(uname -r)"
|
||||
echo "RancherOS Kernel: $KERNEL_VERSION"
|
||||
|
||||
if ! version_gt $(uname -r) $KERNEL_VERSION; then
|
||||
if [ $(uname -r) != $KERNEL_VERSION ] && ! version_gt $(uname -r) $KERNEL_VERSION; then
|
||||
echo "Your host kernel must be greater than RancherOS KERNEL_VERSION"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
3
scripts/tools/collect_rancheros_info.sh
Normal file → Executable file
3
scripts/tools/collect_rancheros_info.sh
Normal file → Executable file
@@ -46,6 +46,9 @@ docker info > $dest_conf_dir/docker-info
|
||||
cat /proc/mounts > $dest_conf_dir/proc-mounts
|
||||
cat /proc/1/mounts > $dest_conf_dir/proc-1-mounts
|
||||
cat /proc/cmdline > $dest_conf_dir/cmdline
|
||||
ip a > $dest_conf_dir/ipall
|
||||
ip route > $dest_conf_dir/iproutes
|
||||
cat /etc/resolv.conf > $dest_conf_dir/resolv
|
||||
dmesg > $dest_conf_dir/dmesg.log
|
||||
|
||||
cd $conf_file_src_dir && cp -rf `ls | grep -E -v "^(pem)$"` $dest_conf_dir
|
||||
|
||||
93
scripts/tools/flush_crt_iso.sh
Executable file
93
scripts/tools/flush_crt_iso.sh
Executable file
@@ -0,0 +1,93 @@
|
||||
#!/bin/bash
|
||||
|
||||
# How to use:
|
||||
# make shell-bind
|
||||
# cd scripts/tools/
|
||||
# wget https://link/rancheros-xxx.iso
|
||||
# wget http://link/custom.crt
|
||||
#
|
||||
# ./flush_crt_iso.sh --iso rancheros-vmware-autoformat.iso --cert custom.crt
|
||||
# # or
|
||||
# ./flush_crt_iso.sh --initrd initrd-xxxx --cert custom.crt
|
||||
#
|
||||
# exit
|
||||
# ls ./build/
|
||||
#
|
||||
|
||||
set -ex
|
||||
|
||||
BASE_DIR=/tmp
|
||||
ORIGIN_DIR=/tmp/origin
|
||||
NEW_DIR=/tmp/new
|
||||
WORK_DIR=/tmp/work
|
||||
|
||||
mkdir -p ${ORIGIN_DIR} ${NEW_DIR} ${WORK_DIR} ${DAPPER_SOURCE}/build
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case $1 in
|
||||
--initrd)
|
||||
shift 1
|
||||
INITRD_FILE=$(readlink -f $1)
|
||||
;;
|
||||
--iso)
|
||||
shift 1
|
||||
ISO_FILE=$(readlink -f $1)
|
||||
;;
|
||||
--cert)
|
||||
shift 1
|
||||
CERT_FILE=$(readlink -f $1)
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
shift 1
|
||||
done
|
||||
|
||||
function rebuild_initrd() {
|
||||
local initrd_name=$1
|
||||
local output_dir=$2
|
||||
|
||||
# update and rebuild the initrd
|
||||
pushd ${WORK_DIR}
|
||||
mv initrd-* ${initrd_name}.gz
|
||||
gzip -d ${initrd_name}.gz
|
||||
cpio -i -F ${initrd_name}
|
||||
rm -f ${initrd_name}
|
||||
|
||||
cat ${CERT_FILE} >> ${WORK_DIR}/usr/etc/ssl/certs/ca-certificates.crt
|
||||
|
||||
find | cpio -H newc -o | gzip -9 > ${output_dir}/${initrd_name}
|
||||
popd
|
||||
}
|
||||
|
||||
|
||||
if [ ! -z ${INITRD_FILE} ]; then
|
||||
cp ${INITRD_FILE} ${WORK_DIR}/
|
||||
rebuild_initrd $(basename ${INITRD_FILE}) ${DAPPER_SOURCE}/build/
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# copy the iso content
|
||||
mount -t iso9660 -o loop ${ISO_FILE} ${ORIGIN_DIR}
|
||||
cp -rf ${ORIGIN_DIR}/* ${NEW_DIR}
|
||||
|
||||
# copy the initrd file
|
||||
INITRD_NAME=$(basename ${ORIGIN_DIR}/boot/initrd-*)
|
||||
cp ${ORIGIN_DIR}/boot/initrd-* ${WORK_DIR}/
|
||||
|
||||
rebuild_initrd ${INITRD_NAME} ${NEW_DIR}/boot
|
||||
|
||||
pushd ${NEW_DIR}
|
||||
xorriso \
|
||||
-as mkisofs \
|
||||
-l -J -R -V "${DISTRIB_ID}" \
|
||||
-no-emul-boot -boot-load-size 4 -boot-info-table \
|
||||
-b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
|
||||
-isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin \
|
||||
-o $(basename ${ISO_FILE}) .
|
||||
popd
|
||||
|
||||
# copy out
|
||||
umount ${ORIGIN_DIR}
|
||||
cp ${NEW_DIR}/$(basename ${ISO_FILE}) ${DAPPER_SOURCE}/build/
|
||||
@@ -29,7 +29,7 @@ github.com/sigma/vmw-ovflib master
|
||||
github.com/sigma/bdoor master
|
||||
github.com/stretchr/testify a1f97990ddc16022ec7610326dd9bce31332c116
|
||||
github.com/vbatts/tar-split v0.9.11
|
||||
github.com/vishvananda/netlink f5a6f697a596c788d474984a38a0ac4ba0719e93
|
||||
github.com/vishvananda/netlink b76f71f1d33745ac0833fff4277481599a8ee73f https://github.com/niusmallnan/netlink
|
||||
github.com/vishvananda/netns 54f0e4339ce73702a0607f49922aaa1e749b418d
|
||||
github.com/xeipuuv/gojsonpointer 6fe8760cad3569743d51ddbb243b26f8456742dc
|
||||
github.com/xeipuuv/gojsonreference e02fc20de94c78484cd5ffb007f8af96be030a45
|
||||
|
||||
7
vendor/github.com/vishvananda/netlink/addr_linux.go
generated
vendored
7
vendor/github.com/vishvananda/netlink/addr_linux.go
generated
vendored
@@ -103,14 +103,17 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
|
||||
}
|
||||
}
|
||||
|
||||
if addr.Broadcast == nil {
|
||||
if addr.Broadcast == nil && prefixlen < 31 {
|
||||
calcBroadcast := make(net.IP, masklen/8)
|
||||
for i := range localAddrData {
|
||||
calcBroadcast[i] = localAddrData[i] | ^addr.Mask[i]
|
||||
}
|
||||
addr.Broadcast = calcBroadcast
|
||||
}
|
||||
req.AddData(nl.NewRtAttr(syscall.IFA_BROADCAST, addr.Broadcast))
|
||||
|
||||
if addr.Broadcast != nil {
|
||||
req.AddData(nl.NewRtAttr(syscall.IFA_BROADCAST, addr.Broadcast))
|
||||
}
|
||||
|
||||
if addr.Label != "" {
|
||||
labelData := nl.NewRtAttr(syscall.IFA_LABEL, nl.ZeroTerminated(addr.Label))
|
||||
|
||||
Reference in New Issue
Block a user