GUI version to control all

This commit is contained in:
2019-06-11 11:14:38 +02:00
parent c4f1510e25
commit 1873e21c71
11 changed files with 366 additions and 400 deletions

6
.gitignore vendored
View File

@@ -1,7 +1,9 @@
**/thumbs.bd
*.bak
api.log
client/config.ps1
*.log
*.out
client/configpcm.ini
client/controltkinter.py
BD/database*
reports/
__pycache__/

Binary file not shown.

View File

@@ -2,18 +2,23 @@
Powerful Computer Manager is the super-simple-but-powerful program to automatizate tasks in groups of computers (In a Active Directory site, or not) in a unattended way.
It inteed to be a simple SSMS alternative, that inventarizes computers and install/remove software in it, tweak system of run arbitrary commands.
You only have to write simple _cooks_ that are small yaml text files, create groups of computers and assign _cooks_ to this computers, and will be run in the destination computers
You only have to write simple _cooks_ that are small yaml text files, create groups of computers and assign _cooks_ to this groups, and will be run in the destination computers
# Disclaimer
I'm using this program in the company I work with 10 computers with Windows 8.1/10 with various software (MSI,EXE,...) and tweaking services, and it works right
I'm using this program in the company I work with 12 computers with Windows 8.1/10 with various software (MSI,EXE,...) and tweaking services, and it works right
It's not super-stable and error proof, then, I don't have any responsability if something crashes, but you can open a Issue and will see it
# Roadmap
GUI administration in Python to superseed Powershell CLI control program and be cross-platform
- English (Its all in Spanish now). Create a way to translate it
- Security (API 1)
- Stabilize all
- If anyone wants to create a better gui in Python it will be awesome. I used easygui to create a fast usable gui but maybe is not very proffesional.. Anyone?
I had some in TKInter but easygui was very useful without making difficult release it as first usable version
# Requirements
@@ -22,16 +27,16 @@ For server you can use Linux or Windows, and in theory any environment that can
- Python3 with:
- Falcon
- Waitress-serve
- Json (Python3 have it preinstalled)
- Yaml
Python3 deps can be installed it using pip install command (pip install waitress falcon pyyaml)
- For controlling the program, you have to use "control.ps1" using Powershell. Powershell comes with Windows, and can be installed (PWCore) in Linux and macOS (I didn't tested it).
- For controlling the program, you have to start control.pyw using Python3. It doesn't need to be started in server, but it has to be in that folder (Or with configpcm.ini file).
It uses easygui of python3 (pip install easygui)
## Clients
- Windows:
- Windows 7 SP1 absolute minimal, but its only officially tested in 8.1 and 10, Windows 7 is being old now.
- It needs Powershell 5.0+, lower versions doesn't have some commands, not tested. In Windows 7 and 8.1, you have to update Powershell. (With Powershell 3.0/4.0, some commands like Get-Package doesn't work)
You can update from here: https://docs.microsoft.com/en-us/powershell/scripting/setup/installing-windows-powershell?view=powershell-6#upgrading-existing-windows-powershell
- It needs Powershell 5.0+ (Not PWCore versions), lower versions doesnt guaranteed to work, not tested. In Windows 7 and 8.1, you have to update Powershell. (With Powershell 3.0/4.0, some commands like Get-Package doesn't work)
You can update from here: https://docs.microsoft.com/en-us/powershell/scripting/setup/installing-windows-powershell?view=powershell-6#upgrading-existing-windows-powershell (Download link: https://www.microsoft.com/en-us/download/details.aspx?id=54616)
- Linux:
- Not supported yet, but when Windows be stable, I will try to do it in some way
@@ -42,10 +47,10 @@ For server you can use Linux or Windows, and in theory any environment that can
- Install dependencies
- Open sysopt.py file and change values if needed
- Use bat file if you are in Windows to run the python server, or sh file if you are in Linux environment
- Go to Client folder and copy "configexample.ps1" to "config.ps1" and change their values to yours.
- For clients to work, they have to run "client\client.ps1" every 30 mins/1 hour or so, I did using Active Directory and a Task Scheduled GPO (Copying client.ps1 and config.ps1 files from Client to SysVol\DomainName\Scripts\)
- Go to Client folder and copy "configpcm_example.ini" to "configpcm.ini" and change their values to yours.
- For clients to work, they have to run "client\client.ps1" every 30 mins/1 hour or so, I did using Active Directory and a Task Scheduled GPO (Copying client.ps1 and configpcm.ini files from Client to SysVol\DomainName\Scripts\)
- User: SYSTEM (Or NT\SYSTEM)
- Command: powershell.exe
- Args: -executionpolicy bypass -windowstyle hidden -noninteractive -nologo -file "\\SERVER\SysVol\DOMAINNAME\scripts\client.ps1"
Note: client.ps1 has to have control.ps1 file with it
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

191
api.py
View File

@@ -1,5 +1,6 @@
#!/usr/bin/python3
# Build 5
BUILD = 12
API_VER = 0 #Its beta, API 1 will have password checks enabled
##It can be run directly with "waitress-serve --port=3333 api:api"
import falcon
import random
@@ -31,7 +32,7 @@ class getComputerExists(object):
UUID = value
if ComputerName is None:
response.media = {'RESULT': '0'}
response.media = {'RESULT': 'ERROR'}
else:
result = sql.select("SELECT COUNT(*) 'RESULT' FROM COMPUTERS WHERE Name='"+ComputerName+"' AND UUID='"+UUID+"'")
@@ -40,11 +41,14 @@ class getComputerExists(object):
sql.insert("UPDATE COMPUTERS SET UUID='"+UUID+"' WHERE Name='"+ComputerName+"'")
response.media = {'RESULT': '1'}
return
elif sql.select("SELECT COUNT(*) 'RESULT' FROM COMPUTERS WHERE Name='"+ComputerName+"'")[0]['RESULT'] != 0:
response.media = {'RESULT': 'ERROR'}
return
if sysopt.addComputers == True:
sql.insert("INSERT INTO COMPUTERS (`Name`,`UUID`) VALUES('"+ComputerName+"','"+UUID+"')")
response.media = {'RESULT': '1'}
else:
response.media = {'RESULT': '0'}
response.media = {'RESULT': 'ERROR'}
else: #Exists
response.media = {'RESULT': '1'}
@@ -94,7 +98,27 @@ class getComputersGrp(object): #List of computers in a group
data = sql.select("SELECT * FROM COMPUTERS WHERE ID_C IN (SELECT ID_C FROM COMPUTER_GROUP WHERE ID_G='"+GroupID+"') ORDER BY Name")
response.media = data
class getCook(object): # Get the list of cooks for a computer to implement (Var all=1 for see all of, implemented or not)
##
# getCookAll: Get the list of cooks added at least to one group
# /get/cookall?
# NoParams
##
class getCookAll(object):
def on_get(self,request, response):
logit(request)
data = sql.select("SELECT DISTINCT CookName FROM COOKS_IDG ORDER BY CookName ASC") #All cooks
response.media = data
##
# getCookPend: Get the list of cooks that are pending to deploy to a computer
# /get/cookpend?
# @param ComputerName/ComputerID -> Computer to deploy it
# @param GroupName/GroupID: Groups
# @param SeeAll: Send all cooks from this computer
# @param UUID: Check UUID validation of this computer (Not implemented yet)
##
class getCookPend(object): # Get the list of cooks for a computer to implement (Var all=1 for see all of, implemented or not)
def on_get(self,request, response):
logit(request)
ComputerID,GroupID, SeeAll =None, None, None
@@ -110,10 +134,10 @@ class getCook(object): # Get the list of cooks for a computer to implement (Var
if key == "SeeAll":
SeeAll = str(value)
if ComputerID is None and GroupID is None:
response.media = {'ERROR': 'I need a Group or Computer to search'}
if ComputerID is None and GroupID is None: # Error of null parameters
response.media = {'TEXT': 'I need a Group or Computer to search','RESULT':'ERROR'}
elif ComputerID is not None and SeeAll is None:
data = sql.select("SELECT * FROM COOKS_IDG WHERE ID_G IN (SELECT ID_G FROM COMPUTER_GROUP WHERE ID_C = '"+ComputerID+"')") #All cooks for this computer
data = sql.select("SELECT DISTINCT CookName FROM COOKS_IDG WHERE ID_G IN (SELECT ID_G FROM COMPUTER_GROUP WHERE ID_C = '"+ComputerID+"')") #All cooks for this computer
fordelete = []
for i in range(len(data)):
for key, value in data[i].items(): #Iterate in a dict (json)
@@ -127,11 +151,16 @@ class getCook(object): # Get the list of cooks for a computer to implement (Var
for x in reversed(fordelete): #Deleting cooks that are implemented in client. Reverse order (Because is an array and index..)
data.pop(x)
response.media = data
else:
response.media = sql.select("SELECT * FROM COOKS_IDG WHERE ID_G IN (SELECT ID_G FROM COMPUTER_GROUP WHERE ID_C = '"+ComputerID+"')") #All cooks for this computer
else: # SeeAll. Send all cooks
response.media = sql.select("SELECT DISTINCT CookName FROM COOKS_IDG WHERE ID_G IN (SELECT ID_G FROM COMPUTER_GROUP WHERE ID_C = '"+ComputerID+"')") #All cooks for this computer
class setCook(object): #Assign Cook to group
##
# addCookGrp: Assign Cook to group
# /add/cookgrp?
# @param GroupName/GroupID -> Group to show cooks
# @param CookName -> Cook to assign
##
class addCookGrp(object): #Assign Cook to group
def on_get(self, request, response):
logit(request)
GroupID, CookName = None, None # Initialize
@@ -144,12 +173,12 @@ class setCook(object): #Assign Cook to group
if key == "GroupID":
GroupID = value
if GroupID is None or exists is False:
response.media = {'ERROR': 'GroupID is not defined or Cook not exists'}
response.media = {'TEXT': 'GroupID is not defined or Cook not exists','RESULT':'ERROR'}
elif int(sql.select("SELECT COUNT(*) 'COUNT' FROM COOKS_IDG WHERE `ID_G`='"+GroupID+"' AND `CookName`='"+CookName+"'")[0]['COUNT']) > 0:
response.media = {'WARNING': 'This union GROUP-CookName exists'}
response.media = {'TEXT': 'This union GROUP-CookName exists','RESULT':'0'}
else:
result = sql.insert("INSERT INTO COOKS_IDG (`ID_G`,`CookName`) VALUES ('"+GroupID+"','"+CookName+"')")
response.media = result
response.media = {'TEXT': 'OK'}
class delCookGrp(object): #Delete cook from a group
def on_get(self,request,response):
@@ -167,9 +196,9 @@ class delCookGrp(object): #Delete cook from a group
if GroupID is not None and CookName is not None:
result = sql.insert("DELETE FROM COOKS_IDG WHERE ID_G='"+GroupID+"' AND CookName='"+CookName+"'")
response.media = result
#response.media = result
else:
response.media = {'RESULT': 'Error, no Group, or CookName does\'t exists'}
response.media = {'TEXT': 'Error, no Group, or CookName does\'t exists','RESULT':'ERROR'}
class delEmptyPcsGroup(object): #Delete all computers from a group
def on_get(self,request,response):
@@ -185,11 +214,15 @@ class delEmptyPcsGroup(object): #Delete all computers from a group
result = sql.insert("DELETE FROM COMPUTER_GROUP WHERE ID_G='"+GroupID+"'")
response.media = result
else:
response.media = {'RESULT': 'Error, this group doesn\'t exists'}
response.media = {'TEXT': 'Error, this group doesn\'t exists','RESULT':'ERROR'}
class getCookGrp(object): # Get cooks from a Group
##
# getCookGrp: Get cooks from a Group
# /get/cookgrp?
# @param GroupName/GroupID -> Group to show cooks
##
class getCookGrp(object):
def on_get(self,request,response):
logit(request)
GroupID = None # Initialize
@@ -203,8 +236,13 @@ class getCookGrp(object): # Get cooks from a Group
result = sql.select("SELECT * FROM COOKS_IDG WHERE ID_G='"+GroupID+"'")
response.media = result
else:
response.media = {'RESULT': 'Error, no Group selected'}
response.media = {'TEXT': 'Error, no Group selected','RESULT':'ERROR'}
##
# getGrpCook: Get groups from a Cook
# /get/grpcook?
# @param CookName -> Cook to show groups
##
class getGrpCook(object): # Get Groups of a Cook
def on_get(self,request,response):
logit(request)
@@ -218,7 +256,7 @@ class getGrpCook(object): # Get Groups of a Cook
if CookName is not None:
response.media = sql.select("SELECT Name FROM GROUPS WHERE ID_G IN (SELECT ID_G FROM COOKS_IDG WHERE CookName='"+CookName+"')")
else:
response.media = {'RESULT': 'Error, no Cook selected'}
response.media = {'TEXT': 'Error, no Cook selected','RESULT':'ERROR'}
class getStatusCook(object): # Get Status of a Cook (If Brief=1 is sent too, brief status (Completed:X, updated:X..))
def on_get(self,request,response):
@@ -233,7 +271,7 @@ class getStatusCook(object): # Get Status of a Cook (If Brief=1 is sent too, bri
if CookName is not None:
response.media = sql.select("SELECT Name, Revision, Error FROM COMPUTERS,COOKS_STATUS WHERE CookName = '"+CookName+"' AND COMPUTERS.ID_C=COOKS_STATUS.ID_C")
else:
response.media = {'RESULT': 'Error, no Cook selected'}
response.media = {'TEXT': 'Error, no Cook selected','RESULT':'ERROR'}
class getLastRevisionCook(object): # Get Number Revision (Revision=X)
def on_get(self,request,response):
@@ -250,8 +288,13 @@ class getLastRevisionCook(object): # Get Number Revision (Revision=X)
filecook = myfile.read()
response.media = {'Revision': str(yaml.safe_load(filecook)['revision'])}
else:
response.media = {'RESULT': 'Error, no Cook selected'}
response.media = {'TEXT': 'Error, no Cook selected','RESULT':'ERROR'}
##
# addComputer: Add a computer in database
# /add/computer?
# @param ComputerName -> ComputerName to add
##
class addComputer(object):
def on_get(self, request, response):
logit(request)
@@ -261,7 +304,7 @@ class addComputer(object):
ComputerName = value
if ComputerName is None:
response.media = {'RESULT': 'Error, you need a ComputerName to add'}
response.media = {'TEXT': 'Error, you need a ComputerName to add','RESULT':'ERROR'}
else:
result = sql.insert("INSERT INTO COMPUTERS (Name) VALUES ('"+ComputerName+"')")
response.media = result
@@ -276,7 +319,7 @@ class addGroup(object):
if GroupName is None:
response.media = {'RESULT': 'Error, you need a GroupName to add'}
response.media = {'TEXT': 'Error, you need a GroupName to add','RESULT':'ERROR'}
else:
result = sql.insert("INSERT INTO GROUPS (Name) VALUES ('"+GroupName+"')")
response.media = result
@@ -292,7 +335,7 @@ class delGroup(object): #Delete group
GroupID = str(sql.select("SELECT ID_G FROM GROUPS WHERE Name='"+value+"'")[0]['ID_G'])
if GroupID is None:
response.media = {'RESULT': 'Error, you need a GroupName to delete'}
response.media = {'TEXT': 'Error, you need a GroupName to delete','RESULT':'ERROR'}
else:
sql.insert("DELETE FROM COMPUTER_GROUP WHERE ID_G='"+GroupID+"'")
sql.insert("DELETE FROM COOKS_IDG WHERE ID_G='"+GroupID+"'")
@@ -313,10 +356,10 @@ class updGroup(object): #Delete group
if Count == "0":
GroupNewName = value
else:
response.media = {'RESULT': 'Error, New group name exists'}
response.media = {'TEXT': 'Error, New group name exists','RESULT':'ERROR'}
if GroupID is None or GroupNewName is None:
response.media = {'RESULT': 'Error, you need a GroupName and new name to update name'}
response.media = {'TEXT': 'Error, you need a GroupName and new name to update name','RESULT':'ERROR'}
else:
result = sql.insert("UPDATE GROUPS SET Name='"+GroupNewName+"' WHERE ID_G='"+GroupID+"'")
response.media = result
@@ -336,7 +379,7 @@ class addGrpComputer(object): #Add computer to a group (Local)
GroupID = value
if ComputerID is None or GroupID is None:
response.media = {'RESULT': 'Error, you need a Name and Group to add'}
response.media = {'TEXT': 'Error, you need a Name and Group to add','RESULT':'ERROR'}
else:
result = sql.insert("INSERT INTO COMPUTER_GROUP (ID_C,ID_G) VALUES ('"+ComputerID+"','"+GroupID+"')")
response.media = result
@@ -356,7 +399,7 @@ class delGrpComputer(object): #Del computer from a group
GroupID = value
if ComputerID is None or GroupID is None:
response.media = {'RESULT': 'Error, you need a Name and Group to add'}
response.media = {'TEXT': 'Error, you need a Name and Group to add','RESULT':'ERROR'}
else:
result = sql.insert("DELETE FROM COMPUTER_GROUP WHERE ID_C='"+ComputerID+"' AND ID_G='"+GroupID+"'")
response.media = result
@@ -370,10 +413,12 @@ class delComputer(object): #Delete computer
if key == "ComputerName":
ComputerID = str(sql.select("SELECT ID_C FROM COMPUTERS WHERE Name='"+value+"'")[0]['ID_C'])
if key == "ComputerID":
ComputerID = value
ComputerID = str(sql.select("SELECT ID_C FROM COMPUTERS WHERE ID_C='"+value+"'")[0]['ID_C'])
if ComputerID is None:
response.media = {'RESULT': 'Error, you need a Name/ComputerID to update data'}
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'}
else:
sql.insert("DELETE FROM COMPUTER_GROUP WHERE ID_C='"+ComputerID+"'")
sql.insert("DELETE FROM COOKS_STATUS WHERE ID_C='"+ComputerID+"'")
@@ -390,18 +435,18 @@ class updComputer(object):
try:
ComputerID = str(sql.select("SELECT ID_C FROM COMPUTERS WHERE Name='"+value+"'")[0]['ID_C'])
except:
response.media = {'RESULT': 'Error: Computer not exists in database'}
response.media = {'TEXT': 'Error: Computer not exists in database','RESULT':'ERROR'}
break
if key == "ComputerID":
ComputerID = value
if key == "UUID":
UUID = value
if ComputerID is None and response.media is None:
response.media = {'RESULT': 'Error, you need a ComputerName/ComputerID to update data'}
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:
Count = str(sql.select("SELECT COUNT(*) 'Count' FROM COMPUTERS WHERE UUID='"+UUID+"' AND ID_C='"+ComputerID+"'")[0]['Count'])
if Count == "0":
response.media = {'RESULT': 'Error, computer doesn\'t exists in database'}
response.media = {'TEXT': 'Error, computer doesn\'t exists in database','RESULT':'ERROR'}
else:
for key, value in request.params.items():
if key == "SOVersion":
@@ -419,7 +464,12 @@ class updComputer(object):
if key == "CPUName":
response.media = sql.insert("UPDATE COMPUTERS SET CPUName='"+value+"' WHERE ID_C='"+ComputerID+"'")
##
# updCookName: Rename cook name
# /upd/cookname?
# @param CookName -> Original Cook Name
# @param CookNewName -> New Cook Name
##
class updCookName(object):
def on_get(self, request, response):
logit(request)
@@ -429,16 +479,16 @@ class updCookName(object):
if os.path.isfile('cooks/'+value+'.yaml'):
CookName= value
else:
response.media = {'RESULT': 'Error: Cook not exists in folder'}
response.media = {'TEXT': 'Error: Cook not exists in folder','RESULT':'ERROR'}
break
if key == "CookNewName":
if os.path.isfile('cooks/'+value+'.yaml'):
response.media = {'RESULT': 'Error: There is a cook with the new name in folder!'}
response.media = {'TEXT': 'Error: There is a cook with the new name in folder!','RESULT':'ERROR'}
break
else:
CookNewName= value
if CookName is None or CookNewName is None:
response.media = {'RESULT': 'Error, you need the old and new Cook Name to update data'}
response.media = {'TEXT': 'Error, you need the old and new Cook Name to update data','RESULT':'ERROR'}
elif response.media is None:
old_file = os.path.join("cooks", CookName+'.yaml')
new_file = os.path.join("cooks", CookNewName+'.yaml')
@@ -456,7 +506,7 @@ class loadCook(object):
if os.path.isfile('cooks/'+value+'.yaml'):
CookName= value
else:
response.media = {'RESULT': 'Error: Cook not exists in folder'}
response.media = {'TEXT': 'Error: Cook not exists in folder','RESULT':'ERROR'}
break
if key == "ComputerName":
ComputerID = str(sql.select("SELECT ID_C FROM COMPUTERS WHERE Name='"+value+"'")[0]['ID_C'])
@@ -466,11 +516,11 @@ class loadCook(object):
UUID = value
if CookName is None and response.media is None:
response.media = {'RESULT': 'Error, you need a CookName to load it'}
response.media = {'TEXT': 'Error, you need a CookName to load it','RESULT':'ERROR'}
elif response.media is None:
Count = str(sql.select("SELECT COUNT(*) 'Count' FROM COMPUTERS WHERE UUID='"+UUID+"' AND ID_C='"+ComputerID+"'")[0]['Count'])
if Count == "0":
response.media = {'RESULT': 'Error, computer doesn\'t exists in database'}
response.media = {'TEXT': 'Error, computer doesn\'t exists in database','RESULT':'ERROR'}
else:
with open('cooks/'+CookName+'.yaml', 'r') as myfile:
data = myfile.read()
@@ -485,7 +535,7 @@ class setCookStatus(object):
if os.path.isfile('cooks/'+value+'.yaml'): # You have to know that cook exists.
CookName= value
else:
response.media = {'RESULT': 'Error: Cook not exists in folder'}
response.media = {'TEXT': 'Error: Cook not exists in folder','RESULT':'ERROR'}
break
if key == "ComputerName":
ComputerID = str(sql.select("SELECT ID_C FROM COMPUTERS WHERE Name='"+value+"'")[0]['ID_C'])
@@ -499,7 +549,7 @@ class setCookStatus(object):
ErrorDesc = value
if CookName is None and response.media is None:
response.media = {'RESULT': 'Error, you need a CookName to load it'}
response.media = {'TEXT': 'Error, you need a CookName to load it','RESULT':'ERROR'}
elif response.media is None and CookName is not None and ComputerID is not None and Revision is not None and Error is not None:
statt = sql.select("SELECT COUNT(*) 'RESULT' FROM COOKS_STATUS WHERE CookName='"+CookName+"' AND ID_C='"+ComputerID+"'")[0]['RESULT']
if statt == 0:
@@ -509,33 +559,48 @@ class setCookStatus(object):
#UPDATE, NOT NEW
response.media = sql.insert("UPDATE COOKS_STATUS SET Revision='"+Revision+"',`Error`='"+Error+"',`ErrorDesc`='"+ErrorDesc+"' WHERE ID_C='"+ComputerID+"' AND CookName='"+CookName+"'")
else:
response.media = {'RESULT': 'Error in parameters...'}
response.media = {'TEXT': 'Error in parameters...','RESULT':'ERROR'}
logit(response.media)
api = falcon.API()
api.add_route('/get/computers', getComputers()) #Get list of computer
api.add_route('/get/computerexists', getComputerExists()) #Returns 0 or 1 (name status)
api.add_route('/get/groups', getGroups()) #Get groups of a computer (Or list if not args)
api.add_route('/get/computersgrp', getComputersGrp()) #Get computers in a group
api.add_route('/get/cook', getCook()) #Get cooks from a group
api.add_route('/set/cook', setCook()) #Assign cook to group
api.add_route('/add/computer', addComputer()) #Add computer
api.add_route('/add/group', addGroup()) #Add group to the list of local groups
api.add_route('/add/cookgrp', addCookGrp()) #Assign cook to group
api.add_route('/add/grpcomputer', addGrpComputer()) #Add computer to a group
api.add_route('/del/computer', delComputer()) #Delete computer
api.add_route('/del/cookgrp', delCookGrp()) # Deassign cook from a group
api.add_route('/del/emptypcsgroup', delEmptyPcsGroup()) # Delete all computers from a group
api.add_route('/get/cookgrp', getCookGrp()) # See cooks that have a determinated group
api.add_route('/get/grpcook', getGrpCook()) # See groups of a determinated cook
api.add_route('/get/statuscook', getStatusCook()) # See status of a cook
api.add_route('/get/lastrevisioncook', getLastRevisionCook()) # Returns number of last revision of a cook
api.add_route('/add/computer', addComputer()) #Add computer
api.add_route('/del/computer', delComputer()) #Delete computer
api.add_route('/add/group', addGroup()) #Add group to the list of local groups
api.add_route('/del/group', delGroup()) #Delete group
api.add_route('/upd/group', updGroup()) #Update group name
api.add_route('/add/grpcomputer', addGrpComputer()) #Add computer to a group
api.add_route('/del/grpcomputer', delGrpComputer()) #Delete computer from a group
api.add_route('/get/computerexists', getComputerExists()) #Returns 0 or 1 (name status)
api.add_route('/get/computers', getComputers()) #Get list of computer
api.add_route('/get/computersgrp', getComputersGrp()) #Get computers in a group
api.add_route('/get/cookall', getCookAll()) #Get all cooks implemented in one group at least
api.add_route('/get/cookgrp', getCookGrp()) # See cooks that have a determinated group
api.add_route('/get/cookpend', getCookPend()) #Get cooks pending to implement to a computer
api.add_route('/get/groups', getGroups()) #Get groups of a computer (Or list if not args)
api.add_route('/get/grpcook', getGrpCook()) # See groups of a determinated cook
api.add_route('/get/lastrevisioncook', getLastRevisionCook()) # Returns number of last revision of a cook
api.add_route('/get/statuscook', getStatusCook()) # See status of a cook
api.add_route('/load/cook', loadCook()) # Load a cook (Transfer in json way)
api.add_route('/set/cookstatus', setCookStatus()) # Update status of a cook in a computer (OLD)
api.add_route('/upd/cookstatus', setCookStatus()) # Update status of a cook in a computer
api.add_route('/upd/computer', updComputer()) #Update data of computer
api.add_route('/upd/cookname', updCookName()) #Update file name of cook and SQL references to it.
api.add_route('/load/cook', loadCook()) # Load a cook (Transfer in json way)
api.add_route('/set/cookstatus', setCookStatus()) # Update status of a cook in a computer
api.add_route('/upd/group', updGroup()) #Update group name
#api.add_route('/check/password', checkPassword()) #Check admin password
#api.add_route('/upd/password', updPassword()) # Update password (Or create it not exists)
#api.add_route('/get/password', getPassword()) # Get password (Will be '' if password not exists)
class getApiVer(object):
def on_get(self, request, response):
logit(request)
response.media = {'API':API_VER}
api.add_route('/get/apiver', getApiVer()) # Get API version
print("Build: "+str(BUILD))
print("API Version: "+str(API_VER))

View File

@@ -1,310 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="15" />
<object class="Project" expanded="1">
<property name="class_decoration">; </property>
<property name="code_generation">C++</property>
<property name="disconnect_events">1</property>
<property name="disconnect_mode">source_name</property>
<property name="disconnect_php_events">0</property>
<property name="disconnect_python_events">0</property>
<property name="embedded_files_path">res</property>
<property name="encoding">UTF-8</property>
<property name="event_generation">connect</property>
<property name="file"></property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="indent_with_spaces"></property>
<property name="internationalize">0</property>
<property name="name">MyProject1</property>
<property name="namespace"></property>
<property name="path">.</property>
<property name="precompiled_header"></property>
<property name="relative_path">1</property>
<property name="skip_lua_events">1</property>
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_enum">0</property>
<property name="use_microsoft_bom">0</property>
<object class="Frame" expanded="1">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
<property name="center">wxBOTH</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="enabled">1</property>
<property name="event_handler">impl_virtual</property>
<property name="extra_style"></property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">MainFrame</property>
<property name="pos"></property>
<property name="size">749,396</property>
<property name="style">wxDEFAULT_FRAME_STYLE</property>
<property name="subclass">; ; forward_declare</property>
<property name="title"></property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<property name="xrc_skip_sizer">1</property>
<object class="wxMenuBar" expanded="1">
<property name="bg"></property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">MyMenuBar</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">m_menubar1</property>
<property name="permission">protected</property>
<property name="pos"></property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<object class="wxMenu" expanded="1">
<property name="label">Equipos</property>
<property name="name">m_computers</property>
<property name="permission">protected</property>
<object class="wxMenuItem" expanded="1">
<property name="bitmap"></property>
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_ANY</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Añadir equipo</property>
<property name="name">scomp_addc</property>
<property name="permission">none</property>
<property name="shortcut"></property>
<property name="unchecked_bitmap"></property>
</object>
<object class="wxMenuItem" expanded="1">
<property name="bitmap"></property>
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_ANY</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Borrar equipo</property>
<property name="name">scomp_deletec</property>
<property name="permission">none</property>
<property name="shortcut"></property>
<property name="unchecked_bitmap"></property>
</object>
</object>
<object class="wxMenu" expanded="1">
<property name="label">Grupos</property>
<property name="name">m_groups</property>
<property name="permission">protected</property>
<object class="wxMenuItem" expanded="1">
<property name="bitmap"></property>
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_ANY</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Añadir Grupo</property>
<property name="name">sgroup_addg</property>
<property name="permission">none</property>
<property name="shortcut"></property>
<property name="unchecked_bitmap"></property>
</object>
<object class="wxMenuItem" expanded="1">
<property name="bitmap"></property>
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_ANY</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Borrar grupo</property>
<property name="name">sgroup_delg</property>
<property name="permission">none</property>
<property name="shortcut"></property>
<property name="unchecked_bitmap"></property>
</object>
<object class="wxMenuItem" expanded="1">
<property name="bitmap"></property>
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_ANY</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Ver equipos de un grupo</property>
<property name="name">sgroup_seeg</property>
<property name="permission">none</property>
<property name="shortcut"></property>
<property name="unchecked_bitmap"></property>
</object>
<object class="wxMenuItem" expanded="1">
<property name="bitmap"></property>
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_ANY</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Vaciar grupo</property>
<property name="name">sgroup_emptyg</property>
<property name="permission">none</property>
<property name="shortcut"></property>
<property name="unchecked_bitmap"></property>
</object>
<object class="wxMenuItem" expanded="1">
<property name="bitmap"></property>
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_ANY</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Cambiar nombre de un grupo</property>
<property name="name">sgroup_reng</property>
<property name="permission">none</property>
<property name="shortcut"></property>
<property name="unchecked_bitmap"></property>
</object>
<object class="wxMenuItem" expanded="1">
<property name="bitmap"></property>
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_ANY</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Recetas asignadas a un grupo</property>
<property name="name">sgroup_cooksg</property>
<property name="permission">none</property>
<property name="shortcut"></property>
<property name="unchecked_bitmap"></property>
</object>
</object>
<object class="wxMenu" expanded="1">
<property name="label">Recetas</property>
<property name="name">m_cooks</property>
<property name="permission">protected</property>
<object class="wxMenuItem" expanded="1">
<property name="bitmap"></property>
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_ANY</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Recetas de un grupo</property>
<property name="name">scook_cooksg</property>
<property name="permission">none</property>
<property name="shortcut"></property>
<property name="unchecked_bitmap"></property>
</object>
<object class="wxMenuItem" expanded="1">
<property name="bitmap"></property>
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_ANY</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Añadir receta a un grupo</property>
<property name="name">scook_addcookg</property>
<property name="permission">none</property>
<property name="shortcut"></property>
<property name="unchecked_bitmap"></property>
</object>
<object class="wxMenuItem" expanded="1">
<property name="bitmap"></property>
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_ANY</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Borrar receta de un grupo</property>
<property name="name">scook_deletecookg</property>
<property name="permission">none</property>
<property name="shortcut"></property>
<property name="unchecked_bitmap"></property>
</object>
<object class="wxMenuItem" expanded="1">
<property name="bitmap"></property>
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_ANY</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Renombrar receta</property>
<property name="name">scook_renamecook</property>
<property name="permission">none</property>
<property name="shortcut"></property>
<property name="unchecked_bitmap"></property>
</object>
<object class="wxMenuItem" expanded="1">
<property name="bitmap"></property>
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_ANY</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Detalles de implantación de una receta</property>
<property name="name">scook_detailscook</property>
<property name="permission">none</property>
<property name="shortcut"></property>
<property name="unchecked_bitmap"></property>
</object>
</object>
<object class="wxMenu" expanded="1">
<property name="label">Reportes</property>
<property name="name">m_reports</property>
<property name="permission">protected</property>
<object class="wxMenuItem" expanded="1">
<property name="bitmap"></property>
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_ANY</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Reporte de equipos</property>
<property name="name">srep_rcomp</property>
<property name="permission">none</property>
<property name="shortcut"></property>
<property name="unchecked_bitmap"></property>
</object>
<object class="wxMenuItem" expanded="1">
<property name="bitmap"></property>
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_ANY</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Reporte de grupos</property>
<property name="name">srep_rgroup</property>
<property name="permission">none</property>
<property name="shortcut"></property>
<property name="unchecked_bitmap"></property>
</object>
<object class="wxMenuItem" expanded="1">
<property name="bitmap"></property>
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_ANY</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Reporte de recetas</property>
<property name="name">srep_rcook</property>
<property name="permission">none</property>
<property name="shortcut"></property>
<property name="unchecked_bitmap"></property>
</object>
</object>
</object>
</object>
</object>
</wxFormBuilder_Project>

View File

@@ -1,12 +1,14 @@
# Build 2
# Build 5
$root = $PSCommandPath | Split-Path -Parent
. $root\config.ps1
$server = (Get-Content "$root\configpcm.ini" | select -Skip 1 | ConvertFrom-StringData).server
$resources = (Get-Content "$root\configpcm.ini" | select -Skip 1 | ConvertFrom-StringData).resources
$computerName = $env:COMPUTERNAME
$computerName = [System.Net.Dns]::GetHostName()
$UUID=(get-wmiobject Win32_ComputerSystemProduct).UUID
$exists = Invoke-RestMethod -Method Get -Uri "$server/get/computerexists?ComputerName=$computerName&UUID=$UUID"
if ($exists.Result -eq 0){
if ($exists.Result -eq "ERROR"){
Write-Host "Computer outside database:" $computerName
exit
}
@@ -30,7 +32,7 @@ $lastUser = (Get-CimInstance -ClassName Win32_ComputerSystem -Property UserName
Invoke-RestMethod -Method Get -Uri "$server/upd/computer?ComputerName=$computerName&UUID=$UUID&LastUser=$lastUser" | out-null
$cooks = Invoke-RestMethod -Method Get -Uri "$server/get/cook?ComputerName=$computerName&UUID=$UUID"
$cooks = Invoke-RestMethod -Method Get -Uri "$server/get/cookpend?ComputerName=$computerName&UUID=$UUID"
foreach ($CookName in $cooks){
Set-Location $env:temp # For downloading/copying items, use system temp location
@@ -79,7 +81,7 @@ foreach ($CookName in $cooks){
$err = 1
}
}
"KILL_PROCESS" {
{$_ -in "KILL_PROCESS","KILLPROCESS"} {
$p = Get-Process -Name "$param"
if ($? -eq $true){ # Only do something if exists
Stop-Process -InputObject $p -Force -ErrorVariable errvar -ErrorAction Continue
@@ -90,7 +92,7 @@ foreach ($CookName in $cooks){
}
"CMD" { # Run a cmd command. Note: Runs at high priv.
cmd.exe /c "$param"
if ($? -eq $false){ # Error in CMD
if ($LASTEXITCODE -ne 0){ # Error in CMD
$err = 1
}
}
@@ -208,7 +210,7 @@ foreach ($CookName in $cooks){
if ($cook.runever -eq "1"){
$err = -1 # This is for run but not for error, is by cook saw.
}
Invoke-RestMethod -Method Get -Uri "$server/set/cookstatus?ComputerName=$computerName&UUID=$UUID&CookName=$CookName&Revision=$CookRevision&Error=$err&ErrorDesc=$errvar" | out-null
Invoke-RestMethod -Method Get -Uri "$server/upd/cookstatus?ComputerName=$computerName&UUID=$UUID&CookName=$CookName&Revision=$CookRevision&Error=$err&ErrorDesc=$errvar" | out-null
#Delete files copied to temp for saving space
foreach ($element in $filesCopied) {

View File

@@ -1,2 +0,0 @@
$server = "http://miserver.dominio:3333" #Server that runs api service
$resources = "\\MISERVER\REPOFOLDER" #Where files for copy are (Not cooks)

View File

@@ -0,0 +1,2 @@
server=http://miserver.dominio:3333
resources=\\\\MISERVER\\REPOFOLDER

View File

@@ -1,6 +1,9 @@
# Build 1
# Build 2
Write-Host "This utility is obsolete and may not work. Please use control.pyw"
$root = $PSCommandPath | Split-Path -Parent
. $root\config.ps1
$server = (Get-Content "$root\configpcm.ini" | select -Skip 1 | ConvertFrom-StringData).server
$resources = (Get-Content "$root\configpcm.ini" | select -Skip 1 | ConvertFrom-StringData).resources
function seeGroups {
$answer = Invoke-RestMethod -Method Get -Uri "$server/get/groups"
@@ -255,7 +258,7 @@ function menuCooks {
$CookName = Read-Host -Prompt "Nombre de la receta a añadir"
seeGroups #Function
$GroupName = Read-Host -Prompt "Nombre del grupo que quieres que lo tenga"
Invoke-RestMethod -Method Get -Uri "$server/set/cook?GroupName=$GroupName&CookName=$CookName"
Invoke-RestMethod -Method Get -Uri "$server/add/cookgrp?GroupName=$GroupName&CookName=$CookName"
pause
} '5' {

199
client/control.pyw Normal file
View File

@@ -0,0 +1,199 @@
#!/usr/bin/python3
# Version 0.5
import easygui
import configparser
import json
import requests
import subprocess, platform
def ping(host):
"""
Returns True if host (str) responds to a ping request.
Remember that a host may not respond to a ping (ICMP) request even if the host name is valid.
"""
# Option for the number of packets as a function of
param = '-n' if platform.system().lower()=='windows' else '-c'
# Building the command. Ex: "ping -c 1 google.com"
command = ['ping', param, '1', host]
return subprocess.call(command) == 0
## sendmenudot, returns of choice of a series of choices that has "." as delimiter inside it (For returning index)
def sendmenudot(text,title,choices):
menu = easygui.choicebox(text,title,choices)
if menu is not None:
return menu.split('.')[0]
else:
return menu
## showchoicesapi, apiurl has to have all (Inlcuding server part)
def showchoicesapi(text,title,apiurl,field='Name'):
try:
jsonobj = json.loads(requests.get(apiurl).text)
listitems = []
for ite in jsonobj:
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')
return None
def sendsettoapi(suburl,goodtext): # Send a add/del/modify to API. Doesn't return more than "Valid" and "Not valid"
global c_server
try:
jsonobj = json.loads(requests.get(c_server+suburl).text)
if jsonobj is not None and jsonobj['RESULT'] is not None and jsonobj['RESULT'] == 'ERROR':
if jsonobj['TEXT']:
easygui.msgbox(jsonobj['TEXT'],"Error","Ok")
else:
easygui.msgbox("Error no especificado","Error","Ok")
return 1
else:
easygui.msgbox(goodtext,"Exito","Ok")
return 0
except:
easygui.msgbox("Error inesperado","Error","Ok")
return 1
config = configparser.ConfigParser()
config.read('configpcm.ini')
c_server = config['General']['server']
c_resources = config['General']['resources'].replace('\\\\','\\')
def menuprinc():
menu = sendmenudot("Menú principal","Seleccione opción",['1.Equipos','2.Grupos','3.Recetas','4.Reportes/Listados'])
if menu == '1':
mcomputers()
elif menu == '2':
mgroups()
elif menu == '3':
mcooks()
elif menu == '4':
mreports()
def mcomputers():
global c_server
menu = sendmenudot("Menú equipos","Seleccione opción",['1.Añadir equipo','2.Borrar equipo','3.Añadir equipo a un grupo','4.Listado de equipos'])
if menu == '1':
newcomputer = easygui.enterbox("Nombre del nuevo equipo","Añadir equipo")
if easygui.ynbox("Nombre del equipo: '"+newcomputer+"'. ¿Seguro?","Añadir equipo"):
sendsettoapi("/add/computer?ComputerName="+newcomputer,"Equipo añadido a la base de datos")
elif menu == '2':
whatc = showchoicesapi("Seleccione equipo a borrar","Borrar equipo",c_server+"/get/computers")
if whatc is not None and easygui.ynbox("Se va a borrar el equipo '"+whatc+"'. ¿Seguro?","Borrar equipo"):
sendsettoapi("/del/computer?ComputerName="+whatc,"Equipo borrado")
elif menu == '3':
m_addcomputergroup()
elif menu == '4':
showchoicesapi("Lista de equipos","Listado de equipos",c_server+"/get/computers")
elif menu is None:
menuprinc()
return
mcomputers()
def mgroups():
global c_server
menu = sendmenudot("Menú grupos","Seleccione opción",['1.Añadir grupo','2.Borrar grupo','3.Añadir equipo a un grupo','4.Quitar equipo de un grupo','5.Listado de grupos','6.Listado de equipos de un grupo'])
if menu == '1':
newgroup = easygui.enterbox("Nombre del nuevo grupo","Añadir grupo")
if easygui.ynbox("Nombre del grupo: '"+newgroup+"'. ¿Seguro?","Añadir grupo"):
sendsettoapi("/add/group?GroupName="+newgroup,"Grupo añadido a la base de datos")
elif menu == '2':
group = showchoicesapi("Lista de grupos. Selecciona uno para borrarlo","Borrar grupo",c_server+"/get/groups",'Name')
if group is not None:
if easygui.ynbox("Borrar grupo '"+group+"'. ¿Seguro?","Borrar grupo"):
sendsettoapi("/del/group?GroupName="+group,"Grupo borrado")
elif menu == '3':
m_addcomputergroup()
elif menu == '4':
m_delcomputergroup()
elif menu == '5':
showchoicesapi("Listado de grupos","Listado de grupos",c_server+"/get/groups",field='Name')
elif menu == '6':
group = showchoicesapi("Lista de grupos","Listado de equipos de un grupo",c_server+"/get/groups")
showchoicesapi("Lista de equipos del grupo "+group,"Listado de equipos de un grupo",c_server+"/get/computersgrp?GroupName="+group)
elif menu is None:
menuprinc()
return
mcomputers()
def mcooks():
global c_server
global c_resources
menu = sendmenudot("Menú recetas","Seleccione opción",['1.Detalles de una receta','2.Renombrar receta','3.Añadir receta a un grupo','4.Eliminar receta de un grupo','5.Grupos de una receta'])
if menu == '1':
cook = showchoicesapi("Lista de recetas implementadas en algún grupo. Selecciona una para ver sus datos","Detalles de una receta",c_server+"/get/cookall",'CookName')
if cook is not None:
showchoicesapi("Lista de grupos de la receta "+cook,"Listado de grupos de una receta",c_server+"/get/grpcook?CookName="+cook)
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.","Renombrar receta",c_server+"/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?","Renombrar receta"):
sendsettoapi("/upd/cookname?CookName="+cook+"&CookNewName="+newname,"Receta cambiada de nombre")
elif menu == '3':
cook = easygui.enterbox("Nombre de la receta","Añadir receta a un grupo")
group = showchoicesapi("Lista de grupos existentes","Listado de grupos",c_server+"/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",c_server+"/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",c_server+"/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",c_server+"/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",c_server+"/get/grpcook?CookName="+cook,'Name')
elif menu is None:
menuprinc()
return
mcooks()
def mreports():
global c_server
global c_resources
menu = sendmenudot("Menú reportes","Seleccione opción",['1.Listado de equipos','2.Listado de grupos','3.Equipos y recetas de un grupo','4.Grupos de una receta'])
if menu == '1': #Listado de equipos
showchoicesapi("Lista de equipos","Listado de equipos",c_server+"/get/computers")
elif menu == '2': #Listado de grupos
showchoicesapi("Lista de grupos","Listado de grupos",c_server+"/get/groups")
elif menu == '3':
group = showchoicesapi("Lista de grupos","Listado de grupos",c_server+"/get/groups")
showchoicesapi("Lista de equipos del grupo "+group,"Listado de equipos y recetas de un grupo",c_server+"/get/computersgrp?GroupName="+group)
showchoicesapi("Lista de recetas del grupo "+group,"Listado de equipos y recetas de un grupo",c_server+"/get/cookgrp?GroupName="+group,'CookName')
elif menu == '4':
cook = showchoicesapi("Lista de recetas con grupo. Selecciona una para ver sus grupos","Listado de grupos de una receta",c_server+"/get/cookall",'CookName')
if cook is not None:
showchoicesapi("Lista de grupos de la receta "+cook,"Listado de grupos de una receta",c_server+"/get/grpcook?CookName="+cook)
elif menu is None:
menuprinc()
return
mreports()
def m_addcomputergroup():
whatc = howchoicesapi("Seleccione equipo a añadir a un grupo","Añadir Equipo a grupo",c_server+"/get/computers")
if whatc is None:
return
whatg = showchoicesapi("Seleccione grupo a ser añadido","Añadir Equipo a grupo",c_server+"/get/groups")
if whatg is None:
return
sendsettoapi("/add/grpcomputer?ComputerName="+whatc+"&GroupName="+whatg,"Equipo añadido al grupo")
def m_delcomputergroup():
group = showchoicesapi("Seleccione grupo del que quitar un equipo","Borrar equipo de un grupo",c_server+"/get/groups")
if group is None:
return
computer = showchoicesapi("Seleccione grupo a ser quitado","Borrar equipo de un grupo",c_server+"/get/computersgrp?GroupName="+group)
if computer is None:
return
if easygui.ynbox("Quitar el equipo "+computer+" del grupo '"+group+"'. ¿Seguro?","Borrar equipo de un grupo"):
sendsettoapi("/del/grpcomputer?ComputerName="+computer+"&GroupName="+group,"Equipo quitado del grupo")
menuprinc()

View File

@@ -1,3 +1,3 @@
addComputers = False # False/True accept auto add computers that start client program and connect to server
debugsql = True # True is show in log all SQL queries
debugsql = False # True is show in log all SQL queries