Exemple #1
0
class CloudStackApiClient:
    _MAX_RETRY = 180
    _ASYNC_INTERVAL = 5
    _INSTANCE = None

    @classmethod
    def get_instance(cls, zoneid, debug=False):
        if cls._INSTANCE is None or ( cls._INSTANCE and cls._INSTANCE.zoneid != zoneid ):
            cls._INSTANCE = cls(zoneid, debug)
        return cls._INSTANCE

    def __init__(self, zoneid, debug):
        self.zoneid = zoneid
        self._debug = debug
        self._config = read_config()
        self._cs = CloudStack(**self._config)
        self._vms = {}
        self._zones = {}
        self._lbs = {}
        self._templates = {}
        self._offerings = {}
        self._networks = {}

    def _print_debug(self, text):
        if self._debug:
            print_debug(text)

    def _dump(self, data=None):
        if self._debug and data:
            print_debug(json.dumps(data, sort_keys=True, indent=2))

    def queryAsyncJobResult(self, jobid):
        for i in range(0, self._MAX_RETRY):
            job = self._cs.queryAsyncJobResult(jobid=jobid)
            if job['jobstatus'] == 1:
                self._dump(job)
                return job
            self._print_debug("wait for job: {} times".format(i + 1))
            time.sleep(self._ASYNC_INTERVAL)
        return None

    def _list(self, api_name, params):
        results = getattr(self._cs, api_name)(**params)
        self._dump(results)
        section = re.sub('^list(.+)s$', lambda m: m.group(1), api_name).lower()
        if section in results:
            return results[section]
        else:
            return []

    def listZones(self):
        return self._list("listZones", { "zoneid": self.zoneid })

    def listLoadBalancerRules(self):
        return self._list("listLoadBalancerRules", { "zoneid": self.zoneid })

    def listNetworks(self):
        return self._list("listNetworks", { "zoneid": self.zoneid })

    def listTemplates(self):
        return self._list("listTemplates", { "zoneid": self.zoneid, "templatefilter": "self" })

    def listServiceOfferings(self):
        return self._list("listServiceOfferings", {})

    def listVirtualMachines(self):
        return self._list("listVirtualMachines", { "zoneid": self.zoneid })

    def deployVirtualMachine(self, name, templateid, offeringid, networkids):
        result = self._cs.deployVirtualMachine(
            zoneid=self.zoneid,
            serviceofferingid=offeringid,
            templateid=templateid,
            networkids=",".join(networkids),
            name=name,
            displayname=name
        )
        job = self.queryAsyncJobResult(result['jobid'])
        if job is None or "jobresult" not in job or "virtualmachine" not in job["jobresult"]:
            return None
        uuid = job['jobresult']['virtualmachine']['id']
        self._vms[uuid] = { 'uuid': uuid, 'name': name }
        return self._vms[uuid]

    def destroyVirtualMachine(self, vmid):
        result = self._cs.destroyVirtualMachine(id=vmid, expunge=True)
        self.queryAsyncJobResult(result['jobid'])

    def assignToLoadBalancerRule(self, lbid, vmid):
        result = self._cs.assignToLoadBalancerRule(id=lbid, virtualmachineids=vmid)
        self.queryAsyncJobResult(result['jobid'])

    def removeFromLoadBalancerRule(self, lbid, vmid):
        result = self._cs.removeFromLoadBalancerRule(id=lbid, virtualmachineids=vmid)
        self.queryAsyncJobResult(result['jobid'])

    def _get_data(self, uuid, cache, method, params, force=False):
        if uuid not in cache or force:
            cache = {}
            for x in getattr(self, method)():
                cache[x['id']] = { p[0]:x[p[1]] for p in params }
        if uuid in cache:
            return cache[uuid]
        return None

    def get_vm_data(self, uuid, force=False):
        return self._get_data(
            uuid=uuid, cache=self._vms, method="listVirtualMachines",
            params=(('name', 'name'), ('uuid', 'id')),
            force=force
        )

    def get_zone_data(self, uuid, force=False):
        return self._get_data(
            uuid=uuid, cache=self._zones, method="listZones",
            params=(('name', 'name'), ('uuid', 'id')),
            force=force
        )

    def get_lb_data(self, uuid, force=False):
        return self._get_data(
            uuid=uuid, cache=self._lbs, method="listLoadBalancerRules",
            params=(('name', 'name'), ('uuid', 'id')),
            force=force
        )

    def get_network_data(self, uuid, force=False):
        return self._get_data(
            uuid=uuid, cache=self._networks, method="listNetworks",
            params=(('name', 'name'), ('uuid', 'id')),
            force=force
        )

    def get_template_data(self, uuid, force=False):
        return self._get_data(
            uuid=uuid, cache=self._templates, method="listTemplates",
            params=(('name', 'name'), ('uuid', 'id')),
            force=force
        )

    def get_offering_data(self, uuid, force=False):
        return self._get_data(
            uuid=uuid, cache=self._offerings, method="listServiceOfferings",
            params=(('name', 'name'), ('uuid', 'id')),
            force=force
        )

    def create_vm(self, name, lbid, templateid, offeringid, networkids):
        vm = self.deployVirtualMachine(name, templateid, offeringid, networkids)
        if vm:
            self.assignToLoadBalancerRule(lbid, vm['uuid'])
        return vm

    def remove_vm(self, vmid, lbid):
        self.removeFromLoadBalancerRule(lbid, vmid)
        self.destroyVirtualMachine(vmid)
Exemple #2
0
class CloudstackCloudAdapter(CloudAdapter):
    def __init__(self):
        super().__init__()
        self.cs = CloudStack(
            endpoint=os.getenv("CLOUDSTACK_API_ENDPOINT"),
            key=os.getenv("CLOUDSTACK_API_KEY"),
            secret=os.getenv("CLOUDSTACK_API_SECRET"),
        )

    def get_service_offering(self, name) -> dict:
        res = self.cs.listServiceOfferings(name=name)
        if not res:
            raise Exception(f"Error: Service offering not found: {name}")
        return res["serviceoffering"][0]

    def get_zone(self, name) -> dict:
        res = self.cs.listZones(name=name)
        if not res:
            raise Exception(f"Error: Zone not found: {name}")
        return res["zone"][0]

    def get_template(self, name) -> dict:
        for tf in ["community", "self"]:
            res = self.cs.listTemplates(name=name, templatefilter=tf)
            if res:
                break
        else:
            raise Exception(f"Error: Template not found: {name}")
        return res["template"][0]

    def get_params(self, name: str) -> dict:
        user_data = self.launch.get("user_data")
        if user_data:
            user_data = base64.b64encode(user_data.encode("utf-8"))

        return {
            "displayname": name,
            "serviceofferingid": self.get_service_offering(
                name=self.launch["service_offering"]
            ).get("id"),
            "affinitygroupnames": self.launch.get("affinity_groups"),
            "securitygroupnames": self.launch.get("security_groups"),
            "templateid": self.get_template(name=self.launch["template"]).get("id"),
            "zoneid": self.get_zone(name=self.launch["zone"]).get("id"),
            "userdata": user_data,
            "keypair": self.launch.get("ssh_key"),
            "group": self.launch.get("group"),
            "rootdisksize": self.launch.get("root_disk_size"),
        }

    def get_current_instances(self) -> List[GenericCloudInstance]:
        filter_tag = f"scalr={self.filter}"
        log.info(f"cloudstack: Querying with filter_tag: {filter_tag}")
        servers = self.cs.listVirtualMachines(
            tags=[
                {
                    "key": "scalr",
                    "value": self.filter,
                }
            ],
            fetch_list=True,
        )
        return [
            GenericCloudInstance(
                id=server["id"],
                name=server["name"],
                status=server["state"].lower(),
            )
            for server in sorted(servers, key=lambda i: i["created"])
        ]

    def ensure_instances_running(self):
        for server in self.get_current_instances():
            log.info(f"cloudstack: Server {server.name} status {server.status}")
            if server.status in ["stopping", "stopped"]:
                self.cs.startVirtualMachine(id=server.id)
                log.info(f"cloudstack: Server {server.name} started")

    def deploy_instance(self, name: str):
        params = self.get_params(name=name)

        tags = self.launch.get("tags", {})
        tags = [
            {
                "key": "scalr",
                "value": self.filter,
            }
        ]
        server = self.cs.deployVirtualMachine(**params)
        self.cs.createTags(
            resourceids=[
                server["id"],
            ],
            resourcetype="UserVm",
            tags=tags,
        )

    def destroy_instance(self, instance: GenericCloudInstance):
        log.info(f"cloudstack: Destroying instance {instance}")
        self.cs.destroyVirtualMachine(id=instance.id)
Exemple #3
0
from cs import CloudStack
import json
import time
import base64

cs = CloudStack(endpoint='https://api.exoscale.ch/v1',
                key='EXOf89522678165c544107d1099',
                secret='JgfCHbX_6cS-I3xoetLEXgHfHlJQe7e2Vlv0SC6XpCc')

print("Deploying Database")
#database
db = cs.deployVirtualMachine(
    serviceofferingid="21624abb-764e-4def-81d7-9fc54b5957fb",
    templateid="2e9be9bf-558d-4a0b-8e6d-03695fe93555",
    zoneid="1128bd56-b4d9-4ac6-a7b9-c715b187ce11",
    keypair="CloudSys",
    securitygroupids=[
        "83e73717-774f-4361-b8c1-a28158dd09c1",
        "21714f20-3e37-4e45-93da-b515ecdfdc03"
    ])
databaseID = db["id"]
jobID = db["jobid"]

#wait for job
while True:
    res = cs.queryAsyncJobResult(jobid=jobID)
    if (res["jobstatus"] == 1):
        break
    time.sleep(1)

allVM = cs.listVirtualMachines()