Compare commits
	
		
			13 Commits
		
	
	
		
			4cf11798aa
			...
			local-qemu
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| f5c079ffc2 | |||
| 0e5dfe6bde | |||
| 2adbb8d94c | |||
| 8446d11720 | |||
| a580b04659 | |||
| 2e6894ad14 | |||
| 2e6c6517f3 | |||
| be6c1b38b7 | |||
| aa8e129913 | |||
| 71e09807a7 | |||
| 4816170c03 | |||
| 6af241e8be | |||
| c8ec53f207 | 
							
								
								
									
										14
									
								
								.drone.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								.drone.yml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					kind: pipeline
 | 
				
			||||||
 | 
					name: publish docker image
 | 
				
			||||||
 | 
					steps:
 | 
				
			||||||
 | 
					  - name: build and publish
 | 
				
			||||||
 | 
					    image: plugins/docker
 | 
				
			||||||
 | 
					    settings:
 | 
				
			||||||
 | 
					      username:
 | 
				
			||||||
 | 
					        from_secret: docker_reg_username_3wc
 | 
				
			||||||
 | 
					      password:
 | 
				
			||||||
 | 
					        from_secret: docker_reg_passwd_3wc
 | 
				
			||||||
 | 
					      repo: 3wordchant/capsul-flask
 | 
				
			||||||
 | 
					      tags: latest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										48
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					FROM python:3.8-alpine as build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN apk add --no-cache \
 | 
				
			||||||
 | 
					    build-base \
 | 
				
			||||||
 | 
					    gcc \
 | 
				
			||||||
 | 
					    gettext \
 | 
				
			||||||
 | 
					    git \
 | 
				
			||||||
 | 
					    jpeg-dev \
 | 
				
			||||||
 | 
					    libffi-dev \
 | 
				
			||||||
 | 
					    libjpeg \
 | 
				
			||||||
 | 
					    musl-dev \
 | 
				
			||||||
 | 
					    postgresql-dev \
 | 
				
			||||||
 | 
					    python3-dev \
 | 
				
			||||||
 | 
					    zlib-dev
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN mkdir -p /app/{code,venv}
 | 
				
			||||||
 | 
					WORKDIR /app/code
 | 
				
			||||||
 | 
					COPY Pipfile Pipfile.lock /app/code/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN python3 -m venv /app/venv
 | 
				
			||||||
 | 
					RUN pip install pipenv setuptools
 | 
				
			||||||
 | 
					ENV PATH="/app/venv/bin:$PATH" VIRTUAL_ENV="/app/venv"
 | 
				
			||||||
 | 
					RUN pip install wheel cppy
 | 
				
			||||||
 | 
					# Install dependencies into the virtual environment with Pipenv
 | 
				
			||||||
 | 
					RUN pipenv install --deploy --verbose
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FROM python:3.8-alpine
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN apk add --no-cache \
 | 
				
			||||||
 | 
					    cloud-utils \
 | 
				
			||||||
 | 
					    libjpeg \
 | 
				
			||||||
 | 
					    libpq \
 | 
				
			||||||
 | 
					    libstdc++ \
 | 
				
			||||||
 | 
					    libvirt-client \
 | 
				
			||||||
 | 
					    openssh-client \
 | 
				
			||||||
 | 
					    virt-install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COPY . /app/code/
 | 
				
			||||||
 | 
					WORKDIR /app/code
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COPY --from=build /app/venv /app/venv
 | 
				
			||||||
 | 
					ENV PATH="/app/venv/bin:$PATH" VIRTUAL_ENV="/app/venv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CMD ["gunicorn", "--bind", "0.0.0.0:5000", "-k", "gevent", "--worker-connections", "1000", "app:app"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VOLUME /app/code
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EXPOSE 5000
 | 
				
			||||||
@ -26,8 +26,24 @@ class StdoutMockFlaskMail:
 | 
				
			|||||||
    def send(self, message: Message):
 | 
					    def send(self, message: Message):
 | 
				
			||||||
      current_app.logger.info(f"Email would have been sent if configured:\n\nto: {','.join(message.recipients)}\nsubject: {message.subject}\nbody:\n\n{message.body}\n\n")
 | 
					      current_app.logger.info(f"Email would have been sent if configured:\n\nto: {','.join(message.recipients)}\nsubject: {message.subject}\nbody:\n\n{message.body}\n\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
load_dotenv(find_dotenv())
 | 
					load_dotenv(find_dotenv())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for var_name in [
 | 
				
			||||||
 | 
					  "SPOKE_HOST_TOKEN", "HUB_TOKEN", "STRIPE_SECRET_KEY",
 | 
				
			||||||
 | 
					  "BTCPAY_PRIVATE_KEY", "MAIL_PASSWORD"
 | 
				
			||||||
 | 
					]:
 | 
				
			||||||
 | 
					  var = os.environ.get(f"{var_name}_FILE")
 | 
				
			||||||
 | 
					  if not var:
 | 
				
			||||||
 | 
					    continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if not os.path.isfile(var):
 | 
				
			||||||
 | 
					    continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  with open(var) as secret_file:
 | 
				
			||||||
 | 
					    os.environ[var_name] = secret_file.read().rstrip('\n')
 | 
				
			||||||
 | 
					  del os.environ[f"{var_name}_FILE"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app = Flask(__name__)
 | 
					app = Flask(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app.config.from_mapping(
 | 
					app.config.from_mapping(
 | 
				
			||||||
 | 
				
			|||||||
@ -215,11 +215,12 @@ class CapsulFlaskHub(VirtualizationInterface):
 | 
				
			|||||||
        # no need to do anything here since if it cant be parsed then generic_operation will handle it.
 | 
					        # no need to do anything here since if it cant be parsed then generic_operation will handle it.
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if error_message != "":
 | 
				
			||||||
 | 
					      raise ValueError(f"create capsul operation {operation_id} on {assigned_hosts} failed with {error_message}")
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
    if number_of_assigned != 1:
 | 
					    if number_of_assigned != 1:
 | 
				
			||||||
      assigned_hosts_string = ", ".join(assigned_hosts)
 | 
					      assigned_hosts_string = ", ".join(assigned_hosts)
 | 
				
			||||||
      raise ValueError(f"expected create capsul operation {operation_id} to be assigned to one host, it was assigned to {number_of_assigned} ({assigned_hosts_string})")
 | 
					      raise ValueError(f"expected create capsul operation {operation_id} to be assigned to one host, it was assigned to {number_of_assigned} ({assigned_hosts_string})")
 | 
				
			||||||
    if error_message != "":
 | 
					 | 
				
			||||||
      raise ValueError(f"create capsul operation {operation_id} on {assigned_hosts_string} failed with {error_message}")
 | 
					 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def destroy(self, email: str, id: str):
 | 
					  def destroy(self, email: str, id: str):
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@
 | 
				
			|||||||
# check available RAM and IPv4s
 | 
					# check available RAM and IPv4s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ram_bytes_to_allocate="$1"
 | 
					ram_bytes_to_allocate="$1"
 | 
				
			||||||
ram_bytes_available=$(grep -E "^(size|memory_available_bytes)" /proc/spl/kstat/zfs/arcstats | awk '{sum+=$3} END {printf "%.0f", sum}')
 | 
					ram_bytes_available="$(($(grep Available /proc/meminfo | grep -o '[0-9]*') * 1024))"
 | 
				
			||||||
ram_bytes_remainder="$((ram_bytes_available - ram_bytes_to_allocate))"
 | 
					ram_bytes_remainder="$((ram_bytes_available - ram_bytes_to_allocate))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if echo "$ram_bytes_to_allocate" | grep -vqE "^[0-9]+$"; then
 | 
					if echo "$ram_bytes_to_allocate" | grep -vqE "^[0-9]+$"; then
 | 
				
			||||||
@ -11,8 +11,8 @@ if echo "$ram_bytes_to_allocate" | grep -vqE "^[0-9]+$"; then
 | 
				
			|||||||
  exit 1
 | 
					  exit 1
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# 20GB
 | 
					# 0.25GB
 | 
				
			||||||
if [ "$ram_bytes_remainder" -le $((20 * 1024 * 1024 * 1024)) ]; then
 | 
					if [ "$ram_bytes_remainder" -le $((1 * 1024 * 1024 * 1024 / 4)) ]; then
 | 
				
			||||||
  echo "VM is requesting more RAM than $(hostname -f) has available."
 | 
					  echo "VM is requesting more RAM than $(hostname -f) has available."
 | 
				
			||||||
  echo "Bytes requested: $ram_bytes_to_allocate"
 | 
					  echo "Bytes requested: $ram_bytes_to_allocate"
 | 
				
			||||||
  echo "Bytes available: $ram_bytes_available"
 | 
					  echo "Bytes available: $ram_bytes_available"
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
vmname="$1"
 | 
					vmname="$1"
 | 
				
			||||||
template_file="/tank/img/$2"
 | 
					template_file="/tank/img/$2"
 | 
				
			||||||
 | 
					qemu_tank_dir="/tank"
 | 
				
			||||||
vcpus="$3"
 | 
					vcpus="$3"
 | 
				
			||||||
memory="$4"
 | 
					memory="$4"
 | 
				
			||||||
pubkeys="$5"
 | 
					pubkeys="$5"
 | 
				
			||||||
@ -50,40 +51,40 @@ if echo "$public_ipv4" | grep -vqE "^[0-9.]+$"; then
 | 
				
			|||||||
  exit 1
 | 
					  exit 1
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
disk="/tank/vm/$vmname.qcow2"
 | 
					disk="$vmname.qcow2"
 | 
				
			||||||
cdrom="/tank/vm/$vmname.iso"
 | 
					cdrom="$vmname.iso"
 | 
				
			||||||
xml="/tank/vm/$vmname.xml"
 | 
					xml="$vmname.xml"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if [ -f /tank/vm/$vmname.qcow2 ]; then
 | 
					if [ -f /tank/vm/$vmname.qcow2 ]; then
 | 
				
			||||||
    echo "Randomly generated name matched an existing VM! Odds are like one in a billion. Buy a lotto ticket."
 | 
					    echo "Randomly generated name matched an existing VM! Odds are like one in a billion. Buy a lotto ticket."
 | 
				
			||||||
    exit 1
 | 
					    exit 1
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cp "$template_file" "$disk"
 | 
					cp "$template_file" "/tank/vm/$disk"
 | 
				
			||||||
cp /tank/config/cyberia-cloudinit.yml /tmp/cloudinit.yml
 | 
					cp /tank/config/cyberia-cloudinit.yml /tmp/cloudinit.yml
 | 
				
			||||||
echo "$pubkeys" | while IFS= read -r line; do
 | 
					echo "$pubkeys" | while IFS= read -r line; do
 | 
				
			||||||
  echo "      - $line" >> /tmp/cloudinit.yml
 | 
					  echo "      - $line" >> /tmp/cloudinit.yml
 | 
				
			||||||
done
 | 
					done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cloud-localds "$cdrom" /tmp/cloudinit.yml
 | 
					cloud-localds "/tank/vm/$cdrom" /tmp/cloudinit.yml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qemu-img resize "$disk" "$root_volume_size"
 | 
					qemu-img resize "/tank/vm/$disk" "$root_volume_size"
 | 
				
			||||||
virt-install \
 | 
					virt-install \
 | 
				
			||||||
    --memory "$memory" \
 | 
					    --memory "$memory" \
 | 
				
			||||||
    --vcpus "$vcpus" \
 | 
					    --vcpus "$vcpus" \
 | 
				
			||||||
    --name "$vmname" \
 | 
					    --name "$vmname" \
 | 
				
			||||||
    --disk "$disk",bus=virtio \
 | 
					    --disk "$qemu_tank_dir/vm/$disk",bus=virtio \
 | 
				
			||||||
    --disk "$cdrom",device=cdrom \
 | 
					    --disk "$qemu_tank_dir/vm/$cdrom",device=cdrom \
 | 
				
			||||||
    --os-type Linux \
 | 
					    --os-type Linux \
 | 
				
			||||||
    --os-variant generic \
 | 
					    --os-variant generic \
 | 
				
			||||||
    --virt-type kvm \
 | 
					    --virt-type kvm \
 | 
				
			||||||
    --graphics vnc,listen=127.0.0.1 \
 | 
					    --graphics vnc,listen=127.0.0.1 \
 | 
				
			||||||
    --network network=$network_name,filterref=clean-traffic,model=virtio \
 | 
					    --network network=$network_name,model=virtio \
 | 
				
			||||||
    --import \
 | 
					    --import \
 | 
				
			||||||
    --print-xml > "$xml"
 | 
					    --print-xml > "/tank/vm/$xml"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
chmod 0600 "$xml" "$disk" "$cdrom"
 | 
					chmod 0600 "/tank/vm/$xml" "/tank/vm/$disk" "/tank/vm/$cdrom"
 | 
				
			||||||
virsh define "$xml"
 | 
					virsh define "/tank/vm/$xml"
 | 
				
			||||||
virsh start "$vmname"
 | 
					virsh start "$vmname"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
echo "success"
 | 
					echo "success"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										38
									
								
								docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					version: "3.8"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					services:
 | 
				
			||||||
 | 
					  app:
 | 
				
			||||||
 | 
					    image: 3wordchant/capsul-flask:latest
 | 
				
			||||||
 | 
					    build: .
 | 
				
			||||||
 | 
					    volumes:
 | 
				
			||||||
 | 
					      - "./:/app/code"
 | 
				
			||||||
 | 
					      - "../tank:/tank"
 | 
				
			||||||
 | 
					      - "/var/run/libvirt/libvirt-sock:/var/run/libvirt/libvirt-sock"
 | 
				
			||||||
 | 
					    depends_on:
 | 
				
			||||||
 | 
					      - db
 | 
				
			||||||
 | 
					    ports:
 | 
				
			||||||
 | 
					      - "5000:5000"
 | 
				
			||||||
 | 
					    environment:
 | 
				
			||||||
 | 
					      - "POSTGRES_CONNECTION_PARAMETERS=host=db port=5432 user=capsul password=capsul dbname=capsul"
 | 
				
			||||||
 | 
					      - SPOKE_MODEL=shell-scripts
 | 
				
			||||||
 | 
					        #- FLASK_DEBUG=1
 | 
				
			||||||
 | 
					      - BASE_URL=http://localhost:5000
 | 
				
			||||||
 | 
					      - ADMIN_PANEL_ALLOW_EMAIL_ADDRESSES=3wc.capsul@doesthisthing.work
 | 
				
			||||||
 | 
					      - VIRSH_DEFAULT_CONNECT_URI=qemu:///system
 | 
				
			||||||
 | 
					    # The image uses gunicorn by default, let's override it with Flask's
 | 
				
			||||||
 | 
					    # built-in development server
 | 
				
			||||||
 | 
					    command: ["flask", "run", "-h", "0.0.0.0", "-p", "5000"]
 | 
				
			||||||
 | 
					    devices:
 | 
				
			||||||
 | 
					      - "/dev/kvm:/dev/kvm"
 | 
				
			||||||
 | 
					  db:
 | 
				
			||||||
 | 
					    image: "postgres:9.6.5-alpine"
 | 
				
			||||||
 | 
					    volumes:
 | 
				
			||||||
 | 
					      - "postgres:/var/lib/postgresql/data"
 | 
				
			||||||
 | 
					    environment:
 | 
				
			||||||
 | 
					      POSTGRES_USER: capsul
 | 
				
			||||||
 | 
					      POSTGRES_PASSWORD: capsul
 | 
				
			||||||
 | 
					      POSTGRES_DB: capsul
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					volumes:
 | 
				
			||||||
 | 
					  postgres:
 | 
				
			||||||
		Reference in New Issue
	
	Block a user