[SOLVED] Custom Backup Library

mKenfenheuer

Active Member
Mar 20, 2017
10
14
43
Hallo zusammen,

ich verusche aktuell eine eigene Library zum erstellen/hochladen von Backups zu schreiben.
Soweit funktioniert die HTTP/2 verbindung auch, jedoch kann ich keine Fixed Indexes hochladen.

Testweise lade ich zwei, 4MB chunks hoch. Diese werden auch mit dem richtigen digest bestätigt:
Code:
{"data":"bb9f8df61474d25e71fa00722318cd387396ca1736605e1248821cc0de3d3af8"}

Anschließend schließe ich den Fixed Index. Jedoch nicht erfolgreich.

Die Fehlermeldung im Log ist folgende:
Code:
POST /fixed_close: 400 Bad Request: fixed writer 'sample.img.fidx' close failed - received wrong number of chunk (0 != 2)

Heißt also für mich, die chunks kommen an, werden verarbeitet (sonst gäbe es keine rückmeldung mit dem digest) jedoch muss beim schließen des Index etwas falsch laufen. Ich komme jedoch nicht drauf.
Ebenso werden blobs nicht automatisch in den Index übernommen, ich muss bei Ende des Backups ein index.json hochladen damit das Backup nicht fehlschlägt.
Tut dies der PBS nicht selber anlegen wie in der Doku beschrieben?

Hier noch mein code zum hochladen der chunks, etc.

C-like:
 public async Task<bool> UploadBlobFile(string name, IDataBlob blob)
        {
            if (name.EndsWith(".blob"))
                name.Substring(0, name.Length - 5);

            byte[] data = await blob.RawByteFormat();
           
            HeaderField[] headers = new HeaderField[]
            {
                new HeaderField { Name = ":method", Value = "POST" },
                new HeaderField { Name = ":scheme", Value = "http" },
                new HeaderField { Name = ":path", Value = $"/blob?file-name={name}.blob&encoded-size={data.Length}" },
            };

            var stream = await _connection.CreateStreamAsync(
                headers, endOfStream: false);

            await stream.WriteAsync(data, true);

            // Wait for response headers
            var reponseHeaders = await stream.ReadHeadersAsync();


            if (reponseHeaders.First(s => s.Name == ":status").Value != "200")
                return false;

            // Read response data

            StringBuilder sb = new StringBuilder();
            byte[] buf = new byte[8192];

            while (true)
            {
                var res = await stream.ReadAsync(new ArraySegment<byte>(buf));
                if (res.EndOfStream) break;
                var text = Encoding.UTF8.GetString(buf, 0, res.BytesRead);
                sb.Append(text);
            }

            BackupFile file = new BackupFile()
            {
                Filename = name + ".blob",
                CryptMode = blob.GetCryptMode(),
                Size = blob.GetDataLength(),
                Csum = blob.GetCsum(),
            };

            _index.Files.Add(file);

            return true;
        }

        public async Task<int> CreateFixedIndex(string name, int size, bool reusecsum = false)
        {
            if (name.EndsWith(".fidx"))
                name.Substring(0, name.Length - 5);
           
            HeaderField[] headers = new HeaderField[]
            {
                new HeaderField { Name = ":method", Value = "POST" },
                new HeaderField { Name = ":scheme", Value = "http" },
                new HeaderField { Name = ":path", Value = $"/fixed_index?archive-name={name}.fidx&size={size}" },
            };

            var stream = await _connection.CreateStreamAsync(
                headers, endOfStream: true);

            // Wait for response headers
            var reponseHeaders = await stream.ReadHeadersAsync();


            if (reponseHeaders.First(s => s.Name == ":status").Value != "200")
                return -1;

            // Read response data

            StringBuilder sb = new StringBuilder();
            byte[] buf = new byte[8192];

            while (true)
            {
                var res = await stream.ReadAsync(new ArraySegment<byte>(buf));
                if (res.EndOfStream) break;
                var text = Encoding.UTF8.GetString(buf, 0, res.BytesRead);
                sb.Append(text);
            }

            var data = JsonConvert.DeserializeObject<WriterResponse>(sb.ToString());
            return data.Data;
        }
        public async Task<string> UploadFixedChunk(int writer_id, byte[] data)
        {
            UnencryptedDataBlob blob = new UnencryptedDataBlob(data);

            var _blobData = await blob.RawByteFormat();
            var digest = BitConverter.ToString(SHA256.HashData(data)).Replace("-", "").ToLower();

            HeaderField[] headers = new HeaderField[]
            {
                new HeaderField { Name = ":method", Value = "POST" },
                new HeaderField { Name = ":scheme", Value = "http" },
                new HeaderField { Name = ":path", Value = $"/fixed_chunk?digest={digest}&encoded-size={_blobData.Length}&size={data.Length}&wid={writer_id}" },
            };

            var stream = await _connection.CreateStreamAsync(
                headers, endOfStream: false);

            await stream.WriteAsync(_blobData, true);

            // Wait for response headers
            var reponseHeaders = await stream.ReadHeadersAsync();

            if (reponseHeaders.First(s => s.Name == ":status").Value != "200")
                return null;

            // Read response data

            StringBuilder sb = new StringBuilder();
            byte[] buf = new byte[8192];

            while (true)
            {
                var res = await stream.ReadAsync(new ArraySegment<byte>(buf));
                if (res.EndOfStream) break;
                var text = Encoding.UTF8.GetString(buf, 0, res.BytesRead);
                sb.Append(text);
            }

            var resp = JsonConvert.DeserializeObject<ChunkResponse>(sb.ToString());
            return resp.Data;
        }
 
Last edited:
super dass du das problem bereits geloest hast (sogar mit unserer Doku :)). interessehalber - wofuer schreibst du die bibliothek?
 
Hauptsächlich ist mein Ziel eine Backup-Lösung für Datenbank-Systeme (MySQL oder MSSQL).

Die Library (noch nicht 100% fertig) ist hier zu finden: GitHub NuGet
Implementiert werden muss noch die Verschlüsselung und Kompression von Blobs.

Edit: wir sind ja hier im Deutschen Teil, vielleicht kannst du ja deinen Post auch noch kurz übersetzen ;)
 

About

The Proxmox community has been around for many years and offers help and support for Proxmox VE, Proxmox Backup Server, and Proxmox Mail Gateway.
We think our community is one of the best thanks to people like you!

Get your subscription!

The Proxmox team works very hard to make sure you are running the best software and getting stable updates and security enhancements, as well as quick enterprise support. Tens of thousands of happy customers have a Proxmox subscription. Get yours easily in our online shop.

Buy now!