forked from shaba/openuds
Removed legacy actors
This commit is contained in:
parent
a3bcedc38f
commit
f922bbcd2e
10
legacy_actors/.gitignore
vendored
10
legacy_actors/.gitignore
vendored
@ -1,10 +0,0 @@
|
||||
bin
|
||||
*_enterprise*
|
||||
udsactor*.deb
|
||||
udsactor*.build
|
||||
udsactor*.changes
|
||||
/udsactor_*.dsc
|
||||
/udsactor_*.tar.xz
|
||||
/udsactor_*_amd64.buildinfo
|
||||
/udsactor*.rpm
|
||||
linux/debian/files
|
@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>actors</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.python.pydev.PyDevBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.python.pydev.pythonNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?eclipse-pydev version="1.0"?><pydev_project>
|
||||
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
|
||||
<path>/${PROJECT_DIR_NAME}/src</path>
|
||||
</pydev_pathproperty>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
|
||||
</pydev_project>
|
1
legacy_actors/linux/.gitignore
vendored
1
legacy_actors/linux/.gitignore
vendored
@ -1 +0,0 @@
|
||||
/udsactor-*[1-9].*.spec
|
@ -1,98 +0,0 @@
|
||||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
|
||||
# Directories
|
||||
SOURCEDIR := ../src
|
||||
LIBDIR := $(DESTDIR)/usr/share/UDSActor
|
||||
BINDIR := $(DESTDIR)/usr/bin
|
||||
SBINDIR = $(DESTDIR)/usr/sbin
|
||||
APPSDIR := $(DESTDIR)/usr/share/applications
|
||||
CFGDIR := $(DESTDIR)/etc/udsactor
|
||||
INITDIR := $(DESTDIR)/etc/init.d
|
||||
POLKITDIR := $(DESTDIR)/usr/share/polkit-1/actions/
|
||||
XDGAUTOSTARTDIR := $(DESTDIR)/etc/xdg/autostart
|
||||
KDEAUTOSTARTDIR := $(DESTDIR)/usr/share/autostart
|
||||
|
||||
PYC := $(shell find $(SOURCEDIR) -name '*.py[co]')
|
||||
CACHES := $(shell find $(SOURCEDIR) -name '__pycache__')
|
||||
|
||||
clean:
|
||||
rm -rf $(PYC) $(CACHES) $(DESTDIR)
|
||||
install-udsactor-xrdp:
|
||||
mkdir -p $(BINDIR)
|
||||
cp scripts/uds-sesman.sh $(BINDIR)/uds-sesman
|
||||
cp scripts/uds-wait-session.sh $(BINDIR)/uds-wait-session
|
||||
|
||||
chmod 0755 $(BINDIR)/uds-sesman
|
||||
chmod 0755 $(BINDIR)/uds-wait-session
|
||||
|
||||
install-udsactor-nx:
|
||||
mkdir -p $(BINDIR)
|
||||
cp scripts/udsnxstart.sh $(BINDIR)/udsnxstart
|
||||
cp scripts/udsnxstop.sh $(BINDIR)/udsnxstop
|
||||
|
||||
chmod 0755 $(BINDIR)/udsnxstart
|
||||
chmod 0755 $(BINDIR)/udsnxstop
|
||||
install-udsactor:
|
||||
rm -rf $(DESTDIR)
|
||||
mkdir -p $(LIBDIR)
|
||||
mkdir -p $(BINDIR)
|
||||
mkdir -p $(SBINDIR)
|
||||
mkdir -p $(APPSDIR)
|
||||
mkdir -p $(CFGDIR)
|
||||
mkdir -p $(POLKITDIR)
|
||||
mkdir -p $(XDGAUTOSTARTDIR)
|
||||
mkdir -p $(KDEAUTOSTARTDIR)
|
||||
|
||||
mkdir $(LIBDIR)/img
|
||||
|
||||
# Cleans up .pyc and cache folders
|
||||
rm -f $(PYC) $(CACHES)
|
||||
|
||||
cp -r $(SOURCEDIR)/udsactor $(LIBDIR)/udsactor
|
||||
cp $(SOURCEDIR)/img/uds.png $(LIBDIR)/img
|
||||
|
||||
cp $(SOURCEDIR)/UDSActorConfig.py $(LIBDIR)
|
||||
cp $(SOURCEDIR)/UDSActorUser.py $(LIBDIR)
|
||||
# QT Dialogs & resources
|
||||
cp $(SOURCEDIR)/*_ui.py $(LIBDIR)
|
||||
cp $(SOURCEDIR)/UDSActor_rc.py $(LIBDIR)
|
||||
|
||||
# Menu GUI app
|
||||
cp desktop/UDS_Actor_Configuration.desktop $(APPSDIR)
|
||||
|
||||
# Autostart elements for gnome/kde
|
||||
cp desktop/UDSActorTool.desktop $(XDGAUTOSTARTDIR)
|
||||
cp desktop/UDSActorTool.desktop $(KDEAUTOSTARTDIR)
|
||||
|
||||
# scripts
|
||||
cp scripts/udsactor $(BINDIR)
|
||||
cp scripts/UDSActorConfig-pkexec $(SBINDIR)
|
||||
cp scripts/UDSActorTool-startup $(BINDIR)
|
||||
cp scripts/udsvapp ${BINDIR}
|
||||
|
||||
# Policy to run as administrator
|
||||
cp policy/org.openuds.pkexec.UDSActorConfig.policy $(POLKITDIR)
|
||||
|
||||
# Fix permissions
|
||||
chmod 755 $(BINDIR)/udsactor
|
||||
chmod 755 $(BINDIR)/udsvapp
|
||||
chmod 755 $(BINDIR)/UDSActorTool-startup
|
||||
chmod 755 $(SBINDIR)/UDSActorConfig-pkexec
|
||||
chmod 755 $(LIBDIR)/UDSActorConfig.py
|
||||
chmod 755 $(LIBDIR)/UDSActorUser.py
|
||||
chmod 644 $(POLKITDIR)/org.openuds.pkexec.UDSActorConfig.policy
|
||||
|
||||
# If for red hat based, copy init.d
|
||||
ifeq ($(DISTRO),rh)
|
||||
mkdir -p $(INITDIR)
|
||||
cp debian/udsactor.init $(INITDIR)/udsactor
|
||||
ln -s /usr/share/UDSActor/UDSActorConfig.py $(SBINDIR)/UDSActorConfig
|
||||
ln -s /usr/share/UDSActor/UDSActorUser.py $(BINDIR)/UDSActorTool
|
||||
endif
|
||||
|
||||
# chmod 0755 $(BINDIR)/udsactor
|
||||
uninstall:
|
||||
rm -rf $(LIBDIR)
|
||||
# rm -f $(BINDIR)/udsactor
|
||||
rm -rf $(CFGDIR)
|
@ -1,34 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
VERSION=`cat ../../VERSION`
|
||||
RELEASE=1
|
||||
|
||||
top=`pwd`
|
||||
|
||||
# Debian based
|
||||
dpkg-buildpackage -b
|
||||
|
||||
cat udsactor-template.spec |
|
||||
sed -e s/"version 0.0.0"/"version ${VERSION}"/g |
|
||||
sed -e s/"release 1"/"release ${RELEASE}"/g > udsactor-$VERSION.spec
|
||||
|
||||
# Now fix dependencies for opensuse
|
||||
cat udsactor-template.spec |
|
||||
sed -e s/"version 0.0.0"/"version ${VERSION}"/g |
|
||||
sed -e s/"name udsactor"/"name udsactor-opensuse"/g |
|
||||
sed -e s/"PyQt4"/"python-qt4"/g |
|
||||
sed -e s/"libXScrnSaver"/"libXss1"/g > udsactor-opensuse-$VERSION.spec
|
||||
|
||||
|
||||
# Right now, udsactor-xrdp-1.7.0.spec is not needed
|
||||
for pkg in udsactor-$VERSION.spec udsactor-opensuse-$VERSION.spec; do
|
||||
|
||||
rm -rf rpm
|
||||
for folder in SOURCES BUILD RPMS SPECS SRPMS; do
|
||||
mkdir -p rpm/$folder
|
||||
done
|
||||
|
||||
rpmbuild -v -bb --clean --buildroot=$top/rpm/BUILD/$pkg-root --target noarch $pkg 2>&1
|
||||
done
|
||||
|
||||
#rm udsactor-$VERSION
|
3
legacy_actors/linux/debian/.gitignore
vendored
3
legacy_actors/linux/debian/.gitignore
vendored
@ -1,3 +0,0 @@
|
||||
/udsactor/
|
||||
/udsactor-xrdp/
|
||||
/udsactor-nx/
|
@ -1,53 +0,0 @@
|
||||
udsactor (3.0.0) stable; urgency=medium
|
||||
|
||||
* Upgraded to 3.0.0 release
|
||||
|
||||
-- Adolfo Gómez García <agomez@virtualcable.es> Wed, 10 Jul 2019 9:24:10 +0200
|
||||
|
||||
udsactor (2.2.1) stable; urgency=medium
|
||||
|
||||
* Upgraded to 2.2.1 release
|
||||
|
||||
-- Adolfo Gómez García <agomez@virtualcable.es> Thu, 2 Oct 2018 12:44:12 +0200
|
||||
|
||||
udsactor (2.2.0) stable; urgency=medium
|
||||
|
||||
* Upgraded to 2.2.0 release
|
||||
|
||||
-- Adolfo Gómez García <agomez@virtualcable.es> Thu, 19 Oct 2017 16:44:12 +0200
|
||||
|
||||
udsactor (2.1.0) stable; urgency=medium
|
||||
|
||||
* Fixes for 2.1.0 release
|
||||
|
||||
-- Adolfo Gómez García <agomez@virtualcable.es> Tue, 19 Jan 2017 08:00:22 +0200
|
||||
|
||||
udsactor (2.0.0) stable; urgency=medium
|
||||
|
||||
* Upgrade for 2.0.0
|
||||
|
||||
-- Adolfo Gómez García <agomez@virtualcable.es> Tue, 01 Mar 2016 03:39:21 +0100
|
||||
|
||||
udsactor (1.9.1) stable; urgency=medium
|
||||
|
||||
* Upgrade for 1.9.1
|
||||
|
||||
-- Adolfo Gómez García <agomez@virtualcable.es> Tue, 01 Mar 2016 03:19:21 +0100
|
||||
|
||||
udsactor (1.9.0) stable; urgency=medium
|
||||
|
||||
* Upgrade for 1.9.0 (fixed package version)
|
||||
|
||||
-- Adolfo Gómez García <agomez@virtualcable.es> Tue, 05 May 2015 07:10:27 +0200
|
||||
|
||||
udsactor (1.7.5) stable; urgency=medium
|
||||
|
||||
* Upgrade for 1.7.5
|
||||
|
||||
-- Adolfo Gómez García <agomez@virtualcable.es> Thu, 23 Apr 2015 06:08:53 +0200
|
||||
|
||||
udsactor (1.7.0) stable; urgency=medium
|
||||
|
||||
* Initial release.
|
||||
|
||||
-- Adolfo Gómez García <agomez@virtualcable.es> Mon, 17 Nov 2014 05:32:41 +0100
|
@ -1 +0,0 @@
|
||||
9
|
@ -1,17 +0,0 @@
|
||||
Source: udsactor
|
||||
Section: admin
|
||||
Priority: optional
|
||||
Maintainer: Adolfo Gómez García <agomez@virtualcable.es>
|
||||
Build-Depends: debhelper (>= 7), po-debconf
|
||||
Standards-Version: 3.9.2
|
||||
Homepage: http://www.virtualcable.es
|
||||
|
||||
Package: udsactor
|
||||
Section: admin
|
||||
Priority: optional
|
||||
Architecture: all
|
||||
Depends: policykit-1(>=0.100), python3-requests (>=0.8.2), python3-pyqt4 (>=4.9), python3-six(>=1.1), python3 (>=3.4), libxss1, xscreensaver, ${misc:Depends}
|
||||
Recommends: python3-prctl(>=1.1.1)
|
||||
Description: Actor for Universal Desktop Services (UDS) Broker
|
||||
This package provides the required components to allow this machine to work on an environment managed by UDS Broker.
|
||||
|
@ -1,26 +0,0 @@
|
||||
Format-Specification: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?op=file&rev=135
|
||||
Name: udsactor
|
||||
Maintainer: Adolfo Gómez García
|
||||
Source: http://www.udsenterprise.com/
|
||||
|
||||
Copyright: 2014 Virtual Cable S.L.U.
|
||||
License: BSD-3-clause
|
||||
|
||||
License: GPL-2+
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
.
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
.
|
||||
On Debian systems, the full text of the GNU General Public
|
||||
License version 2 can be found in the file
|
||||
`/usr/share/common-licenses/GPL-2'.
|
@ -1 +0,0 @@
|
||||
readme.txt
|
@ -1,46 +0,0 @@
|
||||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
configure: configure-stamp
|
||||
configure-stamp:
|
||||
dh_testdir
|
||||
touch configure-stamp
|
||||
build: build-arch build-indep
|
||||
build-arch: build-stamp
|
||||
build-indep: build-stamp
|
||||
build-stamp: configure-stamp
|
||||
dh_testdir
|
||||
$(MAKE)
|
||||
touch $@
|
||||
clean:
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
rm -f build-stamp configure-stamp
|
||||
dh_clean
|
||||
install: build
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_prep
|
||||
dh_installdirs
|
||||
$(MAKE) DESTDIR=$(CURDIR)/debian/udsactor install-udsactor
|
||||
$(MAKE) DESTDIR=$(CURDIR)/debian/udsactor-xrdp install-udsactor-xrdp
|
||||
$(MAKE) DESTDIR=$(CURDIR)/debian/udsactor-nx install-udsactor-nx
|
||||
binary-arch: build install
|
||||
# emptyness
|
||||
binary-indep: build install
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_installchangelogs
|
||||
dh_installdocs
|
||||
dh_installdebconf
|
||||
dh_installinit --no-start
|
||||
dh_python2=python
|
||||
dh_compress
|
||||
dh_link
|
||||
dh_fixperms
|
||||
dh_installdeb
|
||||
dh_shlibdeps
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
binary: binary-indep
|
||||
.PHONY: build clean binary-indep binary install configure
|
@ -1 +0,0 @@
|
||||
3.0 (native)
|
@ -1,37 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
NXNODECFG=/usr/NX/etc/node.cfg
|
||||
|
||||
. /usr/share/debconf/confmodule
|
||||
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
configure)
|
||||
TMPFILE=$(mktemp /tmp/node.cfg.XXXXX)
|
||||
trap "rm -f $TMPFILE" 0
|
||||
cat $NXNODECFG | sed -e "s/.*udsnxst.*//; s/\(UserScriptAfterSessionStart *=.*\)/#\1/;s/\(UserScriptAfterSessionClose *=.*\)/#\1/" > $TMPFILE
|
||||
echo >> $TMPFILE
|
||||
echo "# Added by udsactor-nx (udsnxstart and udsnxstop)" >> $TMPFILE
|
||||
echo UserScriptAfterSessionStart = \"/usr/bin/udsnxstart\" >> $TMPFILE
|
||||
echo UserScriptAfterSessionClose = \"/usr/bin/udsnxstop\" >> $TMPFILE
|
||||
cp $TMPFILE $NXNODECFG
|
||||
invoke-rc.d nxserver restart
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
# Don't know why, but descriptors get "weird" when launched daemon, so we tell here to debconf to stop.
|
||||
# Solved not starting the service right now, defered to next reboot
|
||||
|
||||
|
||||
exit 0
|
@ -1,30 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
NXNODECFG=/usr/NX/etc/node.cfg
|
||||
|
||||
. /usr/share/debconf/confmodule
|
||||
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
purge)
|
||||
;;
|
||||
remove)
|
||||
if [ -f $NXNODECFG ]; then
|
||||
TMPFILE=$(mktemp /tmp/node.cfg.XXXXX)
|
||||
trap "rm -f $TMPFILE" 0
|
||||
cat $NXNODECFG | sed -e "s/.*udsnxst.*//" > $TMPFILE
|
||||
cp $TMPFILE $NXNODECFG
|
||||
invoke-rc.d nxserver restart
|
||||
fi
|
||||
;;
|
||||
upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postrm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
#DEBHELPER#
|
@ -1,39 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
SESMANFILE=/etc/pam.d/xrdp-sesman
|
||||
|
||||
. /usr/share/debconf/confmodule
|
||||
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
configure)
|
||||
trap "cp $SESMANFILE $SESMANFILE.uds.old" 0
|
||||
|
||||
TMPFILE=$(mktemp /tmp/sesman.XXXXX)
|
||||
trap "rm -f $TMPFILE" 0
|
||||
grep -v uds $SESMANFILE > $TMPFILE # Removes all UDS lines from sesman if they exists
|
||||
|
||||
echo >> $TMPFILE
|
||||
echo "# Added by udsactor-xrdp" >> $TMPFILE
|
||||
echo "session optional pam_exec.so /usr/bin/uds-sesman" >> $TMPFILE
|
||||
cp $TMPFILE $SESMANFILE
|
||||
trap "rm -f $TMPFILE" 0
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
# Don't know why, but descriptors get "weird" when launched daemon, so we tell here to debconf to stop.
|
||||
# Solved not starting the service right now, defered to next reboot
|
||||
|
||||
|
||||
exit 0
|
@ -1,30 +0,0 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
SESMANFILE=/etc/pam.d/xrdp-sesman
|
||||
|
||||
. /usr/share/debconf/confmodule
|
||||
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
purge)
|
||||
;;
|
||||
remove)
|
||||
if [ -f $SESMANFILE ]; then
|
||||
TMPFILE=$(mktemp /tmp/sesman.XXXXX)
|
||||
trap "rm -f $TMPFILE" 0
|
||||
grep -v uds $SESMANFILE > $TMPFILE # Removes all UDS lines from sesman if they exists
|
||||
cp $TMPFILE $SESMANFILE
|
||||
trap "rm -f $TMPFILE" 0
|
||||
fi
|
||||
;;
|
||||
upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postrm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
#DEBHELPER#
|
@ -1,45 +0,0 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
. /usr/share/debconf/confmodule
|
||||
db_version 2.0
|
||||
|
||||
# This conf script is capable of backing up
|
||||
db_capb backup
|
||||
|
||||
if [ -f /etc/udsactor/udsactor.cfg ] && [ "$1" != "reconfigure" ]; then
|
||||
echo "/etc/udsactor/udsactor.cfg already exists, leaving untouched."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
STATE=1
|
||||
while [ "$STATE" != 0 -a "$STATE" != 4 ]; do
|
||||
case "$STATE" in
|
||||
1)
|
||||
db_input high udsactor/host || true
|
||||
;;
|
||||
2)
|
||||
db_input high udsactor/secure || true
|
||||
;;
|
||||
3)
|
||||
db_input high udsactor/masterKey || true
|
||||
;;
|
||||
esac
|
||||
|
||||
if db_go; then
|
||||
STATE=$(($STATE + 1))
|
||||
else
|
||||
STATE=$(($STATE - 1))
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
# If "cancelled", exit
|
||||
if [ "$STATE" = 0 ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# If using reconfigure, and already exists an configuration file, move it to a backup
|
||||
if [ -f /etc/udsactor/udsactor.cfg ] && [ "$1" = "reconfigure" ]; then
|
||||
echo "/etc/udsactor.cfg backup to /etc/udsactor.cfg.back"
|
||||
mv /etc/udsactor/udsactor.cfg /etc/udsactor/udsactor.cfg.back
|
||||
fi
|
@ -1,23 +0,0 @@
|
||||
#!/bin/sh -e
|
||||
### BEGIN INIT INFO
|
||||
# Provides: udsactor
|
||||
# Required-Start: $local_fs $remote_fs $network $syslog $named
|
||||
# Required-Stop: $local_fs $remote_fs $network $syslog $named
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: UDS Actor
|
||||
### END INIT INFO
|
||||
#
|
||||
|
||||
# . /lib/lsb/init-functions
|
||||
|
||||
case "$1" in
|
||||
start|stop|restart)
|
||||
/usr/bin/udsactor $1
|
||||
;;
|
||||
force-reload)
|
||||
/usr/bin/udsactor restart
|
||||
;;
|
||||
*) echo "Usage: $0 {start|stop|restart|force-reload}" >&2; exit 1 ;;
|
||||
esac
|
||||
|
@ -1,2 +0,0 @@
|
||||
/usr/share/UDSActor/UDSActorConfig.py /usr/sbin/UDSActorConfig
|
||||
/usr/share/UDSActor/UDSActorUser.py /usr/bin/UDSActorTool
|
@ -1,54 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /usr/share/debconf/confmodule
|
||||
|
||||
set -e
|
||||
case "$1" in
|
||||
configure)
|
||||
/usr/bin/python3 -m compileall /usr/share/UDSActor > /dev/nul 2>&1
|
||||
# If new "fresh" install or if configuration file has disappeared...
|
||||
if [ "$2" = "" ] || [ ! -f /etc/udsactor/udsactor.cfg ]; then
|
||||
db_get udsactor/host
|
||||
host=$RET
|
||||
db_get udsactor/secure
|
||||
ssl=$RET
|
||||
if [ "$ssl" = "true" ]; then
|
||||
ssl=True;
|
||||
else
|
||||
ssl=False;
|
||||
fi
|
||||
db_get udsactor/masterKey
|
||||
masterKey=$RET
|
||||
|
||||
# If already has a config file there
|
||||
if [ -f /etc/udsactor/udsactor.cfg ]; then
|
||||
cp /etc/udsactor/udsactor.cfg /etc/udsactor/udsactor.cfg.dpkg-old
|
||||
fi
|
||||
|
||||
echo "[uds]" > /etc/udsactor/udsactor.cfg
|
||||
echo "host = $host" >> /etc/udsactor/udsactor.cfg
|
||||
echo "logLevel = 30000" >> /etc/udsactor/udsactor.cfg
|
||||
echo "ssl = $ssl" >> /etc/udsactor/udsactor.cfg
|
||||
echo "masterKey = $masterKey" >> /etc/udsactor/udsactor.cfg
|
||||
|
||||
fi
|
||||
|
||||
# Fix perms so only root can access "masterKey"
|
||||
chmod 0700 /etc/udsactor
|
||||
chmod 0600 /etc/udsactor/udsactor.cfg
|
||||
chown root:root /etc/udsactor
|
||||
chown root:root /etc/udsactor/udsactor.cfg
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
@ -1,14 +0,0 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
. /usr/share/debconf/confmodule
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$1" = "purge" ] ; then
|
||||
if [ -f /etc/udsactor/udsactor.cfg ]; then
|
||||
mv /etc/udsactor/udsactor.cfg /etc/udsactor/udsactor.cfg.dpkg-backup
|
||||
# Remove .pyc leaved behind
|
||||
rm -rf /usr/share/UDSActor || true > /dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
|
@ -1 +0,0 @@
|
||||
#! /bin/bash -e
|
@ -1,20 +0,0 @@
|
||||
Template: udsactor/host
|
||||
Type: string
|
||||
Default:
|
||||
Description: UDS Server address:
|
||||
The actor needs the address of the server in order to communicate with it.
|
||||
Provide here full address (or i) of the UDS server
|
||||
|
||||
Template: udsactor/secure
|
||||
Type: boolean
|
||||
Default: true
|
||||
Description: Use secure (https) connection to communicate with UDS server?
|
||||
If selected, the communication will be done using https.
|
||||
If not selected, the communication will be done using http
|
||||
|
||||
Template: udsactor/masterKey
|
||||
Type: string
|
||||
Default:
|
||||
Description: Master Key:
|
||||
This key is available on UDS Administration interface.
|
||||
Look for it under configuration, on Security tab.
|
@ -1,12 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Name=UDS Actor Tool
|
||||
Comment=UDS Actor Userspace tools
|
||||
Exec=/usr/bin/UDSActorTool-startup
|
||||
Icon=/usr/share/UDSActor/img/uds.png
|
||||
Terminal=false
|
||||
Type=Application
|
||||
NoDisplay=true
|
||||
X-KDE-autostart-after=panel
|
||||
X-KDE-StartupNotify=false
|
||||
X-DBUS-StartupType=None
|
||||
X-KDE-UniqueApplet=false
|
@ -1,11 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Name=UDS Actor Configuration
|
||||
Version=1.0
|
||||
Exec=/usr/sbin/UDSActorConfig-pkexec
|
||||
Comment=UDS Actor Configuration Application. (Must be executed as root)
|
||||
Icon=/usr/share/UDSActor/img/uds.png
|
||||
Type=Application
|
||||
Terminal=false
|
||||
StartupNotify=true
|
||||
Encoding=UTF-8
|
||||
Categories=Settings;System;
|
@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE policyconfig PUBLIC
|
||||
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
|
||||
|
||||
<policyconfig>
|
||||
|
||||
<action id="org.freedesktop.policykit.pkexec.run-UDSActorConfig">
|
||||
<description>Run UDS Actor Configuration Program</description>
|
||||
<message>Authentication is required to run UDS Actor Configuration</message>
|
||||
<defaults>
|
||||
<allow_any>no</allow_any>
|
||||
<allow_inactive>no</allow_inactive>
|
||||
<allow_active>auth_admin_keep</allow_active>
|
||||
</defaults>
|
||||
<annotate key="org.freedesktop.policykit.exec.path">/usr/sbin/UDSActorConfig</annotate>
|
||||
<annotate key="org.freedesktop.policykit.exec.allow_gui">TRUE</annotate>
|
||||
</action>
|
||||
|
||||
</policyconfig>
|
@ -1,3 +0,0 @@
|
||||
UDSActor is the client actor needed to get machines managed by UDS Broker.
|
||||
|
||||
Please, visit http://www.udsenterprise.com for more information
|
@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
# pkexec env DISPLAY=$DISPLAY QT_X11_NO_MITSHM=1 "/usr/sbin/UDSActorConfig" "$@"
|
||||
pkexec "/usr/sbin/UDSActorConfig" "$@"
|
@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Simple hack to wait for systray to be present
|
||||
# Exec tool if not already runned by session manager
|
||||
ps -ef | grep "$USER" | grep -v grep | grep -v UDSActorTool-startup | grep 'UDSActorTool' -q
|
||||
# If not already running
|
||||
if [ $? -eq 1 ]; then
|
||||
sleep 5
|
||||
exec /usr/bin/UDSActorTool
|
||||
fi
|
@ -1,13 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
env > /tmp/env.txt
|
||||
|
||||
if [ "$PAM_TYPE" = "open_session" ]; then
|
||||
nohup /usr/bin/udsactor login $PAM_USER &
|
||||
# Wait in backgroud to TTY to close (close_session is not being invoked right now)
|
||||
nohup /usr/bin/uds-wait-session &
|
||||
elif [ "$PAM_TYPE" = "close_session" ]; then
|
||||
nohup /usr/bin/udsactor logout $PAM_USER &
|
||||
fi
|
||||
|
||||
return 0
|
@ -1,12 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
while :
|
||||
do
|
||||
sleep 5 # Wait 5 seconds between checks
|
||||
found=`ps -f -u$PAM_USER | grep -v grep | grep -v uds-wait-session | grep "$PAM_TTY" | wc -l`
|
||||
|
||||
if [ "$found" = "0" ]; then
|
||||
/usr/bin/udsactor logout $PAM_USER
|
||||
exit 0
|
||||
fi
|
||||
done
|
@ -1,6 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
FOLDER=/usr/share/UDSActor
|
||||
|
||||
cd $FOLDER
|
||||
exec python3 -m udsactor.linux.UDSActorService $@
|
@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
exec /usr/bin/udsactor login $2 &
|
@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
exec /usr/bin/udsactor logout $2 &
|
@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
/usr/bin/udsactor login "$USER"
|
||||
$@
|
||||
/usr/bin/udsactor logout "$USER"
|
@ -1,70 +0,0 @@
|
||||
%define _topdir %(echo $PWD)/rpm
|
||||
%define name udsactor
|
||||
%define version 0.0.0
|
||||
%define release 1
|
||||
%define buildroot %{_topdir}/%{name}-%{version}-%{release}-root
|
||||
|
||||
BuildRoot: %{buildroot}
|
||||
Name: %{name}
|
||||
Version: %{version}
|
||||
Release: %{release}
|
||||
Summary: Actor for Universal Desktop Services (UDS) Broker
|
||||
License: BSD3
|
||||
Group: Admin
|
||||
Requires: python-six python-requests PyQt4 libXScrnSaver
|
||||
Vendor: Virtual Cable S.L.U.
|
||||
URL: http://www.udsenterprise.com
|
||||
Provides: udsactor
|
||||
|
||||
%define _rpmdir ../
|
||||
%define _rpmfilename %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm
|
||||
|
||||
|
||||
%install
|
||||
curdir=`pwd`
|
||||
cd ../..
|
||||
make DESTDIR=$RPM_BUILD_ROOT DISTRO=rh install-udsactor
|
||||
cd $curdir
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
curdir=`pwd`
|
||||
cd ../..
|
||||
make DESTDIR=$RPM_BUILD_ROOT DISTRO=rh clean
|
||||
cd $curdir
|
||||
|
||||
|
||||
%post
|
||||
systemctl enable udsactor.service > /dev/null 2>&1
|
||||
|
||||
%preun
|
||||
systemctl disable udsactor.service > /dev/null 2>&1
|
||||
systemctl stop udsactor.service > /dev/null 2>&1
|
||||
|
||||
%postun
|
||||
# $1 == 0 on uninstall, == 1 on upgrade for preun and postun (just a reminder for me... :) )
|
||||
if [ $1 -eq 0 ]; then
|
||||
rm -rf /etc/udsactor
|
||||
rm /var/log/udsactor.log
|
||||
fi
|
||||
# And, posibly, the .pyc leaved behind on /usr/share/UDSActor
|
||||
rm -rf /usr/share/UDSActor > /dev/null 2>&1
|
||||
|
||||
%description
|
||||
This package provides the required components to allow this machine to work on an environment managed by UDS Broker.
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
/etc/udsactor
|
||||
/etc/xdg/autostart/UDSActorTool.desktop
|
||||
/etc/init.d/udsactor
|
||||
/usr/bin/UDSActorTool-startup
|
||||
/usr/bin/udsactor
|
||||
/usr/bin/udsvapp
|
||||
/usr/bin/UDSActorTool
|
||||
/usr/sbin/UDSActorConfig
|
||||
/usr/sbin/UDSActorConfig-pkexec
|
||||
/usr/share/UDSActor/*
|
||||
/usr/share/applications/UDS_Actor_Configuration.desktop
|
||||
/usr/share/autostart/UDSActorTool.desktop
|
||||
/usr/share/polkit-1/actions/org.openuds.pkexec.UDSActorConfig.policy
|
6
legacy_actors/src/.gitignore
vendored
6
legacy_actors/src/.gitignore
vendored
@ -1,6 +0,0 @@
|
||||
build
|
||||
dist
|
||||
*.spec
|
||||
.idea
|
||||
*_enterprise*
|
||||
/samples/
|
@ -1,5 +0,0 @@
|
||||
<RCC>
|
||||
<qresource prefix="images">
|
||||
<file>img/uds.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="UDSActorConfig"
|
||||
version="1.6.0.0"
|
||||
processorArchitecture="x86"
|
||||
/>
|
||||
<description>Description</description>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
@ -1,119 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import sys
|
||||
import os
|
||||
from PyQt4 import QtCore, QtGui
|
||||
import six
|
||||
|
||||
from udsactor import store
|
||||
from udsactor import REST
|
||||
from udsactor import utils
|
||||
from udsactor.log import logger
|
||||
|
||||
from setup_dialog_ui import Ui_UdsActorSetupDialog
|
||||
|
||||
|
||||
class UDSConfigDialog(QtGui.QDialog):
|
||||
|
||||
def __init__(self, data, parent=None):
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.ui = Ui_UdsActorSetupDialog()
|
||||
self.ui.setupUi(self)
|
||||
if data is not None:
|
||||
self.ui.host.setText(data.get('host', ''))
|
||||
self.ui.masterKey.setText(data.get('masterKey', ''))
|
||||
self.ui.useSSl.setCurrentIndex(1 if data.get('ssl', False) is True else 0)
|
||||
self.ui.logLevelComboBox.setCurrentIndex(int(data.get('logLevel', '10000')) / 10000 - 1)
|
||||
|
||||
def _getCfg(self):
|
||||
return {
|
||||
'host': six.text_type(self.ui.host.text()),
|
||||
'masterKey': six.text_type(self.ui.masterKey.text()),
|
||||
'ssl': self.ui.useSSl.currentIndex() == 1,
|
||||
'logLevel': (self.ui.logLevelComboBox.currentIndex() + 1) * 10000
|
||||
}
|
||||
|
||||
def textChanged(self):
|
||||
enableButtons = self.ui.host.text() != '' and self.ui.masterKey.text() != ''
|
||||
self.ui.testButton.setEnabled(enableButtons)
|
||||
self.ui.saveButton.setEnabled(enableButtons)
|
||||
|
||||
def cancelAndDiscard(self):
|
||||
logger.debug('Cancelling changes')
|
||||
self.close()
|
||||
|
||||
def testParameters(self):
|
||||
logger.debug('Testing connection')
|
||||
try:
|
||||
cfg = self._getCfg()
|
||||
api = REST.Api(
|
||||
cfg['host'], cfg['masterKey'], cfg['ssl'])
|
||||
api.test()
|
||||
QtGui.QMessageBox.information(
|
||||
self, 'Test Passed', 'The test was executed successfully', QtGui.QMessageBox.Ok)
|
||||
logger.info('Test was passed successfully')
|
||||
except Exception as e:
|
||||
logger.info('Test error: {}'.format(utils.exceptionToMessage(e)))
|
||||
QtGui.QMessageBox.critical(self, 'Test Error', utils.exceptionToMessage(e), QtGui.QMessageBox.Ok)
|
||||
|
||||
def acceptAndSave(self):
|
||||
cfg = self._getCfg()
|
||||
store.writeConfig(cfg)
|
||||
self.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# If to be run as "sudo" on linux, we will need this to avoid problems
|
||||
if 'linux' in sys.platform:
|
||||
os.environ['QT_X11_NO_MITSHM'] = '1'
|
||||
|
||||
app = QtGui.QApplication(sys.argv)
|
||||
|
||||
if store.checkPermissions() is False:
|
||||
QtGui.QMessageBox.critical(None, 'Notice', 'This Program must be executed as administrator', QtGui.QMessageBox.Ok)
|
||||
sys.exit(1)
|
||||
|
||||
# Read configuration
|
||||
cfg = store.readConfig()
|
||||
|
||||
if cfg is not None:
|
||||
logger.setLevel(int(cfg.get('logLevel', 20000)))
|
||||
else:
|
||||
logger.setLevel(20000)
|
||||
|
||||
myapp = UDSConfigDialog(cfg)
|
||||
myapp.show()
|
||||
sys.exit(app.exec_())
|
@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="UDSActorService"
|
||||
version="1.6.0.0"
|
||||
processorArchitecture="x86"
|
||||
/>
|
||||
<description>Description</description>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
@ -1,372 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import sys
|
||||
from PyQt4 import QtGui # @UnresolvedImport
|
||||
from PyQt4 import QtCore # @UnresolvedImport
|
||||
import pickle
|
||||
import time
|
||||
import datetime
|
||||
import signal
|
||||
import six
|
||||
from udsactor import ipc
|
||||
from udsactor import utils
|
||||
from udsactor.log import logger
|
||||
from udsactor.service import IPC_PORT
|
||||
from udsactor import operations
|
||||
from about_dialog_ui import Ui_UDSAboutDialog
|
||||
from message_dialog_ui import Ui_UDSMessageDialog
|
||||
from udsactor.scriptThread import ScriptExecutorThread
|
||||
from udsactor import VERSION
|
||||
|
||||
trayIcon = None
|
||||
|
||||
doLogoff = False
|
||||
|
||||
TIMER_TIMEOUT = 5 # In seconds
|
||||
|
||||
|
||||
def sigTerm(sigNo, stackFrame):
|
||||
if trayIcon:
|
||||
trayIcon.quit(extra=" (by sigterm)")
|
||||
|
||||
|
||||
# About dialog
|
||||
class UDSAboutDialog(QtGui.QDialog):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.ui = Ui_UDSAboutDialog()
|
||||
self.ui.setupUi(self)
|
||||
self.ui.VersionLabel.setText("Version " + VERSION)
|
||||
|
||||
def closeDialog(self):
|
||||
self.hide()
|
||||
|
||||
|
||||
class UDSMessageDialog(QtGui.QDialog):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.ui = Ui_UDSMessageDialog()
|
||||
self.ui.setupUi(self)
|
||||
|
||||
def displayMessage(self, message):
|
||||
self.ui.message.setText(message)
|
||||
self.show()
|
||||
|
||||
def closeDialog(self):
|
||||
self.hide()
|
||||
|
||||
|
||||
class MessagesProcessor(QtCore.QThread):
|
||||
|
||||
logoff = QtCore.pyqtSignal(name='logoff')
|
||||
displayMessage = QtCore.pyqtSignal(six.text_type, name='displayMessage')
|
||||
script = QtCore.pyqtSignal(six.text_type, name='script')
|
||||
exit = QtCore.pyqtSignal(name='exit')
|
||||
information = QtCore.pyqtSignal(dict, name='information')
|
||||
|
||||
def __init__(self):
|
||||
super(MessagesProcessor, self).__init__()
|
||||
# Retries connection for a while
|
||||
for _ in range(10):
|
||||
try:
|
||||
self.ipc = ipc.ClientIPC(IPC_PORT)
|
||||
self.ipc.start()
|
||||
break
|
||||
except Exception:
|
||||
logger.debug('IPC Server is not reachable')
|
||||
self.ipc = None
|
||||
time.sleep(2)
|
||||
|
||||
self.running = False
|
||||
|
||||
def stop(self):
|
||||
self.running = False
|
||||
if self.ipc:
|
||||
self.ipc.stop()
|
||||
|
||||
def isAlive(self):
|
||||
return self.ipc is not None
|
||||
|
||||
def requestInformation(self):
|
||||
if self.ipc is not None:
|
||||
info = self.ipc.requestInformation()
|
||||
logger.debug('Request information: {}'.format(info))
|
||||
|
||||
def sendLogin(self, userName):
|
||||
if self.ipc:
|
||||
self.ipc.sendLogin(userName)
|
||||
|
||||
def sendLogout(self, userName):
|
||||
if self.ipc:
|
||||
self.ipc.sendLogout(userName)
|
||||
|
||||
def run(self):
|
||||
if self.ipc is None:
|
||||
return
|
||||
self.running = True
|
||||
|
||||
# Wait a bit so we ensure IPC thread is running...
|
||||
time.sleep(2)
|
||||
|
||||
while self.running and self.ipc.running:
|
||||
try:
|
||||
msg = self.ipc.getMessage()
|
||||
if msg is None:
|
||||
break
|
||||
msgId, data = msg
|
||||
logger.debug('Got Message on User Space: {}:{}'.format(msgId, data))
|
||||
if msgId == ipc.MSG_MESSAGE:
|
||||
self.displayMessage.emit(data)
|
||||
elif msgId == ipc.MSG_LOGOFF:
|
||||
self.logoff.emit()
|
||||
elif msgId == ipc.MSG_SCRIPT:
|
||||
self.script.emit(data)
|
||||
elif msgId == ipc.MSG_INFORMATION:
|
||||
self.information.emit(pickle.loads(data))
|
||||
except Exception as e:
|
||||
try:
|
||||
logger.error('Got error on IPC thread {}'.format(utils.exceptionToMessage(e)))
|
||||
except:
|
||||
logger.error('Got error on IPC thread (an unicode error??)')
|
||||
|
||||
if self.ipc.running is False and self.running is True:
|
||||
logger.warn('Lost connection with Service, closing program')
|
||||
|
||||
self.exit.emit()
|
||||
|
||||
|
||||
class UDSSystemTray(QtGui.QSystemTrayIcon):
|
||||
|
||||
def __init__(self, app_, parent=None):
|
||||
self.app = app_
|
||||
|
||||
# style = app.style()
|
||||
# icon = QtGui.QIcon(style.standardPixmap(QtGui.QStyle.SP_ComputerIcon))
|
||||
icon = QtGui.QIcon(':/images/img/uds.png')
|
||||
|
||||
QtGui.QSystemTrayIcon.__init__(self, icon, parent)
|
||||
self.menu = QtGui.QMenu(parent)
|
||||
exitAction = self.menu.addAction("About")
|
||||
exitAction.triggered.connect(self.about)
|
||||
self.setContextMenu(self.menu)
|
||||
self.ipc = MessagesProcessor()
|
||||
self.sessionStart = datetime.datetime.now()
|
||||
self.maxIdleTime = None
|
||||
self.showIdleWarn = True
|
||||
self.maxSessionTime = None
|
||||
self.showMaxSessionWarn = True
|
||||
self.timer = QtCore.QTimer()
|
||||
self.timer.timeout.connect(self.checkTimers)
|
||||
|
||||
if self.ipc.isAlive() is False:
|
||||
raise Exception('No connection to service, exiting.')
|
||||
|
||||
self.stopped = False
|
||||
|
||||
self.ipc.displayMessage.connect(self.displayMessage)
|
||||
self.ipc.exit.connect(self.quit)
|
||||
self.ipc.script.connect(self.executeScript)
|
||||
self.ipc.logoff.connect(self.logoff)
|
||||
self.ipc.information.connect(self.information)
|
||||
|
||||
# Pre generate a request for information (general parameters) to daemon/service
|
||||
self.ipc.requestInformation()
|
||||
|
||||
self.aboutDlg = UDSAboutDialog()
|
||||
self.msgDlg = UDSMessageDialog()
|
||||
|
||||
self.counter = 0
|
||||
|
||||
self.resetTimervars()
|
||||
self.timer.start(TIMER_TIMEOUT * 1000) # Launch idle checking every 5 seconds
|
||||
|
||||
self.ipc.start()
|
||||
# If this is running, it's because he have logged in
|
||||
self.ipc.sendLogin(operations.getCurrentUser())
|
||||
|
||||
def resetTimervars(self):
|
||||
self.lastTimerTime = datetime.datetime.now()
|
||||
self.graceTimerShots = 6 # Start counting for idle after 30 seconds after login, got on windows some "instant" logout because of idle timer not being reset??
|
||||
|
||||
def checkTimers(self):
|
||||
# Check clock readjustment
|
||||
# This is executed
|
||||
elapsed_seconds = (datetime.datetime.now() - self.lastTimerTime).total_seconds()
|
||||
if elapsed_seconds > TIMER_TIMEOUT * 4 or elapsed_seconds < 0:
|
||||
# Clock has changed a lot, reset session variables, idle timer, etc..
|
||||
self.resetTimervars()
|
||||
return
|
||||
|
||||
self.lastTimerTime = datetime.datetime.now()
|
||||
|
||||
self.checkIdle()
|
||||
self.checkMaxSession()
|
||||
|
||||
def checkMaxSession(self):
|
||||
if self.maxSessionTime is None or self.maxSessionTime == 0:
|
||||
logger.debug('Returning because maxSessionTime is zero')
|
||||
return
|
||||
|
||||
remainingTime = self.maxSessionTime - (datetime.datetime.now() - self.sessionStart).total_seconds()
|
||||
logger.debug('Remaining time: {}'.format(remainingTime))
|
||||
|
||||
if self.showMaxSessionWarn is True and remainingTime < 300: # With five minutes, show a warning message
|
||||
self.showMaxSessionWarn = False
|
||||
self.msgDlg.displayMessage('Your session will expire in less that 5 minutes. Please, save your work and disconnect.')
|
||||
return
|
||||
|
||||
if remainingTime <= 0:
|
||||
logger.debug('Remaining time is less than cero, exiting')
|
||||
self.quit(extra=" (max session time {} {})".format(self.maxSessionTime, self.sessionStart))
|
||||
|
||||
def checkIdle(self):
|
||||
if self.maxIdleTime is None: # No idle check
|
||||
return
|
||||
|
||||
if self.graceTimerShots > 0:
|
||||
self.graceTimerShots -= 1
|
||||
return
|
||||
|
||||
idleTime = operations.getIdleDuration()
|
||||
remainingTime = self.maxIdleTime - idleTime
|
||||
|
||||
if remainingTime > 120: # Reset show Warning dialog if we have more than 5 minutes left
|
||||
self.showIdleWarn = True
|
||||
|
||||
logger.debug('User has been idle for: {}'.format(idleTime))
|
||||
|
||||
if self.showIdleWarn is True and remainingTime < 120: # With two minutes, show a warning message
|
||||
self.showIdleWarn = False
|
||||
self.msgDlg.displayMessage("You have been idle for too long. The session will end if you don't resume operations")
|
||||
|
||||
if remainingTime <= 0:
|
||||
logger.info('User has been idle for too long, notifying Broker that service can be reclaimed')
|
||||
self.quit(logoff=True, extra=' (idle: {} vs {})'.format(idleTime, self.maxIdleTime))
|
||||
|
||||
def displayMessage(self, message):
|
||||
logger.debug('Displaying message')
|
||||
self.msgDlg.displayMessage(message)
|
||||
|
||||
def executeScript(self, script):
|
||||
logger.debug('Executing script')
|
||||
th = ScriptExecutorThread(script)
|
||||
th.start()
|
||||
|
||||
def logoff(self):
|
||||
self.counter += 1
|
||||
# print("Logofff --", self.counter)
|
||||
|
||||
def information(self, info):
|
||||
'''
|
||||
Invoked when received information from service
|
||||
'''
|
||||
logger.info('Got information message: {}'.format(info))
|
||||
if 'idle' in info:
|
||||
idle = int(info['idle'])
|
||||
operations.initIdleDuration(idle)
|
||||
self.maxIdleTime = idle
|
||||
logger.debug('Set screensaver launching to {}'.format(idle))
|
||||
else:
|
||||
self.maxIdleTime = None
|
||||
|
||||
if 'maxSession' in info:
|
||||
maxSession = int(info['maxSession'])
|
||||
# operations.initMaxSession(maxSession)
|
||||
self.maxSessionTime = maxSession
|
||||
logger.debug('Set maxsession to {}'.format(maxSession))
|
||||
|
||||
def about(self):
|
||||
self.aboutDlg.exec_()
|
||||
|
||||
def quit(self, logoff=False, extra=''):
|
||||
global doLogoff # pylint: disable=global-statement
|
||||
logger.debug('Quit invoked')
|
||||
if not self.stopped:
|
||||
self.stopped = True
|
||||
try:
|
||||
# If we close Client, send Logoff to Broker
|
||||
# if sys.platform != 'win32':
|
||||
self.ipc.sendLogout(operations.getCurrentUser() + extra)
|
||||
self.timer.stop()
|
||||
self.ipc.stop()
|
||||
except Exception:
|
||||
# May we have lost connection with server, simply exit in that case
|
||||
pass
|
||||
|
||||
doLogoff = logoff
|
||||
|
||||
self.app.quit()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = QtGui.QApplication(sys.argv)
|
||||
|
||||
# if not QtGui.QSystemTrayIcon.isSystemTrayAvailable():
|
||||
# # QtGui.QMessageBox.critical(None, "Systray", "I couldn't detect any system tray on this system.")
|
||||
# sys.exit(1)
|
||||
|
||||
# This is important so our app won't close on message windows
|
||||
QtGui.QApplication.setQuitOnLastWindowClosed(False)
|
||||
|
||||
try:
|
||||
trayIcon = UDSSystemTray(app)
|
||||
except Exception:
|
||||
logger.error('UDS Service is not running, or it can\'t contact with UDS Server. User Tools stopped')
|
||||
sys.exit(1)
|
||||
|
||||
# Sets a default idle duration, but will not be used unless idle is notified from server
|
||||
operations.initIdleDuration(3600 * 16)
|
||||
|
||||
trayIcon.show()
|
||||
|
||||
# Catch kill and logout user :)
|
||||
signal.signal(signal.SIGTERM, sigTerm)
|
||||
|
||||
# app.aboutToQuit.connect()
|
||||
res = app.exec_()
|
||||
|
||||
logger.debug('Exiting')
|
||||
trayIcon.quit(logoff=doLogoff) # Pass existing doLogoff
|
||||
|
||||
if doLogoff:
|
||||
try:
|
||||
time.sleep(1)
|
||||
operations.loggoff() # Invoke log off
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
sys.exit(res)
|
@ -1,203 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Resource object code
|
||||
#
|
||||
# Created: Mon Apr 27 22:05:02 2015
|
||||
# by: The Resource Compiler for PyQt (Qt v4.8.6)
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore
|
||||
|
||||
qt_resource_data = b"\
|
||||
\x00\x00\x09\xd1\
|
||||
\x89\
|
||||
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
|
||||
\x00\x00\x30\x00\x00\x00\x30\x08\x06\x00\x00\x00\x57\x02\xf9\x87\
|
||||
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
|
||||
\xa7\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\
|
||||
\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07\x74\x49\x4d\x45\x07\
|
||||
\xdf\x04\x1b\x12\x2a\x1c\x39\xec\x95\x7d\x00\x00\x09\x5e\x49\x44\
|
||||
\x41\x54\x68\xde\xd5\x9a\x7b\x8c\x54\xd5\x1d\xc7\x3f\xbf\xfb\x9a\
|
||||
\x99\x65\x5f\xc8\x63\x41\x51\x40\x40\xac\xd1\x20\xd1\xc5\x68\x40\
|
||||
\x51\xac\x6b\xb5\xe0\xa3\xb1\x94\xa8\x58\x6b\x2a\xad\xa6\x91\xc6\
|
||||
\xd8\x54\xa5\x16\x9b\xf1\xd1\x2a\xa9\x68\x6b\x35\xd1\x1a\x27\xb6\
|
||||
\x6b\xb5\xad\xb5\x69\x8b\x4b\x5c\xaa\x28\x0a\x2c\x2f\x95\x5d\x1e\
|
||||
\x8b\x40\x61\xdd\x65\x60\xd8\xf7\xee\x9d\xb9\xaf\xd3\x3f\x76\x06\
|
||||
\x76\x61\x76\x65\x67\xc6\x3f\xfc\x25\x37\x33\x39\xf7\xce\xf9\x9d\
|
||||
\xef\xf9\x9e\xdf\x73\xae\x28\xa5\xf8\x3a\x8b\x51\xc8\xc9\x6a\xea\
|
||||
\x2a\x8a\x95\xa2\xa8\xb4\x54\xc2\xe5\x65\x9a\x15\xb6\x24\xec\x78\
|
||||
\x4a\xab\x6f\x70\xb5\xc6\x3d\x2e\x4d\xcd\x01\x89\xa3\x81\x4a\x24\
|
||||
\x7c\x3f\xbd\x6f\x3d\x40\x2b\xd0\x59\x5b\x6d\xe7\xb4\x93\x32\x1c\
|
||||
\x06\x6a\xea\x2a\x42\xc0\x4c\xe0\x7c\xe0\x1c\xe0\x6c\xe0\x2c\x60\
|
||||
\x14\x10\x12\x41\xb7\x2c\xd1\x5a\x0e\xf9\xda\x8e\x9d\xae\x1c\x68\
|
||||
\xf2\xb4\x44\x22\x10\xcf\x03\xa5\x14\x41\x00\x4a\x81\x52\x64\x94\
|
||||
\x06\x80\x97\xbe\x6c\xe0\x20\x50\x0f\x6c\x04\x56\xd7\x56\xdb\xf1\
|
||||
\x9c\x01\xd4\xd4\x55\x14\xa7\x17\x76\x05\x70\x3d\x70\x25\x30\x66\
|
||||
\xa8\xc9\xbe\x68\xf6\x59\xfd\x6e\x92\x2f\x9a\x5d\x74\x5d\x10\xcd\
|
||||
\x02\x31\x40\x04\x85\x96\x7e\x4a\x21\x4a\x01\x01\x22\x0a\x51\x6e\
|
||||
\x7a\xfd\x00\x72\xc2\x27\xfb\x81\x95\xc0\x9b\x40\x4b\x6d\xb5\x1d\
|
||||
\x7c\x29\x80\x9a\xba\x8a\x31\xc0\xf7\x81\xf9\xc0\xec\xfe\xb3\x0d\
|
||||
\xba\x0b\x02\x07\x9b\x7c\x5e\x7f\xa3\x87\xc0\x4b\x62\x5b\x33\xe8\
|
||||
\xd4\x66\x91\xd4\x26\xe3\x4a\x39\x81\x84\x51\x98\x7d\x53\x29\x1f\
|
||||
\x4d\x7c\xcc\xe2\x22\x4c\xd3\x47\xf7\x5b\x31\xbc\x38\xa6\xdb\x84\
|
||||
\xe5\xee\x23\xe4\xec\xc2\x70\x0f\xa1\x44\x50\x62\x65\xd4\xb7\x01\
|
||||
\x2f\x03\xbf\xae\xad\xb6\x13\x83\x02\xa8\xa9\xab\xb8\x00\xf8\x37\
|
||||
\x70\xe6\x70\xce\xa1\xae\xc3\xaa\xd5\x49\x36\x6f\x4e\xd2\x3c\xe2\
|
||||
\x61\xda\x8c\x2b\xf0\x89\x00\x1a\x30\x70\x83\xc4\xb0\x30\x47\x4f\
|
||||
\x40\x8c\xd0\x80\xbd\x11\xe5\x20\x2a\x89\xa6\x6c\x42\xce\x5e\xca\
|
||||
\x3b\xfe\x42\x79\x47\x0c\x94\x8f\x12\x33\xf3\xd8\x27\xc0\xdc\xda\
|
||||
\x6a\xbb\x3d\x33\x90\xe1\x95\x35\x5b\xc7\x45\x80\x2d\xc3\x5d\x3c\
|
||||
\xf4\x9d\xeb\x33\x4e\x17\x12\xc6\x0d\x24\x8c\xaa\xf4\xe2\x33\x47\
|
||||
\x5c\x1d\xbb\xc4\x0c\x61\x8d\x9d\x88\x18\x56\x7a\x2c\x38\x76\x29\
|
||||
\x31\x08\xb4\x62\x3c\x7d\x0c\x3d\x91\x4b\x69\x1a\xff\x7b\x1a\xce\
|
||||
\x69\xa1\xbd\xfc\x8e\x34\x13\x0a\x60\x06\xf0\x5e\x7f\xdd\xc7\x00\
|
||||
\xb4\x75\xf8\x4b\x72\xf5\x4a\x41\x00\xe7\x4e\x33\x99\x32\x7d\x2c\
|
||||
\x0a\x3d\x2b\x42\x2d\x54\x84\x35\x76\x22\xe8\xa7\xa2\x22\x40\x54\
|
||||
\x0a\x25\x16\x4d\xe3\x5f\xa4\x65\xdc\x4a\xe4\x38\x9b\x33\xe6\x2d\
|
||||
\x8a\xac\x38\x09\x40\xed\x47\x5d\xd3\x74\x4d\x72\x76\xa1\xba\xa1\
|
||||
\x71\xc7\xd5\xef\x30\xa6\xf8\xf0\xc9\x36\x62\x58\x18\xa7\x9d\x0e\
|
||||
\xa2\xf5\xd1\x75\xea\xdc\x22\xca\xa6\xad\x6c\x21\x2d\xe3\x56\xa0\
|
||||
\x05\xa9\xcc\x8d\x5b\xe7\x2d\x8a\x9c\x3e\x90\x81\x4e\xdf\xde\x52\
|
||||
\xdf\x8b\xa6\xe5\x1e\x07\x4a\x23\xed\x3c\x32\xff\x21\x4c\xdd\x43\
|
||||
\xa9\xe3\x9b\xa1\x17\x9f\x86\xe8\x66\xce\xf3\x8a\xf2\xe8\x28\x9e\
|
||||
\x8f\x63\x4d\xcb\xb0\x50\x0e\x5c\x3a\x00\x80\x69\xc8\xaa\x86\xc6\
|
||||
\x24\x4d\x2d\x2e\x92\x23\x11\x7e\xa0\x33\x7e\xe4\x01\x1e\xb8\x36\
|
||||
\x8a\x65\xb8\x28\x04\xd1\x74\xb4\x48\x49\xde\x41\x32\xd0\xc2\xd8\
|
||||
\x91\x0b\x33\x00\x42\xc0\x94\x01\x00\x62\x51\xa7\x36\x50\x34\xac\
|
||||
\xdf\xd6\x8b\x9d\x0a\x72\x56\xe4\xf9\x26\x17\x4c\xd8\xcc\xc2\x59\
|
||||
\xaf\xa1\x49\x00\x22\x88\x61\x92\xbf\x18\xf8\xfa\x69\xfd\x07\xca\
|
||||
\x07\x00\x48\xcb\x2d\x3d\xbd\x81\xbf\xe6\xa3\xee\xbc\xd5\xdd\x34\
|
||||
\xf3\x75\x2e\x99\xbc\x1e\x3f\x18\xee\xb9\x1f\xea\x28\xf9\x27\x8d\
|
||||
\x9d\x08\x60\x87\xa6\xf1\x58\xa2\xd5\xe3\x83\x4d\x3d\x27\xba\xf0\
|
||||
\x61\x89\xeb\x1b\x2c\xfd\xe6\xe3\xcc\x9a\xb4\x9e\xa4\x5d\x80\xc5\
|
||||
\xe3\xa2\xfb\x03\x62\x58\xc7\x49\x00\x62\x51\x47\x01\x51\x5d\x97\
|
||||
\x86\x03\x5f\x38\x34\xec\x49\xe6\xac\x50\x21\x80\x62\xc9\xe5\x2b\
|
||||
\x38\x6f\xd4\x7a\x02\xa5\xe5\xb9\xfb\x0e\xa6\xd7\x92\x09\x7e\x2e\
|
||||
\xd0\x9c\x8d\x01\x62\x51\xc7\x05\xaa\x00\x7f\x6b\x83\xcd\x91\x56\
|
||||
\x2f\x67\xa3\x56\x08\x25\x91\x76\xee\x9e\xb5\x9c\xd1\x91\x96\x34\
|
||||
\xa8\x5c\x01\xb8\xe8\xde\x31\x17\x6d\x03\x7b\xb2\x02\x48\x83\x68\
|
||||
\x02\x16\x2a\x05\xff\x5d\xdf\x4d\x47\x97\x9f\xb3\x7b\x55\x4a\xe3\
|
||||
\xcc\xb2\x06\xee\xbb\xf8\xc7\x94\x85\x5a\xf1\x03\x23\x67\x00\xa6\
|
||||
\xd7\x9c\x61\x20\x05\xec\x1e\x14\x40\x5a\xfe\x21\xc2\x8b\x8e\xa3\
|
||||
\x78\x7f\x43\x37\xc9\x94\xca\xc3\x1e\x42\x4c\x2e\xdf\xc6\xcf\x2f\
|
||||
\xb9\x8d\xb2\x70\x6b\x0e\x4c\x08\x96\xd7\x82\x1c\x0f\x64\x89\xda\
|
||||
\x6a\xfb\xe8\x90\x00\x62\x51\xc7\x07\x1e\x16\x61\x5f\x47\x57\xc0\
|
||||
\xe6\xed\xbd\x04\xb9\x7b\x57\x02\xa5\x31\xa1\x74\x07\x3f\xbd\xf8\
|
||||
\x6e\x46\x47\x5a\x00\x49\xa6\xcf\xf2\x97\xb3\x28\x3a\xa1\x64\x7d\
|
||||
\xff\xa1\x0f\x07\xf3\x42\x27\x82\x38\x7a\xb4\xdd\xbd\x51\xd7\x84\
|
||||
\x3d\xfb\x1d\x76\xed\x4b\x62\x18\x92\x17\x88\x73\x47\xad\xe3\xa1\
|
||||
\x4b\x17\x71\xcb\xb9\x4f\xbd\xdb\x91\x2a\xb9\x0d\xb8\x1f\xf8\x6d\
|
||||
\x3a\x0b\x3e\x38\x48\xa2\x42\x24\xf5\x29\xea\xb8\x31\xae\x39\xa5\
|
||||
\x8a\xac\xe1\xc0\xb7\xaf\xd7\x34\x79\xb4\x7e\xcf\xa1\x8b\xfe\xba\
|
||||
\x6a\x0b\x86\xa1\x33\xf7\x92\x62\x26\x4e\xb0\xf0\x7d\x95\x87\x4b\
|
||||
\x54\x20\xaa\x47\x17\xff\xee\x79\x17\xb5\xfe\x79\xfa\x13\xfb\xa5\
|
||||
\x33\x35\x2a\x0c\x8c\x00\xc6\x01\xdf\x03\x7e\x94\x2e\xa8\x08\xb4\
|
||||
\x22\xa6\xed\xbb\x9c\xb0\xbd\x11\x25\x06\xc0\xa8\xda\x6a\xbb\xf5\
|
||||
\x24\x00\xbf\x7b\x63\xba\x5c\x36\x73\x52\x79\x24\x6c\xcd\x57\x4a\
|
||||
\x2d\x07\x26\x83\x22\x50\x8a\xb7\x6b\xf7\xb0\xf3\xf3\xfd\x58\xa6\
|
||||
\xf0\xad\x2b\x4a\x28\x29\xd6\x0b\x11\x9b\x5c\xe0\xca\xaa\xca\xf8\
|
||||
\xba\x6c\x37\xc7\x2f\xef\xba\x13\x58\x11\x68\xc5\x23\x2f\xd8\x59\
|
||||
\x8a\x52\x2e\x20\x87\x6b\xab\xed\x8a\xac\x47\x68\xe7\xde\x43\xa5\
|
||||
\x1f\x6c\xfa\x7c\x75\x7b\x67\xef\xab\x96\xa9\x4f\xb6\x0c\x9b\xce\
|
||||
\xe4\x18\x3e\xde\xfb\x5d\x5a\xb4\x18\x18\x67\xe1\xb8\x01\x1f\x6f\
|
||||
\xeb\xcd\x8b\x81\x7e\x62\x02\xab\x6b\xea\x2a\xae\xca\x76\xb3\x65\
|
||||
\x79\xc9\x2b\x81\x16\x59\x10\x72\x0e\xf4\x88\xdf\x9d\xf1\x40\xff\
|
||||
\x19\xb4\x22\xbb\xfd\x61\xb3\x5c\x44\xde\x0b\x59\xc6\x8c\xf3\xa7\
|
||||
\x4f\x45\x95\x3f\xc6\xb6\x83\x73\xe8\x49\x95\x11\x20\xe8\xee\x27\
|
||||
\x44\x8e\x5c\x88\xaf\x4c\xa6\x4d\xb2\x98\x53\x59\x8c\xeb\x15\x04\
|
||||
\xc8\x61\xe0\xda\xaa\xca\xf8\xd6\x6c\x37\xcf\xbf\xef\xb9\xbf\x8d\
|
||||
\x8b\x2f\xbd\xb9\xaf\xb0\xe1\xe6\xda\x6a\xfb\xad\xac\x0c\x88\x48\
|
||||
\x0a\x38\x90\x72\x3c\x36\x6e\xef\x64\x6d\xe3\x7c\xba\x53\xe5\x7d\
|
||||
\x59\x25\x10\x58\x33\x48\x95\xbf\x80\x26\x2e\xbb\xf6\xa6\x68\xd8\
|
||||
\x93\xcc\x2b\xfd\xee\x27\x63\x81\x97\x6b\xea\x2a\x46\x67\xbd\x79\
|
||||
\xe4\x91\x86\xf4\xe2\x03\x60\xfd\x50\xb9\x50\xf2\x58\x84\x13\x1f\
|
||||
\xbd\x2f\xdd\xe8\x1f\x5a\xf1\x8a\x7e\x88\x1f\x59\x88\x61\xc0\xe6\
|
||||
\xcf\x6c\x0e\x1d\xc9\x3d\x52\x9f\x20\x33\x81\x97\xb2\x07\x31\x7b\
|
||||
\x6a\xfa\xeb\x26\xa0\x6b\x50\x00\xe9\x5c\x68\x7b\x5f\x9f\x23\x85\
|
||||
\xf8\x4d\x59\xa6\xd3\x70\x4a\x9f\x41\x69\x63\xf0\x03\xc5\x86\x6d\
|
||||
\xbd\x85\x3a\x46\x00\x37\xd4\xd4\x55\x3c\x93\x05\xc2\xbd\xc0\x54\
|
||||
\xe0\xa6\x74\x33\x6c\xf0\xb6\xca\xe2\x65\xd6\x37\x80\x75\x48\x68\
|
||||
\xa4\x53\xf6\x2a\x5e\xe4\xe6\x6c\x7e\x10\x3d\xb9\x86\x50\xeb\x35\
|
||||
\xf8\xbe\x70\xf6\x59\x21\xe6\x54\x8e\x28\x54\xd6\x6c\xa7\xed\x61\
|
||||
\xed\xa9\x3c\x9c\x2d\x99\xdb\x01\x34\xa2\x92\x68\xee\xa6\xc1\xb2\
|
||||
\x34\xbc\xf0\x55\xb8\x25\x4f\xa1\x6b\x1e\x9f\xff\x2f\xc5\xa7\x3b\
|
||||
\x93\xe8\x05\xf1\xac\x44\x80\xfb\xd3\x5d\xc0\xe1\x03\x48\xcb\xd3\
|
||||
\x00\xba\x53\x8b\xa8\xce\x41\x92\x2b\x70\x47\xdc\x83\x1f\xb9\x05\
|
||||
\xc3\x50\x34\x34\x26\x39\xd8\xec\x16\xca\x1e\x16\x00\x13\x73\x06\
|
||||
\x10\x8b\x3a\x6f\x82\x34\x6b\xce\x46\x34\xf7\xb3\x21\x42\x6a\x08\
|
||||
\xb7\xf4\x09\x94\x76\x06\xae\x17\xb0\xb5\xde\xc6\x4e\x16\xcc\x1e\
|
||||
\xee\xcc\x87\x01\x80\x9f\x28\x11\xac\x8e\x7b\x87\x6c\x2e\x06\xc6\
|
||||
\x14\x9c\xb2\x17\x11\xf1\x48\xb4\x7b\x6c\xfa\xac\x17\x5d\x2f\x08\
|
||||
\x0d\xf3\xf3\x05\xb0\x1a\x8c\x0f\xc4\xfd\x04\xb3\xfb\xe9\xc1\x41\
|
||||
\x28\xf0\xc3\xd7\xe2\x96\x3e\x8f\xa1\x79\xec\x6b\x72\xd8\xd6\xd0\
|
||||
\x8b\x69\xe4\x0d\x62\x52\x5e\x00\x62\x51\xa7\x1b\x78\x06\x31\x1d\
|
||||
\xa3\xeb\x49\x34\x77\xf7\xd0\x49\x4d\xd1\x0f\xf0\xc3\x37\xa2\x89\
|
||||
\xa2\xa1\x31\x45\xcb\x11\x37\x5f\x00\xad\xf9\x32\x40\x2c\xea\xfc\
|
||||
\x1d\x78\x5b\x54\x07\x66\xe7\x03\x80\x3f\xb4\x3d\x94\x3d\x85\xd2\
|
||||
\x46\xe3\x7a\x8a\x2d\xdb\xed\xbc\xea\x07\x60\x55\xde\x00\x32\x6d\
|
||||
\x3c\x90\x16\x3d\xf9\x4f\xac\xae\x28\x6a\x48\x7b\x98\x8a\x53\xfe\
|
||||
\x1a\x9a\x72\x89\x27\x3c\xea\x1b\x93\xf9\xd8\xc3\xca\x82\x00\x48\
|
||||
\x17\xf9\xf3\x10\x33\x69\x76\x2d\xc7\xec\xad\x1e\xaa\x8a\xc7\x0f\
|
||||
\xcf\xc3\x2d\x7d\x14\x4d\x5c\x36\x6f\xef\x6b\x0a\xe4\xd0\x72\x7d\
|
||||
\x21\x53\xf3\x16\x82\x81\x4c\x70\xbb\x57\x89\x89\xd5\x71\x17\x46\
|
||||
\xf2\xed\x21\x41\x38\x25\x0f\x12\x84\xae\xc1\xd4\x03\xd6\x6d\xea\
|
||||
\x26\xe5\x0e\xcb\xb5\x6e\x04\x7e\x51\x55\x19\xf7\x0a\x06\x20\x0d\
|
||||
\xe2\x8f\xc0\xaf\x50\x2e\x56\xdb\xed\xe8\xce\x87\x43\xb8\x57\x13\
|
||||
\xa7\xf4\x71\xd0\x4a\xe9\xec\x0e\xd8\xb5\x37\x75\xaa\x6a\xb6\x02\
|
||||
\x57\x55\x55\xc6\x13\xa7\xfa\x83\x61\x25\xc3\xb1\xa8\xf3\x4b\x90\
|
||||
\x95\x60\x13\x4e\xcc\x41\x4f\xbe\x33\x78\xa3\xd7\xba\x08\x2f\xbc\
|
||||
\x10\x94\xcb\xee\x7d\x29\xec\xe4\x97\x5a\xf4\xfb\xc0\x65\x55\x95\
|
||||
\xf1\x9e\xe1\xac\x69\xd8\xd9\x7c\x2c\xea\x2c\x05\x79\x52\x89\x49\
|
||||
\xa8\x75\x01\x66\xf7\x8a\xc1\x53\x8d\xb2\xdf\x80\x68\x74\x75\xfb\
|
||||
\xec\xdc\x9b\x62\x88\xff\x1f\x5e\x06\x16\x54\x55\xc6\x87\xdd\x0a\
|
||||
\xcc\xa9\x1c\x89\x45\x9d\x07\x81\xfb\x00\xcc\xae\x07\x09\xb7\x7d\
|
||||
\x27\xbb\x39\x68\x25\x04\xd6\xd5\x18\xba\x47\xfd\xee\x24\x9e\x9f\
|
||||
\x95\x85\x7b\x80\x25\x55\x95\xf1\xce\x5c\xd6\x92\x73\x3d\x15\x8b\
|
||||
\x3a\xcf\xa6\xc3\x7d\x97\x96\x7c\x8b\x48\x7c\x22\xba\xbb\x81\xe3\
|
||||
\x7f\x99\x66\x40\x8c\xea\x3b\x52\x81\xe2\xf0\xd1\x01\x1d\xbe\x36\
|
||||
\xe0\xb6\xaa\xca\xf8\x1f\xaa\x2a\xe3\x7e\xae\xeb\xc8\xab\x20\x8c\
|
||||
\x45\x9d\x7f\x01\x73\xc1\x58\x2b\x41\x13\xa1\xc4\x5c\x42\xed\x4b\
|
||||
\xd0\x53\x35\x48\x70\x18\x3d\xb5\x16\x3d\xb5\x0a\xc4\x40\xa0\x7f\
|
||||
\x23\x60\x03\x70\x5d\x55\x65\xfc\x4f\xf9\xb7\xdc\x0b\x50\x85\x2c\
|
||||
\x5e\x66\x15\x01\x77\x01\xcf\x42\x00\x52\x8c\x92\x11\x88\xea\x01\
|
||||
\xd5\xd3\xd7\x1c\xf7\x14\xb7\xde\x30\x12\xcb\x94\x97\x94\xe2\x67\
|
||||
\x55\x95\xf1\xb6\x42\x64\x7c\x52\xc8\x97\x3d\x16\x2f\xb3\xa6\x00\
|
||||
\xaf\xa4\xeb\xdb\xe2\xe3\x0d\x5e\x38\x67\x72\xa8\x73\x4e\xe5\x88\
|
||||
\x65\x73\x67\x1c\x7a\x8e\x02\x8a\x7c\x15\x6f\xab\x2c\x5e\x66\xcd\
|
||||
\x06\xae\x03\x2e\x04\xcc\xd2\x62\x6d\xfb\x35\xb3\x4b\x9f\x5f\x30\
|
||||
\xfb\x70\x63\xa1\x75\xc9\x57\xf9\xba\xcd\xe2\x65\x56\x91\x08\x32\
|
||||
\xf3\xbc\xb0\xbd\x74\x51\x67\xf0\x55\xe8\xf8\x3f\x66\x47\x07\xd4\
|
||||
\xf8\xcc\x73\x31\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
|
||||
\
|
||||
"
|
||||
|
||||
qt_resource_name = b"\
|
||||
\x00\x06\
|
||||
\x07\x03\x7d\xc3\
|
||||
\x00\x69\
|
||||
\x00\x6d\x00\x61\x00\x67\x00\x65\x00\x73\
|
||||
\x00\x03\
|
||||
\x00\x00\x70\x37\
|
||||
\x00\x69\
|
||||
\x00\x6d\x00\x67\
|
||||
\x00\x07\
|
||||
\x0b\xb6\x57\xa7\
|
||||
\x00\x75\
|
||||
\x00\x64\x00\x73\x00\x2e\x00\x70\x00\x6e\x00\x67\
|
||||
"
|
||||
|
||||
qt_resource_struct = b"\
|
||||
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
|
||||
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
|
||||
\x00\x00\x00\x12\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\
|
||||
\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
|
||||
"
|
||||
|
||||
def qInitResources():
|
||||
QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
|
||||
|
||||
def qCleanupResources():
|
||||
QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
|
||||
|
||||
qInitResources()
|
@ -1,240 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>UDSAboutDialog</class>
|
||||
<widget class="QDialog" name="UDSAboutDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>466</width>
|
||||
<height>402</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Verdana</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>About UDS Actor</string>
|
||||
</property>
|
||||
<property name="locale">
|
||||
<locale language="English" country="UnitedStates"/>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="LogoLabel">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><img src=":/images/img/uds.png"/> UDS Actor Tools</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>5</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="TitleLabel">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">UDS Actor</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="VersionLabel">
|
||||
<property name="text">
|
||||
<string>Version 1.7.0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>5</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="aboutTab">
|
||||
<attribute name="title">
|
||||
<string>&About</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="aboutBrowser">
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Verdana'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif';"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">(c) 2012-2016, Virtual Cable S.L.U.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-style:italic;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.udsenterprise.com"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">http://www.udsenterprise.com</span></a></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.openuds.org"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">http://www.openuds.org</span></a></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif';"><br /></p></body></html></string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="authorsTab">
|
||||
<attribute name="title">
|
||||
<string>A&uthors</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="authorsBrowser">
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Verdana'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Adolfo Gómez García &lt;agomez@virtualcable.es&gt;</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="licenseTab">
|
||||
<attribute name="title">
|
||||
<string>&License Agreement</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="licenseBrowser">
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Verdana'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Copyright (c) 2012-2016 Virtual Cable S.L.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">All rights reserved.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Redistribution and use in source and binary forms, with or without modification,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">are permitted provided that the following conditions are met:</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> * Redistributions of source code must retain the above copyright notice,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> this list of conditions and the following disclaimer.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> * Redistributions in binary form must reproduce the above copyright notice,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> this list of conditions and the following disclaimer in the documentation</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> and/or other materials provided with the distribution.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> * Neither the name of Virtual Cable S.L. nor the names of its contributors</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> may be used to endorse or promote products derived from this software</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> without specific prior written permission.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot;</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="UDSActor.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>clicked(QAbstractButton*)</signal>
|
||||
<receiver>UDSAboutDialog</receiver>
|
||||
<slot>closeDialog()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>432</x>
|
||||
<y>381</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>282</x>
|
||||
<y>362</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<slots>
|
||||
<slot>closeDialog()</slot>
|
||||
</slots>
|
||||
</ui>
|
@ -1,164 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'about-dialog.ui'
|
||||
#
|
||||
# Created: Mon Apr 27 22:05:02 2015
|
||||
# by: PyQt4 UI code generator 4.11.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
|
||||
class Ui_UDSAboutDialog(object):
|
||||
def setupUi(self, UDSAboutDialog):
|
||||
UDSAboutDialog.setObjectName(_fromUtf8("UDSAboutDialog"))
|
||||
UDSAboutDialog.resize(466, 402)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Verdana"))
|
||||
font.setPointSize(9)
|
||||
UDSAboutDialog.setFont(font)
|
||||
UDSAboutDialog.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates))
|
||||
UDSAboutDialog.setModal(True)
|
||||
self.vboxlayout = QtGui.QVBoxLayout(UDSAboutDialog)
|
||||
self.vboxlayout.setSpacing(9)
|
||||
self.vboxlayout.setMargin(9)
|
||||
self.vboxlayout.setObjectName(_fromUtf8("vboxlayout"))
|
||||
self.LogoLabel = QtGui.QLabel(UDSAboutDialog)
|
||||
self.LogoLabel.setObjectName(_fromUtf8("LogoLabel"))
|
||||
self.vboxlayout.addWidget(self.LogoLabel)
|
||||
spacerItem = QtGui.QSpacerItem(20, 5, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
|
||||
self.vboxlayout.addItem(spacerItem)
|
||||
self.TitleLabel = QtGui.QLabel(UDSAboutDialog)
|
||||
self.TitleLabel.setObjectName(_fromUtf8("TitleLabel"))
|
||||
self.vboxlayout.addWidget(self.TitleLabel)
|
||||
self.VersionLabel = QtGui.QLabel(UDSAboutDialog)
|
||||
self.VersionLabel.setObjectName(_fromUtf8("VersionLabel"))
|
||||
self.vboxlayout.addWidget(self.VersionLabel)
|
||||
spacerItem1 = QtGui.QSpacerItem(20, 5, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
|
||||
self.vboxlayout.addItem(spacerItem1)
|
||||
self.tabWidget = QtGui.QTabWidget(UDSAboutDialog)
|
||||
self.tabWidget.setObjectName(_fromUtf8("tabWidget"))
|
||||
self.aboutTab = QtGui.QWidget()
|
||||
self.aboutTab.setObjectName(_fromUtf8("aboutTab"))
|
||||
self.vboxlayout1 = QtGui.QVBoxLayout(self.aboutTab)
|
||||
self.vboxlayout1.setSpacing(6)
|
||||
self.vboxlayout1.setMargin(9)
|
||||
self.vboxlayout1.setObjectName(_fromUtf8("vboxlayout1"))
|
||||
self.aboutBrowser = QtGui.QTextBrowser(self.aboutTab)
|
||||
self.aboutBrowser.setOpenExternalLinks(True)
|
||||
self.aboutBrowser.setObjectName(_fromUtf8("aboutBrowser"))
|
||||
self.vboxlayout1.addWidget(self.aboutBrowser)
|
||||
self.tabWidget.addTab(self.aboutTab, _fromUtf8(""))
|
||||
self.authorsTab = QtGui.QWidget()
|
||||
self.authorsTab.setObjectName(_fromUtf8("authorsTab"))
|
||||
self.vboxlayout2 = QtGui.QVBoxLayout(self.authorsTab)
|
||||
self.vboxlayout2.setSpacing(6)
|
||||
self.vboxlayout2.setMargin(9)
|
||||
self.vboxlayout2.setObjectName(_fromUtf8("vboxlayout2"))
|
||||
self.authorsBrowser = QtGui.QTextBrowser(self.authorsTab)
|
||||
self.authorsBrowser.setOpenExternalLinks(True)
|
||||
self.authorsBrowser.setObjectName(_fromUtf8("authorsBrowser"))
|
||||
self.vboxlayout2.addWidget(self.authorsBrowser)
|
||||
self.tabWidget.addTab(self.authorsTab, _fromUtf8(""))
|
||||
self.licenseTab = QtGui.QWidget()
|
||||
self.licenseTab.setObjectName(_fromUtf8("licenseTab"))
|
||||
self.vboxlayout3 = QtGui.QVBoxLayout(self.licenseTab)
|
||||
self.vboxlayout3.setSpacing(6)
|
||||
self.vboxlayout3.setMargin(9)
|
||||
self.vboxlayout3.setObjectName(_fromUtf8("vboxlayout3"))
|
||||
self.licenseBrowser = QtGui.QTextBrowser(self.licenseTab)
|
||||
self.licenseBrowser.setObjectName(_fromUtf8("licenseBrowser"))
|
||||
self.vboxlayout3.addWidget(self.licenseBrowser)
|
||||
self.tabWidget.addTab(self.licenseTab, _fromUtf8(""))
|
||||
self.vboxlayout.addWidget(self.tabWidget)
|
||||
self.buttonBox = QtGui.QDialogButtonBox(UDSAboutDialog)
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Close)
|
||||
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
|
||||
self.vboxlayout.addWidget(self.buttonBox)
|
||||
|
||||
self.retranslateUi(UDSAboutDialog)
|
||||
self.tabWidget.setCurrentIndex(0)
|
||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("clicked(QAbstractButton*)")), UDSAboutDialog.closeDialog)
|
||||
QtCore.QMetaObject.connectSlotsByName(UDSAboutDialog)
|
||||
|
||||
def retranslateUi(self, UDSAboutDialog):
|
||||
UDSAboutDialog.setWindowTitle(_translate("UDSAboutDialog", "About UDS Actor", None))
|
||||
self.LogoLabel.setText(_translate("UDSAboutDialog", "<html><head/><body><p><img src=\":/images/img/uds.png\"/> UDS Actor Tools</p></body></html>", None))
|
||||
self.TitleLabel.setText(_translate("UDSAboutDialog", "<html><head/><body><p><span style=\" font-family:\'Sans Serif\'; font-size:9pt; font-weight:600;\">UDS Actor</span></p></body></html>", None))
|
||||
self.VersionLabel.setText(_translate("UDSAboutDialog", "Version 1.7.0", None))
|
||||
self.aboutBrowser.setHtml(_translate("UDSAboutDialog", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
|
||||
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
|
||||
"p, li { white-space: pre-wrap; }\n"
|
||||
"</style></head><body style=\" font-family:\'Verdana\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
|
||||
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'Sans Serif\';\"><br /></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'Sans Serif\'; font-weight:600;\">(c) 2014, Virtual Cable S.L.U.</span></p>\n"
|
||||
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'Sans Serif\'; font-style:italic;\"><br /></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><a href=\"http://www.udsenterprise.com\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt; text-decoration: underline; color:#0000ff;\">http://www.udsenterprise.com</span></a></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><a href=\"http://www.openuds.org\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt; text-decoration: underline; color:#0000ff;\">http://www.openuds.org</span></a></p>\n"
|
||||
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'Sans Serif\';\"><br /></p></body></html>", None))
|
||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.aboutTab), _translate("UDSAboutDialog", "&About", None))
|
||||
self.authorsBrowser.setHtml(_translate("UDSAboutDialog", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
|
||||
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
|
||||
"p, li { white-space: pre-wrap; }\n"
|
||||
"</style></head><body style=\" font-family:\'Verdana\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'Sans Serif\';\">Adolfo Gómez García <agomez@virtualcable.es></span></p></body></html>", None))
|
||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.authorsTab), _translate("UDSAboutDialog", "A&uthors", None))
|
||||
self.licenseBrowser.setHtml(_translate("UDSAboutDialog", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
|
||||
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
|
||||
"p, li { white-space: pre-wrap; }\n"
|
||||
"</style></head><body style=\" font-family:\'Verdana\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">Copyright (c) 2014 Virtual Cable S.L.</span></p>\n"
|
||||
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"><br /></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">All rights reserved.</span></p>\n"
|
||||
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"><br /></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">Redistribution and use in source and binary forms, with or without modification,</span></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">are permitted provided that the following conditions are met:</span></p>\n"
|
||||
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"><br /></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> * Redistributions of source code must retain the above copyright notice,</span></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> this list of conditions and the following disclaimer.</span></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> * Redistributions in binary form must reproduce the above copyright notice,</span></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> this list of conditions and the following disclaimer in the documentation</span></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> and/or other materials provided with the distribution.</span></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> * Neither the name of Virtual Cable S.L. nor the names of its contributors</span></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> may be used to endorse or promote products derived from this software</span></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> without specific prior written permission.</span></p>\n"
|
||||
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"><br /></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"</span></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE</span></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE</span></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE</span></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL</span></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR</span></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER</span></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,</span></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE</span></p>\n"
|
||||
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span></p>\n"
|
||||
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"><br /></p></body></html>", None))
|
||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.licenseTab), _translate("UDSAboutDialog", "&License Agreement", None))
|
||||
|
||||
import UDSActor_rc
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
app = QtGui.QApplication(sys.argv)
|
||||
UDSAboutDialog = QtGui.QDialog()
|
||||
ui = Ui_UDSAboutDialog()
|
||||
ui.setupUi(UDSAboutDialog)
|
||||
UDSAboutDialog.show()
|
||||
sys.exit(app.exec_())
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 9.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 43 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.5 KiB |
@ -1,89 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>UDSMessageDialog</class>
|
||||
<widget class="QDialog" name="UDSMessageDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>339</width>
|
||||
<height>188</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Verdana</family>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>UDS Actor</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="verticalLayoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>321</width>
|
||||
<height>171</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="message"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>15</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>clicked(QAbstractButton*)</signal>
|
||||
<receiver>UDSMessageDialog</receiver>
|
||||
<slot>closeDialog()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>203</x>
|
||||
<y>161</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>337</x>
|
||||
<y>125</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<slots>
|
||||
<slot>closeDialog()</slot>
|
||||
</slots>
|
||||
</ui>
|
@ -1,71 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'message-dialog.ui'
|
||||
#
|
||||
# Created: Mon Apr 27 22:05:02 2015
|
||||
# by: PyQt4 UI code generator 4.11.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
|
||||
class Ui_UDSMessageDialog(object):
|
||||
def setupUi(self, UDSMessageDialog):
|
||||
UDSMessageDialog.setObjectName(_fromUtf8("UDSMessageDialog"))
|
||||
UDSMessageDialog.resize(339, 188)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(UDSMessageDialog.sizePolicy().hasHeightForWidth())
|
||||
UDSMessageDialog.setSizePolicy(sizePolicy)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Verdana"))
|
||||
font.setPointSize(10)
|
||||
UDSMessageDialog.setFont(font)
|
||||
self.verticalLayoutWidget = QtGui.QWidget(UDSMessageDialog)
|
||||
self.verticalLayoutWidget.setGeometry(QtCore.QRect(10, 10, 321, 171))
|
||||
self.verticalLayoutWidget.setObjectName(_fromUtf8("verticalLayoutWidget"))
|
||||
self.verticalLayout = QtGui.QVBoxLayout(self.verticalLayoutWidget)
|
||||
self.verticalLayout.setMargin(0)
|
||||
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
|
||||
self.message = QtGui.QTextBrowser(self.verticalLayoutWidget)
|
||||
self.message.setObjectName(_fromUtf8("message"))
|
||||
self.verticalLayout.addWidget(self.message)
|
||||
spacerItem = QtGui.QSpacerItem(20, 15, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
|
||||
self.verticalLayout.addItem(spacerItem)
|
||||
self.buttonBox = QtGui.QDialogButtonBox(self.verticalLayoutWidget)
|
||||
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
|
||||
self.verticalLayout.addWidget(self.buttonBox)
|
||||
|
||||
self.retranslateUi(UDSMessageDialog)
|
||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("clicked(QAbstractButton*)")), UDSMessageDialog.closeDialog)
|
||||
QtCore.QMetaObject.connectSlotsByName(UDSMessageDialog)
|
||||
|
||||
def retranslateUi(self, UDSMessageDialog):
|
||||
UDSMessageDialog.setWindowTitle(_translate("UDSMessageDialog", "UDS Actor", None))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
app = QtGui.QApplication(sys.argv)
|
||||
UDSMessageDialog = QtGui.QDialog()
|
||||
ui = Ui_UDSMessageDialog()
|
||||
ui.setupUi(UDSMessageDialog)
|
||||
UDSMessageDialog.show()
|
||||
sys.exit(app.exec_())
|
||||
|
@ -1,327 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>UdsActorSetupDialog</class>
|
||||
<widget class="QDialog" name="UdsActorSetupDialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::WindowModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>243</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Verdana</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>UDS Actor Configuration</string>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="locale">
|
||||
<locale language="English" country="UnitedStates"/>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QPushButton" name="testButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>160</y>
|
||||
<width>361</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Click to test the selecter parameters</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string><html><head/><body><p>Click on this button to test the server host and master key parameters.</p><p>A window will be displayed with results after the test is executed.</p><p><br/></p><p>This button will only be active if all parameters are filled.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Test parameters</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="saveButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>190</y>
|
||||
<width>101</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Accepts changes and saves them</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Clicking on this button will accept all changes and save them, closing the configuration window</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Accept && Save</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="cancelButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>260</x>
|
||||
<y>190</y>
|
||||
<width>121</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Cancel all changes and discard them</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Discards all changes and closes the configuration window</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cancel && Discard</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
<width>361</width>
|
||||
<height>131</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>16</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>UDS Server Host</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="host">
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Uds Broker Server Addres. Use IP or FQDN</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Enter here the UDS Broker Addres using either its IP address or its FQDN address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>UDS Master Key</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="masterKey">
|
||||
<property name="toolTip">
|
||||
<string>Master key to communicate with UDS Broker</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string><html><head/><body><p>Enter the Master Key (found on<span style=" font-weight:600;"> UDS Configuration</span> section) of the UDS Broker to allow communication of the Actor with Broker</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Security</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="useSSl">
|
||||
<property name="toolTip">
|
||||
<string>Select communication security with broker</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string><html><head/><body><p>Select the security for communications with UDS Broker.</p><p>The recommended method of communication is <span style=" font-weight:600;">Use SSL</span>, but selection needs to be acording to your broker configuration.</p></body></html></string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Do not use SSL</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Use SSL</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="logLevelLabel">
|
||||
<property name="text">
|
||||
<string>Log Level</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="logLevelComboBox">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="frame">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">DEBUG</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">INFO</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">ERROR</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">FATAL</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>host</sender>
|
||||
<signal>textChanged(QString)</signal>
|
||||
<receiver>UdsActorSetupDialog</receiver>
|
||||
<slot>textChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>123</x>
|
||||
<y>31</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>143</x>
|
||||
<y>48</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>masterKey</sender>
|
||||
<signal>textChanged(QString)</signal>
|
||||
<receiver>UdsActorSetupDialog</receiver>
|
||||
<slot>textChanged()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>258</x>
|
||||
<y>75</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>299</x>
|
||||
<y>84</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>cancelButton</sender>
|
||||
<signal>pressed()</signal>
|
||||
<receiver>UdsActorSetupDialog</receiver>
|
||||
<slot>cancelAndDiscard()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>315</x>
|
||||
<y>165</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>231</x>
|
||||
<y>161</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>testButton</sender>
|
||||
<signal>pressed()</signal>
|
||||
<receiver>UdsActorSetupDialog</receiver>
|
||||
<slot>testParameters()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>239</x>
|
||||
<y>132</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>285</x>
|
||||
<y>185</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>saveButton</sender>
|
||||
<signal>pressed()</signal>
|
||||
<receiver>UdsActorSetupDialog</receiver>
|
||||
<slot>acceptAndSave()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>71</x>
|
||||
<y>165</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>124</x>
|
||||
<y>181</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<slots>
|
||||
<slot>textChanged()</slot>
|
||||
<slot>cancelAndDiscard()</slot>
|
||||
<slot>testParameters()</slot>
|
||||
<slot>acceptAndSave()</slot>
|
||||
</slots>
|
||||
</ui>
|
@ -1,152 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'setup-dialog.ui'
|
||||
#
|
||||
# Created: Mon Apr 27 22:05:03 2015
|
||||
# by: PyQt4 UI code generator 4.11.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
|
||||
class Ui_UdsActorSetupDialog(object):
|
||||
def setupUi(self, UdsActorSetupDialog):
|
||||
UdsActorSetupDialog.setObjectName(_fromUtf8("UdsActorSetupDialog"))
|
||||
UdsActorSetupDialog.setWindowModality(QtCore.Qt.WindowModal)
|
||||
UdsActorSetupDialog.resize(400, 243)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(UdsActorSetupDialog.sizePolicy().hasHeightForWidth())
|
||||
UdsActorSetupDialog.setSizePolicy(sizePolicy)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(_fromUtf8("Verdana"))
|
||||
font.setPointSize(9)
|
||||
UdsActorSetupDialog.setFont(font)
|
||||
UdsActorSetupDialog.setAutoFillBackground(False)
|
||||
UdsActorSetupDialog.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates))
|
||||
UdsActorSetupDialog.setSizeGripEnabled(False)
|
||||
UdsActorSetupDialog.setModal(True)
|
||||
self.testButton = QtGui.QPushButton(UdsActorSetupDialog)
|
||||
self.testButton.setEnabled(False)
|
||||
self.testButton.setGeometry(QtCore.QRect(20, 160, 361, 23))
|
||||
self.testButton.setObjectName(_fromUtf8("testButton"))
|
||||
self.saveButton = QtGui.QPushButton(UdsActorSetupDialog)
|
||||
self.saveButton.setEnabled(False)
|
||||
self.saveButton.setGeometry(QtCore.QRect(20, 190, 101, 23))
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.saveButton.sizePolicy().hasHeightForWidth())
|
||||
self.saveButton.setSizePolicy(sizePolicy)
|
||||
self.saveButton.setObjectName(_fromUtf8("saveButton"))
|
||||
self.cancelButton = QtGui.QPushButton(UdsActorSetupDialog)
|
||||
self.cancelButton.setGeometry(QtCore.QRect(260, 190, 121, 23))
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.cancelButton.sizePolicy().hasHeightForWidth())
|
||||
self.cancelButton.setSizePolicy(sizePolicy)
|
||||
self.cancelButton.setObjectName(_fromUtf8("cancelButton"))
|
||||
self.layoutWidget = QtGui.QWidget(UdsActorSetupDialog)
|
||||
self.layoutWidget.setGeometry(QtCore.QRect(20, 20, 361, 131))
|
||||
self.layoutWidget.setObjectName(_fromUtf8("layoutWidget"))
|
||||
self.formLayout = QtGui.QFormLayout(self.layoutWidget)
|
||||
self.formLayout.setFieldGrowthPolicy(QtGui.QFormLayout.AllNonFixedFieldsGrow)
|
||||
self.formLayout.setMargin(0)
|
||||
self.formLayout.setVerticalSpacing(16)
|
||||
self.formLayout.setObjectName(_fromUtf8("formLayout"))
|
||||
self.label = QtGui.QLabel(self.layoutWidget)
|
||||
self.label.setObjectName(_fromUtf8("label"))
|
||||
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label)
|
||||
self.host = QtGui.QLineEdit(self.layoutWidget)
|
||||
self.host.setAcceptDrops(False)
|
||||
self.host.setObjectName(_fromUtf8("host"))
|
||||
self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.host)
|
||||
self.label_3 = QtGui.QLabel(self.layoutWidget)
|
||||
self.label_3.setObjectName(_fromUtf8("label_3"))
|
||||
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label_3)
|
||||
self.masterKey = QtGui.QLineEdit(self.layoutWidget)
|
||||
self.masterKey.setObjectName(_fromUtf8("masterKey"))
|
||||
self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.masterKey)
|
||||
self.label_4 = QtGui.QLabel(self.layoutWidget)
|
||||
self.label_4.setObjectName(_fromUtf8("label_4"))
|
||||
self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.label_4)
|
||||
self.useSSl = QtGui.QComboBox(self.layoutWidget)
|
||||
self.useSSl.setObjectName(_fromUtf8("useSSl"))
|
||||
self.useSSl.addItem(_fromUtf8(""))
|
||||
self.useSSl.addItem(_fromUtf8(""))
|
||||
self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.useSSl)
|
||||
self.logLevelLabel = QtGui.QLabel(self.layoutWidget)
|
||||
self.logLevelLabel.setObjectName(_fromUtf8("logLevelLabel"))
|
||||
self.formLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.logLevelLabel)
|
||||
self.logLevelComboBox = QtGui.QComboBox(self.layoutWidget)
|
||||
self.logLevelComboBox.setFrame(True)
|
||||
self.logLevelComboBox.setObjectName(_fromUtf8("logLevelComboBox"))
|
||||
self.logLevelComboBox.addItem(_fromUtf8(""))
|
||||
self.logLevelComboBox.setItemText(0, _fromUtf8("DEBUG"))
|
||||
self.logLevelComboBox.addItem(_fromUtf8(""))
|
||||
self.logLevelComboBox.setItemText(1, _fromUtf8("INFO"))
|
||||
self.logLevelComboBox.addItem(_fromUtf8(""))
|
||||
self.logLevelComboBox.setItemText(2, _fromUtf8("ERROR"))
|
||||
self.logLevelComboBox.addItem(_fromUtf8(""))
|
||||
self.logLevelComboBox.setItemText(3, _fromUtf8("FATAL"))
|
||||
self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.logLevelComboBox)
|
||||
|
||||
self.retranslateUi(UdsActorSetupDialog)
|
||||
self.logLevelComboBox.setCurrentIndex(1)
|
||||
QtCore.QObject.connect(self.host, QtCore.SIGNAL(_fromUtf8("textChanged(QString)")), UdsActorSetupDialog.textChanged)
|
||||
QtCore.QObject.connect(self.masterKey, QtCore.SIGNAL(_fromUtf8("textChanged(QString)")), UdsActorSetupDialog.textChanged)
|
||||
QtCore.QObject.connect(self.cancelButton, QtCore.SIGNAL(_fromUtf8("pressed()")), UdsActorSetupDialog.cancelAndDiscard)
|
||||
QtCore.QObject.connect(self.testButton, QtCore.SIGNAL(_fromUtf8("pressed()")), UdsActorSetupDialog.testParameters)
|
||||
QtCore.QObject.connect(self.saveButton, QtCore.SIGNAL(_fromUtf8("pressed()")), UdsActorSetupDialog.acceptAndSave)
|
||||
QtCore.QMetaObject.connectSlotsByName(UdsActorSetupDialog)
|
||||
|
||||
def retranslateUi(self, UdsActorSetupDialog):
|
||||
UdsActorSetupDialog.setWindowTitle(_translate("UdsActorSetupDialog", "UDS Actor Configuration", None))
|
||||
self.testButton.setToolTip(_translate("UdsActorSetupDialog", "Click to test the selecter parameters", None))
|
||||
self.testButton.setWhatsThis(_translate("UdsActorSetupDialog", "<html><head/><body><p>Click on this button to test the server host and master key parameters.</p><p>A window will be displayed with results after the test is executed.</p><p><br/></p><p>This button will only be active if all parameters are filled.</p></body></html>", None))
|
||||
self.testButton.setText(_translate("UdsActorSetupDialog", "Test parameters", None))
|
||||
self.saveButton.setToolTip(_translate("UdsActorSetupDialog", "Accepts changes and saves them", None))
|
||||
self.saveButton.setWhatsThis(_translate("UdsActorSetupDialog", "Clicking on this button will accept all changes and save them, closing the configuration window", None))
|
||||
self.saveButton.setText(_translate("UdsActorSetupDialog", "Accept && Save", None))
|
||||
self.cancelButton.setToolTip(_translate("UdsActorSetupDialog", "Cancel all changes and discard them", None))
|
||||
self.cancelButton.setWhatsThis(_translate("UdsActorSetupDialog", "Discards all changes and closes the configuration window", None))
|
||||
self.cancelButton.setText(_translate("UdsActorSetupDialog", "Cancel && Discard", None))
|
||||
self.label.setText(_translate("UdsActorSetupDialog", "UDS Server Host", None))
|
||||
self.host.setToolTip(_translate("UdsActorSetupDialog", "Uds Broker Server Addres. Use IP or FQDN", None))
|
||||
self.host.setWhatsThis(_translate("UdsActorSetupDialog", "Enter here the UDS Broker Addres using either its IP address or its FQDN address", None))
|
||||
self.label_3.setText(_translate("UdsActorSetupDialog", "UDS Master Key", None))
|
||||
self.masterKey.setToolTip(_translate("UdsActorSetupDialog", "Master key to communicate with UDS Broker", None))
|
||||
self.masterKey.setWhatsThis(_translate("UdsActorSetupDialog", "<html><head/><body><p>Enter the Master Key (found on<span style=\" font-weight:600;\"> UDS Configuration</span> section) of the UDS Broker to allow communication of the Actor with Broker</p></body></html>", None))
|
||||
self.label_4.setText(_translate("UdsActorSetupDialog", "Security", None))
|
||||
self.useSSl.setToolTip(_translate("UdsActorSetupDialog", "Select communication security with broker", None))
|
||||
self.useSSl.setWhatsThis(_translate("UdsActorSetupDialog", "<html><head/><body><p>Select the security for communications with UDS Broker.</p><p>The recommended method of communication is <span style=\" font-weight:600;\">Use SSL</span>, but selection needs to be acording to your broker configuration.</p></body></html>", None))
|
||||
self.useSSl.setItemText(0, _translate("UdsActorSetupDialog", "Do not use SSL", None))
|
||||
self.useSSl.setItemText(1, _translate("UdsActorSetupDialog", "Use SSL", None))
|
||||
self.logLevelLabel.setText(_translate("UdsActorSetupDialog", "Log Level", None))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
app = QtGui.QApplication(sys.argv)
|
||||
UdsActorSetupDialog = QtGui.QDialog()
|
||||
ui = Ui_UdsActorSetupDialog()
|
||||
ui.setupUi(UdsActorSetupDialog)
|
||||
UdsActorSetupDialog.show()
|
||||
sys.exit(app.exec_())
|
||||
|
@ -1,215 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import urllib3
|
||||
from udsactor import operations
|
||||
from udsactor import store
|
||||
from udsactor import REST
|
||||
from udsactor import ipc
|
||||
from udsactor import httpserver
|
||||
|
||||
from time import sleep
|
||||
|
||||
import random
|
||||
import requests
|
||||
import json
|
||||
import logging
|
||||
|
||||
|
||||
def testRest():
|
||||
# cfg = store.readConfig()
|
||||
cfg = {'host': '172.27.0.1:8000', 'masterKey': '8f914604ad2c5c558575856299866bbb', 'ssl': False}
|
||||
print(cfg)
|
||||
print("Intefaces: ", list(operations.getNetworkInfo()))
|
||||
print("Joined Domain: ", operations.getDomainName())
|
||||
|
||||
# renameComputer('win7-64')
|
||||
# joinDomain('dom.dkmon.com', 'ou=pruebas_2,dc=dom,dc=dkmon,dc=com', 'administrador@dom.dkmon.com', 'Temporal2012', True)
|
||||
# reboot()
|
||||
r = REST.Api(cfg['host'], cfg['masterKey'], cfg['ssl'], scrambledResponses=True)
|
||||
print("Connected: {}".format(r.isConnected))
|
||||
r.test()
|
||||
try:
|
||||
r.init('02:46:00:00:00:07')
|
||||
except REST.UnmanagedHostError:
|
||||
print('Unmanaged host (confirmed)')
|
||||
|
||||
uuid = r.init('02:46:00:00:00:08')
|
||||
print("Notify comm:", r.notifyComm('http://172.27.0.1:8000/'))
|
||||
|
||||
print("Connected: {}".format(r.isConnected))
|
||||
|
||||
print('uuid = {}'.format(uuid))
|
||||
|
||||
# print 'Login: {}'.format(r.login('test-user'))
|
||||
# print 'Logout: {}'.format(r.logout('test-user'))
|
||||
print("Information: >>{}<<".format(r.information()))
|
||||
print("Login: >>{}<<".format(r.login('Pepito')))
|
||||
|
||||
print(r.setReady([(v.mac, v.ip) for v in operations.getNetworkInfo()]))
|
||||
print(r.log(10000, 'Test error message'))
|
||||
|
||||
|
||||
def ipcTest():
|
||||
s = ipc.ServerIPC(39188) # I have got the enterprise number for Virtual Cable. This number is not about ports, but as good as any other selection :)
|
||||
|
||||
s.start()
|
||||
|
||||
sleep(1)
|
||||
|
||||
client = ipc.ClientIPC(39188)
|
||||
client.start()
|
||||
client2 = ipc.ClientIPC(39188)
|
||||
client2.start()
|
||||
|
||||
print("Requesting information")
|
||||
client.requestInformation()
|
||||
print("Sending login info")
|
||||
client.sendLogin('user1')
|
||||
print("Sending logout info")
|
||||
client.sendLogout('mariete' * 1000)
|
||||
|
||||
print('Sending message')
|
||||
s.sendMessage(ipc.MSG_LOGOFF, None)
|
||||
s.sendMessage(ipc.MSG_MESSAGE, 'Cierra la sesión')
|
||||
s.sendMessage(33, 'invalid')
|
||||
s.sendMessage(ipc.MSG_SCRIPT, 'print "hello"')
|
||||
print('Message sent')
|
||||
|
||||
for c in (client, client2):
|
||||
print(c.getMessage())
|
||||
print(c.getMessage())
|
||||
print(c.getMessage())
|
||||
|
||||
client.stop()
|
||||
client.join()
|
||||
|
||||
s.sendMessage(ipc.MSG_LOGOFF, None)
|
||||
s.sendMessage(ipc.MSG_MESSAGE, 'Cierra la sesión')
|
||||
s.sendMessage(33, 'invalid')
|
||||
s.sendMessage(ipc.MSG_SCRIPT, 'print "hello"')
|
||||
|
||||
print(client2.getMessage())
|
||||
print(client2.getMessage())
|
||||
print(client2.getMessage())
|
||||
|
||||
client2.stop()
|
||||
s.stop()
|
||||
client2.join()
|
||||
s.join()
|
||||
|
||||
|
||||
def ipcServer():
|
||||
s = ipc.ServerIPC(39188, {'idle': 180}) # I have got the enterprise number for Virtual Cable. This number is not about ports, but as good as any other selection :)
|
||||
|
||||
s.start()
|
||||
|
||||
counter = 0
|
||||
while True:
|
||||
try:
|
||||
counter += 1
|
||||
print("Sending new message {}".format(counter))
|
||||
s.sendMessage(ipc.MSG_MESSAGE, 'This is a test message ñöitó 33.3€ {}'.format(counter))
|
||||
counter += 1
|
||||
s.sendMessage(ipc.MSG_SCRIPT, 'print "This is a test message ñöitó 33.3€ {}"'.format(counter))
|
||||
counter += 1
|
||||
s.sendMessage(ipc.MSG_LOGOFF, None)
|
||||
sleep(1)
|
||||
except:
|
||||
break
|
||||
|
||||
s.stop()
|
||||
|
||||
|
||||
def testIdle():
|
||||
for _ in range(1, 10):
|
||||
print(operations.getIdleDuration())
|
||||
sleep(1)
|
||||
|
||||
|
||||
def testServer():
|
||||
|
||||
# Disable verify warinings
|
||||
logging.getLogger("requests").setLevel(logging.ERROR)
|
||||
urllib3.disable_warnings() # @UndefinedVariable
|
||||
|
||||
s = ipc.ServerIPC(39188) # I have got the enterprise number for Virtual Cable. This number is not about ports, but as good as any other selection :)
|
||||
|
||||
s.start()
|
||||
|
||||
client = ipc.ClientIPC(39188)
|
||||
client.start()
|
||||
|
||||
while True:
|
||||
try:
|
||||
port = random.randrange(32000, 64000)
|
||||
server = httpserver.HTTPServerThread(('172.27.0.8', port), s)
|
||||
break
|
||||
except:
|
||||
pass
|
||||
|
||||
serverUrl = server.getServerUrl()
|
||||
server.start()
|
||||
|
||||
print(serverUrl)
|
||||
|
||||
res = requests.post(serverUrl + '/message', data=json.dumps({'message': 'Test message'}), headers={'content-type': 'application/json'}, verify=False)
|
||||
print(res)
|
||||
print(res.json())
|
||||
|
||||
res = requests.post(serverUrl + '/script', data=json.dumps({'script': 'import time\ntime.sleep(1)\nfor v in xrange(10): print "Hello world, this is an script"'}), headers={'content-type': 'application/json'}, verify=False)
|
||||
print(res)
|
||||
print(res.json())
|
||||
|
||||
res = requests.post(serverUrl + '/script', data=json.dumps({'script': 'print "Hello world, this is an script"', 'user': True}), headers={'content-type': 'application/json'}, verify=False)
|
||||
print(res)
|
||||
print(res.json())
|
||||
|
||||
res = requests.get(serverUrl + '/information?param1=1¶m2=2', headers={'content-type': 'application/json'}, verify=False)
|
||||
print(res)
|
||||
print(res.json())
|
||||
|
||||
print("Messages:")
|
||||
print(client.getMessage())
|
||||
print(client.getMessage())
|
||||
|
||||
# try:
|
||||
# while True:
|
||||
# Sleep(1000)
|
||||
# except:
|
||||
# pass
|
||||
|
||||
server.stop()
|
||||
s.stop()
|
||||
client.stop()
|
||||
|
||||
|
||||
def testRemote():
|
||||
serverUrl = "https://172.27.0.208:52562/633a1245873848b7b4017c23283bc195"
|
||||
print(serverUrl)
|
||||
|
||||
res = requests.post(serverUrl + '/message', data=json.dumps({'message': 'Test message'}), headers={'content-type': 'application/json'}, verify=False)
|
||||
print(res)
|
||||
print(res.json())
|
||||
|
||||
res = requests.post(serverUrl + '/script', data=json.dumps({'script': 'import time\ntime.sleep(1)\nfor v in xrange(10): print "Hello world, this is an script"'}), headers={'content-type': 'application/json'}, verify=False)
|
||||
print(res)
|
||||
print(res.json())
|
||||
|
||||
res = requests.post(serverUrl + '/script', data=json.dumps({'script': 'print "Hello world, this is an script"', 'user': True}), headers={'content-type': 'application/json'}, verify=False)
|
||||
print(res)
|
||||
print(res.json())
|
||||
|
||||
res = requests.get(serverUrl + '/information?param1=1¶m2=2', headers={'content-type': 'application/json'}, verify=False)
|
||||
print(res)
|
||||
print(res.json())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# ipcServer()
|
||||
# ipcTest()
|
||||
testRest()
|
||||
# testIdle()
|
||||
# testServer()
|
||||
# testRemote()
|
||||
|
@ -1,255 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 201 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
|
||||
# pylint: disable-msg=E1101,W0703
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import requests
|
||||
import logging
|
||||
import json
|
||||
import uuid
|
||||
import six
|
||||
import warnings
|
||||
|
||||
from udsactor.log import logger
|
||||
|
||||
from udsactor import VERSION
|
||||
from .utils import exceptionToMessage
|
||||
|
||||
VERIFY_CERT = False
|
||||
|
||||
|
||||
class RESTError(Exception):
|
||||
ERRCODE = 0
|
||||
|
||||
|
||||
class ConnectionError(RESTError):
|
||||
ERRCODE = -1
|
||||
|
||||
|
||||
# Errors ""raised"" from broker
|
||||
class InvalidKeyError(RESTError):
|
||||
ERRCODE = 1
|
||||
|
||||
|
||||
class UnmanagedHostError(RESTError):
|
||||
ERRCODE = 2
|
||||
|
||||
|
||||
class UserServiceNotFoundError(RESTError):
|
||||
ERRCODE = 3
|
||||
|
||||
|
||||
class OsManagerError(RESTError):
|
||||
ERRCODE = 4
|
||||
|
||||
|
||||
# Disable warnings log messages
|
||||
try:
|
||||
import urllib3 # @UnusedImport @UnresolvedImport
|
||||
except Exception:
|
||||
from requests.packages import urllib3 # @Reimport @UnresolvedImport
|
||||
|
||||
try:
|
||||
urllib3.disable_warnings() # @UndefinedVariable
|
||||
warnings.simplefilter("ignore")
|
||||
except Exception:
|
||||
pass # In fact, isn't too important, but will log warns to logging file
|
||||
|
||||
|
||||
def ensureResultIsOk(result):
|
||||
if 'error' not in result:
|
||||
return
|
||||
|
||||
for i in (InvalidKeyError, UnmanagedHostError, UserServiceNotFoundError, OsManagerError):
|
||||
if result['error'] == i.ERRCODE:
|
||||
raise i(result['result'])
|
||||
|
||||
err = RESTError(result['result'])
|
||||
err.ERRCODE = result['error']
|
||||
raise err
|
||||
|
||||
|
||||
class Api(object):
|
||||
|
||||
def __init__(self, host, masterKey, ssl):
|
||||
self.host = host
|
||||
self.masterKey = masterKey
|
||||
self.useSSL = True if ssl else False
|
||||
self.uuid = None
|
||||
self.mac = None
|
||||
self.url = "{}://{}/rest/actor/".format(('http', 'https')[self.useSSL], self.host)
|
||||
self.idle = None
|
||||
self.maxSession = None
|
||||
self.secretKey = six.text_type(uuid.uuid4())
|
||||
try:
|
||||
self.newerRequestLib = requests.__version__.split('.')[0] >= '1' # @UndefinedVariable
|
||||
except Exception:
|
||||
self.newerRequestLib = False # I no version, guess this must be an old requests
|
||||
|
||||
# Disable logging requests messages except for errors, ...
|
||||
logging.getLogger("requests").setLevel(logging.CRITICAL)
|
||||
# Tries to disable all warnings
|
||||
try:
|
||||
warnings.simplefilter("ignore") # Disables all warnings
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _getUrl(self, method, key=None, ids=None):
|
||||
url = self.url + method
|
||||
params = []
|
||||
if key is not None:
|
||||
params.append('key=' + key)
|
||||
if ids is not None:
|
||||
params.append('id=' + ids)
|
||||
params.append('version=' + VERSION)
|
||||
|
||||
if len(params) > 0:
|
||||
url += '?' + '&'.join(params)
|
||||
|
||||
return url
|
||||
|
||||
def _request(self, url, data=None):
|
||||
try:
|
||||
if data is None:
|
||||
# Old requests version does not support verify, but they do not checks ssl certificate by default
|
||||
if self.newerRequestLib:
|
||||
r = requests.get(url, verify=VERIFY_CERT)
|
||||
else:
|
||||
logger.debug('Requesting with old')
|
||||
r = requests.get(url) # Always ignore certs??
|
||||
else:
|
||||
if data == '':
|
||||
data = '{"dummy": true}' # Ensures no proxy rewrites POST as GET because body is empty...
|
||||
if self.newerRequestLib:
|
||||
r = requests.post(url, data=data, headers={'content-type': 'application/json'}, verify=VERIFY_CERT)
|
||||
else:
|
||||
logger.debug('Requesting with old')
|
||||
r = requests.post(url, data=data, headers={'content-type': 'application/json'})
|
||||
|
||||
# From versions of requests, content maybe bytes or str. We need str for json.loads
|
||||
content = r.content
|
||||
if not isinstance(content, six.text_type):
|
||||
content = content.decode('utf8')
|
||||
r = json.loads(content) # Using instead of r.json() to make compatible with oooold rquests lib versions
|
||||
except requests.exceptions.RequestException as e:
|
||||
raise ConnectionError(e)
|
||||
except Exception as e:
|
||||
raise ConnectionError(exceptionToMessage(e))
|
||||
|
||||
ensureResultIsOk(r)
|
||||
|
||||
return r
|
||||
|
||||
@property
|
||||
def isConnected(self):
|
||||
return self.uuid is not None
|
||||
|
||||
def test(self):
|
||||
url = self._getUrl('test', self.masterKey)
|
||||
return self._request(url)['result']
|
||||
|
||||
def init(self, ids):
|
||||
'''
|
||||
Ids is a comma separated values indicating MAC=ip
|
||||
Server returns:
|
||||
uuid, mac
|
||||
Optionally can return an third parameter, that is max "idle" request time
|
||||
'''
|
||||
logger.debug('Invoking init')
|
||||
url = self._getUrl('init', key=self.masterKey, ids=ids)
|
||||
res = self._request(url)['result']
|
||||
logger.debug('Got response parameters: {}'.format(res))
|
||||
self.uuid, self.mac = res[0:2]
|
||||
# Optional idle parameter
|
||||
try:
|
||||
self.idle = int(res[2])
|
||||
if self.idle < 30:
|
||||
self.idle = None # No values under 30 seconds are allowed :)
|
||||
except Exception:
|
||||
self.idle = None
|
||||
|
||||
return self.uuid
|
||||
|
||||
def postMessage(self, msg, data, processData=True):
|
||||
logger.debug('Invoking post message {} with data {}'.format(msg, data))
|
||||
|
||||
if self.uuid is None:
|
||||
raise ConnectionError('REST api has not been initialized')
|
||||
|
||||
if processData:
|
||||
if data and not isinstance(data, six.text_type):
|
||||
data = data.decode('utf8')
|
||||
data = json.dumps({'data': data})
|
||||
url = self._getUrl('/'.join([self.uuid, msg]))
|
||||
return self._request(url, data)['result']
|
||||
|
||||
def notifyComm(self, url):
|
||||
logger.debug('Notifying comms {}'.format(url))
|
||||
return self.postMessage('notifyComms', url)
|
||||
|
||||
def login(self, username):
|
||||
logger.debug('Notifying login {}'.format(username))
|
||||
return self.postMessage('login', username)
|
||||
|
||||
def logout(self, username):
|
||||
logger.debug('Notifying logout {}'.format(username))
|
||||
return self.postMessage('logout', username)
|
||||
|
||||
def information(self):
|
||||
logger.debug('Requesting information'.format())
|
||||
return self.postMessage('information', '')
|
||||
|
||||
def setReady(self, ipsInfo, hostName=None):
|
||||
logger.debug('Notifying readyness: {}'.format(ipsInfo))
|
||||
# data = ','.join(['{}={}'.format(v[0], v[1]) for v in ipsInfo])
|
||||
data = {
|
||||
'ips': ipsInfo,
|
||||
'hostname': hostName
|
||||
}
|
||||
return self.postMessage('ready', data)
|
||||
|
||||
def notifyIpChanges(self, ipsInfo):
|
||||
logger.debug('Notifying ip changes: {}'.format(ipsInfo))
|
||||
data = ','.join(['{}={}'.format(v[0], v[1]) for v in ipsInfo])
|
||||
return self.postMessage('ip', data)
|
||||
|
||||
def getTicket(self, ticketId, secure=False):
|
||||
url = self._getUrl('ticket/' + ticketId, self.masterKey) + "&secure={}".format('1' if secure else '0')
|
||||
return self._request(url)['result']
|
||||
|
||||
|
||||
def log(self, logLevel, message):
|
||||
data = json.dumps({'message': message, 'level': logLevel})
|
||||
return self.postMessage('log', data, processData=False)
|
||||
|
@ -1,53 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# On centos, old six release does not includes byte2int, nor six.PY2
|
||||
import six
|
||||
|
||||
VERSION = '3.0.0'
|
||||
|
||||
__title__ = 'udsactor'
|
||||
__version__ = VERSION
|
||||
__build__ = 0x010756
|
||||
__author__ = 'Adolfo Gómez <dkmaster@dkmon.com>'
|
||||
__license__ = "BSD 3-clause"
|
||||
__copyright__ = "Copyright 2014-2018 VirtualCable S.L.U."
|
||||
|
||||
if not hasattr(six, 'byte2int'):
|
||||
if six.PY3:
|
||||
import operator
|
||||
six.byte2int = operator.itemgetter(0)
|
||||
else:
|
||||
def _byte2int(bs):
|
||||
return ord(bs[0])
|
||||
six.byte2int = _byte2int
|
@ -1,101 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
|
||||
from tempfile import gettempdir
|
||||
from os.path import exists, join
|
||||
|
||||
CERTFILE = 'UDSActor.pem'
|
||||
|
||||
|
||||
def createSelfSignedCert(force=False):
|
||||
|
||||
certFile = join(gettempdir(), CERTFILE)
|
||||
|
||||
if exists(certFile) and not force:
|
||||
return certFile
|
||||
|
||||
certData = '''-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCb50K3mIznNklz
|
||||
yVAD7xSQOSJQ6+NPXj7U9/4zLZ+TvmbQ7RqUUsxbfxHbeRnoYTWV2nKk4+tHqmvz
|
||||
ujLSS/loFhTSMqtrLn7rowSYJoQhKOUkAiQlWkqCfItWgL5pJopDpNHFul9Rn3ds
|
||||
PMWQTiGeUNR4Y3RnBhr1Q1BsqAzf4m6zFUmgLPPmVLdF4uJ3Tuz8TSy2gWLs5aSr
|
||||
5do4WamwUfYjRSVMJECmwjUM4rQ8SQgg0sHBeBuDUGNBvBQFac1G7qUcMReeu8Zr
|
||||
DUtMsXma/l4rA8NB5CRmTrQbTBF4l+jb2BDFebDqDUK1Oqs9X35yOQfDOAFYHiix
|
||||
PX0IsXOZAgMBAAECggEBAJi3000RrIUZUp6Ph0gzPMuCjDEEwWiQA7CPNX1gpb8O
|
||||
dp0WhkDhUroWIaICYPSXtOwUTtVjRqivMoxPy1Thg3EIoGC/rdeSdlXRHMEGicwJ
|
||||
yVyalFnatr5Xzg5wkxVh4XMd0zeDt7e3JD7s0QLo5lm1CEzd77qz6lhzFic5/1KX
|
||||
bzdULtTlq60dazg2hEbcS4OmM1UMCtRVDAsOIUIZPL0M9j1C1d1iEdYnh2xshKeG
|
||||
/GOfo95xsgdMlGjtv3hUT5ryKVoEsu+36rGb4VfhPfUvvoVbRx5QZpW+QvxaYh5E
|
||||
Fi0JEROozFwG31Y++8El7J3yQko8cFBa1lYYUwwpNAECgYEAykT+GiM2YxJ4uVF1
|
||||
OoKiE9BD53i0IG5j87lGPnWqzEwYBwnqjEKDTou+uzMGz3MDV56UEFNho7wUWh28
|
||||
LpEkjJB9QgbsugjxIBr4JoL/rYk036e/6+U8I95lvYWrzb+rBMIkRDYI7kbQD/mQ
|
||||
piYUpuCkTymNAu2RisK6bBzJslkCgYEAxVE23OQvkCeOV8hJNPZGpJ1mDS+TiOow
|
||||
oOScMZmZpail181eYbAfMsCr7ri812lSj98NvA2GNVLpddil6LtS1cQ5p36lFBtV
|
||||
xQUMZiFz4qVbEak+izL+vPaev/mXXsOcibAIQ+qI/0txFpNhJjpaaSy6vRCBYFmc
|
||||
8pgSoBnBI0ECgYAUKCn2atnpp5aWSTLYgNosBU4vDA1PShD14dnJMaqyr0aZtPhF
|
||||
v/8b3btFJoGgPMLxgWEZ+2U4ju6sSFhPf7FXvLJu2QfQRkHZRDbEh7t5DLpTK4Fp
|
||||
va9vl6Ml7uM/HsGpOLuqfIQJUs87OFCc7iCSvMJDDU37I7ekT2GKkpfbCQKBgBrE
|
||||
0NeY0WcSJrp7/oqD2sOcYurpCG/rrZs2SIZmGzUhMxaa0vIXzbO59dlWELB8pmnE
|
||||
Tf20K//x9qA5OxDe0PcVPukdQlH+/1zSOYNliG44FqnHtyd1TJ/gKVtMBiAiE4uO
|
||||
aSClod5Yosf4SJbCFd/s5Iyfv52NqsAyp1w3Aj/BAoGAVCnEiGUfyHlIR+UH4zZW
|
||||
GXJMeqdZLfcEIszMxLePkml4gUQhoq9oIs/Kw+L1DDxUwzkXN4BNTlFbOSu9gzK1
|
||||
dhuIUGfS6RPL88U+ivC3A0y2jT43oUMqe3hiRt360UQ1GXzp2dMnR9odSRB1wHoO
|
||||
IOjEBZ8341/c9ZHc5PCGAG8=
|
||||
-----END PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIID7zCCAtegAwIBAgIJAIrEIthCfxUCMA0GCSqGSIb3DQEBCwUAMIGNMQswCQYD
|
||||
VQQGEwJFUzEPMA0GA1UECAwGTWFkcmlkMREwDwYDVQQHDAhBbGNvcmNvbjEMMAoG
|
||||
A1UECgwDVURTMQ4wDAYDVQQLDAVBY3RvcjESMBAGA1UEAwwJVURTIEFjdG9yMSgw
|
||||
JgYJKoZIhvcNAQkBFhlzdXBwb3J0QHVkc2VudGVycHJpc2UuY29tMB4XDTE0MTAy
|
||||
NjIzNDEyNFoXDTI0MTAyMzIzNDEyNFowgY0xCzAJBgNVBAYTAkVTMQ8wDQYDVQQI
|
||||
DAZNYWRyaWQxETAPBgNVBAcMCEFsY29yY29uMQwwCgYDVQQKDANVRFMxDjAMBgNV
|
||||
BAsMBUFjdG9yMRIwEAYDVQQDDAlVRFMgQWN0b3IxKDAmBgkqhkiG9w0BCQEWGXN1
|
||||
cHBvcnRAdWRzZW50ZXJwcmlzZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
|
||||
ggEKAoIBAQCb50K3mIznNklzyVAD7xSQOSJQ6+NPXj7U9/4zLZ+TvmbQ7RqUUsxb
|
||||
fxHbeRnoYTWV2nKk4+tHqmvzujLSS/loFhTSMqtrLn7rowSYJoQhKOUkAiQlWkqC
|
||||
fItWgL5pJopDpNHFul9Rn3dsPMWQTiGeUNR4Y3RnBhr1Q1BsqAzf4m6zFUmgLPPm
|
||||
VLdF4uJ3Tuz8TSy2gWLs5aSr5do4WamwUfYjRSVMJECmwjUM4rQ8SQgg0sHBeBuD
|
||||
UGNBvBQFac1G7qUcMReeu8ZrDUtMsXma/l4rA8NB5CRmTrQbTBF4l+jb2BDFebDq
|
||||
DUK1Oqs9X35yOQfDOAFYHiixPX0IsXOZAgMBAAGjUDBOMB0GA1UdDgQWBBRShS90
|
||||
5lJTNvYPIEqP3GxWwG5iiDAfBgNVHSMEGDAWgBRShS905lJTNvYPIEqP3GxWwG5i
|
||||
iDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAU0Sp4gXhQmRVzq+7+
|
||||
vRFUkQuPj4Ga/d9r5Wrbg3hck3+5pwe9/7APoq0P/M0DBhQpiJKjrD6ydUevC+Y/
|
||||
43ZOJPhMlNw0o6TdQxOkX6FDwQanLLs7sfvJvqtVzYn3nuRFKT3dvl7Zg44QMw2M
|
||||
ay42q59fAcpB4LaDx/i7gOYSS5eca3lYW7j7YSr/+ozXK2KlgUkuCUHN95lOq+dF
|
||||
trmV9mjzM4CNPZqKSE7kpHRywgrXGPCO000NvEGSYf82AtgRSFKiU8NWLQSEPdcB
|
||||
k//2dsQZw2cRZ8DrC2B6Tb3M+3+CA6wVyqfqZh1SZva3LfGvq/C+u+ItguzPqNpI
|
||||
xtvM
|
||||
-----END CERTIFICATE-----'''
|
||||
with open(certFile, "wt") as f:
|
||||
f.write(certData)
|
||||
|
||||
return certFile
|
@ -1,233 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from udsactor.log import logger
|
||||
from udsactor import utils
|
||||
from udsactor.certs import createSelfSignedCert
|
||||
from udsactor.scriptThread import ScriptExecutorThread
|
||||
|
||||
import threading
|
||||
import string
|
||||
import random
|
||||
import json
|
||||
import six
|
||||
from six.moves import socketserver # @UnresolvedImport, pylint: disable=import-error
|
||||
from six.moves import BaseHTTPServer # @UnresolvedImport, pylint: disable=import-error
|
||||
import time
|
||||
|
||||
import ssl
|
||||
|
||||
startTime = time.time()
|
||||
|
||||
|
||||
class HTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
protocol_version = 'HTTP/1.0'
|
||||
server_version = 'UDS Actor Server'
|
||||
sys_version = ''
|
||||
|
||||
uuid = None
|
||||
service = None
|
||||
lock = threading.Lock()
|
||||
|
||||
def sendJsonError(self, code, message):
|
||||
self.send_response(code)
|
||||
self.send_header('Content-type', 'application/json')
|
||||
self.end_headers()
|
||||
self.wfile.write(json.dumps({'error': message}))
|
||||
return
|
||||
|
||||
def sendJsonResponse(self, data):
|
||||
self.send_response(200)
|
||||
data = json.dumps(data)
|
||||
self.send_header('Content-type', 'application/json')
|
||||
self.send_header('Content-Length', len(data))
|
||||
self.end_headers()
|
||||
# Send the html message
|
||||
self.wfile.write(data)
|
||||
|
||||
def do_GET(self):
|
||||
# Very simple path & params splitter
|
||||
path = self.path.split('?')[0][1:].split('/')
|
||||
try:
|
||||
params = dict((v.split('=') for v in self.path.split('?')[1].split('&')))
|
||||
except Exception:
|
||||
params = {}
|
||||
|
||||
if path[0] != HTTPServerHandler.uuid:
|
||||
self.sendJsonError(403, 'Forbidden')
|
||||
return
|
||||
|
||||
if len(path) != 2:
|
||||
self.sendJsonResponse("UDS Actor has been running for {} seconds".format(time.time() - startTime))
|
||||
return
|
||||
|
||||
try:
|
||||
operation = getattr(self, 'get_' + path[1])
|
||||
result = operation(params) # Protect not POST methods
|
||||
except AttributeError:
|
||||
self.sendJsonError(404, 'Method not found')
|
||||
return
|
||||
except Exception as e:
|
||||
logger.error('Got exception executing GET {}: {}'.format(path[1], utils.toUnicode(e.message)))
|
||||
self.sendJsonError(500, str(e))
|
||||
return
|
||||
|
||||
self.sendJsonResponse(result)
|
||||
|
||||
def do_POST(self):
|
||||
path = self.path.split('?')[0][1:].split('/')
|
||||
if path[0] != HTTPServerHandler.uuid:
|
||||
self.sendJsonError(403, 'Forbidden')
|
||||
return
|
||||
|
||||
if len(path) != 2:
|
||||
self.sendJsonError(400, 'Invalid request')
|
||||
return
|
||||
|
||||
try:
|
||||
HTTPServerHandler.lock.acquire()
|
||||
length = int(self.headers.get('content-length'))
|
||||
content = self.rfile.read(length).decode('utf8')
|
||||
logger.debug('length: {}, content >>{}<<'.format(length, content))
|
||||
params = json.loads(content)
|
||||
|
||||
operation = getattr(self, 'post_' + path[1])
|
||||
result = operation(params) # Protect not POST methods
|
||||
except AttributeError:
|
||||
self.sendJsonError(404, 'Method not found')
|
||||
return
|
||||
except Exception as e:
|
||||
logger.error('Got exception executing POST {}: {}'.format(path[1], utils.toUnicode(e.message)))
|
||||
self.sendJsonError(500, str(e))
|
||||
return
|
||||
finally:
|
||||
HTTPServerHandler.lock.release()
|
||||
|
||||
self.sendJsonResponse(result)
|
||||
|
||||
def post_logoff(self, params):
|
||||
logger.debug('Sending LOGOFF to clients')
|
||||
HTTPServerHandler.service.ipc.sendLoggofMessage()
|
||||
return 'ok'
|
||||
|
||||
# Alias
|
||||
post_logout = post_logoff
|
||||
|
||||
def post_message(self, params):
|
||||
logger.debug('Sending MESSAGE to clients')
|
||||
if 'message' not in params:
|
||||
raise Exception('Invalid message parameters')
|
||||
HTTPServerHandler.service.ipc.sendMessageMessage(params['message'])
|
||||
return 'ok'
|
||||
|
||||
def post_script(self, params):
|
||||
logger.debug('Received script: {}'.format(params))
|
||||
if 'script' not in params:
|
||||
raise Exception('Invalid script parameters')
|
||||
if 'user' in params:
|
||||
logger.debug('Sending SCRIPT to clients')
|
||||
HTTPServerHandler.service.ipc.sendScriptMessage(params['script'])
|
||||
else:
|
||||
# Execute script at server space, that is, here
|
||||
# as a parallel thread
|
||||
th = ScriptExecutorThread(params['script'])
|
||||
th.start()
|
||||
return 'ok'
|
||||
|
||||
def post_preConnect(self, params):
|
||||
logger.debug('Received Pre connection')
|
||||
if 'user' not in params or 'protocol' not in params:
|
||||
raise Exception('Invalid preConnect parameters')
|
||||
return HTTPServerHandler.service.preConnect(params.get('user'), params.get('protocol'))
|
||||
|
||||
def get_information(self, params):
|
||||
# TODO: Return something useful? :)
|
||||
return 'Up and running'
|
||||
|
||||
def get_uuid(self, params):
|
||||
return self.service.api.uuid
|
||||
|
||||
def log_error(self, fmt, *args):
|
||||
logger.error('HTTP ' + fmt % args)
|
||||
|
||||
def log_message(self, fmt, *args):
|
||||
logger.info('HTTP ' + fmt % args)
|
||||
|
||||
|
||||
class HTTPServerThread(threading.Thread):
|
||||
def __init__(self, address, service):
|
||||
super(self.__class__, self).__init__()
|
||||
|
||||
if HTTPServerHandler.uuid is None:
|
||||
HTTPServerHandler.uuid = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(48))
|
||||
|
||||
self.certFile = createSelfSignedCert()
|
||||
HTTPServerHandler.service = service
|
||||
|
||||
self.initiateServer(address)
|
||||
|
||||
def getPort(self):
|
||||
return self.address[1]
|
||||
|
||||
def getIp(self):
|
||||
return self.address[0]
|
||||
|
||||
def initiateServer(self, address):
|
||||
self.address = (address[0], address[1]) # Copy address & keep it for future reference...
|
||||
|
||||
addr = ('0.0.0.0', address[1]) # Adapt to listen on 0.0.0.0
|
||||
|
||||
self.server = socketserver.TCPServer(addr, HTTPServerHandler)
|
||||
self.server.socket = ssl.wrap_socket(self.server.socket, certfile=self.certFile, server_side=True)
|
||||
|
||||
def getServerUrl(self):
|
||||
return 'https://{}:{}/{}'.format(self.getIp(), self.getPort(), HTTPServerHandler.uuid)
|
||||
|
||||
def stop(self):
|
||||
logger.debug('Stopping REST Service')
|
||||
self.server.shutdown()
|
||||
|
||||
def restart(self, address=None):
|
||||
|
||||
if address is None:
|
||||
# address = self.server.server_address
|
||||
address = self.address
|
||||
|
||||
self.address = (address[0], self.address[1]) # Copy address & keep it for future reference, port is never changed once assigned on init
|
||||
|
||||
# Listening on 0.0.0.0, does not need to restart listener..
|
||||
# self.stop()
|
||||
# self.initiateServer(address)
|
||||
|
||||
def run(self):
|
||||
self.server.serve_forever()
|
@ -1,438 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import socket
|
||||
import threading
|
||||
import sys
|
||||
import traceback
|
||||
import pickle
|
||||
import errno
|
||||
import time
|
||||
import six
|
||||
|
||||
from udsactor.utils import toUnicode
|
||||
from udsactor.log import logger
|
||||
|
||||
# The IPC Server will wait for connections from clients
|
||||
# Clients will open socket, and wait for data from server
|
||||
# The messages sent (from server) will be the following (subject to future changes):
|
||||
# Message_id Data Action
|
||||
# ------------ -------- --------------------------
|
||||
# MSG_LOGOFF None Logout user from session
|
||||
# MSG_MESSAGE message,level Display a message with level (INFO, WARN, ERROR, FATAL) # TODO: Include level, right now only has message
|
||||
# MSG_SCRIPT python script Execute an specific python script INSIDE CLIENT environment (this messages is not sent right now)
|
||||
# The messages received (sent from client) will be the following:
|
||||
# Message_id Data Action
|
||||
# ------------ -------- --------------------------
|
||||
# REQ_LOGOUT Logout user from session
|
||||
# REQ_INFORMATION None Request information from ipc server (maybe configuration parameters in a near future)
|
||||
# REQ_LOGIN python script Execute an specific python script INSIDE CLIENT environment (this messages is not sent right now)
|
||||
#
|
||||
# All messages are in the form:
|
||||
# BYTE
|
||||
# 0 1-2 3 4 ...
|
||||
# MSG_ID DATA_LENGTH (little endian) Data (can be 0 length)
|
||||
# With a previos "MAGIC" header in fron of each message
|
||||
|
||||
MSG_LOGOFF = 0xA1
|
||||
MSG_MESSAGE = 0xB2
|
||||
MSG_SCRIPT = 0xC3
|
||||
MSG_INFORMATION = 0xD4
|
||||
MSG_TICKET = 0x90
|
||||
|
||||
# Request messages
|
||||
REQ_INFORMATION = MSG_INFORMATION
|
||||
REQ_LOGIN = 0xE5
|
||||
REQ_LOGOUT = MSG_LOGOFF
|
||||
REQ_TICKET = MSG_TICKET
|
||||
VALID_REQUESTS = (REQ_INFORMATION, REQ_LOGIN, REQ_LOGOUT, REQ_TICKET)
|
||||
|
||||
VALID_MESSAGES = (MSG_LOGOFF, MSG_MESSAGE, MSG_SCRIPT, MSG_INFORMATION)
|
||||
|
||||
REQ_INFORMATION = 0xAA
|
||||
|
||||
# Reverse msgs dict for debugging
|
||||
REV_DICT = {
|
||||
MSG_LOGOFF: 'MSG_LOGOFF',
|
||||
MSG_MESSAGE: 'MSG_MESSAGE',
|
||||
MSG_SCRIPT: 'MSG_SCRIPT',
|
||||
MSG_INFORMATION: 'MSG_INFORMATION',
|
||||
REQ_TICKET: 'REQ_TICKET',
|
||||
REQ_LOGIN: 'REQ_LOGIN',
|
||||
REQ_LOGOUT: 'REQ_LOGOUT'
|
||||
}
|
||||
|
||||
MAGIC = b'\x55\x44\x53\x00' # UDS in hexa with a padded 0 to the right
|
||||
|
||||
|
||||
# Allows notifying login/logout from client for linux platform
|
||||
ALLOW_LOG_METHODS = sys.platform != 'win32'
|
||||
|
||||
|
||||
# States for client processor
|
||||
ST_SECOND_BYTE = 0x01
|
||||
ST_RECEIVING = 0x02
|
||||
ST_PROCESS_MESSAGE = 0x02
|
||||
|
||||
|
||||
class ClientProcessor(threading.Thread):
|
||||
def __init__(self, parent, clientSocket):
|
||||
super(ClientProcessor, self).__init__()
|
||||
self.parent = parent
|
||||
self.clientSocket = clientSocket
|
||||
self.running = False
|
||||
self.messages = six.moves.queue.Queue(32) # @UndefinedVariable
|
||||
|
||||
def stop(self):
|
||||
logger.debug('Stoping client processor')
|
||||
self.running = False
|
||||
|
||||
def processRequest(self, msg, data):
|
||||
logger.debug('Got Client message {}={}'.format(msg, REV_DICT.get(msg)))
|
||||
if self.parent.clientMessageProcessor is not None:
|
||||
self.parent.clientMessageProcessor(msg, data)
|
||||
|
||||
def run(self):
|
||||
self.running = True
|
||||
self.clientSocket.setblocking(0)
|
||||
|
||||
state = None
|
||||
recv_msg = None
|
||||
recv_data = None
|
||||
while self.running:
|
||||
try:
|
||||
counter = 1024
|
||||
while counter > 0: # So we process at least the incoming queue every XX bytes readed
|
||||
counter -= 1
|
||||
b = self.clientSocket.recv(1)
|
||||
if b == b'':
|
||||
# Client disconnected
|
||||
self.running = False
|
||||
self.processRequest(REQ_LOGOUT, 'CLIENT_CONNECTION_LOST')
|
||||
break
|
||||
buf = six.byte2int(b) # Empty buffer, this is set as non-blocking
|
||||
if state is None:
|
||||
if buf in VALID_REQUESTS:
|
||||
logger.debug('State set to {}'.format(buf))
|
||||
state = buf
|
||||
recv_msg = buf
|
||||
continue # Get next byte
|
||||
else:
|
||||
logger.debug('Got unexpected data {}'.format(buf))
|
||||
elif state in VALID_REQUESTS:
|
||||
logger.debug('First length byte is {}'.format(buf))
|
||||
msg_len = buf
|
||||
state = ST_SECOND_BYTE
|
||||
continue
|
||||
elif state == ST_SECOND_BYTE:
|
||||
msg_len += buf << 8
|
||||
logger.debug('Second length byte is {}, len is {}'.format(buf, msg_len))
|
||||
if msg_len == 0:
|
||||
self.processRequest(recv_msg, None)
|
||||
state = None
|
||||
break
|
||||
state = ST_RECEIVING
|
||||
recv_data = b''
|
||||
continue
|
||||
elif state == ST_RECEIVING:
|
||||
recv_data += six.int2byte(buf)
|
||||
msg_len -= 1
|
||||
if msg_len == 0:
|
||||
self.processRequest(recv_msg, recv_data)
|
||||
recv_data = None
|
||||
state = None
|
||||
break
|
||||
else:
|
||||
logger.debug('Got invalid message from request: {}, state: {}'.format(buf, state))
|
||||
except socket.error as e:
|
||||
# If no data is present, no problem at all, pass to check messages
|
||||
pass
|
||||
except Exception as e:
|
||||
tb = traceback.format_exc()
|
||||
logger.error('Error: {}, trace: {}'.format(e, tb))
|
||||
|
||||
if self.running is False:
|
||||
break
|
||||
|
||||
try:
|
||||
msg = self.messages.get(block=True, timeout=1)
|
||||
except six.moves.queue.Empty: # No message got in time @UndefinedVariable
|
||||
continue
|
||||
|
||||
logger.debug('Got message {}={}'.format(msg, REV_DICT.get(msg)))
|
||||
|
||||
try:
|
||||
m = msg[1] if msg[1] is not None else b''
|
||||
ln = len(m)
|
||||
data = MAGIC + six.int2byte(msg[0]) + six.int2byte(ln & 0xFF) + six.int2byte(ln >> 8) + m
|
||||
try:
|
||||
self.clientSocket.sendall(data)
|
||||
except socket.error as e:
|
||||
# Send data error
|
||||
logger.debug('Socket connection is no more available: {}'.format(e.args))
|
||||
self.running = False
|
||||
except Exception as e:
|
||||
logger.error('Invalid message in queue: {}'.format(e))
|
||||
|
||||
logger.debug('Client processor stopped')
|
||||
try:
|
||||
self.clientSocket.close()
|
||||
except Exception:
|
||||
pass # If can't close, nothing happens, just end thread
|
||||
|
||||
|
||||
class ServerIPC(threading.Thread):
|
||||
|
||||
def __init__(self, listenPort, clientMessageProcessor=None):
|
||||
super(ServerIPC, self).__init__()
|
||||
self.port = listenPort
|
||||
self.running = False
|
||||
self.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self.threads = []
|
||||
self.clientMessageProcessor = clientMessageProcessor
|
||||
|
||||
def stop(self):
|
||||
logger.debug('Stopping Server IPC')
|
||||
self.running = False
|
||||
for t in self.threads:
|
||||
t.stop()
|
||||
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect(('localhost', self.port))
|
||||
self.serverSocket.close()
|
||||
|
||||
for t in self.threads:
|
||||
t.join()
|
||||
|
||||
def sendMessage(self, msgId, msgData):
|
||||
'''
|
||||
Notify message to all listening threads
|
||||
'''
|
||||
logger.debug('Sending message {}({}),{} to all clients'.format(msgId, REV_DICT.get(msgId), msgData))
|
||||
|
||||
# Convert to bytes so length is correctly calculated
|
||||
if isinstance(msgData, six.text_type):
|
||||
msgData = msgData.encode('utf8')
|
||||
|
||||
for t in self.threads:
|
||||
if t.isAlive():
|
||||
logger.debug('Sending to {}'.format(t))
|
||||
t.messages.put((msgId, msgData))
|
||||
|
||||
def sendLoggofMessage(self):
|
||||
self.sendMessage(MSG_LOGOFF, '')
|
||||
|
||||
def sendMessageMessage(self, message):
|
||||
self.sendMessage(MSG_MESSAGE, message)
|
||||
|
||||
def sendScriptMessage(self, script):
|
||||
self.sendMessage(MSG_SCRIPT, script)
|
||||
|
||||
def sendInformationMessage(self, info):
|
||||
self.sendMessage(MSG_INFORMATION, pickle.dumps(info))
|
||||
|
||||
# This one is the only one dumped in json, be care with this!!
|
||||
def sendTicketMessage(self, ticketData):
|
||||
self.sendMessage(MSG_TICKET, json.dumps(ticketData))
|
||||
|
||||
def cleanupFinishedThreads(self):
|
||||
'''
|
||||
Cleans up current threads list
|
||||
'''
|
||||
aliveThreads = []
|
||||
for t in self.threads:
|
||||
if t.isAlive():
|
||||
logger.debug('Thread {} is alive'.format(t))
|
||||
aliveThreads.append(t)
|
||||
self.threads[:] = aliveThreads
|
||||
|
||||
def run(self):
|
||||
self.running = True
|
||||
|
||||
self.serverSocket.bind(('localhost', self.port))
|
||||
self.serverSocket.setblocking(1)
|
||||
self.serverSocket.listen(4)
|
||||
|
||||
while True:
|
||||
try:
|
||||
(clientSocket, address) = self.serverSocket.accept()
|
||||
# Stop processing if thread is mean to stop
|
||||
if self.running is False:
|
||||
break
|
||||
logger.debug('Got connection from {}'.format(address))
|
||||
|
||||
self.cleanupFinishedThreads() # House keeping
|
||||
|
||||
logger.debug('Starting new thread, current: {}'.format(self.threads))
|
||||
t = ClientProcessor(self, clientSocket)
|
||||
self.threads.append(t)
|
||||
t.start()
|
||||
except Exception as e:
|
||||
logger.error('Got an exception on Server ipc thread: {}'.format(e))
|
||||
|
||||
|
||||
class ClientIPC(threading.Thread):
|
||||
def __init__(self, listenPort):
|
||||
super(ClientIPC, self).__init__()
|
||||
self.port = listenPort
|
||||
self.running = False
|
||||
self.clientSocket = None
|
||||
self.messages = six.moves.queue.Queue(32) # @UndefinedVariable
|
||||
|
||||
self.connect()
|
||||
|
||||
def stop(self):
|
||||
self.running = False
|
||||
|
||||
def getMessage(self):
|
||||
while self.running:
|
||||
try:
|
||||
return self.messages.get(timeout=1)
|
||||
except six.moves.queue.Empty: # @UndefinedVariable
|
||||
continue
|
||||
|
||||
return None
|
||||
|
||||
def sendRequestMessage(self, msg, data=None):
|
||||
logger.debug('Sending request for msg: {}({}), {}'.format(msg, REV_DICT.get(msg), data))
|
||||
if data is None:
|
||||
data = b''
|
||||
|
||||
if isinstance(data, six.text_type): # Convert to bytes if necessary
|
||||
data = data.encode('utf-8')
|
||||
|
||||
ln = len(data)
|
||||
msg = six.int2byte(msg) + six.int2byte(ln & 0xFF) + six.int2byte(ln >> 8) + data
|
||||
self.clientSocket.sendall(msg)
|
||||
|
||||
def requestInformation(self):
|
||||
self.sendRequestMessage(REQ_INFORMATION)
|
||||
|
||||
def sendLogin(self, username):
|
||||
self.sendRequestMessage(REQ_LOGIN, username)
|
||||
|
||||
def sendLogout(self, username):
|
||||
self.sendRequestMessage(REQ_LOGOUT, username)
|
||||
|
||||
def requestTicket(self, ticketId, secure=True):
|
||||
self.sendRequestMessage(REQ_TICKET, json.dumps({'ticketId': ticketId, 'secure': secure}))
|
||||
|
||||
def messageReceived(self):
|
||||
'''
|
||||
Override this method to automatically get notified on new message
|
||||
received. Message is at self.messages queue
|
||||
'''
|
||||
pass # Messa
|
||||
|
||||
def receiveBytes(self, number):
|
||||
msg = b''
|
||||
while self.running and len(msg) < number:
|
||||
try:
|
||||
buf = self.clientSocket.recv(number - len(msg))
|
||||
if buf == b'':
|
||||
logger.debug('Buf {}, msg {}({})'.format(buf, msg, REV_DICT.get(msg)))
|
||||
self.running = False
|
||||
break
|
||||
msg += buf
|
||||
except socket.timeout:
|
||||
pass
|
||||
|
||||
if self.running is False:
|
||||
logger.debug('Not running, returning None')
|
||||
return None
|
||||
return msg
|
||||
|
||||
def connect(self):
|
||||
self.clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.clientSocket.connect(('localhost', self.port))
|
||||
self.clientSocket.settimeout(2) # 2 seconds timeout
|
||||
|
||||
def run(self):
|
||||
self.running = True
|
||||
|
||||
while self.running:
|
||||
try:
|
||||
msg = b''
|
||||
# We look for magic message header
|
||||
while self.running: # Wait for MAGIC
|
||||
try:
|
||||
buf = self.clientSocket.recv(len(MAGIC) - len(msg))
|
||||
if buf == b'':
|
||||
self.running = False
|
||||
break
|
||||
msg += buf
|
||||
if len(msg) != len(MAGIC):
|
||||
continue # Do not have message
|
||||
if msg != MAGIC: # Skip first byte an continue searchong
|
||||
msg = msg[1:]
|
||||
continue
|
||||
break
|
||||
except socket.timeout: # Timeout is here so we can get stop thread
|
||||
continue
|
||||
|
||||
if self.running is False:
|
||||
break
|
||||
|
||||
# Now we get message basic data (msg + datalen)
|
||||
msg = bytearray(self.receiveBytes(3))
|
||||
|
||||
# We have the magic header, here comes the message itself
|
||||
if msg is None:
|
||||
continue
|
||||
|
||||
msgId = msg[0]
|
||||
dataLen = msg[1] + (msg[2] << 8)
|
||||
if msgId not in VALID_MESSAGES:
|
||||
raise Exception('Invalid message id: {}'.format(msgId))
|
||||
|
||||
data = self.receiveBytes(dataLen)
|
||||
if data is None:
|
||||
continue
|
||||
|
||||
self.messages.put((msgId, data))
|
||||
self.messageReceived()
|
||||
|
||||
except socket.error as e:
|
||||
if e.errno == errno.EINTR:
|
||||
time.sleep(1) #
|
||||
continue # Ignore interrupted system call
|
||||
logger.error('Communication with server got an error: {}'.format(toUnicode(e.strerror)))
|
||||
# self.running = False
|
||||
return
|
||||
except Exception as e:
|
||||
tb = traceback.format_exc()
|
||||
logger.error('Error: {}, trace: {}'.format(e, tb))
|
||||
|
||||
try:
|
||||
self.clientSocket.close()
|
||||
except Exception:
|
||||
pass # If can't close, nothing happens, just end thread
|
||||
|
@ -1,234 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import sys
|
||||
import os
|
||||
import stat
|
||||
import subprocess
|
||||
|
||||
from udsactor import operations
|
||||
|
||||
from udsactor.service import CommonService
|
||||
from udsactor.service import initCfg
|
||||
from udsactor.service import IPC_PORT
|
||||
|
||||
from udsactor import ipc
|
||||
from udsactor import store
|
||||
from udsactor.log import logger
|
||||
|
||||
from udsactor.linux.daemon import Daemon
|
||||
from udsactor.linux import renamer
|
||||
|
||||
POST_CMD = '/etc/udsactor/post'
|
||||
|
||||
try:
|
||||
from prctl import set_proctitle # @UnresolvedImport
|
||||
except Exception: # Platform may not include prctl, so in case it's not available, we let the "name" as is
|
||||
|
||||
def set_proctitle(_):
|
||||
pass
|
||||
|
||||
|
||||
class UDSActorSvc(Daemon, CommonService):
|
||||
rebootMachineAfterOp = False
|
||||
|
||||
def __init__(self, args=None):
|
||||
Daemon.__init__(self, '/var/run/udsa.pid')
|
||||
CommonService.__init__(self)
|
||||
|
||||
def rename(self, name, user=None, oldPassword=None, newPassword=None):
|
||||
'''
|
||||
Renames the computer, and optionally sets a password for an user
|
||||
before this
|
||||
'''
|
||||
hostName = operations.getComputerName()
|
||||
|
||||
if hostName.lower() == name.lower():
|
||||
logger.info('Computer name is already {}'.format(hostName))
|
||||
self.setReady()
|
||||
return
|
||||
|
||||
# Check for password change request for an user
|
||||
if user is not None:
|
||||
logger.info('Setting password for user {}'.format(user))
|
||||
try:
|
||||
operations.changeUserPassword(user, oldPassword, newPassword)
|
||||
except Exception as e:
|
||||
# We stop here without even renaming computer, because the
|
||||
# process has failed
|
||||
raise Exception(
|
||||
'Could not change password for user {} (maybe invalid current password is configured at broker): {} '.format(user, unicode(e)))
|
||||
|
||||
renamer.rename(name)
|
||||
|
||||
if self.rebootMachineAfterOp is False:
|
||||
self.setReady()
|
||||
else:
|
||||
logger.info('Rebooting computer to activate new name {}'.format(name))
|
||||
self.reboot()
|
||||
|
||||
def joinDomain(self, name, domain, ou, account, password):
|
||||
logger.fatal('Join domain is not supported on linux platforms right now')
|
||||
|
||||
def preConnect(self, user, protocol):
|
||||
'''
|
||||
Invoked when received a PRE Connection request via REST
|
||||
'''
|
||||
# Execute script in /etc/udsactor/post after interacting with broker, if no reboot is requested ofc
|
||||
# This will be executed only when machine gets "ready"
|
||||
try:
|
||||
pre_cmd = store.preApplication()
|
||||
if os.path.isfile(pre_cmd):
|
||||
if (os.stat(pre_cmd).st_mode & stat.S_IXUSR) != 0:
|
||||
subprocess.call([pre_cmd, user, protocol])
|
||||
else:
|
||||
logger.info('PRECONNECT file exists but it it is not executable (needs execution permission by root)')
|
||||
else:
|
||||
logger.info('PRECONNECT file not found & not executed')
|
||||
except Exception:
|
||||
# Ignore output of execution command
|
||||
logger.error('Executing preconnect command give')
|
||||
|
||||
return 'ok'
|
||||
|
||||
def run(self):
|
||||
cfg = initCfg() # Gets a local copy of config to get "reboot"
|
||||
|
||||
logger.debug('CFG: {}'.format(cfg))
|
||||
|
||||
if cfg is not None:
|
||||
self.rebootMachineAfterOp = cfg.get('reboot', True)
|
||||
else:
|
||||
self.rebootMachineAfterOp = False
|
||||
|
||||
logger.info('Reboot after is {}'.format(self.rebootMachineAfterOp))
|
||||
|
||||
logger.debug('Running Daemon')
|
||||
set_proctitle('UDSActorDaemon')
|
||||
|
||||
# Linux daemon will continue running unless something is requested to
|
||||
while True:
|
||||
brokerConnected = self.interactWithBroker()
|
||||
if brokerConnected is False:
|
||||
logger.debug('Interact with broker returned false, stopping service after a while')
|
||||
return
|
||||
elif brokerConnected is True:
|
||||
break
|
||||
|
||||
# If brokerConnected returns None, repeat the cycle
|
||||
self.doWait(16000) # Wait for a looong while
|
||||
|
||||
if self.isAlive is False:
|
||||
logger.debug('The service is not alive after broker interaction, stopping it')
|
||||
return
|
||||
|
||||
if self.rebootRequested is True:
|
||||
logger.debug('Reboot has been requested, stopping service')
|
||||
return
|
||||
|
||||
# Execute script in /etc/udsactor/post after interacting with broker, if no reboot is requested ofc
|
||||
# This will be executed only when machine gets "ready"
|
||||
try:
|
||||
|
||||
if os.path.isfile(POST_CMD):
|
||||
if (os.stat(POST_CMD).st_mode & stat.S_IXUSR) != 0:
|
||||
subprocess.call([POST_CMD, ])
|
||||
else:
|
||||
logger.info('POST file exists but it it is not executable (needs execution permission by root)')
|
||||
else:
|
||||
logger.info('POST file not found & not executed')
|
||||
except Exception as e:
|
||||
# Ignore output of execution command
|
||||
logger.error('Executing post command give')
|
||||
|
||||
self.initIPC()
|
||||
|
||||
# *********************
|
||||
# * Main Service loop *
|
||||
# *********************
|
||||
# Counter used to check ip changes only once every 10 seconds, for
|
||||
# example
|
||||
counter = 0
|
||||
while self.isAlive:
|
||||
counter += 1
|
||||
if counter % 10 == 0:
|
||||
self.checkIpsChanged()
|
||||
# In milliseconds, will break
|
||||
self.doWait(1000)
|
||||
|
||||
self.endIPC()
|
||||
self.endAPI()
|
||||
|
||||
self.notifyStop()
|
||||
|
||||
|
||||
def usage():
|
||||
sys.stderr.write("usage: {} start|stop|restart|login 'username'|logout 'username'\n".format(sys.argv[0]))
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logger.setLevel(20000)
|
||||
|
||||
if len(sys.argv) == 3 and sys.argv[1] in ('login', 'logout'):
|
||||
logger.debug('Running client udsactor')
|
||||
client = None
|
||||
try:
|
||||
client = ipc.ClientIPC(IPC_PORT)
|
||||
if 'login' == sys.argv[1]:
|
||||
client.sendLogin(sys.argv[2])
|
||||
sys.exit(0)
|
||||
elif 'logout' == sys.argv[1]:
|
||||
client.sendLogout(sys.argv[2])
|
||||
sys.exit(0)
|
||||
else:
|
||||
usage()
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
elif len(sys.argv) != 2:
|
||||
usage()
|
||||
|
||||
logger.debug('Executing actor')
|
||||
daemon = UDSActorSvc()
|
||||
if len(sys.argv) == 2:
|
||||
if 'start' == sys.argv[1]:
|
||||
daemon.start()
|
||||
elif 'stop' == sys.argv[1]:
|
||||
daemon.stop()
|
||||
elif 'restart' == sys.argv[1]:
|
||||
daemon.restart()
|
||||
else:
|
||||
usage()
|
||||
sys.exit(0)
|
||||
else:
|
||||
usage()
|
@ -1,32 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
@ -1,183 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014-2018 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
@author: : http://www.jejik.com/authors/sander_marechal/
|
||||
@see: : http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/
|
||||
'''
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import atexit
|
||||
from udsactor.log import logger
|
||||
|
||||
from signal import SIGTERM
|
||||
|
||||
|
||||
class Daemon:
|
||||
"""
|
||||
A generic daemon class.
|
||||
|
||||
Usage: subclass the Daemon class and override the run() method
|
||||
"""
|
||||
|
||||
def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
|
||||
self.stdin = stdin
|
||||
self.stdout = stdout
|
||||
self.stderr = stderr
|
||||
self.pidfile = pidfile
|
||||
|
||||
def daemonize(self):
|
||||
"""
|
||||
do the UNIX double-fork magic, see Stevens' "Advanced
|
||||
Programming in the UNIX Environment" for details (ISBN 0201563177)
|
||||
http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
|
||||
"""
|
||||
try:
|
||||
pid = os.fork()
|
||||
if pid > 0:
|
||||
# exit first parent
|
||||
sys.exit(0)
|
||||
except OSError as e:
|
||||
logger.error("fork #1 error: {}".format(e))
|
||||
sys.stderr.write("fork #1 failed: {}\n".format(e))
|
||||
sys.exit(1)
|
||||
|
||||
# decouple from parent environment
|
||||
os.chdir("/")
|
||||
os.setsid()
|
||||
os.umask(0)
|
||||
|
||||
# do second fork
|
||||
try:
|
||||
pid = os.fork()
|
||||
if pid > 0:
|
||||
# exit from second parent
|
||||
sys.exit(0)
|
||||
except OSError as e:
|
||||
logger.error("fork #2 error: {}".format(e))
|
||||
sys.stderr.write("fork #2 failed: {}\n".format(e))
|
||||
sys.exit(1)
|
||||
|
||||
# redirect standard file descriptors
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
si = open(self.stdin, 'r')
|
||||
so = open(self.stdout, 'ab+')
|
||||
se = open(self.stderr, 'ab+', 0)
|
||||
os.dup2(si.fileno(), sys.stdin.fileno())
|
||||
os.dup2(so.fileno(), sys.stdout.fileno())
|
||||
os.dup2(se.fileno(), sys.stderr.fileno())
|
||||
|
||||
# write pidfile
|
||||
atexit.register(self.delpid)
|
||||
pid = str(os.getpid())
|
||||
with open(self.pidfile, 'w+') as f:
|
||||
f.write("{}\n".format(pid))
|
||||
|
||||
def delpid(self):
|
||||
try:
|
||||
os.remove(self.pidfile)
|
||||
except Exception:
|
||||
# Not found/not permissions or whatever...
|
||||
pass
|
||||
|
||||
def start(self):
|
||||
"""
|
||||
Start the daemon
|
||||
"""
|
||||
logger.debug('Starting daemon')
|
||||
# Check for a pidfile to see if the daemon already runs
|
||||
try:
|
||||
pf = open(self.pidfile, 'r')
|
||||
pid = int(pf.read().strip())
|
||||
pf.close()
|
||||
except IOError:
|
||||
pid = None
|
||||
|
||||
if pid:
|
||||
message = "pidfile {} already exist. Daemon already running?\n".format(pid)
|
||||
logger.error(message)
|
||||
sys.stderr.write(message)
|
||||
sys.exit(1)
|
||||
|
||||
# Start the daemon
|
||||
self.daemonize()
|
||||
try:
|
||||
self.run()
|
||||
except Exception as e:
|
||||
logger.error('Exception running process: {}'.format(e))
|
||||
|
||||
if os.path.exists(self.pidfile):
|
||||
os.remove(self.pidfile)
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
Stop the daemon
|
||||
"""
|
||||
# Get the pid from the pidfile
|
||||
try:
|
||||
pf = open(self.pidfile, 'r')
|
||||
pid = int(pf.read().strip())
|
||||
pf.close()
|
||||
except IOError:
|
||||
pid = None
|
||||
|
||||
if pid is None:
|
||||
message = "pidfile {} does not exist. Daemon not running?\n".format(self.pidfile)
|
||||
logger.info(message)
|
||||
# sys.stderr.write(message)
|
||||
return # not an error in a restart
|
||||
|
||||
# Try killing the daemon process
|
||||
try:
|
||||
while True:
|
||||
os.kill(pid, SIGTERM)
|
||||
time.sleep(1)
|
||||
except OSError as err:
|
||||
if err.errno == 3: # No such process
|
||||
if os.path.exists(self.pidfile):
|
||||
os.remove(self.pidfile)
|
||||
else:
|
||||
sys.stderr.write(err)
|
||||
sys.exit(1)
|
||||
|
||||
def restart(self):
|
||||
"""
|
||||
Restart the daemon
|
||||
"""
|
||||
self.stop()
|
||||
self.start()
|
||||
|
||||
# Overridables
|
||||
def run(self):
|
||||
"""
|
||||
You should override this method when you subclass Daemon. It will be called after the process has been
|
||||
daemonized by start() or restart().
|
||||
"""
|
@ -1,80 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
import six
|
||||
|
||||
# Valid logging levels, from UDS Broker (uds.core.utils.log)
|
||||
OTHER, DEBUG, INFO, WARN, ERROR, FATAL = (10000 * (x + 1) for x in six.moves.xrange(6)) # @UndefinedVariable
|
||||
|
||||
|
||||
class LocalLogger(object):
|
||||
def __init__(self):
|
||||
# tempdir is different for "user application" and "service"
|
||||
# service wil get c:\windows\temp, while user will get c:\users\XXX\temp
|
||||
# Try to open logger at /var/log path
|
||||
# If it fails (access denied normally), will try to open one at user's home folder, and if
|
||||
# agaim it fails, open it at the tmpPath
|
||||
|
||||
for logDir in ('/var/log', os.path.expanduser('~'), tempfile.gettempdir()):
|
||||
try:
|
||||
fname = os.path.join(logDir, 'udsactor.log')
|
||||
logging.basicConfig(
|
||||
filename=fname,
|
||||
filemode='a',
|
||||
format='%(levelname)s %(asctime)s %(message)s',
|
||||
level=logging.DEBUG
|
||||
)
|
||||
self.logger = logging.getLogger('udsactor')
|
||||
os.chmod(fname, 0o0600)
|
||||
return
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Logger can't be set
|
||||
self.logger = None
|
||||
|
||||
def log(self, level, message):
|
||||
# Debug messages are logged to a file
|
||||
# our loglevels are 10000 (other), 20000 (debug), ....
|
||||
# logging levels are 10 (debug), 20 (info)
|
||||
# OTHER = logging.NOTSET
|
||||
self.logger.log(int(level / 1000) - 10, message)
|
||||
|
||||
def isWindows(self):
|
||||
return False
|
||||
|
||||
def isLinux(self):
|
||||
return True
|
@ -1,248 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import socket
|
||||
import platform
|
||||
import fcntl
|
||||
import os
|
||||
import ctypes # @UnusedImport
|
||||
import ctypes.util
|
||||
import subprocess
|
||||
import struct
|
||||
import array
|
||||
import six
|
||||
from udsactor import utils
|
||||
from .renamer import rename
|
||||
|
||||
|
||||
def _getMacAddr(ifname):
|
||||
'''
|
||||
Returns the mac address of an interface
|
||||
Mac is returned as unicode utf-8 encoded
|
||||
'''
|
||||
if isinstance(ifname, list):
|
||||
return dict([(name, _getMacAddr(name)) for name in ifname])
|
||||
if isinstance(ifname, six.text_type):
|
||||
ifname = ifname.encode('utf-8') # If unicode, convert to bytes (or str in python 2.7)
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
info = bytearray(fcntl.ioctl(s.fileno(), 0x8927, struct.pack(str('256s'), ifname[:15])))
|
||||
return six.text_type(''.join(['%02x:' % char for char in info[18:24]])[:-1]).upper()
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def _getIpAddr(ifname):
|
||||
'''
|
||||
Returns the ip address of an interface
|
||||
Ip is returned as unicode utf-8 encoded
|
||||
'''
|
||||
if isinstance(ifname, list):
|
||||
return dict([(name, _getIpAddr(name)) for name in ifname])
|
||||
if isinstance(ifname, six.text_type):
|
||||
ifname = ifname.encode('utf-8') # If unicode, convert to bytes (or str in python 2.7)
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
return six.text_type(socket.inet_ntoa(fcntl.ioctl(
|
||||
s.fileno(),
|
||||
0x8915, # SIOCGIFADDR
|
||||
struct.pack(str('256s'), ifname[:15])
|
||||
)[20:24]))
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def _getInterfaces():
|
||||
'''
|
||||
Returns a list of interfaces names coded in utf-8
|
||||
'''
|
||||
max_possible = 128 # arbitrary. raise if needed.
|
||||
space = max_possible * 16
|
||||
if platform.architecture()[0] == '32bit':
|
||||
offset, length = 32, 32
|
||||
elif platform.architecture()[0] == '64bit':
|
||||
offset, length = 16, 40
|
||||
else:
|
||||
raise OSError('Unknown arquitecture {0}'.format(platform.architecture()[0]))
|
||||
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
names = array.array(str('B'), b'\0' * space)
|
||||
outbytes = struct.unpack(str('iL'), fcntl.ioctl(
|
||||
s.fileno(),
|
||||
0x8912, # SIOCGIFCONF
|
||||
struct.pack(str('iL'), space, names.buffer_info()[0])
|
||||
))[0]
|
||||
namestr = names.tostring()
|
||||
# return namestr, outbytes
|
||||
return [namestr[i:i + offset].split(b'\0', 1)[0].decode('utf-8') for i in range(0, outbytes, length)]
|
||||
|
||||
|
||||
def _getIpAndMac(ifname):
|
||||
ip, mac = _getIpAddr(ifname), _getMacAddr(ifname)
|
||||
return (ip, mac)
|
||||
|
||||
|
||||
def getComputerName():
|
||||
'''
|
||||
Returns computer name, with no domain
|
||||
'''
|
||||
return socket.gethostname().split('.')[0]
|
||||
|
||||
|
||||
def getNetworkInfo():
|
||||
for ifname in _getInterfaces():
|
||||
ip, mac = _getIpAndMac(ifname)
|
||||
if mac != '00:00:00:00:00:00' and ip.startswith('169.254') is False: # Skips local interfaces & interfaces with no dhcp IPs
|
||||
yield utils.Bunch(name=ifname, mac=mac, ip=ip)
|
||||
|
||||
|
||||
def getDomainName():
|
||||
return ''
|
||||
|
||||
|
||||
def getLinuxVersion():
|
||||
lv = platform.linux_distribution()
|
||||
return lv[0] + ', ' + lv[1]
|
||||
|
||||
|
||||
def reboot(flags=0):
|
||||
'''
|
||||
Simple reboot using os command
|
||||
'''
|
||||
# Workaround for dummy thread
|
||||
if six.PY3 is False:
|
||||
import threading
|
||||
threading._DummyThread._Thread__stop = lambda x: 42
|
||||
|
||||
subprocess.call(['/sbin/shutdown', 'now', '-r'])
|
||||
|
||||
|
||||
def loggoff():
|
||||
'''
|
||||
Right now restarts the machine...
|
||||
'''
|
||||
# Workaround for dummy thread
|
||||
if six.PY3 is False:
|
||||
import threading
|
||||
threading._DummyThread._Thread__stop = lambda x: 42
|
||||
|
||||
subprocess.call(['/usr/bin/pkill', '-u', os.environ['USER']])
|
||||
# subprocess.call(['/sbin/shutdown', 'now', '-r'])
|
||||
# subprocess.call(['/usr/bin/systemctl', 'reboot', '-i'])
|
||||
|
||||
|
||||
def renameComputer(newName):
|
||||
rename(newName)
|
||||
|
||||
|
||||
def joinDomain(domain, ou, account, password, executeInOneStep=False):
|
||||
pass
|
||||
|
||||
|
||||
def changeUserPassword(user, oldPassword, newPassword):
|
||||
'''
|
||||
Simple password change for user using command line
|
||||
'''
|
||||
os.system('echo "{1}\n{1}" | /usr/bin/passwd {0} 2> /dev/null'.format(user, newPassword))
|
||||
|
||||
|
||||
class XScreenSaverInfo(ctypes.Structure):
|
||||
_fields_ = [('window', ctypes.c_long),
|
||||
('state', ctypes.c_int),
|
||||
('kind', ctypes.c_int),
|
||||
('til_or_since', ctypes.c_ulong),
|
||||
('idle', ctypes.c_ulong),
|
||||
('eventMask', ctypes.c_ulong)]
|
||||
|
||||
# Initialize xlib & xss
|
||||
try:
|
||||
xlibPath = ctypes.util.find_library('X11')
|
||||
xssPath = ctypes.util.find_library('Xss')
|
||||
xlib = xss = None
|
||||
if not xlibPath or not xssPath:
|
||||
raise Exception()
|
||||
xlib = ctypes.cdll.LoadLibrary(xlibPath)
|
||||
xss = ctypes.cdll.LoadLibrary(xssPath)
|
||||
|
||||
# Fix result type to XScreenSaverInfo Structure
|
||||
xss.XScreenSaverQueryExtension.restype = ctypes.c_int
|
||||
xss.XScreenSaverAllocInfo.restype = ctypes.POINTER(XScreenSaverInfo) # Result in a XScreenSaverInfo structure
|
||||
display = xlib.XOpenDisplay(None)
|
||||
info = xss.XScreenSaverAllocInfo()
|
||||
except Exception: # Libraries not accesible, not found or whatever..
|
||||
xlib = xss = display = info = None
|
||||
|
||||
|
||||
def initIdleDuration(atLeastSeconds):
|
||||
'''
|
||||
On linux we set the screensaver to at least required seconds, or we never will get "idle"
|
||||
'''
|
||||
# Workaround for dummy thread
|
||||
if six.PY3 is False:
|
||||
import threading
|
||||
threading._DummyThread._Thread__stop = lambda x: 42
|
||||
|
||||
subprocess.call(['/usr/bin/xset', 's', '{}'.format(atLeastSeconds + 30)])
|
||||
# And now reset it
|
||||
subprocess.call(['/usr/bin/xset', 's', 'reset'])
|
||||
|
||||
|
||||
def getIdleDuration():
|
||||
'''
|
||||
Returns idle duration, in seconds
|
||||
'''
|
||||
if xlib is None or xss is None:
|
||||
return 0 # Libraries not available
|
||||
|
||||
event_base = ctypes.c_int()
|
||||
error_base = ctypes.c_int()
|
||||
|
||||
available = xss.XScreenSaverQueryExtension(display, ctypes.byref(event_base), ctypes.byref(error_base))
|
||||
|
||||
if available != 1:
|
||||
return 0 # No screen saver is available, no way of getting idle
|
||||
|
||||
xss.XScreenSaverQueryInfo(display, xlib.XDefaultRootWindow(display), info)
|
||||
|
||||
# Centos seems to set state to 1?? (weird, but it's happening don't know why... will try this way)
|
||||
if info.contents.state != 0 and 'centos' not in platform.linux_distribution()[0].lower().strip():
|
||||
return 3600 * 100 * 1000 # If screen saver is active, return a high enough value
|
||||
|
||||
return info.contents.idle / 1000.0
|
||||
|
||||
|
||||
def getCurrentUser():
|
||||
'''
|
||||
Returns current logged in user
|
||||
'''
|
||||
return os.environ['USER']
|
@ -1,61 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import platform
|
||||
import os
|
||||
import sys
|
||||
import pkgutil
|
||||
|
||||
from udsactor.log import logger
|
||||
|
||||
renamers = {}
|
||||
|
||||
|
||||
# Renamers now are for IPv4 only addresses
|
||||
def rename(newName):
|
||||
distribution = platform.linux_distribution()[0].lower().strip()
|
||||
if distribution in renamers:
|
||||
return renamers[distribution](newName)
|
||||
|
||||
# Try Debian renamer, simplest one
|
||||
logger.info('Renamer for platform "{0}" not found, tryin debian renamer'.format(distribution))
|
||||
return renamers['debian'](newName)
|
||||
|
||||
|
||||
# Do load of packages
|
||||
def _init():
|
||||
pkgpath = os.path.dirname(sys.modules[__name__].__file__)
|
||||
for _, name, _ in pkgutil.iter_modules([pkgpath]):
|
||||
__import__(__name__ + '.' + name, globals(), locals())
|
||||
|
||||
_init()
|
@ -1,68 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from udsactor.linux.renamer import renamers
|
||||
from udsactor.log import logger
|
||||
|
||||
import os
|
||||
|
||||
|
||||
def rename(newName):
|
||||
'''
|
||||
Debian renamer
|
||||
Expects new host name on newName
|
||||
Host does not needs to be rebooted after renaming
|
||||
'''
|
||||
logger.debug('using Debian renamer')
|
||||
|
||||
with open('/etc/hostname', 'w') as hostname:
|
||||
hostname.write(newName)
|
||||
|
||||
# Force system new name
|
||||
os.system('/bin/hostname %s' % newName)
|
||||
|
||||
# add name to "hosts"
|
||||
with open('/etc/hosts', 'r') as hosts:
|
||||
lines = hosts.readlines()
|
||||
with open('/etc/hosts', 'w') as hosts:
|
||||
hosts.write("127.0.1.1\t%s\n" % newName)
|
||||
for l in lines:
|
||||
if l[:9] == '127.0.1.1': # Skips existing 127.0.1.1. if it already exists
|
||||
continue
|
||||
hosts.write(l)
|
||||
|
||||
return True
|
||||
|
||||
# All names in lower case
|
||||
renamers['debian'] = rename
|
||||
renamers['ubuntu'] = rename
|
@ -1,66 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from udsactor.linux.renamer import renamers
|
||||
from udsactor.log import logger
|
||||
|
||||
import os
|
||||
|
||||
|
||||
def rename(newName):
|
||||
'''
|
||||
RH, Centos, Fedora Renamer
|
||||
Expects new host name on newName
|
||||
Host does not needs to be rebooted after renaming
|
||||
'''
|
||||
logger.debug('using SUSE renamer')
|
||||
|
||||
with open('/etc/hostname', 'w') as hostname:
|
||||
hostname.write(newName)
|
||||
|
||||
# Force system new name
|
||||
os.system('/bin/hostname %s' % newName)
|
||||
|
||||
# add name to "hosts"
|
||||
with open('/etc/hosts', 'r') as hosts:
|
||||
lines = hosts.readlines()
|
||||
with open('/etc/hosts', 'w') as hosts:
|
||||
hosts.write("127.0.1.1\t{}\n".format(newName))
|
||||
for l in lines:
|
||||
if l[:9] != '127.0.1.1': # Skips existing 127.0.1.1. if it already exists
|
||||
hosts.write(l)
|
||||
|
||||
return True
|
||||
|
||||
# All names in lower case
|
||||
renamers['opensuse'] = rename
|
||||
renamers['suse'] = rename
|
@ -1,75 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from udsactor.linux.renamer import renamers
|
||||
from udsactor.log import logger
|
||||
|
||||
import os
|
||||
|
||||
|
||||
def rename(newName):
|
||||
'''
|
||||
RH, Centos, Fedora Renamer
|
||||
Expects new host name on newName
|
||||
Host does not needs to be rebooted after renaming
|
||||
'''
|
||||
logger.debug('using RH renamer')
|
||||
|
||||
with open('/etc/hostname', 'w') as hostname:
|
||||
hostname.write(newName)
|
||||
|
||||
# Force system new name
|
||||
os.system('/bin/hostname %s' % newName)
|
||||
|
||||
# add name to "hosts"
|
||||
with open('/etc/hosts', 'r') as hosts:
|
||||
lines = hosts.readlines()
|
||||
with open('/etc/hosts', 'w') as hosts:
|
||||
hosts.write("127.0.1.1\t{}\n".format(newName))
|
||||
for l in lines:
|
||||
if l[:9] != '127.0.1.1': # Skips existing 127.0.1.1. if it already exists
|
||||
hosts.write(l)
|
||||
|
||||
with open('/etc/sysconfig/network', 'r') as net:
|
||||
lines = net.readlines()
|
||||
with open('/etc/sysconfig/network', 'w') as net:
|
||||
net.write('HOSTNAME={}\n'.format(newName))
|
||||
for l in lines:
|
||||
if l[:8] != 'HOSTNAME':
|
||||
net.write(l)
|
||||
|
||||
return True
|
||||
|
||||
# All names in lower case
|
||||
renamers['centos linux'] = rename
|
||||
renamers['centos'] = rename
|
||||
renamers['fedora'] = rename
|
@ -1,93 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
|
||||
import six
|
||||
import os
|
||||
|
||||
DEBUG = False
|
||||
|
||||
CONFIGFILE = '/etc/udsactor/udsactor.cfg' if DEBUG is False else '/tmp/udsactor.cfg'
|
||||
PRECONNECT_CMD = '/etc/udsactor/pre'
|
||||
|
||||
|
||||
def checkPermissions():
|
||||
return True if DEBUG else os.getuid() == 0
|
||||
|
||||
|
||||
def readConfig():
|
||||
res = {}
|
||||
try:
|
||||
cfg = six.moves.configparser.SafeConfigParser() # @UndefinedVariable
|
||||
cfg.optionxform = six.text_type
|
||||
cfg.read(CONFIGFILE)
|
||||
# Just reads 'uds' section
|
||||
for key in cfg.options('uds'):
|
||||
res[key] = cfg.get('uds', key)
|
||||
if res[key].lower() in ('true', 'yes', 'si'):
|
||||
res[key] = True
|
||||
elif res[key].lower() in ('false', 'no'):
|
||||
res[key] = False
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def writeConfig(data):
|
||||
cfg = six.moves.configparser.SafeConfigParser() # @UndefinedVariable
|
||||
cfg.optionxform = six.text_type
|
||||
cfg.add_section('uds')
|
||||
for key, val in data.items():
|
||||
cfg.set('uds', key, str(val))
|
||||
|
||||
# Ensures exists destination folder
|
||||
dirname = os.path.dirname(CONFIGFILE)
|
||||
if not os.path.exists(dirname):
|
||||
os.mkdir(dirname, mode=0o700) # Will create only if route to path already exists, for example, /etc (that must... :-))
|
||||
|
||||
with open(CONFIGFILE, 'w') as f:
|
||||
cfg.write(f)
|
||||
|
||||
os.chmod(CONFIGFILE, 0o0600)
|
||||
|
||||
|
||||
def useOldJoinSystem():
|
||||
return False
|
||||
|
||||
|
||||
# Right now, we do not really need an application to be run on "startup" as could ocur with windows
|
||||
def runApplication():
|
||||
return None
|
||||
|
||||
|
||||
def preApplication():
|
||||
return PRECONNECT_CMD
|
@ -1,104 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import traceback
|
||||
import sys
|
||||
import six
|
||||
|
||||
if sys.platform == 'win32':
|
||||
from udsactor.windows.log import LocalLogger # @UnusedImport
|
||||
else:
|
||||
from udsactor.linux.log import LocalLogger # @Reimport
|
||||
|
||||
# Valid logging levels, from UDS Broker (uds.core.utils.log)
|
||||
OTHER, DEBUG, INFO, WARN, ERROR, FATAL = (10000 * (x + 1) for x in six.moves.xrange(6)) # @UndefinedVariable
|
||||
|
||||
|
||||
class Logger(object):
|
||||
|
||||
def __init__(self):
|
||||
self.logLevel = INFO
|
||||
self.logger = LocalLogger()
|
||||
self.remoteLogger = None
|
||||
|
||||
def setLevel(self, level):
|
||||
'''
|
||||
Sets log level filter (minimum level required for a log message to be processed)
|
||||
:param level: Any message with a level below this will be filtered out
|
||||
'''
|
||||
self.logLevel = int(level) # Ensures level is an integer or fails
|
||||
|
||||
def setRemoteLogger(self, remoteLogger):
|
||||
self.remoteLogger = remoteLogger
|
||||
|
||||
def log(self, level, message):
|
||||
if level < self.logLevel: # Skip not wanted messages
|
||||
return
|
||||
|
||||
# If remote logger is available, notify message to it
|
||||
try:
|
||||
if self.remoteLogger is not None and self.remoteLogger.isConnected and level >= INFO:
|
||||
self.remoteLogger.log(level, message)
|
||||
except Exception as e:
|
||||
self.logger.log(FATAL, 'Error notifying log to broker: {}'.format(e.message))
|
||||
|
||||
self.logger.log(level, message)
|
||||
|
||||
def debug(self, message):
|
||||
self.log(DEBUG, message)
|
||||
|
||||
def warn(self, message):
|
||||
self.log(WARN, message)
|
||||
|
||||
def info(self, message):
|
||||
self.log(INFO, message)
|
||||
|
||||
def error(self, message):
|
||||
self.log(ERROR, message)
|
||||
|
||||
def fatal(self, message):
|
||||
self.log(FATAL, message)
|
||||
|
||||
def exception(self):
|
||||
try:
|
||||
tb = traceback.format_exc()
|
||||
except Exception:
|
||||
tb = '(could not get traceback!)'
|
||||
|
||||
self.log(DEBUG, tb)
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
|
||||
|
||||
logger = Logger()
|
@ -1,40 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
# pylint: disable=unused-wildcard-import,wildcard-import
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import sys
|
||||
if sys.platform == 'win32':
|
||||
from .windows.operations import * # @UnusedWildImport
|
||||
else:
|
||||
from .linux.operations import * # @UnusedWildImport
|
@ -1,51 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 201 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
|
||||
# pylint: disable-msg=E1101,W0703
|
||||
|
||||
from udsactor.log import logger
|
||||
|
||||
import threading
|
||||
import six
|
||||
|
||||
|
||||
class ScriptExecutorThread(threading.Thread):
|
||||
def __init__(self, script):
|
||||
super(ScriptExecutorThread, self).__init__()
|
||||
self.script = script
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
logger.debug('Executing script: {}'.format(self.script))
|
||||
six.exec_(self.script, globals(), None)
|
||||
except Exception as e:
|
||||
logger.error('Error executing script: {}'.format(e))
|
@ -1,377 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from udsactor.log import logger
|
||||
|
||||
from . import operations
|
||||
from . import store
|
||||
from . import REST
|
||||
from . import ipc
|
||||
from . import httpserver
|
||||
from .scriptThread import ScriptExecutorThread
|
||||
from .utils import exceptionToMessage
|
||||
|
||||
import socket
|
||||
import time
|
||||
import random
|
||||
import os
|
||||
import subprocess
|
||||
import shlex
|
||||
import stat
|
||||
import json
|
||||
|
||||
IPC_PORT = 39188
|
||||
|
||||
cfg = None
|
||||
|
||||
|
||||
def initCfg():
|
||||
global cfg # pylint: disable=global-statement
|
||||
cfg = store.readConfig()
|
||||
|
||||
if logger.logger.isWindows():
|
||||
# Logs will also go to windows event log for services
|
||||
logger.logger.serviceLogger = True
|
||||
|
||||
if cfg is not None:
|
||||
logger.setLevel(cfg.get('logLevel', 20000))
|
||||
else:
|
||||
logger.setLevel(20000)
|
||||
cfg = {}
|
||||
|
||||
# If ANY var is missing, reset cfg
|
||||
for v in ('host', 'ssl', 'masterKey'):
|
||||
if v not in cfg:
|
||||
cfg = None
|
||||
break
|
||||
|
||||
return cfg
|
||||
|
||||
|
||||
class CommonService(object):
|
||||
|
||||
def __init__(self):
|
||||
self.isAlive = True
|
||||
self.api = None
|
||||
self.ipc = None
|
||||
self.httpServer = None
|
||||
self.rebootRequested = False
|
||||
self.knownIps = []
|
||||
self.loggedIn = False
|
||||
socket.setdefaulttimeout(20)
|
||||
|
||||
def reboot(self):
|
||||
self.rebootRequested = True
|
||||
|
||||
def execute(self, cmdLine, section): # pylint: disable=no-self-use
|
||||
cmd = shlex.split(cmdLine, posix=False)
|
||||
|
||||
if os.path.isfile(cmd[0]):
|
||||
if (os.stat(cmd[0]).st_mode & stat.S_IXUSR) != 0:
|
||||
try:
|
||||
res = subprocess.check_call(cmd)
|
||||
except Exception as e:
|
||||
logger.error('Got exception executing: {} - {}'.format(cmdLine, e))
|
||||
return False
|
||||
logger.info('Result of executing cmd was {}'.format(res))
|
||||
return True
|
||||
else:
|
||||
logger.error('{} file exists but it it is not executable (needs execution permission by admin/root)'.format(section))
|
||||
else:
|
||||
logger.error('{} file not found & not executed'.format(section))
|
||||
|
||||
return False
|
||||
|
||||
def setReady(self):
|
||||
self.api.setReady([(v.mac, v.ip) for v in operations.getNetworkInfo()])
|
||||
|
||||
def interactWithBroker(self):
|
||||
'''
|
||||
Returns True to continue to main loop, false to stop & exit service
|
||||
'''
|
||||
# If no configuration is found, stop service
|
||||
if cfg is None:
|
||||
logger.fatal('No configuration found, stopping service')
|
||||
return False
|
||||
|
||||
self.api = REST.Api(cfg['host'], cfg['masterKey'], cfg['ssl'])
|
||||
|
||||
# Wait for Broker to be ready
|
||||
counter = 0
|
||||
while self.isAlive:
|
||||
try:
|
||||
# getNetworkInfo is a generator function
|
||||
netInfo = tuple(operations.getNetworkInfo())
|
||||
self.knownIps = dict(((i.mac, i.ip) for i in netInfo))
|
||||
ids = ','.join([i.mac for i in netInfo])
|
||||
if ids == '':
|
||||
# Wait for any network interface to be ready
|
||||
logger.debug('No valid network interfaces found, retrying in a while...')
|
||||
raise Exception()
|
||||
logger.debug('Ids: {}'.format(ids))
|
||||
self.api.init(ids)
|
||||
# Set remote logger to notify log info to broker
|
||||
logger.setRemoteLogger(self.api)
|
||||
|
||||
break
|
||||
except REST.InvalidKeyError:
|
||||
logger.fatal('Can\'t sync with broker: Invalid broker Master Key')
|
||||
return False
|
||||
except REST.UnmanagedHostError:
|
||||
# Maybe interface that is registered with broker is not enabled already?
|
||||
# Right now, we thing that the interface connected to broker is
|
||||
# the interface that broker will know, let's see how this works
|
||||
logger.fatal('This host is not managed by UDS Broker (ids: {})'.format(ids))
|
||||
return False # On unmanaged hosts, there is no reason right now to continue running
|
||||
except Exception as e:
|
||||
logger.debug('Exception on network info: retrying')
|
||||
# Any other error is expectable and recoverable, so let's wait a bit and retry again
|
||||
# but, if too many errors, will log it (one every minute, for
|
||||
# example)
|
||||
counter += 1
|
||||
if counter % 60 == 0: # Every 5 minutes, raise a log
|
||||
logger.info('Trying to inititialize connection with broker (last error: {})'.format(exceptionToMessage(e)))
|
||||
# Wait a bit before next check
|
||||
self.doWait(5000)
|
||||
|
||||
# Now try to run the "runonce" element
|
||||
runOnce = store.runApplication()
|
||||
if runOnce is not None:
|
||||
logger.info('Executing runOnce app: {}'.format(runOnce))
|
||||
if self.execute(runOnce, 'RunOnce') is True:
|
||||
# operations.reboot()
|
||||
return False
|
||||
|
||||
# Broker connection is initialized, now get information about what to
|
||||
# do
|
||||
counter = 0
|
||||
while self.isAlive:
|
||||
try:
|
||||
logger.debug('Requesting information of what to do now')
|
||||
info = self.api.information()
|
||||
data = info.split('\r')
|
||||
if len(data) != 2:
|
||||
logger.error('The format of the information message is not correct (got {})'.format(info))
|
||||
raise Exception
|
||||
params = data[1].split('\t')
|
||||
if data[0] == 'rename':
|
||||
try:
|
||||
if len(params) == 1: # Simple rename
|
||||
logger.debug('Renaming computer to {}'.format(params[0]))
|
||||
self.rename(params[0])
|
||||
# Rename with change password for an user
|
||||
elif len(params) == 4:
|
||||
logger.debug('Renaming computer to {}'.format(params))
|
||||
self.rename(params[0], params[1], params[2], params[3])
|
||||
else:
|
||||
logger.error('Got invalid parameter for rename operation: {}'.format(params))
|
||||
return False
|
||||
break
|
||||
except Exception as e:
|
||||
logger.error('Error at computer renaming stage: {}'.format(e.message))
|
||||
return None # Will retry complete broker connection if this point is reached
|
||||
elif data[0] == 'domain':
|
||||
if len(params) != 5:
|
||||
logger.error('Got invalid parameters for domain message: {}'.format(params))
|
||||
return False # Stop running service
|
||||
self.joinDomain(params[0], params[1], params[2], params[3], params[4])
|
||||
break
|
||||
else:
|
||||
logger.error('Unrecognized action sent from broker: {}'.format(data[0]))
|
||||
return False # Stop running service
|
||||
except REST.UserServiceNotFoundError:
|
||||
logger.error('The host has lost the sync state with broker! (host uuid changed?)')
|
||||
return False
|
||||
except Exception as err:
|
||||
if counter % 60 == 0:
|
||||
logger.warn('Too many retries in progress, though still trying (last error: {})'.format(exceptionToMessage(err)))
|
||||
counter += 1
|
||||
# Any other error is expectable and recoverable, so let's wait
|
||||
# a bit and retry again
|
||||
# Wait a bit before next check
|
||||
self.doWait(5000)
|
||||
|
||||
if self.rebootRequested:
|
||||
try:
|
||||
operations.reboot()
|
||||
except Exception as e:
|
||||
logger.error('Exception on reboot: {}'.format(e.message))
|
||||
return False # Stops service
|
||||
|
||||
return True
|
||||
|
||||
def checkIpsChanged(self):
|
||||
if self.api is None or self.api.uuid is None:
|
||||
return # Not connected
|
||||
netInfo = tuple(operations.getNetworkInfo())
|
||||
for i in netInfo:
|
||||
# If at least one ip has changed
|
||||
if i.mac in self.knownIps and self.knownIps[i.mac] != i.ip:
|
||||
logger.info('Notifying ip change to broker (mac {}, from {} to {})'.format(i.mac, self.knownIps[i.mac], i.ip))
|
||||
try:
|
||||
# Notifies all interfaces IPs
|
||||
self.api.notifyIpChanges(((v.mac, v.ip) for v in netInfo))
|
||||
|
||||
# Regenerates Known ips
|
||||
self.knownIps = dict(((v.mac, v.ip) for v in netInfo))
|
||||
|
||||
# And notify new listening address to broker
|
||||
address = (self.knownIps[self.api.mac], self.httpServer.getPort())
|
||||
# And new listening address
|
||||
self.httpServer.restart(address)
|
||||
# sends notification
|
||||
self.api.notifyComm(self.httpServer.getServerUrl())
|
||||
|
||||
except Exception as e:
|
||||
logger.warn('Got an error notifiying IPs to broker: {} (will retry in a bit)'.format(e.message.decode('windows-1250', 'ignore')))
|
||||
|
||||
def clientMessageProcessor(self, msg, data):
|
||||
logger.debug('Got message {}'.format(msg))
|
||||
if self.api is None:
|
||||
logger.info('Rest api not ready')
|
||||
return
|
||||
|
||||
if msg == ipc.REQ_LOGIN:
|
||||
self.loggedIn = True
|
||||
res = self.api.login(data).split('\t')
|
||||
# third parameter, if exists, sets maxSession duration to this.
|
||||
# First & second parameters are ip & hostname of connection source
|
||||
if len(res) >= 3:
|
||||
self.api.maxSession = int(res[2]) # Third parameter is max session duration
|
||||
msg = ipc.REQ_INFORMATION # Senf information, requested or not, to client on login notification
|
||||
if msg == ipc.REQ_LOGOUT and self.loggedIn is True:
|
||||
self.loggedIn = False
|
||||
self.api.logout(data)
|
||||
self.onLogout(data)
|
||||
if msg == ipc.REQ_INFORMATION:
|
||||
info = {}
|
||||
if self.api.idle is not None:
|
||||
info['idle'] = self.api.idle
|
||||
if self.api.maxSession is not None:
|
||||
info['maxSession'] = self.api.maxSession
|
||||
self.ipc.sendInformationMessage(info)
|
||||
if msg == ipc.REQ_TICKET:
|
||||
d = json.loads(data)
|
||||
try:
|
||||
result = self.api.getTicket(d['ticketId'], d['secure'])
|
||||
self.ipc.sendTicketMessage(result)
|
||||
except Exception:
|
||||
logger.exception('Getting ticket')
|
||||
self.ipc.sendTicketMessage({'error': 'invalid ticket'})
|
||||
|
||||
def initIPC(self):
|
||||
# ******************************************
|
||||
# * Initialize listener IPC & REST threads *
|
||||
# ******************************************
|
||||
logger.debug('Starting IPC listener at {}'.format(IPC_PORT))
|
||||
self.ipc = ipc.ServerIPC(IPC_PORT, clientMessageProcessor=self.clientMessageProcessor)
|
||||
self.ipc.start()
|
||||
|
||||
if self.api.mac in self.knownIps:
|
||||
address = (self.knownIps[self.api.mac], random.randrange(43900, 44000))
|
||||
logger.info('Starting REST listener at {}'.format(address))
|
||||
self.httpServer = httpserver.HTTPServerThread(address, self)
|
||||
self.httpServer.start()
|
||||
# And notify it to broker
|
||||
self.api.notifyComm(self.httpServer.getServerUrl())
|
||||
|
||||
def endIPC(self):
|
||||
# Remove IPC threads
|
||||
if self.ipc is not None:
|
||||
try:
|
||||
self.ipc.stop()
|
||||
except Exception:
|
||||
logger.error('Couln\'t stop ipc server')
|
||||
if self.httpServer is not None:
|
||||
try:
|
||||
self.httpServer.stop()
|
||||
except Exception:
|
||||
logger.error('Couln\'t stop REST server')
|
||||
|
||||
def endAPI(self):
|
||||
if self.api is not None:
|
||||
try:
|
||||
if self.loggedIn:
|
||||
self.loggedIn = False
|
||||
self.api.logout('service_stopped')
|
||||
self.api.notifyComm(None)
|
||||
except Exception as e:
|
||||
logger.error('Couln\'t remove comms url from broker: {}'.format(e))
|
||||
|
||||
# self.notifyStop()
|
||||
|
||||
# ***************************************************
|
||||
# Methods that ARE overriden by linux & windows Actor
|
||||
# ***************************************************
|
||||
def rename(self, name, user=None, oldPassword=None, newPassword=None):
|
||||
'''
|
||||
Invoked when broker requests a rename action
|
||||
MUST BE OVERRIDEN
|
||||
'''
|
||||
raise NotImplementedError('Method renamed has not been implemented!')
|
||||
|
||||
def joinDomain(self, name, domain, ou, account, password):
|
||||
'''
|
||||
Invoked when broker requests a "domain" action
|
||||
MUST BE OVERRIDEN
|
||||
'''
|
||||
raise NotImplementedError('Method renamed has not been implemented!')
|
||||
|
||||
# ****************************************
|
||||
# Methods that CAN BE overriden by actors
|
||||
# ****************************************
|
||||
def notifyLocal(self):
|
||||
self.setReady(operations.getComputerName())
|
||||
|
||||
def doWait(self, miliseconds):
|
||||
'''
|
||||
Invoked to wait a bit
|
||||
CAN be OVERRIDEN
|
||||
'''
|
||||
time.sleep(float(miliseconds) / 1000)
|
||||
|
||||
def notifyStop(self):
|
||||
'''
|
||||
Overriden to log stop
|
||||
'''
|
||||
logger.info('Service is being stopped')
|
||||
|
||||
def preConnect(self, user, protocol):
|
||||
'''
|
||||
Invoked when received a PRE Connection request via REST
|
||||
'''
|
||||
logger.debug('Pre-connect does nothing')
|
||||
return 'ok'
|
||||
|
||||
def onLogout(self, user):
|
||||
logger.debug('On logout invoked for {}'.format(user))
|
@ -1,39 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
# pylint: disable=unused-wildcard-import, wildcard-import
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import sys
|
||||
if sys.platform == 'win32':
|
||||
from udsactor.windows.store import * # @UnusedWildImport
|
||||
else:
|
||||
from udsactor.linux.store import * # @UnusedWildImport
|
@ -1,72 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import sys
|
||||
import six
|
||||
|
||||
if sys.platform == 'win32':
|
||||
_fromEncoding = 'windows-1250'
|
||||
else:
|
||||
_fromEncoding = 'utf-8'
|
||||
|
||||
|
||||
def toUnicode(msg):
|
||||
try:
|
||||
if not isinstance(msg, six.text_type):
|
||||
if isinstance(msg, six.binary_type):
|
||||
return msg.decode(_fromEncoding, 'ignore')
|
||||
return six.text_type(msg)
|
||||
else:
|
||||
return msg
|
||||
except Exception:
|
||||
try:
|
||||
return six.text_type(msg)
|
||||
except Exception:
|
||||
return ''
|
||||
|
||||
|
||||
def exceptionToMessage(e):
|
||||
msg = ''
|
||||
for arg in e.args:
|
||||
if isinstance(arg, Exception):
|
||||
msg = msg + exceptionToMessage(arg)
|
||||
else:
|
||||
msg = msg + toUnicode(arg) + '. '
|
||||
return msg
|
||||
|
||||
|
||||
class Bunch(dict):
|
||||
def __init__(self, **kw):
|
||||
dict.__init__(self, kw)
|
||||
self.__dict__ = self
|
||||
|
@ -1,148 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
# _*_ coding: iso-8859-1 _*_
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import win32com.client # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32com.server.policy # @UnresolvedImport, pylint: disable=import-error
|
||||
import os
|
||||
|
||||
from udsactor.log import logger
|
||||
|
||||
# based on python SENS example from
|
||||
# http://timgolden.me.uk/python/win32_how_do_i/track-session-events.html
|
||||
|
||||
# from Sens.h
|
||||
SENSGUID_PUBLISHER = "{5fee1bd6-5b9b-11d1-8dd2-00aa004abd5e}"
|
||||
SENSGUID_EVENTCLASS_LOGON = "{d5978630-5b9f-11d1-8dd2-00aa004abd5e}"
|
||||
|
||||
# from EventSys.h
|
||||
PROGID_EventSystem = "EventSystem.EventSystem"
|
||||
PROGID_EventSubscription = "EventSystem.EventSubscription"
|
||||
|
||||
IID_ISensLogon = "{d597bab3-5b9f-11d1-8dd2-00aa004abd5e}"
|
||||
|
||||
|
||||
class SensLogon(win32com.server.policy.DesignatedWrapPolicy):
|
||||
_com_interfaces_ = [IID_ISensLogon]
|
||||
_public_methods_ = [
|
||||
'Logon',
|
||||
'Logoff',
|
||||
'StartShell',
|
||||
'DisplayLock',
|
||||
'DisplayUnlock',
|
||||
'StartScreenSaver',
|
||||
'StopScreenSaver'
|
||||
]
|
||||
|
||||
def __init__(self, service):
|
||||
self._wrap_(self)
|
||||
self.service = service
|
||||
|
||||
def Logon(self, *args):
|
||||
logger.debug('Logon event: {}'.format(args))
|
||||
if self.service.api is not None and self.service.api.isConnected:
|
||||
try:
|
||||
data = self.service.api.login(args[0])
|
||||
logger.debug('Data received for login: {}'.format(data))
|
||||
data = data.split('\t')
|
||||
if len(data) >= 2:
|
||||
logger.debug('Data is valid: {}'.format(data))
|
||||
windir = os.environ['windir']
|
||||
with open(os.path.join(windir, 'remoteip.txt'), 'w') as f:
|
||||
f.write(data[0])
|
||||
with open(os.path.join(windir, 'remoteh.txt'), 'w') as f:
|
||||
f.write(data[1])
|
||||
except Exception as e:
|
||||
logger.fatal('Error notifying logon to server: {}'.format(e))
|
||||
|
||||
def Logoff(self, *args):
|
||||
logger.debug('Logoff event: arguments: {}'.format(args))
|
||||
if self.service is not None and self.service.api is not None and self.service.api.isConnected:
|
||||
try:
|
||||
self.service.api.logout(args[0])
|
||||
except Exception as e:
|
||||
logger.fatal('Error notifying logoff to server: {}'.format(e))
|
||||
|
||||
logger.debug('Invoking onLogout: {}'.format(self.service))
|
||||
self.service.onLogout(args[0])
|
||||
logger.debug('Invoked!!')
|
||||
|
||||
def StartShell(self, *args):
|
||||
# logevent('StartShell : %s' % [args])
|
||||
pass
|
||||
|
||||
def DisplayLock(self, *args):
|
||||
# logevent('DisplayLock : %s' % [args])
|
||||
pass
|
||||
|
||||
def DisplayUnlock(self, *args):
|
||||
# logevent('DisplayUnlock : %s' % [args])
|
||||
pass
|
||||
|
||||
def StartScreenSaver(self, *args):
|
||||
# When finished basic actor, we will use this to provide a new parameter: logout on screensaver
|
||||
# This will allow to easily close sessions of idle users
|
||||
# logevent('StartScreenSaver : %s' % [args])
|
||||
pass
|
||||
|
||||
def StopScreenSaver(self, *args):
|
||||
# logevent('StopScreenSaver : %s' % [args])
|
||||
pass
|
||||
|
||||
|
||||
def logevent(msg):
|
||||
logger.info(msg)
|
||||
|
||||
# def register():
|
||||
# call the CoInitialize to allow the registration to run in an other
|
||||
# thread
|
||||
# pythoncom.CoInitialize()
|
||||
|
||||
# logevent('Registring ISensLogon')
|
||||
|
||||
# sl=SensLogon()
|
||||
# subscription_interface=pythoncom.WrapObject(sl)
|
||||
|
||||
# event_system=win32com.client.Dispatch(PROGID_EventSystem)
|
||||
|
||||
# event_subscription=win32com.client.Dispatch(PROGID_EventSubscription)
|
||||
# event_subscription.EventClassID=SENSGUID_EVENTCLASS_LOGON
|
||||
# event_subscription.PublisherID=SENSGUID_PUBLISHER
|
||||
# event_subscription.SubscriptionName='Python subscription'
|
||||
# event_subscription.SubscriberInterface=subscription_interface
|
||||
|
||||
# event_system.Store(PROGID_EventSubscription, event_subscription)
|
||||
|
||||
# pythoncom.PumpMessages()
|
||||
# #logevent('ISensLogon stopped')
|
@ -1,375 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
# pylint: disable=unused-wildcard-import, wildcard-import
|
||||
|
||||
import struct
|
||||
import subprocess
|
||||
import os
|
||||
import stat
|
||||
|
||||
import win32serviceutil # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32service # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32security # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32net # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32event # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32com.client # @UnresolvedImport, @UnusedImport, pylint: disable=import-error
|
||||
import pythoncom # @UnresolvedImport, pylint: disable=import-error
|
||||
import servicemanager # @UnresolvedImport, pylint: disable=import-error
|
||||
|
||||
from udsactor import operations
|
||||
from udsactor import store
|
||||
from udsactor.service import CommonService
|
||||
from udsactor.service import initCfg
|
||||
|
||||
from udsactor.log import logger
|
||||
|
||||
from .SENS import SensLogon
|
||||
from .SENS import logevent
|
||||
from .SENS import SENSGUID_EVENTCLASS_LOGON
|
||||
from .SENS import SENSGUID_PUBLISHER
|
||||
from .SENS import PROGID_EventSubscription
|
||||
from .SENS import PROGID_EventSystem
|
||||
|
||||
POST_CMD = 'c:\\windows\\post-uds.bat'
|
||||
|
||||
|
||||
class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService):
|
||||
'''
|
||||
This class represents a Windows Service for managing actor interactions
|
||||
with UDS Broker and Machine
|
||||
'''
|
||||
_svc_name_ = "UDSActor"
|
||||
_svc_display_name_ = "UDS Actor Service"
|
||||
_svc_description_ = "UDS Actor for machines managed by UDS Broker"
|
||||
# 'System Event Notification' is the SENS service
|
||||
_svc_deps_ = ['EventLog', 'SENS']
|
||||
|
||||
def __init__(self, args):
|
||||
win32serviceutil.ServiceFramework.__init__(self, args)
|
||||
CommonService.__init__(self)
|
||||
self.hWaitStop = win32event.CreateEvent(None, 1, 0, None)
|
||||
self._user = None
|
||||
|
||||
def SvcStop(self):
|
||||
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
|
||||
self.isAlive = False
|
||||
win32event.SetEvent(self.hWaitStop)
|
||||
|
||||
SvcShutdown = SvcStop
|
||||
|
||||
def notifyStop(self):
|
||||
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
|
||||
servicemanager.PYS_SERVICE_STOPPED,
|
||||
(self._svc_name_, ''))
|
||||
|
||||
def doWait(self, miliseconds):
|
||||
win32event.WaitForSingleObject(self.hWaitStop, miliseconds)
|
||||
|
||||
def rename(self, name, user=None, oldPassword=None, newPassword=None):
|
||||
'''
|
||||
Renames the computer, and optionally sets a password for an user
|
||||
before this
|
||||
'''
|
||||
hostName = operations.getComputerName()
|
||||
|
||||
if hostName.lower() == name.lower():
|
||||
logger.info('Computer name is now {}'.format(hostName))
|
||||
self.setReady()
|
||||
return
|
||||
|
||||
# Check for password change request for an user
|
||||
if user is not None:
|
||||
logger.info('Setting password for user {}'.format(user))
|
||||
try:
|
||||
operations.changeUserPassword(user, oldPassword, newPassword)
|
||||
except Exception as e:
|
||||
# We stop here without even renaming computer, because the
|
||||
# process has failed
|
||||
raise Exception(
|
||||
'Could not change password for user {} (maybe invalid current password is configured at broker): {} '.format(user, unicode(e)))
|
||||
|
||||
operations.renameComputer(name)
|
||||
# Reboot just after renaming
|
||||
logger.info('Rebooting computer to activate new name {}'.format(name))
|
||||
self.reboot()
|
||||
|
||||
def oneStepJoin(self, name, domain, ou, account, password):
|
||||
'''
|
||||
Ejecutes the join domain in exactly one step
|
||||
'''
|
||||
currName = operations.getComputerName()
|
||||
# If name is desired, simply execute multiStepJoin, because computer
|
||||
# name will not change
|
||||
if currName.lower() == name.lower():
|
||||
self.multiStepJoin(name, domain, ou, account, password)
|
||||
else:
|
||||
operations.renameComputer(name)
|
||||
logger.debug('Computer renamed to {} without reboot'.format(name))
|
||||
operations.joinDomain(
|
||||
domain, ou, account, password, executeInOneStep=True)
|
||||
logger.debug(
|
||||
'Requested join domain {} without errors'.format(domain))
|
||||
self.reboot()
|
||||
|
||||
def multiStepJoin(self, name, domain, ou, account, password):
|
||||
currName = operations.getComputerName()
|
||||
if currName.lower() == name.lower():
|
||||
currDomain = operations.getDomainName()
|
||||
if currDomain is not None:
|
||||
# logger.debug('Name: "{}" vs "{}", Domain: "{}" vs "{}"'.format(currName.lower(), name.lower(), currDomain.lower(), domain.lower()))
|
||||
logger.info(
|
||||
'Machine {} is part of domain {}'.format(name, domain))
|
||||
self.setReady()
|
||||
else:
|
||||
operations.joinDomain(
|
||||
domain, ou, account, password, executeInOneStep=False)
|
||||
self.reboot()
|
||||
else:
|
||||
operations.renameComputer(name)
|
||||
logger.info(
|
||||
'Rebooting computer got activate new name {}'.format(name))
|
||||
self.reboot()
|
||||
|
||||
def joinDomain(self, name, domain, ou, account, password):
|
||||
ver = operations.getWindowsVersion()
|
||||
ver = ver[0] * 10 + ver[1]
|
||||
logger.debug('Starting joining domain {} with name {} (detected operating version: {})'.format(
|
||||
domain, name, ver))
|
||||
# If file c:\compat.bin exists, joind domain in two steps instead one
|
||||
|
||||
# Accepts one step joinDomain, also remember XP is no more supported by
|
||||
# microsoft, but this also must works with it because will do a "multi
|
||||
# step" join
|
||||
if ver >= 60 and store.useOldJoinSystem() is False:
|
||||
self.oneStepJoin(name, domain, ou, account, password)
|
||||
else:
|
||||
logger.info('Using multiple step join because configuration requests to do so')
|
||||
self.multiStepJoin(name, domain, ou, account, password)
|
||||
|
||||
def preConnect(self, user, protocol):
|
||||
logger.debug('Pre connect invoked')
|
||||
if protocol != 'rdp': # If connection is not using rdp, skip adding user
|
||||
return 'ok'
|
||||
# Well known SSID for Remote Desktop Users
|
||||
REMOTE_USERS_SID = 'S-1-5-32-555'
|
||||
|
||||
p = win32security.GetBinarySid(REMOTE_USERS_SID)
|
||||
groupName = win32security.LookupAccountSid(None, p)[0]
|
||||
|
||||
useraAlreadyInGroup = False
|
||||
resumeHandle = 0
|
||||
while True:
|
||||
users, _, resumeHandle = win32net.NetLocalGroupGetMembers(None, groupName, 1, resumeHandle, 32768)
|
||||
if user.lower() in [u['name'].lower() for u in users]:
|
||||
useraAlreadyInGroup = True
|
||||
break
|
||||
if resumeHandle == 0:
|
||||
break
|
||||
|
||||
if useraAlreadyInGroup is False:
|
||||
logger.debug('User not in group, adding it')
|
||||
self._user = user
|
||||
try:
|
||||
userSSID = win32security.LookupAccountName(None, user)[0]
|
||||
win32net.NetLocalGroupAddMembers(None, groupName, 0, [{'sid': userSSID}])
|
||||
except Exception as e:
|
||||
logger.error('Exception adding user to Remote Desktop Users: {}'.format(e))
|
||||
else:
|
||||
self._user = None
|
||||
logger.debug('User {} already in group'.format(user))
|
||||
|
||||
# Now try to run pre connect command
|
||||
try:
|
||||
pre_cmd = store.preApplication()
|
||||
if os.path.isfile(pre_cmd):
|
||||
if (os.stat(pre_cmd).st_mode & stat.S_IXUSR) != 0:
|
||||
subprocess.call([pre_cmd, user, protocol])
|
||||
else:
|
||||
logger.info('PRECONNECT file exists but it it is not executable (needs execution permission by root)')
|
||||
else:
|
||||
logger.info('PRECONNECT file not found & not executed')
|
||||
except Exception as e:
|
||||
# Ignore output of execution command
|
||||
logger.error('Executing preconnect command give')
|
||||
|
||||
return 'ok'
|
||||
|
||||
def ovLogon(self, username, password):
|
||||
# Compose packet for ov
|
||||
ub = username.encode('utf8')
|
||||
up = username.encode('utf8')
|
||||
packet = struct.pack('!I', len(ub)) + ub + struct.pack('!I', len(up)) + up
|
||||
# Send packet with username/password to ov pipe
|
||||
operations.writeToPipe("\\\\.\\pipe\\VDSMDPipe", packet, True)
|
||||
return 'done'
|
||||
|
||||
def onLogout(self, user):
|
||||
logger.debug('Windows onLogout invoked: {}, {}'.format(user, self._user))
|
||||
try:
|
||||
REMOTE_USERS_SID = 'S-1-5-32-555'
|
||||
p = win32security.GetBinarySid(REMOTE_USERS_SID)
|
||||
groupName = win32security.LookupAccountSid(None, p)[0]
|
||||
except Exception:
|
||||
logger.error('Exception getting Windows Group')
|
||||
return
|
||||
|
||||
if self._user is not None:
|
||||
try:
|
||||
win32net.NetLocalGroupDelMembers(None, groupName, [self._user])
|
||||
except Exception as e:
|
||||
logger.error('Exception removing user from Remote Desktop Users: {}'.format(e))
|
||||
|
||||
def SvcDoRun(self): # pylint: disable=too-many-statements, too-many-branches
|
||||
'''
|
||||
Main service loop
|
||||
'''
|
||||
try:
|
||||
initCfg()
|
||||
|
||||
logger.debug('running SvcDoRun')
|
||||
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
|
||||
servicemanager.PYS_SERVICE_STARTED,
|
||||
(self._svc_name_, ''))
|
||||
|
||||
# call the CoInitialize to allow the registration to run in an other
|
||||
# thread
|
||||
logger.debug('Initializing com...')
|
||||
pythoncom.CoInitialize()
|
||||
|
||||
# ********************************************************
|
||||
# * Ask brokers what to do before proceding to main loop *
|
||||
# ********************************************************
|
||||
while True:
|
||||
brokerConnected = self.interactWithBroker()
|
||||
if brokerConnected is False:
|
||||
logger.debug('Interact with broker returned false, stopping service after a while')
|
||||
self.notifyStop()
|
||||
win32event.WaitForSingleObject(self.hWaitStop, 5000)
|
||||
return
|
||||
elif brokerConnected is True:
|
||||
break
|
||||
|
||||
# If brokerConnected returns None, repeat the cycle
|
||||
self.doWait(16000) # Wait for a looong while
|
||||
|
||||
if self.interactWithBroker() is False:
|
||||
logger.debug('Interact with broker returned false, stopping service after a while')
|
||||
self.notifyStop()
|
||||
win32event.WaitForSingleObject(self.hWaitStop, 5000)
|
||||
return
|
||||
|
||||
if self.isAlive is False:
|
||||
logger.debug('The service is not alive after broker interaction, stopping it')
|
||||
self.notifyStop()
|
||||
return
|
||||
|
||||
if self.rebootRequested is True:
|
||||
logger.debug('Reboot has been requested, stopping service')
|
||||
self.notifyStop()
|
||||
return
|
||||
|
||||
self.initIPC()
|
||||
except Exception: # Any init exception wil be caught, service must be then restarted
|
||||
logger.exception()
|
||||
logger.debug('Exiting service with failure status')
|
||||
os._exit(-1) # pylint: disable=protected-access
|
||||
|
||||
# ********************************
|
||||
# * Registers SENS subscriptions *
|
||||
# ********************************
|
||||
logevent('Registering ISensLogon')
|
||||
subscription_guid = '{41099152-498E-11E4-8FD3-10FEED05884B}'
|
||||
sl = SensLogon(self)
|
||||
subscription_interface = pythoncom.WrapObject(sl)
|
||||
|
||||
event_system = win32com.client.Dispatch(PROGID_EventSystem)
|
||||
|
||||
event_subscription = win32com.client.Dispatch(PROGID_EventSubscription)
|
||||
event_subscription.EventClassID = SENSGUID_EVENTCLASS_LOGON
|
||||
event_subscription.PublisherID = SENSGUID_PUBLISHER
|
||||
event_subscription.SubscriptionName = 'UDS Actor subscription'
|
||||
event_subscription.SubscriptionID = subscription_guid
|
||||
event_subscription.SubscriberInterface = subscription_interface
|
||||
|
||||
event_system.Store(PROGID_EventSubscription, event_subscription)
|
||||
|
||||
logger.debug('Registered SENS, running main loop')
|
||||
|
||||
# Execute script in c:\\windows\\post-uds.bat after interacting with broker, if no reboot is requested ofc
|
||||
# This will be executed only when machine gets "ready"
|
||||
try:
|
||||
if os.path.isfile(POST_CMD):
|
||||
subprocess.call([POST_CMD, ])
|
||||
else:
|
||||
logger.info('POST file not found & not executed')
|
||||
except Exception as e:
|
||||
# Ignore output of execution command
|
||||
logger.error('Executing post command give')
|
||||
|
||||
# *********************
|
||||
# * Main Service loop *
|
||||
# *********************
|
||||
# Counter used to check ip changes only once every 10 seconds, for
|
||||
# example
|
||||
counter = 0
|
||||
while self.isAlive:
|
||||
counter += 1
|
||||
# Process SENS messages, This will be a bit asyncronous (1 second
|
||||
# delay)
|
||||
pythoncom.PumpWaitingMessages()
|
||||
if counter >= 15: # Once every 15 seconds
|
||||
counter = 0
|
||||
try:
|
||||
self.checkIpsChanged()
|
||||
except Exception as e:
|
||||
logger.error('Error checking ip change: {}'.format(e))
|
||||
# In milliseconds, will break
|
||||
win32event.WaitForSingleObject(self.hWaitStop, 1000)
|
||||
|
||||
logger.debug('Exited main loop, deregistering SENS')
|
||||
|
||||
# *******************************************
|
||||
# * Remove SENS subscription before exiting *
|
||||
# *******************************************
|
||||
event_system.Remove(
|
||||
PROGID_EventSubscription, "SubscriptionID == " + subscription_guid)
|
||||
|
||||
self.endIPC() # Ends IPC servers
|
||||
self.endAPI() # And deinitializes REST api if needed
|
||||
|
||||
self.notifyStop()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
initCfg()
|
||||
win32serviceutil.HandleCommandLine(UDSActorSvc)
|
@ -1,32 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
@ -1,77 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import servicemanager # @UnresolvedImport, pylint: disable=import-error
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
# Valid logging levels, from UDS Broker (uds.core.utils.log)
|
||||
OTHER, DEBUG, INFO, WARN, ERROR, FATAL = (10000 * (x + 1) for x in range(6))
|
||||
|
||||
|
||||
class LocalLogger(object):
|
||||
def __init__(self):
|
||||
# tempdir is different for "user application" and "service"
|
||||
# service wil get c:\windows\temp, while user will get c:\users\XXX\temp
|
||||
logging.basicConfig(
|
||||
filename=os.path.join(tempfile.gettempdir(), 'udsactor.log'),
|
||||
filemode='a',
|
||||
format='%(levelname)s %(asctime)s %(message)s',
|
||||
level=logging.INFO
|
||||
)
|
||||
self.logger = logging.getLogger('udsactor')
|
||||
self.serviceLogger = False
|
||||
|
||||
def log(self, level, message):
|
||||
# Debug messages are logged to a file
|
||||
# our loglevels are 10000 (other), 20000 (debug), ....
|
||||
# logging levels are 10 (debug), 20 (info)
|
||||
# OTHER = logging.NOTSET
|
||||
self.logger.log(level // 1000 - 10, message)
|
||||
|
||||
if level < INFO or self.serviceLogger is False: # Only information and above will be on event log
|
||||
return
|
||||
|
||||
if level < WARN: # Info
|
||||
servicemanager.LogInfoMsg(message)
|
||||
elif level < ERROR: # WARN
|
||||
servicemanager.LogWarningMsg(message)
|
||||
else: # Error & Fatal
|
||||
servicemanager.LogErrorMsg(message)
|
||||
|
||||
def isWindows(self):
|
||||
return True
|
||||
|
||||
def isLinux(self):
|
||||
return False
|
@ -1,244 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import win32com.client # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32net # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32security # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32api # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32con # @UnresolvedImport, pylint: disable=import-error
|
||||
import ctypes
|
||||
from ctypes.wintypes import DWORD, LPCWSTR
|
||||
import os
|
||||
|
||||
from udsactor import utils
|
||||
from udsactor.log import logger
|
||||
|
||||
|
||||
def getErrorMessage(res=0):
|
||||
# sys_fs_enc = sys.getfilesystemencoding() or 'mbcs'
|
||||
msg = win32api.FormatMessage(res)
|
||||
return msg.decode('windows-1250', 'ignore')
|
||||
|
||||
|
||||
def getComputerName():
|
||||
return win32api.GetComputerNameEx(win32con.ComputerNamePhysicalDnsHostname)
|
||||
|
||||
|
||||
def getNetworkInfo():
|
||||
obj = win32com.client.Dispatch("WbemScripting.SWbemLocator")
|
||||
wmobj = obj.ConnectServer("localhost", "root\\cimv2")
|
||||
adapters = wmobj.ExecQuery("Select * from Win32_NetworkAdapterConfiguration where IpEnabled=True")
|
||||
try:
|
||||
for obj in adapters:
|
||||
for ip in obj.IPAddress:
|
||||
if ':' in ip: # Is IPV6, skip this
|
||||
continue
|
||||
if ip is None or ip == '' or ip.startswith('169.254') or ip.startswith('0.'): # If single link ip, or no ip
|
||||
continue
|
||||
# logger.debug('Net config found: {}=({}, {})'.format(obj.Caption, obj.MACAddress, ip))
|
||||
yield utils.Bunch(name=obj.Caption, mac=obj.MACAddress, ip=ip)
|
||||
except Exception:
|
||||
return
|
||||
|
||||
|
||||
def getDomainName():
|
||||
'''
|
||||
Will return the domain name if we belong a domain, else None
|
||||
(if part of a network group, will also return None)
|
||||
'''
|
||||
# Status:
|
||||
# 0 = Unknown
|
||||
# 1 = Unjoined
|
||||
# 2 = Workgroup
|
||||
# 3 = Domain
|
||||
domain, status = win32net.NetGetJoinInformation()
|
||||
if status != 3:
|
||||
domain = None
|
||||
|
||||
return domain
|
||||
|
||||
|
||||
def getWindowsVersion():
|
||||
return win32api.GetVersionEx()
|
||||
|
||||
|
||||
EWX_LOGOFF = 0x00000000
|
||||
EWX_SHUTDOWN = 0x00000001
|
||||
EWX_REBOOT = 0x00000002
|
||||
EWX_FORCE = 0x00000004
|
||||
EWX_POWEROFF = 0x00000008
|
||||
EWX_FORCEIFHUNG = 0x00000010
|
||||
|
||||
|
||||
def reboot(flags=EWX_FORCEIFHUNG | EWX_REBOOT):
|
||||
hproc = win32api.GetCurrentProcess()
|
||||
htok = win32security.OpenProcessToken(hproc, win32security.TOKEN_ADJUST_PRIVILEGES | win32security.TOKEN_QUERY)
|
||||
privs = ((win32security.LookupPrivilegeValue(None, win32security.SE_SHUTDOWN_NAME), win32security.SE_PRIVILEGE_ENABLED),)
|
||||
win32security.AdjustTokenPrivileges(htok, 0, privs)
|
||||
win32api.ExitWindowsEx(flags, 0)
|
||||
|
||||
|
||||
def loggoff():
|
||||
win32api.ExitWindowsEx(EWX_LOGOFF)
|
||||
|
||||
|
||||
def renameComputer(newName):
|
||||
# Needs admin privileges to work
|
||||
if ctypes.windll.kernel32.SetComputerNameExW(DWORD(win32con.ComputerNamePhysicalDnsHostname), LPCWSTR(newName)) == 0: # @UndefinedVariable
|
||||
# win32api.FormatMessage -> returns error string
|
||||
# win32api.GetLastError -> returns error code
|
||||
# (just put this comment here to remember to log this when logger is available)
|
||||
error = getErrorMessage()
|
||||
computerName = win32api.GetComputerNameEx(win32con.ComputerNamePhysicalDnsHostname)
|
||||
raise Exception('Error renaming computer from {} to {}: {}'.format(computerName, newName, error))
|
||||
|
||||
|
||||
NETSETUP_JOIN_DOMAIN = 0x00000001
|
||||
NETSETUP_ACCT_CREATE = 0x00000002
|
||||
NETSETUP_ACCT_DELETE = 0x00000004
|
||||
NETSETUP_WIN9X_UPGRADE = 0x00000010
|
||||
NETSETUP_DOMAIN_JOIN_IF_JOINED = 0x00000020
|
||||
NETSETUP_JOIN_UNSECURE = 0x00000040
|
||||
NETSETUP_MACHINE_PWD_PASSED = 0x00000080
|
||||
NETSETUP_JOIN_WITH_NEW_NAME = 0x00000400
|
||||
NETSETUP_DEFER_SPN_SET = 0x1000000
|
||||
|
||||
|
||||
def joinDomain(domain, ou, account, password, executeInOneStep=False):
|
||||
'''
|
||||
Joins machine to a windows domain
|
||||
:param domain: Domain to join to
|
||||
:param ou: Ou that will hold machine
|
||||
:param account: Account used to join domain
|
||||
:param password: Password of account used to join domain
|
||||
:param executeInOneStep: If true, means that this machine has been renamed and wants to add NETSETUP_JOIN_WITH_NEW_NAME to request so we can do rename/join in one step.
|
||||
'''
|
||||
# If account do not have domain, include it
|
||||
if '@' not in account and '\\' not in account:
|
||||
if '.' in domain:
|
||||
account = account + '@' + domain
|
||||
else:
|
||||
account = domain + '\\' + account
|
||||
|
||||
# Do log
|
||||
flags = NETSETUP_ACCT_CREATE | NETSETUP_DOMAIN_JOIN_IF_JOINED | NETSETUP_JOIN_DOMAIN
|
||||
|
||||
if executeInOneStep:
|
||||
flags |= NETSETUP_JOIN_WITH_NEW_NAME
|
||||
|
||||
flags = DWORD(flags)
|
||||
|
||||
domain = LPCWSTR(domain)
|
||||
|
||||
# Must be in format "ou=.., ..., dc=...,"
|
||||
ou = LPCWSTR(ou) if ou is not None and ou != '' else None
|
||||
account = LPCWSTR(account)
|
||||
password = LPCWSTR(password)
|
||||
|
||||
res = ctypes.windll.netapi32.NetJoinDomain(None, domain, ou, account, password, flags)
|
||||
# Machine found in another ou, use it and warn this on log
|
||||
if res == 2224:
|
||||
flags = DWORD(NETSETUP_DOMAIN_JOIN_IF_JOINED | NETSETUP_JOIN_DOMAIN)
|
||||
res = ctypes.windll.netapi32.NetJoinDomain(None, domain, None, account, password, flags)
|
||||
if res != 0:
|
||||
# Log the error
|
||||
error = getErrorMessage(res)
|
||||
if res == 1355:
|
||||
error = "DC Is not reachable"
|
||||
logger.error('Error joining domain: {}, {}'.format(error, res))
|
||||
raise Exception('Error joining domain {}, with credentials {}/*****{}: {}, {}'.format(domain, account, ', under OU {}'.format(ou) if ou is not None else '', res, error))
|
||||
|
||||
|
||||
def changeUserPassword(user, oldPassword, newPassword):
|
||||
computerName = LPCWSTR(getComputerName())
|
||||
user = LPCWSTR(user)
|
||||
oldPassword = LPCWSTR(oldPassword)
|
||||
newPassword = LPCWSTR(newPassword)
|
||||
|
||||
res = ctypes.windll.netapi32.NetUserChangePassword(computerName, user, oldPassword, newPassword)
|
||||
|
||||
if res != 0:
|
||||
# Log the error, and raise exception to parent
|
||||
error = getErrorMessage(res)
|
||||
raise Exception('Error changing password for user {}: {} {}'.format(user.value, res, error))
|
||||
|
||||
|
||||
class LASTINPUTINFO(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('cbSize', ctypes.c_uint),
|
||||
('dwTime', ctypes.c_uint),
|
||||
]
|
||||
|
||||
|
||||
def initIdleDuration(atLeastSeconds):
|
||||
'''
|
||||
In windows, there is no need to set screensaver
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
def getIdleDuration():
|
||||
try:
|
||||
lastInputInfo = LASTINPUTINFO()
|
||||
lastInputInfo.cbSize = ctypes.sizeof(lastInputInfo)
|
||||
if ctypes.windll.user32.GetLastInputInfo(ctypes.byref(lastInputInfo)) == 0:
|
||||
return 0
|
||||
# if lastInputInfo.dwTime > 1000000000: # Value toooo high, nonsense...
|
||||
# return 0
|
||||
current = ctypes.c_uint(ctypes.windll.kernel32.GetTickCount())
|
||||
millis = current.value - lastInputInfo.dwTime # @UndefinedVariable
|
||||
if millis < 0:
|
||||
return 0
|
||||
return millis / 1000.0
|
||||
except Exception as e:
|
||||
logger.error('Getting idle duration: {}'.format(e))
|
||||
return 0
|
||||
|
||||
|
||||
def getCurrentUser():
|
||||
'''
|
||||
Returns current logged in username
|
||||
'''
|
||||
return os.environ['USERNAME']
|
||||
|
||||
def writeToPipe(pipeName, bytesPayload, waitForResponse):
|
||||
# (str, bytes, bool) -> Optional[bytes]
|
||||
try:
|
||||
with open(pipeName, 'r+b', 0) as f:
|
||||
f.write(bytesPayload)
|
||||
# f.seek(0) # As recommended on intenet, but seems to work fin without thos
|
||||
if waitForResponse:
|
||||
return f.read()
|
||||
return b'ok'
|
||||
except Exception as e:
|
||||
None
|
@ -1,143 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import pickle
|
||||
from win32com.shell import shell # @UnresolvedImport, pylint: disable=import-error
|
||||
try:
|
||||
import winreg as wreg
|
||||
except ImportError: # Python 2.7 fallback
|
||||
import _winreg as wreg # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32security # @UnresolvedImport, pylint: disable=import-error
|
||||
|
||||
DEBUG = False
|
||||
|
||||
|
||||
# Can be changed to whatever we want, but registry key is protected by permissions
|
||||
def encoder(data):
|
||||
return data.encode('bz2')
|
||||
|
||||
|
||||
def decoder(data):
|
||||
return data.decode('bz2')
|
||||
|
||||
|
||||
path = 'Software\\UDSActor'
|
||||
baseKey = wreg.HKEY_CURRENT_USER if DEBUG is True else wreg.HKEY_LOCAL_MACHINE # @UndefinedVariable
|
||||
|
||||
|
||||
def checkPermissions():
|
||||
return True if DEBUG else shell.IsUserAnAdmin()
|
||||
|
||||
|
||||
def fixRegistryPermissions(handle):
|
||||
if DEBUG:
|
||||
return
|
||||
# Fix permissions so users can't read this key
|
||||
v = win32security.GetSecurityInfo(handle, win32security.SE_REGISTRY_KEY, win32security.DACL_SECURITY_INFORMATION)
|
||||
dacl = v.GetSecurityDescriptorDacl()
|
||||
n = 0
|
||||
# Remove all normal users access permissions to the registry key
|
||||
while n < dacl.GetAceCount():
|
||||
if unicode(dacl.GetAce(n)[2]) == u'PySID:S-1-5-32-545': # Whell known Users SID
|
||||
dacl.DeleteAce(n)
|
||||
else:
|
||||
n += 1
|
||||
win32security.SetSecurityInfo(handle, win32security.SE_REGISTRY_KEY,
|
||||
win32security.DACL_SECURITY_INFORMATION | win32security.PROTECTED_DACL_SECURITY_INFORMATION,
|
||||
None, None, dacl, None)
|
||||
|
||||
|
||||
def readConfig():
|
||||
try:
|
||||
key = wreg.OpenKey(baseKey, path, 0, wreg.KEY_QUERY_VALUE) # @UndefinedVariable
|
||||
data, _ = wreg.QueryValueEx(key, '') # @UndefinedVariable
|
||||
wreg.CloseKey(key) # @UndefinedVariable
|
||||
return pickle.loads(decoder(data))
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def writeConfig(data, fixPermissions=True):
|
||||
try:
|
||||
key = wreg.OpenKey(baseKey, path, 0, wreg.KEY_ALL_ACCESS) # @UndefinedVariable
|
||||
except Exception:
|
||||
key = wreg.CreateKeyEx(baseKey, path, 0, wreg.KEY_ALL_ACCESS) # @UndefinedVariable
|
||||
if fixPermissions is True:
|
||||
fixRegistryPermissions(key.handle)
|
||||
|
||||
wreg.SetValueEx(key, "", 0, wreg.REG_BINARY, encoder(pickle.dumps(data))) # @UndefinedVariable
|
||||
wreg.CloseKey(key) # @UndefinedVariable
|
||||
|
||||
|
||||
def useOldJoinSystem():
|
||||
try:
|
||||
key = wreg.OpenKey(baseKey, 'Software\\UDSEnterpriseActor', 0, wreg.KEY_QUERY_VALUE) # @UndefinedVariable
|
||||
try:
|
||||
data, _ = wreg.QueryValueEx(key, 'join') # @UndefinedVariable
|
||||
except Exception:
|
||||
data = ''
|
||||
wreg.CloseKey(key) # @UndefinedVariable
|
||||
except:
|
||||
data = ''
|
||||
|
||||
return data == 'old'
|
||||
|
||||
|
||||
# Gives the oportunity to run an application ONE TIME (because, the registry key "run" will be deleted after read)
|
||||
def runApplication():
|
||||
try:
|
||||
key = wreg.OpenKey(baseKey, 'Software\\UDSEnterpriseActor', 0, wreg.KEY_ALL_ACCESS) # @UndefinedVariable
|
||||
try:
|
||||
data, _ = wreg.QueryValueEx(key, 'run') # @UndefinedVariable
|
||||
wreg.DeleteValue(key, 'run') # @UndefinedVariable
|
||||
except Exception:
|
||||
data = None
|
||||
wreg.CloseKey(key) # @UndefinedVariable
|
||||
except Exception:
|
||||
data = None
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def preApplication():
|
||||
try:
|
||||
key = wreg.OpenKey(baseKey, 'Software\\UDSEnterpriseActor', 0, wreg.KEY_ALL_ACCESS) # @UndefinedVariable
|
||||
try:
|
||||
data, _ = wreg.QueryValueEx(key, 'pre') # @UndefinedVariable
|
||||
except Exception:
|
||||
data = None
|
||||
wreg.CloseKey(key) # @UndefinedVariable
|
||||
except Exception:
|
||||
data = None
|
||||
|
||||
return data
|
@ -1,15 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
function process {
|
||||
pyuic4 about-dialog.ui -o about_dialog_ui.py -x
|
||||
pyuic4 message-dialog.ui -o message_dialog_ui.py -x
|
||||
pyuic4 setup-dialog.ui -o setup_dialog_ui.py -x
|
||||
}
|
||||
|
||||
pyrcc4 -py3 UDSActor.qrc -o UDSActor_rc.py
|
||||
|
||||
|
||||
# process current directory ui's
|
||||
process
|
||||
|
Loading…
Reference in New Issue
Block a user