Skip to content

Commit b51b428

Browse files
authored
Merge pull request ceph#57169 from jagombar/fixCpatch
cpatch: Search base image when patching files. Reviewed-by: John Mulligan <[email protected]> Reviewed-by: Josh Durgin <[email protected]>
2 parents bc2bb38 + f192d5f commit b51b428

File tree

2 files changed

+93
-112
lines changed

2 files changed

+93
-112
lines changed

src/script/cpatch

Lines changed: 53 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ if [ $py -eq 1 ] || [ $all -eq 1 ]; then
123123
echo "py"
124124
# Exclude node_modules because it's the huge sources in
125125
# dashboard/frontend
126-
exclude="--exclude=node_modules"
126+
exclude="--exclude=node_modules --exclude=.tox --exclude=.angular"
127127
fi
128128
tar $exclude --exclude=tests --exclude-backups -cf $TMP/mgr_plugins.tar *
129129
popd > /dev/null
@@ -132,106 +132,100 @@ if [ $py -eq 1 ] || [ $all -eq 1 ]; then
132132
pushd ../src/python-common > /dev/null
133133
find ./ -name "*.pyc" -exec rm -f {} \;
134134
# Exclude node_modules because it's the huge sources in dashboard/frontend
135-
tar --exclude=node_modules --exclude=tests --exclude-backups -cf $TMP/python_common.tar *
135+
tar --exclude=node_modules --exclude=tests --exclude=.tox --exclude-backups -cf $TMP/python_common.tar *
136136
popd > /dev/null
137-
dockerfile+=$'ADD python_common.tar /usr/lib/python3.8/site-packages\n'
137+
dockerfile+=$'ADD python_common.tar tmp_python_common\n'
138+
dockerfile+=$'RUN for i in tmp_python_common/*; do find /usr/lib/python*/site-packages -type d -name $(basename $i) -exec cp -frpv $i/* \'{}\' \;; done && rm -rf tmp_python_common\n'
138139

139140
pushd lib/cython_modules/lib.3
140141
CYTHONLIBS="*.cpython-3*.so"
141142
mkdir -p $TMP/cythonlib
142143
for f in $CYTHONLIBS; do cp $f $TMP/cythonlib ; done
143144
[ $strip -eq 1 ] && strip $TMP/cythonlib/*
144145
popd > /dev/null
145-
dockerfile+=$'ADD cythonlib /usr/lib64/python3.8/site-packages\n'
146+
dockerfile+=$'ADD cythonlib tmp_python_common\n'
147+
dockerfile+=$'RUN for i in tmp_python_common/*; do find /usr/lib/python*/site-packages -type d -name $(basename $i) -exec cp -frpv $i/* \'{}\' \;; done && rm -rf tmp_python_common\n'
146148

147149
# cephadm
148150
pushd ../src/cephadm > /dev/null
149-
build.sh $TMP/cephadm
151+
./build.sh $TMP/cephadm
150152
dockerfile+=$'ADD cephadm /usr/sbin/cephadm\n'
151153
popd > /dev/null
152154
fi
153155

156+
# Create some temporary directories. The binaries or libraries to patch are placed in these as the cli options are processed.
157+
# At the end the base container is searched for files in these directories and the original files are replaced.
158+
mkdir -p $TMP/bin
159+
mkdir -p $TMP/lib
160+
154161
if [ $core -eq 1 ] || [ $all -eq 1 ]; then
155162
# binaries are annoying because the ceph version is embedded all over
156163
# the place, so we have to include everything but the kitchen sink.
157-
echo "core"
158-
159164
BINS="ceph-mgr ceph-mon ceph-osd rados"
160-
mkdir -p $TMP/bin
161-
for f in $BINS; do cp bin/$f $TMP/bin ; done
162-
[ $strip -eq 1 ] && strip $TMP/bin/*
163-
dockerfile+=$'ADD bin /usr/bin\n'
164-
165-
# We need ceph-common to support the binaries
166-
# We need librados/rbd to support mgr modules
167-
# that import the python bindings
168-
LIBS="libceph-common.so.2 libceph-common.so librados.so.2 librados.so librados.so.2.0.0"
169-
mkdir -p $TMP/lib
170-
for f in $LIBS; do cp lib/$f $TMP/lib ; done
165+
if [ $core -eq 1 ]; then
166+
echo "core"
167+
for f in $BINS; do cp bin/$f $TMP/bin ; done
168+
else
169+
# copy ALL locally built binaries (apart from test programs) over those that already exist in the image.
170+
echo "all"
171+
find bin -type f \! \( -name "ceph_test*" -o -name "test_*" -o -name "unittest_*" \) -exec cp {} $TMP/bin \;
172+
# Need to strip all binaries that are copied (except those in the core BINS list) otherwise the container will be huge
173+
# Some of the files in the bins directory are actually scripts so ignore errors when strip fails for these files.
174+
find $TMP/bin -type f $(printf "! -name %s " $BINS) -exec strip {} \; || true
175+
fi
176+
[ $strip -eq 1 ] && for f in $BINS; do strip $TMP/bin/$f; done
177+
178+
# Copy all locally built libraries over those that already exist in the image
179+
cp -d lib/*.so lib/*.so.* $TMP/lib
171180
[ $strip -eq 1 ] && strip $TMP/lib/*
172-
dockerfile+=$'ADD lib /usr/lib64\n'
173-
174-
ECLIBS="libec_*.so*"
175-
mkdir -p $TMP/eclib
176-
for f in lib/$ECLIBS; do cp $f $TMP/eclib ; done
177-
[ $strip -eq 1 ] && strip $TMP/eclib/*
178-
dockerfile+=$'ADD eclib /usr/lib64/ceph/erasure-code\n'
179-
180-
CLSLIBS="libcls_*.so*"
181-
mkdir -p $TMP/clslib
182-
for f in lib/$CLSLIBS; do cp $f $TMP/clslib ; done
183-
[ $strip -eq 1 ] && strip $TMP/clslib/*
184-
dockerfile+=$'ADD clslib /usr/lib64/rados-classes\n'
185-
186-
# by default locally built binaries assume /usr/local
187-
dockerfile+=$'RUN rm -rf /usr/local/lib64 ; ln -s /usr/lib64 /usr/local ; ln -s /usr/share/ceph /usr/local/share\n'
188181
fi
189182

190183
if [ $rgw -eq 1 ] || [ $all -eq 1 ]; then
191184
echo "rgw"
192185
RGW="radosgw radosgw-admin"
193-
mkdir -p $TMP/rgw
194-
for f in $RGW; do cp bin/$f $TMP/rgw ; done
195-
[ $strip -eq 1 ] && strip $TMP/rgw/*
196-
dockerfile+=$'ADD rgw /usr/bin\n'
197-
198-
RGWLIBS="libradosgw.so*"
199-
mkdir -p $TMP/rgwlib
200-
for f in lib/$RGWLIBS; do cp $f $TMP/rgwlib ; done
201-
[ $strip -eq 1 ] && strip $TMP/rgwlib/*
202-
dockerfile+=$'ADD rgwlib /usr/lib64\n'
186+
for f in $RGW; do cp bin/$f $TMP/bin ; done
187+
[ $strip -eq 1 ] && for f in $RGW; do strip $TMP/bin/$f; done
188+
189+
RGWLIBS="librados.so.* libceph-common.so.*"
190+
for f in $RGWLIBS; do cp lib/$f $TMP/lib ; done
191+
[ $strip -eq 1 ] && for f in $RGWLIBS; do strip $TMP/lib/$f; done
203192
fi
204193

205194
if [ $cephfs -eq 1 ] || [ $all -eq 1 ]; then
206195
echo "cephfs"
207196
FS="ceph-mds"
208-
mkdir -p $TMP/fs
209-
for f in $FS; do cp bin/$f $TMP/fs ; done
210-
[ $strip -eq 1 ] && strip $TMP/fs/*
211-
dockerfile+=$'ADD fs /usr/bin\n'
197+
for f in $FS; do cp bin/$f $TMP/bin ; done
198+
[ $strip -eq 1 ] && for f in $FS; do strip $TMP/bin/$f; done
212199

213200
FSLIBS="libcephfs.so*"
214-
mkdir -p $TMP/fslib
215201
for f in lib/$FSLIBS; do cp $f $TMP/fslib ; done
216-
[ $strip -eq 1 ] && strip $TMP/fslib/*
217-
dockerfile+=$'ADD fslib /usr/lib64\n'
202+
[ $strip -eq 1 ] && for f in $FSLIBS; do strip $TMP/lib/$f; done
218203
fi
219204

220205
if [ $rbd -eq 1 ] || [ $all -eq 1 ]; then
221206
echo "rbd"
222207
RBD="rbd rbd-mirror"
223-
mkdir -p $TMP/rbd
224-
for f in $RBD; do cp bin/$f $TMP/rbd ; done
225-
[ $strip -eq 1 ] && strip $TMP/rbd/*
226-
dockerfile+=$'ADD rbd /usr/bin\n'
208+
for f in $RBD; do cp bin/$f $TMP/bin ; done
209+
[ $strip -eq 1 ] && for f in $RBD; do strip $TMP/bin/$f; done
227210

228211
RBDLIBS="librbd.so*"
229-
mkdir -p $TMP/rbdlib
230-
for f in lib/$RBDLIBS; do cp $f $TMP/rbdlib ; done
231-
[ $strip -eq 1 ] && strip $TMP/rbdlib/*
232-
dockerfile+=$'ADD rbdlib /usr/lib64\n'
212+
for f in lib/$RBDLIBS; do cp $f $TMP/lib ; done
213+
[ $strip -eq 1 ] && for f in $RBDLIBS; do strip $TMP/lib/$f; done
233214
fi
234215

216+
# For every binary file that was copied to the $TMP/bin directory by the steps above, search for the existing file in the container and replace it.
217+
dockerfile+=$'ADD bin /tmpbin\n'
218+
dockerfile+=$'RUN for i in tmpbin/*; do find /usr/bin /usr/sbin -name $(basename $i) -exec mv -f $i \'{}\' \;; echo $(basename $i); done && rm -rf tmpbin\n'
219+
220+
# For every library file that was copied to the $TMP/lib directory by the steps above, search for the existing file in the container and replace it.
221+
dockerfile+=$'ADD lib /tmplib\n'
222+
dockerfile+=$'RUN for i in tmplib/*; do find /usr/lib64 -name $(basename $i) -exec mv -f $i \'{}\' \;; echo $(basename $i); done && rm -rf tmplib\n'
223+
224+
# by default locally built binaries assume /usr/local
225+
dockerfile+=$'RUN rm -rf /usr/local/lib64 ; ln -sf /usr/lib64 /usr/local ; ln -sf /usr/share/ceph /usr/local/share\n'
226+
# locally built binaries assume libceph-common.so.2 is in /usr/lib64 - create link to library that was just copied
227+
dockerfile+=$'RUN ln -sf /usr/lib64/ceph/libceph-common.so.2 /usr/lib64/libceph-common.so.2\n'
228+
235229
echo "build"
236230
pushd $TMP > /dev/null
237231
echo "$dockerfile" > Dockerfile

src/script/cpatch.py

Lines changed: 40 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,22 @@ def build(self):
459459
dresult = job(component)
460460
dlines.extend(dresult)
461461

462+
if os.path.isdir(self._workdir / "tmp_bin"):
463+
# For every binary file that was copied to the tmp_bin directory by the jobs above, search for the existing file in the container and replace it.
464+
dlines.append("ADD tmp_bin /tmpbin")
465+
dlines.append("RUN for i in tmpbin/*; do find /usr/bin /usr/sbin -name $(basename $i) -exec mv -f $i '{}' \;; echo $(basename $i); done && rm -rf tmpbin")
466+
467+
if os.path.isdir(self._workdir / "tmp_lib"):
468+
# For every library file that was copied to the tmp_lib directory by the jobs above, search for the existing file in the container and replace it.
469+
dlines.append("ADD tmp_lib /tmplib")
470+
dlines.append("RUN for i in tmplib/*; do find /usr/lib64 -name $(basename $i) -exec mv -f $i '{}' \;; echo $(basename $i); done && rm -rf tmplib")
471+
472+
if os.path.isdir(self._workdir / "tmp_bin"):
473+
# by default locally built binaries assume /usr/local
474+
dlines.append("RUN rm -rf /usr/local/lib64 && ln -sf /usr/lib64 /usr/local && ln -sf /usr/share/ceph /usr/local/share")
475+
# locally built binaries assume libceph-common.so.2 is in /usr/lib64 - create link to library that was just copied
476+
dlines.append("RUN ln -sf /usr/lib64/ceph/libceph-common.so.2 /usr/lib64/libceph-common.so.2")
477+
462478
with open(self._workdir / "Dockerfile", "w") as fout:
463479
for line in dlines:
464480
print(line, file=fout)
@@ -502,7 +518,9 @@ def _copy_binary(self, src_path, dst_path):
502518
if self._ctx.strip_binaries:
503519
log.debug("copy and strip: %s", dst_path)
504520
shutil.copy2(src_path, dst_path)
505-
_run(["strip", str(dst_path)]).check_returncode()
521+
output = _run(["file", str(dst_path)], capture_output=True, text=True)
522+
if "ELF" in output.stdout:
523+
_run(["strip", str(dst_path)]).check_returncode()
506524
return
507525
log.debug("hard linking: %s", dst_path)
508526
try:
@@ -511,39 +529,29 @@ def _copy_binary(self, src_path, dst_path):
511529
pass
512530
os.link(src_path, dst_path)
513531

514-
def _bins_and_libs(self, prefix, bin_patterns, lib_patterns):
532+
def _bins_and_libs(self, prefix, bin_patterns, lib_patterns, exclude_prefixes=[]):
515533
out = []
516534

517535
bin_src = self._ctx.build_dir / "bin"
518536
bin_dst = self._workdir / f"{prefix}_bin"
519537
bin_dst.mkdir(parents=True, exist_ok=True)
520538
for path in bin_src.iterdir():
521539
if any(path.match(m) for m in bin_patterns):
540+
if any(path.match(f"{m}*") for m in exclude_prefixes):
541+
continue
522542
self._copy_binary(path, bin_dst / path.name)
523-
out.append(f"ADD {prefix}_bin /usr/bin")
524543

525544
lib_src = self._ctx.build_dir / "lib"
526545
lib_dst = self._workdir / f"{prefix}_lib"
527546
lib_dst.mkdir(parents=True, exist_ok=True)
528547
for path in lib_src.iterdir():
529548
if any(path.match(m) for m in lib_patterns):
549+
if any(path.match(f"{m}*") for m in exclude_prefixes):
550+
continue
530551
self._copy_binary(path, lib_dst / path.name)
531-
out.append(f"ADD {prefix}_lib /usr/lib64")
532552

533553
return out
534554

535-
def _conditional_libs(self, src_dir, name, destination, lib_patterns):
536-
lib_src = self._ctx.build_dir / src_dir
537-
lib_dst = self._workdir / name
538-
lib_dst.mkdir(parents=True, exist_ok=True)
539-
try:
540-
for path in lib_src.iterdir():
541-
if any(path.match(m) for m in lib_patterns):
542-
self._copy_binary(path, lib_dst / path.name)
543-
except FileNotFoundError as err:
544-
log.warning("skipping lib %s: %s", name, err)
545-
return f"ADD {name} {destination}"
546-
547555
def _py_site_packages(self):
548556
"""Return the correct python site packages dir for the image."""
549557
if self._cached_py_site_packages is not None:
@@ -583,7 +591,7 @@ def _py_mgr_job(self, component):
583591
exclude_dirs = ("tests",)
584592
else:
585593
log.debug("Excluding dashboard from mgr")
586-
exclude_dirs = ("tests", "node_modules")
594+
exclude_dirs = ("tests", "node_modules", ".tox", ".angular" )
587595
exclude_file_suffixes = (".pyc", ".pyo", ".tmp", "~")
588596
with tarfile.open(self._workdir / name, mode="w") as tar:
589597
with ChangeDir(self._ctx.source_dir / "src/pybind/mgr"):
@@ -596,7 +604,7 @@ def _py_mgr_job(self, component):
596604

597605
def _py_common_job(self, component):
598606
name = "python_common.tar"
599-
exclude_dirs = ("tests", "node_modules")
607+
exclude_dirs = ("tests", "node_modules", ".tox" )
600608
exclude_file_suffixes = (".pyc", ".pyo", ".tmp", "~")
601609
with tarfile.open(self._workdir / name, mode="w") as tar:
602610
with ChangeDir(self._ctx.source_dir / "src/python-common"):
@@ -637,60 +645,39 @@ def _core_job(self, component):
637645
# [Quoth the original script]:
638646
# binaries are annoying because the ceph version is embedded all over
639647
# the place, so we have to include everything but the kitchen sink.
640-
out = []
641-
642-
out.extend(
643-
self._bins_and_libs(
644-
prefix="core",
645-
bin_patterns=["ceph-mgr", "ceph-mon", "ceph-osd", "rados"],
646-
lib_patterns=["libceph-common.so*", "librados.so*"],
647-
)
648-
)
649-
650-
out.append(
651-
self._conditional_libs(
652-
src_dir="lib",
653-
name="eclib",
654-
destination="/usr/lib64/ceph/erasure-code",
655-
lib_patterns=["libec_*.so*"],
656-
)
657-
)
658-
out.append(
659-
self._conditional_libs(
660-
src_dir="lib",
661-
name="clslib",
662-
destination="/usr/lib64/rados-classes",
663-
lib_patterns=["libcls_*.so*"],
664-
)
665-
)
648+
if not self._ctx.components_selected:
649+
log.warning("Copying ALL locally built binaries over those that already exist in the image.")
650+
bins=['*']
651+
else:
652+
bins=["ceph-mgr", "ceph-mon", "ceph-osd", "rados"]
666653

667-
# [Quoth the original script]:
668-
# by default locally built binaries assume /usr/local
669-
out.append(
670-
"RUN rm -rf /usr/local/lib64 && ln -s /usr/lib64 /usr/local && ln -s /usr/share/ceph /usr/local/share"
654+
return self._bins_and_libs(
655+
prefix="tmp",
656+
bin_patterns=bins,
657+
lib_patterns=["*.so","*.so.*"],
658+
exclude_prefixes=["ceph_test","test_","unittest_"],
671659
)
672-
673660
return out
674661

675662
def _rgw_job(self, component):
676663
return self._bins_and_libs(
677-
prefix="rgw",
664+
prefix="tmp",
678665
bin_patterns=["radosgw", "radosgw-admin"],
679-
lib_patterns=["libradosgw.so*"],
666+
lib_patterns=["librados.so*", "libceph-common.so*"],
680667
)
681668
return out
682669

683670
def _cephfs_job(self, component):
684671
return self._bins_and_libs(
685-
prefix="cephfs",
672+
prefix="tmp",
686673
bin_patterns=["ceph-mds"],
687674
lib_patterns=["libcephfs.so*"],
688675
)
689676
return out
690677

691678
def _rbd_job(self, component):
692679
return self._bins_and_libs(
693-
prefix="rbd",
680+
prefix="tmp",
694681
bin_patterns=["rbd", "rbd-mirror"],
695682
lib_patterns=["librbd.so*"],
696683
)

0 commit comments

Comments
 (0)