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() );
void fillKeepList(const std::unordered_map< std::string, std::map< Arch, std::map< Edition, sat::Solvable > > > &installedKernels, std::set< sat::Solvable::IdType > &list) const
void addAttribute(const sat::SolvAttr &attr, const std::string &value="")
Filter by the value of the specified attr attribute.
static const ResKind package
void markObsoleteKernels()
bool removePackageAndCheck(PoolItem &item, const str::regex &validRemovals) const
static ZConfig & instance()
Singleton ctor.
std::set< size_t > _keepOldestOffsets
Filter solvables according to their status.
std::string multiversionKernels() const
ResStatus & status() const
Returns the current status.
std::string unameR() const
void addDependency(const sat::SolvAttr &attr, const std::string &name, const Rel &op, const Edition &edition)
Query "name|global op edition".
void addKind(const ResKind &kind)
Filter by selectable kind.
Edition represents [epoch:]version[-release]
RW_pointer< Impl > _pimpl
std::set< Edition > _keepSpecificEditions
void setUnameR(const std::string &val)
std::string getline(std::istream &str)
Read one line from stream.
unsigned split(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \, const Trim trim_r=NO_TRIM)
Split line_r into words.
ResStatus & statusReset() const
Reset status.
void setKernelArch(const zypp::Arch &arch)
static std::string detectRunningKernel()
std::set< size_t > _keepLatestOffsets
const_iterator begin() const
Query result accessers.
std::string keepSpec() const
static const SolvAttr name
void setInstalledOnly()
Return only repo packages.
bool setToBeUninstalled(TransactByValue causer)
const_iterator end() const
An iterator pointing to the end of the query result.
void setKeepSpec(const std::string &val)
Regular expression match result.
void cleanDevelAndSrcPackages(const str::regex &validRemovals, std::set< Edition > &validEditions, const std::string &flavour=std::string())
Use POSIX Extended Regular Expression syntax when interpreting regex.
bool isToBeUninstalled() const
void setMatchExact()
Set to match exact string instead of substring.
static const SolvAttr provides
bool regex_match(const std::string &s, smatch &matches, const regex ®ex)
regex ZYPP_STR_REGEX regex ZYPP_STR_REGEX
Combining sat::Solvable and ResStatus.
Easy-to use interface to the ZYPP dependency resolver.
Solvable to Selectable transform functor.
static ResPool instance()
Singleton ctor.