source: ogAgent-Git/src/opengnsys/oglive/operations.py @ 2ac6daa

oglive
Last change on this file since 2ac6daa was 2ac6daa, checked in by Ramón M. Gómez <ramongomez@…>, 5 years ago

#908: Trying to fix a bug when obteining execution outputs.

  • Property mode set to 100644
File size: 7.5 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# Copyright (c) 2014 Virtual Cable S.L.
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without modification,
7# are permitted provided that the following conditions are met:
8#
9#    * Redistributions of source code must retain the above copyright notice,
10#      this list of conditions and the following disclaimer.
11#    * Redistributions in binary form must reproduce the above copyright notice,
12#      this list of conditions and the following disclaimer in the documentation
13#      and/or other materials provided with the distribution.
14#    * Neither the name of Virtual Cable S.L. nor the names of its contributors
15#      may be used to endorse or promote products derived from this software
16#      without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29"""
30@author: Ramón M. Gómez, ramongomez at us dot es
31"""
32from __future__ import unicode_literals
33
34import socket
35import platform
36import os
37import fcntl
38import subprocess
39import struct
40import array
41import six
42import chardet
43from opengnsys import utils
44
45
46def _getMacAddr(ifname):
47    """
48    Returns the mac address of an interface
49    Mac is returned as unicode utf-8 encoded
50    """
51    if isinstance(ifname, list):
52        return dict([(name, _getMacAddr(name)) for name in ifname])
53    if isinstance(ifname, six.text_type):
54        ifname = ifname.encode('utf-8')  # If unicode, convert to bytes (or str in python 2.7)
55    try:
56        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
57        info = bytearray(fcntl.ioctl(s.fileno(), 0x8927, struct.pack(str('256s'), ifname[:15])))
58        return six.text_type(''.join(['%02x:' % char for char in info[18:24]])[:-1])
59    except Exception:
60        return None
61
62
63def _getIpAddr(ifname):
64    """
65    Returns the ip address of an interface
66    Ip is returned as unicode utf-8 encoded
67    """
68    if isinstance(ifname, list):
69        return dict([(name, _getIpAddr(name)) for name in ifname])
70    if isinstance(ifname, six.text_type):
71        ifname = ifname.encode('utf-8')  # If unicode, convert to bytes (or str in python 2.7)
72    try:
73        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
74        return six.text_type(socket.inet_ntoa(fcntl.ioctl(
75            s.fileno(),
76            0x8915,  # SIOCGIFADDR
77            struct.pack(str('256s'), ifname[:15])
78        )[20:24]))
79    except Exception:
80        return None
81
82
83def _getInterfaces():
84    """
85    Returns a list of interfaces names coded in utf-8
86    """
87    max_possible = 128  # arbitrary. raise if needed.
88    space = max_possible * 16
89    if platform.architecture()[0] == '32bit':
90        offset, length = 32, 32
91    elif platform.architecture()[0] == '64bit':
92        offset, length = 16, 40
93    else:
94        raise OSError('Unknown arquitecture {0}'.format(platform.architecture()[0]))
95
96    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
97    names = array.array(str('B'), b'\0' * space)
98    outbytes = struct.unpack(str('iL'), fcntl.ioctl(
99        s.fileno(),
100        0x8912,  # SIOCGIFCONF
101        struct.pack(str('iL'), space, names.buffer_info()[0])
102    ))[0]
103    namestr = names.tostring()
104    # return namestr, outbytes
105    return [namestr[i:i + offset].split(b'\0', 1)[0].decode('utf-8') for i in range(0, outbytes, length)]
106
107
108def _getIpAndMac(ifname):
109    ip, mac = _getIpAddr(ifname), _getMacAddr(ifname)
110    return ip, mac
111
112
113def _exec_ogcommand(ogcmd):
114    """
115    Loads OpenGnsys environment variables, executes the command and returns the result
116    """
117    ret = subprocess.check_output(ogcmd, shell=True)
118    return ret
119
120
121def getComputerName():
122    """
123    Returns computer name, with no domain
124    """
125    return socket.gethostname().split('.')[0]
126
127
128def getNetworkInfo():
129    """
130    Obtains a list of network interfaces
131    :return: A "generator" of elements, that are dict-as-object, with this elements:
132      name: Name of the interface
133      mac: mac of the interface
134      ip: ip of the interface
135    """
136    for ifname in _getInterfaces():
137        ip, mac = _getIpAndMac(ifname)
138        if mac != '00:00:00:00:00:00':  # Skips local interfaces
139            yield utils.Bunch(name=ifname, mac=mac, ip=ip)
140
141
142def getDomainName():
143    return ''
144
145
146def get_oglive_version():
147    """
148    Returns ogLive Kernel version and architecture
149    :return: kernel version
150    """
151    kv = platform.os.uname()
152    return kv[2] + ', ' + kv[4]
153
154
155def reboot():
156    """
157    Simple reboot using OpenGnsys script
158    """
159    # Workaround for dummy thread
160    if six.PY3 is False:
161        import threading
162        threading._DummyThread._Thread__stop = lambda x: 42
163
164    _exec_ogcommand('/opt/opengnsys/scripts/reboot')
165
166
167def poweroff():
168    """
169    Simple power off using OpenGnsys script
170    """
171    # Workaround for dummy thread
172    if six.PY3 is False:
173        import threading
174        threading._DummyThread._Thread__stop = lambda x: 42
175
176    _exec_ogcommand('/opt/opengnsys/scripts/poweroff')
177
178
179def get_etc_path():
180    """
181    Returns etc directory path.
182    """
183    return os.sep + 'etc'
184
185
186def get_configuration():
187    """
188    Returns client's configuration
189    Warning: this operation may take some time
190    :return:
191    """
192    try:
193        _exec_ogcommand('/opt/opengnsys/interfaceAdm/getConfiguration')
194        # Returns content of configuration file
195        cfgdata = open('/tmp/getconfig', 'r').read().strip()
196    except IOError:
197        cfgdata = ''
198    return cfgdata
199
200
201def exec_command(cmd):
202    """
203    Executing a shell command
204    :param cmd:
205    :return: object with components:
206      output: standard output
207      error: error output
208      exit: exit code
209    """
210    proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
211    (out, err) = proc.communicate()
212    stat = proc.returncode
213    return stat, out.decode(chardet.detect(out)['encoding']).encode('utf8'),\
214           err.decode(chardet.detect(err)['encoding']).encode('utf8')
215
216
217def get_hardware():
218    """
219    Returns client's hardware list
220    :return:
221    """
222    try:
223        filepath = _exec_ogcommand('/opt/opengnsys/scripts/listHardwareInfo').strip()
224        # Returns content of configuration file, skipping the header line and newline characters
225        with open(filepath, 'r') as f:
226            harddata = map(str.strip, f.readlines()[1:])
227    except IOError:
228        harddata = ''
229    return harddata
230
231
232def get_software(disk, part):
233    """
234    Returns software list installed on an operating system
235    :param disk:
236    :param part:
237    :return:
238    """
239    try:
240        filepath = _exec_ogcommand('/opt/opengnsys/scripts/listSoftwareInfo {} {}'.format(disk, part)).strip()
241        # Returns content of configuration file, skipping the header line and newline characters
242        with open(filepath, 'r') as f:
243            softdata = map(str.strip, f.readlines())
244    except IOError:
245        softdata = ''
246    return softdata
Note: See TracBrowser for help on using the repository browser.