Nis 17

Remote Raspbian OS’deki Mariadb’nin yedeğini Windows Lokaline yedekleyen C# desktop uygulaması

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text;
using System.Linq;
using System.Security.Policy;
using System.Threading.Tasks;
using System.Windows.Forms;

private void btnReports_Click(object sender1, EventArgs e1)
{

StreamReader sRead = File.OpenText(@”config.txt”);
string metin;
while ((metin = sRead.ReadLine()) != null)
{
// Okunan veriler textbox içerisine atılıyor.
string phrase = metin;
string[] words = phrase.Split(‘,’);

if (words[0] != null && words[1] != null && words[2] != null && words[3] != null)
{
server = words[0];
veritabaniAdi = words[1];
kullaniciAdi = words[2];
sifre = Descrpyt(words[3]);
}

}

// İşlem nesnesini oluşturun
string dateTimeString = DateTime.Now.ToString(“yyyy.MM.dd__HH.mm”);
Process process = new Process();

// Hedef dizini oluştur
string targetDirectory = @”C:\DB_YEDEK”;
if (!Directory.Exists(targetDirectory))
{
Directory.CreateDirectory(targetDirectory);
}

// Başlangıç bilgilerini ayarlayın
process.StartInfo.FileName = @”C:\Program Files\MySQL\MySQL Workbench 8.0 CE\mysqldump.exe”;
// –skip-triggers –no-create-info : parametrelerini kullanarak yalnızca verileri içeren ve tablo yapısını içermeyen bir SQL dosyası oluşturur.
process.StartInfo.Arguments = $” –result-file=\”C:\\DB_YEDEK\\{dateTimeString}.sql\” –user={kullaniciAdi} -p{sifre} –host={server} –port=3306 –default-character-set=utf8 –protocol=tcp –skip-triggers –no-create-info \”h4ck3r_charge\””;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;

// Olayları tanımlayın
process.OutputDataReceived += (sender, e) =>
{
if (!String.IsNullOrEmpty(e.Data))
{
Console.WriteLine(e.Data);
}
};
process.ErrorDataReceived += (sender, e) =>
{
if (!String.IsNullOrEmpty(e.Data))
{
Console.WriteLine(“Error: ” + e.Data);
}
};

// Komutu çalıştırın
process.Start();

// Çıktı ve hata akışlarını başlatın
Console.WriteLine(“VERİTABANI YEDEKLEME İŞLEMİ DEVAM EDİYOR…”);
//MessageBox.Show(“VERİTABANI YEDEKLEME İŞLEMİ DEVAM EDİYOR…”, “Bilgi”, MessageBoxButtons.OK, MessageBoxIcon.Information);
process.BeginOutputReadLine();

process.BeginErrorReadLine();

// İşlem tamamlanana kadar bekle
process.WaitForExit();

// Yedek dosyasını sıkıştırın
string backupFilePath = $”{targetDirectory}\\{dateTimeString}.sql”;
string compressedFilePath = $”{targetDirectory}\\{dateTimeString}.gz”;
using (FileStream fileToCompress = File.OpenRead(backupFilePath))
{
using (FileStream compressedFileStream = File.Create(compressedFilePath))
{
using (GZipStream compressionStream = new GZipStream(compressedFileStream, CompressionMode.Compress))
{
fileToCompress.CopyTo(compressionStream);
}
}
}

string inputFile = $”{targetDirectory}\\{dateTimeString}.sql”;
string compressedFile = $”{targetDirectory}\\{dateTimeString}.gz”;
string encryptedFile = $”{targetDirectory}\\{dateTimeString}.zip”;
string decryptedFile = $”{targetDirectory}\\{dateTimeString}.sql2″;
string password = “AnahtarSecret24April”;

// Dosyayı sıkıştır
CompressFile(inputFile, compressedFile);

// Dosyayı şifrele
EncryptFile(compressedFile, encryptedFile, password);

// Dosyayı çöz
//DecryptFile(encryptedFile, decryptedFile, password);

// Orijinal dosyayı sil
DeleteFile(inputFile);

Console.WriteLine(“Dosya sıkıştırma, şifreleme ve çözme işlemi tamamlandı.”);

Console.WriteLine(“Yedekleme tamamlandı.”);
MessageBox.Show($”VERİTABANI YEDEKLEME İŞLEMİ TAMAMLANDI…\n\n DOSYA KONUMU: {targetDirectory}\\{dateTimeString}.zip”, “Bilgi”, MessageBoxButtons.OK, MessageBoxIcon.Information);
}

static void CompressFile(string inputFile, string compressedFile)
{
using (FileStream inputStream = File.OpenRead(inputFile))
{
using (FileStream compressedStream = File.Create(compressedFile))
{
using (GZipStream gzipStream = new GZipStream(compressedStream, CompressionMode.Compress))
{
inputStream.CopyTo(gzipStream);
}
}
}
}

static void EncryptFile(string inputFile, string encryptedFile, string password)
{
byte[] salt = GenerateSalt(); // Tuz oluştur

using (Aes aesAlg = Aes.Create())
{
aesAlg.KeySize = 256; // 256-bit AES kullan
aesAlg.BlockSize = 128; // 128-bit blok boyutu
aesAlg.Padding = PaddingMode.PKCS7; // Dolgu modu
aesAlg.Mode = CipherMode.CBC; // CBC modu

// Anahtar ve IV oluştur
var keyDerivationFunction = new Rfc2898DeriveBytes(password, salt, 10000);
aesAlg.Key = keyDerivationFunction.GetBytes(aesAlg.KeySize / 8);
aesAlg.IV = keyDerivationFunction.GetBytes(aesAlg.BlockSize / 8);

using (FileStream inputFileStream = File.OpenRead(inputFile))
{
using (FileStream encryptedFileStream = File.Create(encryptedFile))
{
using (CryptoStream cryptoStream = new CryptoStream(encryptedFileStream, aesAlg.CreateEncryptor(), CryptoStreamMode.Write))
{
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputFileStream.Read(buffer, 0, buffer.Length)) > 0)
{
cryptoStream.Write(buffer, 0, bytesRead);
}
}
}
}
}
}

static void DecryptFile(string encryptedFile, string decryptedFile, string password)
{
byte[] salt = GenerateSalt(); //

using (Aes aesAlg = Aes.Create())
{
aesAlg.KeySize = 256; // 256-bit AES kullan
aesAlg.BlockSize = 128; // 128-bit blok boyutu
aesAlg.Padding = PaddingMode.PKCS7; // Dolgu modu
aesAlg.Mode = CipherMode.CBC; // CBC modu

// Anahtar ve IV oluştur
var keyDerivationFunction = new Rfc2898DeriveBytes(password, salt, 10000);
aesAlg.Key = keyDerivationFunction.GetBytes(aesAlg.KeySize / 8);
aesAlg.IV = keyDerivationFunction.GetBytes(aesAlg.BlockSize / 8);

try
{
using (FileStream encryptedFileStream = File.OpenRead(encryptedFile))
{
using (FileStream decryptedFileStream = File.Create(decryptedFile))
{
using (CryptoStream cryptoStream = new CryptoStream(encryptedFileStream, aesAlg.CreateDecryptor(), CryptoStreamMode.Read))
{
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = cryptoStream.Read(buffer, 0, buffer.Length)) > 0)
{
decryptedFileStream.Write(buffer, 0, bytesRead);
}
}
}
}
}
catch (CryptographicException ex)
{
Console.WriteLine(“Hata: ” + ex.Message);
}
}
}

static byte[] GenerateSalt()
{
byte[] salt = new byte[16];
using (var rng = new RNGCryptoServiceProvider())
{
rng.GetBytes(salt);
}
return salt;
}

static void DeleteFile(string filePath)
{
if (File.Exists(filePath))
{
File.Delete(filePath);
}
}

}

Şub 15

TFTP ile anahtarlara Firmware yükleme ve Config dosyalarını yedekleme

TFTP (Trivial File Transfer Protocol) kurulum faydalanılan link:

sudo apt install tftpd-hpa

sudo systemctl status tftpd-hpa

sudo nano /etc/default/tftpd-hpa

TFTP_USERNAME =”ftp”.

TFTP_DIRECTORY =”/tftp”

TFTP_ADDRESS =”:69″

TFTP_OPTIONS =” –secure –create”

sudo mkdir /tftp

sudo chown tftp:tftp /tftp

sudo systemctl restart tftpd-hpa

sudo systemctl status tftpd-hpa

 

 

Bazı test edilen anahtarlara ait güncel firmwareler:

ProCurve J9085A Switch 2610-24 R.11.123 Released on Mar 1, 2021
HP J9565A Switch 2615-8-PoE Released on Dec 6, 2022  A.15.16.0025 günceli A.15.16.0026
HP J9623A 2620-24 Switch Released on Nov 2, 2022 RA.16.04.0026 günceli  RA.16.04.0027
Aruba JL558A 2930F-48G-740W-PoE+-4SFP+ Switch WC.16.11.0011 Released on Apr 11, 2023 günceli WC.16.11.0015
HP J9773A 2530-24G-PoEP Switch YA.16.11.0011 Released on Apr 11, 2023 günceli  YA.16.11.0015
Aruba JL677A 6100 24G CL4 4SFP+ Swch ArubaOS-CX_6100-6000_10.11.1021 Released on May 15, 2023 günceli PL.10.12.1000
Dell EMC Networking N1524P/N1548P 6.7.1.20  günceli 6.7.1.21 18.03.2023
juniper / EX2200-48T-4G 12.3R8.7 ve 12.3R6.6  modelleri var güncel firmware araştırılıyor.

 

tftp_server_adresi_örnek: 10.1.1.1 olsun.  Secondary için güncel firmwareler yüklendikten sonra active imaj o seçilerek reboot edildikten sonra sorun olmazsa primary içinde yüklenebilir.

 

hp 2615 serisi için firmware güncelleme ve config yedeği alma:

copy tftp flash 10.1.1.1 A_15_16_0021.swi secondary allow-no-signature

copy running-config tftp://10.1.1.1/config-backups/hp2615-192.168.1.11/config.cfg

hp 2610 serisi için:

copy tftp flash 10.1.1.1 R_11_123.swi secondary

copy running-config tftp://10.1.1.1/config-backups/hp2610-192.168.1.51/config.cfg

hp 2620 serisi için:

copy tftp flash 10.1.1.1 RA_16_04_0025.swi secondary

copy running-config tftp://10.1.1.1/config-backups/hp2620-192.168.1.91/config.cfg

dell 1524 ve 1548 serisi için:

copy tftp://10.1.1.1/N1500v6.7.1.21.stk active

write file tftp://10.1.1.1/config-backups/dell1500-192.168.1.111/config.cfg

 

Gerekli güncellemeleri yaptıktan sonra https://metacpan.org/pod/App::Netdisco adresinden açık kaynaklı web destekli snmp ile cihazların her türlü bilgilerini toplayan güzel bir yazılım Netdisco‘yuda kurarsanız tadından yenmez.

 

Cisco anahtarlarda konfig yedeğini tftp sunucusuna yollama:

Periyodik yedeklemede Cisco IOS güzel/kullanışlı archive komutunu sunuyor.

archive

path tftp://10.1.1.1/config-backups/cisco-192.168.1.2/

maximum 14

time-period 60

write-memory

 

burada time-period 60 dk yani 1 saati ifade eder. Yedekleme sıklığını uzatmak istersek mesela 24 saatte bir için time-period 1440 set edilir.

 

Umarım faydalı olur 🙂

 

 

Şub 13

iRedMail (Open Source Mail Server Solution) IMAP’te silinen postaların kaydı

 

  • İredmail açık kaynaklı mail çözümlerinden, zimbra ve Zextras‘ta var piyasada incelendiğinde hatta bunların bileşenlerini kendimizde entegre ederek kurulum yapabiliriz.
  • Postfix, dovecot, amavis, clamav ve spamassasian İredmail’in saz arkadaşları.
  • Bunlara ilave proxmox mail gw, rsamd ve roundcubemail sistemin iyileştirmelerinde ve kullanım kolaylıklarında öncülük ediyor, Mail kotanız kısıtlı ise thunderbird son kullanıcı için kullanılabilir.

Burada amacımız son kullanıcının sildiği maillerin kaydının loglanması:

pico /etc/dovecot/dovecot.conf dosyasının  mail_plugins kısmına  notify mail_log eklenerek bu iş kolayca hallediliyor. Detaylar için mail_log_plugin kısmını okumakta fayda var.

İlgili dosyanın içeriği:

# Listen addresses.
#   – ‘*’ means all available IPv4 addresses.
#   – ‘[::]’ means all available IPv6 addresses.
# Listen on all available addresses by default
listen = * [::]

#base_dir = /var/run/dovecot
mail_plugins = quota mailbox_alias acl notify mail_log

Dovecot servisini restart etmeden öncesinde config kontrol etme:

Dovecot_config_check adresten detaylı bilgi alınabilir.

doveconf 1>/dev/null
echo $?

çıktı 0 ise sorun yok 0’dan farklı değer ise config’te sorun var.

grep “delete” /var/log/mail/dovecot.log | grep -E “parmaksiz|huseyin” ile loglar süzülebilir.

Feb 31 01:54:37 imap(hxx.parmaksiz@xxx.edu.tr): Info: delete: box=Trash, uid=37000, msgid=<5c6b6f9435cfbde6cd44d@xxx.edu.tr>, size=3210
Feb 31 02:00:17 imap(mxx.parmaksiz@xxx.edu.tr): Info: delete: box=INBOX, uid=131000, msgid=<34b506d546554354e78@web.xxx.edu.tr>, size=1234

Şub 08

DEB paketi oluşturma (mac adresi değiştirme) örneği (Pardus, Linux …)

Faydanılan Github proje linki:

https://github.com/dogukaneren/Mac-Changer

 

Amaç: İlgili interface’teki mac adresinin değiştirilmesi için .deb paketi oluşturma. Buradan yola çıkarak debian tabanlı yerli ve milli işletim sistemimiz Pardus içinde güzel deb paketleri oluşturulabilir.

 

mac_degistir.py  (python dosya içeriği)

import subprocess
import random
import sys

def generate_random_mac():
mac = [0x00, 0x16, 0x3e, random.randint(0x00, 0x7f), random.randint(0x00, 0xff), random.randint(0x00, 0xff)]
return ‘:’.join(f”{x:02x}” for x in mac)

def change_mac(interface, new_mac):
try:
subprocess.call([‘sudo’, ‘ifconfig’, interface, ‘down’])
subprocess.call([‘sudo’, ‘ifconfig’, interface, ‘hw’, ‘ether’, new_mac])
subprocess.call([‘sudo’, ‘ifconfig’, interface, ‘up’])
print(f”MAC address of {interface} changed to {new_mac}”)
except Exception as e:
print(f”An error occurred: {str(e)}”)

if __name__ == “__main__”:
if len(sys.argv) != 2:
print(“Usage: python3 mac-changer.py <interface>”)
sys.exit(1)

interface = sys.argv[1]
random_mac = generate_random_mac()
change_mac(interface, random_mac)

 

mac_degistir.sh  (shell script dosya içeriği)

#!/bin/bash

old_mac_file=”.old-mac”

if [ “$EUID” -ne 0 ]; then
echo “Please run this script as root (sudo).”
exit 1
fi

generate_random_mac() {
printf “02:%02X:%02X:%02X:%02X:%02X\n” $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256))
}

while getopts “i:m:” opt; do
case “$opt” in
i) interface=”$OPTARG”;;
m) new_mac=”$OPTARG”;;
\?) echo “Usage: $0 -i <interface_name> [-m <new_mac>]”
exit 1;;
esac
done

if [ -z “$interface” ]; then
echo “Usage: $0 -i <interface_name> [-m <new_mac>]”
exit 1
fi

if ! ip link show dev “$interface” &> /dev/null; then
echo “Error: Interface ‘$interface’ does not exist.”
exit 1
fi

if [ -z “$new_mac” ]; then
new_mac=$(generate_random_mac)
fi

ip link set dev “$interface” down

old_mac=$(ip link show dev “$interface” | awk ‘/ether/ {print $2}’)
echo “$old_mac” > “$old_mac_file”

ip link set dev “$interface” address “$new_mac” up

if [ “$?” -eq 0 ]; then
echo “Changed MAC address of ‘$interface’ to ‘$new_mac’.”
else
echo “Error: Failed to change MAC address of ‘$interface’.”
fi

exit 0

 

Deb paketi için dosyanın oluşturulması:

mkdir MC
mkdir MC/DEBIAN
touch MC/DEBIAN/control

Script için dosyanın oluşturulması:
mkdir -p MC/usr/bin
chmod +x mac_degistir.sh
mv mac_degistir.sh MC/usr/bin/mac_degistir


Deb paketi için kontrol dosyasının oluşturulması ve içeriği:
pico MC/DEBIAN/control
Package: mac-degistir
Version: 1.0
Architecture: all
Maintainer: h4ck3r <your-mail>
Description: MAC addresses changing on Linux
Depends: iproute2

Paketin oluşturulması:
dpkg-deb --build mac-degistir

Paketin kurulması:
dpkg -i mac-degistir.deb


İlgili interface'te mac aderinin değiştirilmesi (ip a veya ifconfig ile interfaceler listelenir):
mac-degistir -i enp0s31f6 (bendeki kablolu interface adı = enp0s31f6 olduğu için)
mac-changer -i <interface-name> -m "AA:BB:CC:11:22:33"
 
Umarım faydalı olur :)


 






 

Şub 08

Galera ile Database (MariaDB) Clustering (Veritabanı Kümeleme)

Kullanılan bileşenler:

  • 3 adet Rpi (2 adet Rpi4 1 adet Rpi3)
  • Rpi OS Lite
  • Mariadb
  • Galera

Amaç:

Bağımsız n+1 mariadb database’ine sahip veritabanlarının senkronizasyonunu sağlamak. Max sayı için 10’u geçmese iyi olur densede henüz test etme şansım olmadı, test edince güncel veriler ile performans ve farklı modlardaki çalışma mantığını ilerleyen zamanlarda ekleyeceğim inşallah.

 

Hostlar sırasıyla aşağıdaki ipleri static alsın:

192.168.1.202

192.168.1.203

192.168.1.204

201 (1. host) hostunda yapılacaklar:

cat /proc/cpuinfo | grep Serial

Serial : 100000000903a2f3

sudo pico /etc/hosts dosyasının içine:

192.168.1.202 100000000903a2f3

192.168.1.203 100000001aeafbd0

192.168.1.204 00000000ac70ad1e

sudo apt install mariadb-server

sudo mysql_secure_installation ile root şifresi belirlenir.

sudo apt install phpmyadmin web tarafında db kontrol arayüzü kurulur.

sudo apt install software-properties-common

sudo nano /etc/mysql/conf.d/galera.cnf dosyasının içine:

[mysqld]

binlog_format=ROW

default-storage-engine=innodb

innodb_autoinc_lock_mode=2

bind-address=0.0.0.0

# Galera Provider Configuration

wsrep_on=ON

wsrep_provider=/usr/lib/galera/libgalera_smm.so

# Galera Cluster Configuration

wsrep_cluster_name=”h4ck3r_cluster”

wsrep_cluster_address=”gcomm://192.168.1.202,192.168.1.203,192.168.1.204″

# Galera Synchronization Configuration

wsrep_sst_method=rsync

# Galera Node Configuration

wsrep_node_address=”192.168.1.202″

wsrep_node_name=”100000000903a2f3″

202 (2. host) hostunda yapılacaklar:

cat /proc/cpuinfo | grep Serial

Serial : 100000001aeafbd0

sudo pico /etc/hosts dosyasının içine:

192.168.1.202 100000000903a2f3

192.168.1.203 100000001aeafbd0

192.168.1.204 00000000ac70ad1e

sudo apt install mariadb-server

sudo mysql_secure_installation ile root şifresi belirlenir.

sudo apt install phpmyadmin web tarafında db kontrol arayüzü kurulur.

sudo apt install software-properties-common

sudo nano /etc/mysql/conf.d/galera.cnf dosyasının içine:

[mysqld]

binlog_format=ROW

default-storage-engine=innodb

innodb_autoinc_lock_mode=2

bind-address=0.0.0.0

# Galera Provider Configuration

wsrep_on=ON

wsrep_provider=/usr/lib/galera/libgalera_smm.so

# Galera Cluster Configuration

wsrep_cluster_name=”h4ck3r_cluster”

wsrep_cluster_address=”gcomm://192.168.1.202,192.168.1.203,192.168.1.204″

# Galera Synchronization Configuration

wsrep_sst_method=rsync

# Galera Node Configuration

wsrep_node_address=”192.168.1.203″

wsrep_node_name=”100000001aeafbd0

203 (3. host) hostunda yapılacaklar:

cat /proc/cpuinfo | grep Serial

Serial : 00000000ac70ad1e

sudo pico /etc/hosts dosyasının içine:

192.168.1.202 100000000903a2f3

192.168.1.203 100000001aeafbd0

192.168.1.204 00000000ac70ad1e

sudo apt install mariadb-server

sudo mysql_secure_installation ile root şifresi belirlenir.

sudo apt install phpmyadmin web tarafında db kontrol arayüzü kurulur.

sudo apt install software-properties-common

sudo nano /etc/mysql/conf.d/galera.cnf dosyasının içine:

[mysqld]

binlog_format=ROW

default-storage-engine=innodb

innodb_autoinc_lock_mode=2

bind-address=0.0.0.0

# Galera Provider Configuration

wsrep_on=ON

wsrep_provider=/usr/lib/galera/libgalera_smm.so

# Galera Cluster Configuration

wsrep_cluster_name=”h4ck3r_cluster”

wsrep_cluster_address=”gcomm://192.168.1.202,192.168.1.203,192.168.1.204″

# Galera Synchronization Configuration

wsrep_sst_method=rsync

# Galera Node Configuration

wsrep_node_address=”192.168.1.204″

wsrep_node_name=”00000000ac70ad1e

Bu işlemle tamamlanınca 3 hosttada:

sudo systemctl stop mysql

sudo systemctl status mysql

ile mysql servislerinin stopped olması kontrol edilir.

İlk hostta:

sudo galera_new_cluster komutu ile galerayı aktif edeceğiz ve aşağıdaki komutla clusterdaki value değeri 1 olarak görülecek.

v2x@v2xcharge:~ $ mysql -u root -p -e “SHOW STATUS LIKE ‘wsrep_cluster_size'”

Enter password:

+——————–+——-+

| Variable_name | Value |

+——————–+——-+

| wsrep_cluster_size | 1 |

İkinci hostta:

sudo systemctl start mysql

mysql -u root -p -e “SHOW STATUS LIKE ‘wsrep_cluster_size'”

value değeri 2 olması gerek.

Üçüncü hostta:

sudo systemctl start mysql

mysql -u root -p -e “SHOW STATUS LIKE ‘wsrep_cluster_size'”

value değeri 3 olması gerek.

Sonrasında phpmyadmin üzerinden herhangi bir host üzerinden vt oluşturulup senkronizasyon durumu kontrol edilebilir.

 

Umarım bir faydamız dokunur 🙂

Şub 08

PHP-Server-Side Processing

Kullanılan bileşenler:

  • mariadb  Ver 15.1 Distrib 10.6.16-MariaDB, for debian-linux-gnu (x86_64) using  EditLine wrapper
  • Ubuntu 22.04.3 LTS
  • PHP 8.1.2-1ubuntu2.14 (cli) (built: Aug 18 2023 11:41:11) (NTS)

 

Örnek bir database (ister console ister phpmyadmin üzerinden create edilen):

CREATE TABLE PersonelBilgi (
id int(11) NOT NULL,
name varchar(32) COLLATE utf8_unicode_ci NOT NULL,
surname varchar(32) COLLATE utf8_unicode_ci NOT NULL,
birthday date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

 

Datatable’ler (https://datatables.net/) büyük boyutta veri ve satırlarda yavaşlamalar olur bunun nedeni son kullanıcı tarafındaki tarayıcılar ve pc kaynaklarıdır. Bu işlemi son kullanıcı yerine sunucu tarafında yapma işlemi server-side-processing olarak karşımıza çıkar.

 

 

Örnek bir html:

<!-- h4ck3r.html-->
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="initial-scale=1.0, maximum-scale=2.0">
	<title>PHP-Server-Side Processing for Datatables</title>
	<link rel="stylesheet" type="text/css" href="media/css/jquery.dataTables.css">
	<script type="text/javascript" language="javascript" src="media/js/jquery.js"></script>
	<script type="text/javascript" language="javascript" src="media/js/jquery.dataTables.js"></script>
	
	<script type="text/javascript" language="javascript" class="init">
		$(document).ready(function() {
			$('#example').dataTable( {
				"processing": true,
				"serverSide": true,
				"ajax": "scripts/SP.php"
			} );
		} );
	</script>
</head>

<body class="dt-example">
	<div class="container">
		<section>
			<table id="example" class="display" cellspacing="0" width="100%">
				<thead>
					<tr>
						<th>ID</th>
						<th>Name</th>
						<th>Surname</th>
						<th>Birthday</th>
					</tr>
				</thead>

				<tfoot>
					<tr>
						<th>ID</th>
						<th>Name</th>
						<th>Surname</th>
						<th>Birthday</th>
					</tr>
				</tfoot>
			</table>
		</section>
	</div>	
</body>
</html>


Sunucu tarafında işlemi yapacak PHP: SP.php
<?php

$table = "PersonelBilgi";
$primaryKey = 'id';
$columns = array(
    array('db' => 'id',     'dt' => 0), /* dt sırasını indexi*/
    array('db' => 'name',     'dt' => 1), /* Field'ler Vt de yazıldığı gibi*/
    array('db' => 'surname',  'dt' => 2), /* Hepsini yazmak zorunda değilsiniz */ 
    array('db' => 'birthday',   'dt' => 3) /* h4ck3r.html de table karşılığına göre ayarlanmalıdır*/ 
);

$host      ="localhost";
$username  ="h4ck3r";
$pass      ="Esr5XyAlp24*";
$vt        ="PersonelDB24";

$sql_details = array(
    'user' => $username,
    'pass' => $pass,
    'db'   => $vt,
    'host' => $host
);

require( 'datatablessp.class.php' );
 
echo json_encode(
    SSP::simple( $_GET, $sql_details, $table, $primaryKey, $columns )
);




datatablessp.class.php:

<?php

/*
 * Helper functions for building a DataTables server-side processing SQL query
 *
 * The static functions in this class are just helper functions to help build
 * the SQL used in the DataTables demo server-side processing scripts. These
 * functions obviously do not represent all that can be done with server-side
 * processing, they are intentionally simple to show how it works. More complex
 * server-side processing operations will likely require a custom script.
 *
 * See http://datatables.net/usage/server-side for full details on the server-
 * side processing requirements of DataTables.
 *
 * @license MIT - http://datatables.net/license_mit
 */


// REMOVE THIS BLOCK - used for DataTables test environment only!
// $file = $_SERVER['DOCUMENT_ROOT'].'/datatables/mysql.php';
// if ( is_file( $file ) ) {
// include( $file );
// }


class SSP {
 /**
 * Create the data output array for the DataTables rows
 *
 * @param array $columns Column information array
 * @param array $data Data from the SQL get
 * @return array Formatted data in a row based format
 */
 static function data_output ( $columns, $data )
 {
 $out = array();

 for ( $i=0, $ien=count($data) ; $i<$ien ; $i++ ) {
 $row = array();

 for ( $j=0, $jen=count($columns) ; $j<$jen ; $j++ ) {
 $column = $columns[$j];

 // Is there a formatter?
 if ( isset( $column['formatter'] ) ) {
 $row[ $column['dt'] ] = $column['formatter']( $data[$i][ $column['db'] ], $data[$i] );
 }
 else {
 $row[ $column['dt'] ] = $data[$i][ $columns[$j]['db'] ];
 }
 }

 $out[] = $row;
 }

 return $out;
 }


 /**
 * Paging
 *
 * Construct the LIMIT clause for server-side processing SQL query
 *
 * @param array $request Data sent to server by DataTables
 * @param array $columns Column information array
 * @return string SQL limit clause
 */
 static function limit ( $request, $columns )
 {
 $limit = '';

 if ( isset($request['start']) && $request['length'] != -1 ) {
 $limit = "LIMIT ".intval($request['start']).", ".intval($request['length']);
 }

 return $limit;
 }


 /**
 * Ordering
 *
 * Construct the ORDER BY clause for server-side processing SQL query
 *
 * @param array $request Data sent to server by DataTables
 * @param array $columns Column information array
 * @return string SQL order by clause
 */
 static function order ( $request, $columns )
 {
 $order = '';

 if ( isset($request['order']) && count($request['order']) ) {
 $orderBy = array();
 $dtColumns = SSP::pluck( $columns, 'dt' );

 for ( $i=0, $ien=count($request['order']) ; $i<$ien ; $i++ ) {
 // Convert the column index into the column data property
 $columnIdx = intval($request['order'][$i]['column']);
 $requestColumn = $request['columns'][$columnIdx];

 $columnIdx = array_search( $requestColumn['data'], $dtColumns );
 $column = $columns[ $columnIdx ];

 if ( $requestColumn['orderable'] == 'true' ) {
 $dir = $request['order'][$i]['dir'] === 'asc' ?
 'ASC' :
 'DESC';

 $orderBy[] = '`'.$column['db'].'` '.$dir;
 }
 }

 $order = 'ORDER BY '.implode(', ', $orderBy);
 }

 return $order;
 }


 /**
 * Searching / Filtering
 *
 * Construct the WHERE clause for server-side processing SQL query.
 *
 * NOTE this does not match the built-in DataTables filtering which does it
 * word by word on any field. It's possible to do here performance on large
 * databases would be very poor
 *
 * @param array $request Data sent to server by DataTables
 * @param array $columns Column information array
 * @param array $bindings Array of values for PDO bindings, used in the
 * sql_exec() function
 * @return string SQL where clause
 */
 static function filter ( $request, $columns, &$bindings )
 {
 $globalSearch = array();
 $columnSearch = array();
 $dtColumns = SSP::pluck( $columns, 'dt' );

 if ( isset($request['search']) && $request['search']['value'] != '' ) {
 $str = $request['search']['value'];

 for ( $i=0, $ien=count($request['columns']) ; $i<$ien ; $i++ ) {
 $requestColumn = $request['columns'][$i];
 $columnIdx = array_search( $requestColumn['data'], $dtColumns );
 $column = $columns[ $columnIdx ];

 if ( $requestColumn['searchable'] == 'true' ) {
 $binding = SSP::bind( $bindings, '%'.$str.'%', PDO::PARAM_STR );
 $globalSearch[] = "`".$column['db']."` LIKE ".$binding;
 }
 }
 }

 // Individual column filtering
 for ( $i=0, $ien=count($request['columns']) ; $i<$ien ; $i++ ) {
 $requestColumn = $request['columns'][$i];
 $columnIdx = array_search( $requestColumn['data'], $dtColumns );
 $column = $columns[ $columnIdx ];

 $str = $requestColumn['search']['value'];

 if ( $requestColumn['searchable'] == 'true' &&
 $str != '' ) {
 $binding = SSP::bind( $bindings, '%'.$str.'%', PDO::PARAM_STR );
 $columnSearch[] = "`".$column['db']."` LIKE ".$binding;
 }
 }

 // Combine the filters into a single string
 $where = '';

 if ( count( $globalSearch ) ) {
 $where = '('.implode(' OR ', $globalSearch).')';
 }

 if ( count( $columnSearch ) ) {
 $where = $where === '' ?
 implode(' AND ', $columnSearch) :
 $where .' AND '. implode(' AND ', $columnSearch);
 }

 if ( $where !== '' ) {
 $where = 'WHERE '.$where;
 }

 return $where;
 }


 /**
 * Perform the SQL queries needed for an server-side processing requested,
 * utilising the helper functions of this class, limit(), order() and
 * filter() among others. The returned array is ready to be encoded as JSON
 * in response to an SSP request, or can be modified if needed before
 * sending back to the client.
 *
 * @param array $request Data sent to server by DataTables
 * @param array $sql_details SQL connection details - see sql_connect()
 * @param string $table SQL table to query
 * @param string $primaryKey Primary key of the table
 * @param array $columns Column information array
 * @return array Server-side processing response array
 */
 static function simple ( $request, $sql_details, $table, $primaryKey, $columns )
 {
 $bindings = array();
 $db = SSP::sql_connect( $sql_details );

 // Build the SQL query string from the request
 $limit = SSP::limit( $request, $columns );
 $order = SSP::order( $request, $columns );
 $where = SSP::filter( $request, $columns, $bindings );

 // Main query to actually get the data
 $data = SSP::sql_exec( $db, $bindings,
 "SELECT SQL_CALC_FOUND_ROWS `".implode("`, `", SSP::pluck($columns, 'db'))."`
 FROM `$table`
 $where
 $order
 $limit"
 );

 // Data set length after filtering
 $resFilterLength = SSP::sql_exec( $db,
 "SELECT FOUND_ROWS()"
 );
 $recordsFiltered = $resFilterLength[0][0];

 // Total data set length
 $resTotalLength = SSP::sql_exec( $db,
 "SELECT COUNT(`{$primaryKey}`)
 FROM `$table`"
 );
 $recordsTotal = $resTotalLength[0][0];


 /*
 * Output
 */
 return array(
 "draw" => intval( $request['draw'] ),
 "recordsTotal" => intval( $recordsTotal ),
 "recordsFiltered" => intval( $recordsFiltered ),
 "data" => SSP::data_output( $columns, $data )
 );
 }


 /**
 * Connect to the database
 *
 * @param array $sql_details SQL server connection details array, with the
 * properties:
 * * host - host name
 * * db - database name
 * * user - user name
 * * pass - user password
 * @return resource Database connection handle
 */
 static function sql_connect ( $sql_details )
 {
 try {
 $db = @new PDO(
 "mysql:host={$sql_details['host']};dbname={$sql_details['db']};charset=UTF8",
 $sql_details['user'],
 $sql_details['pass'],
 array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION )
 );
 }
 catch (PDOException $e) {
 SSP::fatal(
 "An error occurred while connecting to the database. ".
 "The error reported by the server was: ".$e->getMessage()
 );
 }

 return $db;
 }


 /**
 * Execute an SQL query on the database
 *
 * @param resource $db Database handler
 * @param array $bindings Array of PDO binding values from bind() to be
 * used for safely escaping strings. Note that this can be given as the
 * SQL query string if no bindings are required.
 * @param string $sql SQL query to execute.
 * @return array Result from the query (all rows)
 */
 static function sql_exec ( $db, $bindings, $sql=null )
 {
 // Argument shifting
 if ( $sql === null ) {
 $sql = $bindings;
 }

 $stmt = $db->prepare( $sql );
 //echo $sql;

 // Bind parameters
 if ( is_array( $bindings ) ) {
 for ( $i=0, $ien=count($bindings) ; $i<$ien ; $i++ ) {
 $binding = $bindings[$i];
 $stmt->bindValue( $binding['key'], $binding['val'], $binding['type'] );
 }
 }

 // Execute
 try {
 $stmt->execute();
 }
 catch (PDOException $e) {
 SSP::fatal( "An SQL error occurred: ".$e->getMessage() );
 }

 // Return all
 return $stmt->fetchAll();
 }


 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Internal methods
 */

 /**
 * Throw a fatal error.
 *
 * This writes out an error message in a JSON string which DataTables will
 * see and show to the user in the browser.
 *
 * @param string $msg Message to send to the client
 */
 static function fatal ( $msg )
 {
 echo json_encode( array( 
 "error" => $msg
 ) );

 exit(0);
 }

 /**
 * Create a PDO binding key which can be used for escaping variables safely
 * when executing a query with sql_exec()
 *
 * @param array &$a Array of bindings
 * @param * $val Value to bind
 * @param int $type PDO field type
 * @return string Bound key to be used in the SQL where this parameter
 * would be used.
 */
 static function bind ( &$a, $val, $type )
 {
 $key = ':binding_'.count( $a );

 $a[] = array(
 'key' => $key,
 'val' => $val,
 'type' => $type
 );

 return $key;
 }


 /**
 * Pull a particular property from each assoc. array in a numeric array, 
 * returning and array of the property values from each item.
 *
 * @param array $a Array to get data from
 * @param string $prop Property to read
 * @return array Array of property values
 */
 static function pluck ( $a, $prop )
 {
 $out = array();

 for ( $i=0, $len=count($a) ; $i<$len ; $i++ ) {
 $out[] = $a[$i][$prop];
 }

 return $out;
 }
}


Umarım herkese faydalı olur :)

Şub 07

Auto run any script (Python’da tasarlanan bir GUI) on startup for Raspberry Pi 4

Kullanılan bileşenler:

  • python3.11
  • pyinstaller
  • crontab

 

 

GUI.py içeriği:

#!/usr/bin/env python
# coding: utf-8

# In[1]:
import tkinter as tk
from tkinter import Label, PhotoImage
#from PIL import Image, ImageTk

# Ana pencereyi oluşturun
root = tk.Tk()
root.title(“İlk GUI Uygulamam”)
root.geometry(“600×350”)

# Tarih ve saat bilgisini iki değişkene ayırın
tarih = “12.12.2023”
saat = “15:30″

# Sütunları yapılandırın
root.columnconfigure(0, weight=1) # İlk sütun genişlemeye uygun
root.columnconfigure(1, weight=1) # İkinci sütun genişlemeye uygun
root.columnconfigure(2, weight=1) # Üçüncü sütun genişlemeye uygun

# Sol üst köşede tarih bilgisini gösteren bir etiket oluşturun
tarih_etiket = Label(root, text=tarih)
tarih_etiket.grid(row=0, column=0, padx=0, pady=0, sticky=”nw”)

# Üst ortada saat bilgisini gösteren bir etiket oluşturun
saat_etiket = Label(root, text=saat)
saat_etiket.grid(row=1, column=0, padx=0, pady=0, sticky=”nw”)

# Üst ortada kullanıcı adınızı gösteren bir etiket oluşturun
kullanici_adi_etiket = Label(root, text=”Kullanıcı Adı”)
kullanici_adi_etiket.grid(row=0, column=1, padx=0, pady=0, sticky=”nw”)

# Üst ortada kullanıcı adınızı gösteren bir etiket oluşturun
kullanici_adi_etiket = Label(root, text=”h4ck3r”)
kullanici_adi_etiket.grid(row=1, column=1, padx=0, pady=0, sticky=”nw”)

# Üst ortada kullanıcı adınızı gösteren bir etiket oluşturun
kullanici_adi_etiket = Label(root, text=”Anlık KWH”)
kullanici_adi_etiket.grid(row=2, column=1, padx=0, pady=30, sticky=”nw”)

# Üst ortada kullanıcı adınızı gösteren bir etiket oluşturun
kullanici_adi_etiket = Label(root, text=”1P veya 3P faz sayısı ve Amper”)
kullanici_adi_etiket.grid(row=2, column=1, padx=0, pady=50, sticky=”nw”)

# Üst ortada kullanıcı adınızı gösteren bir etiket oluşturun
kullanici_adi_etiket = Label(root, text=”Voltaj”)
kullanici_adi_etiket.grid(row=2, column=1, padx=0, pady=70, sticky=”nw”)

# Üst ortada kullanıcı adınızı gösteren bir etiket oluşturun
kullanici_adi_etiket = Label(root, text=”Sıcaklık”)
kullanici_adi_etiket.grid(row=2, column=1, padx=0, pady=90, sticky=”nw”)

# Üst ortada kullanıcı adınızı gösteren bir etiket oluşturun
kullanici_adi_etiket = Label(root, text=”Harcanan Enerji”)
kullanici_adi_etiket.grid(row=2, column=1, padx=0, pady=110, sticky=”nw”)

# Sayaç etiketini oluşturun
sayaç_etiket = Label(root, text=”Sayaç:”)
sayaç_etiket.grid(row=2, column=1, padx=0, pady=145, sticky=”nw”)

# Canvas (Tuval) ve Pil görselini oluşturun
canvas = tk.Canvas(root, width=200, height=300)
canvas.grid(row=2, column=0, padx=10, pady=0, sticky=”ne”)
canvas.create_rectangle(50, 50, 150, 250, fill=”white”, outline=”black”)

# Pil dilimlerini ve renklerini oluşturun
slices = []
colors = [
“#FF0000”, # Kırmızı
“#FF3300”, # Koyu Portakal
“#FF6600”, # Portakal
“#FF9900”, # Açık Portakal
“#FFCC00”, # Koyu Sarı
“#FFFF00”, # Sarı
“#CCFF00”, # Açık Yeşil
“#99FF00”, # Yeşil
“#66FF00”, # Koyu Yeşil
“#33FF00”, # Daha Koyu Yeşil
“#00FF00″ # Tam Yeşil
]

for i in range(11):
y1 = 250 – i * 20
y2 = y1 – 20
slice = canvas.create_rectangle(50, y2, 150, y1, fill=”white”, outline=”black”)
slices.append(slice)

# Sayaç etiketini oluşturun
saniye = 60 # Başlangıç değeri 60 saniye (1 dakika)
sayaç_etiket = Label(root, text=f”Sayaç: {saniye:02d}”, font=(“Arial”, 28))
sayaç_etiket.grid(row=2, column=1, padx=0, pady=130, sticky=”n”)

# Pilin doluluğunu ve sayacı güncelleyen fonksiyon
def güncelle():
global saniye
saniye -= 1

# Pil dilimlerini güncelle
dilim_sayısı = int((60 – saniye) / 6) # Her 6 saniyede bir dilim artacak
for i in range(11):
if i < dilim_sayısı:
canvas.itemconfig(slices[i], fill=colors[i])
else:
canvas.itemconfig(slices[i], fill=”white”)

# Sayaç etiketi güncelle
if saniye > 0:
sayaç_etiket.config(text=f”{saniye:02d}”)
else:
sayaç_etiket.config(text=”Süre doldu!”)

if saniye > 0:
root.after(1000, güncelle)

# Güncellemeyi başlat
güncelle()

# Pencereyi görüntülemek için bir döngü başlatın
root.mainloop()

 

Python dosyasını executable yapma:

pyinstaller –onefile GUI.py  komutu ile python dosyası executable formatta tek dosya haline getiriliyor. onefile parametresi öncesinde tekrarlı 2 adet – olacak. Bu işlem sonrası dist dizini oluşuyor ve executable dosya oraya oluyor.

 

calistir.sh dosyasını crontab veya autostart işlemlerinde executable dosyayı tetiklemek için kullanma:

sudo pico calistir.sh  dosyasının içeriği:

#!/bin/sh

cd /home/h4ck3r/Desktop/dist/
./GUI >> /home/h4ck3r/Desktop/cronlog.txt 2>&1

 

Raspbian reboot edilince crontab ile ilgili script’in tetiklenmesi (I. yol):

crontab -e

@reboot sleep 1 && export DISPLAY=:0 XAUTHORITY=/home/h4ck3r/.Xauthority && /home/h4ck3r/Desktop/calistir.sh

 

Raspbian reboot edilince autostart ile ilgili scrip’in tetiklenmesi (II. yol)

sudo mkdir ~/.config/autostart

sudo pico ~/.config/autostart/.desktop

[Desktop Entry]
Name=MyApp
Exec=/home/h4ck3r/Desktop/calistir.sh
Type=Application
#X-GNOME-Autostart-Delay=30 # Gecikmeyi saniye cinsinden

 

Böylece herhangi bir script veya GUI destekleyen bir form yazılımlarını RPI’de ilk açılışta çalıştırmış oluyoruz. Umarım faydalı bir içerik olur 🙂

 

Ağu 03

Ubuntu 22.04 LTS (Jammy Jellyfish) ve Proxmox VE 7.2 üzerine temel CEPH-QUINCY (V17.2.3) kurulumları

Bu dökümanın oluşturulmasında, birlikte çalıştığımız mesai arkadaşlarım Öğr. Gör. Murat ÖZALP, Öğr. Gör Semih KARACA’nın büyük katkıları vardır.

Manuel kurulum yapıyoruz amele usulü 🙂

https://docs.ceph.com/en/latest/install/manual-deployment/

Bir tane Proxmox makine, 3 tane Proxmox Ceph makine, 3 tane Linux Ceph makine

Bir tane Proxmox makine: 10.x.x.150 ip adresli ve test amaçlı vm, container yapıları bu makinede koşacak.

3 tane Proxmox makine: frontend kısmı ipleri sırayla 10.x.x.151,

10.x.x.152, 10.x.x.153

backend (ceph) kısmı ipleri sırayla 172.x.x.151,

172.x.x.152, 172.x.x.153

3 tane Linux makine: frontend kısmı ipleri sırayla 10.x.x.154,

10.x.x.155, 10.x.x.156

backend (ceph) kısmı ipleri sırayla 172.x.x.154,

172.x.x.155, 172.x.x.156

 

Tüm makinelerde 250GB ssd ile 500GB nvme diskler var. Tüm makinelerde 1Gbps 2 tane ethernet var.

Install Linux Ceph Storage Cluster

apt-get install ceph ceph-mds

SSH parolasız bağlanma

ssh-keygen -t rsa

ssh-copy-id root@10.x.x.152

ssh-copy-id root@10.x.x.153

Kurulum

root@ceph01:~# uuidgen

8bd9c2e7-6131-4dc6-93bb-667b4de89970

 

nano /etc/ceph/ceph.conf

[global]

fsid = 8bd9c2e7-6131-4dc6-93bb-667b4de89970

mon initial members = ceph01,ceph02,ceph03

mon host = 10.x.x.151,10.x.x.152,10.x.x.153

public network = 10.x.x.0/24

cluster network = 172.x.x.0/24

auth cluster required = cephx

auth service required = cephx

auth client required = cephx

osd journal size = 1024

osd pool default size = 3

osd pool default min size = 2

osd pool default pg num = 32

osd pool default pgp num = 32

osd crush chooseleaf type = 1

osd pool default pg autoscale mode = off

 

nano /etc/hosts

10.x.x.151      ceph01

10.x.x.152      ceph02

10.x.x.153      ceph03

 

root@ceph01:~# ceph-authtool –create-keyring /tmp/ceph.mon.keyring –gen-key -n mon. –cap mon ‘allow *’

creating /tmp/ceph.mon.keyring

 

root@ceph01:~# ceph-authtool –create-keyring /etc/ceph/ceph.client.admin.keyring –gen-key -n client.admin –cap mon ‘allow *’ –cap osd ‘allow *’ –cap mds ‘allow *’ –cap mgr ‘allow *’

creating /etc/ceph/ceph.client.admin.keyring

 

root@ceph01:~# ceph-authtool –create-keyring /var/lib/ceph/bootstrap-osd/ceph.keyring –gen-key -n client.bootstrap-osd –cap mon ‘profile bootstrap-osd’ –cap mgr ‘allow r’

creating /var/lib/ceph/bootstrap-osd/ceph.keyring

 

root@ceph01:~# ceph-authtool /tmp/ceph.mon.keyring –import-keyring /etc/ceph/ceph.client.admin.keyring

importing contents of /etc/ceph/ceph.client.admin.keyring into /tmp/ceph.mon.keyring

 

root@ceph01:~# ceph-authtool /tmp/ceph.mon.keyring –import-keyring /var/lib/ceph/bootstrap-osd/ceph.keyring

importing contents of /var/lib/ceph/bootstrap-osd/ceph.keyring into /tmp/ceph.mon.keyring

 

root@ceph01:~# chown ceph:ceph /tmp/ceph.mon.keyring

root@ceph01:~# monmaptool –create –add ceph01 10.x.x.151 –add ceph02 10.x.x.152 –add ceph03 10.x.x.153 –fsid 8bd9c2e7-6131-4dc6-93bb-667b4de89970 /tmp/monmap

monmaptool: monmap file /tmp/monmap

setting min_mon_release = octopus

monmaptool: set fsid to 8bd9c2e7-6131-4dc6-93bb-667b4de89970

monmaptool: writing epoch 0 to /tmp/monmap (3 monitors)

 

root@ceph01:~# scp /tmp/monmap root@ceph02:/tmp/

monmap

root@ceph01:~# scp /tmp/monmap root@ceph03:/tmp/

monmap

root@ceph01:~# scp /etc/ceph/ceph.client.admin.keyring root@ceph02:/etc/ceph/

ceph.client.admin.keyring

root@ceph01:~# scp /etc/ceph/ceph.client.admin.keyring root@ceph03:/etc/ceph/

ceph.client.admin.keyring

root@ceph01:~# scp /tmp/ceph.mon.keyring root@ceph02:/tmp/

ceph.mon.keyring

root@ceph01:~# scp /tmp/ceph.mon.keyring root@ceph03:/tmp/

ceph.mon.keyring

root@ceph01:~# scp /var/lib/ceph/bootstrap-osd/ceph.keyring root@ceph02:/var/lib/ceph/bootstrap-osd/

ceph.keyring

root@ceph01:~# scp /var/lib/ceph/bootstrap-osd/ceph.keyring root@ceph03:/var/lib/ceph/bootstrap-osd/

ceph.keyring

 

Her hostta

Hostname = ceph01, ceph02, ceph03 şeklinde gidiyorsa aşağıdaki komutlarda değişken kullanılabilir.

 

sudo -u ceph mkdir /var/lib/ceph/mon/ceph-ceph01

sudo -u ceph mkdir /var/lib/ceph/mon/ceph-ceph02

sudo -u ceph mkdir /var/lib/ceph/mon/ceph-ceph03

 

chown ceph:ceph /tmp/ceph.mon.keyring

chown ceph:ceph /tmp/ceph.mon.keyring

chown ceph:ceph /tmp/ceph.mon.keyring

 

sudo -u ceph ceph-mon –mkfs -i ceph01 –monmap /tmp/monmap –keyring /tmp/ceph.mon.keyring

sudo -u ceph ceph-mon –mkfs -i ceph02 –monmap /tmp/monmap –keyring /tmp/ceph.mon.keyring

sudo -u ceph ceph-mon –mkfs -i ceph03 –monmap /tmp/monmap –keyring /tmp/ceph.mon.keyring

 

systemctl start ceph-mon@ceph01

systemctl enable ceph-mon@ceph01

systemctl status ceph-mon@ceph01.service

 

systemctl start ceph-mon@ceph02

systemctl enable ceph-mon@ceph02

systemctl status ceph-mon@ceph02.service

 

systemctl start ceph-mon@ceph03

systemctl enable ceph-mon@ceph03

systemctl status ceph-mon@ceph03.service

 

sudo -u ceph mkdir /var/lib/ceph/mgr/ceph-ceph01

sudo -u ceph mkdir /var/lib/ceph/mgr/ceph-ceph02

sudo -u ceph mkdir /var/lib/ceph/mgr/ceph-ceph03

 

ceph auth get-or-create mgr.ceph01 mon ‘allow profile mgr’ osd ‘allow *’ mds ‘allow *’ > /var/lib/ceph/mgr/ceph-ceph01/keyring

ceph auth get-or-create mgr.ceph02 mon ‘allow profile mgr’ osd ‘allow *’ mds ‘allow *’ > /var/lib/ceph/mgr/ceph-ceph02/keyring

ceph auth get-or-create mgr.ceph03 mon ‘allow profile mgr’ osd ‘allow *’ mds ‘allow *’ > /var/lib/ceph/mgr/ceph-ceph03/keyring

 

systemctl restart ceph-mgr@ceph01

systemctl restart ceph-mgr@ceph02

systemctl restart ceph-mgr@ceph03

 

systemctl enable ceph-mgr@ceph01

systemctl enable ceph-mgr@ceph02

systemctl enable ceph-mgr@ceph03

 

 

Cluster kuruldu. Tek hosta bunları yaz:

ceph mon enable-msgr2

ceph osd set noup # OSD oluşturma işlemini hemen yaymasın. Aşağıda bu flag’i kaldıracağız.

 

Disk bölümlerini ve OSD’leri oluştur

1. Yöntem: Manuel

for i in a b c e f g ; do echo -e “dp\n1\nd\n2\nw” | fdisk /dev/sd$i; done        # sda, sdb, vb. tüm disklerdeki partitionları sil.

for i in a b c e f g ; do ceph-volume lvm zap /dev/sd$i ; done

for i in a b c e f g ; do vgcreate ceph-block-sd$i /dev/sd$i; done

for i in a b c e f g ; do lvcreate -l 50%FREE -n block-sd$i-1 ceph-block-sd$i; done

for i in a b c e f g ; do lvcreate -l 100%FREE -n block-sd$i-2 ceph-block-sd$i; done

for i in a b c e f g ; do for j in 1 2; do ceph-volume lvm create –bluestore –data ceph-block-sd$i/block-sd$i-$j; done; done

 

2. Yöntem: Otomatik (hepsini yapıyor)

ceph-volume lvm zap –destroy /dev/sda  # diskte partition varsa bu komutla uçur. (sda nvme0n1 olabilir diske göre)

ceph-volume lvm batch –osds-per-device 2 /dev/sdX # diskte partition yok ve sıfır disk ise

NoUp flag’ini kaldır

ceph osd unset noup #tek host # OSD oluşturma tamamlandı ve işlemlere başlat.

Dashboard

 

apt install ceph-mgr-dashboard

ceph mgr module enable dashboard # Bu satırda hata veriyor. Aşağıda “Bug düzeltme” başlığında çözümü var.

ceph dashboard create-self-signed-cert

ceph dashboard ac-user-create (kullanıcı adı) (şifre) administrator

https://(node ip-adı):8443

Bug düzeltme

# ceph mgr module enable dashboard

Üstteki komutu verince alttaki hatayı veriyor:

Error ENOENT: module ‘dashboard’ reports that it cannot run on the active manager daemon: invalid version number ‘8.5.2+ds1’ (pass –force to force enablement)

 

Hatanın sebebi, python3-cheroot paketindeki bir hata. Bunun için yeni sürüm çıkarmışlar. Doğrudan kendimiz indirip kurarsak düzeliyor:

wget http://ftp.de.debian.org/debian/pool/main/p/python-cheroot/python3-cheroot_8.6.0+ds1-3_all.deb

dpkg -i python3-cheroot_8.6.0+ds1-3_all.deb

 

Detay: https://bugs.launchpad.net/ubuntu/+source/ceph/+bug/1967139

Bir diske birden fazla OSD oluşturma

ceph-volume lvm batch –osds-per-device 4 /dev/sdX -> çok iyi

 

OSD yanlışıkla silinince Pool’u destroy etme

pveceph pool destroy bseuprmxcephpool –force

 

Servisleri restart etme sırası:

Mon, mgr ve osd

Proxmox kurulumu (Proxmox 7.2 içinde Ceph Pasific 16 sürümü geliyor)

Proxmoxları kurup 3 makinede de default Ceph kurduktan sonra, Proxmox web arayüzünden bu 3 makineyide mon ve mgr yaptık.

Sonrasında Ceph'in 17 sürümüne yükseltmek için aşağıdaki adımları uyguladık.

sed -i 's/pacific/quincy/' /etc/apt/sources.list.d/ceph.list

/etc/apt/sources.list.d/ceph.list dosyası aşağıdaki gibi olacak.

deb http://download.proxmox.com/debian/ceph-quincy bullseye main

Set the ‘noout’ Flag

Set the noout flag for the duration of the upgrade (optional, but recommended):

ceph osd set noout

Or via the GUI in the OSD tab (Manage Global Flags).

Upgrade on each Ceph Cluster Node

Upgrade all your nodes with the following commands or by installing the latest updates via the GUI. It will upgrade the Ceph on your node to Quincy.

apt update
apt full-upgrade

Makineleri tek tek reboot ettikten sonra Ceph’in artık proxmoxta 16’dan 17 sürümüne geçtiğini göreceksiniz.

ceph-volume lvm zap –destroy /dev/nvmen01      ile proxmox’un nvme diskleri osd oluşturma için hazır hale getiriyoruz.

Guiden her nvme için sadece 1 osd yapılıyor ve OSD’ler yapılırken mgr PG oluşuyor. Aynı zamanda osd keyringleri. Gui’den 1 den fazla osd yapamadığımız için ve keyringleri manuel oluşturmamak için Gui ile her hostta 1 osd oluşturuyoruz. Sonrasında ilk hosttaki osd’yi out deyip stop ettikten sonra destroy ediyoruz. Sonra komut satırında o hosttaki nvme diske 2 veya 4 osd yapmak istersek:

ceph-volume lvm batch –osds-per-device 4 /dev/nvme0n1 diyoruz.

Bu işlemi 3 hostta yukarıdaki açıklamadaki sırayla yapıyoruz.

Proxmox’ta bu kadar basit.

 

Benchmark

fio ile rbdengine kullanarak Ceph seviyesinde io testi yapmak için. Kaynak: https://tracker.ceph.com/projects/ceph/wiki/Benchmark_Ceph_Cluster_Performance

 

Test için Pool oluşturma:

ceph osd pool create bseu-linux-ceph-images 128 128

ceph osd pool application enable bseu-linux-ceph-images rbd

 

Test için disk imajı oluşturma:

rbd create image01 –size 20480 –pool  bseu-linux-ceph-images

rbd map image01 –pool  bseu-linux-ceph-images –name client.admin

/sbin/mkfs.ext4 -m0 /dev/rbd/ bseu-linux-ceph-images/image01

mkdir /mnt/ceph-block-device1

mount /dev/rbd/ bseu-linux-ceph-images/image01 /mnt/ceph-block-device1

 

Fio config dosyası

[global]

ioengine=rbd

clientname=admin

pool=bseu-linux-ceph-images

rbdname=image01

rw=randrw

rwmixread=70

bs=4k

#bs=1k

[rbd_iodepth32]

iodepth=32

 

 

Sehven Ceph.conf’ta autoscale off yapılmaz ve sistem yanlışlıkla autoscale on yapılırsa:

İlk olarak conf’ta autoscale off yapılır.

Sonrasında servisler restart edilecek,

systemctl restart ceph-mon@ceph01

systemctl restart ceph-mon@ceph02

systemctl restart ceph-mon@ceph03

systemctl restart ceph-mgr.target

ceph osd pool set bseu-linux-ceph-images pg_autoscale_mode off

ceph osd pool set  bseu-linux-ceph-images pg_num 128

ceph osd pool set  bseu-linux-ceph-images pgp_num 128

 

Sonuçlar

CEPH-Proxmox-pacific

root@pve02:~# fio rbd.fio
rbd_iodepth32: (g=0): rw=randrw, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=rbd, iodepth=32
fio-3.25
Starting 1 process
Jobs: 1 (f=1): [m(1)][100.0%][r=22.1MiB/s,w=9.82MiB/s][r=5658,w=2513 IOPS][eta 00m:00s]
rbd_iodepth32: (groupid=0, jobs=1): err= 0: pid=242908: Fri Jul 29 09:44:17 2022
read: IOPS=8634, BW=33.7MiB/s (35.4MB/s)(13.0GiB/424979msec)
write: IOPS=3702, BW=14.5MiB/s (15.2MB/s)(6146MiB/424979msec); 0 zone resets

 

CEPH-quincy
root@ceph01:~# fio ceph.fio
rbd_iodepth32: (g=0): rw=randrw, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=rbd, iodepth=32
fio-3.28
Starting 1 process
Jobs: 1 (f=1): [m(1)][100.0%][r=84.8MiB/s,w=35.9MiB/s][r=21.7k,w=9186 IOPS][eta 00m:00s]
rbd_iodepth32: (groupid=0, jobs=1): err= 0: pid=63995: Fri Jul 29 08:04:50 2022
read: IOPS=22.3k, BW=87.0MiB/s (91.2MB/s)(14.0GiB/164769msec)
write: IOPS=9548, BW=37.3MiB/s (39.1MB/s)(6146MiB/164769msec); 0 zone resets

 

 

Proxmox Backup Server testleri yapıldı.

İyileştirme ve ilerlemelerde güncellenecektir.

 

Nis 06

PostgreSQL Master-Slave Kurulumu

*2 adet Ubuntu Server 20.04 LTS gerekli.
*Birinci sunucu master, ikinci makine ise slave.
*Master okuma-yazma, slave ise readonly.

İşlem adımları:
Her iki sunucuda yapılacaklar:
1- ip adresleri ve hostname ayarları.
2- apt update && apt upgrade -y ile güncellemeler.
3- sudo apt-get install postgresql postgresql-client postgresql-contrib -y ile PostgreSQL 12 kur.
4- nano /etc/postgresql/12/main/postgresql.conf dosyasında localhost yerine listen_addresses = '*' postgresql portunun ip üzerinden dinleyecek hale getir.

Master sunucuda yapılacaklar:
1- sudo -u postgres psql postgresql giriş.
2- create user replicaauthuser with replication encrypted password 'Password1'; replication için gerekli user ve password oluştur.
3- nano /etc/postgresql/12/main/pg_hba.conf dosyasında host replication replicaauthuser 10.10.10.11/32 md5 oluşturduğunuz kullanıcı adı ve slave sunucunun ip adresini gir.
4- systemctl restart postgresql postgresql servisini yeniden başlat.

Slave sunucuda yapılacaklar:
1- systemctl stop postgresql postgresql servisini durdur ve su - postgres postgres kullanıcısına giriş yap.
2- rm -rf /var/lib/postgresql/12/main/* postgresql veri dizinindeki herşeyi uçur sil.
3- pg_basebackup -h 10.10.10.10 -D /var/lib/postgresql/12/main -U replicaauthuser -P -v -R -X stream -C -S slave01 replication ayarını yap. Komuttaki ip adresi master sunucusuna aittir.
4- cd /var/lib/postgresql/12/main bakınca master sunucudaki içeriklerin geldiği görülür.
5- systemctl restart postgresql ile postgresql servisi restart edilir.

Master sunucuda kontrol için yapılacaklar:
1- su - postgres
2- psql -c "SELECT * FROM pg_replication_slots;" çıktısında slave01 ve active_pid numarasına sahip olmalı.
3- Ayrıca psql -c "\x" -c "SELECT * FROM pg_stat_replication;" ilede kontrol edilebilir.

Mar 09

Aruba switchlerde parola sıfırlama (switch password reset)

Belki hardware bazında üzerindeki reset ve clear tuşları kolayınıza gelebilir ama bu yöntemde basit :
>>> The MGRinfo.txt file method : this file will be containing the passwords that are set for the switch.
follow the steps :

> take console .
1.Consol kablunuzu bağlayın.
> reboot the switch.
2.Anahtarı yeniden başlatın.
> keep pressing 0 till you see this =>
3. 0 a basarak monitoring moda girin.
> then ls/ [enter / carriage return ] look for cfa0
4. ls komutu ile mevcut dosya ve bileşenleri listeleyin.
> then cd cfa0 ​
5. 2530 versiyonunda buna gerek kalmadı mgrinfo.txt ana dizinde vardı.
>look for mgrinfo.txt by giving ls /
6. cat ile açarak mevcut şifreyi görebiliyorsanız, göremezseniz ise.
> then : rm mgrinfo.txt
7. Mevcut dosyayı rm mgrinfo.txt ile uçurun.
> boot
8. boot komutu ile yeniden başlattıktan sonra artık şifre felan yok.

Eski yazılar «