> Hi, > > I've tried to adapt the patch to current PVE 7.1-12 (see below) but I > still get > > proxmoxer.core.ResourceException: 501 Not Implemented: upload failed > - > {'errors': b''} > > When I try to upload a snippet. > > My proxmoxer setup works for iso, the following succeeds: > > proxmox.nodes(h).storage(s).upload.post(content="iso",filename=f) > > But the following fails (f being read "rb" from some xxx.yaml) > > proxmox.nodes(h).storage(s).upload.post(content="snippets",filename=f > ) > > Not having snippet upload makes it impossible to use PVE auth realm > tokens to control permissions, you have to give a priviledged system > account to users *just* to be able to do cloud init with a yaml which > is not great security wise (and not practical). > > I'm probably missing a few things to have a patch that works, I'm > willing to put some time on it if someone gives me directions.
I instrumented some PVE perl code and failure to recognize the upload API data seems to happen somewhere in the logic of /usr/share/perl5/PVE/APIServer/AnyEvent.pm:file_upload_multipart With my patch installed for content=snippet filename=yoyobig.yaml if I upload a 16137 or more byte files it works, but for 16136 byte and below it fails with 501 not implemented which is suspicious. By adding max debug to python http libs I was able to check that the headers are strictly identical except for Content-Length as expected, see below. There's a comment in AnyEvent.pm about "# assume we have single line headers" and also some complex state handling while parsing the request but for now I wasn't able to pinpoint what triggers the failure. Help welcomed :) Sincerely, Laurent Debug logs: import http.client http.client.HTTPConnection.debuglevel=5 import logging logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) Works: INFO:proxmoxer.core:POST https://nuc2:8006/api2/json/nodes/nuc2/storage/element2dir/upload {'content': 'snippets', 'filename': <_io.BufferedReader name='yoyobig.yaml'>} DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): nuc2:8006 send: b'POST /api2/json/nodes/nuc2/storage/element2dir/upload HTTP/1.1\r\nHost: nuc2:8006\r\nUser-Agent: python-requests/2.23.0\r\nAccept-Encoding: gzip, deflate\r\naccept: application/json, application/x-javasc ript, text/javascript, text/x-javascript, text/x-json\r\nConnection: keep-alive\r\nContent-Length: 16385\r\nContent-Type: multipart/form-data; boundary=790f8b2d9dcdc452863bff66e1d262bc\r\nAuthorization: PVEAPITo ken=root@pam!testpython1=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\r\n\r\n' send: b'--790f8b2d9dcdc452863bff66e1d262bc\r\nContent-Disposition: form-data; name="content"\r\n\r\nsnippets\r\n--790f8b2d9dcdc452863bff66e1d262bc\r\nContent-Disposition: form-data; name="filename"; filename="yo yobig.yaml"\r\n\r\n#cloud-config\xhostname: test... Fails: INFO:proxmoxer.core:POST https://nuc2:8006/api2/json/nodes/nuc2/storage/element2dir/upload {'content': 'snippets', 'filename': <_io.BufferedReader name='yoyobig.yaml'>} DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): nuc2:8006 send: b'POST /api2/json/nodes/nuc2/storage/element2dir/upload HTTP/1.1\r\nHost: nuc2:8006\r\nUser-Agent: python-requests/2.23.0\r\nAccept-Encoding: gzip, deflate\r\naccept: application/json, application/x-javasc ript, text/javascript, text/x-javascript, text/x-json\r\nConnection: keep-alive\r\nContent-Length: 16384\r\nContent-Type: multipart/form-data; boundary=1ae9ce4d260e3f514d7c12ec03e4389f\r\nAuthorization: PVEAPITo ken=root@pam!testpython1=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\r\n\r\n' send: b'--1ae9ce4d260e3f514d7c12ec03e4389f\r\nContent-Disposition: form-data; name="content"\r\n\r\nsnippets\r\n--1ae9ce4d260e3f514d7c12ec03e4389f\r\nContent-Disposition: form-data; name="filename"; filename="yo yobig.yaml"\r\n\r\n#cloud-config\nhostname: test... > Thanks! > > Sincerely, > > Laurent (paying PVE+PBS customer at work) > > root@test:/usr/share/perl5# diff -u PVE/Storage.pm{-orig,} > --- PVE/Storage.pm-orig 2022-04-08 09:15:52.443943197 +0200 > +++ PVE/Storage.pm 2022-04-08 09:17:23.457073570 +0200 > @@ -412,6 +412,15 @@ > return $plugin->get_subdir($scfg, 'iso'); > } > > +sub get_snippet_dir { > + my ($cfg, $storeid) = @_; > + > + my $scfg = storage_config($cfg, $storeid); > + my $plugin = PVE::Storage::Plugin->lookup($scfg->{type}); > + > + return $plugin->get_subdir($scfg, 'snippets'); > +} > + > sub get_vztmpl_dir { > my ($cfg, $storeid) = @_; > > root@test:/usr/share/perl5# diff -u ./PVE/API2/Storage/Status.pm{- > orig,} > --- ./PVE/API2/Storage/Status.pm-orig 2022-04-08 > 09:15:43.883836880 +0200 > +++ ./PVE/API2/Storage/Status.pm 2022-04-08 10:23:43.914401204 > +0200 > @@ -381,7 +381,7 @@ > content => { > description => "Content type.", > type => 'string', format => 'pve-storage-content', > - enum => ['iso', 'vztmpl'], > + enum => ['iso', 'vztmpl', 'snippets'], > }, > filename => { > description => "The name of the file to create. > Caution: This will be normalized!", > @@ -446,8 +446,10 @@ > raise_param_exc({ filename => "wrong file extension" > }); > } > $path = PVE::Storage::get_vztmpl_dir($cfg, $param- > >{storage}); > - } else { > - raise_param_exc({ content => "upload content type > '$content' not allowed" }); > + } elsif ($content eq 'snippets') { > + $path = PVE::Storage::get_snippet_dir($cfg, $param- > >{storage}); > + } else { > + raise_param_exc({ content => "upload content type > '$content' not allowed" }); > } > > die "storage '$param->{storage}' does not support '$content' > content\n" > @@ -564,7 +566,7 @@ > content => { > description => "Content type.", # TODO: could be > optional & detected in most cases > type => 'string', format => 'pve-storage-content', > - enum => ['iso', 'vztmpl'], > + enum => ['iso', 'vztmpl', 'snippets'], > }, > filename => { > description => "The name of the file to create. > Caution: This will be normalized!", > @@ -627,6 +629,8 @@ > raise_param_exc({ filename => "wrong file extension" > }); > } > $path = PVE::Storage::get_vztmpl_dir($cfg, $storage); > + } elsif ($content eq 'snippets') { > + $path = PVE::Storage::get_snippet_dir($cfg, > $storage); > } else { > raise_param_exc({ content => "upload content-type > '$content' is not allowed" }); > } > > > _______________________________________________ > pve-devel mailing list > pve-devel@lists.proxmox.com > https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel