My first zypp python plugin

Hi,

I need to execute some operations when a package is installed/removed/updated.
From a quick read of the documentation seems that i could create a zypp plugin (python) which can execute these operations according the transaction data.
I tried to write a “commit plugin” to start but nothing happens.
It’s not called from zypper.
The plugin content is this
What am i wronging?

I briefly tested on TW and plugin most certainly is called. You need to provide more detailed description what you actually did and why you think it dies not work.

Yep, i must correct me. I have seen in /var/log/zypper.log that it is called.
Now, this is my plugin content:


#!/usr/bin/env python
#
# zypp commit plugin
#
import os
import sys
from zypp_plugin import Plugin

class MyPlugin(Plugin):

  def PLUGINBEGIN(self, headers, body):
    # commit is going to start.
    print "Start myplugin......"

    if headers.has_key('userdata'):
      print "Commit starts with TID '%s'" % headers'userdata']
    self.ack()

  def PLUGINEND(self, headers, body):
    # commit ended
    self.ack()

plugin = MyPlugin()
plugin.main()


When i run a package installation (for debug purpose) i would see the print output in the log.
I see nothing.
The goal of this simple plugin is to understand how it works (protocol) and how i can read the transaction data and then to execute my business logic.

If you can give me a better documentation about that i’d be very happy.

And which log would it be?

/var/log/zypper.log.
Probably that print output doesn’t write there.

How could i see the headers and body content ?

And did you try to actually look into this file? Your code results in Python exception on TW. There is no plugin for Python 2 in TW and code is incompatible with Python 3. The following works:

#!/usr/bin/env python3
#
# zypp commit plugin
#
import os
import sys
from zypp_plugin import Plugin


class MyPlugin(Plugin):


  def PLUGINBEGIN(self, headers, body):
    # commit is going to start.
    if 'userdata' in headers:
      print ("Commit starts with TID '%s'" % headers'userdata'])
    self.ack()


  def PLUGINEND(self, headers, body):
    # commit ended
    self.ack()


plugin = MyPlugin()
plugin.main()

With python3 i get an error on this line:


from zypp_plugin import Plugin
ModuleNotFoundError: No module named 'zypp_plugin'

With python3.9 it works for me.
This is the content of my example script :


#!/usr/bin/env python3.9
#
# zypp commit plugin
#
import os
import sys
from zypp_plugin import Plugin


class MyPlugin(Plugin):


    def PLUGINBEGIN(self, headers, body):

        print ("PLUGINBEGIN start")
        print ("headers: '%s'" % headers)
        print ("body: '%s'" % body)

        # commit is going to start.
        if 'userdata' in headers:
            print ("Commit starts with TID '%s'" % headers'userdata'])
        self.ack()


    def COMMITBEGIN(self, headers, body):
        print ("COMMITBEGIN start")
        print ("headers: '%s'" % headers)
        print ("body: '%s'" % body)
        self.ack()


    def COMMITEND(self, headers, body):
        print ("COMMITEND start")
        print ("headers: '%s'" % headers)
        print ("body: '%s'" % body)
        self.ack()


    def PLUGINEND(self, headers, body):
        # commit ended
        self.ack()


plugin = MyPlugin()
plugin.main()

I see the transaction data in /var/log/zypper.log finally :wink:
Following i report only commit output because headers and body are empty in PLUGINBEGIN and PLUGINEND


COMMITBEGIN start
2021-06-28 11:00:08 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! headers: '{}'
2021-06-28 11:00:08 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! body: '{
2021-06-28 11:00:08 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! "TransactionStepList": {
2021-06-28 11:00:08 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! "solvable": {
2021-06-28 11:00:08 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! "a": "noarch",
2021-06-28 11:00:08 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! "n": "screenfetch",
2021-06-28 11:00:08 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! "r": "1.5",
2021-06-28 11:00:08 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! "v": "3.9.1"
2021-06-28 11:00:08 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! },
2021-06-28 11:00:08 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! "type": "-"
2021-06-28 11:00:08 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! }]
2021-06-28 11:00:08 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! }'


COMMITEND start
2021-06-28 11:00:09 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! headers: '{}'
2021-06-28 11:00:09 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! body: '{
2021-06-28 11:00:09 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! "TransactionStepList": {
2021-06-28 11:00:09 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! "solvable": {
2021-06-28 11:00:09 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! "a": "noarch",
2021-06-28 11:00:09 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! "n": "screenfetch",
2021-06-28 11:00:09 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! "r": "1.5",
2021-06-28 11:00:09 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! "v": "3.9.1"
2021-06-28 11:00:09 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! },
2021-06-28 11:00:09 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! "stage": "ok",
2021-06-28 11:00:09 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! "type": "-"
2021-06-28 11:00:09 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! }]
2021-06-28 11:00:09 <2> localhost.localdomain(14995) [PLUGIN] PluginScript.cc(~PluginDumpStderr):75 ! }'


For the test, I installed and removed screenfetch package as you can see in the log.
Anyway, i have some doubts yet.
Why do i not see the “userdata” in the headers in PLUGINBEGIN?
It should contain it or depends by package?
Moreover, transactionsteplist in the body, contains the packages name involved in the transaction, could it also contain the files involved ?

For this case the file are:


/usr/bin/screenfetch
/usr/share/doc/packages/screenfetch
/usr/share/doc/packages/screenfetch/CHANGELOG
/usr/share/doc/packages/screenfetch/README.mkdn
/usr/share/doc/packages/screenfetch/TODO
/usr/share/licenses/screenfetch
/usr/share/licenses/screenfetch/COPYING
/usr/share/man/man1/screenfetch.1.gz

There are multiple packages for different Python versions and default Python version can be changed as well. You provided zero information about your system, there is no way anyone could guess what was needed.

Ah ok, now i seen that exist various version.
I thought that there was an error in my system and thus i posted the script which works in my case.
About the doubts above we can get the transaction id setting it with --userdata option. In my case :


sudo zypper --userdata MyTrans in -f screenfetch

In pluginbegin function i can get MyTrans in the header.
From the libzypp documentation seems that in TransactionStepList cannot be present info about the files list of the transaction.
If that is correct , we can close this thread and mark it as resolved.

Thanks for the collaboration

Hi. I want to learn how to create a zypp plugin with the help of python coding. I want to know how python coding perform. Is python coding required internet for performing and creating plugins?