diff options
-rw-r--r-- | src/api/migrations/0004_snapshotconfig_snapshotrelation.py | 42 | ||||
-rw-r--r-- | src/api/migrations/0005_snapshotconfig_delta.py | 18 | ||||
-rw-r--r-- | src/api/models.py | 103 | ||||
-rw-r--r-- | src/notifier/manager.py | 4 | ||||
-rw-r--r-- | src/static/css/detail_view.css | 33 | ||||
-rw-r--r-- | src/templates/account/booking_list.html | 63 | ||||
-rw-r--r-- | src/templates/account/configuration_list.html | 33 | ||||
-rw-r--r-- | src/templates/account/details.html | 8 | ||||
-rw-r--r-- | src/templates/account/image_list.html | 38 | ||||
-rw-r--r-- | src/templates/account/resource_list.html | 31 | ||||
-rw-r--r-- | src/templates/notifier/email_fulfilled.txt | 6 | ||||
-rw-r--r-- | src/templates/snapshot_workflow/steps/meta.html | 19 | ||||
-rw-r--r-- | src/templates/snapshot_workflow/steps/select_host.html | 65 | ||||
-rw-r--r-- | src/workflow/forms.py | 2 | ||||
-rw-r--r-- | src/workflow/models.py | 10 | ||||
-rw-r--r-- | src/workflow/snapshot_workflow.py | 9 |
16 files changed, 342 insertions, 142 deletions
diff --git a/src/api/migrations/0004_snapshotconfig_snapshotrelation.py b/src/api/migrations/0004_snapshotconfig_snapshotrelation.py new file mode 100644 index 0000000..62bc7af --- /dev/null +++ b/src/api/migrations/0004_snapshotconfig_snapshotrelation.py @@ -0,0 +1,42 @@ +# Generated by Django 2.1 on 2019-01-17 15:54 + +import api.models +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('resource_inventory', '0004_auto_20181017_1532'), + ('api', '0003_auto_20190102_1956'), + ] + + operations = [ + migrations.CreateModel( + name='SnapshotConfig', + fields=[ + ('taskconfig_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='api.TaskConfig')), + ('image', models.IntegerField(null=True)), + ('dashboard_id', models.IntegerField()), + ('host', models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='resource_inventory.Host')), + ], + bases=('api.taskconfig',), + ), + migrations.CreateModel( + name='SnapshotRelation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('status', models.IntegerField(default=0)), + ('task_id', models.CharField(default=api.models.get_task_uuid, max_length=37)), + ('lab_token', models.CharField(default='null', max_length=50)), + ('message', models.TextField(default='')), + ('config', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='api.SnapshotConfig')), + ('job', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Job')), + ('snapshot', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='resource_inventory.Image')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/src/api/migrations/0005_snapshotconfig_delta.py b/src/api/migrations/0005_snapshotconfig_delta.py new file mode 100644 index 0000000..559af90 --- /dev/null +++ b/src/api/migrations/0005_snapshotconfig_delta.py @@ -0,0 +1,18 @@ +# Generated by Django 2.1 on 2019-01-17 16:07 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0004_snapshotconfig_snapshotrelation'), + ] + + operations = [ + migrations.AddField( + model_name='snapshotconfig', + name='delta', + field=models.TextField(default='{}'), + ), + ] diff --git a/src/api/models.py b/src/api/models.py index a1fedfe..e4016aa 100644 --- a/src/api/models.py +++ b/src/api/models.py @@ -214,6 +214,10 @@ class Job(models.Model): if 'network' not in d: d['network'] = {} d['network'][relation.task_id] = relation.config.to_dict() + for relation in SnapshotRelation.objects.filter(job=self): + if 'snapshot' not in d: + d['snapshot'] = {} + d['snapshot'][relation.task_id] = relation.config.to_dict() j['payload'] = d @@ -221,7 +225,13 @@ class Job(models.Model): def get_tasklist(self, status="all"): tasklist = [] - clist = [HostHardwareRelation, AccessRelation, HostNetworkRelation, SoftwareRelation] + clist = [ + HostHardwareRelation, + AccessRelation, + HostNetworkRelation, + SoftwareRelation, + SnapshotRelation + ] if status == "all": for cls in clist: tasklist += list(cls.objects.filter(job=self)) @@ -261,6 +271,10 @@ class Job(models.Model): if 'network' not in d: d['network'] = {} d['network'][relation.task_id] = relation.config.get_delta() + for relation in SnapshotRelation.objects.filter(job=self).filter(status=status): + if 'snapshot' not in d: + d['snapshot'] = {} + d['snapshot'][relation.task_id] = relation.config.get_delta() j['payload'] = d return j @@ -534,6 +548,61 @@ class NetworkConfig(TaskConfig): self.delta = json.dumps(d) +class SnapshotConfig(TaskConfig): + + host = models.ForeignKey(Host, null=True, on_delete=models.DO_NOTHING) + image = models.IntegerField(null=True) + dashboard_id = models.IntegerField() + delta = models.TextField(default="{}") + + def to_dict(self): + d = {} + if self.host: + d['host'] = self.host.labid + if self.image: + d['image'] = self.image + d['dashboard_id'] = self.dashboard_id + return d + + def to_json(self): + return json.dumps(self.to_dict()) + + def get_delta(self): + if not self.delta: + self.delta = self.to_json() + self.save() + d = json.loads(self.delta) + return d + + def clear_delta(self): + self.delta = json.dumps(self.to_dict()) + self.save() + + def set_host(self, host): + self.host = host + d = json.loads(self.delta) + d['host'] = host.labid + self.delta = json.dumps(d) + + def set_image(self, image): + self.image = image + d = json.loads(self.delta) + d['image'] = self.image + self.delta = json.dumps(d) + + def clear_image(self): + self.image = None + d = json.loads(self.delta) + d.pop("image", None) + self.delta = json.dumps(d) + + def set_dashboard_id(self, dash): + self.dashboard_id = dash + d = json.loads(self.delta) + d['dashboard_id'] = self.dashboard_id + self.delta = json.dumps(d) + + def get_task(task_id): for taskclass in [AccessRelation, SoftwareRelation, HostHardwareRelation, HostNetworkRelation]: try: @@ -617,9 +686,41 @@ class HostNetworkRelation(TaskRelation): return super(self.__class__, self).delete(*args, **kwargs) +class SnapshotRelation(TaskRelation): + snapshot = models.ForeignKey(Image, on_delete=models.CASCADE) + config = models.OneToOneField(SnapshotConfig, on_delete=models.CASCADE) + + def type_str(self): + return "Snapshot Task" + + def get_delta(self): + return self.config.to_dict() + + def delete(self, *args, **kwargs): + self.config.delete() + return super(self.__class__, self).delete(*args, **kwargs) + + class JobFactory(object): @classmethod + def makeSnapshotTask(cls, image, booking, host): + relation = SnapshotRelation() + job = Job.objects.get(booking=booking) + config = SnapshotConfig.objects.create(dashboard_id=image.id) + + relation.job = job + relation.config = config + relation.config.save() + relation.config = relation.config + relation.snapshot = image + relation.save() + + config.clear_delta() + config.set_host(host) + config.save() + + @classmethod def makeCompleteJob(cls, booking): hosts = Host.objects.filter(bundle=booking.resource) job = None diff --git a/src/notifier/manager.py b/src/notifier/manager.py index 3361074..f03c2cc 100644 --- a/src/notifier/manager.py +++ b/src/notifier/manager.py @@ -75,7 +75,7 @@ class NotificationHandler(object): if (not hasattr(task, "user")) or task.user == user: user_tasklist.append( { - "title": task.type_str + " Message: ", + "title": task.type_str() + " Message: ", "content": task.message } ) @@ -94,7 +94,7 @@ class NotificationHandler(object): "Your Booking is Ready", message, os.environ.get("DEFAULT_FROM_EMAIL", "opnfv@pharos-dashboard"), - user.userprofile.email_addr, + [user.userprofile.email_addr], fail_silently=False ) diff --git a/src/static/css/detail_view.css b/src/static/css/detail_view.css index 89d0867..69a2643 100644 --- a/src/static/css/detail_view.css +++ b/src/static/css/detail_view.css @@ -1,14 +1,25 @@ -.detail_card { - border: 2px; - border-color: black; - border-radius: 5px; - margin: 5px; - padding: 5px; - box-shadow: 0px 0px 7px 0px rgba(0,0,0,0.75); +.card_container { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-gap: 25px 25px; + justify-items: stretch; +} + +.card_container ul > li { + padding: 7px !important; + font-size: 16px; } -.detail_btn_group { - margin: 3px; - padding: 3px; - padding-bottom: 5px; +.detail_card { + border: 2px; + border-color: black; + border-radius: 5px; + margin: 5px; + padding-left: 25px; + padding-right: 25px; + padding-bottom: 15px; + box-shadow: 0px 0px 7px 0px rgba(0,0,0,0.75); + display: flex; + flex-direction: column; + justify-content: space-between; } diff --git a/src/templates/account/booking_list.html b/src/templates/account/booking_list.html index c7c5e00..9c6f3db 100644 --- a/src/templates/account/booking_list.html +++ b/src/templates/account/booking_list.html @@ -1,52 +1,41 @@ {% extends "base.html" %} {% block content %} -<script> -function edit_booking(pk){ - var csrf = $('input[name="csrfmiddlewaretoken"]').val(); - $.ajax({ - type: "POST", - url: "/", - data: { "target": pk, "create": 0, "csrfmiddlewaretoken": csrf}, - beforeSend: function(request) { - request.setRequestHeader("X-CSFRToken", csrf); - } - }).done(function(){ - window.location.replace("/wf/"); - }).fail(function(){}) -} -</script> <h2>Bookings I Own</h2> + <div class="card_container"> {% for booking in bookings %} <div class="detail_card"> - <ul> - <li>id: {{booking.id}}</li> - <li>lab: {{booking.resource.template.lab.lab_user.username}}</li> - <li>resource: {{booking.resource.template.name}}</li> - <li>start: {{booking.start}}</li> - <li>end: {{booking.end}}</li> - <li>purpose: {{booking.purpose}}</li> - </ul> - <div class="detail_btn_group"> - <button style="display:none" class="btn btn-primary" onclick="edit_booking({{booking.id}});">Edit</button> - <button class="btn btn-primary" onclick="location.href='/booking/detail/{{booking.id}}/';">Details</button> + <div> + <h3>Booking {{booking.id}}</h3> + <ul class="list-group"> + <li class="list-group-item">id: {{booking.id}}</li> + <li class="list-group-item">lab: {{booking.resource.template.lab.lab_user.username}}</li> + <li class="list-group-item">resource: {{booking.resource.template.name}}</li> + <li class="list-group-item">start: {{booking.start}}</li> + <li class="list-group-item">end: {{booking.end}}</li> + <li class="list-group-item">purpose: {{booking.purpose}}</li> + </ul> </div> + <a class="btn btn-primary" href="/booking/detail/{{booking.id}}/">Details</a> </div> {% endfor %} + </div> <h2>Bookings I Collaborate On</h2> + <div class="card_container"> {% for booking in collab_bookings %} <div class="detail_card"> - <ul> - <li>id: {{booking.id}}</li> - <li>lab: {{booking.lab}}</li> - <li>resource: {{booking.resource_name}}</li> - <li>start: {{booking.start}}</li> - <li>end: {{booking.end}}</li> - <li>purpose: {{booking.purpose}}</li> - </ul> - <div class="detail_btn_group"> - <button style="display: none" class="btn btn-primary" disabled=true onclick="edit_booking({{booking.id}});">Edit</button> - <button class="btn btn-primary" onclick="location.href='/booking/detail/{{booking.id}}/';">Details</button> + <div> + <h3>Booking {{booking.id}}</h3> + <ul class="list-group"> + <li class="list-group-item">id: {{booking.id}}</li> + <li class="list-group-item">lab: {{booking.lab}}</li> + <li class="list-group-item">resource: {{booking.resource_name}}</li> + <li class="list-group-item">start: {{booking.start}}</li> + <li class="list-group-item">end: {{booking.end}}</li> + <li class="list-group-item">purpose: {{booking.purpose}}</li> + </ul> </div> + <a class="btn btn-primary" href="/booking/detail/{{booking.id}}/">Details</a> </div> {% endfor %} + </div> {% endblock %} diff --git a/src/templates/account/configuration_list.html b/src/templates/account/configuration_list.html index 9dcec07..14d0472 100644 --- a/src/templates/account/configuration_list.html +++ b/src/templates/account/configuration_list.html @@ -1,31 +1,18 @@ {% extends "base.html" %} {% block content %} -<script> -function edit_configuration(pk){ - var csrf = $('input[name="csrfmiddlewaretoken"]').val(); - $.ajax({ - type: "POST", - url: "/", - data: { "target": pk, "create": 2, "csrfmiddlewaretoken": csrf}, - beforeSend: function(request) { - request.setRequestHeader("X-CSFRToken", csrf); - } - }).done(function(){ - window.location.replace("/wf/"); - }).fail(function(){}); -} -</script> + <div class="card_container"> {% for config in configurations %} <div class="detail_card"> - <ul> - <li>id: {{config.id}}</li> - <li>name: {{config.name}}</li> - <li>description: {{config.description}}</li> - <li>resource: {{config.bundle}}</li> - </ul> - <div class="detail_btn_group"> - <button style="display: none" class="btn btn-primary" onclick="edit_configuration({{config.id}});">Edit</button> + <div> + <h3>Configuration {{config.id}}</h3> + <ul class="list-group"> + <li class="list-group-item">id: {{config.id}}</li> + <li class="list-group-item">name: {{config.name}}</li> + <li class="list-group-item">description: {{config.description}}</li> + <li class="list-group-item">resource: {{config.bundle}}</li> + </ul> </div> </div> {% endfor %} + </div> {% endblock %} diff --git a/src/templates/account/details.html b/src/templates/account/details.html index acf3eb1..3092ad0 100644 --- a/src/templates/account/details.html +++ b/src/templates/account/details.html @@ -2,8 +2,8 @@ {% load staticfiles %} {% block content %} <h1>Account Details</h1> -<a class="btn btn-primary" onclick="location.href = '{% url 'account:my-resources' %}'">My Resources</a> -<a class="btn btn-primary" onclick="location.href = '{% url 'account:my-bookings' %}'">My Bookings</a> -<a class="btn btn-primary" onclick="location.href = '{% url 'account:my-configurations' %}'">My Configurations</a> -<a class="btn btn-primary" onclick="location.href = '{% url 'account:my-images' %}'">My Snapshots</a> +<a class="btn btn-primary" href="{% url 'account:my-resources' %}">My Resources</a> +<a class="btn btn-primary" href="{% url 'account:my-bookings' %}">My Bookings</a> +<a class="btn btn-primary" href="{% url 'account:my-configurations' %}">My Configurations</a> +<a class="btn btn-primary" href="{% url 'account:my-images' %}">My Snapshots</a> {% endblock content %} diff --git a/src/templates/account/image_list.html b/src/templates/account/image_list.html index 72ea1f5..7566a9c 100644 --- a/src/templates/account/image_list.html +++ b/src/templates/account/image_list.html @@ -1,27 +1,37 @@ {% extends "base.html" %} {% block content %} <h2>Images I Own</h2> +<div class="card_container"> {% for image in images %} <div class="detail_card"> - <ul> - <li>id: {{image.id}}</li> - <li>lab: {{image.from_lab.name}}</li> - <li>name: {{image.name}}</li> - <li>description: {{image.description}}</li> - <li>host profile: {{image.host_type.name}}</li> - </ul> + <div> + <h3>Image {{image.id}}</h3> + <ul class="list-group"> + <li class="list-group-item">id: {{image.id}}</li> + <li class="list-group-item">lab: {{image.from_lab.name}}</li> + <li class="list-group-item">name: {{image.name}}</li> + <li class="list-group-item">description: {{image.description}}</li> + <li class="list-group-item">host profile: {{image.host_type.name}}</li> + </ul> + </div> </div> {% endfor %} +</div> <h2>Public Images</h2> +<div class="card_container"> {% for image in public_images %} <div class="detail_card"> - <ul> - <li>id: {{image.id}}</li> - <li>lab: {{image.from_lab.name}}</li> - <li>name: {{image.name}}</li> - <li>description: {{image.description}}</li> - <li>host profile: {{image.host_type.name}}</li> - </ul> + <div> + <h3>Image {{image.id}}</h3> + <ul class="list-group"> + <li class="list-group-item">id: {{image.id}}</li> + <li class="list-group-item">lab: {{image.from_lab.name}}</li> + <li class="list-group-item">name: {{image.name}}</li> + <li class="list-group-item">description: {{image.description}}</li> + <li class="list-group-item">host profile: {{image.host_type.name}}</li> + </ul> + </div> </div> {% endfor %} +</div> {% endblock %} diff --git a/src/templates/account/resource_list.html b/src/templates/account/resource_list.html index 7e4194b..cdacdd6 100644 --- a/src/templates/account/resource_list.html +++ b/src/templates/account/resource_list.html @@ -1,30 +1,17 @@ {% extends "base.html" %} {% block content %} -<script> -function edit_resource(pk){ - var csrf = $('input[name="csrfmiddlewaretoken"]').val(); - $.ajax({ - type: "POST", - url: "/", - data: { "target": pk, "create": 1, "csrfmiddlewaretoken": csrf}, - beforeSend: function(request) { - request.setRequestHeader("X-CSFRToken", csrf); - } - }).done(function(){ - window.location.replace("/wf/"); - }).fail(function(){}); -} -</script> + <div class="card_container"> {% for resource in resources %} <div class="detail_card"> - <ul> - <li>id: {{resource.id}}</li> - <li>name: {{resource.name}}</li> - <li>description: {{resource.description}}</li> - </ul> - <div class="detail_btn_group"> - <button style="display: none" class="btn btn-primary" onclick="edit_resource({{resource.id}});">Edit</button> + <div> + <h3>Resource {{resource.id}}</h3> + <ul class="list-group"> + <li class="list-group-item">id: {{resource.id}}</li> + <li class="list-group-item">name: {{resource.name}}</li> + <li class="list-group-item">description: {{resource.description}}</li> + </ul> </div> </div> {% endfor %} + </div> {% endblock %} diff --git a/src/templates/notifier/email_fulfilled.txt b/src/templates/notifier/email_fulfilled.txt index d473961..65593db 100644 --- a/src/templates/notifier/email_fulfilled.txt +++ b/src/templates/notifier/email_fulfilled.txt @@ -3,9 +3,9 @@ The booking you requested of the OPNFV Lab as a Service has finished deploying and is ready for you to use. The lab that fulfilled your booking request has sent you the following messages: - {% for message in messages %} - {% message.title %} - {% message.content %} + {% for email_message in messages %} + {{ email_message.title }} + {{ email_message.content }} -------------------- {% endfor %} diff --git a/src/templates/snapshot_workflow/steps/meta.html b/src/templates/snapshot_workflow/steps/meta.html index 2e767cc..cc49691 100644 --- a/src/templates/snapshot_workflow/steps/meta.html +++ b/src/templates/snapshot_workflow/steps/meta.html @@ -4,16 +4,21 @@ {% load bootstrap3 %} {% block content %} - - <style> +.meta_container { + padding: 50px; +} </style> - {% bootstrap_form_errors form type='non_fields' %} -<form id="meta_form" action="/wf/workflow/" method="POST" class="form"> -{% csrf_token %} -{{form}} -</form> +<div class="meta_container"> + <form id="meta_form" action="/wf/workflow/" method="POST" class="form"> + {% csrf_token %} + <div class="form-group"> + {% bootstrap_field form.name %} + {% bootstrap_field form.description %} + </div> + </form> +</div> {% endblock content %} {% block onleave %} diff --git a/src/templates/snapshot_workflow/steps/select_host.html b/src/templates/snapshot_workflow/steps/select_host.html index 16dd5d4..27a9238 100644 --- a/src/templates/snapshot_workflow/steps/select_host.html +++ b/src/templates/snapshot_workflow/steps/select_host.html @@ -5,43 +5,73 @@ {% block content %} - <style> .booking { - border-style: solid; + border-style: none; border-color: black; - border-width: 2px; - display: inline-block; - padding: 3px; + border: 2px; + border-radius: 5px; + margin: 20px; + padding-left: 25px; + padding-right: 25px; + padding-bottom: 25px; + box-shadow: 0px 0px 7px 0px rgba(0,0,0,0.75); + transition-property: box-shadow; + transition-duration: 0.1s; + float: left; + } + .booking:hover { + box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.75); + transition-property: box-shadow; + transition-duration: 0.1s; } .host { + cursor: pointer; border-style: solid; border-color: black; border-width: 1px; - margin: 2px; + border-radius: 5px; + margin: 5px; + padding: 5px; + text-align: center; + box-shadow: 0px 0px 2px 0px rgba(0,0,0,0.75); + transition-property: box-shadow; + transition-duration: 0.1s; + } + .host:hover { + box-shadow: 0px 0px 4px 0px rgba(0,0,0,0.75); + transition-property: box-shadow; + transition-duration: 0.1s; + background-color: rgba(144,238,144,0.3); + } + .selected { + background-color: lightgreen !important; + } + .booking_container { + overflow: auto; + padding: 30px; } </style> - {% bootstrap_form_errors form type='non_fields' %} <form id="host_select_form" action="/wf/workflow/" method="POST" class="form"> {% csrf_token %} <input type="hidden" id="hidden_json_input", name="host"/> </form> -<div id="host_select_container"> +<div id="host_select_container" class="booking_container"> </div> <script> var selected_host = null; -var initial = {{chosen|default:'null'}}; +var initial = {{chosen|safe|default:'null'}}; function select(booking_id, host_name){ var input = document.getElementById("hidden_json_input"); input.value = JSON.stringify({"booking": booking_id, "name": host_name}); // clear out and highlist host if(selected_host){ - selected_host.style['background-color'] = "white"; + selected_host.classList.remove("selected"); } selected_host = document.getElementById("booking_" + booking_id + "_host_" + host_name); - selected_host.style['background-color'] = "lightgrey"; + selected_host.classList.add("selected"); } function draw_bookings(){ @@ -53,17 +83,20 @@ function draw_bookings(){ var heading = document.createElement("H3"); heading.appendChild(document.createTextNode("Booking " + booking_id)); booking.appendChild(heading); - var desc = "start: " + booking_hosts[booking_id].start + - " end: " + booking_hosts[booking_id].end + - " purpose: " + booking_hosts[booking_id].purpose; - booking.appendChild(document.createTextNode(desc)); + booking.appendChild(document.createTextNode("start: " + booking_hosts[booking_id].start)); + booking.appendChild(document.createElement("BR")); + booking.appendChild(document.createTextNode("end: " + booking_hosts[booking_id].end)); + booking.appendChild(document.createElement("BR")); + booking.appendChild(document.createTextNode("purpose: " + booking_hosts[booking_id].purpose)); + booking.appendChild(document.createElement("BR")); + booking.appendChild(document.createTextNode("hosts:")); booking.id = "booking_" + booking_id; booking.className = "booking"; var hosts = booking_hosts[booking_id].hosts; for(var i=0; i<hosts.length; i++){ var host = document.createElement("DIV"); host.id = "booking_" + booking_id + "_host_" + hosts[i].name; - host.className = "host"; + host.classList.add("host"); host.appendChild(document.createTextNode(hosts[i].name)); var hostname = hosts[i].name; host.booking = booking_id; diff --git a/src/workflow/forms.py b/src/workflow/forms.py index b8c7f66..726e7dd 100644 --- a/src/workflow/forms.py +++ b/src/workflow/forms.py @@ -461,7 +461,7 @@ class SnapshotHostSelectForm(forms.Form): class SnapshotMetaForm(forms.Form): name = forms.CharField() - description = forms.CharField() + description = forms.CharField(widget=forms.Textarea) class ConfirmationForm(forms.Form): diff --git a/src/workflow/models.py b/src/workflow/models.py index 495ce07..4e79546 100644 --- a/src/workflow/models.py +++ b/src/workflow/models.py @@ -11,6 +11,7 @@ from django.shortcuts import render from django.contrib import messages from django.http import HttpResponse +from django.utils import timezone import yaml import requests @@ -385,6 +386,8 @@ class Repository(): if not booking_id: return "SNAP, No booking ID provided" booking = Booking.objects.get(pk=booking_id) + if booking.start > timezone.now() or booking.end < timezone.now(): + return "Booking is not active" name = self.el.get(self.SNAPSHOT_NAME) if not name: return "SNAP, no name provided" @@ -400,6 +403,13 @@ class Repository(): image.owner = owner image.host_type = host.profile image.save() + try: + current_image = host.config.image + image.os = current_image.os + image.save() + except Exception: + pass + JobFactory.makeSnapshotTask(image, booking, host) def make_generic_resource_bundle(self): owner = self.el[self.SESSION_USER] diff --git a/src/workflow/snapshot_workflow.py b/src/workflow/snapshot_workflow.py index 4ddc397..0d53ed4 100644 --- a/src/workflow/snapshot_workflow.py +++ b/src/workflow/snapshot_workflow.py @@ -87,7 +87,14 @@ class Image_Meta_Step(WorkflowStep): def get_context(self): context = super(Image_Meta_Step, self).get_context() - context['form'] = SnapshotMetaForm() + name = self.repo_get(self.repo.SNAPSHOT_NAME, False) + desc = self.repo_get(self.repo.SNAPSHOT_DESC, False) + form = None + if name and desc: + form = SnapshotMetaForm(initial={"name": name, "description": desc}) + else: + form = SnapshotMetaForm() + context['form'] = form return context def post_render(self, request): |