Диплом: Разработка сетевого программного обеспечения на примере ГКУ "Ресурсы Ямала"

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам
71
помещает значения HTML и CSS свойств выбранных (активированных)
объектов во внутренние переменные для дальнейшей работы.
Отображает пользователю имена всех выбранных серверов, скриптов или
команд в отдельной строке вэб-интерфейса. Когда элементов выбрано много, это
добавляет удобства использования.
В случае деактивации элемента, он удаляется из переменных и
соответственно, из отдельного списка в интерфейсе
Изменяет CSS свойства элементов, в зависимости от состояния
активирован или деактивирован
Код функции «selector»:
function selector(box_id, body_id, name, obj) {
var body = document.getElementById(body_id);
var box = document.getElementById(box_id);
var div = document.getElementById(obj);
var txt = '<a title=\"Deselect ' + name + '\" href=\"javascript:;\" onclick=\"selector(\''
+ box_id + '\', \'' + body_id + '\', \'' + name + '\', \''+ obj + '\')\">' + name + '</a> | '
if (!box) { return; }
function change(list) {
if ( box.checked == false ) {
box.checked = true; body.classList.add('selected');
window[list] = window[list] + txt;
div.innerHTML = window[list];
}
else {
box.checked = false; body.classList.remove('selected');
window[list] = window[list].replace(txt, '');
if ( window[list] == pref ) { div.innerHTML = ''; }
else { div.innerHTML = window[list]; }
}
}
if ( obj == 'SS' ) { pref = 'Выбраны серверы: '; window.slist = window.slist || pref;
change('slist'); }
else if ( obj == 'SX' ) { pref = 'Выбраны скрипты: '; window.xlist = window.xlist || pref;
change('xlist'); }
}
3. Проверка параметров
После выполнения функции «selector» управление передаётся функции
«Validation», которая:
72
При запуске команды или скрипта проверяет, выбраны ли серверы
При нажатии на кнопку «Выполнить скрипт» проверяет, выбраны ли
скрипты
Оповещает пользователя если какой-либо необходимый элемент не
выбран
Если выполняется скрипт, запрашивает у пользователя подтверждение
выполнения действий, дополнительно отображая во всплывающем окне список
выбранных серверов и выполняемых действий.
В случае подтверждения возвращает HTTP серверу набор данных в виде
ссылки, содержащий имена серверов, команд или скриптов.
В случае неподтверждения возвращает пользователя на главную
страницу проекта
Код функции «Validation»
function Validation(cmd, srv, scr, dgr) {
var check = function(item) { return item.checked; }
if (scr) {
var scripts = Array.from(document.getElementsByName('selected_scripts'));
if (!scripts.some(check)) { alert('Script(s) not selected.'); return false; }
}
if (srv) {
var server_names = '';
var servers = Array.from(document.getElementsByName('selected_servers'));
if (!servers.some(check)) { alert('Server(s) not selected.'); return false; }
servers.forEach(function(S) { if (S.checked) { server_names = '\n\t' + S.dataset.target +
server_names; }});
}
if (dgr) {
var sure = confirm(
'\nВы выполняете следующие команды:\n\t'
+ cmd +
'\n\nНа серверах: '
+ server_names +
'\n\nВЫ УВЕРЕНЫ ?'
);
if (! sure) { return false; }
}
73
}
4. Внутренние функции Django
После обработки действий пользователя в интерфейсе, их дальнейшая
обработка выполняется одним из модулей Django «Представление». Модуль
«Представление» является обычной python функцией, которая содержит набор
данных, отображаемых на HTML страницах, а также обрабатывает получаемые
данные на стороне сервера Django и возвращает результаты обратно в вэб-
интерфейс пользователя.
«Представление», обрабатывающее действия с содержимым проекта
расположено в файле «views.py» и описано в функции «project_view». В
рассматриваемом примере, при получении HTTP-запроса, содержащего строку
«run_cmd», вызывается пользовательская Python функция «run_cmd»
Код представления «project_view»:
@login_required
def project_view(request, project_id):
"""Выводит всю информацию о проекте, обрабатывает кнопки действий."""
project = get_object_or_404(Project, id=project_id)
check_perm_or404('view_project', project, request.user)
data = request.GET
if data.get('run_cmnd'):
url = run_cmd(data, project, request.user)
return HttpResponseRedirect(url)
logids = data.getlist('logid', default=[])
cmdlog = data.get('cmdlog', default=None)
hide_details_form = HideInfoForm(initial=data)
commandsorted = sorted(commandict.itervalues(), key=lambda cmd: cmd.position)
servers_filter = data.get('servers', default='')
servers = project.server_set.order_by('name')
servers_filtered = servers.filter(name__iregex=servers_filter)
servers_filter_form = ServersFilterForm(initial=data)
scripts_filter = data.get('scripts', default='')
scripts = project.script_set.order_by('desc')
scripts_filtered = scripts.filter(flnm__iregex=scripts_filter)
scripts_filter_form = ScriptsFilterForm(initial=data)
74
context = {
'jobs': jobs,
'logs': logids,
'info': info(data),
'cmdlog': cmdlog,
'project': project,
'scripts': scripts,
'servers': servers,
'commands': commandsorted,
'servers_filtered': servers_filtered,
'scripts_filtered': scripts_filtered,
'hide_info_form': hide_details_form,
'servers_filter': servers_filter_form,
'scripts_filter': scripts_filter_form,
}
if len(logids) > 1:
context['allogs'] = u'/command_log/?cmd={cmd!s}&prid={pid!s}&logid={log!s}'.format(
cmd=cmdlog, pid=project_id, log='&logid='.join(logids))
return render(request, 'ups/project.html', context)
5. Обработка параметров и подготовка к запуску
Функция «run_cmd» получает на вход имя проекта, имя пользователя и
данные, содержащие список серверов и имя команды.
Далее производится проверка прав пользователя управление серверами
проекта. В случае если у пользователя нет на это прав, ему возвращается ошибка и
дальнейшее выполнение функции прекращается. Проверка разрешений
выполняется встроенным в Django методом «check_perm_or404».
После проверки прав формируется HTTP ссылка вида:
«/projects/{P}/?repeat=1&run_cmnd={C}&run_type=RUN'.format(C=name,
P=project.id)».
Где {P} – идентификатор проекта, {C} – имя команды.
Далее, для каждого сервера:
Генерируется случайный, уникальный ключ, который будет
использоваться как имя лог файла
Проверяются права пользователя на управление данным сервером и
формируется массив параметров, представленный в таблице 15.
75
Таблица 15.
Массив сформированных параметров
Ключ
Описание значения
opt
Словарь, содержащий адрес сервера, порт SSH
uniq
Уникальный ключ для формирования лог-файла
logi
Строка вида: «logid={текущее значение переменной uniq
http
По этой ссылке будет вызвана другая функция
serv
Идентификатор сервера
cmnd
Список выполняемых команд или скриптов
user
Пользователь, инициировавший запуск
login
Имя пользователя для подключения к серверу
password
Пароль пользователя сервера
cdat
Текущее время
name
Имя проекта в вэб-интерфейсе
proj
Имя проекта
Используя значения из созданного массива, для каждого сервера
генерируются уникальные ссылки, по которым будет доступен просмотр истории
выполнения команд.
Код функции «run_cmd»
def run_cmd(data, project, user):
"""Запускает выбранную команду."""
tab = ''
date = run_date()
runt = data['run_type']
name = data['run_cmnd']
check_perm_or404('run_command', project, user)
check_perm_or404(commandict[name].permission, project, user)
http = u'/projects/{P}/?repeat=1&run_cmnd={C}&run_type=RUN'.format(C=name,
P=project.id)
dict = {
'opt': [],
'uniq': '',
'logi': '',
'http': http,
'serv': None,
'cmnd': name,
76
'name': name,
'user': user,
'cdat': date,
'proj': project,
}
# Server commands
tab = 'logs'
for server_id in data.getlist('selected_servers'):
uniq = uniqkey()
serv = get_object_or_404(Server, id=server_id)
port = data.get('port') or serv.port
dict['logi'] += '&logid=%s' % uniq
dict.update({'uniq': uniq, 'serv': serv})
dict['http'] = u'{http}&selected_servers={srv}'.format(http=http, srv=server_id)
dict['opt'] = ['--server', serv.addr, '--port', port, --login, serv.login, --password,
serv.password]
starter(dict)
if dict['his'] and not data.get('repeat'):
url = u'/projects/{pid!s}/?&cmdlog={cmd!s}{log!s}{opt!s}'.format(
opt=info(data, tab),
log=dict['logi'],
pid=project.id,
cmd=name,
)
else:
tab = data.get('tab', default='')
if tab == 'logs':
tab = 'scripts'
url = u'/command_log/?cmd={cmd!s}&tab={tab!s}&prid={pid!s}{log!s}{opt!s}'.format(
opt=info(data, tab),
log=dict['logi'],
pid=project.id,
cmd=name,
tab=tab,
)
return url
Сформированный ранее массив передается на вход функции «starter»,
которая выполняет следующие действия:
Хранит указание пути к интерпретатору Python
77
Из данных, полученных на предыдущем шаге, формирует список
аргументов для дальнейшего использования, приводя их к формату,
доступному для запуска в командной строке.
В случае если пользователь запускает скрипт с дополнительными
параметрами, то они дописываются к телу скрипта
Создаёт лог файл и записывает в него поток вывода
Создает отдельный фоновый процесс в ОС
Вызывает модуль, содержащий код выполняемой команды. Модули
команд представлены в виде файлов «.py» и расположены в отдельной
папке «modules»
Записывает содержимое лог-файла в историю
Код функции «starter»
def starter(dict):
"""Запускает выполнение команды в фоновом процессе."""
python = opj(conf.BASE_DIR, './venv/bin/python')
opt = [
python, 'starter.py', dict['cmnd'],
'--name', str(dict['proj'].name),
'--pid', str(dict['proj'].id),
'--key', dict['uniq'],
'--date', dict['cdat'],
]
parser = ArgumentParser()
parser.add_argument('-H', '--history', help="Save log to history", action='store_true')
parser.add_argument('-x', '--script', help='List of script files', action='append')
parser.add_argument('-o', '--options', help='Custom script options', action='append')
parser.add_argument('-s', '--server', help="Server's ssh address")
parser.add_argument('-P', '--port', help="Server's port")
parser.add_argument('-D', '--date', help='Cron job date')
parser.add_argument('-n', '--name', help='Project name')
parser.add_argument('cmd', help='Command name')
parser.add_argument('-k', '--key', help='Unique key')
parser.add_argument('-i', '--id', help='Project id')
parser.add_argument('-l', '--login', help='Server login')
parser.add_argument('-p', '--password', help='Server password')
args = parser.parse_args()
command = import_module('modules.%s' % args.cmd)
errfile = ERR_FILE + args.key
logfile = LOG_FILE + args.key
78
opt.extend(dict['opt'])
# Доп. опции скриптов
for ID in dict['data'].getlist('selected_scripts'):
dict['http'] += '&selected_scripts={}'.format(ID)
script = get_object_or_404(Script, id=ID)
opt.extend(['-x', str(script.file)])
oplist = str(dict['data'].get('script_opt' + ID))
dict['http'] += '&script_opt{id}={val}'.format(id=ID, val=oplist)
oplist = oplist.split()
opdone = ' '.join(escape(opt) for opt in oplist)
# Добавляем дополнительные параметры
opt.extend(['-o', opdone])
if dict['his']:
opt.extend(['--history'])
add_event(dict)
error = 0
# Запуск команды }------------------------
with open(logfile, 'a') as log:
error += command.run(args, log)
# Запись лога в базу }-------------------
with open(logfile) as f:
fullog = f.read()
log = log_cutter(fullog)
if args.from_cron:
cron_log(args, error, log)
else:
if args.history:
regular_log(args, error, log)
with open(errfile, 'w') as f:
f.write(str(error))
Popen(opt)
6. Выполнение команды
После того, как все подготовительные действия завершены и сформированы
все необходимые параметры, в зависимости от выполняемой команды вызывается
соответствующий ей модуль. Все модули состоят из функции «run», содержащей
программный код выполняемых действий и вызова следующей функции «execute»,
которая обеспечивает подключение к необходимому серверу и выполнение
79
требуемых команд. Например, для проверки обновлений ОС вызывается модуль
«check_updates.py».
Код модуля «check_updates.py»:
def run(args, log):
command = [
''' printf '\n-----{{ <b>Сервер {server}</b> }}-----\n'
printf '\nДоступные обновления:\n'
yum check-update
'''
]
result = execute(args, command, log)
return result
Далее выполняется подключение к удаленному серверу и выполнение
команды. Эти действия выполняет функция «execute». Для подключения к серверу
используется библиотека «paramiko»[8], которая перед выполнением команды
выполняет проверку успешности подключения.
Код функции «execute»:
def execute(args, command, log)
""" Подключение по SSH и выполнение """
host = args.server
user = args.login
password = args.password
command = command
logs = args.log
client = pm.SSHClient()
client.load_system_host_keys()
client.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
client.set_missing_host_key_policy(AllowAllKeys())
client.connect(HOST, username=USER, password=PASSWORD)
channel = client.invoke_shell()
stdin = channel.makefile('wb')
stdout = channel.makefile('rb')
stdin.write(command)
print stdout.read()
for line in stdin.read(), stdout.read():
logs = logs + line
80
stdout.close()
stdin.close()
client.close()
Если выполняющаяся команда в процессе своей работы формирует
построчный вывод данных в консоль, ход выполнения можно видеть в вэб-
интерфейсе в реальном времени по ссылке, сформированной ранее. Для этого
используется функция command_log().
Код функции «command_log»:
def command_log(request):
"""Выводит страницу логов выполняющейся команды."""
data = request.GET
project = get_object_or_404(Project, id=data['prid'])
check_perm_or404('view_project', project, request.user)
check_perm_or404('run_command', project, request.user)
final = {}
logids = data.getlist('logid')
url = request.META['SERVER_NAME']
qst = request.META['QUERY_STRING']
context = {
'name': data['cmd'].capitalize().replace('_', ' '),
'his': commandickt[data['cmd']].his,
'cancel': '/cancel/?%s' % qst,
'back': back_url(data),
'ok': 'btn-success',
'project': project,
'logs': [],
'color': '',
}
for logid in logids:
err = 999
event = None
log = 'Working...'
final[logid] = False
logfile = conf.LOG_FILE + logid
errfile = conf.ERR_FILE + logid
if context['his']:
event = get_object_or_404(History, uniq=logid)
log = event.desc
if event.exit:
err = int(event.exit)

Смотрите также:

"Автоматизация обработки заявок ООО "Проектно-Строительная Компания"
"Автоматизация процесса аттестации персонала для ООО "Нэт Бай Нэт Холдинг"
"Анализ интернет-активности конкурентов ( на примере конкурентов "Газпром нефть")
"Бухгалтерский учёт и аудит расчётов с подотчётними лицами в организации на примере ООО "ЛОЦ 10""
«Психологическое сопровождение персонала в организации на примере ООО «Крокус»
Cовершенствование деловой оценки персонала в организации (на примере ООО "Даймонд кейтеринг развитие")
PR как средство продвижения организации (на примере ПАО "Тамбовский завод "Комсомолец им. Н.С. Артемова")
PR-коммуникации в сфере общественного питания (на примере кафе-кондитерской «Cream Cheese»)
SMM как средство повышения эффективности работы учреждений социокультурной сферы (на примере Малого театра)
Value-based education: ценности в системе образования и способы их реализации на уроке английского языка. Опыт Европейских стран