Fixed bugs, new options for cooks

This commit is contained in:
2019-09-05 08:38:06 +02:00
parent ada3b9a6d2
commit 90683c44b0
7 changed files with 89 additions and 55 deletions

3
.gitignore vendored
View File

@@ -7,4 +7,5 @@ BD/database*
reports/
__pycache__/
.vscode/
cooks/*.yaml
cooks/*.yaml
control/

View File

@@ -16,7 +16,7 @@ It's not error proof, then, I don't have any responsability if something crashes
- Complete translation English and Spanish
- Somewhat more security in API 1
- Stabilize all
- I created a simple GUI in EasyGUI to be easy used, but maybe I will transition to a web GUI more dynamic and visually better
- I created a simple GUI in EasyGUI to be easy used, but if I have time, maybe will do a webUI more dynamic and visually better (Without needing to install php/apache/nginx, using python)
# Requirements
@@ -55,4 +55,7 @@ For server you can use Linux or Windows, and in theory any environment that can
Note: client.ps1 has to have controlpcm.ini file with it
- If you don't have Active Directory, you can do the Task Scheduled task in every computer without problems, and using another Shared folder, it will work
- Start api.py using .bat o .sh file. You can do in systemd way, or a cron, or in a terminal of windows server,...
- Start control.pyw to setup password and start adding computers, groups and cooks
- For use of param "-startup 1" for cooks that has to be run without users, you will have to create a Task Scheduled GPO when workstation startsup/powers off with param -startup 1, like:
- Args: -executionpolicy bypass -windowstyle hidden -noninteractive -nologo -file "\\SERVER\SysVol\DOMAINNAME\scripts\client.ps1" -startup 1
- Start control.pyw to setup password and start adding computers, groups and cooks. You can use doc/example_cooks for examples. If anyone wants, I will setup a git repo for cooks.

34
api.py
View File

@@ -1,5 +1,5 @@
#!/usr/bin/python3
BUILD = 16
BUILD = 18
API_VER = 1
##It can be run directly with "waitress-serve --port=3333 api:api"
import falcon
@@ -111,7 +111,7 @@ class getComputers(object):
##
# getComputersGrp: Know all computers that have a group
# getComputersGrp: Know all computers that have this group
# /get/computersgrp?
# @param GroupName/GroupID -> Group to see computers
##
@@ -537,6 +537,12 @@ class delGrpComputer(object): #Del computer from a group
response.media = result
##
# delComputer: Delete computer and data of it
# /del/computer?
# @param ComputerName/ComputerID -> Computer ID or Name
# @param Password -> Password validated command
##
class delComputer(object): #Delete computer
def on_get(self, request, response):
logit(request)
@@ -546,8 +552,11 @@ class delComputer(object): #Delete computer
ComputerID = str(sql.select("SELECT ID_C FROM COMPUTERS WHERE Name='"+value+"'")[0]['ID_C'])
if key == "ComputerID":
ComputerID = str(sql.select("SELECT ID_C FROM COMPUTERS WHERE ID_C='"+value+"'")[0]['ID_C'])
if ComputerID is None:
if key == "Password" and value == retPassword():
Password=value
if Password is None:
response.media = {'TEXT': 'Invalid password','RESULT':'ERROR'}
elif ComputerID is None:
response.media = {'TEXT': 'Error, you need a Name/ComputerID to update data','RESULT':'ERROR'}
elif ComputerID=='':
response.media = {'TEXT': 'Error, this Name/ID is not valid','RESULT':'ERROR'}
@@ -575,7 +584,8 @@ class updComputer(object):
UUID = value
if key == "Password" and value == retPassword():
Password=value
if Password is None:
response.media = {'TEXT': 'Invalid password','RESULT':'ERROR'}
if ComputerID is None and response.media is None:
response.media = {'TEXT': 'Error, you need a ComputerName/ComputerID to update data','RESULT':'ERROR'}
elif response.media is None and ComputerID is not None and UUID is not None:
@@ -609,27 +619,27 @@ class updComputer(object):
class updCookName(object):
def on_get(self, request, response):
logit(request)
CookName, CookNewName= None, None #Initialize
CookName, CookNewName,Password= None, None,None #Initialize
for key, value in request.params.items():
if key == "CookName":
if os.path.isfile('cooks/'+value+'.yaml'):
CookName= value
else:
response.media = {'TEXT': 'Error: Cook not exists in folder','RESULT':'ERROR'}
break
if key == "CookNewName":
if os.path.isfile('cooks/'+value+'.yaml'):
response.media = {'TEXT': 'Error: There is a cook with the new name in folder!','RESULT':'ERROR'}
break
else:
CookNewName= value
if key == "Password" and value == retPassword():
Password=value
if CookName is None or CookNewName is None:
response.media = {'TEXT': 'Error, you need the old and new Cook Name to update data','RESULT':'ERROR'}
elif Password is None: # Validate password
if Password is None:
response.media = {'TEXT': 'Invalid password','RESULT':'ERROR'}
elif response.media is None: #Like else
if response.media is not None:
pass
elif CookName is None or CookNewName is None:
response.media = {'TEXT': 'Error, you need the old and new Cook Name to update data','RESULT':'ERROR'}
else: #Do it.
old_file = os.path.join("cooks", CookName+'.yaml')
new_file = os.path.join("cooks", CookNewName+'.yaml')
os.rename(old_file, new_file)

View File

@@ -1,4 +1,6 @@
# Build 7
# Build 8
param([Int32]$startup=0)
Write-Host $startup
$root = $PSCommandPath | Split-Path -Parent
$server = (Get-Content "$root\configpcm.ini" | select -Skip 1 | ConvertFrom-StringData).server
$resources = (Get-Content "$root\configpcm.ini" | select -Skip 1 | ConvertFrom-StringData).resources
@@ -9,12 +11,12 @@ $UUID=(get-wmiobject Win32_ComputerSystemProduct).UUID
$exists = Invoke-RestMethod -Method Get -Uri "$server/get/computerexists?ComputerName=$computerName&UUID=$UUID"
if ($exists.Result -eq "ERROR"){
if ($exists.EXITCODE -eq '3'){
Write-Host "Computer outside database:" $computerName
}else{
Write-Host "Computer and UUID of $computerName doesn't match"
}
exit
if ($exists.EXITCODE -eq '3'){
Write-Host "Computer outside database:" $computerName
}else{
Write-Host "Computer and UUID of $computerName doesn't match"
}
exit
}
$Timestamp = [int64](([datetime]::UtcNow)-(get-date "1/1/1970")).TotalSeconds
@@ -22,8 +24,8 @@ $Timestamp = [int64](([datetime]::UtcNow)-(get-date "1/1/1970")).TotalSeconds
$SOData = Get-CimInstance Win32_OperatingSystem
$SOVersion = $SOData.Version
if ($SOVersion -match "^10.0."){ #If its Windows 10, add revision number for knowing hotfix installed
$revi = -join(".",(Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion' UBR).UBR)
$SOVersion += $revi
$revi = -join(".",(Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion' UBR).UBR)
$SOVersion += $revi
}
# Update Computer Data
@@ -44,6 +46,11 @@ foreach ($CookName in $cooks){
$cook = Invoke-RestMethod -Method Get -Uri "$server/load/cook?CookName=$CookName&ComputerName=$computerName&UUID=$UUID"
Write-Host "Receta:" $cook.name
$CookRevision = $cook.revision
$atstartup = $cook.atstartup
if ($atstartup -eq 1 -and $startup -ne 1){ # If script has to tun at startup of computer, and there is not this moment..
Write-Host "Se salta ya que no esta arrancando/apagandose el equipo..."
continue # Go for next
}
$err = 0
$exit = 0
$inif = $false
@@ -119,9 +126,9 @@ foreach ($CookName in $cooks){
}
$filesCopied.Add($param) > $null #Add to list
}
"REMOVE" { # Remove files / folders
Remove-Item "$param" -Recurse -Force -ErrorAction Continue # They not see errors (Because error will be file not found)
}
"REMOVE" { # Remove files / folders
Remove-Item "$param" -Recurse -Force -ErrorAction Continue # They not see errors (Because error will be file not found)
}
"INSTALLMSI" { # Installs a .msi file (From $env:temp)
Start-Process msiexec.exe -Wait -ArgumentList "/norestart /quiet /I $param" -ErrorVariable errvar
if ($? -eq $false){ # Error in MSI
@@ -134,8 +141,8 @@ foreach ($CookName in $cooks){
$err = 1
}
}
"MSG" { # Display a message
msg * "$param"
"MSG" { # Display a message
msg * "$param"
}
{$_ -in "SLEEP","PAUSE"}{ # Pause exec some seconds
[int]$secs = $param

View File

@@ -1,5 +1,5 @@
#!/usr/bin/python3
# Version 0.7
# Version 0.72
import easygui
import configparser
import json
@@ -46,7 +46,7 @@ def showchoicesapi(text,title,suburl,field='Name'):
listitems.append(ite[field])
return easygui.choicebox(text,title,listitems)
except:
easygui.msgbox(msg='Error en la aplicación al consultar', title=title, ok_button='OK')
easygui.msgbox(msg=T('Error talking with API'), title=title, ok_button='OK')
return None
def sendsettoapi(suburl,goodtext): # Send a add/del/modify to API. Doesn't return more than "Valid" and "Not valid"
@@ -91,7 +91,7 @@ def returnvalueapi(suburl,field="Name"):
jsonobj = json.loads(requests.get(c_server+suburl+twopart).text)
return jsonobj[field]
except:
easygui.msgbox(msg='Error en la aplicación al consultar', title="Error", ok_button='OK')
easygui.msgbox(msg=T('Error talking with API'), title="Error", ok_button='OK')
return None
@@ -165,7 +165,7 @@ def mgroups():
def mcooks():
global c_server
global c_resources
menu = sendmenudot(T('Cooks menu'),T('Select option'),['1.Detalles de una receta','2.'+T('Rename cook'),'3.Añadir receta a un grupo','4.Eliminar receta de un grupo','5.Grupos de una receta'])
menu = sendmenudot(T('Cooks menu'),T('Select option'),['1.Detalles de una receta','2.'+T('Rename cook'),'3.Añadir receta a un grupo','4.Eliminar receta de un grupo','5.Grupos de una receta','6.'+T('Clean cook status')])
if menu == '1':
cook = showchoicesapi("Lista de recetas implementadas en algún grupo. Selecciona una para ver sus datos","Detalles de una receta","/get/cookall",'CookName')
if cook is not None:
@@ -180,32 +180,36 @@ def mcooks():
if ite['Error'] == 0:
err = " implementado correctamente"
else:
err = " con errores"
err = ' '+T('With errors')
s_err = s_err + 1
list.append(ite['Name']+" -> Revision "+str(ite['Revision'])+err)
easygui.choicebox("Detalles de equipos de la receta "+cook+"\nEquipos: "+str(s_com)+" Con errores: "+str(s_err)+'\nUltima revision: '+str(s_lastrev),"Detalles de una receta",list)
elif menu == '2':
cook = showchoicesapi("Lista de recetas implementadas en algún grupo. Selecciona una para renombrarla. Si la receta no está en ningún grupo, se puede renombrar desde fuera.",T('Rename cook'),c_server+"/get/cookall",'CookName')
cook = showchoicesapi("Lista de recetas implementadas en algún grupo. Selecciona una para renombrarla. Si la receta no está en ningún grupo, se puede renombrar desde fuera.",T('Rename cook'),"/get/cookall",'CookName')
if cook is not None:
newname = easygui.enterbox("Nombre de la nueva receta","Renombrar receta")
if newname is not None and easygui.ynbox("Cambiar nombre de la receta '"+cook+"' por '"+newname+"'. ¿Seguro?",T('Rename cook')):
sendsettoapi("/upd/cookname?CookName="+cook+"&CookNewName="+newname,"Receta cambiada de nombre")
elif menu == '3':
cook = easygui.enterbox(T('Name of the cook'),"Añadir receta a un grupo")
group = showchoicesapi("Lista de grupos existentes","Listado de grupos",c_server+"/get/groups")
group = showchoicesapi("Lista de grupos existentes","Listado de grupos","/get/groups")
if easygui.ynbox("Añadir la receta "+cook+" al grupo '"+group+"'. ¿Seguro?","Añadir receta a un grupo"):
sendsettoapi("/add/cookgrp?CookName="+cook+"&GroupName="+group,"Receta añadida al grupo")
elif menu == '4':
cook = showchoicesapi("Lista de recetas implementadas en algún grupo. Selecciona una para elegir un grupo de esa receta para borrar. Si la receta no está en ningún grupo, no saldrá.","Eliminar receta de un grupo","/get/cookall",'CookName')
if cook is not None:
group = showchoicesapi("Lista de grupos que tienen esa receta. Selecciona el grupo a quitar","Eliminar receta de un grupo","/get/grpcook?CookName="+cook,'Name')
group = showchoicesapi("Lista de grupos que tienen esa receta ("+cook+"). Selecciona el grupo a quitar","Eliminar receta de un grupo","/get/grpcook?CookName="+cook,'Name')
if group is not None and easygui.ynbox("Se va a quitar la receta "+cook+" del grupo "+group+". ¿Seguro?","Eliminar receta de un grupo"):
sendsettoapi("/del/cookgrp?CookName="+cook+"&GroupName="+group,"Receta quitada del grupo")
elif menu == '5':
cook = showchoicesapi("Lista de recetas implementadas en algún grupo. Selecciona una para elegir un grupo de esa receta para borrar. Si la receta no está en ningún grupo, no saldrá.","Eliminar receta de un grupo","/get/cookall",'CookName')
cook = showchoicesapi("Lista de recetas implementadas en algún grupo. Selecciona una para ver los grupos de la receta. Si la receta no está en ningún grupo, no saldrá.","Grupos de una receta","/get/cookall",'CookName')
if cook is not None:
showchoicesapi("Lista de grupos que tienen esa receta. Selecciona el grupo a quitar","Eliminar receta de un grupo","/get/grpcook?CookName="+cook,'Name')
showchoicesapi("Lista de grupos que tienen la receta "+cook+".","Grupos de una receta","/get/grpcook?CookName="+cook,'Name')
elif menu == '6':
cook = showchoicesapi("Lista de recetas implementadas en algún grupo. Selecciona para limpiar sus estadísticas de implementación. Si la receta no está en ningún grupo, no saldrá.", T('Clean cook status'),"/get/cookall",'CookName')
if cook is not None and easygui.ynbox("Se va a limpiar el estado de implementación de la receta "+cook+". ¿Seguro?",T('Clean cook status')):
sendsettoapi("/del/cleancook?CookName="+cook,cook+" limpiada")
elif menu is None:
menuprinc()
return

View File

@@ -42,25 +42,28 @@ def T_es(textid):
'Name of the cook':'Nombre de la receta',
'Select a group': 'Seleccione un grupo',
'Cooks of computer': 'Recetas del equipo',
'Groups of computer':'Grupos del equipo',
'Groups of computer': 'Grupos del equipo',
'Cooks pending of computer': 'Recetas pendientes del equipo',
'New group name':'Nombre del nuevo grupo',
'Computers menu':'Menú equipos',
'Groups menu':'Menú grupos',
'Cooks menu':'Menú recetas',
'Reports menu':'Menú reportes',
'List of computers and cooks of a group':'Listado de equipos y recetas de un grupo',
'List of groups of a cook':'Listado de grupos de una receta',
'Select computer to add to a group':'Seleccione equipo para añadir a un grupo',
'Select group to be added':'Seleccione grupo a ser añadido',
'Select group to delete':'Seleccione grupo a quitar',
'New group name': 'Nombre del nuevo grupo',
'Computers menu': 'Menú equipos',
'Groups menu': 'Menú grupos',
'Cooks menu': 'Menú recetas',
'Reports menu': 'Menú reportes',
'List of computers and cooks of a group': 'Listado de equipos y recetas de un grupo',
'List of groups of a cook': 'Listado de grupos de una receta',
'Select computer to add to a group': 'Seleccione equipo para añadir a un grupo',
'Select group to be added': 'Seleccione grupo a ser añadido',
'Select group to delete': 'Seleccione grupo a quitar',
'Rename cook': 'Renombrar receta',
'Set password':'Establecer contraseña',
'Set password': 'Establecer contraseña',
'There is no password yet in PCM. Please set one below':'No hay contraseña aún en PCM. Por favor, escriba una debajo',
'Confirm it':'Confirmalo',
'Password not match. App will exit':'Las contraseñas no coinciden. La aplicación se va a cerrar',
'Enter password':'Introducir contraseña',
'Enter password to start':'Introduzca la contraseña para empezar'
'Confirm it': 'Confirmalo',
'Password not match. App will exit': 'Las contraseñas no coinciden. La aplicación se va a cerrar',
'Enter password': 'Introducir contraseña',
'Enter password to start': 'Introduzca la contraseña para empezar',
'Clean cook status': 'Borrar estado de una receta',
'With errors': 'Con errores',
'Error talking with API': 'Error en la comunicación con la API'
}
return dict[textid]

View File

@@ -5,8 +5,14 @@ First: Name, a line like below, with the name
"name: My Super Cook"
Then, the revision number, when this number changes, cook will be reapplied
"revision: 1"
If the cook has to run everytime client is called (And not only one time per new revision), you have to add:
"runever: 1" (1-> Everytime, if you change to 0 or delete, it will not do it)
If the cook has to run when no user is logued in, add:
"atstartup: 1"
Be aware that for be able to use this, in task scheduler (Or your favourite method) you have to run client.ps1 with argument "-startup 1" when no users are logued
And then, steps. First a "steps:" line, and then line by line the steps of the cook
"steps:
- PWCMD|White-Output "Hello World"