fold Container object into Instance
diff --git a/xos/cord/admin.py b/xos/cord/admin.py
index 9e7946e..dbe0b35 100644
--- a/xos/cord/admin.py
+++ b/xos/cord/admin.py
@@ -1,7 +1,6 @@
from django.contrib import admin
from cord.models import *
-from core.models import Container
from django import forms
from django.utils.safestring import mark_safe
from django.contrib.auth.admin import UserAdmin
@@ -160,7 +159,6 @@
bbs_account = forms.CharField(required=False)
creator = forms.ModelChoiceField(queryset=User.objects.all())
instance = forms.ModelChoiceField(queryset=Instance.objects.all(),required=False)
- container = forms.ModelChoiceField(queryset=Container.objects.all(),required=False)
use_cobm = forms.BooleanField(required=False)
last_ansible_hash = forms.CharField(required=False)
@@ -173,7 +171,6 @@
self.fields['bbs_account'].initial = self.instance.bbs_account
self.fields['creator'].initial = self.instance.creator
self.fields['instance'].initial = self.instance.instance
- self.fields['container'].initial = self.instance.container
self.fields['use_cobm'].initial = self.instance.use_cobm
self.fields['last_ansible_hash'].initial = self.instance.last_ansible_hash
if (not self.instance) or (not self.instance.pk):
@@ -188,7 +185,6 @@
self.instance.creator = self.cleaned_data.get("creator")
self.instance.instance = self.cleaned_data.get("instance")
self.instance.last_ansible_hash = self.cleaned_data.get("last_ansible_hash")
- self.instance.container = self.cleaned_data.get("container")
self.instance.use_cobm = self.cleaned_data.get("use_cobm")
return super(VCPETenantForm, self).save(commit=commit)
@@ -199,7 +195,7 @@
list_display = ('backend_status_icon', 'id', 'subscriber_tenant' )
list_display_links = ('backend_status_icon', 'id')
fieldsets = [ (None, {'fields': ['backend_status_text', 'kind', 'provider_service', 'subscriber_tenant', 'service_specific_id', # 'service_specific_attribute',
- 'bbs_account', 'creator', 'use_cobm', 'instance', 'container', 'last_ansible_hash'],
+ 'bbs_account', 'creator', 'use_cobm', 'instance', 'last_ansible_hash'],
'classes':['suit-tab suit-tab-general']})]
readonly_fields = ('backend_status_text', 'service_specific_attribute', 'bbs_account')
form = VCPETenantForm
diff --git a/xos/core/admin.py b/xos/core/admin.py
index 317c6a5..aaa72cb 100644
--- a/xos/core/admin.py
+++ b/xos/core/admin.py
@@ -1203,7 +1203,7 @@
class ImageAdmin(XOSBaseAdmin):
fieldsets = [('Image Details',
- {'fields': ['backend_status_text', 'name', 'disk_format', 'container_format'],
+ {'fields': ['backend_status_text', 'name', 'kind', 'disk_format', 'container_format'],
'classes': ['suit-tab suit-tab-general']})
]
readonly_fields = ('backend_status_text', )
@@ -1214,7 +1214,7 @@
user_readonly_fields = ['name', 'disk_format', 'container_format']
- list_display = ['backend_status_icon', 'name']
+ list_display = ['backend_status_icon', 'name', 'kind']
list_display_links = ('backend_status_icon', 'name', )
class NodeForm(forms.ModelForm):
@@ -1282,10 +1282,10 @@
class InstanceAdmin(XOSBaseAdmin):
form = InstanceForm
fieldsets = [
- ('Instance Details', {'fields': ['backend_status_text', 'slice', 'deployment', 'flavor', 'image', 'node', 'all_ips_string', 'instance_id', 'instance_name', 'ssh_command'], 'classes': ['suit-tab suit-tab-general'], })
+ ('Instance Details', {'fields': ['backend_status_text', 'slice', 'deployment', 'isolation', 'flavor', 'image', 'node', 'all_ips_string', 'instance_id', 'instance_name', 'ssh_command'], 'classes': ['suit-tab suit-tab-general'], })
]
readonly_fields = ('backend_status_text', 'ssh_command', 'all_ips_string')
- list_display = ['backend_status_icon', 'all_ips_string', 'instance_id', 'instance_name', 'slice', 'flavor', 'image', 'node', 'deployment']
+ list_display = ['backend_status_icon', 'all_ips_string', 'instance_id', 'instance_name', 'isolation', 'slice', 'flavor', 'image', 'node', 'deployment']
list_display_links = ('backend_status_icon', 'all_ips_string', 'instance_id', )
suit_form_tabs =(('general', 'Instance Details'), ('ports', 'Ports'))
@@ -1372,38 +1372,38 @@
# obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
# obj.delete()
-class ContainerPortInline(XOSTabularInline):
- fields = ['backend_status_icon', 'network', 'container', 'ip', 'mac', 'segmentation_id']
- readonly_fields = ("backend_status_icon", "ip", "mac", "segmentation_id")
- model = Port
- selflink_fieldname = "network"
- extra = 0
- verbose_name_plural = "Ports"
- verbose_name = "Port"
- suit_classes = 'suit-tab suit-tab-ports'
+#class ContainerPortInline(XOSTabularInline):
+# fields = ['backend_status_icon', 'network', 'container', 'ip', 'mac', 'segmentation_id']
+# readonly_fields = ("backend_status_icon", "ip", "mac", "segmentation_id")
+# model = Port
+# selflink_fieldname = "network"
+# extra = 0
+# verbose_name_plural = "Ports"
+# verbose_name = "Port"
+# suit_classes = 'suit-tab suit-tab-ports'
-class ContainerAdmin(XOSBaseAdmin):
- fieldsets = [
- ('Container Details', {'fields': ['backend_status_text', 'slice', 'node', 'docker_image', 'volumes', 'no_sync'], 'classes': ['suit-tab suit-tab-general'], })
- ]
- readonly_fields = ('backend_status_text', )
- list_display = ['backend_status_icon', 'id']
- list_display_links = ('backend_status_icon', 'id', )
-
- suit_form_tabs =(('general', 'Container Details'), ('ports', 'Ports'))
-
- inlines = [TagInline, ContainerPortInline]
-
- def formfield_for_foreignkey(self, db_field, request, **kwargs):
- if db_field.name == 'slice':
- kwargs['queryset'] = Slice.select_by_user(request.user)
-
- return super(ContainerAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
-
- def queryset(self, request):
- # admins can see all instances. Users can only see instances of
- # the slices they belong to.
- return Container.select_by_user(request.user)
+#class ContainerAdmin(XOSBaseAdmin):
+# fieldsets = [
+# ('Container Details', {'fields': ['backend_status_text', 'slice', 'node', 'docker_image', 'volumes', 'no_sync'], 'classes': ['suit-tab suit-tab-general'], })
+# ]
+# readonly_fields = ('backend_status_text', )
+# list_display = ['backend_status_icon', 'id']
+# list_display_links = ('backend_status_icon', 'id', )
+#
+# suit_form_tabs =(('general', 'Container Details'), ('ports', 'Ports'))
+#
+# inlines = [TagInline, ContainerPortInline]
+#
+# def formfield_for_foreignkey(self, db_field, request, **kwargs):
+# if db_field.name == 'slice':
+# kwargs['queryset'] = Slice.select_by_user(request.user)
+#
+# return super(ContainerAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
+#
+# def queryset(self, request):
+# # admins can see all instances. Users can only see instances of
+# # the slices they belong to.
+# return Container.select_by_user(request.user)
class UserCreationForm(forms.ModelForm):
"""A form for creating new users. Includes all the required
@@ -1760,7 +1760,7 @@
readonly_fields = ('backend_status_icon', )
class NetworkPortInline(XOSTabularInline):
- fields = ['backend_status_icon', 'network', 'instance', 'container', 'ip', 'mac']
+ fields = ['backend_status_icon', 'network', 'instance', 'ip', 'mac']
readonly_fields = ("backend_status_icon", "ip", "mac")
model = Port
selflink_fieldname = "instance"
@@ -2057,5 +2057,5 @@
admin.site.register(TenantRoot, TenantRootAdmin)
admin.site.register(TenantRootRole, TenantRootRoleAdmin)
admin.site.register(TenantAttribute, TenantAttributeAdmin)
- admin.site.register(Container, ContainerAdmin)
+# admin.site.register(Container, ContainerAdmin)
diff --git a/xos/core/models/__init__.py b/xos/core/models/__init__.py
index bc97dab..c380e9c 100644
--- a/xos/core/models/__init__.py
+++ b/xos/core/models/__init__.py
@@ -24,7 +24,6 @@
from .node import Node
from .slicetag import SliceTag
from .instance import Instance
-from .container import Container
from .reservation import ReservedResource
from .reservation import Reservation
from .network import Network, NetworkParameterType, NetworkParameter, Port, NetworkTemplate, Router, NetworkSlice, ControllerNetwork
diff --git a/xos/core/models/image.py b/xos/core/models/image.py
index 21d4f23..1a3cbf7 100644
--- a/xos/core/models/image.py
+++ b/xos/core/models/image.py
@@ -7,7 +7,10 @@
# Create your models here.
class Image(PlCoreBase):
+ KIND_CHOICES = (('vm', 'Virtual Machine'), ('container', 'Container'), )
+
name = StrippedCharField(max_length=256, unique=True)
+ kind = models.CharField(null=False, blank=False, max_length=30, choices=KIND_CHOICES, default="vm")
disk_format = StrippedCharField(max_length=256)
container_format = StrippedCharField(max_length=256)
path = StrippedCharField(max_length=256, null=True, blank=True, help_text="Path to image on local disk")
diff --git a/xos/core/models/instance.py b/xos/core/models/instance.py
index 75826f6..af1f965 100644
--- a/xos/core/models/instance.py
+++ b/xos/core/models/instance.py
@@ -80,6 +80,8 @@
# Create your models here.
class Instance(PlCoreBase):
+ ISOLATION_CHOICES = (('vm', 'Virtual Machine'), ('container', 'Container'), )
+
objects = InstanceManager()
deleted_objects = InstanceDeletionManager()
instance_id = StrippedCharField(null=True, blank=True, max_length=200, help_text="Nova instance id")
@@ -97,6 +99,7 @@
flavor = models.ForeignKey(Flavor, help_text="Flavor of this instance", default=get_default_flavor)
tags = generic.GenericRelation(Tag)
userData = models.TextField(blank=True, null=True, help_text="user_data passed to instance during creation")
+ isolation = models.CharField(null=False, blank=False, max_length=30, choices=ISOLATION_CHOICES, default="vm")
def __unicode__(self):
if self.name and Slice.objects.filter(id=self.slice_id) and (self.name != self.slice.name):
diff --git a/xos/core/models/network.py b/xos/core/models/network.py
index 48af5a6..b12068c 100644
--- a/xos/core/models/network.py
+++ b/xos/core/models/network.py
@@ -2,7 +2,7 @@
import socket
import sys
from django.db import models
-from core.models import PlCoreBase, Site, Slice, Instance, Controller, Container
+from core.models import PlCoreBase, Site, Slice, Instance, Controller
from core.models import ControllerLinkManager,ControllerLinkDeletionManager
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
@@ -211,7 +211,6 @@
class Port(PlCoreBase):
network = models.ForeignKey(Network,related_name='links')
instance = models.ForeignKey(Instance, null=True, blank=True, related_name='ports')
- container = models.ForeignKey(Container, null=True, blank=True, related_name='ports')
ip = models.GenericIPAddressField(help_text="Instance ip address", blank=True, null=True)
port_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum port id")
mac = models.CharField(null=True, blank=True, max_length=256, help_text="MAC address associated with this port")
diff --git a/xos/core/models/service.py b/xos/core/models/service.py
index c263bba..9646ce8 100644
--- a/xos/core/models/service.py
+++ b/xos/core/models/service.py
@@ -353,8 +353,8 @@
super(TenantWithContainer, self).__init__(*args, **kwargs)
self.cached_instance=None
self.orig_instance_id = self.get_initial_attribute("instance_id")
- self.cached_container=None
- self.orig_container_id = self.get_initial_attribute("container_id")
+# self.cached_container=None
+# self.orig_container_id = self.get_initial_attribute("container_id")
@property
@@ -381,29 +381,29 @@
self.cached_instance=None
self.set_attribute("instance_id", value)
- @property
- def container(self):
- from core.models import Container
- if getattr(self, "cached_container", None):
- return self.cached_container
- container_id=self.get_attribute("container_id")
- if not container_id:
- return None
- containers=Container.objects.filter(id=container_id)
- if not containers:
- return None
- container=containers[0]
- container.caller = self.creator
- self.cached_container = container
- return container
-
- @container.setter
- def container(self, value):
- if value:
- value = value.id
- if (value != self.get_attribute("container_id", None)):
- self.cached_container=None
- self.set_attribute("container_id", value)
+# @property
+# def container(self):
+# from core.models import Container
+# if getattr(self, "cached_container", None):
+# return self.cached_container
+# container_id=self.get_attribute("container_id")
+# if not container_id:
+# return None
+# containers=Container.objects.filter(id=container_id)
+# if not containers:
+# return None
+# container=containers[0]
+# container.caller = self.creator
+# self.cached_container = container
+# return container
+#
+# @container.setter
+# def container(self, value):
+# if value:
+# value = value.id
+# if (value != self.get_attribute("container_id", None)):
+# self.cached_container=None
+# self.set_attribute("container_id", value)
@property
def creator(self):
@@ -464,13 +464,13 @@
nodes = sorted(nodes, key=lambda node: node.instances.all().count())
return nodes[0]
- def pick_node_for_container_on_metal(self):
- from core.models import Node
- nodes = list(Node.objects.all())
- # TODO: logic to filter nodes by which nodes are up, and which
- # nodes the slice can instantiate on.
- nodes = sorted(nodes, key=lambda node: node.containers.all().count())
- return nodes[0]
+# def pick_node_for_container_on_metal(self):
+# from core.models import Node
+# nodes = list(Node.objects.all())
+# # TODO: logic to filter nodes by which nodes are up, and which
+# # nodes the slice can instantiate on.
+# nodes = sorted(nodes, key=lambda node: node.containers.all().count())
+# return nodes[0]
def manage_container_in_instance(self):
from core.models import Instance, Flavor
@@ -506,72 +506,72 @@
instance.delete()
raise
- def manage_container_on_metal(self):
- from core.models import Container, Instance, Flavor, Port
-
- if self.deleted:
- return
-
- if (self.container is not None):
- self.container.delete()
- self.container = None
-
- if self.container is None:
- if not self.provider_service.slices.count():
- raise XOSConfigurationError("The VCPE service has no slices")
-
- slice = self.provider_service.slices.all()[0]
- node = self.pick_node_for_container_on_metal()
-
- # Our current docker network strategy requires that there be some
- # instance on the server that connects to the networks, so that
- # the containers can piggyback off of that configuration.
- instances = Instance.objects.filter(slice=slice, node=node)
- if not instances:
- flavors = Flavor.objects.filter(name="m1.small")
- if not flavors:
- raise XOSConfigurationError("No m1.small flavor")
-
- node =self.pick_node_for_instance()
- instance = Instance(slice = self.provider_service.slices.all()[0],
- node = node,
- image = self.image,
- creator = self.creator,
- deployment = node.site_deployment.deployment,
- flavor = flavors[0])
- instance.save()
-
- # Now make the container...
- container = Container(slice = slice,
- node = node,
- docker_image = "andybavier/docker-vcpe",
- creator = self.creator,
- no_sync=True)
- container.save()
-
- # ... and add the ports for the container
- # XXX probably should be done in model_policy
- for network in slice.networks.all():
- if (network.name.endswith("-nat")):
- continue
- port = Port(network = network,
- container = container)
- port.save()
-
- container.no_sync = False
- container.save()
-
- try:
- self.container = container
- super(TenantWithContainer, self).save()
- except:
- container.delete()
- raise
+# def manage_container_on_metal(self):
+# from core.models import Container, Instance, Flavor, Port
+#
+# if self.deleted:
+# return
+#
+# if (self.container is not None):
+# self.container.delete()
+# self.container = None
+#
+# if self.container is None:
+# if not self.provider_service.slices.count():
+# raise XOSConfigurationError("The VCPE service has no slices")
+#
+# slice = self.provider_service.slices.all()[0]
+# node = self.pick_node_for_container_on_metal()
+#
+# # Our current docker network strategy requires that there be some
+# # instance on the server that connects to the networks, so that
+# # the containers can piggyback off of that configuration.
+# instances = Instance.objects.filter(slice=slice, node=node)
+# if not instances:
+# flavors = Flavor.objects.filter(name="m1.small")
+# if not flavors:
+# raise XOSConfigurationError("No m1.small flavor")
+#
+# node =self.pick_node_for_instance()
+# instance = Instance(slice = self.provider_service.slices.all()[0],
+# node = node,
+# image = self.image,
+# creator = self.creator,
+# deployment = node.site_deployment.deployment,
+# flavor = flavors[0])
+# instance.save()
+#
+# # Now make the container...
+# container = Container(slice = slice,
+# node = node,
+# docker_image = "andybavier/docker-vcpe",
+# creator = self.creator,
+# no_sync=True)
+# container.save()
+#
+# # ... and add the ports for the container
+# # XXX probably should be done in model_policy
+# for network in slice.networks.all():
+# if (network.name.endswith("-nat")):
+# continue
+# port = Port(network = network,
+# container = container)
+# port.save()
+#
+# container.no_sync = False
+# container.save()
+#
+# try:
+# self.container = container
+# super(TenantWithContainer, self).save()
+# except:
+# container.delete()
+# raise
def manage_container(self):
- if self.use_cobm:
- self.manage_container_on_metal()
- else:
+# if self.use_cobm:
+# self.manage_container_on_metal()
+# else:
self.manage_container_in_instance()
def cleanup_container(self):
@@ -579,10 +579,10 @@
# print "XXX cleanup instance", self.instance
self.instance.delete()
self.instance = None
- if self.container:
- # print "XXX cleanup container", self.container
- self.container.delete()
- self.container = None
+# if self.container:
+# # print "XXX cleanup container", self.container
+# self.container.delete()
+# self.container = None
class CoarseTenant(Tenant):
""" TODO: rename "CoarseTenant" --> "StaticTenant" """
diff --git a/xos/model_policies/model_policy_Image.py b/xos/model_policies/model_policy_Image.py
index 72f76fa..c77d5bb 100644
--- a/xos/model_policies/model_policy_Image.py
+++ b/xos/model_policies/model_policy_Image.py
@@ -2,6 +2,10 @@
from core.models import Controller, ControllerImages, Image
from collections import defaultdict
+ if (image.kind == "container"):
+ # container images do not get instantiated
+ return
+
controller_images = ControllerImages.objects.filter(image=image)
existing_controllers = [cs.controller for cs in controller_images]
diff --git a/xos/openstack_observer/steps/sync_container.py b/xos/openstack_observer/steps/sync_container.py
index 0f5dcc4..ae598b8 100644
--- a/xos/openstack_observer/steps/sync_container.py
+++ b/xos/openstack_observer/steps/sync_container.py
@@ -8,7 +8,7 @@
from xos.config import Config
from observer.syncstep import SyncStep
from observer.ansible import run_template_ssh
-from core.models import Service, Slice, Container
+from core.models import Service, Slice, Instance
from services.onos.models import ONOSService, ONOSApp
from util.logger import Logger, logging
@@ -19,34 +19,28 @@
logger = Logger(level=logging.INFO)
class SyncContainer(SyncStep):
- provides=[Container]
- observes=Container
+ provides=[Instance]
+ observes=Instance
requested_interval=0
template_name = "sync_container.yaml"
def __init__(self, *args, **kwargs):
super(SyncContainer, self).__init__(*args, **kwargs)
-# def fetch_pending(self, deleted):
-# if (not deleted):
-# objs = ONOSService.get_service_objects().filter(Q(enacted__lt=F('updated')) | Q(enacted=None),Q(lazy_blocked=False))
-# else:
-# objs = ONOSService.get_deleted_service_objects()
-#
-# return objs
+ def fetch_pending(self, deletion=False):
+ objs = super(SyncContainer, self).fetch_pending(deletion)
+ objs = [x for x in objs if x.isolation=="container"]
+ return objs
def get_node(self,o):
return o.node
def get_node_key(self, node):
return "/root/setup/node_key"
- #return "/opt/xos/node-key"
def get_instance_port(self, container_port):
- print container_port
- print container_port.network
for p in container_port.network.links.all():
- if (p.instance) and (p.instance.node == container_port.container.node) and (p.mac):
+ if (p.instance) and (p.instance.kind=="vm") and (p.instance.node == container_port.container.node) and (p.mac):
return p
return None
@@ -81,10 +75,10 @@
fields["baremetal_ssh"] = True
fields["instance_name"] = "rootcontext"
fields["container_name"] = "%s-%s" % (o.slice.name, str(o.id))
- fields["docker_image"] = o.docker_image
+ fields["docker_image"] = o.image.name
fields["username"] = "root"
fields["ports"] = self.get_ports(o)
- fields["volumes"] = [x.strip() for x in o.volumes.split(",")]
+ fields["volumes"] = [] # XXX [x.strip() for x in o.volumes.split(",")]
return fields
def sync_fields(self, o, fields):
diff --git a/xos/openstack_observer/steps/sync_instances.py b/xos/openstack_observer/steps/sync_instances.py
index 1209448..1130c24 100644
--- a/xos/openstack_observer/steps/sync_instances.py
+++ b/xos/openstack_observer/steps/sync_instances.py
@@ -22,6 +22,11 @@
observes=Instance
playbook='sync_instances.yaml'
+ def fetch_pending(self, deletion=False):
+ objs = super(SyncInstances, self).fetch_pending(deletion)
+ objs = [x for x in objs if x.isolation=="vm"]
+ return objs
+
def get_userdata(self, instance, pubkeys):
userdata = '#cloud-config\n\nopencloud:\n slicename: "%s"\n hostname: "%s"\n restapi_hostname: "%s"\n restapi_port: "%s"\n' % (instance.slice.name, instance.node.name, RESTAPI_HOSTNAME, str(RESTAPI_PORT))
userdata += 'ssh_authorized_keys:\n'
diff --git a/xos/openstack_observer/steps/sync_ports.py b/xos/openstack_observer/steps/sync_ports.py
index 7b20d29..178fa86 100644
--- a/xos/openstack_observer/steps/sync_ports.py
+++ b/xos/openstack_observer/steps/sync_ports.py
@@ -144,14 +144,11 @@
# For ports that were created by the user, find that ones
# that don't have neutron ports, and create them.
- for port in Port.objects.filter(Q(port_id__isnull=True), Q(instance__isnull=False) | Q(container__isnull=False)):
+ for port in Port.objects.filter(Q(port_id__isnull=True), Q(instance__isnull=False) ):
logger.info("XXX working on port %s" % port)
- if port.instance:
- controller = port.instance.node.site_deployment.controller
- slice = port.instance.slice
- else:
- controller = port.container.node.site_deployment.controller
- slice = port.container.slice
+ controller = port.instance.node.site_deployment.controller
+ slice = port.instance.slice
+
if controller:
cn=port.network.controllernetworks.filter(controller=controller)
if not cn:
diff --git a/xos/openstack_observer/templates/start-container.sh.j2 b/xos/openstack_observer/templates/start-container.sh.j2
index dc3b7cb..86491eb 100644
--- a/xos/openstack_observer/templates/start-container.sh.j2
+++ b/xos/openstack_observer/templates/start-container.sh.j2
@@ -6,11 +6,13 @@
CONTAINER={{ container_name }}
IMAGE={{ docker_image }}
+{% if volumes %}
{% for volume in volumes %}
DEST_DIR=/var/container_volumes/$CONTAINER/{{ volume }}
mkdir -p $DEST_DIR
VOLUME_ARGS="$VOLUME_ARGS -v $DEST_DIR:{{ volume }}"
{% endfor %}
+{% endif %}
docker inspect $CONTAINER > /dev/null 2>&1
if [ "$?" == 1 ]