Архив рубрики: Python

INSERT / UPDATE в MySQL на Python

Ну в принципе и не на Python, важен принцип. Что мне нужно? Если UPDATE завершился ошибкой (данные не обновлены т.к. их нет), тогда INSERT. Вообще в MYSQL есть специальная команда — REPLACE, у которой синтаксис такой-же как у INSERT, за исключением того, что если такая запись уже есть, то она просто измениться. Одно НО. Таблица обязательно должна содержать колонки с UNIQUE. А если их нет, и добавить нельзя? Тогда к сожалению придется «отлавливать» результат выполнения UPDATE — а именно количество изменившихся записей. Если 0 — считаем что такой записи вообще нет, и вставляем. На Python нечто подобное реализовать можно вот так:

sql="update device_status set param_value=0,stamp=now() where param_name='Uptime' and device_id="+str(device_id);   
 func.putlog("---обновляю статус свича в биллинге ")    
 cursor2 = connb2.cursor()
 func.putlog("----SQL:"+sql)    
 try:
  cursor2.execute(sql);
  connb2.commit();
  print (format(cursor2.rowcount))
  if format(cursor2.rowcount)=="0":
    func.putlog("---- новый свич, добавляем данные в таблицу..");
    sql="INSERT into device_status (record_id,device_id,port_id,param_name,param_value,stamp) values (null,"+str(device_id)+",null,'Uptime',UNIX_TIMESTAMP(),now())";
    cursor2.execute(sql);
    connb2.commit();  
    sql="INSERT into device_status (record_id,device_id,port_id,param_name,param_value,stamp) values (null,"+str(device_id)+",null,'State',2,now())";
    cursor2.execute(sql);
    connb2.commit();

Сетевые настройки из FreeRadius через DHCP

Прилетела задача наладить выдачу IP адресов абонентам. Условия задачи:

  • Отдельного сервера под авторизации не дадим — обойдетесь 😉
  • Абоненты должны получать сетевые настройки по DHCP
  • Сеть разнородная. Это и PON оборудование, и обычные свичи с настроенной Опцией 82 и WiFi базы с точками
  • Если ни под одно из условий выдачи IP данные не попадают — необходимо выдать IP из «гостевой» сети

Читать далее Сетевые настройки из FreeRadius через DHCP

pip error: option —single-version-externally-managed not recognized

При попытке установки mysql-connector на одном из серверов FreeBSD, при помощи:

pip install mysql-connector

Получил ошибку:

root@phaeton:/usr/local/etc/raddb/mods-config# pip install mysql-connector
DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7.
Collecting mysql-connector
  Using cached https://files.pythonhosted.org/packages/8e/78/049f747325ce0154263cd1b10fe7ea9ddb17e839111c6f8f824d5964cfb5/mysql-connector-2.2.8.tar.gz
Installing collected packages: mysql-connector
  Running setup.py install for mysql-connector ... error
    Complete output from command /usr/local/bin/python2.7 -u -c "import setuptools, tokenize;__file__='/tmp/pip-install-MpZe2P/mysql-connector/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-record-GA8HB9/install-record.txt --single-version-externally-managed --compile:
    usage: -c [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
       or: -c --help [cmd1 cmd2 ...]
       or: -c --help-commands
       or: -c cmd --help
    
    error: option --single-version-externally-managed not recognized
    
    ----------------------------------------
Command "/usr/local/bin/python2.7 -u -c "import setuptools, tokenize;__file__='/tmp/pip-install-MpZe2P/mysql-connector/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-record-GA8HB9/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-install-MpZe2P/mysql-connector/

Решение:

pip install -U setuptools
pip install -U wheel

Добавляем модуль python для FreeRadius3

Случилось так, что стандартными средствами FreeRadius авторизации ну никак не «разрулить» те условия, которые необходимы. Решение: включим/поставим модуль python для FreeRadius и будем использовать его для авторизации и выдачи абонентам сетевых настроек.

Далее пути указаны для Ubuntu.

1) Сделаем симлинк (читай включим модуль) для модуля pyhton в папке

ln -s /etc/freeradius/3.0/mods-available/python /etc/freeradius/3.0/mods-enabled

2) В файле настроек пропишем путь для файла написанного на языке python, который будет отвечать за авторизацию, и имя собственно модуля, например work:

python_path="/etc/freeradius/3.0/mods-config/python"
module = work

Так-же нужно расскоментировать те функции, которые будут вызываться модулем. Например:

mod_authorize = ${.module}
func_authorize = authorize
mod_authenticate = ${.module}
func_authenticate = authenticate

 

3) Создадим модуль work. Можно на основе example. В моём случае он адаптирован под python3 (в «базе» он поставляется пот python 2.7):

#! /usr/bin/env python3

import radiusd

def instantiate(p):
  print ("*** instantiate ***")
  print (p)
  # return 0 for success or -1 for failure

def authenticate(p):
    print ("*** Autefication!!***")
    print (p)
def authorize(p):
  print ("*** authorize ***")
  radiusd.radlog(radiusd.L_INFO, '*** radlog call in authorize ***')
  print (p)
  print (radiusd.config)
  return radiusd.RLM_MODULE_OK

def preacct(p):
  print ("*** preacct ***")
  print (p)
  return radiusd.RLM_MODULE_OK

def accounting(p):
  print ("*** accounting ***")
  radiusd.radlog(radiusd.L_INFO, '*** radlog call in accounting (0) ***')
  print (p)
  return radiusd.RLM_MODULE_OK

def pre_proxy(p):
  print ("*** pre_proxy ***")
  print (p)
  return radiusd.RLM_MODULE_OK

def post_proxy(p):
  print ("*** post_proxy ***")
  print (p)
  return radiusd.RLM_MODULE_OK

def post_auth(p):
  print ("*** post_auth ***")
  print (p)
  return radiusd.RLM_MODULE_OK

def recv_coa(p):
  print ("*** recv_coa ***")
  print (p)
  return radiusd.RLM_MODULE_OK

def send_coa(p):
  print ("*** send_coa ***")
  print (p)
  return radiusd.RLM_MODULE_OK

def detach():
  print ("*** goodbye from example.py ***")
  return radiusd.RLM_MODULE_OK

И чуть изменим файл radiusd.py:

#! /usr/bin/env python3

# from modules.h

RLM_MODULE_REJECT = 0
RLM_MODULE_FAIL = 1
RLM_MODULE_OK = 2
RLM_MODULE_HANDLED = 3
RLM_MODULE_INVALID = 4
RLM_MODULE_USERLOCK = 5
RLM_MODULE_NOTFOUND = 6
RLM_MODULE_NOOP = 7
RLM_MODULE_UPDATED = 8
RLM_MODULE_NUMCODES = 9

# from log.h
L_AUTH = 2
L_INFO = 3
L_ERR = 4
L_WARN = 5
L_PROXY = 6
L_ACCT = 7

L_DBG = 16
L_DBG_WARN = 17
L_DBG_ERR = 18
L_DBG_WARN_REQ = 19
L_DBG_ERR_REQ = 20

# log function
def radlog(level, msg):
    import sys
    sys.stdout.write(msg + '\n')

    level = level


В файле default включим модули в секциях authorize и authenticate:

authorize {
  python
....
}
authenticate {
  Auth-Type PAP {
    pap
    python
  }
...
}

Запускаем:

radtest steve testing localhost 1812 testing123

В логах наблюдаем:

Ready to process requests
(0) Received Access-Request Id 62 from 127.0.0.1:53324 to 127.0.0.1:1812 length 75
(0)   User-Name = "steve"
(0)   User-Password = "testing"
(0)   NAS-IP-Address = 126.0.0.1
(0)   NAS-Port = 1812
(0)   Message-Authenticator = 0xacf43d1ab9f8719bc9e92f0f7ebd4395
(0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default
(0)   authorize {
*** authorize ***
*** radlog call in authorize ***
(('User-Name', 'steve'), ('User-Password', 'testing'), ('NAS-IP-Address', '126.0.0.1'), ('NAS-Port', '1812'), ('Message-Authenticator', '0xacf43d1ab9f8719bc9e92f0f7ebd4395'))
{}
(0)     [python] = ok
(0)     policy filter_username {
(0)       if (&User-Name) {
(0)       if (&User-Name)  -> TRUE