diff --git a/.gitignore b/.gitignore
index 72461b8..0cb6c82 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,11 +3,10 @@
*.log
*.out
client/configpcm.ini
+client/client.sh
BD/database*
-reports/
__pycache__/
**/__pycache__/
.vscode/
cooks/*.yaml
-control/
-_site
\ No newline at end of file
+control/
\ No newline at end of file
diff --git a/BD/emptydatabase.db b/BD/emptydatabase.db
index bc4dcde..df8146e 100644
Binary files a/BD/emptydatabase.db and b/BD/emptydatabase.db differ
diff --git a/README.MD b/README.MD
index 9a4d5fa..5b76d59 100644
--- a/README.MD
+++ b/README.MD
@@ -17,7 +17,7 @@ It's not error proof, then, I don't have any responsability if something crashes
- Somewhat more security in API 1
- Stabilize all
- 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)
-
+- Support Linux clients
# Requirements
diff --git a/api.py b/api.py
index fa306b1..1dcf324 100644
--- a/api.py
+++ b/api.py
@@ -1,5 +1,5 @@
#!/usr/bin/python3
-BUILD = 21
+BUILD = 24
API_VER = 1
##It can be run directly with "waitress-serve --port=3333 api:api"
import falcon
@@ -10,7 +10,7 @@ import sql # SQL work file
import json,yaml
from datetime import datetime
-import sysopt #File of options
+sqlAddComputers = sql.retOption('AddComputers')
def logit(text):
text = str(text)
@@ -60,7 +60,7 @@ class getComputerExists(object):
elif sql.select("SELECT COUNT(*) 'RESULT' FROM COMPUTERS WHERE Name='"+ComputerName+"'")[0]['RESULT'] != 0: #Not UUID match, but computer exists
response.media = {'TEXT': 'Error, computer and UUID doesn\'t match in database', 'RESULT': 'ERROR','EXITCODE':'2'}
return
- if sysopt.addComputers == True: #Computer doesn't exist, but you have enabled add all computers
+ if sqlAddComputers == True: #Computer doesn't exist, but you have enabled add all computers
sql.insert("INSERT INTO COMPUTERS (`Name`,`UUID`) VALUES('"+ComputerName+"','"+UUID+"')")
response.media = {'RESULT': '1'}
else: #Computer doesn't exist and you don't want to be added
@@ -571,11 +571,17 @@ class delComputer(object): #Delete computer
resp = sql.insert("DELETE FROM COMPUTERS WHERE ID_C='"+ComputerID+"'")
logit(resp)
-
+##
+# updComputer: Upd computer data
+# /upd/computer?
+# @param ComputerID -> Computer ID
+# @param UUID -> UUID of computer
+# No need password, validate from ComputerID+UUID for updates..
+##
class updComputer(object):
def on_get(self, request, response):
logit(request)
- ComputerID, UUID, Password= None, None,None
+ ComputerID, UUID = None, None
for key, value in request.params.items():
if key == "ComputerName":
try:
@@ -587,10 +593,6 @@ class updComputer(object):
ComputerID = value
if key == "UUID":
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:
@@ -613,6 +615,10 @@ class updComputer(object):
response.media = sql.insert("UPDATE COMPUTERS SET RAM='"+value+"' WHERE ID_C='"+ComputerID+"'")
if key == "CPUName":
response.media = sql.insert("UPDATE COMPUTERS SET CPUName='"+value+"' WHERE ID_C='"+ComputerID+"'")
+ if key == "RAMFree":
+ response.media = sql.insert("UPDATE COMPUTERS SET RAMFree='"+str(value)+"' WHERE ID_C='"+ComputerID+"'")
+ if key == "HDD":
+ response.media = sql.insert("UPDATE COMPUTERS SET HDD='"+str(value)+"' WHERE ID_C='"+ComputerID+"'")
##
# updCookName: Rename cook name
@@ -809,7 +815,6 @@ 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.
diff --git a/client/ADcomputerData.ps1 b/client/ADcomputerData.ps1
deleted file mode 100644
index 568fe61..0000000
--- a/client/ADcomputerData.ps1
+++ /dev/null
@@ -1,76 +0,0 @@
-$root = $PSCommandPath | Split-Path -Parent
-. $root\config.ps1
-
-$table = (Invoke-RestMethod -Method Get -Uri "$server/get/computers") # Get all computers
-$DNSPrefix = (get-DnsClientGlobalSetting).SuffixSearchList[0] # Get DNS Prefix, needed to search computers in some environments
-
-
-$array = @()
-
-function getPrograms($computername) {
-
-
- #Define the variable to hold the location of Currently Installed Programs
-
- $UninstallKey="SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
-
- #Create an instance of the Registry Object and open the HKLM base key
-
- $reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$computername)
-
- #Drill down into the Uninstall key using the OpenSubKey Method
-
- $regkey=$reg.OpenSubKey($UninstallKey)
-
- #Retrieve an array of string that contain all the subkey names
-
- $subkeys=$regkey.GetSubKeyNames()
-
- #Open each Subkey and use GetValue Method to return the required values for each
-
- $allprogs = @()
-
- foreach($key in $subkeys){
-
- $thisKey=$UninstallKey+"\\"+$key
-
- $thisSubKey=$reg.OpenSubKey($thisKey)
-
- $obj = New-Object PSObject
-
- $obj | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $computername
-
- $obj | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $($thisSubKey.GetValue("DisplayName"))
-
- $obj | Add-Member -MemberType NoteProperty -Name "DisplayVersion" -Value $($thisSubKey.GetValue("DisplayVersion"))
-
- $obj | Add-Member -MemberType NoteProperty -Name "InstallLocation" -Value $($thisSubKey.GetValue("InstallLocation"))
-
- $obj | Add-Member -MemberType NoteProperty -Name "Publisher" -Value $($thisSubKey.GetValue("Publisher"))
-
-
- $allprogs += $obj
-
- }
-
- return $allprogs
-}
-
-
-foreach ($comp in $table){
- $name = -join($comp.Name,".",$DNSPrefix);
- if (Test-Connection -ComputerName $name -Quiet){
- Write-Output $name
- $array += getPrograms($name)
- }else{
- Write-Output "$name Offline"
- }
-
-}
-
-#$array | Where-Object { $_.DisplayName } | select ComputerName, DisplayName, DisplayVersion, Publisher | ft -auto
-
-$array | Where-Object { $_.DisplayName } | select ComputerName, DisplayName, DisplayVersion | export-csv "$PSScriptRoot\..\Reports\software.csv" -NoTypeInformation -Delimiter ";" -Encoding ASCII
-Write-Host "Guardado en ..\Reports\software.csv"
-#$content = [System.IO.File]::ReadAllText("$PSScriptRoot\Reports\software.csv").Replace("A","")
-#[System.IO.File]::WriteAllText("$PSScriptRoot\Reports\software.csv", $content)
\ No newline at end of file
diff --git a/client/client.ps1 b/client/client.ps1
index 4431bbb..e09feea 100644
--- a/client/client.ps1
+++ b/client/client.ps1
@@ -1,13 +1,13 @@
-# Build 9
+# Build 11
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
+#Write-Host $startup
+$srcdir = $PSCommandPath | Split-Path -Parent
+$server = (Get-Content "$srcdir\configpcm.ini" | select -Skip 1 | ConvertFrom-StringData).server
+$resources = (Get-Content "$srcdir\configpcm.ini" | select -Skip 1 | ConvertFrom-StringData).resources
$64bit = [Environment]::Is64BitOperatingSystem
$computerName = [System.Net.Dns]::GetHostName()
-$UUID=(get-wmiobject Win32_ComputerSystemProduct).UUID
+$UUID=(Get-CimInstance Win32_ComputerSystemProduct).UUID
$exists = Invoke-RestMethod -Method Get -Uri "$server/get/computerexists?ComputerName=$computerName&UUID=$UUID"
if ($exists.Result -eq "ERROR"){
@@ -29,15 +29,35 @@ if ($SOVersion -match "^10.0."){ #If its Windows 10, add revision number for kno
}
# Update Computer Data
-$CPUInfo = Get-WmiObject Win32_Processor
-$RAMInstalled = Get-WmiObject CIM_PhysicalMemory | Measure-Object -Property capacity -Sum | ForEach-Object {[math]::round(($_.sum / 1MB),2)}
-$paramInvoke = -join("$server/upd/computer?ComputerName=$computerName&UUID=",$UUID,"&SOVersion=",$SOVersion,"&SOCaption=",$SOData.Caption,"&SOBit=",$SOData.OsArchitecture.Substring(0,2),"&LastConnection=",$Timestamp,"&RAM=",$RAMInstalled,"&CPUName=",$CPUInfo.Name)
-Invoke-RestMethod -Method Get -Uri $paramInvoke | out-null
-# More info
+$CPUInfo = (Get-CimInstance Win32_Processor) | Select Name,MaxClockSpeed,ThreadCount
+$CPUName = -join($CPUInfo.ThreadCount, " x ",$CPUInfo.Name.Trim()," (",$CPUInfo.MaxClockSpeed," MHz)")
+$RAMInstalled = Get-CimInstance CIM_PhysicalMemory | Measure-Object -Property capacity -Sum | ForEach-Object {[math]::round(($_.sum / 1MB),2)}
+$RAMFree = [Math]::Round((Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory/1024,0)
+$RAMUsed = $RamInstalled-$RAMFree
+# Disks
+$objDisks = Get-CimInstance -Class win32_LogicalDisk -Filter "DriveType = '3'"
+$diskResults = @()
+ ForEach( $disk in $objDisks )
+ {
+ $ThisVolume = "" | select Volume,Capacity,FreeSpace
+ $ThisVolume.Volume = $disk.DeviceID
+ $ThisVolume.Capacity = $([Math]::Round($disk.Size / 1GB,2))
+ $ThisVolume.FreeSpace = $([Math]::Round($disk.FreeSpace / 1GB,2))
+ $DiskResults += $ThisVolume
+ }
+$DisksData = $DiskResults |ConvertTo-Json
+$DisksData = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($DisksData)) #I can't enter to database all without encode
$lastUser = (Get-CimInstance -ClassName Win32_ComputerSystem -Property UserName -ComputerName .).UserName
-Invoke-RestMethod -Method Get -Uri "$server/upd/computer?ComputerName=$computerName&UUID=$UUID&LastUser=$lastUser" | out-null
+# Send it
+$paramInvoke = -join("$server/upd/computer?ComputerName=$computerName&UUID=",$UUID,"&SOVersion=",$SOVersion,"&SOCaption=",$SOData.Caption,"&SOBit=",$SOData.OsArchitecture.Substring(0,2),"&LastConnection=",$Timestamp,"&RAM=",$RAMInstalled,"&RAMFree=",$RAMFree,"&CPUName=",$CPUName,"&LastUser=",$lastUser,"&HDD=",$DisksData)
+Invoke-RestMethod -Method Get -Uri $paramInvoke | out-null
+
+# More info (Only if has to be)
+# $paramInvoke = -join("$server/upd/computerhis?ComputerName=$computerName&UUID=",$UUID,"&RAMFree=",$RAMFree,"&RAMUsed=",$RAMUsed,"&Timestamp=",$Timestamp,"&DisksUse=",$disksUse)
+# Invoke-RestMethod -Method Get -Uri $paramInvoke | out-null
+# Load Cooks of computer
$cooks = Invoke-RestMethod -Method Get -Uri "$server/get/cookpend?ComputerName=$computerName&UUID=$UUID"
foreach ($CookName in $cooks){
diff --git a/doc/howto_writecook.md b/doc/howto_writecook.md
index 2fdb0db..ab71333 100644
--- a/doc/howto_writecook.md
+++ b/doc/howto_writecook.md
@@ -21,37 +21,50 @@ And then, steps. First a "steps:" line, and then line by line the steps of the c
Steps are ever put like "Type of step" | "Command"
You can put comments in every line putting another "|" and comments at finish, like.. "CMD|WinSCP-5.13.4-Setup.exe /VERYSILENT /NORESTART|Note: Installing WinSCP"
-Cook finishes executing if they had and error (Except in a NOERROR block), or if finishes right.
+Cook finishes executing if they had and error (Except inside a NOERROR block), or if finishes right.
+
+You have examples in the example_cooks folder
Note: Cooks start in directory $env:temp (%TEMP%) from SYSTEM user.
-# Type of commands
-- CMD and PWCMD: cmd command or Powershell command. Cmd commands can not work properly if has quotes (Because its run as cmd /c ""), if they are a Powershell equivalent, please use it. Normally cmd command uses are for install/uninstall exe programs or some like that, because powershell doesn't wait to exit a exe command
-- REPOTOLOCAL: Copy a file from REPO folder configured to local in temp folder to use it. You can copy files or folders with same command.
-- INSTALLMSI: Installs an MSI file silently (Params /quiet /norestart are put, do not repeat). You can add parameters (Like INSTALLMSI|superapp.msi ADDLOCAL=extension SETASDEFAULT=1)
-- NOERROR and ENDNOERROR: This is for creating a block of instructions that not captures errors, then cook works ever if instruction fails
- Example:
- NOERROR|For deleting a file that maybe can not exist
- PWCMD|Remove-Item C:\Windows\loginstall.txt
- ENDNOERROR|Finish
-- SERV_DISABLE and SERV_ENABLE: Enables or disables a Windows Service
-- MSG|Display a message to user
-- COMMENT or REM: Makes cook comments (COMMENT|This is a comment)
-- KILL_PROCESS: Kill a process name if exists
-- UNINSTALL: Uninstalls a program by name if its installed. It searchs it by Powershell command 'Get-Package -Name "Program*"', take care of it. You can use to see name
-- REMOVE: Removes a file or folder path from local computer. It's recursive
-- SLEEP and PAUSE: Pauses execution seconds specified in param
-- DOWNLOAD: This downloads a file from network/internet to $env:temp/filename. Its *required* to put a filename, that goes this way: DOWNLOAD|http://www.example.org/file.zip;filename.zip. ";" is that separates URL and filename. It seems to be a limit in PowerShell Invoke-WebRequest that limits this downloads to some like 128MB
-- EXIT: Terminates a cook in this instruction. If a param is specified, exit will be with error code and the param as text of error. (Ej: EXIT|Error at seeking for file)
+# Commands avaiable (LINUX IS NOT SUPPORTED YET)
+
+| OS | COMMAND | Description |
+|----- |------------- |--------------------------------------------------------------------------------------------------------- |
+| W | CMD | Cmd command. Beware of quotes, because internally is run as cmd /c "" |
+| W/L | PWCMD | Powershell command, runs using Invoke-Command |
+| W/L | REPOTOLOCAL | Copy a file from REPO folder configured to local in temp folder. You can copy a file or a folder |
+| W | INSTALLMSI | Installs an MSI file silently (Params /quiet /norestart are put, do not repeat). You can add parameters (Like INSTALLMSI|superapp.msi ADDLOCAL=extension SETASDEFAULT=1) |
+| W/L | NOERROR | Creates a block of instructions that not captures errors and continues event if fails
Example:
NOERROR|Try to delete a file that maybe can not exist
PWCMD|Remove-Item C:\Windows\loginstall.txt
ENDNOERROR|Finish |
+| W/L | ENDNOERROR | Finishes NOERROR Block |
+| W/L | SERV_ENABLE | Enables a service |
+| W/L | SERV_DISABLE | Disables a service |
+| W/L | MSG | Shows a message to user |
+| W/L | REM / COMMENT | Annotation for developers in cooks |
+| W/L | KILL_PROCESS | Kills a process |
+| W/L | UNINSTALL | Uninstalls a software by name. (It finishes using * at Windows 'Get-Package -Name "Program*"', be care) |
+| W/L | REMOVE | Removes a file or folder path from local compuer. It's recursive |
+| W/L | SLEEP / PAUSE | Pauses execution seconds specified in param (SLEEP|3) |
+| W/L | DOWNLOAD * | Downloads a file from network to tempFolder/filename. It's required to put a filename like: DOWNLOAD|http://example.org/file.zip;filename.zip. ";" separates URL and filename |
+| W/L | EXIT | Terminates cook execution. It can take a param as error text (EXIT|Error at removing file) |
+| L | BASH | Bash command |
+
+
+- *DOWNLOAD: It seems to be a limit in PowerShell Invoke-WebRequest that limits this downloads to some like 128MB
+
+Inside of a Cook, you can use a simple IF query:
+| OS | COMMAND | Runs if when: |
+|----- |----------------- |--------------------------------------------------------------------------------- |
+| W/L | IFSOFTWAREINST | When program is installed. |
+| W/L | IFSOFTWAREVER | When program is installed and has X version (Name;Version) |
+| W/L | IFPATHEXISTS | When if file exists |
+| W/L | IFPWCMD | When powershell command returns True (Beware of command executed if using Linux) |
+| W/L | IF64BIT | When computer is running a 64 Bit operating system |
+| W/L | IF32BIT | When computer is running a 32 Bit operating system |
+| W/L | IFWINDOWS | When computer is running Windows |
+| W/L | IFLINUX | When computer is running Linux |
+| L | IFBASH | When bash command returns True |
+| W/L | ELSE | Else of IF... |
+| W/L | ENDIF | Finishes IF block |
-## If types
-Inside a cook, you can use IF/ELSE/ENDIF scheme.
-- IFSOFTWAREINST: Runs the if, if a program is installed.
-- IFSOFTWAREVER: Runs the if, if a program is installed and has X version. (Run with two param: "Name;Version")
-- IFPATHEXISTS: Runs if file exists
-- IFPWCMD: If powershell command returns $true (Executed succesfully), if is run
-- IF64BIT: If you are in a 64 Bit operating system
-- IF32BIT: If you are in a 32 Bit operating system
-- ELSE: Else..
-- ENDIF
diff --git a/sql.py b/sql.py
index 28b551f..c508fab 100644
--- a/sql.py
+++ b/sql.py
@@ -1,6 +1,5 @@
-# Build 2
+# Build 3
import sqlite3
-import sysopt #File of options
from shutil import copyfile
from os import path
from datetime import datetime
@@ -27,24 +26,32 @@ def dict_factory(cursor, row):
def select(query):
conn = sqlite3.connect('BD/database.db')
conn.row_factory = dict_factory
- if sysopt.debugsql==True:
+ if debugsql==True:
logit("SQL: "+query)
cur = conn.execute(query)
return cur.fetchall()
def insert(query):
conn = sqlite3.connect('BD/database.db')
- if sysopt.debugsql==True:
+ if debugsql==True:
logit("SQL: "+query)
try:
c = conn.cursor()
c.execute(query)
conn.commit()
conn.close()
- if sysopt.debugsql==True:
+ if debugsql==True:
logit("SQL Ok")
return {'RESULT': 'OK'}
except:
- if sysopt.debugsql==True:
+ if debugsql==True:
logit("SQL Error")
return {'RESULT': 'SQLite3 Error'}
+
+def retOption(option):
+ try:
+ return select("SELECT Value FROM OPTIONS WHERE Option='"+option+"'")[0]['Value']
+ except:
+ return None
+
+debugsql = retOption('DebugSQL')
\ No newline at end of file
diff --git a/sysopt.py b/sysopt.py
deleted file mode 100644
index ba71be9..0000000
--- a/sysopt.py
+++ /dev/null
@@ -1,3 +0,0 @@
-
-addComputers = False # False/True accept auto add computers that start client program and connect to server
-debugsql = False # True is show in log all SQL queries