single node,w/o ceph networking implemented
This commit is contained in:
parent
2a66be07a6
commit
da5a600ccb
23 changed files with 866 additions and 147 deletions
|
|
@ -6,22 +6,23 @@
|
|||
|
||||
import errno
|
||||
import os
|
||||
import subprocess
|
||||
import subprocess as sp
|
||||
import tempfile
|
||||
import time
|
||||
import random
|
||||
|
||||
from functools import wraps
|
||||
from os.path import join
|
||||
from typing import Union
|
||||
from decouple import config
|
||||
|
||||
import bitmath
|
||||
import sshtunnel
|
||||
from decouple import config
|
||||
|
||||
import qmp
|
||||
from config import (WITHOUT_CEPH, VM_PREFIX, VM_DIR, IMAGE_DIR,
|
||||
etcd_client, logging, request_pool,
|
||||
running_vms, vm_pool)
|
||||
NETWORK_PREFIX, etcd_client, logging,
|
||||
request_pool, running_vms, vm_pool)
|
||||
from ucloud_common.helpers import get_ipv4_address
|
||||
from ucloud_common.request import RequestEntry, RequestType
|
||||
from ucloud_common.vm import VMEntry, VMStatus
|
||||
|
|
@ -37,13 +38,62 @@ class VM:
|
|||
return "VM({})".format(self.key)
|
||||
|
||||
|
||||
def create_dev(script, _id, dev):
|
||||
assert isinstance(_id, str) and isinstance(dev, str), "_id and dev both must be string"
|
||||
try:
|
||||
output = sp.check_output([script, _id, dev], stderr=sp.PIPE)
|
||||
except Exception as e:
|
||||
print(e.stderr)
|
||||
return None
|
||||
else:
|
||||
return output.decode("utf-8").strip()
|
||||
|
||||
|
||||
def create_vxlan_br_tap(_id, _dev):
|
||||
network_script_base = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'network')
|
||||
vxlan = create_dev(script=os.path.join(network_script_base, 'create-vxlan.sh'),
|
||||
_id=_id, dev=_dev)
|
||||
if vxlan:
|
||||
bridge = create_dev(script=os.path.join(network_script_base, 'create-bridge.sh'),
|
||||
_id=_id, dev=vxlan)
|
||||
if bridge:
|
||||
tap = create_dev(script=os.path.join(network_script_base, 'create-tap.sh'),
|
||||
_id=str(random.randint(1, 100000)), dev=bridge)
|
||||
if tap:
|
||||
return tap
|
||||
|
||||
|
||||
def random_bytes(num=6):
|
||||
return [random.randrange(256) for _ in range(num)]
|
||||
|
||||
|
||||
def generate_mac(uaa=False, multicast=False, oui=None, separator=':', byte_fmt='%02x'):
|
||||
mac = random_bytes()
|
||||
if oui:
|
||||
if type(oui) == str:
|
||||
oui = [int(chunk) for chunk in oui.split(separator)]
|
||||
mac = oui + random_bytes(num=6-len(oui))
|
||||
else:
|
||||
if multicast:
|
||||
mac[0] |= 1 # set bit 0
|
||||
else:
|
||||
mac[0] &= ~1 # clear bit 0
|
||||
if uaa:
|
||||
mac[0] &= ~(1 << 1) # clear bit 1
|
||||
else:
|
||||
mac[0] |= 1 << 1 # set bit 1
|
||||
return separator.join(byte_fmt % b for b in mac)
|
||||
|
||||
|
||||
def get_start_command_args(
|
||||
vm_entry, vnc_sock_filename: str, migration=False, migration_port=4444
|
||||
vm_entry, vnc_sock_filename: str, migration=False, migration_port=4444,
|
||||
):
|
||||
threads_per_core = 1
|
||||
vm_memory = int(bitmath.parse_string(vm_entry.specs["ram"]).to_MB())
|
||||
vm_cpus = int(vm_entry.specs["cpu"])
|
||||
vm_uuid = vm_entry.uuid
|
||||
vm_networks = vm_entry.network
|
||||
|
||||
|
||||
if WITHOUT_CEPH:
|
||||
command = "-drive file={},format=raw,if=virtio,cache=none".format(
|
||||
|
|
@ -62,8 +112,21 @@ def get_start_command_args(
|
|||
|
||||
if migration:
|
||||
command += " -incoming tcp:0:{}".format(migration_port)
|
||||
|
||||
tap = None
|
||||
for network_name in vm_networks:
|
||||
_key = os.path.join(NETWORK_PREFIX, vm_entry.owner, network_name)
|
||||
network = etcd_client.get(_key, value_in_json=True)
|
||||
network_type = network.value["type"]
|
||||
network_id = str(network.value["id"])
|
||||
|
||||
if network_type == "vxlan":
|
||||
tap = create_vxlan_br_tap(network_id, "eno1")
|
||||
|
||||
command += " -netdev tap,id=vmnet{net_id},ifname={tap},script=no,downscript=no"\
|
||||
" -device virtio-net-pci,netdev=vmnet{net_id},mac={mac}"\
|
||||
.format(tap=tap, net_id=network_id, mac=generate_mac())
|
||||
|
||||
command += " -nic tap,model=virtio,mac={}".format(vm_entry.mac)
|
||||
return command.split(" ")
|
||||
|
||||
|
||||
|
|
@ -144,8 +207,8 @@ def create(vm_entry: VMEntry):
|
|||
]
|
||||
|
||||
try:
|
||||
subprocess.check_output(_command_to_create)
|
||||
except subprocess.CalledProcessError as e:
|
||||
sp.check_output(_command_to_create)
|
||||
except sp.CalledProcessError as e:
|
||||
if e.returncode == errno.EEXIST:
|
||||
logging.debug("Image for vm %s exists", vm_entry.uuid)
|
||||
# File Already exists. No Problem Continue
|
||||
|
|
@ -158,7 +221,7 @@ def create(vm_entry: VMEntry):
|
|||
vm_entry.status = "ERROR"
|
||||
else:
|
||||
try:
|
||||
subprocess.check_output(_command_to_extend)
|
||||
sp.check_output(_command_to_extend)
|
||||
except Exception as e:
|
||||
logging.exception(e)
|
||||
else:
|
||||
|
|
@ -199,7 +262,7 @@ def delete(vm_entry):
|
|||
vm_deletion_command = ["rbd", "rm", path_without_protocol]
|
||||
|
||||
try:
|
||||
subprocess.check_output(vm_deletion_command)
|
||||
sp.check_output(vm_deletion_command)
|
||||
except Exception as e:
|
||||
logging.exception(e)
|
||||
else:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue