cleanup, fix instance sync
diff --git a/xos/synchronizers/base/backend.py.bak b/xos/synchronizers/base/backend.py.bak
deleted file mode 100644
index 6e46b85..0000000
--- a/xos/synchronizers/base/backend.py.bak
+++ /dev/null
@@ -1,34 +0,0 @@
-import threading
-import time
-from observer.event_loop import XOSObserver
-from observer.event_manager import EventListener
-from util.logger import Logger, logging
-from model_policy import run_policy
-from xos.config import Config
-
-logger = Logger(level=logging.INFO)
-
-class Backend:
-
- def run(self):
- # start the openstack observer
- observer = XOSObserver()
- observer_thread = threading.Thread(target=observer.run)
- observer_thread.start()
-
- # start model policies thread
- observer_name = getattr(Config(), "observer_name", "")
- if (not observer_name):
- model_policy_thread = threading.Thread(target=run_policy)
- model_policy_thread.start()
- else:
- print "Skipping model policies thread for service observer."
-
- model_policy_thread = threading.Thread(target=run_policy)
- model_policy_thread.start()
-
- # start event listene
- event_manager = EventListener(wake_up=observer.wake_up)
- event_manager_thread = threading.Thread(target=event_manager.run)
- event_manager_thread.start()
-
diff --git a/xos/synchronizers/base/controller.diff b/xos/synchronizers/base/controller.diff
deleted file mode 100644
index 865b83e..0000000
--- a/xos/synchronizers/base/controller.diff
+++ /dev/null
@@ -1,37 +0,0 @@
-diff -up xos/model_policies/model_policy_Controller.py.orig xos/model_policies/model_policy_Controller.py
---- xos/model_policies/model_policy_Controller.py.orig 2015-01-19 20:09:13.000000000 +0000
-+++ xos/model_policies/model_policy_Controller.py 2015-04-07 21:48:51.462215000 +0000
-@@ -1,6 +1,6 @@
-
- def handle(controller):
-- from core.models import Controller, Site, ControllerSite, Slice, ControllerSlice, User, ControllerUser
-+ from core.models import Controller, Site, ControllerSite, Slice, ControllerSlice, User, ControllerUser, ControllerImages, ControllerNetwork
- from collections import defaultdict
-
- # relations for all sites
-@@ -36,3 +36,25 @@ def handle(controller):
- controller not in ctrls_by_user[user]:
- controller_user = ControllerUser(controller=controller, user=user)
- controller_user.save()
-+ # relations for all networks
-+ ctrls_by_network = defaultdict(list)
-+ ctrl_networks = ControllerNetwork.objects.all()
-+ for ctrl_network in ctrl_networks:
-+ ctrls_by_network[ctrl_network.network].append(ctrl_network.controller)
-+ networks = Network.objects.all()
-+ for network in networks:
-+ if network not in ctrls_by_network or \
-+ controller not in ctrls_by_network[network]:
-+ controller_network = ControllerNetwork(controller=controller, network=network)
-+ controller_network.save()
-+ # relations for all images
-+ ctrls_by_image = defaultdict(list)
-+ ctrl_images = ControllerImages.objects.all()
-+ for ctrl_image in ctrl_images:
-+ ctrls_by_image[ctrl_image.image].append(ctrl_image.controller)
-+ images = Image.objects.all()
-+ for image in images:
-+ if image not in ctrls_by_image or \
-+ controller not in ctrls_by_image[image]:
-+ controller_image = ControllerImages(controller=controller, image=image)
-+ controller_image.save()
diff --git a/xos/synchronizers/base/steps/sync_controller_slices.py.bak b/xos/synchronizers/base/steps/sync_controller_slices.py.bak
deleted file mode 100644
index e04da8e..0000000
--- a/xos/synchronizers/base/steps/sync_controller_slices.py.bak
+++ /dev/null
@@ -1,95 +0,0 @@
-import os
-import base64
-from collections import defaultdict
-from netaddr import IPAddress, IPNetwork
-from django.db.models import F, Q
-from xos.config import Config
-from observer.openstacksyncstep import OpenStackSyncStep
-from core.models import *
-from observer.ansible import *
-from openstack.driver import OpenStackDriver
-from util.logger import observer_logger as logger
-import json
-
-class SyncControllerSlices(OpenStackSyncStep):
- provides=[Slice]
- requested_interval=0
- observes=ControllerSlice
-
- def fetch_pending(self, deleted):
- if (deleted):
- return ControllerSlice.deleted_objects.all()
- else:
- return ControllerSlice.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
-
- def sync_record(self, controller_slice):
- logger.info("sync'ing slice controller %s" % controller_slice)
-
- controller_register = json.loads(controller_slice.controller.backend_register)
- if (controller_register.get('disabled',False)):
- raise Exception('Controller %s is disabled'%controller_slice.controller.name)
-
- if not controller_slice.controller.admin_user:
- logger.info("controller %r has no admin_user, skipping" % controller_slice.controller)
- return
-
- controller_users = ControllerUser.objects.filter(user=controller_slice.slice.creator,
- controller=controller_slice.controller)
- if not controller_users:
- raise Exception("slice createor %s has not accout at controller %s" % (controller_slice.slice.creator, controller_slice.controller.name))
- else:
- controller_user = controller_users[0]
- roles = ['Admin']
-
- max_instances=int(controller_slice.slice.max_slivers)
- tenant_fields = {'endpoint':controller_slice.controller.auth_url,
- 'admin_user': controller_slice.controller.admin_user,
- 'admin_password': controller_slice.controller.admin_password,
- 'admin_tenant': 'admin',
- 'tenant': controller_slice.slice.name,
- 'tenant_description': controller_slice.slice.description,
- 'roles':roles,
- 'name':controller_user.user.email,
- 'ansible_tag':'%s@%s'%(controller_slice.slice.name,controller_slice.controller.name),
- 'max_instances':max_instances}
-
- expected_num = len(roles)+1
- res = run_template('sync_controller_slices.yaml', tenant_fields, path='controller_slices', expected_num=expected_num)
- tenant_id = res[0]['id']
- if (not controller_slice.tenant_id):
- try:
- driver = OpenStackDriver().admin_driver(controller=controller_slice.controller)
- driver.shell.nova.quotas.update(tenant_id=controller_slice.tenant_id, instances=int(controller_slice.slice.max_slivers))
- except:
- logger.log_exc('Could not update quota for %s'%controller_slice.slice.name)
- raise Exception('Could not update quota for %s'%controller_slice.slice.name)
-
- controller_slice.tenant_id = tenant_id
- controller_slice.backend_status = '1 - OK'
- controller_slice.save()
-
-
- def delete_record(self, controller_slice):
- controller_register = json.loads(controller_slice.controller.backend_register)
- if (controller_register.get('disabled',False)):
- raise Exception('Controller %s is disabled'%controller_slice.controller.name)
-
- controller_users = ControllerUser.objects.filter(user=controller_slice.slice.creator,
- controller=controller_slice.controller)
- if not controller_users:
- raise Exception("slice createor %s has not accout at controller %s" % (controller_slice.slice.creator, controller_slice.controller.name))
- else:
- controller_user = controller_users[0]
-
- tenant_fields = {'endpoint':controller_slice.controller.auth_url,
- 'admin_user': controller_slice.controller.admin_user,
- 'admin_password': controller_slice.controller.admin_password,
- 'admin_tenant': 'admin',
- 'tenant': controller_slice.slice.name,
- 'tenant_description': controller_slice.slice.description,
- 'name':controller_user.user.email,
- 'ansible_tag':'%s@%s'%(controller_slice.slice.name,controller_slice.controller.name),
- 'delete': True}
-
- expected_num = 1
- res = run_template('sync_controller_slices.yaml', tenant_fields, path='controller_slices', expected_num=expected_num)
diff --git a/xos/synchronizers/base/steps/sync_slivers.py.bak b/xos/synchronizers/base/steps/sync_slivers.py.bak
deleted file mode 100644
index c4240fa..0000000
--- a/xos/synchronizers/base/steps/sync_slivers.py.bak
+++ /dev/null
@@ -1,179 +0,0 @@
-import os
-import base64
-import socket
-from django.db.models import F, Q
-from xos.config import Config
-from xos.settings import RESTAPI_HOSTNAME, RESTAPI_PORT
-from observer.openstacksyncstep import OpenStackSyncStep
-from core.models.sliver import Sliver
-from core.models.slice import Slice, SlicePrivilege, ControllerSlice
-from core.models.network import Network, NetworkSlice, ControllerNetwork
-from observer.ansible import *
-from util.logger import observer_logger as logger
-
-def escape(s):
- s = s.replace('\n',r'\n').replace('"',r'\"')
- return s
-
-class SyncSlivers(OpenStackSyncStep):
- provides=[Sliver]
- requested_interval=0
- observes=Sliver
-
- def get_userdata(self, sliver, pubkeys):
- userdata = '#cloud-config\n\nopencloud:\n slicename: "%s"\n hostname: "%s"\n restapi_hostname: "%s"\n restapi_port: "%s"\n' % (sliver.slice.name, sliver.node.name, RESTAPI_HOSTNAME, str(RESTAPI_PORT))
- userdata += 'ssh_authorized_keys:\n'
- for key in pubkeys:
- userdata += ' - %s\n' % key
- return userdata
-
- def sync_record(self, sliver):
- logger.info("sync'ing sliver:%s slice:%s controller:%s " % (sliver, sliver.slice.name, sliver.node.site_deployment.controller))
- controller_register = json.loads(sliver.node.site_deployment.controller.backend_register)
-
- if (controller_register.get('disabled',False)):
- raise Exception('Controller %s is disabled'%sliver.node.site_deployment.controller.name)
-
- metadata_update = {}
- if (sliver.numberCores):
- metadata_update["cpu_cores"] = str(sliver.numberCores)
-
- for tag in sliver.slice.tags.all():
- if tag.name.startswith("sysctl-"):
- metadata_update[tag.name] = tag.value
-
- # public keys
- slice_memberships = SlicePrivilege.objects.filter(slice=sliver.slice)
- pubkeys = set([sm.user.public_key for sm in slice_memberships if sm.user.public_key])
- if sliver.creator.public_key:
- pubkeys.add(sliver.creator.public_key)
-
- if sliver.slice.creator.public_key:
- pubkeys.add(sliver.slice.creator.public_key)
-
- if sliver.slice.service and sliver.slice.service.public_key:
- pubkeys.add(sliver.slice.service.public_key)
-
- if sliver.slice.service and sliver.slice.service.public_key:
- pubkeys.add(sliver.slice.service.public_key)
-
- nics = []
- networks = [ns.network for ns in NetworkSlice.objects.filter(slice=sliver.slice)]
- controller_networks = ControllerNetwork.objects.filter(network__in=networks,
- controller=sliver.node.site_deployment.controller)
-
- for controller_network in controller_networks:
- if controller_network.network.template.visibility == 'private' and \
- controller_network.network.template.translation == 'none':
- if not controller_network.net_id:
- raise Exception("Private Network %s has no id; Try again later" % controller_network.network.name)
- nics.append(controller_network.net_id)
-
- # now include network template
- network_templates = [network.template.shared_network_name for network in networks \
- if network.template.shared_network_name]
-
- #driver = self.driver.client_driver(caller=sliver.creator, tenant=sliver.slice.name, controller=sliver.controllerNetwork)
- driver = self.driver.admin_driver(tenant='admin', controller=sliver.node.site_deployment.controller)
- nets = driver.shell.quantum.list_networks()['networks']
- for net in nets:
- if net['name'] in network_templates:
- nics.append(net['id'])
-
- if (not nics):
- for net in nets:
- if net['name']=='public':
- nics.append(net['id'])
-
- image_id = None
- controller_images = sliver.image.controllerimages.filter(controller=sliver.node.site_deployment.controller)
- if controller_images:
- image_id = controller_images[0].glance_image_id
- logger.info("using image_id from ControllerImage object: " + str(image_id))
-
- if image_id is None:
- controller_driver = self.driver.admin_driver(controller=sliver.node.site_deployment.controller)
- image_id = None
- images = controller_driver.shell.glanceclient.images.list()
- for image in images:
- if image.name == sliver.image.name or not image_id:
- image_id = image.id
- logger.info("using image_id from glance: " + str(image_id))
-
- try:
- legacy = Config().observer_legacy
- except:
- legacy = False
-
- if (legacy):
- host_filter = sliver.node.name.split('.',1)[0]
- else:
- host_filter = sliver.node.name.strip()
-
- availability_zone_filter = 'nova:%s'%host_filter
- sliver_name = '%s-%d'%(sliver.slice.name,sliver.id)
-
- userData = self.get_userdata(sliver, pubkeys)
- if sliver.userData:
- userData = sliver.userData
-
- controller = sliver.node.site_deployment.controller
- tenant_fields = {'endpoint':controller.auth_url,
- 'admin_user': sliver.creator.email,
- 'admin_password': sliver.creator.remote_password,
- 'admin_tenant': sliver.slice.name,
- 'tenant': sliver.slice.name,
- 'tenant_description': sliver.slice.description,
- 'name':sliver_name,
- 'ansible_tag':sliver_name,
- 'availability_zone': availability_zone_filter,
- 'image_id':image_id,
- 'flavor_id':sliver.flavor.id,
- 'nics':nics,
- 'meta':metadata_update,
- 'user_data':r'%s'%escape(userData)}
-
- res = run_template('sync_slivers.yaml', tenant_fields,path='slivers', expected_num=1)
- sliver_id = res[0]['info']['OS-EXT-SRV-ATTR:instance_name']
- sliver_uuid = res[0]['id']
-
- try:
- hostname = res[0]['info']['OS-EXT-SRV-ATTR:hypervisor_hostname']
- ip = socket.gethostbyname(hostname)
- sliver.ip = ip
- except:
- pass
-
- sliver.instance_id = sliver_id
- sliver.instance_uuid = sliver_uuid
- sliver.instance_name = sliver_name
- sliver.save()
-
- def delete_record(self, sliver):
- controller_register = json.loads(sliver.node.site_deployment.controller.backend_register)
-
- if (controller_register.get('disabled',False)):
- raise Exception('Controller %s is disabled'%sliver.node.site_deployment.controller.name)
-
- sliver_name = '%s-%d'%(sliver.slice.name,sliver.id)
- controller = sliver.node.site_deployment.controller
- tenant_fields = {'endpoint':controller.auth_url,
- 'admin_user': sliver.creator.email,
- 'admin_password': sliver.creator.remote_password,
- 'admin_tenant': sliver.slice.name,
- 'tenant': sliver.slice.name,
- 'tenant_description': sliver.slice.description,
- 'name':sliver_name,
- 'ansible_tag':sliver_name,
- 'delete': True}
-
- try:
- res = run_template('sync_slivers.yaml', tenant_fields,path='slivers', expected_num=1)
- except Exception,e:
- print "Could not sync %s"%sliver_name
- #import traceback
- #traceback.print_exc()
- raise e
-
- if (len(res)!=1):
- raise Exception('Could not delete sliver %s'%sliver.slice.name)
diff --git a/xos/synchronizers/base/syncstep.py.bak b/xos/synchronizers/base/syncstep.py.bak
deleted file mode 100644
index a1f242b..0000000
--- a/xos/synchronizers/base/syncstep.py.bak
+++ /dev/null
@@ -1,203 +0,0 @@
-import os
-import base64
-from datetime import datetime
-from xos.config import Config
-from util.logger import Logger, logging
-from observer.steps import *
-from django.db.models import F, Q
-from core.models import *
-import json
-import time
-import pdb
-import traceback
-
-logger = Logger(level=logging.INFO)
-
-def f7(seq):
- seen = set()
- seen_add = seen.add
- return [ x for x in seq if not (x in seen or seen_add(x))]
-
-def elim_dups(backend_str):
- strs = backend_str.split(' // ')
- strs2 = f7(strs)
- return ' // '.join(strs2)
-
-def deepgetattr(obj, attr):
- return reduce(getattr, attr.split('.'), obj)
-
-
-class InnocuousException(Exception):
- pass
-
-class FailedDependency(Exception):
- pass
-
-class SyncStep(object):
- """ An XOS Sync step.
-
- Attributes:
- psmodel Model name the step synchronizes
- dependencies list of names of models that must be synchronized first if the current model depends on them
- """
- slow=False
- def get_prop(self, prop):
- try:
- sync_config_dir = Config().sync_config_dir
- except:
- sync_config_dir = '/etc/xos/sync'
- prop_config_path = '/'.join(sync_config_dir,self.name,prop)
- return open(prop_config_path).read().rstrip()
-
- def __init__(self, **args):
- """Initialize a sync step
- Keyword arguments:
- name -- Name of the step
- provides -- XOS models sync'd by this step
- """
- dependencies = []
- self.driver = args.get('driver')
- self.error_map = args.get('error_map')
-
- try:
- self.soft_deadline = int(self.get_prop('soft_deadline_seconds'))
- except:
- self.soft_deadline = 5 # 5 seconds
-
- return
-
- def fetch_pending(self, deletion=False):
- # This is the most common implementation of fetch_pending
- # Steps should override it if they have their own logic
- # for figuring out what objects are outstanding.
- main_obj = self.observes
- if (not deletion):
- objs = main_obj.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None),Q(lazy_blocked=False))
- else:
- objs = main_obj.deleted_objects.all()
-
- return objs
- #return Sliver.objects.filter(ip=None)
-
- def check_dependencies(self, obj, failed):
- for dep in self.dependencies:
- peer_name = dep[0].lower() + dep[1:] # django names are camelCased with the first letter lower
-
- try:
- peer_object = deepgetattr(obj, peer_name)
- try:
- peer_objects = peer_object.all()
- except AttributeError:
- peer_objects = [peer_object]
- except:
- peer_objects = []
-
- if (hasattr(obj,'controller')):
- try:
- peer_objects = filter(lambda o:o.controller==obj.controller, peer_objects)
- except AttributeError:
- pass
-
- if (failed in peer_objects):
- if (obj.backend_status!=failed.backend_status):
- obj.backend_status = failed.backend_status
- obj.save(update_fields=['backend_status'])
- raise FailedDependency("Failed dependency for %s:%s peer %s:%s failed %s:%s" % (obj.__class__.__name__, str(getattr(obj,"pk","no_pk")), peer_object.__class__.__name__, str(getattr(peer_object,"pk","no_pk")), failed.__class__.__name__, str(getattr(failed,"pk","no_pk"))))
-
- def call(self, failed=[], deletion=False):
- pending = self.fetch_pending(deletion)
- for o in pending:
- sync_failed = False
- try:
- backoff_disabled = Config().observer_backoff_disabled
- except:
- backoff_disabled = 0
-
- try:
- scratchpad = json.loads(o.backend_register)
- if (scratchpad):
- next_run = scratchpad['next_run']
- if (not backoff_disabled and next_run>time.time()):
- sync_failed = True
- except:
- logger.log_exc("Exception while loading scratchpad")
- pass
-
- if (not sync_failed):
- try:
- for f in failed:
- self.check_dependencies(o,f) # Raises exception if failed
- if (deletion):
- self.delete_record(o)
- o.delete(purge=True)
- else:
- self.sync_record(o)
- o.enacted = datetime.now() # Is this the same timezone? XXX
- scratchpad = {'next_run':0, 'exponent':0}
- o.backend_register = json.dumps(scratchpad)
- o.backend_status = "1 - OK"
- o.save(update_fields=['enacted','backend_status','backend_register'])
- except (InnocuousException,Exception) as e:
- logger.log_exc("sync step failed!")
- try:
- if (o.backend_status.startswith('2 - ')):
- str_e = '%s // %r'%(o.backend_status[4:],e)
- str_e = elim_dups(str_e)
- else:
- str_e = '%r'%e
- except:
- str_e = '%r'%e
-
- try:
- error = self.error_map.map(str_e)
- except:
- error = '2 - %s'%str_e
-
- if isinstance(e, InnocuousException) and not force_error:
- o.backend_status = '1 - %s'%error
- else:
- o.backend_status = '3 - %s'%error
-
- try:
- scratchpad = json.loads(o.backend_register)
- scratchpad['exponent']
- except:
- logger.log_exc("Exception while updating scratchpad")
- scratchpad = {'next_run':0, 'exponent':0}
-
- # Second failure
- if (scratchpad['exponent']):
- delay = scratchpad['exponent'] * 600 # 10 minutes
- if (delay<1440):
- delay = 1440
- scratchpad['next_run'] = time.time() + delay
-
- scratchpad['exponent']+=1
-
- o.backend_register = json.dumps(scratchpad)
-
- # TOFIX:
- # DatabaseError: value too long for type character varying(140)
- if (o.pk):
- try:
- o.backend_status = o.backend_status[:1024]
- o.save(update_fields=['backend_status','backend_register','updated'])
- except:
- print "Could not update backend status field!"
- pass
- sync_failed = True
-
-
- if (sync_failed):
- failed.append(o)
-
- return failed
-
- def sync_record(self, o):
- return
-
- def delete_record(self, o):
- return
-
- def __call__(self, **args):
- return self.call(**args)
diff --git a/xos/synchronizers/openstack/steps/sync_instances.yaml b/xos/synchronizers/openstack/steps/sync_instances.yaml
index 70da32d..476890f 100644
--- a/xos/synchronizers/openstack/steps/sync_instances.yaml
+++ b/xos/synchronizers/openstack/steps/sync_instances.yaml
@@ -19,6 +19,7 @@
timeout: 200
userdata: "{{ user_data }}"
config_drive: yes
+ auto_ip: no
nics:
{% for nic in nics %}
- {{ nic.kind }}-id: {{ nic.value }}