snap
This commit is contained in:
@@ -6,18 +6,20 @@ This module provides API routes for managing Certificate Authorities and Certifi
|
||||
|
||||
from flask import request, jsonify
|
||||
from app import db, logger
|
||||
from app.models.certificate_models import CertificateAuthority, Certificate
|
||||
from app.models.certificate_models import CertificateAuthority, Certificate, CertificateRevocationList
|
||||
from app.models.models import Project
|
||||
from cryptography import x509
|
||||
from app.utils.certificate_utils import (
|
||||
generate_self_signed_ca,
|
||||
issue_certificate,
|
||||
generate_self_signed_ca,
|
||||
issue_certificate,
|
||||
revoke_certificate,
|
||||
generate_crl_for_ca,
|
||||
encrypt_private_key,
|
||||
decrypt_private_key
|
||||
)
|
||||
from app.controller import api_bp
|
||||
from app.utils.standard_responses import api_response
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
import uuid
|
||||
|
||||
|
||||
@@ -86,7 +88,8 @@ def create_ca_for_project(project_id):
|
||||
)
|
||||
|
||||
# Create a new CA
|
||||
common_name = f"rootca.{project_id}.xcloudify.tech"
|
||||
domain_name = f"{project_id}.xcloudify.tech"
|
||||
common_name = f"rootca.{domain_name}"
|
||||
ca_data = generate_self_signed_ca(
|
||||
common_name=common_name,
|
||||
organization="xCloudify",
|
||||
@@ -103,7 +106,7 @@ def create_ca_for_project(project_id):
|
||||
common_name=common_name,
|
||||
organization="xCloudify",
|
||||
organizational_unit="IT",
|
||||
dns_name=common_name,
|
||||
domain_name=domain_name,
|
||||
validity_period=5,
|
||||
is_active=True,
|
||||
private_key=encrypted_private_key, # Store encrypted private key
|
||||
@@ -226,17 +229,24 @@ def create_certificate():
|
||||
)
|
||||
|
||||
# Get CA
|
||||
ca = CertificateAuthority.query.get_or_404(data['ca_id'])
|
||||
ca: CertificateAuthority = CertificateAuthority.query.get_or_404(data['ca_id'])
|
||||
|
||||
# Decrypt CA private key (in a real implementation, this would require additional authentication)
|
||||
# For this example, we'll use the project_id as the password
|
||||
decrypted_ca_private_key = decrypt_private_key(ca.private_key, ca.project_id)
|
||||
|
||||
#Just in case somsone specifies the full domain name, lets strip it all off
|
||||
data['common_name']=str(data['common_name']).replace(ca.domain_name,"")
|
||||
full_common_name=f"{data['common_name']}.{ca.domain_name}"
|
||||
# Also check for double periods and replace with a single period
|
||||
full_common_name=str(full_common_name).replace("..",".")
|
||||
|
||||
|
||||
# Issue certificate
|
||||
cert_data = issue_certificate(
|
||||
ca_private_key_pem=decrypted_ca_private_key,
|
||||
ca_cert_pem=ca.certificate_data,
|
||||
common_name=data['common_name'],
|
||||
common_name=full_common_name,
|
||||
certificate_type=data['certificate_type'],
|
||||
country=data.get('country'),
|
||||
state=data.get('state'),
|
||||
@@ -255,7 +265,7 @@ def create_certificate():
|
||||
name=data['name'],
|
||||
ca_id=data['ca_id'],
|
||||
certificate_type=data['certificate_type'],
|
||||
common_name=data['common_name'],
|
||||
common_name=full_common_name,
|
||||
country=data.get('country'),
|
||||
state=data.get('state'),
|
||||
city=data.get('city'),
|
||||
@@ -413,29 +423,50 @@ def revoke_certificate_route(cert_id):
|
||||
# For this example, we'll use the project_id as the password
|
||||
decrypted_ca_private_key = decrypt_private_key(ca.private_key, ca.project_id)
|
||||
|
||||
# Revoke certificate and generate CRL
|
||||
crl_data = revoke_certificate(
|
||||
ca_private_key_pem=decrypted_ca_private_key,
|
||||
ca_cert_pem=ca.certificate_data,
|
||||
cert_pem=cert.certificate_data,
|
||||
crl_number=1 # In a real implementation, this should be incremented
|
||||
)
|
||||
|
||||
# Update certificate status
|
||||
cert.revoked = True
|
||||
cert.revoked_at = datetime.utcnow()
|
||||
|
||||
# Get all revoked certificates for this CA
|
||||
revoked_certs = Certificate.query.filter_by(ca_id=ca.id, revoked=True).all()
|
||||
|
||||
# Prepare revoked certificates data for CRL generation
|
||||
revoked_certs_data = []
|
||||
for revoked_cert in revoked_certs:
|
||||
# Load the certificate to get its serial number
|
||||
cert_obj = x509.load_pem_x509_certificate(revoked_cert.certificate_data.encode('utf-8'))
|
||||
revoked_certs_data.append((cert_obj.serial_number, revoked_cert.revoked_at))
|
||||
|
||||
# Generate CRL with all revoked certificates
|
||||
crl_data = generate_crl_for_ca(
|
||||
ca_private_key_pem=decrypted_ca_private_key,
|
||||
ca_cert_pem=ca.certificate_data,
|
||||
revoked_certs=revoked_certs_data,
|
||||
crl_number=len(ca.crls) + 1 # Increment CRL number
|
||||
)
|
||||
|
||||
# Create or update CRL record
|
||||
# In a real implementation, you would store the CRL in the database
|
||||
# For this example, we'll just log it
|
||||
crl = CertificateRevocationList(
|
||||
ca_id=ca.id,
|
||||
crl_number=len(ca.crls) + 1,
|
||||
crl_data=crl_data,
|
||||
next_update=datetime.utcnow() + timedelta(days=30)
|
||||
)
|
||||
|
||||
db.session.add(crl)
|
||||
db.session.flush() # Get the ID of the new CRL
|
||||
|
||||
# Update CA's current CRL reference
|
||||
ca.current_crl_id = crl.id
|
||||
|
||||
db.session.commit()
|
||||
|
||||
logger.info(f"Revoked certificate {cert_id}")
|
||||
logger.info(f"Revoked certificate {cert_id} and updated CRL for CA {ca.id}")
|
||||
|
||||
return api_response(message="Certificate revoked successfully")
|
||||
return api_response(message="Certificate revoked successfully and CRL updated")
|
||||
except Exception as e:
|
||||
logger.error(f"Error revoking certificate {cert_id}: {str(e)}")
|
||||
db.session.rollback()
|
||||
return api_response(
|
||||
success=False,
|
||||
status=500,
|
||||
@@ -600,13 +631,19 @@ def get_crl(ca_id):
|
||||
try:
|
||||
ca = CertificateAuthority.query.get_or_404(ca_id)
|
||||
|
||||
# In a real implementation, you would retrieve the current CRL from storage
|
||||
# For this example, we'll return a placeholder
|
||||
crl_data = "-----BEGIN X509 CRL-----\n"
|
||||
crl_data += "Placeholder CRL data\n"
|
||||
crl_data += "-----END X509 CRL-----\n"
|
||||
|
||||
return crl_data, 200, {'Content-Type': 'application/x-pem-file'}
|
||||
# Get the current CRL for this CA
|
||||
if ca.current_crl:
|
||||
crl_data = ca.current_crl.crl_data
|
||||
else:
|
||||
# If no CRL exists, return an empty CRL
|
||||
# In a real implementation, you might want to generate one on-demand
|
||||
crl_data = "-----BEGIN X509 CRL-----\n"
|
||||
crl_data += "-----END X509 CRL-----\n"
|
||||
headers = {
|
||||
'Content-Type': 'application/x-pem-file',
|
||||
'Content-Disposition': f'attachment; filename="{ca_id}-CRL.pem"'
|
||||
}
|
||||
return crl_data, 200,headers
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting CRL for CA {ca_id}: {str(e)}")
|
||||
return api_response(
|
||||
|
||||
@@ -23,7 +23,7 @@ class CertificateAuthority(BaseModel):
|
||||
city = Column(String(255), nullable=True)
|
||||
organization = Column(String(255), nullable=True)
|
||||
organizational_unit = Column(String(255), nullable=True)
|
||||
dns_name = Column(String(255), nullable=True)
|
||||
domain_name = Column(String(255), nullable=True)
|
||||
validity_period = Column(Integer, default=5, nullable=False)
|
||||
is_active = Column(Boolean, default=True, nullable=False)
|
||||
private_key = Column(LONGTEXT, nullable=True) # Encrypted private key
|
||||
@@ -31,8 +31,10 @@ class CertificateAuthority(BaseModel):
|
||||
|
||||
# Relationships
|
||||
project = relationship("Project", backref="certificate_authority")
|
||||
certificates = relationship("Certificate", back_populates="ca")
|
||||
crls = relationship("CertificateRevocationList", back_populates="ca")
|
||||
certificates = relationship("Certificate", back_populates="ca", foreign_keys="Certificate.ca_id")
|
||||
crls = relationship("CertificateRevocationList", back_populates="ca", foreign_keys="CertificateRevocationList.ca_id")
|
||||
current_crl_id = Column(String(36), ForeignKey("certificate_revocation_lists.id"), nullable=True)
|
||||
current_crl = relationship("CertificateRevocationList", foreign_keys=[current_crl_id])
|
||||
|
||||
def to_json(self):
|
||||
"""Convert the CertificateAuthority object to a JSON-serializable dictionary"""
|
||||
@@ -72,7 +74,7 @@ class Certificate(BaseModel):
|
||||
certificate_data = Column(LONGTEXT, nullable=True) # The actual certificate
|
||||
|
||||
# Relationships
|
||||
ca = relationship("CertificateAuthority", back_populates="certificates")
|
||||
ca = relationship("CertificateAuthority", back_populates="certificates", foreign_keys="Certificate.ca_id")
|
||||
|
||||
def to_json(self):
|
||||
"""Convert the Certificate object to a JSON-serializable dictionary"""
|
||||
@@ -99,7 +101,7 @@ class CertificateRevocationList(BaseModel):
|
||||
next_update = Column(DateTime(timezone=True), nullable=False)
|
||||
|
||||
# Relationships
|
||||
ca = relationship("CertificateAuthority", back_populates="crls")
|
||||
ca = relationship("CertificateAuthority", back_populates="crls", foreign_keys="CertificateRevocationList.ca_id")
|
||||
|
||||
def to_json(self):
|
||||
"""Convert the CertificateRevocationList object to a JSON-serializable dictionary"""
|
||||
|
||||
+20
-1
@@ -87,7 +87,7 @@ class BaseModel(SoftDeleteMixin,db.Model):
|
||||
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
|
||||
|
||||
visible = Column(Boolean, default=True, nullable=False)
|
||||
name = Column(String(255), nullable=False)
|
||||
name = Column(String(255), nullable=False, default="")
|
||||
description = Column(LONGTEXT, nullable=True)
|
||||
status = Column(String(50), nullable=True)
|
||||
created_by = Column(String(36), ForeignKey("users.id"), nullable=True)
|
||||
@@ -949,3 +949,22 @@ class WorkloadRequest(db.Model):
|
||||
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
workload_type = db.Column(db.String(32))
|
||||
vdc = relationship("VirtualDataCenter")
|
||||
|
||||
#Not used by the API, just here to satisfy Alembic
|
||||
class Task(Base):
|
||||
__tablename__ = "tasks"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
worker_id = Column(String(64), index=True)
|
||||
job_details = Column(Text)
|
||||
response = Column(Text)
|
||||
status = Column(Text)
|
||||
success = Column(Text)
|
||||
creation_time = Column(DateTime, default=datetime.utcnow)
|
||||
start_time = Column(DateTime, nullable=True)
|
||||
finish_time = Column(DateTime, nullable=True)
|
||||
wait_time = Column(Float, nullable=True)
|
||||
execution_time = Column(Float, nullable=True)
|
||||
task_type = Column(String(50), nullable=False)
|
||||
depends_on = Column(Integer, nullable=True) # ID of the task this task depends on
|
||||
not_before = Column(DateTime, nullable=True) # Earliest time this task can run
|
||||
|
||||
@@ -297,6 +297,8 @@ def revoke_certificate(ca_private_key_pem, ca_cert_pem, cert_pem, crl_number=1):
|
||||
# Create CRL
|
||||
crl_builder = x509.CertificateRevocationListBuilder().issuer_name(
|
||||
ca_cert.subject
|
||||
).last_update(
|
||||
datetime.utcnow()
|
||||
).next_update(
|
||||
datetime.utcnow() + timedelta(days=30)
|
||||
).add_revoked_certificate(
|
||||
@@ -318,6 +320,61 @@ def revoke_certificate(ca_private_key_pem, ca_cert_pem, cert_pem, crl_number=1):
|
||||
return crl_pem.decode('utf-8')
|
||||
|
||||
|
||||
def generate_crl_for_ca(ca_private_key_pem, ca_cert_pem, revoked_certs, crl_number=1):
|
||||
"""
|
||||
Generate a CRL for a CA with all revoked certificates.
|
||||
|
||||
Args:
|
||||
ca_private_key_pem (str): PEM-encoded CA private key
|
||||
ca_cert_pem (str): PEM-encoded CA certificate
|
||||
revoked_certs (list): List of tuples (serial_number, revocation_date)
|
||||
crl_number (int): CRL number
|
||||
|
||||
Returns:
|
||||
str: PEM-encoded CRL
|
||||
"""
|
||||
# Load CA private key
|
||||
ca_private_key = serialization.load_pem_private_key(
|
||||
ca_private_key_pem.encode('utf-8'),
|
||||
password=None,
|
||||
)
|
||||
|
||||
# Load CA certificate
|
||||
ca_cert = x509.load_pem_x509_certificate(ca_cert_pem.encode('utf-8'))
|
||||
|
||||
# Create CRL builder
|
||||
crl_builder = x509.CertificateRevocationListBuilder().issuer_name(
|
||||
ca_cert.subject
|
||||
).last_update(
|
||||
datetime.utcnow()
|
||||
).next_update(
|
||||
datetime.utcnow() + timedelta(days=30)
|
||||
)
|
||||
|
||||
# Add all revoked certificates to the CRL
|
||||
for serial_number, revocation_date in revoked_certs:
|
||||
revoked_cert = x509.RevokedCertificateBuilder().serial_number(
|
||||
serial_number
|
||||
).revocation_date(
|
||||
revocation_date
|
||||
).build()
|
||||
crl_builder = crl_builder.add_revoked_certificate(revoked_cert)
|
||||
|
||||
# Add CRL number extension
|
||||
crl_builder = crl_builder.add_extension(
|
||||
x509.CRLNumber(crl_number),
|
||||
critical=False
|
||||
)
|
||||
|
||||
# Sign the CRL
|
||||
crl = crl_builder.sign(ca_private_key, hashes.SHA256())
|
||||
|
||||
# Serialize CRL
|
||||
crl_pem = crl.public_bytes(serialization.Encoding.PEM)
|
||||
|
||||
return crl_pem.decode('utf-8')
|
||||
|
||||
|
||||
def encrypt_private_key(private_key_pem, password):
|
||||
"""
|
||||
Encrypt a private key using a password.
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
wget --content-disposition https://api.xcloudify.tech/api/certificates/crl/ca/5e54e03a-740d-4b6b-be11-7c7d1ff4b6d6
|
||||
|
||||
ubuntu@dell02:~/Downloads/code/theapi/sandbox/containers/joke_container$ openssl crl -in 5e54e03a-740d-4b6b-be11-7c7d1ff4b6d6-CRL.pem -inform pem -text -noout
|
||||
Certificate Revocation List (CRL):
|
||||
Version 2 (0x1)
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
Issuer: O = xCloudify, OU = IT, CN = rootca.cbf6c418-2e08-40ac-a903-48836d0d3e07.xcloudify.tech
|
||||
Last Update: Aug 15 04:55:39 2025 GMT
|
||||
Next Update: Sep 14 04:55:39 2025 GMT
|
||||
CRL extensions:
|
||||
X509v3 CRL Number:
|
||||
2
|
||||
Revoked Certificates:
|
||||
Serial Number: 69755EFA0191D96456E99619521A1E74BB6D6F46
|
||||
Revocation Date: Aug 15 04:31:16 2025 GMT
|
||||
Serial Number: 1F8F1C277DB5CCDC2349CCDC929974BCAB979505
|
||||
Revocation Date: Aug 15 04:55:39 2025 GMT
|
||||
Serial Number: 33CDB2FA4350ACBA8B2BB35887739BFD267800EA
|
||||
Revocation Date: Aug 15 04:55:33 2025 GMT
|
||||
Serial Number: 6B5E04A08E6F7060F4195E9A89C2C141887EF834
|
||||
Revocation Date: Aug 15 04:31:40 2025 GMT
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
Signature Value:
|
||||
51:d1:53:2c:82:2d:39:9b:38:d2:71:3b:d4:07:a6:29:c6:2a:
|
||||
a7:62:bd:7f:b0:4a:e6:d7:e2:c3:18:ec:ff:83:09:68:56:23:
|
||||
58:66:ae:ce:ca:03:0b:b6:eb:95:c7:6a:f2:d5:4b:a7:b7:4c:
|
||||
0c:5f:6b:8f:10:3b:f9:bc:fe:1b:88:f3:ea:0d:1e:6d:a5:e9:
|
||||
21:fc:af:93:91:30:4b:53:8b:21:dd:1a:9d:e5:ab:c1:a8:ee:
|
||||
f3:37:d0:32:2a:78:46:8d:aa:ae:be:a5:ff:46:3d:7a:53:fe:
|
||||
25:62:b6:76:49:97:e2:14:68:77:5e:b7:d2:c4:bb:0e:18:80:
|
||||
a8:fa:62:a5:83:d3:0e:29:02:7a:42:4b:7f:9e:2b:50:2c:da:
|
||||
f9:e4:38:cb:73:fe:e6:e5:47:4b:82:2a:f8:9f:a3:38:5d:bf:
|
||||
5b:c1:cd:6f:26:df:82:55:03:4f:43:45:a3:52:ca:3d:77:de:
|
||||
ac:7a:98:3a:59:69:e2:e2:1d:c3:a9:30:67:7d:33:ee:e7:88:
|
||||
aa:1b:9f:0d:8f:8d:1f:22:1d:8d:7f:7d:90:f7:54:50:22:b9:
|
||||
ac:b1:25:6f:12:65:21:90:52:30:64:79:eb:01:41:07:70:18:
|
||||
38:7d:ad:64:b8:69:dc:ef:02:1d:ea:36:9a:39:e8:2c:54:e5:
|
||||
e8:ee:e9:97
|
||||
ubuntu@dell02:~/Downloads/code/theapi/sandbox/containers/joke_container$
|
||||
|
||||
+134
-4
@@ -1,8 +1,8 @@
|
||||
"""First
|
||||
|
||||
Revision ID: 43f3c58925bf
|
||||
Revision ID: 15dbb0114da7
|
||||
Revises:
|
||||
Create Date: 2025-08-07 06:38:28.180125
|
||||
Create Date: 2025-08-15 13:36:30.771991
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
@@ -10,7 +10,7 @@ import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import mysql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '43f3c58925bf'
|
||||
revision = '15dbb0114da7'
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
@@ -153,6 +153,7 @@ def upgrade():
|
||||
sa.Column('ip_address_all', mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column('ip_address_eastwest', sa.String(length=25), nullable=True),
|
||||
sa.Column('ip_address_northsouth', sa.String(length=25), nullable=True),
|
||||
sa.Column('ip_address_public', sa.String(length=25), nullable=True),
|
||||
sa.Column('status', sa.String(length=50), nullable=True),
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||
@@ -167,6 +168,34 @@ def upgrade():
|
||||
sa.ForeignKeyConstraint(['region_id'], ['regions.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_table('certificate_authorities',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('project_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('common_name', sa.String(length=255), nullable=False),
|
||||
sa.Column('country', sa.String(length=2), nullable=True),
|
||||
sa.Column('state', sa.String(length=255), nullable=True),
|
||||
sa.Column('city', sa.String(length=255), nullable=True),
|
||||
sa.Column('organization', sa.String(length=255), nullable=True),
|
||||
sa.Column('organizational_unit', sa.String(length=255), nullable=True),
|
||||
sa.Column('domain_name', sa.String(length=255), nullable=True),
|
||||
sa.Column('validity_period', sa.Integer(), nullable=False),
|
||||
sa.Column('is_active', sa.Boolean(), nullable=False),
|
||||
sa.Column('private_key', mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column('certificate_data', mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('visible', sa.Boolean(), nullable=False),
|
||||
sa.Column('name', sa.String(length=255), nullable=False),
|
||||
sa.Column('description', mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column('status', sa.String(length=50), nullable=True),
|
||||
sa.Column('created_by', sa.String(length=36), nullable=True),
|
||||
sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('deleted', sa.Boolean(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['created_by'], ['users.id'], ),
|
||||
sa.ForeignKeyConstraint(['project_id'], ['projects.id'], ),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('project_id')
|
||||
)
|
||||
op.create_table('region_access',
|
||||
sa.Column('project_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('region_id', sa.String(length=36), nullable=False),
|
||||
@@ -192,6 +221,25 @@ def upgrade():
|
||||
sa.ForeignKeyConstraint(['region_id'], ['regions.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_table('workload_host_available_ports',
|
||||
sa.Column('workload_host_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('start_port', sa.Integer(), nullable=False),
|
||||
sa.Column('end_port', sa.Integer(), nullable=False),
|
||||
sa.Column('protocol', sa.String(length=10), nullable=False),
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('visible', sa.Boolean(), nullable=False),
|
||||
sa.Column('name', sa.String(length=255), nullable=False),
|
||||
sa.Column('description', mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column('status', sa.String(length=50), nullable=True),
|
||||
sa.Column('created_by', sa.String(length=36), nullable=True),
|
||||
sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('deleted', sa.Boolean(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['created_by'], ['users.id'], ),
|
||||
sa.ForeignKeyConstraint(['workload_host_id'], ['workload_hosts.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_table('workload_host_fixed_resources',
|
||||
sa.Column('type', sa.String(length=50), nullable=False),
|
||||
sa.Column('model', sa.String(length=255), nullable=True),
|
||||
@@ -249,6 +297,56 @@ def upgrade():
|
||||
sa.ForeignKeyConstraint(['workload_host_id'], ['workload_hosts.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_table('certificate_revocation_lists',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('ca_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('crl_number', sa.Integer(), nullable=False),
|
||||
sa.Column('crl_data', mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column('next_update', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('visible', sa.Boolean(), nullable=False),
|
||||
sa.Column('name', sa.String(length=255), nullable=False),
|
||||
sa.Column('description', mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column('status', sa.String(length=50), nullable=True),
|
||||
sa.Column('created_by', sa.String(length=36), nullable=True),
|
||||
sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('deleted', sa.Boolean(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['ca_id'], ['certificate_authorities.id'], ),
|
||||
sa.ForeignKeyConstraint(['created_by'], ['users.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_table('certificates',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('ca_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('certificate_type', sa.String(length=50), nullable=False),
|
||||
sa.Column('common_name', sa.String(length=255), nullable=False),
|
||||
sa.Column('country', sa.String(length=2), nullable=True),
|
||||
sa.Column('state', sa.String(length=255), nullable=True),
|
||||
sa.Column('city', sa.String(length=255), nullable=True),
|
||||
sa.Column('organization', sa.String(length=255), nullable=True),
|
||||
sa.Column('organizational_unit', sa.String(length=255), nullable=True),
|
||||
sa.Column('email', sa.String(length=255), nullable=True),
|
||||
sa.Column('validity_period', sa.Integer(), nullable=False),
|
||||
sa.Column('is_active', sa.Boolean(), nullable=False),
|
||||
sa.Column('revoked', sa.Boolean(), nullable=False),
|
||||
sa.Column('revoked_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('public_key', mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column('private_key', mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column('certificate_data', mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('visible', sa.Boolean(), nullable=False),
|
||||
sa.Column('name', sa.String(length=255), nullable=False),
|
||||
sa.Column('description', mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column('status', sa.String(length=50), nullable=True),
|
||||
sa.Column('created_by', sa.String(length=36), nullable=True),
|
||||
sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('deleted', sa.Boolean(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['ca_id'], ['certificate_authorities.id'], ),
|
||||
sa.ForeignKeyConstraint(['created_by'], ['users.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_table('networks',
|
||||
sa.Column('vdc_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('ipv4_cidr', sa.String(length=50), nullable=True),
|
||||
@@ -484,7 +582,8 @@ def upgrade():
|
||||
sa.Column('internal_port', sa.Integer(), nullable=False),
|
||||
sa.Column('external_port', sa.Integer(), nullable=False),
|
||||
sa.Column('protocol', sa.String(length=10), nullable=False),
|
||||
sa.Column('ip_address', sa.String(length=25), nullable=False),
|
||||
sa.Column('external_ip_address', sa.String(length=25), nullable=False),
|
||||
sa.Column('internal_ip_address', sa.String(length=25), nullable=False),
|
||||
sa.Column('dns_record_id', sa.String(length=36), nullable=True),
|
||||
sa.Column('workload_id', sa.String(length=36), nullable=True),
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
@@ -503,11 +602,38 @@ def upgrade():
|
||||
sa.ForeignKeyConstraint(['workload_id'], ['workloads.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
with op.batch_alter_table('tasks', schema=None) as batch_op:
|
||||
batch_op.drop_index('ix_tasks_worker_id')
|
||||
|
||||
op.drop_table('tasks')
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('tasks',
|
||||
sa.Column('id', mysql.INTEGER(display_width=11), autoincrement=True, nullable=False),
|
||||
sa.Column('worker_id', mysql.VARCHAR(length=64), nullable=True),
|
||||
sa.Column('job_details', mysql.TEXT(), nullable=True),
|
||||
sa.Column('response', mysql.TEXT(), nullable=True),
|
||||
sa.Column('status', mysql.TEXT(), nullable=True),
|
||||
sa.Column('success', mysql.TEXT(), nullable=True),
|
||||
sa.Column('creation_time', mysql.DATETIME(), nullable=True),
|
||||
sa.Column('start_time', mysql.DATETIME(), nullable=True),
|
||||
sa.Column('finish_time', mysql.DATETIME(), nullable=True),
|
||||
sa.Column('wait_time', mysql.FLOAT(), nullable=True),
|
||||
sa.Column('execution_time', mysql.FLOAT(), nullable=True),
|
||||
sa.Column('task_type', mysql.VARCHAR(length=50), nullable=False),
|
||||
sa.Column('depends_on', mysql.INTEGER(display_width=11), autoincrement=False, nullable=True),
|
||||
sa.Column('not_before', mysql.DATETIME(), nullable=True),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
mysql_collate='utf8mb4_general_ci',
|
||||
mysql_default_charset='utf8mb4',
|
||||
mysql_engine='InnoDB'
|
||||
)
|
||||
with op.batch_alter_table('tasks', schema=None) as batch_op:
|
||||
batch_op.create_index('ix_tasks_worker_id', ['worker_id'], unique=False)
|
||||
|
||||
op.drop_table('port_forwarding')
|
||||
op.drop_table('container_pod_containers')
|
||||
op.drop_table('cloudflare_dns_records')
|
||||
@@ -521,11 +647,15 @@ def downgrade():
|
||||
op.drop_table('workload_requests')
|
||||
op.drop_table('volumes')
|
||||
op.drop_table('networks')
|
||||
op.drop_table('certificates')
|
||||
op.drop_table('certificate_revocation_lists')
|
||||
op.drop_table('workload_host_pooled_resources')
|
||||
op.drop_table('workload_host_ovs_bridge')
|
||||
op.drop_table('workload_host_fixed_resources')
|
||||
op.drop_table('workload_host_available_ports')
|
||||
op.drop_table('vdcs')
|
||||
op.drop_table('region_access')
|
||||
op.drop_table('certificate_authorities')
|
||||
op.drop_table('workload_hosts')
|
||||
op.drop_table('projects')
|
||||
op.drop_table('universes')
|
||||
@@ -1,39 +0,0 @@
|
||||
"""schema update
|
||||
|
||||
Revision ID: 2ab3b94a6452
|
||||
Revises: fc7f28e036ee
|
||||
Create Date: 2025-08-12 01:01:32.885734
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import mysql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '2ab3b94a6452'
|
||||
down_revision = 'fc7f28e036ee'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
|
||||
|
||||
|
||||
with op.batch_alter_table('port_forwarding', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('external_ip_address', sa.String(length=25), nullable=False))
|
||||
batch_op.add_column(sa.Column('internal_ip_address', sa.String(length=25), nullable=False))
|
||||
batch_op.drop_column('ip_address')
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table('port_forwarding', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('ip_address', mysql.VARCHAR(length=25), nullable=False))
|
||||
batch_op.drop_column('internal_ip_address')
|
||||
batch_op.drop_column('external_ip_address')
|
||||
|
||||
# ### end Alembic commands ###
|
||||
@@ -1,113 +0,0 @@
|
||||
"""Certs
|
||||
|
||||
Revision ID: 37480d4d2782
|
||||
Revises: 5fd95b9faf5f
|
||||
Create Date: 2025-08-14 17:50:33.906740
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import mysql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '37480d4d2782'
|
||||
down_revision = '5fd95b9faf5f'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table('tasks', schema=None) as batch_op:
|
||||
batch_op.drop_index('ix_tasks_worker_id')
|
||||
|
||||
op.drop_table('tasks')
|
||||
with op.batch_alter_table('certificate_authorities', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('visible', sa.Boolean(), nullable=False))
|
||||
batch_op.add_column(sa.Column('name', sa.String(length=255), nullable=False))
|
||||
batch_op.add_column(sa.Column('description', mysql.LONGTEXT(), nullable=True))
|
||||
batch_op.add_column(sa.Column('status', sa.String(length=50), nullable=True))
|
||||
batch_op.add_column(sa.Column('created_by', sa.String(length=36), nullable=True))
|
||||
batch_op.add_column(sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True))
|
||||
batch_op.add_column(sa.Column('deleted', sa.Boolean(), nullable=False))
|
||||
batch_op.create_foreign_key(None, 'users', ['created_by'], ['id'])
|
||||
|
||||
with op.batch_alter_table('certificate_revocation_lists', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('visible', sa.Boolean(), nullable=False))
|
||||
batch_op.add_column(sa.Column('name', sa.String(length=255), nullable=False))
|
||||
batch_op.add_column(sa.Column('description', mysql.LONGTEXT(), nullable=True))
|
||||
batch_op.add_column(sa.Column('status', sa.String(length=50), nullable=True))
|
||||
batch_op.add_column(sa.Column('created_by', sa.String(length=36), nullable=True))
|
||||
batch_op.add_column(sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True))
|
||||
batch_op.add_column(sa.Column('deleted', sa.Boolean(), nullable=False))
|
||||
batch_op.create_foreign_key(None, 'users', ['created_by'], ['id'])
|
||||
|
||||
with op.batch_alter_table('certificates', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('visible', sa.Boolean(), nullable=False))
|
||||
batch_op.add_column(sa.Column('name', sa.String(length=255), nullable=False))
|
||||
batch_op.add_column(sa.Column('description', mysql.LONGTEXT(), nullable=True))
|
||||
batch_op.add_column(sa.Column('status', sa.String(length=50), nullable=True))
|
||||
batch_op.add_column(sa.Column('created_by', sa.String(length=36), nullable=True))
|
||||
batch_op.add_column(sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True))
|
||||
batch_op.add_column(sa.Column('deleted', sa.Boolean(), nullable=False))
|
||||
batch_op.create_foreign_key(None, 'users', ['created_by'], ['id'])
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table('certificates', schema=None) as batch_op:
|
||||
batch_op.drop_constraint(None, type_='foreignkey')
|
||||
batch_op.drop_column('deleted')
|
||||
batch_op.drop_column('deleted_at')
|
||||
batch_op.drop_column('created_by')
|
||||
batch_op.drop_column('status')
|
||||
batch_op.drop_column('description')
|
||||
batch_op.drop_column('name')
|
||||
batch_op.drop_column('visible')
|
||||
|
||||
with op.batch_alter_table('certificate_revocation_lists', schema=None) as batch_op:
|
||||
batch_op.drop_constraint(None, type_='foreignkey')
|
||||
batch_op.drop_column('deleted')
|
||||
batch_op.drop_column('deleted_at')
|
||||
batch_op.drop_column('created_by')
|
||||
batch_op.drop_column('status')
|
||||
batch_op.drop_column('description')
|
||||
batch_op.drop_column('name')
|
||||
batch_op.drop_column('visible')
|
||||
|
||||
with op.batch_alter_table('certificate_authorities', schema=None) as batch_op:
|
||||
batch_op.drop_constraint(None, type_='foreignkey')
|
||||
batch_op.drop_column('deleted')
|
||||
batch_op.drop_column('deleted_at')
|
||||
batch_op.drop_column('created_by')
|
||||
batch_op.drop_column('status')
|
||||
batch_op.drop_column('description')
|
||||
batch_op.drop_column('name')
|
||||
batch_op.drop_column('visible')
|
||||
|
||||
op.create_table('tasks',
|
||||
sa.Column('id', mysql.INTEGER(display_width=11), autoincrement=True, nullable=False),
|
||||
sa.Column('worker_id', mysql.VARCHAR(length=64), nullable=True),
|
||||
sa.Column('job_details', mysql.TEXT(), nullable=True),
|
||||
sa.Column('response', mysql.TEXT(), nullable=True),
|
||||
sa.Column('status', mysql.TEXT(), nullable=True),
|
||||
sa.Column('success', mysql.TEXT(), nullable=True),
|
||||
sa.Column('creation_time', mysql.DATETIME(), nullable=True),
|
||||
sa.Column('start_time', mysql.DATETIME(), nullable=True),
|
||||
sa.Column('finish_time', mysql.DATETIME(), nullable=True),
|
||||
sa.Column('wait_time', mysql.FLOAT(), nullable=True),
|
||||
sa.Column('execution_time', mysql.FLOAT(), nullable=True),
|
||||
sa.Column('task_type', mysql.VARCHAR(length=50), nullable=False),
|
||||
sa.Column('depends_on', mysql.INTEGER(display_width=11), autoincrement=False, nullable=True),
|
||||
sa.Column('not_before', mysql.DATETIME(), nullable=True),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
mysql_collate='utf8mb4_general_ci',
|
||||
mysql_default_charset='utf8mb4',
|
||||
mysql_engine='InnoDB'
|
||||
)
|
||||
with op.batch_alter_table('tasks', schema=None) as batch_op:
|
||||
batch_op.create_index('ix_tasks_worker_id', ['worker_id'], unique=False)
|
||||
|
||||
# ### end Alembic commands ###
|
||||
@@ -1,46 +0,0 @@
|
||||
"""Add workload_host_available_ports table
|
||||
|
||||
Revision ID: 5a4b8c9d1e2f
|
||||
Revises: 43f3c58925bf
|
||||
Create Date: 2025-08-11 06:20:00.000000
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import mysql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '5a4b8c9d1e2f'
|
||||
down_revision = '43f3c58925bf'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('workload_host_available_ports',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('workload_host_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('start_port', sa.Integer(), nullable=False),
|
||||
sa.Column('end_port', sa.Integer(), nullable=False),
|
||||
sa.Column('protocol', sa.String(length=10), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('visible', sa.Boolean(), nullable=False),
|
||||
sa.Column('name', sa.String(length=255), nullable=False),
|
||||
sa.Column('description', mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column('status', sa.String(length=50), nullable=True),
|
||||
sa.Column('created_by', sa.String(length=36), nullable=True),
|
||||
sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('deleted', sa.Boolean(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['created_by'], ['users.id'], ),
|
||||
sa.ForeignKeyConstraint(['workload_host_id'], ['workload_hosts.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_table('workload_host_available_ports')
|
||||
# ### end Alembic commands ###
|
||||
+12
-10
@@ -1,8 +1,8 @@
|
||||
"""schema update
|
||||
"""Cert upd
|
||||
|
||||
Revision ID: fc7f28e036ee
|
||||
Revises: 5a4b8c9d1e2f
|
||||
Create Date: 2025-08-11 22:02:05.721807
|
||||
Revision ID: 5be04054a692
|
||||
Revises: 15dbb0114da7
|
||||
Create Date: 2025-08-15 14:21:28.498864
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
@@ -10,8 +10,8 @@ import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import mysql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'fc7f28e036ee'
|
||||
down_revision = '5a4b8c9d1e2f'
|
||||
revision = '5be04054a692'
|
||||
down_revision = '15dbb0114da7'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
@@ -22,16 +22,18 @@ def upgrade():
|
||||
batch_op.drop_index('ix_tasks_worker_id')
|
||||
|
||||
op.drop_table('tasks')
|
||||
with op.batch_alter_table('workload_hosts', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('ip_address_public', sa.String(length=25), nullable=True))
|
||||
with op.batch_alter_table('certificate_authorities', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('current_crl_id', sa.String(length=36), nullable=True))
|
||||
batch_op.create_foreign_key(None, 'certificate_revocation_lists', ['current_crl_id'], ['id'])
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table('workload_hosts', schema=None) as batch_op:
|
||||
batch_op.drop_column('ip_address_public')
|
||||
with op.batch_alter_table('certificate_authorities', schema=None) as batch_op:
|
||||
batch_op.drop_constraint(None, type_='foreignkey')
|
||||
batch_op.drop_column('current_crl_id')
|
||||
|
||||
op.create_table('tasks',
|
||||
sa.Column('id', mysql.INTEGER(display_width=11), autoincrement=True, nullable=False),
|
||||
@@ -1,110 +0,0 @@
|
||||
"""Certs
|
||||
|
||||
Revision ID: 5fd95b9faf5f
|
||||
Revises: 2ab3b94a6452
|
||||
Create Date: 2025-08-14 15:11:31.845852
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import mysql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '5fd95b9faf5f'
|
||||
down_revision = '2ab3b94a6452'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('certificate_authorities',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('project_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('common_name', sa.String(length=255), nullable=False),
|
||||
sa.Column('country', sa.String(length=2), nullable=True),
|
||||
sa.Column('state', sa.String(length=255), nullable=True),
|
||||
sa.Column('city', sa.String(length=255), nullable=True),
|
||||
sa.Column('organization', sa.String(length=255), nullable=True),
|
||||
sa.Column('organizational_unit', sa.String(length=255), nullable=True),
|
||||
sa.Column('dns_name', sa.String(length=255), nullable=True),
|
||||
sa.Column('validity_period', sa.Integer(), nullable=False),
|
||||
sa.Column('is_active', sa.Boolean(), nullable=False),
|
||||
sa.Column('private_key', mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column('certificate_data', mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['project_id'], ['projects.id'], ),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('project_id')
|
||||
)
|
||||
op.create_table('certificate_revocation_lists',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('ca_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('crl_number', sa.Integer(), nullable=False),
|
||||
sa.Column('crl_data', mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column('next_update', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['ca_id'], ['certificate_authorities.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_table('certificates',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('ca_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('certificate_type', sa.String(length=50), nullable=False),
|
||||
sa.Column('common_name', sa.String(length=255), nullable=False),
|
||||
sa.Column('country', sa.String(length=2), nullable=True),
|
||||
sa.Column('state', sa.String(length=255), nullable=True),
|
||||
sa.Column('city', sa.String(length=255), nullable=True),
|
||||
sa.Column('organization', sa.String(length=255), nullable=True),
|
||||
sa.Column('organizational_unit', sa.String(length=255), nullable=True),
|
||||
sa.Column('email', sa.String(length=255), nullable=True),
|
||||
sa.Column('validity_period', sa.Integer(), nullable=False),
|
||||
sa.Column('is_active', sa.Boolean(), nullable=False),
|
||||
sa.Column('revoked', sa.Boolean(), nullable=False),
|
||||
sa.Column('revoked_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('public_key', mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column('private_key', mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column('certificate_data', mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['ca_id'], ['certificate_authorities.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
with op.batch_alter_table('tasks', schema=None) as batch_op:
|
||||
batch_op.drop_index('ix_tasks_worker_id')
|
||||
|
||||
op.drop_table('tasks')
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('tasks',
|
||||
sa.Column('id', mysql.INTEGER(display_width=11), autoincrement=True, nullable=False),
|
||||
sa.Column('worker_id', mysql.VARCHAR(length=64), nullable=True),
|
||||
sa.Column('job_details', mysql.TEXT(), nullable=True),
|
||||
sa.Column('response', mysql.TEXT(), nullable=True),
|
||||
sa.Column('status', mysql.TEXT(), nullable=True),
|
||||
sa.Column('success', mysql.TEXT(), nullable=True),
|
||||
sa.Column('creation_time', mysql.DATETIME(), nullable=True),
|
||||
sa.Column('start_time', mysql.DATETIME(), nullable=True),
|
||||
sa.Column('finish_time', mysql.DATETIME(), nullable=True),
|
||||
sa.Column('wait_time', mysql.FLOAT(), nullable=True),
|
||||
sa.Column('execution_time', mysql.FLOAT(), nullable=True),
|
||||
sa.Column('task_type', mysql.VARCHAR(length=50), nullable=False),
|
||||
sa.Column('depends_on', mysql.INTEGER(display_width=11), autoincrement=False, nullable=True),
|
||||
sa.Column('not_before', mysql.DATETIME(), nullable=True),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
mysql_collate='utf8mb4_general_ci',
|
||||
mysql_default_charset='utf8mb4',
|
||||
mysql_engine='InnoDB'
|
||||
)
|
||||
with op.batch_alter_table('tasks', schema=None) as batch_op:
|
||||
batch_op.create_index('ix_tasks_worker_id', ['worker_id'], unique=False)
|
||||
|
||||
op.drop_table('certificates')
|
||||
op.drop_table('certificate_revocation_lists')
|
||||
op.drop_table('certificate_authorities')
|
||||
# ### end Alembic commands ###
|
||||
+6
-6
@@ -1,8 +1,8 @@
|
||||
"""Certs
|
||||
"""Empty string default for name
|
||||
|
||||
Revision ID: 23306f452624
|
||||
Revises: 37480d4d2782
|
||||
Create Date: 2025-08-14 21:18:02.277503
|
||||
Revision ID: de4cee778fa3
|
||||
Revises: 5be04054a692
|
||||
Create Date: 2025-08-15 14:25:22.196007
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
@@ -10,8 +10,8 @@ import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import mysql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '23306f452624'
|
||||
down_revision = '37480d4d2782'
|
||||
revision = 'de4cee778fa3'
|
||||
down_revision = '5be04054a692'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
-----BEGIN X509 CRL-----
|
||||
MIICXzCCAUcCAQEwDQYJKoZIhvcNAQELBQAwZjESMBAGA1UECgwJeENsb3VkaWZ5
|
||||
MQswCQYDVQQLDAJJVDFDMEEGA1UEAww6cm9vdGNhLmNiZjZjNDE4LTJlMDgtNDBh
|
||||
Yy1hOTAzLTQ4ODM2ZDBkM2UwNy54Y2xvdWRpZnkudGVjaBcNMjUwODE1MDQ1NTM5
|
||||
WhcNMjUwOTE0MDQ1NTM5WjCBnDAlAhRpdV76AZHZZFbplhlSGh50u21vRhcNMjUw
|
||||
ODE1MDQzMTE2WjAlAhQfjxwnfbXM3CNJzNySmXS8q5eVBRcNMjUwODE1MDQ1NTM5
|
||||
WjAlAhQzzbL6Q1Csuosrs1iHc5v9JngA6hcNMjUwODE1MDQ1NTMzWjAlAhRrXgSg
|
||||
jm9wYPQZXpqJwsFBiH74NBcNMjUwODE1MDQzMTQwWqAOMAwwCgYDVR0UBAMCAQIw
|
||||
DQYJKoZIhvcNAQELBQADggEBAFHRUyyCLTmbONJxO9QHpinGKqdivX+wSubX4sMY
|
||||
7P+DCWhWI1hmrs7KAwu265XHavLVS6e3TAxfa48QO/m8/huI8+oNHm2l6SH8r5OR
|
||||
MEtTiyHdGp3lq8Go7vM30DIqeEaNqq6+pf9GPXpT/iVitnZJl+IUaHdet9LEuw4Y
|
||||
gKj6YqWD0w4pAnpCS3+eK1As2vnkOMtz/ublR0uCKvifozhdv1vBzW8m34JVA09D
|
||||
RaNSyj133qx6mDpZaeLiHcOpMGd9M+7niKobnw2PjR8iHY1/fZD3VFAiuayxJW8S
|
||||
ZSGQUjBkeesBQQdwGDh9rWS4adzvAh3qNpo56CxU5eju6Zc=
|
||||
-----END X509 CRL-----
|
||||
@@ -0,0 +1,15 @@
|
||||
-----BEGIN X509 CRL-----
|
||||
MIICXzCCAUcCAQEwDQYJKoZIhvcNAQELBQAwZjESMBAGA1UECgwJeENsb3VkaWZ5
|
||||
MQswCQYDVQQLDAJJVDFDMEEGA1UEAww6cm9vdGNhLmNiZjZjNDE4LTJlMDgtNDBh
|
||||
Yy1hOTAzLTQ4ODM2ZDBkM2UwNy54Y2xvdWRpZnkudGVjaBcNMjUwODE1MDQ1NTM5
|
||||
WhcNMjUwOTE0MDQ1NTM5WjCBnDAlAhRpdV76AZHZZFbplhlSGh50u21vRhcNMjUw
|
||||
ODE1MDQzMTE2WjAlAhQfjxwnfbXM3CNJzNySmXS8q5eVBRcNMjUwODE1MDQ1NTM5
|
||||
WjAlAhQzzbL6Q1Csuosrs1iHc5v9JngA6hcNMjUwODE1MDQ1NTMzWjAlAhRrXgSg
|
||||
jm9wYPQZXpqJwsFBiH74NBcNMjUwODE1MDQzMTQwWqAOMAwwCgYDVR0UBAMCAQIw
|
||||
DQYJKoZIhvcNAQELBQADggEBAFHRUyyCLTmbONJxO9QHpinGKqdivX+wSubX4sMY
|
||||
7P+DCWhWI1hmrs7KAwu265XHavLVS6e3TAxfa48QO/m8/huI8+oNHm2l6SH8r5OR
|
||||
MEtTiyHdGp3lq8Go7vM30DIqeEaNqq6+pf9GPXpT/iVitnZJl+IUaHdet9LEuw4Y
|
||||
gKj6YqWD0w4pAnpCS3+eK1As2vnkOMtz/ublR0uCKvifozhdv1vBzW8m34JVA09D
|
||||
RaNSyj133qx6mDpZaeLiHcOpMGd9M+7niKobnw2PjR8iHY1/fZD3VFAiuayxJW8S
|
||||
ZSGQUjBkeesBQQdwGDh9rWS4adzvAh3qNpo56CxU5eju6Zc=
|
||||
-----END X509 CRL-----
|
||||
@@ -0,0 +1,15 @@
|
||||
-----BEGIN X509 CRL-----
|
||||
MIICXzCCAUcCAQEwDQYJKoZIhvcNAQELBQAwZjESMBAGA1UECgwJeENsb3VkaWZ5
|
||||
MQswCQYDVQQLDAJJVDFDMEEGA1UEAww6cm9vdGNhLmNiZjZjNDE4LTJlMDgtNDBh
|
||||
Yy1hOTAzLTQ4ODM2ZDBkM2UwNy54Y2xvdWRpZnkudGVjaBcNMjUwODE1MDQ1NTM5
|
||||
WhcNMjUwOTE0MDQ1NTM5WjCBnDAlAhRpdV76AZHZZFbplhlSGh50u21vRhcNMjUw
|
||||
ODE1MDQzMTE2WjAlAhQfjxwnfbXM3CNJzNySmXS8q5eVBRcNMjUwODE1MDQ1NTM5
|
||||
WjAlAhQzzbL6Q1Csuosrs1iHc5v9JngA6hcNMjUwODE1MDQ1NTMzWjAlAhRrXgSg
|
||||
jm9wYPQZXpqJwsFBiH74NBcNMjUwODE1MDQzMTQwWqAOMAwwCgYDVR0UBAMCAQIw
|
||||
DQYJKoZIhvcNAQELBQADggEBAFHRUyyCLTmbONJxO9QHpinGKqdivX+wSubX4sMY
|
||||
7P+DCWhWI1hmrs7KAwu265XHavLVS6e3TAxfa48QO/m8/huI8+oNHm2l6SH8r5OR
|
||||
MEtTiyHdGp3lq8Go7vM30DIqeEaNqq6+pf9GPXpT/iVitnZJl+IUaHdet9LEuw4Y
|
||||
gKj6YqWD0w4pAnpCS3+eK1As2vnkOMtz/ublR0uCKvifozhdv1vBzW8m34JVA09D
|
||||
RaNSyj133qx6mDpZaeLiHcOpMGd9M+7niKobnw2PjR8iHY1/fZD3VFAiuayxJW8S
|
||||
ZSGQUjBkeesBQQdwGDh9rWS4adzvAh3qNpo56CxU5eju6Zc=
|
||||
-----END X509 CRL-----
|
||||
@@ -0,0 +1,15 @@
|
||||
-----BEGIN X509 CRL-----
|
||||
MIICXzCCAUcCAQEwDQYJKoZIhvcNAQELBQAwZjESMBAGA1UECgwJeENsb3VkaWZ5
|
||||
MQswCQYDVQQLDAJJVDFDMEEGA1UEAww6cm9vdGNhLmNiZjZjNDE4LTJlMDgtNDBh
|
||||
Yy1hOTAzLTQ4ODM2ZDBkM2UwNy54Y2xvdWRpZnkudGVjaBcNMjUwODE1MDQ1NTM5
|
||||
WhcNMjUwOTE0MDQ1NTM5WjCBnDAlAhRpdV76AZHZZFbplhlSGh50u21vRhcNMjUw
|
||||
ODE1MDQzMTE2WjAlAhQfjxwnfbXM3CNJzNySmXS8q5eVBRcNMjUwODE1MDQ1NTM5
|
||||
WjAlAhQzzbL6Q1Csuosrs1iHc5v9JngA6hcNMjUwODE1MDQ1NTMzWjAlAhRrXgSg
|
||||
jm9wYPQZXpqJwsFBiH74NBcNMjUwODE1MDQzMTQwWqAOMAwwCgYDVR0UBAMCAQIw
|
||||
DQYJKoZIhvcNAQELBQADggEBAFHRUyyCLTmbONJxO9QHpinGKqdivX+wSubX4sMY
|
||||
7P+DCWhWI1hmrs7KAwu265XHavLVS6e3TAxfa48QO/m8/huI8+oNHm2l6SH8r5OR
|
||||
MEtTiyHdGp3lq8Go7vM30DIqeEaNqq6+pf9GPXpT/iVitnZJl+IUaHdet9LEuw4Y
|
||||
gKj6YqWD0w4pAnpCS3+eK1As2vnkOMtz/ublR0uCKvifozhdv1vBzW8m34JVA09D
|
||||
RaNSyj133qx6mDpZaeLiHcOpMGd9M+7niKobnw2PjR8iHY1/fZD3VFAiuayxJW8S
|
||||
ZSGQUjBkeesBQQdwGDh9rWS4adzvAh3qNpo56CxU5eju6Zc=
|
||||
-----END X509 CRL-----
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<script type="module">import { injectIntoGlobalHook } from "/@react-refresh";
|
||||
injectIntoGlobalHook(window);
|
||||
window.$RefreshReg$ = () => {};
|
||||
window.$RefreshSig$ = () => (type) => type;</script>
|
||||
|
||||
<script type="module" src="/@vite/client"></script>
|
||||
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>GPU Cloud - IaaS Portal</title>
|
||||
<meta name="description" content="IaaS Portal for GPU and Docker containers management" />
|
||||
<meta name="author" content="Lovable" />
|
||||
|
||||
<meta property="og:title" content="GPU Cloud - IaaS Portal" />
|
||||
<meta property="og:description" content="IaaS Portal for GPU and Docker containers management" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:image" content="https://lovable.dev/opengraph-image-p98pqg.png" />
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:site" content="@lovable_dev" />
|
||||
<meta name="twitter:image" content="https://lovable.dev/opengraph-image-p98pqg.png" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root"></div><script src="https://cdn.gpteng.co/lovable.js" type="module"></script>
|
||||
<!-- IMPORTANT: DO NOT REMOVE THIS SCRIPT TAG OR THIS VERY COMMENT! -->
|
||||
|
||||
<script type="module" src="/src/main.tsx?t=1755233128858"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -29,7 +29,7 @@ def redis_subscribe(worker_id):
|
||||
f"__keyspace@2__:worker_status_{worker_id}", #TODO - The number 2 here is important, it's the Redis DB number which must align with the resid URL in config.py!
|
||||
f"__keyspace@2__:worker_queue_{worker_id}"
|
||||
]
|
||||
logger.error(f"Subscribed to {channels}")
|
||||
|
||||
try:
|
||||
pubsub.psubscribe(channels)
|
||||
logger.info(f"Subscribed to Redis keyspace events: {channels}")
|
||||
|
||||
Reference in New Issue
Block a user