Skip to content

Commit cc0edaf

Browse files
committed
confd: Add support to upload images directly
This add support for upgrading images with curl only, without FTP or similiar. The image needs to be base64 encoded. Example: TEMP_JSON=/tmp/restconf.txt echo -n '{"infix-system:input":{"image":"' > "$TEMP_JSON" base64 -w 0 "$BUNDLE_FILE" >> "$TEMP_JSON" echo '"}}' >> "$TEMP_JSON" curl -k \ -X POST \ -u "admin:admin" \ -H "Content-Type: application/yang-data+json" \ -H "Accept: application/yang-data+json" \ -d @"$TEMP_JSON" \ "https://192.168.30.1/restconf/operations/infix-system:install-bundle"
1 parent 60b3a97 commit cc0edaf

File tree

4 files changed

+138
-14
lines changed

4 files changed

+138
-14
lines changed

src/confd/configure.ac

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ PKG_CHECK_MODULES([jansson], [jansson >= 2.0.0])
7878
PKG_CHECK_MODULES([libite], [libite >= 2.6.1])
7979
PKG_CHECK_MODULES([sysrepo], [sysrepo >= 2.2.36])
8080
PKG_CHECK_MODULES([libsrx], [libsrx >= 1.0.0])
81+
PKG_CHECK_MODULES([libssl], [libssl >= 1.0.0])
8182

8283
# Control build with automake flags
8384
AM_CONDITIONAL(CONTAINERS, [test "x$enable_containers" != "xno"])

src/confd/src/Makefile.am

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ confd_plugin_la_CFLAGS = \
1212
$(libite_CFLAGS) \
1313
$(sysrepo_CFLAGS) \
1414
$(libsrx_CFLAGS) \
15+
$(libssl_CFLAGS) \
1516
$(CFLAGS)
1617

1718
confd_plugin_la_LIBADD = \
@@ -20,7 +21,8 @@ confd_plugin_la_LIBADD = \
2021
$(jansson_LIBS) \
2122
$(libite_LIBS) \
2223
$(sysrepo_LIBS) \
23-
$(libsrx_LIBS)
24+
$(libsrx_LIBS) \
25+
$(libssl_LIBS)
2426

2527
confd_plugin_la_SOURCES = \
2628
base64.c base64.h \

src/confd/src/infix-system-software.c

Lines changed: 103 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
/* SPDX-License-Identifier: BSD-3-Clause */
22
#include <srx/common.h>
33
#include <srx/lyx.h>
4+
#include <openssl/bio.h>
5+
#include <openssl/evp.h>
6+
#include <sys/statvfs.h>
47

58
#include "core.h"
69
#include "rauc-installer.h"
@@ -21,38 +24,130 @@ static RaucInstaller *infix_system_sw_new_rauc(void)
2124
return rauc;
2225
}
2326

27+
static int base64_decode_inplace(char *input, size_t input_len, size_t *output_len)
28+
{
29+
BIO *bio, *b64;
30+
int decode_len;
31+
32+
bio = BIO_new_mem_buf(input, input_len);
33+
if (!bio) {
34+
return -1;
35+
}
36+
37+
b64 = BIO_new(BIO_f_base64());
38+
if (!b64) {
39+
BIO_free(bio);
40+
return -1;
41+
}
42+
43+
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
44+
bio = BIO_push(b64, bio);
45+
46+
/* Decode directly into the same buffer */
47+
decode_len = BIO_read(bio, input, input_len);
48+
BIO_free_all(bio);
49+
50+
if (decode_len < 0) {
51+
return -1;
52+
}
53+
54+
*output_len = decode_len;
55+
return 0;
56+
}
57+
2458
static int infix_system_sw_install(sr_session_ctx_t *session, uint32_t sub_id,
2559
const char *path, const sr_val_t *input,
2660
const size_t input_cnt, sr_event_t event,
2761
unsigned request_id, sr_val_t **output,
2862
size_t *output_cnt, void *priv)
2963
{
30-
char *url = input->data.string_val;
3164
sr_error_t srerr = SR_ERR_OK;
3265
GError *raucerr = NULL;
33-
RaucInstaller *rauc;
66+
RaucInstaller *rauc = NULL;
67+
char *install_source = NULL;
68+
69+
const char *url = NULL;
70+
char *binary_data = NULL;
71+
size_t binary_len = 0;
72+
size_t decoded_len = 0;
73+
74+
for (size_t i = 0; i < input_cnt; i++) {
75+
if (strcmp(input[i].xpath, "/infix-system:install-bundle/url") == 0) {
76+
if (input[i].type == SR_STRING_T) {
77+
url = input[i].data.string_val;
78+
}
79+
} else if (strcmp(input[i].xpath, "/infix-system:install-bundle/image") == 0) {
80+
if (input[i].type == SR_BINARY_T) {
81+
binary_data = (char *)input[i].data.binary_val; // Cast away const for in-place decode
82+
binary_len = strlen(binary_data); // Length of base64 string
83+
}
84+
}
85+
}
86+
87+
if (url) {
88+
DEBUG("Installing from URL: %s", url);
89+
install_source = (char *)url;
90+
91+
} else if (binary_data) {
92+
const char *temp_dir = "/tmp";
93+
char path[256];
94+
FILE *fp;
95+
96+
DEBUG("Installing from uploaded binary data (%zu bytes base64)", binary_len);
97+
98+
if (base64_decode_inplace(binary_data, binary_len, &decoded_len) != 0) {
99+
sr_session_set_netconf_error(session, "application", "invalid-value",
100+
NULL, NULL, "Failed to decode base64 image data", 0);
101+
srerr = SR_ERR_INVAL_ARG;
102+
goto cleanup;
103+
}
104+
105+
fmkpath(0775, "%s/images", temp_dir);
106+
snprintf(path, sizeof(path), "%s/images/install_bundle", temp_dir);
107+
108+
fp = fopen(path, "wb");
109+
if (!fp) {
110+
ERROR("Could not open %s", path);
111+
return SR_ERR_NO_MEMORY;
112+
}
34113

35-
DEBUG("url:%s", url);
114+
fwrite(binary_data, sizeof(char), decoded_len, fp);
115+
fclose(fp);
116+
install_source = path;
117+
118+
} else {
119+
ERROR("Unknown source");
120+
return 0;
121+
}
36122

37123
rauc = infix_system_sw_new_rauc();
38-
if (!rauc)
39-
return SR_ERR_INTERNAL;
124+
if (!rauc) {
125+
sr_session_set_netconf_error(session, "application", "operation-failed",
126+
NULL, NULL, "Failed to initialize RAUC installer", 0);
127+
srerr = SR_ERR_INTERNAL;
128+
goto cleanup;
129+
}
40130

41-
rauc_installer_call_install_sync(rauc, url, NULL, &raucerr);
131+
rauc_installer_call_install_sync(rauc, install_source, NULL, &raucerr);
42132
if (raucerr) {
43133
sr_session_set_netconf_error(session, "application", "operation-failed",
44134
NULL, NULL, raucerr->message, 0);
45135
g_error_free(raucerr);
46136
srerr = SR_ERR_OPERATION_FAILED;
47137
}
48138

49-
g_object_unref(rauc);
139+
cleanup:
140+
if (rauc) {
141+
g_object_unref(rauc);
142+
}
143+
50144
return srerr;
51145
}
52146

147+
53148
/*
54149
boot order can only be: primary, secondary and net, limited by model
55-
*/
150+
*/
56151
static int infix_system_sw_set_boot_order(sr_session_ctx_t *session, uint32_t sub_id,
57152
const char *path, const sr_val_t *input,
58153
const size_t input_cnt, sr_event_t event,

src/confd/yang/confd/infix-system-software.yang

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -204,16 +204,42 @@ submodule infix-system-software {
204204
description
205205
"Upgrade the system's software by installing the specified bundle.";
206206
input {
207-
leaf url {
208-
type string;
207+
choice source {
209208
mandatory true;
210209
description
211-
"The location of the software bundle, specified as a Uniform
212-
Resource Locator (URL). Currently supported protocols include
213-
FTP, HTTP(S) and SCP.";
210+
"Source of the software bundle to install.";
211+
case url {
212+
leaf url {
213+
type string;
214+
description
215+
"The location of the software bundle, specified as a Uniform
216+
Resource Locator (URL). Currently supported protocols include
217+
FTP, HTTP(S) and SCP.";
218+
}
219+
}
220+
221+
case upload {
222+
leaf image {
223+
type binary;
224+
description
225+
"The image data to install, provided as base64-encoded binary data.";
226+
}
227+
}
214228
}
215229
}
216230
}
231+
rpc install-upload-bundle {
232+
nacm:default-deny-all;
233+
description "Upgrade the system's software by installing from a supplied blob.";
234+
input {
235+
leaf image {
236+
type binary;
237+
mandatory true;
238+
description "The image to install";
239+
}
240+
}
241+
}
242+
217243
rpc set-boot-order {
218244
nacm:default-deny-all;
219245
description

0 commit comments

Comments
 (0)