mirror of
https://github.com/xcat2/confluent.git
synced 2026-01-12 11:02:30 +00:00
Implement Windows iso extraction
If a user has custom windows categories, match them to media import. To do this, we needed to go to pycdlib, as libarchive can't do UDF-only isos. For now, this has no progress indication, but does extract it similar to most Linux distributions are done.
This commit is contained in:
@@ -9,6 +9,11 @@ logging.getLogger('libarchive').addHandler(logging.NullHandler())
|
||||
import libarchive
|
||||
import hashlib
|
||||
import os
|
||||
try:
|
||||
from io import BytesIO
|
||||
import pycdlib
|
||||
except ImportError:
|
||||
pycdlib = None
|
||||
import shutil
|
||||
import sys
|
||||
import time
|
||||
@@ -24,6 +29,7 @@ import confluent.messages as msg
|
||||
|
||||
COPY = 1
|
||||
EXTRACT = 2
|
||||
EXTRACTUDF = 4
|
||||
READFILES = set([
|
||||
'.disk/info',
|
||||
'media.1/products',
|
||||
@@ -268,8 +274,33 @@ def extract_entries(entries, flags=0, callback=None, totalsize=None, extractlist
|
||||
return float(sizedone) / float(totalsize)
|
||||
|
||||
|
||||
def extract_file(archfile, flags=0, callback=lambda x: None, imginfo=(), extractlist=None):
|
||||
def extract_udf(archfile, callback=lambda x: None):
|
||||
"""Extracts a UDF archive from a file into the current directory."""
|
||||
dfd = os.dup(archfile.fileno())
|
||||
os.lseek(dfd, 0, 0)
|
||||
fp = os.fdopen(dfd, 'rb')
|
||||
udf = pycdlib.PyCdlib()
|
||||
udf.open_fp(fp)
|
||||
for dirent in udf.walk(udf_path='/'):
|
||||
for filent in dirent[2]:
|
||||
currfile = os.path.join(dirent[0], filent)
|
||||
relfile = currfile
|
||||
if currfile[0] == '/':
|
||||
relfile = currfile[1:]
|
||||
targfile = os.path.join('.', relfile)
|
||||
if os.path.exists(targfile):
|
||||
os.unlink(targfile)
|
||||
os.makedirs(os.path.dirname(targfile), exist_ok=True)
|
||||
udf.get_file_from_iso(targfile, udf_path=currfile)
|
||||
udf.close()
|
||||
fp.close()
|
||||
return True
|
||||
|
||||
|
||||
def extract_file(archfile, flags=0, callback=lambda x: None, imginfo=(), extractlist=None, method=EXTRACT):
|
||||
"""Extracts an archive from a file into the current directory."""
|
||||
if EXTRACTUDF & method:
|
||||
return extract_udf(archfile, callback)
|
||||
totalsize = 0
|
||||
for img in imginfo:
|
||||
if not imginfo[img]:
|
||||
@@ -604,7 +635,28 @@ def check_coreos(isoinfo):
|
||||
'method': EXTRACT, 'category': 'coreos'}
|
||||
|
||||
|
||||
|
||||
def check_windows(isoinfo):
|
||||
idwbinfo = isoinfo[1].get('sources/idwbinfo.txt', b'')
|
||||
idwbinfo = idwbinfo.decode()
|
||||
idwbinfo = idwbinfo.split('\n')
|
||||
version = ''
|
||||
for line in idwbinfo:
|
||||
if 'BuildBranch=' in line:
|
||||
branch = line.strip().split('=')[1]
|
||||
if branch == 'rs5_release':
|
||||
version = '2019'
|
||||
elif branch == 'fe_release':
|
||||
version = '2022'
|
||||
elif branch == 'ge_release':
|
||||
version = '2025'
|
||||
category = f'windows{version}'
|
||||
if version:
|
||||
defprofile = '/opt/confluent/lib/osdeploy/{0}'.format(category)
|
||||
if not os.path.exists(defprofile):
|
||||
return None
|
||||
return {'name': 'windows-{0}-x86_64'.format(version), 'method': EXTRACTUDF, 'category': category}
|
||||
return None
|
||||
|
||||
def check_rhel(isoinfo):
|
||||
ver = None
|
||||
arch = None
|
||||
@@ -659,25 +711,47 @@ def check_rhel(isoinfo):
|
||||
|
||||
|
||||
def scan_iso(archive):
|
||||
scanudf = False
|
||||
filesizes = {}
|
||||
filecontents = {}
|
||||
dfd = os.dup(archive.fileno())
|
||||
os.lseek(dfd, 0, 0)
|
||||
try:
|
||||
with libarchive.fd_reader(dfd) as reader:
|
||||
with libarchive.fd_reader(dfd, ) as reader:
|
||||
for ent in reader:
|
||||
if str(ent).endswith('TRANS.TBL'):
|
||||
continue
|
||||
eventlet.sleep(0)
|
||||
filesizes[str(ent)] = ent.size
|
||||
if str(ent) == 'README.TXT':
|
||||
readmecontents = b''
|
||||
for block in ent.get_blocks():
|
||||
readmecontents += bytes(block)
|
||||
if b'ISO-13346' in readmecontents:
|
||||
scanudf = True
|
||||
if str(ent) in READFILES:
|
||||
filecontents[str(ent)] = b''
|
||||
for block in ent.get_blocks():
|
||||
filecontents[str(ent)] += bytes(block)
|
||||
if scanudf:
|
||||
return scan_udf(dfd)
|
||||
finally:
|
||||
os.close(dfd)
|
||||
return filesizes, filecontents
|
||||
|
||||
def scan_udf(dfd):
|
||||
fp = os.fdopen(dfd, 'rb')
|
||||
iso = pycdlib.PyCdlib()
|
||||
iso.open_fp(fp)
|
||||
try:
|
||||
extracted = BytesIO()
|
||||
iso.get_file_from_iso_fp(extracted, udf_path='/sources/idwbinfo.txt')
|
||||
idwbinfo = extracted.getvalue()
|
||||
return {}, {'sources/idwbinfo.txt': idwbinfo}
|
||||
except Exception:
|
||||
return {}, {}
|
||||
|
||||
|
||||
|
||||
def fingerprint(archive):
|
||||
archive.seek(0)
|
||||
@@ -736,9 +810,9 @@ def import_image(filename, callback, backend=False, mfd=None, custtargpath=None,
|
||||
print('Importing OS to ' + targpath + ':')
|
||||
callback({'progress': 0.0})
|
||||
pct = 0.0
|
||||
if EXTRACT & identity['method']:
|
||||
if EXTRACT & identity['method'] or EXTRACTUDF & identity['method']:
|
||||
pct = extract_file(archive, callback=callback, imginfo=imginfo,
|
||||
extractlist=identity.get('extractlist', None))
|
||||
extractlist=identity.get('extractlist', None), method=identity['method'])
|
||||
if COPY & identity['method']:
|
||||
basename = identity.get('copyto', os.path.basename(filename))
|
||||
targiso = os.path.join(targpath, basename)
|
||||
|
||||
Reference in New Issue
Block a user