Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
CIRCLE
/
agent
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
7
Merge Requests
0
Wiki
Members
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
1d60a2b2
authored
Sep 18, 2014
by
Guba Sándor
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
re-refactor Context
parent
56441d4b
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
177 additions
and
585 deletions
+177
-585
agent.py
+9
-37
context.py
+118
-13
linux/_linuxcontext.py
+3
-2
win32/_win32context.py
+46
-425
win32/network.py
+1
-108
No files found.
agent.py
View file @
1d60a2b2
...
...
@@ -25,12 +25,15 @@ from twisted.internet.task import LoopingCall
import
uptime
import
logging
from
os.path
import
exists
from
inspect
import
getargspec
,
isfunction
from
utils
import
SerialLineReceiverBase
from
context
import
Context
# Note: Import everything because later we need to use the BaseContext (relative
# import error.
from
context
import
*
Context
=
get_context
()
logging
.
basicConfig
()
logger
=
logging
.
getLogger
()
...
...
@@ -145,43 +148,12 @@ class SerialLineReceiver(SerialLineReceiverBase):
pass
def
_get_virtio_device
():
path
=
None
GUID
=
'{6FDE7521-1B65-48ae-B628-80BE62016026}'
from
infi.devicemanager
import
DeviceManager
dm
=
DeviceManager
()
dm
.
root
.
rescan
()
# Search Virtio-Serial by name TODO: search by class_guid
for
i
in
dm
.
all_devices
:
if
i
.
has_property
(
"description"
):
if
"virtio-serial"
.
upper
()
in
i
.
description
.
upper
():
path
=
(
"
\\\\
?
\\
"
+
i
.
children
[
0
]
.
instance_id
.
lower
()
.
replace
(
'
\\
'
,
'#'
)
+
"#"
+
GUID
.
lower
()
)
return
path
def
main
():
port
=
None
if
system
==
'Windows'
:
port
=
_get_virtio_device
()
if
port
:
from
context
import
SerialPort
else
:
from
twisted.internet.serial
import
SerialPort
import
pythoncom
pythoncom
.
CoInitialize
()
port
=
r'\\.\COM1'
else
:
port
=
"/dev/virtio-ports/agent"
if
exists
(
port
):
from
context
import
SerialPort
else
:
from
twisted.internet.serial
import
SerialPort
port
=
'/dev/ttyS0'
# Get proper serial class and port name
(
serial
,
port
)
=
get_serial
()
logger
.
info
(
"Opening port
%
s"
,
port
)
SerialPort
(
SerialLineReceiver
(),
port
,
reactor
)
# Open serial connection
serial
(
SerialLineReceiver
(),
port
,
reactor
)
try
:
from
notify
import
register_publisher
register_publisher
(
reactor
)
...
...
context.py
View file @
1d60a2b2
import
platform
from
os.path
import
exists
""" This is the defautl context file. It replaces the Context class
to the platform specific one.
"""
system
=
platform
.
system
()
if
system
==
"Windows"
:
from
windows._win32context
import
Context
from
win32.win32virtio
import
SerialPort
elif
system
==
"Linux"
:
from
linux._linuxcontext
import
Context
from
linux.posixvirtio
import
SerialPort
def
_get_virtio_device
():
path
=
None
GUID
=
'{6FDE7521-1B65-48ae-B628-80BE62016026}'
from
infi.devicemanager
import
DeviceManager
dm
=
DeviceManager
()
dm
.
root
.
rescan
()
# Search Virtio-Serial by name TODO: search by class_guid
for
i
in
dm
.
all_devices
:
if
i
.
has_property
(
"description"
):
if
"virtio-serial"
.
upper
()
in
i
.
description
.
upper
():
path
=
(
"
\\\\
?
\\
"
+
i
.
children
[
0
]
.
instance_id
.
lower
()
.
replace
(
'
\\
'
,
'#'
)
+
"#"
+
GUID
.
lower
()
)
return
path
else
:
raise
NotImplementedError
(
"Platform
%
s is not supported."
,
system
)
def
get_context
():
system
=
platform
.
system
()
if
system
==
"Windows"
:
from
win32._win32context
import
Context
elif
system
==
"Linux"
:
from
linux._linuxcontext
import
Context
else
:
raise
NotImplementedError
(
"Platform
%
s is not supported."
,
system
)
return
Context
class
BaseContext
():
pass
Context
SerialPort
def
get_serial
():
system
=
platform
.
system
()
port
=
None
if
system
==
'Windows'
:
port
=
_get_virtio_device
()
if
port
:
from
win32.win32virtio
import
SerialPort
else
:
from
twisted.internet.serial
import
SerialPort
import
pythoncom
pythoncom
.
CoInitialize
()
port
=
r'\\.\COM1'
elif
system
==
"Linux"
:
port
=
"/dev/virtio-ports/agent"
if
exists
(
port
):
from
linux.posixvirtio
import
SerialPort
else
:
from
twisted.internet.serial
import
SerialPort
port
=
'/dev/ttyS0'
else
:
raise
NotImplementedError
(
"Platform
%
s is not supported."
,
system
)
return
(
SerialPort
,
port
)
class
BaseContext
(
object
):
@staticmethod
def
change_password
(
password
):
pass
@staticmethod
def
restart_networking
():
pass
@staticmethod
def
change_ip
(
interfaces
,
dns
):
pass
@staticmethod
def
set_time
(
time
):
pass
@staticmethod
def
set_hostname
(
hostname
):
pass
@staticmethod
def
mount_store
(
host
,
username
,
password
):
pass
@staticmethod
def
get_keys
():
pass
@staticmethod
def
add_keys
(
keys
):
pass
@staticmethod
def
del_keys
(
keys
):
pass
@staticmethod
def
cleanup
():
pass
@staticmethod
def
start_access_server
():
pass
@staticmethod
def
append
(
data
,
filename
,
chunk_number
,
uuid
):
pass
@staticmethod
def
update
(
filename
,
executable
,
checksum
,
uuid
):
pass
@staticmethod
def
ipaddresses
():
pass
@staticmethod
def
get_agent_version
():
try
:
with
open
(
'version.txt'
)
as
f
:
return
f
.
readline
()
except
IOError
:
return
None
@staticmethod
def
send_expiration
(
url
):
import
notify
notify
.
notify
(
url
)
linux/_linuxcontext.py
View file @
1d60a2b2
...
...
@@ -30,7 +30,8 @@ from hashlib import md5
from
ssh
import
PubKey
from
network
import
change_ip_ubuntu
,
change_ip_rhel
from
.network
import
change_ip_ubuntu
,
change_ip_rhel
from
context
import
BaseContext
from
twisted.internet
import
reactor
...
...
@@ -58,7 +59,7 @@ if system == 'Linux':
distro
=
distros
[
platform
.
linux_distribution
()[
0
]]
class
Context
(
objec
t
):
class
Context
(
BaseContex
t
):
# http://stackoverflow.com/questions/12081310/
# python-module-to-change-system-date-and-time
...
...
win32/_win32context.py
View file @
1d60a2b2
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from
os
import
mkdir
,
environ
,
chdir
import
platform
from
shutil
import
copy
import
subprocess
import
sys
system
=
platform
.
system
()
working_directory
=
"C:/agent"
try
:
chdir
(
sys
.
path
[
0
])
subprocess
.
call
((
'pip'
,
'install'
,
'-r'
,
'requirements.txt'
))
if
system
==
'Linux'
:
copy
(
"/root/agent/misc/vm_renewal"
,
"/usr/local/bin/"
)
except
:
pass
# hope it works
from
os
import
environ
,
join
from
twisted.internet
import
reactor
,
defer
from
twisted.internet.task
import
LoopingCall
import
uptime
import
logging
import
fileinput
import
tarfile
from
os.path
import
expanduser
,
join
,
exists
from
glob
import
glob
from
inspect
import
getargspec
,
isfunction
from
StringIO
import
StringIO
from
base64
import
decodestring
from
hashlib
import
md5
from
shutil
import
rmtree
,
move
from
datetime
import
datetime
import
win32api
import
wmi
import
netifaces
from
utils
import
SerialLineReceiverBase
from
twisted.internet
import
reactor
from
ssh
import
PubKey
from
network
import
change_ip_ubuntu
,
change_ip_rhel
,
change_ip_windows
from
.network
import
change_ip_windows
from
context
import
BaseContext
logging
.
basicConfig
()
...
...
@@ -46,260 +29,74 @@ logger = logging.getLogger()
level
=
environ
.
get
(
'LOGLEVEL'
,
'INFO'
)
logger
.
setLevel
(
level
)
SSH_DIR
=
expanduser
(
'~cloud/.ssh'
)
AUTHORIZED_KEYS
=
join
(
SSH_DIR
,
'authorized_keys'
)
STORE_DIR
=
'/store'
mount_template_linux
=
(
'//
%(host)
s/
%(username)
s
%(dir)
s cifs username=
%(username)
s'
',password=
%(password)
s,iocharset=utf8,uid=cloud 0 0
\n
'
)
distros
=
{
'Scientific Linux'
:
'rhel'
,
'CentOS'
:
'rhel'
,
'CentOS Linux'
:
'rhel'
,
'Debian'
:
'debian'
,
'Ubuntu'
:
'debian'
}
if
system
==
'Linux'
:
distro
=
distros
[
platform
.
linux_distribution
()[
0
]]
# http://stackoverflow.com/questions/12081310/
# python-module-to-change-system-date-and-time
def
linux_set_time
(
time
):
import
ctypes
import
ctypes.util
CLOCK_REALTIME
=
0
class
timespec
(
ctypes
.
Structure
):
_fields_
=
[(
"tv_sec"
,
ctypes
.
c_long
),
(
"tv_nsec"
,
ctypes
.
c_long
)]
librt
=
ctypes
.
CDLL
(
ctypes
.
util
.
find_library
(
"rt"
))
ts
=
timespec
()
ts
.
tv_sec
=
int
(
time
)
ts
.
tv_nsec
=
0
librt
.
clock_settime
(
CLOCK_REALTIME
,
ctypes
.
byref
(
ts
))
class
Context
(
object
):
class
Context
(
BaseContext
):
@staticmethod
def
change_password
(
password
):
if
system
==
'Linux'
:
proc
=
subprocess
.
Popen
([
'/usr/sbin/chpasswd'
],
stdin
=
subprocess
.
PIPE
)
proc
.
communicate
(
'cloud:
%
s
\n
'
%
password
)
elif
system
==
'Windows'
:
from
win32com
import
adsi
ads_obj
=
adsi
.
ADsGetObject
(
'WinNT://localhost/
%
s,user'
%
'cloud'
)
ads_obj
.
Getinfo
()
ads_obj
.
SetPassword
(
password
)
from
win32com
import
adsi
ads_obj
=
adsi
.
ADsGetObject
(
'WinNT://localhost/
%
s,user'
%
'cloud'
)
ads_obj
.
Getinfo
()
ads_obj
.
SetPassword
(
password
)
@staticmethod
def
restart_networking
():
if
system
==
'Linux'
:
if
distro
==
'debian'
:
subprocess
.
call
([
'/etc/init.d/networking'
,
'restart'
])
elif
distro
==
'rhel'
:
subprocess
.
call
([
'/bin/systemctl'
,
'restart'
,
'network'
])
pass
elif
system
==
'Windows'
:
pass
pass
@staticmethod
def
change_ip
(
interfaces
,
dns
):
if
system
==
'Linux'
:
if
distro
==
'debian'
:
change_ip_ubuntu
(
interfaces
,
dns
)
elif
distro
==
'rhel'
:
change_ip_rhel
(
interfaces
,
dns
)
elif
system
==
'Windows'
:
change_ip_windows
(
interfaces
,
dns
)
change_ip_windows
(
interfaces
,
dns
)
@staticmethod
def
set_time
(
time
):
if
system
==
'Linux'
:
linux_set_time
(
float
(
time
))
try
:
subprocess
.
call
([
'/etc/init.d/ntp'
,
'restart'
])
except
:
pass
elif
system
==
'Windows'
:
import
win32api
t
=
datetime
.
utcfromtimestamp
(
float
(
time
))
win32api
.
SetSystemTime
(
t
.
year
,
t
.
month
,
0
,
t
.
day
,
t
.
hour
,
t
.
minute
,
t
.
second
,
0
)
t
=
datetime
.
utcfromtimestamp
(
float
(
time
))
win32api
.
SetSystemTime
(
t
.
year
,
t
.
month
,
0
,
t
.
day
,
t
.
hour
,
t
.
minute
,
t
.
second
,
0
)
@staticmethod
def
set_hostname
(
hostname
):
if
system
==
'Linux'
:
if
distro
==
'debian'
:
with
open
(
'/etc/hostname'
,
'w'
)
as
f
:
f
.
write
(
hostname
)
elif
distro
==
'rhel'
:
for
line
in
fileinput
.
input
(
'/etc/sysconfig/network'
,
inplace
=
1
):
if
line
.
startswith
(
'HOSTNAME='
):
print
'HOSTNAME=
%
s'
%
hostname
else
:
print
line
.
rstrip
()
with
open
(
'/etc/hosts'
,
'w'
)
as
f
:
f
.
write
(
"127.0.0.1 localhost
\n
"
"127.0.1.1
%
s
\n
"
%
hostname
)
subprocess
.
call
([
'/bin/hostname'
,
hostname
])
elif
system
==
'Windows'
:
import
wmi
wmi
.
WMI
()
.
Win32_ComputerSystem
()[
0
]
.
Rename
(
hostname
)
wmi
.
WMI
()
.
Win32_ComputerSystem
()[
0
]
.
Rename
(
hostname
)
@staticmethod
def
mount_store
(
host
,
username
,
password
):
data
=
{
'host'
:
host
,
'username'
:
username
,
'password'
:
password
}
if
system
==
'Linux'
:
data
[
'dir'
]
=
STORE_DIR
if
not
exists
(
STORE_DIR
):
mkdir
(
STORE_DIR
)
# TODO
for
line
in
fileinput
.
input
(
'/etc/fstab'
,
inplace
=
True
):
if
not
(
line
.
startswith
(
'//'
)
and
' cifs '
in
line
):
print
line
.
rstrip
()
with
open
(
'/etc/fstab'
,
'a'
)
as
f
:
f
.
write
(
mount_template_linux
%
data
)
subprocess
.
call
(
'mount -a'
,
shell
=
True
)
elif
system
==
'Windows'
:
import
notify
url
=
'cifs://
%
s:
%
s@
%
s/
%
s'
%
(
username
,
password
,
host
,
username
)
for
c
in
notify
.
clients
:
logger
.
debug
(
"sending url
%
s to client
%
s"
,
url
,
unicode
(
c
))
c
.
sendLine
(
url
.
encode
())
import
notify
url
=
'cifs://
%
s:
%
s@
%
s/
%
s'
%
(
username
,
password
,
host
,
username
)
for
c
in
notify
.
clients
:
logger
.
debug
(
"sending url
%
s to client
%
s"
,
url
,
unicode
(
c
))
c
.
sendLine
(
url
.
encode
())
@staticmethod
def
get_keys
():
retval
=
[]
try
:
with
open
(
AUTHORIZED_KEYS
,
'r'
)
as
f
:
for
line
in
f
.
readlines
():
try
:
retval
.
append
(
PubKey
.
from_str
(
line
))
except
:
logger
.
exception
(
u'Invalid ssh key: '
)
except
IOError
:
pass
return
retval
@staticmethod
def
_save_keys
(
keys
):
print
keys
try
:
mkdir
(
SSH_DIR
)
except
OSError
:
pass
with
open
(
AUTHORIZED_KEYS
,
'w'
)
as
f
:
for
key
in
keys
:
f
.
write
(
unicode
(
key
)
+
'
\n
'
)
pass
@staticmethod
def
add_keys
(
keys
):
if
system
==
'Linux'
:
new_keys
=
Context
.
get_keys
()
for
key
in
keys
:
try
:
p
=
PubKey
.
from_str
(
key
)
if
p
not
in
new_keys
:
new_keys
.
append
(
p
)
except
:
logger
.
exception
(
u'Invalid ssh key: '
)
Context
.
_save_keys
(
new_keys
)
pass
@staticmethod
def
del_keys
(
keys
):
if
system
==
'Linux'
:
new_keys
=
Context
.
get_keys
()
for
key
in
keys
:
try
:
p
=
PubKey
.
from_str
(
key
)
try
:
new_keys
.
remove
(
p
)
except
ValueError
:
pass
except
:
logger
.
exception
(
u'Invalid ssh key: '
)
Context
.
_save_keys
(
new_keys
)
pass
@staticmethod
def
cleanup
():
if
system
==
'Linux'
:
filelist
=
([
'/root/.bash_history'
'/home/cloud/.bash_history'
'/root/.ssh'
'/home/cloud/.ssh'
]
+
glob
(
'/etc/ssh/ssh_host_*'
))
for
f
in
filelist
:
rmtree
(
f
,
ignore_errors
=
True
)
subprocess
.
call
((
'/usr/bin/ssh-keygen'
,
'-A'
))
elif
system
==
'Windows'
:
# TODO
pass
# TODO
pass
@staticmethod
def
start_access_server
():
if
system
==
'Linux'
:
try
:
subprocess
.
call
((
'/sbin/start'
,
'ssh'
))
except
OSError
:
subprocess
.
call
((
'/bin/systemctl'
,
'start'
,
'sshd.service'
))
elif
system
==
'Windows'
:
# TODO
pass
@classmethod
def
_update_linux
(
cls
,
data
,
uuid
):
cur_dir
=
sys
.
path
[
0
]
new_dir
=
cur_dir
+
'.new'
old_dir
=
cur_dir
+
'.old'
f
=
StringIO
(
decodestring
(
data
))
try
:
tar
=
tarfile
.
TarFile
.
open
(
"dummy"
,
fileobj
=
f
,
mode
=
'r|gz'
)
tar
.
extractall
(
new_dir
)
except
tarfile
.
ReadError
as
e
:
logger
.
error
(
e
)
else
:
rmtree
(
old_dir
,
ignore_errors
=
True
)
move
(
cur_dir
,
old_dir
)
move
(
new_dir
,
cur_dir
)
logger
.
info
(
'Updated'
)
reactor
.
stop
()
# TODO
pass
@classmethod
def
_update_windows
(
cls
,
data
,
executable
,
uuid
):
# Extract the tar to the new path
cur_dir
=
sys
.
path
[
0
]
new_dir
=
cur_dir
+
'.version'
f
=
StringIO
(
decodestring
(
data
))
try
:
tar
=
tarfile
.
TarFile
.
open
(
"dummy"
,
fileobj
=
f
,
mode
=
'r|gz'
)
tar
.
extractall
(
new_dir
)
except
tarfile
.
ReadError
as
e
:
logger
.
error
(
e
)
@staticmethod
def
append
(
data
,
filename
,
chunk_number
,
uuid
):
if
chunk_number
==
0
:
flag
=
"w"
else
:
cls
.
_update_registry
(
new_dir
,
executable
)
logger
.
info
(
'Updated'
)
reactor
.
stop
(
)
flag
=
"a"
with
open
(
filename
,
flag
)
as
myfile
:
myfile
.
write
(
data
)
@
class
method
@
static
method
def
_update_registry
(
cls
,
dir
,
executable
):
# HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\circle-agent
from
_winreg
import
(
OpenKeyEx
,
SetValueEx
,
QueryValueEx
,
...
...
@@ -311,41 +108,27 @@ class Context(object):
(
old_executable
,
reg_type
)
=
QueryValueEx
(
key
,
"ImagePath"
)
SetValueEx
(
key
,
"ImagePath"
,
None
,
2
,
join
(
dir
,
executable
))
return
old_executable
@staticmethod
def
append
(
data
,
filename
,
chunk_number
,
uuid
):
if
chunk_number
==
0
:
flag
=
"w"
else
:
flag
=
"a"
with
open
(
filename
,
flag
)
as
myfile
:
myfile
.
write
(
data
)
@staticmethod
def
append_end
(
filenam
e
,
checksum
,
uuid
):
def
update
(
filename
,
executabl
e
,
checksum
,
uuid
):
with
open
(
filename
,
"r"
)
as
f
:
data
=
f
.
read
()
local_checksum
=
md5
(
data
)
.
hexdigest
()
if
local_checksum
!=
checksum
:
raise
Exception
(
"Checksum missmatch the file is damaged."
)
decoded
=
StringIO
(
decodestring
(
data
))
decoded
=
StringIO
(
decodestring
(
data
))
try
:
tar
=
tarfile
.
TarFile
.
open
(
"dummy"
,
fileobj
=
decoded
,
mode
=
'r|gz'
)
tar
.
extractall
(
"/tmp"
)
tar
.
extractall
(
working_directory
)
except
tarfile
.
ReadError
as
e
:
logger
.
error
(
e
)
logger
.
info
(
"Transfer completed!"
)
@staticmethod
def
update
(
data
,
executable
,
uuid
):
if
system
==
"Windows"
:
Context
.
_update_windows
(
data
,
executable
,
uuid
)
else
:
Context
.
_update_linux
(
data
,
executable
,
uuid
)
Context
.
_update_registry
(
working_directory
,
executable
)
logger
.
info
(
'Updated'
)
reactor
.
stop
()
@staticmethod
def
ipaddresses
():
import
netifaces
args
=
{}
interfaces
=
netifaces
.
interfaces
()
for
i
in
interfaces
:
...
...
@@ -363,169 +146,7 @@ class Context(object):
@staticmethod
def
get_agent_version
():
try
:
with
open
(
'version.txt'
)
as
f
:
with
open
(
join
(
working_directory
,
'version.txt'
)
)
as
f
:
return
f
.
readline
()
except
IOError
:
return
None
@staticmethod
def
send_expiration
(
url
):
import
notify
notify
.
notify
(
url
)
class
SerialLineReceiver
(
SerialLineReceiverBase
):
def
connectionMade
(
self
):
self
.
send_command
(
command
=
'agent_started'
,
args
=
{
'version'
:
Context
.
get_agent_version
(),
'system'
:
system
})
def
shutdown
():
self
.
connectionLost2
(
'shutdown'
)
d
=
defer
.
Deferred
()
reactor
.
callLater
(
0.3
,
d
.
callback
,
"1"
)
return
d
reactor
.
addSystemEventTrigger
(
"before"
,
"shutdown"
,
shutdown
)
def
connectionLost2
(
self
,
reason
):
self
.
send_command
(
command
=
'agent_stopped'
,
args
=
{})
def
tick
(
self
):
logger
.
debug
(
"Sending tick"
)
try
:
self
.
send_status
()
except
:
logger
.
exception
(
"Twisted hide exception"
)
def
__init__
(
self
):
super
(
SerialLineReceiver
,
self
)
.
__init__
()
self
.
lc
=
LoopingCall
(
self
.
tick
)
self
.
lc
.
start
(
5
,
now
=
False
)
def
send_status
(
self
):
import
psutil
disk_usage
=
{(
disk
.
device
.
replace
(
'/'
,
'_'
)):
psutil
.
disk_usage
(
disk
.
mountpoint
)
.
percent
for
disk
in
psutil
.
disk_partitions
()}
args
=
{
"cpu"
:
dict
(
psutil
.
cpu_times
()
.
_asdict
()),
"ram"
:
dict
(
psutil
.
virtual_memory
()
.
_asdict
()),
"swap"
:
dict
(
psutil
.
swap_memory
()
.
_asdict
()),
"uptime"
:
{
"seconds"
:
uptime
.
uptime
()},
"disk"
:
disk_usage
,
"user"
:
{
"count"
:
len
(
psutil
.
get_users
())}}
self
.
send_response
(
response
=
'status'
,
args
=
args
)
def
_check_args
(
self
,
func
,
args
):
if
not
isinstance
(
args
,
dict
):
raise
TypeError
(
"Arguments should be all keyword-arguments in a "
"dict for command
%
s instead of
%
s."
%
(
self
.
_pretty_fun
(
func
),
type
(
args
)
.
__name__
))
# check for unexpected keyword arguments
argspec
=
getargspec
(
func
)
if
argspec
.
keywords
is
None
:
# _operation doesn't take ** args
unexpected_kwargs
=
set
(
args
)
-
set
(
argspec
.
args
)
if
unexpected_kwargs
:
raise
TypeError
(
"Command
%
s got unexpected keyword arguments:
%
s"
%
(
self
.
_pretty_fun
(
func
),
", "
.
join
(
unexpected_kwargs
)))
mandatory_args
=
argspec
.
args
if
argspec
.
defaults
:
# remove those with default value
mandatory_args
=
mandatory_args
[
0
:
-
len
(
argspec
.
defaults
)]
missing_kwargs
=
set
(
mandatory_args
)
-
set
(
args
)
if
missing_kwargs
:
raise
TypeError
(
"Command
%
s missing arguments:
%
s"
%
(
self
.
_pretty_fun
(
func
),
", "
.
join
(
missing_kwargs
)))
def
_get_command
(
self
,
command
,
args
):
if
not
isinstance
(
command
,
basestring
)
or
command
.
startswith
(
'_'
):
raise
AttributeError
(
u'Invalid command:
%
s'
%
command
)
try
:
func
=
getattr
(
Context
,
command
)
except
AttributeError
as
e
:
raise
AttributeError
(
u'Command not found:
%
s (
%
s)'
%
(
command
,
e
))
if
not
isfunction
(
func
):
raise
AttributeError
(
"Command refers to non-static method
%
s."
%
self
.
_pretty_fun
(
func
))
self
.
_check_args
(
func
,
args
)
return
func
@staticmethod
def
_pretty_fun
(
fun
):
try
:
argspec
=
getargspec
(
fun
)
args
=
argspec
.
args
if
argspec
.
varargs
:
args
.
append
(
"*"
+
argspec
.
varargs
)
if
argspec
.
keywords
:
args
.
append
(
"**"
+
argspec
.
keywords
)
return
"
%
s(
%
s)"
%
(
fun
.
__name__
,
","
.
join
(
args
))
except
:
return
"<
%
s>"
%
type
(
fun
)
.
__name__
def
handle_command
(
self
,
command
,
args
):
func
=
self
.
_get_command
(
command
,
args
)
retval
=
func
(
**
args
)
self
.
send_response
(
response
=
func
.
__name__
,
args
=
{
'retval'
:
retval
,
'uuid'
:
args
.
get
(
'uuid'
,
None
)})
def
handle_response
(
self
,
response
,
args
):
pass
def
_get_virtio_device
():
path
=
None
GUID
=
'{6FDE7521-1B65-48ae-B628-80BE62016026}'
from
infi.devicemanager
import
DeviceManager
dm
=
DeviceManager
()
dm
.
root
.
rescan
()
# Search Virtio-Serial by name TODO: search by class_guid
for
i
in
dm
.
all_devices
:
if
i
.
has_property
(
"description"
):
if
"virtio-serial"
.
upper
()
in
i
.
description
.
upper
():
path
=
(
"
\\\\
?
\\
"
+
i
.
children
[
0
]
.
instance_id
.
lower
()
.
replace
(
'
\\
'
,
'#'
)
+
"#"
+
GUID
.
lower
()
)
return
path
def
main
():
if
system
==
'Windows'
:
port
=
_get_virtio_device
()
if
port
:
from
w32serial
import
SerialPort
else
:
from
twisted.internet.serial
import
SerialPort
import
pythoncom
pythoncom
.
CoInitialize
()
port
=
r'\\.\COM1'
else
:
#from twisted.internet.serial import SerialPort
# Try virtio first
from
posixvirtio
import
SerialPort
port
=
"/dev/virtio-ports/agent"
if
not
exists
(
port
):
port
=
'/dev/ttyS0'
logger
.
info
(
"Opening port
%
s"
,
port
)
SerialPort
(
SerialLineReceiver
(),
port
,
reactor
)
try
:
from
notify
import
register_publisher
register_publisher
(
reactor
)
except
:
logger
.
exception
(
"Couldnt register notify publisher"
)
logger
.
debug
(
"Starting reactor."
)
reactor
.
run
()
logger
.
debug
(
"Reactor after run."
)
if
__name__
==
'__main__'
:
main
()
win32/network.py
View file @
1d60a2b2
import
netifaces
from
netaddr
import
IPNetwork
,
IPAddress
import
fileinput
import
logging
from
subprocess
import
check_output
,
CalledProcessError
...
...
@@ -9,84 +7,6 @@ logger = logging.getLogger()
interfaces_file
=
'/etc/network/interfaces'
ifcfg_template
=
'/etc/sysconfig/network-scripts/ifcfg-
%
s'
def
get_interfaces_linux
(
interfaces
):
for
ifname
in
netifaces
.
interfaces
():
mac
=
netifaces
.
ifaddresses
(
ifname
)[
17
][
0
][
'addr'
]
conf
=
interfaces
.
get
(
mac
.
upper
())
if
conf
:
yield
ifname
,
conf
def
remove_interfaces_ubuntu
(
devices
):
delete_device
=
False
for
line
in
fileinput
.
input
(
interfaces_file
,
inplace
=
True
):
line
=
line
.
rstrip
()
words
=
line
.
split
()
if
line
.
startswith
(
'#'
)
or
line
==
''
or
line
.
isspace
()
or
not
words
:
# keep line
print
line
continue
if
(
words
[
0
]
in
(
'auto'
,
'allow-hotplug'
)
and
words
[
1
]
.
split
(
':'
)[
0
]
in
devices
):
# remove line
continue
if
words
[
0
]
==
'iface'
:
if
words
[
1
]
.
split
(
':'
)[
0
]
in
devices
:
# remove line
delete_device
=
True
continue
else
:
delete_device
=
False
if
line
[
0
]
in
(
' '
,
'
\t
'
)
and
delete_device
:
# remove line
continue
# keep line
print
line
def
change_ip_ubuntu
(
interfaces
,
dns
):
data
=
list
(
get_interfaces_linux
(
interfaces
))
remove_interfaces_ubuntu
(
dict
(
data
)
.
keys
())
with
open
(
interfaces_file
,
'a'
)
as
f
:
for
ifname
,
conf
in
data
:
ipv4_alias_counter
=
ipv6_alias_counter
=
0
f
.
write
(
'auto
%
s
\n
'
%
ifname
)
for
i
in
conf
[
'addresses'
]:
ip_with_prefix
=
IPNetwork
(
i
)
prefixlen
=
ip_with_prefix
.
prefixlen
ip
=
ip_with_prefix
.
ip
alias
=
ifname
if
ip
.
version
==
6
:
if
ipv6_alias_counter
>
0
:
alias
=
'
%
s:
%
d'
%
(
ifname
,
ipv6_alias_counter
)
ipv6_alias_counter
+=
1
else
:
if
ipv4_alias_counter
>
0
:
alias
=
'
%
s:
%
d'
%
(
ifname
,
ipv4_alias_counter
)
ipv4_alias_counter
+=
1
f
.
write
(
'iface
%(ifname)
s
%(proto)
s static
\n
'
' address
%(ip)
s
\n
'
' netmask
%(prefixlen)
d
\n
'
' gateway
%(gw)
s
\n
'
' dns-nameservers
%(dns)
s
\n
'
%
{
'ifname'
:
alias
,
'proto'
:
'inet6'
if
ip
.
version
==
6
else
'inet'
,
'ip'
:
ip
,
'prefixlen'
:
prefixlen
,
'gw'
:
conf
[
'gw6'
if
ip
.
version
==
6
else
'gw4'
],
'dns'
:
dns
})
# example:
# change_ip_ubuntu({
# u'02:00:00:02:A3:E8': {
...
...
@@ -97,33 +17,6 @@ def change_ip_ubuntu(interfaces, dns):
# '8.8.8.8')
def
change_ip_rhel
(
interfaces
,
dns
):
for
ifname
,
conf
in
get_interfaces_linux
(
interfaces
):
with
open
(
ifcfg_template
%
ifname
,
'w'
)
as
f
:
f
.
write
(
'DEVICE=
%
s
\n
'
'BOOTPROTO=none
\n
'
'USERCTL=no
\n
'
'ONBOOT=yes
\n
'
%
ifname
)
for
i
in
conf
[
'addresses'
]:
ip_with_prefix
=
IPNetwork
(
i
)
ip
=
ip_with_prefix
.
ip
if
ip
.
version
==
6
:
f
.
write
(
'IPV6INIT=yes
\n
'
'IPV6ADDR=
%(ip)
s/
%(prefixlen)
d
\n
'
'IPV6_DEFAULTGW=
%(gw)
s
\n
'
%
{
'ip'
:
ip
,
'prefixlen'
:
ip_with_prefix
.
prefixlen
,
'gw'
:
conf
[
'gw6'
]})
else
:
f
.
write
(
'NETMASK=
%(netmask)
s
\n
'
'IPADDR=
%(ip)
s
\n
'
'GATEWAY=
%(gw)
s
\n
'
%
{
'ip'
:
ip
,
'netmask'
:
str
(
ip_with_prefix
.
netmask
),
'gw'
:
conf
[
'gw4'
]})
def
get_interfaces_windows
(
interfaces
):
import
wmi
nics
=
wmi
.
WMI
()
.
Win32_NetworkAdapterConfiguration
(
IPEnabled
=
True
)
...
...
@@ -133,7 +26,7 @@ def get_interfaces_windows(interfaces):
yield
nic
,
conf
def
change_ip
_windows
(
interfaces
,
dns
):
def
change_ip
(
interfaces
,
dns
):
for
nic
,
conf
in
get_interfaces_windows
(
interfaces
):
link_local
=
IPNetwork
(
'fe80::/16'
)
new_addrs
=
[
IPNetwork
(
ip
)
for
ip
in
conf
[
'addresses'
]]
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment