from celery.decorators import periodic_task
from celery.task.schedules import crontab
from django.conf import settings
from django.utils import timezone
from openstack_auth.utils import fix_auth_url_version
from keystoneauth1.identity import v3
from keystoneauth1 import session
from vm.models import Lease
from vm.models.vm_lease import VmLease


def get_projects():
    from keystoneclient.v3 import client

    auth = v3.Password(
        auth_url=fix_auth_url_version(settings.OPENSTACK_KEYSTONE_URL),
        user_id=settings.OPENSTACK_CIRCLE_USERID,
        password=settings.OPENSTACK_CIRCLE_PASSWORD,
    )
    sess = session.Session(auth=auth, verify=False)
    keystone = client.Client(session=sess, interface=settings.OPENSTACK_INTERFACE)

    return keystone.projects.list(
        domain=settings.OPENSTACK_CIRCLE_DOMAIN_ID,
        user=settings.OPENSTACK_CIRCLE_USERID
    )


def get_project_client(project):
    from novaclient import client

    auth = v3.Password(
        auth_url=fix_auth_url_version(settings.OPENSTACK_KEYSTONE_URL),
        user_id=settings.OPENSTACK_CIRCLE_USERID,
        password=settings.OPENSTACK_CIRCLE_PASSWORD,
        project_id=project.id,
    )
    sess = session.Session(auth=auth, verify=False)
    return client.Client("2.0", session=sess)


def handle_suspend(client, server, lease):
    now = timezone.now()
    if now > lease.time_of_suspend and server.status == 'ACTIVE':
        if lease.suspend_done:
            lease.clean().save()
        else:
            client.servers.suspend(server)
            lease.suspend_done = True
            lease.save()


def handle_destroy(client, server, lease):
    now = timezone.now()
    if now > lease.time_of_delete:
        client.servers.delete(server)


@periodic_task(run_every=crontab(hour="*", minute="*", day_of_week="*"))
def check_lease_expiration():
    projects = get_projects()
    for project in projects:
        client = get_project_client(project)
        servers = client.servers.list()
        for server in servers:
            lease = VmLease.get_or_create_lease(server.id)
            handle_suspend(client, server, lease)
            handle_destroy(client, server, lease)
