Skip to content
This repository has been archived by the owner on Apr 7, 2022. It is now read-only.

Commit

Permalink
Merge pull request #1510 from mfalesni/sprout-updates-2
Browse files Browse the repository at this point in the history
A few additional tweaks to Sprout:
  • Loading branch information
Milan Falešník committed Jan 13, 2015
2 parents f3e06f4 + 072c506 commit 192817a
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 46 deletions.
2 changes: 1 addition & 1 deletion fixtures/parallelizer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def __init__(self, config):
# Retrieve and print the template_name for Jenkins to pick up
template_name = request["appliances"][0]["template_name"]
conf.runtime["cfme_data"]["basic_info"]["appliance_template"] = template_name
self.terminal.write("appliance_template={}\n".format(template_name))
self.terminal.write("appliance_template=\"{}\";\n".format(template_name))
self.terminal.write("Parallelized Sprout setup finished.\n")
self.slave_appliances_data = {}
for appliance in request["appliances"]:
Expand Down
2 changes: 1 addition & 1 deletion fixtures/single_appliance_sprout.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def pytest_configure(config, __multicall__):
# Retrieve and print the template_name for Jenkins to pick up
template_name = request["appliances"][0]["template_name"]
conf.runtime["cfme_data"]["basic_info"]["appliance_template"] = template_name
terminal.write("appliance_template={}\n".format(template_name))
terminal.write("appliance_template=\"{}\";\n".format(template_name))
terminal.write("Single appliance Sprout setup finished.\n")
# And set also the appliances_provider
provider = request["appliances"][0]["provider"]
Expand Down
37 changes: 14 additions & 23 deletions sprout/appliances/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
from utils.providers import provider_factory
from utils.version import LooseVersion

from sprout import redis


def logger():
return create_logger("sprout")
Expand Down Expand Up @@ -282,32 +280,20 @@ def unassigned(cls):
return cls.objects.filter(appliance_pool=None, ready=True)

@classmethod
def give_to_pool(cls, pool, time_minutes):
def give_to_pool(cls, pool):
from appliances.tasks import appliance_power_on
n_appliances = 0
appliances = []
with transaction.atomic():
for template in pool.possible_templates:
for appliance in cls.unassigned().filter(
template=template).all()[:pool.total_count - n_appliances]:
new_name = "{}_{}".format(pool.owner.username, appliance.name)
with redis.appliances_ignored_when_renaming(appliance.name, new_name):
appliance.appliance_pool = pool
appliance.datetime_leased = timezone.now()
appliance.leased_until = appliance.datetime_leased + timedelta(
minutes=time_minutes)
if appliance.provider_api.can_rename:
try:
appliance.name = appliance.provider_api.rename_vm(
appliance.name, new_name)
except Exception as e:
logger().exception(
"Exception {}: {}".format(type(e).__name__, str(e)))
appliance.save()
appliance_power_on.delay(appliance.id)
n_appliances += 1
if n_appliances == pool.total_count:
template=template).all()[:pool.total_count - len(appliances)]:
appliance.appliance_pool = pool
appliance.save()
appliance_power_on.delay(appliance.id)
appliances.append(appliance)
if len(appliances) == pool.total_count:
break
return n_appliances
return len(appliances)

@classmethod
def kill(cls, appliance_or_id):
Expand Down Expand Up @@ -498,6 +484,11 @@ def kill(self):
# No appliances, so just delete it
self.delete()

@property
def possible_other_owners(self):
"""Returns a list of User objects that can own this pool instead of original owner"""
return type(self.owner).objects.exclude(pk=self.owner.pk)

def __repr__(self):
return "<AppliancePool id: {}, group: {}, total_count: {}>".format(
self.id, self.group.id, self.total_count)
Expand Down
36 changes: 35 additions & 1 deletion sprout/appliances/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ def request_appliance_pool(appliance_pool_id, time_minutes):
then if there is need to spin up another appliances, it spins them up via clone_template_to_pool
task."""
pool = AppliancePool.objects.get(id=appliance_pool_id)
n = Appliance.give_to_pool(pool, time_minutes)
n = Appliance.give_to_pool(pool)
for i in range(pool.total_count - n):
tpls = pool.possible_provisioning_templates
if tpls:
Expand All @@ -402,6 +402,7 @@ def apply_lease_times_after_pool_fulfilled(self, appliance_pool_id, time_minutes
if pool.fulfilled:
for appliance in pool.appliances:
apply_lease_times.delay(appliance.id, time_minutes)
pool_appliances_prefix_with_owner.delay(pool.id)
else:
self.retry(args=(appliance_pool_id, time_minutes), countdown=30, max_retries=50)

Expand Down Expand Up @@ -892,3 +893,36 @@ def anyvm_suspend(self, provider, vm):
def anyvm_delete(self, provider, vm):
provider = provider_factory(provider)
provider.delete_vm(vm)


@logged_task(bind=True)
def appliance_rename(self, appliance_id, new_name):
try:
appliance = Appliance.objects.get(id=appliance_id)
except ObjectDoesNotExist:
return
if appliance.name == new_name:
return
with redis.appliances_ignored_when_renaming(appliance.name, new_name):
appliance.name = appliance.provider_api.rename_vm(appliance.name, new_name)
appliance.save()


@logged_task(bind=True)
def pool_appliances_prefix_with_owner(self, pool_id):
with transaction.atomic():
try:
appliance_pool = AppliancePool.objects.get(id=pool_id)
except ObjectDoesNotExist:
return
appliances = [
appliance
for appliance
in appliance_pool.appliances
if (not appliance.name.startswith(appliance_pool.owner.username))
and appliance.provider_api.can_rename
]
for appliance in appliances:
appliance_rename.apply_async(
countdown=10, # To prevent clogging with the transaction.atomic
args=(appliance.id, "{}_{}".format(appliance_pool.owner.username, appliance.name)))
22 changes: 16 additions & 6 deletions sprout/appliances/templates/appliances/my_appliances.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,17 @@ <h2>Listing and operation of your appliances</h2>
<div class="btn-toolbar" role="toolbar" aria-label="Appliance operations">
<div class="btn-group" role="group" aria-label="Power operations">
{% if appliance.can_launch %}
<a href="{% url 'appliances.views.start_appliance' appliance.id %}" class="btn btn-success btn-xs"><span class="glyphicon glyphicon-off"></span> Launch</a>
<a href="{% url 'appliances.views.start_appliance' appliance.id %}" class="btn btn-success btn-xs" onclick="return confirm('Are you sure?')"><span class="glyphicon glyphicon-off"></span> Launch</a>
{% endif %}
{% if appliance.can_stop %}
<a href="{% url 'appliances.views.stop_appliance' appliance.id %}" class="btn btn-danger btn-xs"><span class="glyphicon glyphicon-off"></span> Stop</a>
<a href="{% url 'appliances.views.stop_appliance' appliance.id %}" class="btn btn-danger btn-xs" onclick="return confirm('Are you sure?')"><span class="glyphicon glyphicon-off"></span> Stop</a>
{% endif %}
{% if appliance.can_suspend %}
<a href="{% url 'appliances.views.suspend_appliance' appliance.id %}" class="btn btn-warning btn-xs"><span class="glyphicon glyphicon-pause"></span> Suspend</a>
<a href="{% url 'appliances.views.suspend_appliance' appliance.id %}" class="btn btn-warning btn-xs" onclick="return confirm('Are you sure?')"><span class="glyphicon glyphicon-pause"></span> Suspend</a>
{% endif %}
</div>
<div class="btn-group" role="group" aria-label="">
<a href="{% url 'appliances.views.kill_appliance' appliance.id %}" class="btn btn-danger btn-xs"><span class="glyphicon glyphicon-remove-sign"></span> Kill</a>
<a href="{% url 'appliances.views.kill_appliance' appliance.id %}" class="btn btn-danger btn-xs" onclick="return confirm('Are you sure?')"><span class="glyphicon glyphicon-remove-sign"></span> Kill</a>
</div>
<div class="btn-group" role="group" aria-label="...">
{% if appliance.leased_until %}
Expand Down Expand Up @@ -87,7 +87,17 @@ <h2>Listing and operation of your appliances</h2>
{% else %}
<button class="btn btn-danger btn-sm"><span class="glyphicon glyphicon-remove"></span> Not fulfilled</button>
{% endif %}
<a href="{% url 'appliances.views.kill_pool' pool.id %}" class="btn btn-danger btn-sm"><span class="glyphicon glyphicon-trash"></span> Terminate entire pool</a>
<a href="{% url 'appliances.views.kill_pool' pool.id %}" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure?')"><span class="glyphicon glyphicon-trash"></span> Terminate entire pool</a>
<form action="{% url 'appliances.views.transfer_pool' %}" method="POST">
{% csrf_token %}
<input type="hidden" name="pool_id" value="{{ pool.id }}">
<input type="submit" class="btn btn-success btn-sm" value="Transfer ownership to:" onclick="return confirm('Are you sure?')">
<select name="user_id">
{% for user in pool.possible_other_owners %}
<option value="{{ user.id }}">{{ user.first_name }} {{ user.last_name }}</option>
{% endfor %}
</select>
</form>
</td>
</tr>
</tfoot>
Expand Down Expand Up @@ -122,7 +132,7 @@ <h2>Requesting additional pools</h2>
<label for="count">Number of appliances wanted:</label>
<input type="number" class="form-control" id="count" name="count" min="1" value="1">
</div>
<button class="btn btn-primary btn-lg"><span class="glyphicon glyphicon-star-empty"></span> Gimme one!</button>
<button class="btn btn-primary btn-lg" onclick="return confirm('Are you sure?')"><span class="glyphicon glyphicon-star-empty"></span> Gimme one!</button>
</form>
</div>
<script type="text/javascript">
Expand Down
1 change: 0 additions & 1 deletion sprout/appliances/templates/appliances/vms/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ <h3>Do not overload this page (clicking through the tabs without letting the req
{% else %}
<a href="{% url 'vms_at_provider' provider %}" class="btn btn-danger btn-xs"><span class="glyphicon glyphicon-remove"></span> {{ provider }}</a>
{% endif %}
}
</li>
{% endfor %}
</ul>
Expand Down
1 change: 1 addition & 0 deletions sprout/appliances/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
url(r'versions.group$', views.versions_for_group),
url(r'date.version_group$', views.date_for_group_and_version),
url(r'pool.request$', views.request_pool),
url(r'pool.transfer$', views.transfer_pool),
url(r'pool.kill/(?P<pool_id>\d+)$', views.kill_pool),
url(r'vms$', views.vms, name="vms_default"),
url(r'vms.at/(?P<current_provider>[a-z_A-Z0-9-]+)$', views.vms, name="vms_at_provider"),
Expand Down
24 changes: 24 additions & 0 deletions sprout/appliances/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from django.contrib import messages
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from django.db import transaction
from django.http import HttpResponse
from django.shortcuts import render, redirect
from django.template.base import add_to_builtins
Expand Down Expand Up @@ -229,6 +230,29 @@ def request_pool(request):
return go_back_or_home(request)


def transfer_pool(request):
if not request.user.is_authenticated():
return go_home(request)
try:
pool_id = int(request.POST["pool_id"])
user_id = int(request.POST["user_id"])
with transaction.atomic():
pool = AppliancePool.objects.get(id=pool_id)
if pool.owner != request.user:
raise Exception("User does not have the right to change this pool's owner!")
user = User.objects.get(id=user_id)
if user == request.user:
raise Exception("Why changing owner back to yourself? That does not make sense!")
pool.owner = user
pool.save()
except Exception as e:
messages.error(request, "Exception {} happened: {}".format(type(e).__name__, str(e)))
else:
messages.success(request, "Success!")
finally:
return go_back_or_home(request)


def vms(request, current_provider=None):
if not request.user.is_authenticated():
return go_home(request)
Expand Down
16 changes: 3 additions & 13 deletions utils/mgmt_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
from psphere import managedobjects as mobs
from psphere.client import Client
from psphere.errors import ObjectNotFoundError
from suds import WebFault

from cfme import exceptions as cfme_exc
from utils.log import logger
Expand Down Expand Up @@ -691,19 +690,10 @@ def rename_vm(self, vm_name, new_vm_name):
task = vm.Rename_Task(newName=new_vm_name)
try:
wait_for(
lambda: task.info.state == "success",
fail_func=task.update(), delay=0.5, num_sec=15)
lambda: task.info.state == "success" or self.does_vm_exist(new_vm_name),
fail_func=task.update(), delay=0.5, num_sec=120)
except TimedOutError:
if self.does_vm_exist(new_vm_name):
return new_vm_name
else:
task.update()
if task.info.cancellable:
try:
task.CancelTask()
except WebFault:
pass
return vm_name
return vm_name
else:
return new_vm_name

Expand Down

0 comments on commit 192817a

Please sign in to comment.