Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
ollama
Commits
d9cf18e2
"git@developer.sourcefind.cn:change/sglang.git" did not exist on "29bd4c8135eca0dfcd31d4a1bb1effc6f44c41ef"
Unverified
Commit
d9cf18e2
authored
Aug 11, 2023
by
Patrick Devine
Committed by
GitHub
Aug 11, 2023
Browse files
add maximum retries when pushing (#334)
parent
1556162c
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
35 additions
and
21 deletions
+35
-21
server/auth.go
server/auth.go
+3
-2
server/download.go
server/download.go
+1
-1
server/images.go
server/images.go
+29
-17
server/routes.go
server/routes.go
+2
-1
No files found.
server/auth.go
View file @
d9cf18e2
...
@@ -2,6 +2,7 @@ package server
...
@@ -2,6 +2,7 @@ package server
import
(
import
(
"bytes"
"bytes"
"context"
"crypto/rand"
"crypto/rand"
"crypto/sha256"
"crypto/sha256"
"encoding/base64"
"encoding/base64"
...
@@ -50,7 +51,7 @@ func (r AuthRedirect) URL() (string, error) {
...
@@ -50,7 +51,7 @@ func (r AuthRedirect) URL() (string, error) {
return
fmt
.
Sprintf
(
"%s?service=%s&scope=%s&ts=%d&nonce=%s"
,
r
.
Realm
,
r
.
Service
,
r
.
Scope
,
time
.
Now
()
.
Unix
(),
nonce
),
nil
return
fmt
.
Sprintf
(
"%s?service=%s&scope=%s&ts=%d&nonce=%s"
,
r
.
Realm
,
r
.
Service
,
r
.
Scope
,
time
.
Now
()
.
Unix
(),
nonce
),
nil
}
}
func
getAuthToken
(
redirData
AuthRedirect
,
regOpts
*
RegistryOptions
)
(
string
,
error
)
{
func
getAuthToken
(
ctx
context
.
Context
,
redirData
AuthRedirect
,
regOpts
*
RegistryOptions
)
(
string
,
error
)
{
url
,
err
:=
redirData
.
URL
()
url
,
err
:=
redirData
.
URL
()
if
err
!=
nil
{
if
err
!=
nil
{
return
""
,
err
return
""
,
err
...
@@ -92,7 +93,7 @@ func getAuthToken(redirData AuthRedirect, regOpts *RegistryOptions) (string, err
...
@@ -92,7 +93,7 @@ func getAuthToken(redirData AuthRedirect, regOpts *RegistryOptions) (string, err
"Authorization"
:
sig
,
"Authorization"
:
sig
,
}
}
resp
,
err
:=
makeRequest
(
"GET"
,
url
,
headers
,
nil
,
regOpts
)
resp
,
err
:=
makeRequest
(
ctx
,
"GET"
,
url
,
headers
,
nil
,
regOpts
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Printf
(
"couldn't get token: %q"
,
err
)
log
.
Printf
(
"couldn't get token: %q"
,
err
)
}
}
...
...
server/download.go
View file @
d9cf18e2
...
@@ -137,7 +137,7 @@ func doDownload(ctx context.Context, mp ModelPath, regOpts *RegistryOptions, f *
...
@@ -137,7 +137,7 @@ func doDownload(ctx context.Context, mp ModelPath, regOpts *RegistryOptions, f *
"Range"
:
fmt
.
Sprintf
(
"bytes=%d-"
,
size
),
"Range"
:
fmt
.
Sprintf
(
"bytes=%d-"
,
size
),
}
}
resp
,
err
:=
makeRequest
(
"GET"
,
url
,
headers
,
nil
,
regOpts
)
resp
,
err
:=
makeRequest
(
ctx
,
"GET"
,
url
,
headers
,
nil
,
regOpts
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Printf
(
"couldn't download blob: %v"
,
err
)
log
.
Printf
(
"couldn't download blob: %v"
,
err
)
return
err
return
err
...
...
server/images.go
View file @
d9cf18e2
...
@@ -24,6 +24,8 @@ import (
...
@@ -24,6 +24,8 @@ import (
"github.com/jmorganca/ollama/vector"
"github.com/jmorganca/ollama/vector"
)
)
const
MaxRetries
=
3
type
RegistryOptions
struct
{
type
RegistryOptions
struct
{
Insecure
bool
Insecure
bool
Username
string
Username
string
...
@@ -856,7 +858,7 @@ func DeleteModel(name string) error {
...
@@ -856,7 +858,7 @@ func DeleteModel(name string) error {
return
nil
return
nil
}
}
func
PushModel
(
name
string
,
regOpts
*
RegistryOptions
,
fn
func
(
api
.
ProgressResponse
))
error
{
func
PushModel
(
ctx
context
.
Context
,
name
string
,
regOpts
*
RegistryOptions
,
fn
func
(
api
.
ProgressResponse
))
error
{
mp
:=
ParseModelPath
(
name
)
mp
:=
ParseModelPath
(
name
)
fn
(
api
.
ProgressResponse
{
Status
:
"retrieving manifest"
})
fn
(
api
.
ProgressResponse
{
Status
:
"retrieving manifest"
})
...
@@ -872,7 +874,7 @@ func PushModel(name string, regOpts *RegistryOptions, fn func(api.ProgressRespon
...
@@ -872,7 +874,7 @@ func PushModel(name string, regOpts *RegistryOptions, fn func(api.ProgressRespon
layers
=
append
(
layers
,
&
manifest
.
Config
)
layers
=
append
(
layers
,
&
manifest
.
Config
)
for
_
,
layer
:=
range
layers
{
for
_
,
layer
:=
range
layers
{
exists
,
err
:=
checkBlobExistence
(
mp
,
layer
.
Digest
,
regOpts
)
exists
,
err
:=
checkBlobExistence
(
ctx
,
mp
,
layer
.
Digest
,
regOpts
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -894,13 +896,13 @@ func PushModel(name string, regOpts *RegistryOptions, fn func(api.ProgressRespon
...
@@ -894,13 +896,13 @@ func PushModel(name string, regOpts *RegistryOptions, fn func(api.ProgressRespon
Total
:
layer
.
Size
,
Total
:
layer
.
Size
,
})
})
location
,
err
:=
startUpload
(
mp
,
regOpts
)
location
,
err
:=
startUpload
(
ctx
,
mp
,
regOpts
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Printf
(
"couldn't start upload: %v"
,
err
)
log
.
Printf
(
"couldn't start upload: %v"
,
err
)
return
err
return
err
}
}
err
=
uploadBlobChunked
(
mp
,
location
,
layer
,
regOpts
,
fn
)
err
=
uploadBlobChunked
(
ctx
,
mp
,
location
,
layer
,
regOpts
,
fn
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Printf
(
"error uploading blob: %v"
,
err
)
log
.
Printf
(
"error uploading blob: %v"
,
err
)
return
err
return
err
...
@@ -918,7 +920,7 @@ func PushModel(name string, regOpts *RegistryOptions, fn func(api.ProgressRespon
...
@@ -918,7 +920,7 @@ func PushModel(name string, regOpts *RegistryOptions, fn func(api.ProgressRespon
return
err
return
err
}
}
resp
,
err
:=
makeRequest
(
"PUT"
,
url
,
headers
,
bytes
.
NewReader
(
manifestJSON
),
regOpts
)
resp
,
err
:=
makeRequest
(
ctx
,
"PUT"
,
url
,
headers
,
bytes
.
NewReader
(
manifestJSON
),
regOpts
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -940,7 +942,7 @@ func PullModel(ctx context.Context, name string, regOpts *RegistryOptions, fn fu
...
@@ -940,7 +942,7 @@ func PullModel(ctx context.Context, name string, regOpts *RegistryOptions, fn fu
fn
(
api
.
ProgressResponse
{
Status
:
"pulling manifest"
})
fn
(
api
.
ProgressResponse
{
Status
:
"pulling manifest"
})
manifest
,
err
:=
pullModelManifest
(
mp
,
regOpts
)
manifest
,
err
:=
pullModelManifest
(
ctx
,
mp
,
regOpts
)
if
err
!=
nil
{
if
err
!=
nil
{
return
fmt
.
Errorf
(
"pull model manifest: %s"
,
err
)
return
fmt
.
Errorf
(
"pull model manifest: %s"
,
err
)
}
}
...
@@ -996,13 +998,13 @@ func PullModel(ctx context.Context, name string, regOpts *RegistryOptions, fn fu
...
@@ -996,13 +998,13 @@ func PullModel(ctx context.Context, name string, regOpts *RegistryOptions, fn fu
return
nil
return
nil
}
}
func
pullModelManifest
(
mp
ModelPath
,
regOpts
*
RegistryOptions
)
(
*
ManifestV2
,
error
)
{
func
pullModelManifest
(
ctx
context
.
Context
,
mp
ModelPath
,
regOpts
*
RegistryOptions
)
(
*
ManifestV2
,
error
)
{
url
:=
fmt
.
Sprintf
(
"%s/v2/%s/manifests/%s"
,
mp
.
Registry
,
mp
.
GetNamespaceRepository
(),
mp
.
Tag
)
url
:=
fmt
.
Sprintf
(
"%s/v2/%s/manifests/%s"
,
mp
.
Registry
,
mp
.
GetNamespaceRepository
(),
mp
.
Tag
)
headers
:=
map
[
string
]
string
{
headers
:=
map
[
string
]
string
{
"Accept"
:
"application/vnd.docker.distribution.manifest.v2+json"
,
"Accept"
:
"application/vnd.docker.distribution.manifest.v2+json"
,
}
}
resp
,
err
:=
makeRequest
(
"GET"
,
url
,
headers
,
nil
,
regOpts
)
resp
,
err
:=
makeRequest
(
ctx
,
"GET"
,
url
,
headers
,
nil
,
regOpts
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Printf
(
"couldn't get manifest: %v"
,
err
)
log
.
Printf
(
"couldn't get manifest: %v"
,
err
)
return
nil
,
err
return
nil
,
err
...
@@ -1061,10 +1063,10 @@ func GetSHA256Digest(r io.Reader) (string, int) {
...
@@ -1061,10 +1063,10 @@ func GetSHA256Digest(r io.Reader) (string, int) {
return
fmt
.
Sprintf
(
"sha256:%x"
,
h
.
Sum
(
nil
)),
int
(
n
)
return
fmt
.
Sprintf
(
"sha256:%x"
,
h
.
Sum
(
nil
)),
int
(
n
)
}
}
func
startUpload
(
mp
ModelPath
,
regOpts
*
RegistryOptions
)
(
string
,
error
)
{
func
startUpload
(
ctx
context
.
Context
,
mp
ModelPath
,
regOpts
*
RegistryOptions
)
(
string
,
error
)
{
url
:=
fmt
.
Sprintf
(
"%s/v2/%s/blobs/uploads/"
,
mp
.
Registry
,
mp
.
GetNamespaceRepository
())
url
:=
fmt
.
Sprintf
(
"%s/v2/%s/blobs/uploads/"
,
mp
.
Registry
,
mp
.
GetNamespaceRepository
())
resp
,
err
:=
makeRequest
(
"POST"
,
url
,
nil
,
nil
,
regOpts
)
resp
,
err
:=
makeRequest
(
ctx
,
"POST"
,
url
,
nil
,
nil
,
regOpts
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Printf
(
"couldn't start upload: %v"
,
err
)
log
.
Printf
(
"couldn't start upload: %v"
,
err
)
return
""
,
err
return
""
,
err
...
@@ -1087,10 +1089,10 @@ func startUpload(mp ModelPath, regOpts *RegistryOptions) (string, error) {
...
@@ -1087,10 +1089,10 @@ func startUpload(mp ModelPath, regOpts *RegistryOptions) (string, error) {
}
}
// Function to check if a blob already exists in the Docker registry
// Function to check if a blob already exists in the Docker registry
func
checkBlobExistence
(
mp
ModelPath
,
digest
string
,
regOpts
*
RegistryOptions
)
(
bool
,
error
)
{
func
checkBlobExistence
(
ctx
context
.
Context
,
mp
ModelPath
,
digest
string
,
regOpts
*
RegistryOptions
)
(
bool
,
error
)
{
url
:=
fmt
.
Sprintf
(
"%s/v2/%s/blobs/%s"
,
mp
.
Registry
,
mp
.
GetNamespaceRepository
(),
digest
)
url
:=
fmt
.
Sprintf
(
"%s/v2/%s/blobs/%s"
,
mp
.
Registry
,
mp
.
GetNamespaceRepository
(),
digest
)
resp
,
err
:=
makeRequest
(
"HEAD"
,
url
,
nil
,
nil
,
regOpts
)
resp
,
err
:=
makeRequest
(
ctx
,
"HEAD"
,
url
,
nil
,
nil
,
regOpts
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Printf
(
"couldn't check for blob: %v"
,
err
)
log
.
Printf
(
"couldn't check for blob: %v"
,
err
)
return
false
,
err
return
false
,
err
...
@@ -1101,7 +1103,7 @@ func checkBlobExistence(mp ModelPath, digest string, regOpts *RegistryOptions) (
...
@@ -1101,7 +1103,7 @@ func checkBlobExistence(mp ModelPath, digest string, regOpts *RegistryOptions) (
return
resp
.
StatusCode
==
http
.
StatusOK
,
nil
return
resp
.
StatusCode
==
http
.
StatusOK
,
nil
}
}
func
uploadBlobChunked
(
mp
ModelPath
,
url
string
,
layer
*
Layer
,
regOpts
*
RegistryOptions
,
fn
func
(
api
.
ProgressResponse
))
error
{
func
uploadBlobChunked
(
ctx
context
.
Context
,
mp
ModelPath
,
url
string
,
layer
*
Layer
,
regOpts
*
RegistryOptions
,
fn
func
(
api
.
ProgressResponse
))
error
{
// TODO allow resumability
// TODO allow resumability
// TODO allow canceling uploads via DELETE
// TODO allow canceling uploads via DELETE
// TODO allow cross repo blob mount
// TODO allow cross repo blob mount
...
@@ -1158,7 +1160,7 @@ func uploadBlobChunked(mp ModelPath, url string, layer *Layer, regOpts *Registry
...
@@ -1158,7 +1160,7 @@ func uploadBlobChunked(mp ModelPath, url string, layer *Layer, regOpts *Registry
headers
[
"Content-Length"
]
=
strconv
.
Itoa
(
int
(
layer
.
Size
))
headers
[
"Content-Length"
]
=
strconv
.
Itoa
(
int
(
layer
.
Size
))
// finish the upload
// finish the upload
resp
,
err
:=
makeRequest
(
"PUT"
,
url
,
headers
,
r
,
regOpts
)
resp
,
err
:=
makeRequest
(
ctx
,
"PUT"
,
url
,
headers
,
r
,
regOpts
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Printf
(
"couldn't finish upload: %v"
,
err
)
log
.
Printf
(
"couldn't finish upload: %v"
,
err
)
return
err
return
err
...
@@ -1172,7 +1174,16 @@ func uploadBlobChunked(mp ModelPath, url string, layer *Layer, regOpts *Registry
...
@@ -1172,7 +1174,16 @@ func uploadBlobChunked(mp ModelPath, url string, layer *Layer, regOpts *Registry
return
nil
return
nil
}
}
func
makeRequest
(
method
,
url
string
,
headers
map
[
string
]
string
,
body
io
.
Reader
,
regOpts
*
RegistryOptions
)
(
*
http
.
Response
,
error
)
{
func
makeRequest
(
ctx
context
.
Context
,
method
,
url
string
,
headers
map
[
string
]
string
,
body
io
.
Reader
,
regOpts
*
RegistryOptions
)
(
*
http
.
Response
,
error
)
{
retryCtx
:=
ctx
.
Value
(
"retries"
)
var
retries
int
var
ok
bool
if
retries
,
ok
=
retryCtx
.
(
int
);
ok
{
if
retries
>
MaxRetries
{
return
nil
,
fmt
.
Errorf
(
"Maximum retries hit; are you sure you have access to this resource?"
)
}
}
if
!
strings
.
HasPrefix
(
url
,
"http"
)
{
if
!
strings
.
HasPrefix
(
url
,
"http"
)
{
if
regOpts
.
Insecure
{
if
regOpts
.
Insecure
{
url
=
"http://"
+
url
url
=
"http://"
+
url
...
@@ -1225,13 +1236,14 @@ func makeRequest(method, url string, headers map[string]string, body io.Reader,
...
@@ -1225,13 +1236,14 @@ func makeRequest(method, url string, headers map[string]string, body io.Reader,
if
resp
.
StatusCode
==
http
.
StatusUnauthorized
{
if
resp
.
StatusCode
==
http
.
StatusUnauthorized
{
auth
:=
resp
.
Header
.
Get
(
"Www-Authenticate"
)
auth
:=
resp
.
Header
.
Get
(
"Www-Authenticate"
)
authRedir
:=
ParseAuthRedirectString
(
string
(
auth
))
authRedir
:=
ParseAuthRedirectString
(
string
(
auth
))
token
,
err
:=
getAuthToken
(
authRedir
,
regOpts
)
token
,
err
:=
getAuthToken
(
ctx
,
authRedir
,
regOpts
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
regOpts
.
Token
=
token
regOpts
.
Token
=
token
bodyCopy
=
bytes
.
NewReader
(
buf
.
Bytes
())
bodyCopy
=
bytes
.
NewReader
(
buf
.
Bytes
())
return
makeRequest
(
method
,
url
,
headers
,
bodyCopy
,
regOpts
)
ctx
=
context
.
WithValue
(
ctx
,
"retries"
,
retries
+
1
)
return
makeRequest
(
ctx
,
method
,
url
,
headers
,
bodyCopy
,
regOpts
)
}
}
return
resp
,
nil
return
resp
,
nil
...
...
server/routes.go
View file @
d9cf18e2
...
@@ -277,7 +277,8 @@ func PushModelHandler(c *gin.Context) {
...
@@ -277,7 +277,8 @@ func PushModelHandler(c *gin.Context) {
Password
:
req
.
Password
,
Password
:
req
.
Password
,
}
}
if
err
:=
PushModel
(
req
.
Name
,
regOpts
,
fn
);
err
!=
nil
{
ctx
:=
context
.
Background
()
if
err
:=
PushModel
(
ctx
,
req
.
Name
,
regOpts
,
fn
);
err
!=
nil
{
ch
<-
gin
.
H
{
"error"
:
err
.
Error
()}
ch
<-
gin
.
H
{
"error"
:
err
.
Error
()}
}
}
}()
}()
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment