feat: vm create management command

wip-site
Aravinth Manivannan 2022-06-28 00:57:25 +05:30
parent d84021915f
commit 0606c4ade0
Signed by untrusted user: realaravinth
GPG Key ID: AD9F0F08E855ED88
5 changed files with 232 additions and 19 deletions

View File

@ -1,3 +1,5 @@
from django.contrib import admin
# Register your models here.
from .models import InstanceCreated
admin.site.register(InstanceCreated)

View File

@ -0,0 +1,77 @@
# Create your tests here.
# Copyright © 2022 Aravinth Manivannan <realaravinth@batsense.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import time
import os
from io import StringIO
from urllib.parse import urlparse, urlunparse
import requests
from django.core import mail
from django.contrib.auth import get_user_model
from django.core.management import call_command
from django.urls import reverse
from django.test import TestCase, Client, override_settings
from django.utils.http import urlencode
from django.contrib.auth import authenticate
from django.conf import settings
from accounts.tests import register_util
from dash.models import Instance
from infrastructure.models import InstanceCreated, InstanceConfiguration
class VMCommands(TestCase):
"""
Test command: manage.py create_oidc
"""
def setUp(self):
self.username = "hosteacustomer"
register_util(t=self, username=self.username)
self.vm_name = "MyHosteaVM"
def test_cmd(self):
Application = get_application_model()
stdout = StringIO()
stderr = StringIO()
redirect_uri = "http://example.org"
app_name = "test_cmd_oidc"
self.assertEqual(Instance.objects.filter(name=vm_name).exists(), False)
# username exists
call_command(
"vm", "create", self.vm_name, f"--owner={self.username}", "==flavor=medium"
)
out = stdout.getvalue()
self.assertIn(f"Instance created", out)
instance = Instance.objects.get(name=self.vm_name)
self.assertEqual(instance.owned_by, self.user)
self.assertEqual(
instance.configuration_id, InstanceConfiguration.objects.get(name="s1-4")
)
instance_created = InstanceCreated.objects.get(name=self.vm_name)
self.assertEqual(instance_created.instance, instance)
self.assertEqual(instance_created.created, True)

View File

@ -0,0 +1,103 @@
# Copyright © 2022 Aravinth Manivannan <realaravinth@batsense.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.core.management.base import BaseCommand
from django.core.exceptions import ValidationError
from django.conf import settings
from django.contrib.auth import get_user_model
from oauth2_provider.models import get_application_model
from oauth2_provider.generators import generate_client_id, generate_client_secret
from dash.models import InstanceConfiguration, Instance
from dash.utils import create_instance
from infrastructure.utils import create_vm_if_not_exists
class Command(BaseCommand):
help = "Get user ID from username"
action_key = "action"
vm_name_key = "vm_name"
flavor_key = "flavor"
owner_key = "owner"
def add_arguments(self, parser):
parser.add_argument(
self.action_key,
type=str,
help="VM action: create/delete",
)
parser.add_argument(
self.vm_name_key,
type=str,
help="Name of the VM",
)
parser.add_argument(
f"--{self.owner_key}",
type=str,
help="Owner username",
)
parser.add_argument(
f"--{self.flavor_key}",
type=str,
help="Name of the VM flavor: small, medium, large",
)
def create_vm(self, *args, **options):
owner = options[self.owner_key]
flavor = options[self.flavor_key]
vm_name = options[self.vm_name_key]
if flavor == "small":
size = "s1-2"
elif flavor == "medium":
size = "s1-4"
elif flavor == "large":
size = "s1-8"
else:
self.stdout.write(self.style.WARN("flavour no match"))
size = flavor
user = get_user_model().objects.get(username=owner)
instance = create_instance(vm_name=vm_name, configuration_name=size, user=user)
create_instance
create_vm_if_not_exists(instance)
print("Instance created")
def delete_vm(self, *args, **options):
create_vm
def handle(self, *args, **options):
for i in [self.action_key, self.vm_name_key]:
if i not in options:
self.stdout.write(self.style.ERROR(f"Please provide {i}"))
return
if options[self.action_key] == "create":
for i in [self.flavor_key, self.owner_key]:
if i not in options:
self.stdout.write(self.style.ERROR(f"Please provide {i}"))
return
self.create_vm(*args, **options)
elif options[self.action_key] == "delete":
self.delete_vm(*args, **options)
else:
self.stdout.write(
self.style.ERROR("Unknown action: {options[self.action_key]}")
)
return

View File

@ -12,18 +12,26 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from pathlib import Path
import shutil
import time
import os
import requests
from io import StringIO
from urllib.parse import urlparse, urlunparse
from pathlib import Path
from django.test import TestCase, Client, override_settings
from django.conf import settings
from django.core.management import call_command
from git import Repo
from dash.models import Instance
from .utils import Infra
from dash.models import Instance, InstanceConfiguration
from accounts.tests import register_util, login_util
from dash.tests import create_configurations, create_instance_util
from infrastructure.models import InstanceCreated
from .utils import Infra
def custom_config(test_name: str):
@ -99,9 +107,7 @@ class InfraUtilTest(TestCase):
c = custom_config(test_name="test_add_vm--get-head")
path = c["INFRA"]["HOSTEA_REPO"]["PATH"]
repo = Repo.clone_from(
conf["REMOTE"], path, env={"GIT_SSH_COMMAND": infra.ssh_cmd}
)
repo = Repo.clone_from(conf["REMOTE"], path, env=infra.env)
self.assertEqual(repo.head.commit.hexsha == after_add, True)
before_rm = infra.repo.head.commit.hexsha
@ -111,3 +117,26 @@ class InfraUtilTest(TestCase):
repo.git.pull()
self.assertEqual(repo.head.commit.hexsha == after_rm, True)
vm_name = "cmd_vm"
stdout = StringIO()
stderr = StringIO()
self.assertEqual(Instance.objects.filter(name=vm_name).exists(), False)
# username exists
call_command(
"vm", "create", vm_name, f"--owner={self.username}", "--flavor=medium"
)
out = stdout.getvalue()
instance = Instance.objects.get(name=vm_name)
self.assertEqual(instance.owned_by, self.user)
self.assertEqual(
instance.configuration_id, InstanceConfiguration.objects.get(name="s1-4")
)
instance_created = InstanceCreated.objects.get(instance=instance)
self.assertEqual(instance_created.instance, instance)
self.assertEqual(instance_created.created, True)

View File

@ -30,10 +30,10 @@ from .models import InstanceCreated
def create_vm_if_not_exists(instance: Instance):
infra = Infra()
if not InstanceCreated.objects.filter(instance=instance).exists():
instance = InstanceCreated.objects.create(instance=instance, created=True)
instance.save()
gitea_password = infra.add_vm(instance=instance)
instance.gitea_password = gitea_password
instance = InstanceCreated.objects.create(
instance=instance, gitea_password=gitea_password, created=True
)
instance.save()
@ -48,13 +48,12 @@ class Infra:
if not self.repo_path.exists():
os.makedirs(self.repo_path)
self.ssh_cmd = f"/usr/bin/ssh -oStrictHostKeyChecking=no -i {conf['SSH_KEY']}"
ssh_cmd = f"/usr/bin/ssh -oStrictHostKeyChecking=no -i {conf['SSH_KEY']}"
self.env = {"GIT_SSH_COMMAND": ssh_cmd}
try:
self.repo = Repo(path=self.repo_path)
except InvalidGitRepositoryError:
self.repo = Repo.clone_from(
conf["REMOTE"], self.repo_path, env={"GIT_SSH_COMMAND": self.ssh_cmd}
)
self.repo = Repo.clone_from(conf["REMOTE"], self.repo_path, env=self.env)
def _host_vars_dir(self, subdomain: str) -> Path:
"""
@ -120,13 +119,16 @@ class Infra:
author="Dashboard Bot <bot@dashboard.hostea.org>",
)
def _pull(self):
self.repo.git.pull(env=self.env, rebase="true")
def add_vm(self, instance: Instance) -> str:
"""
Add new VM to infrastructure repository
The gitea user password is returned
"""
self.repo.git.pull()
self._pull()
subdomain = instance.name
host_vars_dir = self._host_vars_dir(subdomain)
@ -205,14 +207,14 @@ class Infra:
)
self._commit(action="add", subdomain=subdomain)
self.repo.git.push()
self.repo.git.push(env=self.env)
return gitea_password
def remove_vm(self, instance: Instance):
"""
Remove a VM from infrastructure repository
"""
self.repo.git.pull()
self._pull()
subdomain = instance.name
host_vars_dir = self._host_vars_dir(subdomain)
@ -229,4 +231,4 @@ class Infra:
),
)
self._commit(action="rm", subdomain=subdomain)
self.repo.git.push()
self.repo.git.push(env=self.env)