[asterisk-scf-commits] asterisk-scf/integration/servicelocatormdns.git branch "master" created.
Commits to the Asterisk SCF project code repositories
asterisk-scf-commits at lists.digium.com
Mon Jun 20 08:12:56 CDT 2011
branch "master" has been created
at 601635f2f988733179708d63fb3159cd9a700502 (commit)
- Log -----------------------------------------------------------------
commit 601635f2f988733179708d63fb3159cd9a700502
Author: Joshua Colp <jcolp at digium.com>
Date: Sun Jun 12 13:05:57 2011 -0300
Add README.txt file.
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..8a21070
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,43 @@
+ServiceLocatorMDNS is a set of python scripts which use multicast DNS to provide location
+information for the service locator. This allows you to use the service locator without
+having to configure your Asterisk SCF components with the IP address and port of it. It
+will be automatically found using multicast DNS.
+
+1. Pre-requisites
+
+The pybonjour module is used as the interface between multicast DNS and python. It must be
+installed for the ServiceLocatorMDNS python scripts to operate. It can be found at
+http://code.google.com/p/pybonjour/
+
+2. Installation on server side
+
+The machine running the service locator must also be running the ServiceLocatorPublisher.py
+python script. This publishes the location information using multicast DNS. There is no
+configuration required for this script.
+
+3. Installation on client side
+
+Each machine running an Asterisk SCF component must also be running the ServiceLocatorAgent.py
+python script. This finds the service locator using multicast DNS and makes it available using
+an Ice locator implementation. There is no configuration required for this script.
+
+4. Asterisk SCF component configuration
+
+Each running component must have the following Ice configuration properties:
+
+Ice.Default.Locator=AsteriskSCF/Locator:default -p 4433 -h localhost
+ServiceLocatorProxy=AsteriskSCF/LocatorService
+ServiceLocatorManagementProxy=AsteriskSCF/LocatorServiceManagement
+
+These tell the Ice client where it can find the locally running ServiceLocatorAgent.py python
+script and how to request the service locator from it.
+
+* Note that while it is possible to run a single ServiceLocatorAgent.py python script for a group
+of machines this defeats the purpose of using multicast DNS since the IP address and port of the
+machine running the python script would have to be put into the configuration file.
+
+5. Done!
+
+This is all that is required to use multicast DNS for finding the service locator. While there is
+some initial configuration required there are no hardcoded IP addresses or ports for the service
+locator.
commit 1ae5d2948731eb9631fe729e639fa07a3934ce4c
Author: Joshua Colp <jcolp at digium.com>
Date: Sat Jun 11 20:08:15 2011 -0300
Turn TODO list into a future improvement list after some research.
diff --git a/ServiceLocatorAgent.py b/ServiceLocatorAgent.py
index 86f24c4..3f8c231 100644
--- a/ServiceLocatorAgent.py
+++ b/ServiceLocatorAgent.py
@@ -20,8 +20,9 @@
import select, sys, traceback, Ice, socket, pybonjour
-# TODO:
-# 1. Remove addresses from proxy when service goes away
+# Future improvements:
+# 1. When a service goes away remove any endpoints, for now we rely on the client failing to connect and trying
+# a different one. Since this is TCP it happens quick enough.
# Ice communicator used for Ice stuff
communicator = None
@@ -202,7 +203,8 @@ def BonjourBrowseCallback(sdRef, flags, interfaceIndex, errorCode, serviceName,
if errorCode != pybonjour.kDNSServiceErr_NoError:
return
- # If a service was removed we should take away their endpoints
+ # If a service was removed we should take away their endpoints, but for now just rely on the client
+ # trying a different endpoint
if not (flags & pybonjour.kDNSServiceFlagsAdd):
return
commit 3a07d00317ab891c19dd9827e522ac845a44fb82
Author: Joshua Colp <jcolp at digium.com>
Date: Sat Jun 11 20:03:30 2011 -0300
Fix a bug where the port would be the value received for the last service for all, and not just the last service.
diff --git a/ServiceLocatorAgent.py b/ServiceLocatorAgent.py
index 86105fb..86f24c4 100644
--- a/ServiceLocatorAgent.py
+++ b/ServiceLocatorAgent.py
@@ -21,8 +21,7 @@
import select, sys, traceback, Ice, socket, pybonjour
# TODO:
-# 1. Remove proxies when a publisher gets shutdown
-# 2. Determine if other transports should be supported other than TCP
+# 1. Remove addresses from proxy when service goes away
# Ice communicator used for Ice stuff
communicator = None
@@ -45,6 +44,12 @@ BonjourServiceName = None
# Addresses for the current service, used internally by callbacks
BonjourAddresses = [ ]
+# Endpoints for service locator proxy
+BonjourLocatorEndpoints = [ ]
+
+# Endpoints for service locator management proxy
+BonjourManagementEndpoints = [ ]
+
# Whether a DNS request has completed or not, used internally by callbacks
BonjourDNSRequestCompleted = False
@@ -108,6 +113,8 @@ def BonjourResolveCallback(sdRef, flags, interfaceIndex, errorCode, fullname,
hosttarget, port, txtRecord):
global communicator
global BonjourAddresses
+ global BonjourLocatorEndpoints
+ global BonjourManagementEndpoints
global BonjourServiceName
global BonjourDNSRecordCompleted
global ServiceLocatorProxy
@@ -118,6 +125,9 @@ def BonjourResolveCallback(sdRef, flags, interfaceIndex, errorCode, fullname,
if errorCode != pybonjour.kDNSServiceErr_NoError:
return
+ # Clear any existing addresses
+ BonjourAddresses = [ ]
+
# Query for A records
BonjourDNSRecordCompleted = False
query = pybonjour.DNSServiceQueryRecord(interfaceIndex = interfaceIndex,
@@ -154,15 +164,25 @@ def BonjourResolveCallback(sdRef, flags, interfaceIndex, errorCode, fullname,
# Remove duplicates from addresses
BonjourAddresses = list(set(BonjourAddresses))
- # But if we have any addresses we need to create the proper proxy
- if BonjourAddresses:
- # We only support TCP transport right now
- transport = 'tcp'
+ # We only support TCP transport right now
+ transport = 'tcp'
- # Construct portion for endpoints
- endpoints = ''.join([':{0} -h {1} -p {2}'.format(transport, address, port) for address in BonjourAddresses])
+ # Add new addresses to all addresses
+ for address in BonjourAddresses:
+ endpoint = ':{0} -h {1} -p {2}'.format(transport, address, port)
+ if BonjourServiceName == 'ServiceLocator':
+ BonjourLocatorEndpoints.append(endpoint)
+ BonjourLocatorEndpoints = list(set(BonjourLocatorEndpoints))
+ BonjourAllAddresses = BonjourLocatorEndpoints
+ elif BonjourServiceName == 'ServiceLocatorManagement':
+ BonjourManagementEndpoints.append(endpoint)
+ BonjourManagementEndpoints = list(set(BonjourManagementEndpoints))
+ BonjourAllAddresses = BonjourManagementEndpoints
+ # But if we have any addresses we need to create the proper proxy
+ if BonjourAllAddresses:
proxy = None
+ endpoints = ''.join(['{0}'.format(address) for address in BonjourAllAddresses])
if BonjourServiceName == 'ServiceLocator':
proxy = communicator.stringToProxy('LocatorService{0}'.format(endpoints))
ServiceLocatorProxy = proxy
commit bf40f4fc6f749256467f9effd773f74aa5a73b60
Author: Joshua Colp <jcolp at digium.com>
Date: Sat Jun 11 19:48:17 2011 -0300
Support multiple services by returning a proxy with multiple endpoints.
diff --git a/ServiceLocatorAgent.py b/ServiceLocatorAgent.py
index 7d5c8e4..86105fb 100644
--- a/ServiceLocatorAgent.py
+++ b/ServiceLocatorAgent.py
@@ -21,9 +21,8 @@
import select, sys, traceback, Ice, socket, pybonjour
# TODO:
-# 2. Remove proxies when a publisher gets shutdown
-# 4. Determine if other transports should be supported other than TCP
-# 5. Determine how to handle multiple responses
+# 1. Remove proxies when a publisher gets shutdown
+# 2. Determine if other transports should be supported other than TCP
# Ice communicator used for Ice stuff
communicator = None
@@ -119,9 +118,6 @@ def BonjourResolveCallback(sdRef, flags, interfaceIndex, errorCode, fullname,
if errorCode != pybonjour.kDNSServiceErr_NoError:
return
- # Clear out any old addresses
- BonjourAddresses = [ ]
-
# Query for A records
BonjourDNSRecordCompleted = False
query = pybonjour.DNSServiceQueryRecord(interfaceIndex = interfaceIndex,
@@ -155,6 +151,9 @@ def BonjourResolveCallback(sdRef, flags, interfaceIndex, errorCode, fullname,
# Yeah request completed
BonjourDNSRequestCompleted = True
+ # Remove duplicates from addresses
+ BonjourAddresses = list(set(BonjourAddresses))
+
# But if we have any addresses we need to create the proper proxy
if BonjourAddresses:
# We only support TCP transport right now
commit 0109bc69cb5c09dbd5881846ddbed339c82f9b03
Author: Joshua Colp <jcolp at digium.com>
Date: Sat Jun 11 19:47:35 2011 -0300
Fix port for service locator management.
diff --git a/ServiceLocatorPublisher.py b/ServiceLocatorPublisher.py
index b5ca659..4ef95ac 100644
--- a/ServiceLocatorPublisher.py
+++ b/ServiceLocatorPublisher.py
@@ -28,7 +28,7 @@ bonjourServiceLocator = pybonjour.DNSServiceRegister(name = 'ServiceLocator',
# Register the service locator management interface with Bonjour
bonjourServiceLocatorManagement = pybonjour.DNSServiceRegister(name = 'ServiceLocatorManagement',
regtype = '_asteriskscf._tcp',
- port = 4411)
+ port = 4422)
# Go into a loop processing results that may come in
while True:
commit ef0b4112e78b182f9285962ba19be7ff6adb2025
Author: Joshua Colp <jcolp at digium.com>
Date: Tue Jun 7 09:55:58 2011 -0300
Add python scripts that provide a mechanism for automatic service locator discovery using Bonjour.
diff --git a/ServiceLocatorAgent.py b/ServiceLocatorAgent.py
new file mode 100644
index 0000000..7d5c8e4
--- /dev/null
+++ b/ServiceLocatorAgent.py
@@ -0,0 +1,262 @@
+#!/usr/bin/env python
+
+#
+# Asterisk SCF -- An open-source communications framework.
+#
+# Copyright (C) 2011, Digium, Inc.
+#
+# See http://www.asterisk.org for more information about
+# the Asterisk SCF project. Please do not directly contact
+# any of the maintainers of this project for assistance;
+# the project provides a web site, mailing lists and IRC
+# channels for your use.
+#
+# This program is free software, distributed under the terms of
+# the GNU General Public License Version 2. See the LICENSE.txt file
+# at the top of the source tree.
+#
+
+# Service Locator Bonjour Receiver
+
+import select, sys, traceback, Ice, socket, pybonjour
+
+# TODO:
+# 2. Remove proxies when a publisher gets shutdown
+# 4. Determine if other transports should be supported other than TCP
+# 5. Determine how to handle multiple responses
+
+# Ice communicator used for Ice stuff
+communicator = None
+
+# Proxy to the service locator interface, may contain multiple endpoints
+ServiceLocatorProxy = None
+
+# Proxy to the service locator management interface, may contain multiple endpoints
+ServiceLocatorManagementProxy = None
+
+# Timeout used for Bonjour requests
+BonjourTimeout = 5
+
+# Timeout used for DNS record queries
+BonjourDNSTimeout = 5
+
+# Service name currently returned, used internally by callbacks
+BonjourServiceName = None
+
+# Addresses for the current service, used internally by callbacks
+BonjourAddresses = [ ]
+
+# Whether a DNS request has completed or not, used internally by callbacks
+BonjourDNSRequestCompleted = False
+
+# Whether a DNS record lookup has completed or not, used internally by callbacks
+BonjourDNSRecordCompleted = False
+
+# We provide an implementation of the locator interface so anyone can ask us to do a lookup
+# for the service locator and service locator management proxy.
+class LocatorI(Ice.Locator):
+ def findObjectById_async(self, cb, id, current):
+ # If this is not for the AsteriskSCF category we certainly know nothing
+ if id.category != 'AsteriskSCF':
+ cb.ice_response(None)
+
+ # Determine which proxy to return
+ if id.name == 'LocatorService':
+ cb.ice_response(ServiceLocatorProxy)
+ elif id.name == 'LocatorServiceManagement':
+ cb.ice_response(ServiceLocatorManagementProxy)
+
+ # Anything else we don't know anything about
+ cb.ice_response(None)
+
+ def findAdapterById_async(self, cb, id, current):
+ # We do not support anything to do with object adapters
+ cb.ice_response(None)
+
+ def getRegistry_async(self, cb, current):
+ # We do not support the registry
+ cb.ice_response(None)
+
+# Callback called when we have an A record for a service
+def BonjourARecordCallback(sdRef, flags, interfaceIndex, errorCode, fullname,
+ rrtype, rrclass, rdata, ttl):
+ global BonjourAddresses
+ global BonjourDNSRecordCompleted
+
+ # If an error occurred just go on our way
+ if errorCode != pybonjour.kDNSServiceErr_NoError:
+ return
+
+ BonjourAddresses.append(socket.inet_ntop(socket.AF_INET, rdata))
+ BonjourDNSRecordCompleted = True
+
+# Callback called when we have an AAAA record for a service
+def BonjourAAAARecordCallback(sdRef, flags, interfaceIndex, errorCode, fullname,
+ rrtype, rrclass, rdata, ttl):
+ global BonjourAddresses
+ global BonjourDNSRecordCompleted
+
+ # If an error occurred just go on our way
+ if errorCode != pybonjour.kDNSServiceErr_NoError:
+ return
+
+ BonjourAddresses.append('\"{0}\"'.format(socket.inet_ntop(socket.AF_INET6, rdata)))
+ BonjourDNSRecordCompleted = True
+
+
+# Callback called when a resolve request on a browse response is completed
+def BonjourResolveCallback(sdRef, flags, interfaceIndex, errorCode, fullname,
+ hosttarget, port, txtRecord):
+ global communicator
+ global BonjourAddresses
+ global BonjourServiceName
+ global BonjourDNSRecordCompleted
+ global ServiceLocatorProxy
+ global ServiceLocatorManagementProxy
+ global BonjourDNSRequestCompleted
+
+ # If an error occurred just go on our way
+ if errorCode != pybonjour.kDNSServiceErr_NoError:
+ return
+
+ # Clear out any old addresses
+ BonjourAddresses = [ ]
+
+ # Query for A records
+ BonjourDNSRecordCompleted = False
+ query = pybonjour.DNSServiceQueryRecord(interfaceIndex = interfaceIndex,
+ fullname = hosttarget,
+ rrtype = pybonjour.kDNSServiceType_A,
+ callBack = BonjourARecordCallback)
+
+ while BonjourDNSRecordCompleted == False:
+ ready = select.select([query], [], [], BonjourDNSTimeout)
+ if query not in ready[0]:
+ break
+ pybonjour.DNSServiceProcessResult(query)
+
+ query.close()
+
+ # Query for AAAA records
+ BonjourDNSRecordCompleted = False
+ query = pybonjour.DNSServiceQueryRecord(interfaceIndex = interfaceIndex,
+ fullname = hosttarget,
+ rrtype = pybonjour.kDNSServiceType_AAAA,
+ callBack = BonjourAAAARecordCallback)
+
+ while BonjourDNSRecordCompleted == False:
+ ready = select.select([query], [], [], BonjourDNSTimeout)
+ if query not in ready[0]:
+ break
+ pybonjour.DNSServiceProcessResult(query)
+
+ query.close()
+
+ # Yeah request completed
+ BonjourDNSRequestCompleted = True
+
+ # But if we have any addresses we need to create the proper proxy
+ if BonjourAddresses:
+ # We only support TCP transport right now
+ transport = 'tcp'
+
+ # Construct portion for endpoints
+ endpoints = ''.join([':{0} -h {1} -p {2}'.format(transport, address, port) for address in BonjourAddresses])
+
+ proxy = None
+ if BonjourServiceName == 'ServiceLocator':
+ proxy = communicator.stringToProxy('LocatorService{0}'.format(endpoints))
+ ServiceLocatorProxy = proxy
+ elif BonjourServiceName == 'ServiceLocatorManagement':
+ proxy = communicator.stringToProxy('LocatorServiceManagement{0}'.format(endpoints))
+ ServiceLocatorManagementProxy = proxy
+
+ print 'Discovered and created proxy: ', proxy
+
+# Callback called when we have a browse response for an Asterisk SCF publisher
+def BonjourBrowseCallback(sdRef, flags, interfaceIndex, errorCode, serviceName,
+ regtype, replyDomain):
+ global BonjourServiceName
+ global BonjourDNSRequestCompleted
+
+ # If an error occurred just go on our way
+ if errorCode != pybonjour.kDNSServiceErr_NoError:
+ return
+
+ # If a service was removed we should take away their endpoints
+ if not (flags & pybonjour.kDNSServiceFlagsAdd):
+ return
+
+ # If this is an unsupported service ignore it
+ if serviceName != 'ServiceLocator':
+ if serviceName != 'ServiceLocatorManagement':
+ return
+
+ BonjourServiceName = serviceName
+
+ # If a service was added we need to resolve, get their records, and construct a proxy
+ resolve = pybonjour.DNSServiceResolve(0,
+ interfaceIndex,
+ serviceName,
+ regtype,
+ replyDomain,
+ BonjourResolveCallback)
+
+ BonjourDNSRequestCompleted = False
+
+ while BonjourDNSRequestCompleted == False:
+ ready = select.select([resolve], [], [], BonjourDNSTimeout)
+
+ # If the resolve attempt timed out abort entirely
+ if resolve not in ready[0]:
+ break
+
+ # Otherwise process the result
+ pybonjour.DNSServiceProcessResult(resolve)
+
+ # Now that we have completed resolving we can move on to the next service
+ resolve.close()
+
+# Ensure some values are properly initialized
+browse = None
+status = 0
+adapter = None
+
+try:
+ # Before we start making ourselves available at all go ahead and start trying
+ # to find the service locator information using Bonjour
+ browse = pybonjour.DNSServiceBrowse(regtype = "_asteriskscf._tcp",
+ callBack = BonjourBrowseCallback)
+
+ # Now initialize Ice
+ communicator = Ice.initialize(sys.argv)
+
+ # Port 4433 has been set aside by us for this purpose, thus why it is hardcoded
+ adapter = communicator.createObjectAdapterWithEndpoints(
+ "LocatorAdapter", "default -h localhost -p 4433")
+
+ # Create an instance of our locator implementation and make it available
+ object = LocatorI()
+ adapter.add(object, communicator.stringToIdentity("AsteriskSCF/Locator"))
+ adapter.activate()
+
+ # Now that the Ice portion is done start processing Bonjour results
+ while True:
+ ready = select.select([browse], [], [], BonjourTimeout)
+ if browse in ready[0]:
+ pybonjour.DNSServiceProcessResult(browse)
+except:
+ status = 1
+
+if browse:
+ browse.close()
+
+if communicator:
+ # Clean up
+ try:
+ communicator.destroy()
+ except:
+ traceback.print_exc()
+ status = 1
+
+sys.exit(status)
diff --git a/ServiceLocatorPublisher.py b/ServiceLocatorPublisher.py
new file mode 100644
index 0000000..b5ca659
--- /dev/null
+++ b/ServiceLocatorPublisher.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+
+#
+# Asterisk SCF -- An open-source communications framework.
+#
+# Copyright (C) 2011, Digium, Inc.
+#
+# See http://www.asterisk.org for more information about
+# the Asterisk SCF project. Please do not directly contact
+# any of the maintainers of this project for assistance;
+# the project provides a web site, mailing lists and IRC
+# channels for your use.
+#
+# This program is free software, distributed under the terms of
+# the GNU General Public License Version 2. See the LICENSE.txt file
+# at the top of the source tree.
+#
+
+# Service Locator Bonjour Publisher
+
+import select, sys, pybonjour
+
+# Register the service locator interface with Bonjour
+bonjourServiceLocator = pybonjour.DNSServiceRegister(name = 'ServiceLocator',
+ regtype = '_asteriskscf._tcp',
+ port = 4411)
+
+# Register the service locator management interface with Bonjour
+bonjourServiceLocatorManagement = pybonjour.DNSServiceRegister(name = 'ServiceLocatorManagement',
+ regtype = '_asteriskscf._tcp',
+ port = 4411)
+
+# Go into a loop processing results that may come in
+while True:
+ ready = select.select([bonjourServiceLocator, bonjourServiceLocatorManagement], [], [])
+ if bonjourServiceLocator in ready[0]:
+ pybonjour.DNSServiceProcessResult(bonjourServiceLocator)
+ elif bonjourServiceLocatorManagement in ready[0]:
+ pybonjour.DNSServiceProcessResult(bonjourServiceLocatorManagement)
+
+# Close both registrations
+bonjourServiceLocator.close()
+bonjourServiceLocatorManagement.close()
-----------------------------------------------------------------------
--
asterisk-scf/integration/servicelocatormdns.git
More information about the asterisk-scf-commits
mailing list