udisks FilesystemUnmount appears to not exist when calling from python - python

I'm trying to unmount a filesystem that I mounted using FilesystemMount, but I keep getting UnknownMethod exceptions. I've verified that I can call the method on the Device interface via D-Feet, but trying to do it via dbus directly doesn't appear to work at all. I've tried using the following arguments:
''
None
[]
['']
The following code demonstrates the problem:
import dbus
bus = dbus.SystemBus()
proxy = bus.get_object('org.freedesktop.UDisks', '/dev/fd0')
dev = dbus.Interface(proxy, 'org.freedesktop.UDisks.Device')
dev.FilesystemUnmount(['force'])
Exception:
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.UnknownMethod: Method "FilesystemUmount" with signature "as" on interface "org.freedesktop.UDisks.Device" doesn't exist

Turns out that the problem is that FilesystemUnmount will only take an ObjectPath that udisks handed out. So by adding a check for that and then looking it up I got it to work. See the code below.
import dbus
path = '/dev/fd0'
bus = dbus.SystemBus()
if not isinstance(path, dbus.ObjectPath):
manager_obj = bus.get_object('org.freedesktop.UDisks',
'/org/freedesktop/UDisks')
manager = dbus.Interface(manager_obj, 'org.freedesktop.UDisks')
path = manager.FindDeviceByDeviceFile(path)
proxy = bus.get_object('org.freedesktop.UDisks', path)
dev = dbus.Interface(proxy, 'org.freedesktop.UDisks.Device')
dev.FilesystemUnmount('')

Related

pysmb from linux to Windows, Unable to connect to shared device

Trying to connect to an smb share via pysmb and getting error...
smb.smb_structs.OperationFailure: Failed to list on \\\\H021BSBD20\\shared_folder: Unable to connect to shared device
The code I am using looks like...
from smb.SMBConnection import SMBConnection
import json
import pprint
import warnings
pp = pprint.PrettyPrinter(indent=4)
PROJECT_HOME = "/path/to/my/project/"
# load configs
CONF = json.load(open(f"{PROJECT_HOME}/configs/configs.json"))
pp.pprint(CONF)
# list all files in storage smb dir
#https://pysmb.readthedocs.io/en/latest/api/smb_SMBConnection.html#smb.SMBConnection.SMBConnection.listPath
IS_DIRECT_TCP = False
CNXN_PORT = 139 if not IS_DIRECT_TCP else 445
LOCAL_IP = "172.18.4.69"
REMOTE_NAME = "H021BSBD20" # exact name shown as Device Name in System Settings
SERVICE_NAME = "\\\\H021BSBD20\\shared_folder"
REMOTE_IP = "172.18.7.102"
try:
conn = SMBConnection(CONF['smb_creds']['username'], CONF['smb_creds']['password'],
my_name=LOCAL_IP, remote_name=REMOTE_NAME,
use_ntlm_v2=True,
is_direct_tcp=IS_DIRECT_TCP)
conn.connect(REMOTE_IP, CNXN_PORT)
except Exception:
warnings.warn("\n\nFailed to initially connect, attempting again with param use_ntlm_v2=False\n\n")
conn = SMBConnection(CONF['smb_creds']['username'], CONF['smb_creds']['password'],
my_name=LOCAL_IP, remote_name=REMOTE_NAME,
use_ntlm_v2=False,
is_direct_tcp=IS_DIRECT_TCP)
conn.connect(REMOTE_IP, CNXN_PORT)
files = conn.listPath(f'{SERVICE_NAME}', '\\')
pp.pprint(files)
Using smbclient on my machine, I can successfully connect to the share by doing...
[root#airflowetl etl]# smbclient -U my_user \\\\H021BSBD20\\shared_folder
The amount of backslashes I use in the python code is so that I can create the same string that works when using this smbclient (have tried with less backslashes in the code and that has not helped).
Note that the user that I am using the access the shared folder in the python code and with smbclient is not able to access / log on to the actual machine that the share is hosted on (they are only allowed to access that particular shared folder as shown above).
Does anyone know what could be happening here? Any other debugging steps that could be done?
After asking on the github repo Issues section (https://github.com/miketeo/pysmb/issues/169), I was able to fix the problem. It was just due to the arg I was using for the conn.listPath() servicename param.
When looking closer at the docs for that function (https://pysmb.readthedocs.io/en/latest/api/smb_SMBConnection.html), I saw...
service_name (string/unicode) – the name of the shared folder for the path
Originally, I was only looking at the function signature, which said service_name, so I assumed it would be the same as with the smbclient command-line tool (which I have been entering the servicename param as \\\\devicename\\sharename (unlike with pysmb which we can see from the docstring wants just the share as the service_name)).
So rather than
files = conn.listPath("\\\\H021BSBD20\\shared_folder", '\\')
I do
files = conn.listPath("shared_folder", '\\')
The full refactored snippet is shown below, just for reference.
import argparse
import json
import os
import pprint
import socket
import sys
import traceback
import warnings
from smb.SMBConnection import SMBConnection
def parseArguments():
# Create argument parser
parser = argparse.ArgumentParser()
# Positional mandatory arguments
parser.add_argument("project_home", help="project home path", type=str)
parser.add_argument("device_name", help="device (eg. NetBIOS) name in configs of share to process", type=str)
# Optional arguments
# parser.add_argument("-dfd", "--data_file_dir",
# help="path to data files dir to be pushed to sink, else source columns based on form_type",
# type=str, default=None)
# Parse arguments
args = parser.parse_args()
return args
args = parseArguments()
for a in args.__dict__:
print(str(a) + ": " + str(args.__dict__[a]))
pp = pprint.PrettyPrinter(indent=4)
PROJECT_HOME = args.project_home
REMOTE_NAME = args.device_name
# load configs
CONF = json.load(open(f"{PROJECT_HOME}/configs/configs.json"))
CREDS = json.load(open(f"{PROJECT_HOME}/configs/creds.json"))
pp.pprint(CONF)
SMB_CONFS = next(info for info in CONF["smb_server_configs"] if info["device_name"] == args.device_name)
print("\nUsing details for device:")
pp.pprint(SMB_CONFS)
# list all files in storage smb dir
#https://pysmb.readthedocs.io/en/latest/api/smb_SMBConnection.html#smb.SMBConnection.SMBConnection.listPath
IS_DIRECT_TCP = False
CNXN_PORT = 139 if IS_DIRECT_TCP is False else 445
LOCAL_IP = socket.gethostname() #"172.18.4.69"
REMOTE_NAME = SMB_CONFS["device_name"]
SHARE_FOLDER = SMB_CONFS["share_folder"]
REMOTE_IP = socket.gethostbyname(REMOTE_NAME) # "172.18.7.102"
print(LOCAL_IP)
print(REMOTE_NAME)
try:
conn = SMBConnection(CREDS['smb_creds']['username'], CREDS['smb_creds']['password'],
my_name=LOCAL_IP, remote_name=REMOTE_NAME,
use_ntlm_v2=False,
is_direct_tcp=IS_DIRECT_TCP)
conn.connect(REMOTE_IP, CNXN_PORT)
except Exception:
traceback.print_exc()
warnings.warn("\n\nFailed to initially connect, attempting again with param use_ntlm_v2=True\n\n")
conn = SMBConnection(CREDS['smb_creds']['username'], CREDS['smb_creds']['password'],
my_name=LOCAL_IP, remote_name=REMOTE_NAME,
use_ntlm_v2=True,
is_direct_tcp=IS_DIRECT_TCP)
conn.connect(REMOTE_IP, CNXN_PORT)
files = conn.listPath(SHARE_FOLDER, '\\')
if len(files) > 0:
print("Found listed files")
for f in files:
print(f.filename)
else:
print("No files to list, this likely indicates a problem. Exiting...")
exit(255)

Print result from dbus object

I want to print the result from the dbus.
In the command line i run this:
busctl introspect org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.DBus.Properties
And i get some results.
I try with python but no luck to print the results.
import dbus
bus = dbus.SystemBus()
eth0 = bus.get_object('org.freedesktop.NetworkManager',
'/org/freedesktop/NetworkManager/Devices/eth0')
eth0_dev_iface = dbus.Interface(eth0,
dbus_interface='org.freedesktop.NetworkManager.Devices')
props = eth0_dev_iface.getProperties()
But i get this error:
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.UnknownMethod: No such method 'getProperties'
This was pretty aggravating. The interface is kinda crazy.
Try this:
import dbus
bus = dbus.SystemBus()
eth0 = bus.get_object('org.freedesktop.NetworkManager',
'/org/freedesktop/NetworkManager/Devices/eth0')
# Here's where we change things
eth0_dev_iface = dbus.Interface(eth0,
dbus_interface='org.freedesktop.DBus.Properties')
eth0_dev_iface.GetAll('org.freedesktop.NetworkManager.Devices')
Now why doesn't the documentation example code work as documented? That's a great question... The code above however, works fine.

Retrieving the netnsid of a network namespace in Python

When trying to find the correct peer network interface of a veth pair that lives in a different namespace, that end is not only indicated by its iflink property, but also by a link-netnsid. This link-netnsid is a network namespace ID which is only meaningful within the current network namespace.
The Linux kernel doesn't offer to map a netnsid to a network namespace inode number, which is the only unique identification. However, Linux offers the RTM_GETNSID request that maps a network namespace identified either by fd (NETNSA_FD) or by PID (NETNSA_PID) to the local netnsid.
How do I make such a RTM_GETNSID request in Python, preferably using the pyroute2 library? So far, I could not successfully request the netnsid for the namespace identified by PID, but only get back an invalid argument error 22, using the following script:
from pyroute2 import IPRoute
from pyroute2.netlink import NLM_F_REQUEST
import pyroute2.netlink.rtnl as rtnl
import pyroute2.netlink.rtnl.nsidmsg as nsidmsg
netstack = IPRoute()
req = nsidmsg.nsidmsg()
req['rtgen_family'] = 0
# 12345 is PID of a process inside another network namespace
req['attrs'] = [('NETNSA_PID', 12345)]
ret = netstack.nlm_request(req, rtnl.RTM_GETNSID, NLM_F_REQUEST)
It turns out that my code actually is correct, but there's a bug in pyroute2 causing the RTNETLINK message to be a few octets too short (visible in strace). As a temporary hack around this library bug it is sufficient to set two attributes, so that the kernel accepts the RTNETLINK packet and works on it, even if it isn't fully correct.
from pyroute2 import IPRoute
from pyroute2.netlink import NLM_F_REQUEST
import pyroute2.netlink.rtnl as rtnl
import pyroute2.netlink.rtnl.nsidmsg as nsidmsg
netstack = IPRoute()
req = nsidmsg.nsidmsg()
req['rtgen_family'] = 0
# 12345 is PID of a process inside another network namespace
req['attrs'] = [('NETNSA_PID', 12345), ('NETNSA_PID', 0] # hack around pyroute 0.5.0 bug
ret = netstack.nlm_request(req, rtnl.RTM_GETNSID, NLM_F_REQUEST)

write file to usb with python on linux

I apologise if the question is so stupid but I am new in linux and python.
The point is that I need to write a python script which will detect connected usb stick and write a file to it. I use opensuse(but script shoild work with any linux distro. in ideal case). Current version can detect usb and write a file if that usb is mounted. But on my machine usb is mounted only if I browse it in file manager. Until that usb detected as a partion but without mount point. So, how can I force the system to mount usb or how can I write a file using devname or devpath or another information what I can get from hal manager. I can not use "mount" command because it requires a root permission
Simplified Source code:
import dbus, gobject, os
class DeviceAddedListener:
def __init__(self):
self.bus = dbus.SystemBus()
self.hal_manager_obj = self.bus.get_object( "org.freedesktop.Hal", "/org/freedesktop/Hal/Manager")
self.hal_manager = dbus.Interface(self.hal_manager_obj, "org.freedesktop.Hal.Manager")
self.hal_manager.connect_to_signal("DeviceAdded", self.added)
def show(self, name, udi):
d_object = self.bus.get_object('org.freedesktop.Hal', udi)
d_interface = dbus.Interface(d_object,'org.freedesktop.Hal.Device')
if d_interface.QueryCapability("volume"):
print name
props = [ "block.device", "volume.label", "volume.is_mounted", "volume.mount_point", "volume.size"]
for p in props:
print '\t', p, " = ",
try:
print d_interface.GetProperty(p)
except:
print "Fail"
def added(self, udi):
self.show("DeviceAdded", udi)
self.bus.add_signal_receiver(self.property_modified,
"PropertyModified",
"org.freedesktop.Hal.Device",
"org.freedesktop.Hal",
udi,
path_keyword = "sending_device" )
def property_modified(self, numupdates, updates, sending_device = None):
self.show("PropertyModified", sending_device)
if __name__ == '__main__':
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
loop = gobject.MainLoop()
DeviceAddedListener()
print "running"
loop.run()
The output when usb plugged in
DeviceAdded
block.device = /dev/sdb1
volume.label = #
volume.is_mounted = 0
volume.mount_point =
volume.size = 4009722368
The output when usb plugged in and mounted
block.device = /dev/sdb1
volume.label = #
volume.is_mounted = 1
volume.mount_point = /media/#
volume.size = 4009722368
Thanks for any help!
You will have to use mount because the kernel controls mounting partitions within the operating system for security reasons. You can use mount without superuser/administrator privileges. Try something like this:
Make sure that the directory (/mnt/usb1/) you are mounting to already exists, and then
mount /dev/sdb1 /mnt/usb1 -o noauto,users,rw,umask=0
There's also something called autofs that does allow automatic mounting:
http://linuxconfig.org/automatically-mount-usb-external-drive-with-autofs
The HAL it's discontinued, I think so better use UDisks to work with pen USB. Then, you can use methods FilesystemMount and FilesystemUnmount, I create one example here (https://gist.github.com/3037221) and have oficial documantation here (http://hal.freedesktop.org/docs/udisks/Device.html#Device.FilesystemMount).

Python: Is it possible to set the clientport with xmlrpclib?

Is it possible to set the clientport for the xmlrpc-connection?
I want to say:
Client should make a ServerProxy-object to over a specific client port
or pseudocode something like this:
serv = xmlrpclib.ServerProxy("server:port","overSpecificClientPort").
Try to define a custom transport. This should be something like that:
import xmlrpclib, httplib
class sourcedTransport(xmlrpclib.Transport):
def setSource(self, src):
self.src = src
def make_connection(self, host):
h = httplib.HTTPConnection(host, source_address= self.src)
return h
srcPort = 43040
srcAddress = ('', srcPort)
p = sourcedTransport()
p.setSource(srcAddress)
server = xmlrpclib.ServerProxy("server:port", transport=p)
EDIT: bug fix httplib.HTTP => httplib.HTTPConnection
And checked that it works, in python 2.7 (but not before)
There is no option for this in module xmlrpclib, but you can create your own by modifying the original version. Assuming you use Linux, fetch /usr/lib/python2.7/xmlrpclib.py. Modify the method make_connection accordingly.
Providing a parameter source_address to HTTPConnection is supported by httplib not before Python version 2.7.
Have fun!

Categories

Resources