27 #include <unordered_map>
28 #include <sys/utsname.h>
30 #undef ZYPP_BASE_LOGGER_LOGGROUP
31 #define ZYPP_BASE_LOGGER_LOGGROUP "PurgeKernels"
38 struct utsname unameData;
39 if ( uname( &unameData) == 0 ) {
41 _uname_r = std::string( unameData.release );
47 void fillKeepList(
const std::unordered_map< std::string, std::map<
Arch, std::map<Edition, sat::Solvable> > > &installedKernels, std::set<sat::Solvable::IdType> &list )
const;
52 std::string kernelVersion;
53 std::ifstream procKernel(
"/proc/sys/kernel/osrelease" );
81 std::set< sat::Solvable::IdType> currentSetOfRemovals;
82 for (
auto it = pool.byStatusBegin( toBeUninstalledFilter ); it != pool.byStatusEnd( toBeUninstalledFilter ); it++ )
83 currentSetOfRemovals.insert( it->id() );
87 if ( !pool.resolver().resolvePool() ) {
88 MIL <<
"Failed to resolve pool, skipping " << pi << std::endl;
89 pool.resolver().problems();
95 for (
auto it = pool.byStatusBegin( toBeUninstalledFilter ); it != pool.byStatusEnd( toBeUninstalledFilter ); it++ ) {
98 if ( it->status().isByUser() || (currentSetOfRemovals.find( it->id() ) != currentSetOfRemovals.end()) )
103 MIL <<
"Package " <<
PoolItem(*it) <<
" should not be removed, skipping " << pi << std::endl;
109 MIL <<
"Removing package: " << pi << std::endl;
121 const unsigned tokenGrp = 1;
122 const unsigned modifierGrp = 2;
125 MIL <<
"Parsing keep spec: " << _keepSpec << std::endl;
127 std::vector<std::string> words;
129 if ( words.empty() ) {
130 WAR <<
"Invalid keep spec: " << _keepSpec <<
" using default latest,running." << std::endl;
134 _keepRunning =
false;
135 _keepLatestOffsets.clear();
136 _keepOldestOffsets.clear();
138 for (
const std::string &word : words ) {
139 if ( word ==
"running" ) {
144 _keepSpecificEditions.insert(
Edition(word) );
148 auto addKeepOff = [](
const auto &off,
auto &set,
const auto &constraint ){
149 const off_t num = off.empty() ? 0 : str::strtonum<off_t>( off );
150 if ( !constraint(num) )
return false;
151 set.insert( static_cast<size_t>(std::abs(num)) );
155 if ( what[tokenGrp] ==
"oldest" ) {
156 addKeepOff( what[modifierGrp], _keepOldestOffsets, [ &word ]( off_t num ) {
158 WAR <<
"Ignoring invalid modifier in keep spec: " << word <<
", oldest supports only positive modifiers." << std::endl;
164 addKeepOff( what[modifierGrp], _keepLatestOffsets, [ &word ]( off_t num ) {
166 WAR <<
"Ignoring invalid modifier in keep spec: " << word <<
", latest supports only negative modifiers." << std::endl;
180 void PurgeKernels::Impl::fillKeepList(
const std::unordered_map<std::string, std::map<
Arch, std::map<Edition, sat::Solvable> > > &installedKernels, std::set<sat::Solvable::IdType> &list )
const
182 for (
const auto &flavourMap : installedKernels ) {
183 for (
const auto &archMap : flavourMap.second ) {
185 size_t currROff = archMap.second.size() - 1;
186 for (
const auto &kernelMap : archMap.second ) {
189 if ( _keepOldestOffsets.find( currOff ) != _keepOldestOffsets.end()
190 || _keepLatestOffsets.find( currROff ) != _keepLatestOffsets.end()
192 || _keepSpecificEditions.find( kernelMap.second.edition() ) != _keepSpecificEditions.end() ) {
193 MIL <<
"Marking kernel " << kernelMap.second <<
" as to keep." << std::endl;
194 list.insert( kernelMap.second.id() ) ;
209 bool isWithFlavour = flavour.size();
212 MIL <<
"Trying to remove source/devel packages for flavour " << flavour << std::endl;
214 MIL <<
"Trying to remove global/default source/devel packages "<< std::endl;
216 auto withFlavour = [&isWithFlavour, &flavour](
const std::string &name ) {
217 return isWithFlavour ? name+
"-"+flavour : name;
229 for (
auto installedSrcPck : q ) {
231 if ( validEditions.find( installedSrcPck.edition() ) == validEditions.end() ) {
232 MIL <<
"Skipping source package " << installedSrcPck <<
" no corresponding kernel with the same version was installed." << std::endl;
245 MIL <<
"Skipping source package " << installedSrcPck <<
" binary packages with the same edition are still installed" << std::endl;
250 removePackageAndCheck( pi, validRemovals );
268 pool.resolver().setForceResolve(
true );
273 const str::regex validRemovals(
"(kernel-syms(-.*)?|kgraft-patch(-.*)?|kernel-livepatch(-.*)?|.*-kmp(-.*)?)");
276 const str::regex validDevelRemovals(
"(kernel-source(-.*)?|(kernel-syms(-.*)?)|(kernel-devel(-.*)?)|(kernel(-.*)?-devel))");
279 const str::regex kernelFlavourRegex(
"^kernel-(.*)$");
282 std::unordered_map< std::string, std::map< Arch, std::map<Edition, sat::Solvable> > > installedKernels;
285 std::set<sat::Solvable::IdType> packagesToKeep;
294 MIL <<
"Searching for obsolete kernels." << std::endl;
296 for (
auto installedKernel : q ) {
298 MIL <<
"Found installed kernel " << installedKernel << std::endl;
304 MIL <<
"Marking kernel " << installedKernel <<
" as to keep." << std::endl;
305 packagesToKeep.insert( installedKernel.id() );
310 if ( what[1].empty() ) {
311 WAR <<
"Could not detect kernel flavour for: " << installedKernel <<
" ...skipping" << std::endl;
315 const std::string flavour = what[1];
316 if ( !installedKernels.count( flavour ) )
317 installedKernels.insert( std::make_pair( flavour, std::map<
Arch, std::map<Edition, sat::Solvable> > {} ) );
319 auto &flavourMap = installedKernels[ flavour ];
320 if ( !flavourMap.count( installedKernel.arch() ) )
321 flavourMap.insert( std::make_pair( installedKernel.arch(), std::map<Edition, sat::Solvable>{} ) );
323 flavourMap[ installedKernel.arch() ].insert( std::make_pair( installedKernel.edition(), installedKernel ) );
329 MIL <<
"Starting to remove obsolete kernels." << std::endl;
332 std::set<Edition> removedVersions;
340 for (
const auto &flavourMap : installedKernels ) {
343 std::set<Edition> removedFlavourVersions;
345 for (
const auto &archMap : flavourMap.second ) {
346 for (
const auto &kernelMap : archMap.second ) {
347 auto &installedKernel = kernelMap.second;
354 if ( packagesToKeep.count( installedKernel.id() ) )
363 removedFlavourVersions.insert( installedKernel.edition() );
373 for (
auto krnlDevPck : develPckQ ) {
375 if ( krnlDevPck.arch() != installedKernel.arch() )
385 removedVersions.insert( removedFlavourVersions.begin(), removedFlavourVersions.end() );