Commit 4dbc4c1f authored by Daniel P. Berrange's avatar Daniel P. Berrange

docker: add support for v2 registry server

Many images are no longer available to download the via
v1 registry server. Implement the v2 registry server
protocol, in combination with the v2.1 metadata file
format.
Signed-off-by: 's avatarDaniel P. Berrange <berrange@redhat.com>
parent 0e1bd373
...@@ -212,6 +212,17 @@ class DockerRegistry(): ...@@ -212,6 +212,17 @@ class DockerRegistry():
def set_auth_handler(self, auth_handler): def set_auth_handler(self, auth_handler):
self.auth_handler = auth_handler self.auth_handler = auth_handler
def supports_v2(self):
try:
(data, res) = self.get_json("/v2/")
ver = res.info().getheader("Docker-Distribution-Api-Version")
except urllib2.HTTPError as e:
ver = e.headers.get("Docker-Distribution-Api-Version", None)
if ver is None:
return False
return ver.startswith("registry/2")
def set_server(self, server): def set_server(self, server):
self.uri_base[1] = server self.uri_base[1] = server
...@@ -376,6 +387,13 @@ class DockerSource(base.Source): ...@@ -376,6 +387,13 @@ class DockerSource(base.Source):
self._check_cert_validate() self._check_cert_validate()
registry = DockerRegistry.from_template(template) registry = DockerRegistry.from_template(template)
registry.set_auth_handler(DockerAuthBearer())
if registry.supports_v2():
self._download_template_impl_v2(registry, image, template, templatedir, createdFiles, createdDirs)
else:
self._download_template_impl_v1(registry, image, template, templatedir, createdFiles, createdDirs)
def _download_template_impl_v1(self, registry, image, template, templatedir, createdFiles, createdDirs):
basicauth = DockerAuthBasic(template.username, template.password) basicauth = DockerAuthBasic(template.username, template.password)
registry.set_auth_handler(basicauth) registry.set_auth_handler(basicauth)
try: try:
...@@ -435,6 +453,49 @@ class DockerSource(base.Source): ...@@ -435,6 +453,49 @@ class DockerSource(base.Source):
with open(indexfile, "w") as f: with open(indexfile, "w") as f:
f.write(json.dumps(index)) f.write(json.dumps(index))
def _download_template_impl_v2(self, registry, image, template, templatedir, createdFiles, createdDirs):
(manifest, res) = registry.get_json( "/v2/%s/%s/manifests/%s" % (
image.repo, image.name, image.tag))
layerChecksums = [
layer["blobSum"] for layer in manifest["fsLayers"]
]
layers = [
json.loads(entry["v1Compatibility"]) for entry in manifest["history"]
]
for i in range(len(layerChecksums)):
layerChecksum = layerChecksums[i]
config = layers[i]
layerdir = templatedir + "/" + config["id"]
if not os.path.exists(layerdir):
os.makedirs(layerdir)
createdDirs.append(layerdir)
jsonfile = layerdir + "/template.json"
datafile = layerdir + "/template.tar.gz"
with open(jsonfile, "w") as fh:
fh.write(json.dumps(config))
registry.save_data("/v2/%s/%s/blobs/%s" % (
image.repo, image.name, layerChecksum),
datafile, checksum=layerChecksum)
index = {
"repo": image.repo,
"name": image.name,
"tag": image.tag,
}
indexfile = templatedir + "/" + layers[0]["id"] + "/index.json"
with open(indexfile, "w") as f:
f.write(json.dumps(index))
def create_template(self, template, templatedir, connect=None): def create_template(self, template, templatedir, connect=None):
image = DockerImage.from_template(template) image = DockerImage.from_template(template)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment