Skip to content

Commit 1c9e637

Browse files
Merge pull request #907 from dtantsur/deploy-iso
Support deploy_iso in addition to deploy_kernel/ramdisk
2 parents a93cb9c + c98f729 commit 1c9e637

File tree

4 files changed

+196
-26
lines changed

4 files changed

+196
-26
lines changed

docs/configuration.md

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ containing the Ironic agent.
1010
`DEPLOY_KERNEL_URL` -- The URL for the kernel to go with the deploy
1111
ramdisk.
1212

13+
`DEPLOY_ISO_URL` -- The URL for the ISO containing the Ironic agent for
14+
drivers that support ISO boot. Optional if kernel/ramdisk are set.
15+
1316
`IRONIC_ENDPOINT` -- The URL for the operator to use when talking to
1417
Ironic.
1518

pkg/provisioner/ironic/init_test.go

+152
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
package ironic
2+
3+
import (
4+
"os"
5+
"strings"
6+
"testing"
7+
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
type EnvFixture struct {
12+
ironicEndpoint string
13+
inspectorEndpoint string
14+
kernelURL string
15+
ramdiskURL string
16+
isoURL string
17+
}
18+
19+
func tearDown() {
20+
for _, e := range os.Environ() {
21+
if !strings.HasPrefix(e, "IRONIC_") && !strings.HasPrefix(e, "DEPLOY_") {
22+
continue
23+
}
24+
parts := strings.SplitN(e, "=", 2)
25+
os.Unsetenv(parts[0])
26+
}
27+
}
28+
29+
func (f EnvFixture) SetUp() {
30+
tearDown()
31+
32+
if f.ironicEndpoint != "" {
33+
os.Setenv("IRONIC_ENDPOINT", f.ironicEndpoint)
34+
}
35+
if f.inspectorEndpoint != "" {
36+
os.Setenv("IRONIC_INSPECTOR_ENDPOINT", f.inspectorEndpoint)
37+
}
38+
if f.kernelURL != "" {
39+
os.Setenv("DEPLOY_KERNEL_URL", f.kernelURL)
40+
}
41+
if f.ramdiskURL != "" {
42+
os.Setenv("DEPLOY_RAMDISK_URL", f.ramdiskURL)
43+
}
44+
if f.isoURL != "" {
45+
os.Setenv("DEPLOY_ISO_URL", f.isoURL)
46+
}
47+
}
48+
49+
func (f EnvFixture) Verify(t *testing.T) {
50+
assert.Equal(t, f.ironicEndpoint, ironicEndpoint)
51+
assert.Equal(t, f.inspectorEndpoint, inspectorEndpoint)
52+
assert.Equal(t, f.kernelURL, deployKernelURL)
53+
assert.Equal(t, f.ramdiskURL, deployRamdiskURL)
54+
assert.Equal(t, f.isoURL, deployISOURL)
55+
}
56+
57+
func TestLoadFromEnv(t *testing.T) {
58+
defer tearDown()
59+
60+
cases := []struct {
61+
name string
62+
env EnvFixture
63+
expectedError string
64+
}{
65+
{
66+
name: "kernel and ramdisk",
67+
env: EnvFixture{
68+
ironicEndpoint: "http://ironic",
69+
inspectorEndpoint: "http://inspector",
70+
kernelURL: "http://kernel",
71+
ramdiskURL: "http://ramdisk",
72+
},
73+
},
74+
{
75+
name: "ISO only",
76+
env: EnvFixture{
77+
ironicEndpoint: "http://ironic",
78+
inspectorEndpoint: "http://inspector",
79+
isoURL: "http://iso",
80+
},
81+
},
82+
{
83+
name: "ISO and kernel/ramdisk",
84+
env: EnvFixture{
85+
ironicEndpoint: "http://ironic",
86+
inspectorEndpoint: "http://inspector",
87+
isoURL: "http://iso",
88+
kernelURL: "http://kernel",
89+
ramdiskURL: "http://ramdisk",
90+
},
91+
},
92+
{
93+
name: "no deploy info",
94+
env: EnvFixture{
95+
ironicEndpoint: "http://ironic",
96+
inspectorEndpoint: "http://inspector",
97+
},
98+
expectedError: "Either DEPLOY_KERNEL_URL and DEPLOY_RAMDISK_URL or DEPLOY_ISO_URL must be set",
99+
},
100+
{
101+
name: "only kernel",
102+
env: EnvFixture{
103+
ironicEndpoint: "http://ironic",
104+
inspectorEndpoint: "http://inspector",
105+
kernelURL: "http://kernel",
106+
},
107+
expectedError: "Either DEPLOY_KERNEL_URL and DEPLOY_RAMDISK_URL or DEPLOY_ISO_URL must be set",
108+
},
109+
{
110+
name: "only ramdisk",
111+
env: EnvFixture{
112+
ironicEndpoint: "http://ironic",
113+
inspectorEndpoint: "http://inspector",
114+
ramdiskURL: "http://ramdisk",
115+
},
116+
expectedError: "Either DEPLOY_KERNEL_URL and DEPLOY_RAMDISK_URL or DEPLOY_ISO_URL must be set",
117+
},
118+
{
119+
name: "ISO and kernel",
120+
env: EnvFixture{
121+
ironicEndpoint: "http://ironic",
122+
inspectorEndpoint: "http://inspector",
123+
kernelURL: "http://kernel",
124+
isoURL: "http://iso",
125+
},
126+
expectedError: "DEPLOY_KERNEL_URL and DEPLOY_RAMDISK_URL can only be set together",
127+
},
128+
{
129+
name: "ISO and ramdisk",
130+
env: EnvFixture{
131+
ironicEndpoint: "http://ironic",
132+
inspectorEndpoint: "http://inspector",
133+
ramdiskURL: "http://ramdisk",
134+
isoURL: "http://iso",
135+
},
136+
expectedError: "DEPLOY_KERNEL_URL and DEPLOY_RAMDISK_URL can only be set together",
137+
},
138+
}
139+
140+
for _, tc := range cases {
141+
t.Run(tc.name, func(t *testing.T) {
142+
tc.env.SetUp()
143+
err := loadConfigFromEnv()
144+
if tc.expectedError != "" {
145+
assert.Regexp(t, tc.expectedError, err, "error message")
146+
} else {
147+
assert.Nil(t, err)
148+
tc.env.Verify(t)
149+
}
150+
})
151+
}
152+
}

pkg/provisioner/ironic/ironic.go

+39-26
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ var (
3535
softPowerOffTimeout = time.Second * 180
3636
deployKernelURL string
3737
deployRamdiskURL string
38+
deployISOURL string
3839
ironicEndpoint string
3940
inspectorEndpoint string
4041
ironicTrustedCAFile string
@@ -82,36 +83,23 @@ func NewMacAddressConflictError(address, node string) error {
8283
return macAddressConflictError{Address: address, ExistingNode: node}
8384
}
8485

85-
func init() {
86-
// NOTE(dhellmann): Use Fprintf() to report errors instead of
87-
// logging, because logging is not configured yet in init().
88-
89-
var authErr error
90-
ironicAuth, inspectorAuth, authErr = clients.LoadAuth()
91-
if authErr != nil {
92-
fmt.Fprintf(os.Stderr, "Cannot start: %s\n", authErr)
93-
os.Exit(1)
94-
}
95-
86+
func loadConfigFromEnv() error {
9687
deployKernelURL = os.Getenv("DEPLOY_KERNEL_URL")
97-
if deployKernelURL == "" {
98-
fmt.Fprintf(os.Stderr, "Cannot start: No DEPLOY_KERNEL_URL variable set\n")
99-
os.Exit(1)
100-
}
10188
deployRamdiskURL = os.Getenv("DEPLOY_RAMDISK_URL")
102-
if deployRamdiskURL == "" {
103-
fmt.Fprintf(os.Stderr, "Cannot start: No DEPLOY_RAMDISK_URL variable set\n")
104-
os.Exit(1)
89+
deployISOURL = os.Getenv("DEPLOY_ISO_URL")
90+
if deployISOURL == "" && (deployKernelURL == "" || deployRamdiskURL == "") {
91+
return errors.New("Either DEPLOY_KERNEL_URL and DEPLOY_RAMDISK_URL or DEPLOY_ISO_URL must be set")
92+
}
93+
if (deployKernelURL == "" && deployRamdiskURL != "") || (deployKernelURL != "" && deployRamdiskURL == "") {
94+
return errors.New("DEPLOY_KERNEL_URL and DEPLOY_RAMDISK_URL can only be set together")
10595
}
10696
ironicEndpoint = os.Getenv("IRONIC_ENDPOINT")
10797
if ironicEndpoint == "" {
108-
fmt.Fprintf(os.Stderr, "Cannot start: No IRONIC_ENDPOINT variable set\n")
109-
os.Exit(1)
98+
return errors.New("No IRONIC_ENDPOINT variable set")
11099
}
111100
inspectorEndpoint = os.Getenv("IRONIC_INSPECTOR_ENDPOINT")
112101
if inspectorEndpoint == "" {
113-
fmt.Fprintf(os.Stderr, "Cannot start: No IRONIC_INSPECTOR_ENDPOINT variable set\n")
114-
os.Exit(1)
102+
return errors.New("No IRONIC_INSPECTOR_ENDPOINT variable set")
115103
}
116104
ironicTrustedCAFile = os.Getenv("IRONIC_CACERT_FILE")
117105
if ironicTrustedCAFile == "" {
@@ -137,11 +125,30 @@ func init() {
137125
if maxHostsStr := os.Getenv("PROVISIONING_LIMIT"); maxHostsStr != "" {
138126
value, err := strconv.Atoi(maxHostsStr)
139127
if err != nil {
140-
fmt.Fprintf(os.Stderr, "Cannot start: Invalid value set for variable PROVISIONING_LIMIT=%s", maxHostsStr)
141-
os.Exit(1)
128+
return errors.Errorf("Invalid value set for variable PROVISIONING_LIMIT=%s", maxHostsStr)
142129
}
143130
maxBusyHosts = value
144131
}
132+
133+
return nil
134+
}
135+
136+
func init() {
137+
// NOTE(dhellmann): Use Fprintf() to report errors instead of
138+
// logging, because logging is not configured yet in init().
139+
140+
var authErr error
141+
ironicAuth, inspectorAuth, authErr = clients.LoadAuth()
142+
if authErr != nil {
143+
fmt.Fprintf(os.Stderr, "Cannot start: %s\n", authErr)
144+
os.Exit(1)
145+
}
146+
147+
err := loadConfigFromEnv()
148+
if err != nil {
149+
fmt.Fprintf(os.Stderr, "Cannot start: %s\n", err)
150+
os.Exit(1)
151+
}
145152
}
146153

147154
// Provisioner implements the provisioning.Provisioner interface
@@ -181,6 +188,7 @@ func LogStartup() {
181188
"inspectorAuthType", inspectorAuth.Type,
182189
"deployKernelURL", deployKernelURL,
183190
"deployRamdiskURL", deployRamdiskURL,
191+
"deployISOURL", deployISOURL,
184192
)
185193
}
186194

@@ -510,8 +518,13 @@ func (p *ironicProvisioner) ValidateManagementAccess(data provisioner.Management
510518
driverInfo := bmcAccess.DriverInfo(p.bmcCreds)
511519
// FIXME(dhellmann): We need to get our IP on the
512520
// provisioning network from somewhere.
513-
driverInfo["deploy_kernel"] = deployKernelURL
514-
driverInfo["deploy_ramdisk"] = deployRamdiskURL
521+
if deployKernelURL != "" && deployRamdiskURL != "" {
522+
driverInfo["deploy_kernel"] = deployKernelURL
523+
driverInfo["deploy_ramdisk"] = deployRamdiskURL
524+
}
525+
if deployISOURL != "" {
526+
driverInfo["deploy_iso"] = deployISOURL
527+
}
515528

516529
// If we have not found a node yet, we need to create one
517530
if ironicNode == nil {

tools/run_local_ironic.sh

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ fi
5050

5151
DEPLOY_KERNEL_URL="${DEPLOY_KERNEL_URL:-"http://${CLUSTER_PROVISIONING_IP}:${HTTP_PORT}/images/ironic-python-agent.kernel"}"
5252
DEPLOY_RAMDISK_URL="${DEPLOY_RAMDISK_URL:-"http://${CLUSTER_PROVISIONING_IP}:${HTTP_PORT}/images/ironic-python-agent.initramfs"}"
53+
DEPLOY_ISO_URL=${DEPLOY_ISO_URL:-}
5354
IRONIC_ENDPOINT="${IRONIC_ENDPOINT:-"${IRONIC_BASE_URL}:6385/v1/"}"
5455
IRONIC_INSPECTOR_ENDPOINT="${IRONIC_INSPECTOR_ENDPOINT:-"${IRONIC_BASE_URL}:5050/v1/"}"
5556
CACHEURL="${CACHEURL:-"http://${PROVISIONING_IP}/images"}"
@@ -71,6 +72,7 @@ PROVISIONING_INTERFACE=${PROVISIONING_INTERFACE}
7172
DHCP_RANGE=${CLUSTER_DHCP_RANGE}
7273
DEPLOY_KERNEL_URL=${DEPLOY_KERNEL_URL}
7374
DEPLOY_RAMDISK_URL=${DEPLOY_RAMDISK_URL}
75+
DEPLOY_ISO_URL=${DEPLOY_ISO_URL}
7476
IRONIC_ENDPOINT=${IRONIC_ENDPOINT}
7577
IRONIC_INSPECTOR_ENDPOINT=${IRONIC_INSPECTOR_ENDPOINT}
7678
CACHEURL=${CACHEURL}

0 commit comments

Comments
 (0)