--- a/usr/src/cmd/installadm/service.py Fri Feb 24 08:46:58 2012 +0100
+++ b/usr/src/cmd/installadm/service.py Fri Feb 24 09:48:42 2012 +0100
@@ -101,19 +101,19 @@
class VersionError(AIServiceError):
'''Raised if the service's version is not supported by
this version of installadm
-
+
'''
def __init__(self, service_name=None, version=None, alt_msg=None):
self.service_name = service_name
self.version = version
self.alt_msg = alt_msg
-
+
def __str__(self):
if self.alt_msg:
return self.alt_msg
else:
return self.short_str()
-
+
def short_str(self):
'''Returns a one-line string message for this error'''
return (cw(_("Service '%(name)s' is incompatible: "
@@ -125,7 +125,7 @@
def __str__(self):
if self.alt_msg:
return self.alt_msg
-
+
return (cw(_("\nService '%(name)s' cannot be modified because it was "
"created with an older version of installadm (service "
"version: %(version)s).\n") %
@@ -136,7 +136,7 @@
def __str__(self):
if self.alt_msg:
return self.alt_msg
-
+
return cw(_("\nService '%(name)s' cannot be modified because it was "
"created with a newer version of installadm (service "
"version: %(version)s).\n") %
@@ -149,7 +149,7 @@
self.source = source
self.target = target
self.reason = reason
-
+
def __str__(self):
return cw(_("\nUnable to mount '%s' at '%s': %s\n" %
(self.source, self.target, self.reason)))
@@ -160,7 +160,7 @@
def __init__(self, target, reason):
self.target = target
self.reason = reason
-
+
def __str__(self):
return cw(_("\nUnable to unmount '%s': %s\n") %
(self.target, self.reason))
@@ -171,7 +171,7 @@
def __init__(self, still_mounted, failures):
self.still_mounted = still_mounted
self.failures = failures
-
+
def __str__(self):
result = list()
if self.still_mounted:
@@ -187,7 +187,7 @@
and a service is already mounted, it is first unmounted (otherwise, the
mount is left as-is. Returns a count of how many services failed to
mount properly, and prints to stderr as the errors are encountered.
-
+
'''
failures = 0
for svc_name in config.get_all_service_names():
@@ -238,23 +238,23 @@
class AIService(object):
'''Class to represent an AI service'''
-
+
MOUNT_ON = com.BOOT_DIR
X86_BOOTFILE = "boot/grub/pxegrub"
EARLIEST_VERSION = 2
LATEST_VERSION = 2
-
+
@classmethod
def create(cls, name, source_image, ip_start=None, ip_count=None,
bootserver=None, alias=None, bootargs=''):
'''Creates a service, setting up configuration, initial manifests,
and DHCP (if desired)
-
+
Args:
name: Desired service name (not checked for validity)
source_image: An InstalladmImage object representing an already
unpacked image area
-
+
Optional Args:
ip_start, ip_count: Starting IP address and number of IP addresses
to allocate in DHCP. If not specified, no DHCP setup will be
@@ -263,23 +263,23 @@
address for the bootfile server
alias: An AIService object to which this service will be aliased
bootargs (x86 only): Additional bootargs to add to menu.lst
-
+
'''
service = cls(name, _check_version=False)
service._image = source_image
service._alias = alias
service._bootargs = bootargs
-
+
if alias is not None and service.image.version < 3:
raise UnsupportedAliasError(cw(_("\nCannot create alias: Aliased "
"service '%s' does not support "
"aliasing. Please use a service "
"with a newer image.\n") % alias))
-
+
compatibility_port = (service.image.version < 1)
logging.debug("compatibility port=%s", compatibility_port)
server_hostname = socket.gethostname()
-
+
# Determine port information
if compatibility_port:
port = get_a_free_tcp_port(server_hostname)
@@ -288,9 +288,9 @@
"web server."))
else:
port = libaimdns.getinteger_property(com.SRVINST, com.PORTPROP)
-
+
props = service._init_service_config(server_hostname, port)
-
+
# Create AI_SERVICE_DIR_PATH/<svcdir> structure
cmd = [com.SETUP_SERVICE_SCRIPT, com.SERVICE_CREATE, name,
props[config.PROP_TXT_RECORD], service._image.path]
@@ -303,12 +303,12 @@
except CalledProcessError:
print >> sys.stderr, _("Failed to setup service directory for "
"service, %s\n" % name)
-
+
service._create_default_manifest()
# Configure DHCP for this service
service._configure_dhcp(ip_start, ip_count, bootserver)
-
+
# Supported client images will interpolate the bootserver's IP
# address (as retrieved from the DHCP server) in place of the
# '$serverIP' string. We choose to utilize this functionality when
@@ -334,13 +334,13 @@
server_ip = "$serverIP"
logging.debug("server_ip=%s", server_ip)
-
+
# Save location of service in format <server_ip_address>:<port>
# It will be used later for setting service discovery fallback
# mechanism.
srv_address = '%s:%u' % (server_ip, port)
logging.debug("srv_address=%s", srv_address)
-
+
# Setup wanboot for SPARC or Grub for x86
if service.image.arch == 'sparc':
service._init_wanboot(srv_address)
@@ -348,12 +348,12 @@
service._init_grub(srv_address)
return service
-
+
def __init__(self, name, image=None, image_class=InstalladmImage,
_check_version=True):
'''Create a reference to an AIService, which can be used to control
and manage installadm services.
-
+
Required arguments:
name: The name of the service. It should already exist.
(Use classmethod AIService.create() to make a new service)
@@ -364,14 +364,14 @@
image_class: If 'image' is omitted, when an image reference is
needed, it will be instantiated as an instance
of the given class. Defaults to InstalladmImage.
-
+
'''
self._name = name
self._image = image
self._alias = None
self._bootargs = None
self._image_class = image_class
-
+
# _check_version should ONLY be used by AIService.create during service
# creation. Bypassing the version check when the service has already
# been created may lead to indeterminate results.
@@ -386,77 +386,77 @@
raise OlderVersionError(name, version)
elif version > self.LATEST_VERSION:
raise NewerVersionError(name, version)
-
+
def enable(self):
'''Enable this service. May fail, if this service is marked in need
of re-verification, and re-verification fails.
-
+
'''
if config.get_service_props(self.name).get(config.PROP_REVERIFY,
False):
self.check_valid()
self.mount()
config.enable_install_service(self.name)
-
+
def disable(self, arch_safe=False, force=False):
'''Disable this service'''
props = {config.PROP_STATUS: config.STATUS_OFF}
config.set_service_props(self.name, props)
-
+
self._unregister()
self.unmount(arch_safe=arch_safe, force=force)
-
+
# If no longer needed, put install instance into
# maintenance
config.check_for_enabled_services()
-
+
def _unregister(self):
cmd = [com.SETUP_SERVICE_SCRIPT, com.SERVICE_DISABLE, self.name]
Popen.check_call(cmd, check_result=Popen.ANY)
-
+
def delete(self):
'''Deletes this service, removing the image area, mountpoints,
and lingering configuration.
-
+
'''
self.disable(arch_safe=True, force=True)
-
+
self.remove_profiles()
for path in self.get_files_to_remove():
force_delete(path)
-
+
def version(self):
'''Look up and return the version of this service. See module
docstring for info on what each service version supports
-
+
'''
props = config.get_service_props(self.name)
try:
return int(props[config.PROP_VERSION])
except (KeyError, ValueError, TypeError):
return None
-
+
@property
def config_dir(self):
'''Returns the path to the configuration directory for this service'''
return os.path.join(AI_SERVICE_DIR_PATH, self.name)
-
+
@property
def database_path(self):
'''Returns the path to the database file for this service'''
return os.path.join(self.config_dir, "AI.db")
-
+
def database(self):
'''Opens an AI_database.DB() object pointing to this service's
database
-
+
'''
return AIdb.DB(self.database_path)
-
+
def rename(self, new_name):
'''Change this service's name to "new_name" updating all relevant
files, aliases and clients.
-
+
'''
self._update_name_in_service_props(new_name)
new_svcdir = os.path.join(AI_SERVICE_DIR_PATH, new_name)
@@ -486,7 +486,7 @@
self._migrate_service_dir(new_svcdir)
self._setup_manifest_dir(new_name=new_name)
-
+
def is_default_arch_service(self):
''' Determine if this is the default-<arch> service'''
@@ -500,7 +500,7 @@
'''
for linkname in WANBOOTCONF, SYSTEMCONF:
self._do_default_sparc_symlink(linkname, svcname)
-
+
def _do_default_sparc_symlink(self, linkname, svcname):
''' Do symlinks for default sparc service
Input:
@@ -516,7 +516,7 @@
raise
new_target = os.path.join(self.MOUNT_ON, svcname, linkname)
os.symlink(new_target, symlink)
-
+
def delete_default_sparc_symlinks(self):
'''Delete symlinks for default sparc service'''
for linkname in WANBOOTCONF, SYSTEMCONF:
@@ -531,10 +531,10 @@
'''Copy or move the AI_SERVICE_DIR_PATH/<svc> directory
Additionally update any compatibility symlinks pointing to it
(or create new ones)
-
+
Input:
newsvcdir - full path to new service dir
-
+
'''
# update any symlinks pointing to svcdir
dirlist = os.listdir(AI_SERVICE_DIR_PATH)
@@ -556,7 +556,7 @@
raise
logging.debug("symlink from %s to %s", fullpath, newsvcdir)
os.symlink(newsvcdir, fullpath)
-
+
logging.debug("rename from %s to %s", self.config_dir, newsvcdir)
os.rename(self.config_dir, newsvcdir)
@@ -578,7 +578,7 @@
def name(self):
'''Service name'''
return self._name
-
+
@staticmethod
def _prepare_target(mountpoint):
logging.debug("_prepare_target: mountpoint is %s", mountpoint)
@@ -587,43 +587,43 @@
except OSError as err:
if err.errno != errno.EEXIST:
raise
-
+
@property
def mountpoint(self):
'''Returns the path to where this service's image should be mounted'''
return os.path.join(self.MOUNT_ON, self.name)
-
+
@property
def bootmountpt(self):
'''Returns the path to where this service's boot specific config
file should be mounted
-
+
'''
if self.arch == 'i386':
return os.path.join(self.mountpoint, MENULST)
else:
return os.path.join(self.mountpoint, SYSTEMCONF)
-
+
def all_bootmountpts(self):
return [os.path.join(self.mountpoint, MENULST),
os.path.join(self.mountpoint, SYSTEMCONF)]
-
+
@property
def bootsource(self):
'''Returns the path to the file that should be mounted at
self.bootmountpt
-
+
'''
if self.arch == 'i386':
return os.path.join(self.config_dir, MENULST)
else:
return os.path.join(self.config_dir, SYSTEMCONF)
-
+
@property
def dhcp_bootfile(self):
'''Returns a string that represents what should be added to DHCP
as this service's bootfile
-
+
'''
if self.arch == 'sparc':
http_port = libaimdns.getinteger_property(com.SRVINST,
@@ -636,13 +636,13 @@
abs_dhcpbfile = os.path.join(self.mountpoint, self.X86_BOOTFILE)
dhcpbfile = os.path.relpath(abs_dhcpbfile, self.MOUNT_ON)
return dhcpbfile
-
+
def _lofs_mount(self, from_path, to_mountpoint):
'''Internal lofs mount function. If the mountpoint
is already in use by this service, returns without doing anything.
Otherwise, will mount from_path on to_mountpoint, raising MountError
for any failure.
-
+
'''
mount_points = com.MNTTab()['mount_point']
specials = com.MNTTab()['special']
@@ -659,10 +659,10 @@
check_result=Popen.SUCCESS)
except CalledProcessError as err:
raise MountError(from_path, to_mountpoint, err.popen.stderr)
-
+
def mount(self):
'''Perform service lofs mounts
-
+
For all services,
/etc/netboot/<svcname> is an lofs mount of <targetdir> (or
self.image.path for an alias)
@@ -679,7 +679,7 @@
try:
self.image.verify()
except ImageError as error:
- # verify doesn't know anything about services so prepend the
+ # verify doesn't know anything about services so prepend the
# service name to the exception to give the user sufficient
# context to fix the problem and re-raise the exception
raise ImageError(cw(_('Service Name: %s\n') %
@@ -689,38 +689,38 @@
self._lofs_mount(self.image.path, self.mountpoint)
# Do second lofi mount of menu.lst(x86) or system.conf(sparc)
self._lofs_mount(self.bootsource, self.bootmountpt)
-
+
def unmount(self, force=False, arch_safe=False):
'''Unmount the service, reversing the effects of AIService.mount()
-
+
Will raise MultipleUnmountFailure if the service does not cleanly
unmount. If errors occur during unmounting, but the unmounts
are otherwise successful, then failures are ignored (logged)
-
+
If arch_safe is True, this command will umount all potential
mountpoints, without checking the underlying image arch
(useful for deleting a service when the underlying image
is corrupted or missing)
-
+
DO NOT UNMOUNT AN ENABLED SERVICE OR YOU WILL HAVE WEIRD ERRORS
-
+
SMF will see a service as enabled and remount it at arbitrary
points in time
-
+
'''
umount_cmd = [UNMOUNT]
if force:
umount_cmd.append("-f")
-
+
if arch_safe:
mountpoints = self.all_bootmountpts()
else:
mountpoints = [self.bootmountpt]
-
+
# The image mountpoint must be unmounted last, as the boot mounts
# are mounted inside of it.
mountpoints.append(self.mountpoint)
-
+
failures = list()
for mountpoint in mountpoints:
cmd = list(umount_cmd)
@@ -731,23 +731,23 @@
check_result=Popen.SUCCESS)
except CalledProcessError as err:
failures.append(UnmountError(mountpoint, err.popen.stderr))
-
+
still_mounted = self._currently_mounted()
if still_mounted:
raise MultipleUnmountError(still_mounted, failures)
-
+
def mounted(self):
'''Returns True if ALL mounts for this service are active.'''
mount_points = com.MNTTab()['mount_point']
return (self.mountpoint in mount_points and
self.bootmountpt in mount_points)
-
+
def _currently_mounted(self):
'''Returns True if ANY mounts for this service are active.
-
+
If AIService.mounted returns False while AIService.partially_mounted
returns True, the service failed to properly mount or unmount
-
+
'''
current_mounts = list()
mount_points = com.MNTTab()['mount_point']
@@ -757,7 +757,7 @@
if boot_mount in mount_points:
current_mounts.append(boot_mount)
return current_mounts
-
+
def is_alias(self):
'''Determine if this service is an alias'''
return (self.basesvc is not None)
@@ -834,7 +834,7 @@
logging.debug("updating alias service props for %s", self.name)
props = {config.PROP_ALIAS_OF: newbasesvc_name}
config.set_service_props(self.name, props)
-
+
# disable the alias
was_mounted = False
if self.mounted():
@@ -843,7 +843,7 @@
if self.arch == 'i386':
self_menulstpath = os.path.join(self.config_dir, MENULST)
-
+
all_aliases = config.get_aliased_services(self.name, recurse=True)
all_clients = config.get_clients(self.name).keys()
for alias in all_aliases:
@@ -899,7 +899,7 @@
if client_bootargs:
grub.update_bootargs(client_menulst, self.bootargs,
client_bootargs)
-
+
# Turning point: Function calls prior to this line will reference
# the 'old' base service's image. Function calls after this line
# will reference the *new* base service's image. Keep that in mind
@@ -913,7 +913,7 @@
"or profiles is no longer valid. This "
"service will be disabled until they "
"have been removed or fixed.\n"))
-
+
# Enable the alias to pick up the new image
if was_mounted:
self.enable()
@@ -922,20 +922,20 @@
def manifest_dir(self):
'''Full path to the directory where this service's
manifests are stored
-
+
'''
return os.path.join(self.config_dir, "AI_data")
-
+
def validate_manifests(self):
'''Re-verifies all relevant AI XML manifests associated with this
service. For any that are no longer valid according to the image's
DTD, an error is printed. A count of the number of invalid manifests
is returned.
-
+
'''
db_conn = self.database()
manifests = AIdb.getNames(db_conn.getQueue(), AIdb.MANIFESTS_TABLE)
-
+
failures = 0
for manifest in manifests:
manifest_path = os.path.join(self.manifest_dir, manifest)
@@ -949,7 +949,7 @@
print >> sys.stderr, error
failures += 1
return failures
-
+
def remove_profiles(self):
''' delete profile files from internal database
Arg: service - object of service to delete profile files for
@@ -979,10 +979,10 @@
service. For any that are no longer valid according to the image's
DTD, an error is printed. A count of the number of invalid profiles
is returned.
-
+
'''
failures = 0
-
+
if self.image.version < 2:
# Older client images do not support profiles
return failures
@@ -993,7 +993,7 @@
queue.put(profile_request)
profile_request.waitAns()
profiles = profile_request.getResponse() or list()
-
+
for profile_name, profile_path in profiles:
valid = validate_file(profile_name, profile_path,
self.image.path, verbose=False)
@@ -1004,16 +1004,16 @@
print >> sys.stderr, error
failures += 1
return failures
-
+
def check_valid(self):
'''Validates whether or not this service can be enabled. If
this service can be enabled, then the PROP_REVERIFY flag is set
to False. If it CANNOT be enabled, the PROP_REVERIFY flag is set to
True, the service is disabled, and InvalidServiceError is raised.
-
+
Currently, this function only validates manifests/profiles against
this service's image (valuable for aliases).
-
+
'''
invalid_manifest_count = self.validate_manifests()
invalid_profile_count = self.validate_profiles()
@@ -1026,7 +1026,7 @@
else:
# Invalid flag is cleared, but user must manually enable service
config.set_service_props(self.name, {config.PROP_REVERIFY: False})
-
+
@property
def basesvc(self):
'''get reference to basesvc of an alias or None if not an alias'''
@@ -1035,7 +1035,7 @@
if config.PROP_ALIAS_OF in props:
basesvc = props[config.PROP_ALIAS_OF]
return basesvc
-
+
@property
def bootargs(self):
'''get bootargs of a service'''
@@ -1044,7 +1044,7 @@
if config.PROP_BOOT_ARGS in props:
bootargs = props[config.PROP_BOOT_ARGS]
return bootargs
-
+
@property
def arch(self):
'''Defer to underlying image object'''
@@ -1052,12 +1052,12 @@
return self.image.arch
else:
return None
-
+
@property
def image(self):
'''Returns a reference to an InstalladmImage object (or subclass)
pointed at this service's image path (following aliases as needed).
-
+
The actual class of the returned object can be modified by
passing in the desired class as the "image_class" keyword arg
to the AIService constructor.
@@ -1077,7 +1077,7 @@
path = alias_svc.image.path
self._image = self._image_class(path)
return self._image
-
+
def _configure_dhcp(self, ip_start, ip_count, bootserver):
'''Add DHCP configuration elements for this service.'''
@@ -1085,13 +1085,13 @@
ip_start, ip_count, bootserver, self.dhcp_bootfile, self.arch)
setup_dhcp_server(self, ip_start, ip_count, bootserver)
-
+
def _init_grub(self, srv_address):
'''Initialize grub (menu.lst) for this service'''
grub.setup_grub(self.name, self.image.path,
self.image.read_image_info(), srv_address,
self.config_dir, self._bootargs)
-
+
def _init_wanboot(self, srv_address):
'''Create system.conf file in AI_SERVICE_DIR_PATH/<svcname>'''
cmd = [com.SETUP_SPARC_SCRIPT, com.SPARC_SERVER, self.image.path,
@@ -1100,13 +1100,28 @@
# the setup-service-script relies on sending information to
# stdout/stderr
logging.debug('Calling %s', cmd)
- Popen.check_call(cmd)
+ # SETUP_SPARC_SCRIPT does math processing that needs to run in "C"
+ # locale to avoid problems with alternative # radix point
+ # representations (e.g. ',' instead of '.' in cs_CZ.*-locales).
+ # Because ksh script uses built-in math we need to set locale here and
+ # we can't set it in script itself
+ modified_env = os.environ.copy()
+ lc_all = modified_env.get('LC_ALL', '')
+ if lc_all != '':
+ modified_env['LC_MONETARY'] = lc_all
+ modified_env['LC_MESSAGES'] = lc_all
+ modified_env['LC_COLLATE'] = lc_all
+ modified_env['LC_TIME'] = lc_all
+ modified_env['LC_CTYPE'] = lc_all
+ del modified_env['LC_ALL']
+ modified_env['LC_NUMERIC'] = 'C'
+ Popen.check_call(cmd, env=modified_env)
self._setup_install_conf()
-
+
def _setup_install_conf(self):
'''Creates the install.conf file, as needed for compatibility
with older sparc clients
-
+
'''
if self.image.version < 3:
# AI clients starting with this version use
@@ -1128,37 +1143,37 @@
if err.errno != errno.ENOENT:
raise
os.symlink(system_conf, install_conf)
-
+
def _init_service_config(self, hostname, port):
'''Initialize this service's .config file. This should only be
called during service creation, from AIService.create()
-
+
'''
txt_record = '%s=%s:%u' % (com.AIWEBSERVER, hostname, port)
logging.debug("txt_record=%s", txt_record)
-
+
service_data = {config.PROP_SERVICE_NAME: self.name,
config.PROP_TXT_RECORD: txt_record,
config.PROP_GLOBAL_MENU: True,
config.PROP_REVERIFY: False,
config.PROP_STATUS: config.STATUS_ON}
-
+
if self._alias:
service_data[config.PROP_ALIAS_OF] = self._alias
else:
service_data[config.PROP_IMAGE_PATH] = self.image.path
-
+
if self.arch == 'i386' and self._bootargs:
service_data[config.PROP_BOOT_ARGS] = self._bootargs
if self.arch == 'sparc':
service_data[config.PROP_GLOBAL_MENU] = False
-
+
logging.debug("service_data=%s", service_data)
-
+
config.create_service_props(self.name, service_data)
-
+
return service_data
-
+
def get_files_to_remove(self):
'''Returns a list of file paths to clean up on service deletion.
For version 1 services, this includes:
@@ -1167,28 +1182,28 @@
* The symlink from AI_SERVICE_DIR_PATH/<port> to the config dir,
if applicable
* The symlink from the webserver's docroot to the manifest dir
-
+
'''
files = [self.mountpoint,
self.config_dir,
os.path.join(AI_SERVICE_DIR_PATH,
config.get_service_port(self.name)),
os.path.join(com.WEBSERVER_DOCROOT, self.name)]
-
+
if not self.is_alias():
files.append(self.image.path)
-
+
# must strip the leading path separator from image_path as
# os.join won't concatenate two absolute paths
webserver_path = os.path.join(com.WEBSERVER_DOCROOT,
self.image.path.lstrip(os.sep))
files.append(webserver_path)
-
+
# find the longest empty path leading up to webserver image path
if os.path.lexists(webserver_path):
# get the parent dir of the webserver path
directory = os.path.dirname(webserver_path)
-
+
# iterate up the directory structure (toward / from the
# image server's image path) adding empty directories
while len(os.listdir(directory)) == 1:
@@ -1200,13 +1215,13 @@
else:
if self.is_default_arch_service() and self.arch == 'sparc':
self.delete_default_sparc_symlinks()
-
+
return files
-
+
def _setup_manifest_dir(self, new_name=None):
'''Create a symlink in the AI webserver's docroot pointing to
the directory containing this service's manifests
-
+
'''
if new_name is not None:
try:
@@ -1222,18 +1237,18 @@
if os.path.islink(linkname) or os.path.exists(linkname):
os.remove(linkname)
os.symlink(data_dir, linkname)
-
+
def _create_default_manifest(self):
'''Create an initial, default manifest for the service (preferring
the manifest contained in the image, but falling back to the one
on the host system as necessary.
-
+
The manifest directory is setup first, as well.
(See _setup_manifest_dir)
-
+
'''
self._setup_manifest_dir()
-
+
default_xml = os.path.join(self.image.path,
IMG_AI_DEFAULT_MANIFEST)
if not os.path.exists(default_xml):
@@ -1245,7 +1260,7 @@
print (_("Warning: Using default manifest %s") %
SYS_AI_DEFAULT_MANIFEST)
default_xml = SYS_AI_DEFAULT_MANIFEST
-
+
manifest_name = "orig_default"
data = DataFiles.from_service(self,
manifest_file=default_xml,
@@ -1255,7 +1270,7 @@
manifest_path = os.path.join(self.manifest_dir, manifest_name)
place_manifest(data, manifest_path)
self.set_default_manifest(manifest_name)
-
+
def set_default_manifest(self, manifest_name, skip_manifest_check=False):
'''Make manifest "manifest_name" the default for this service'''
if not skip_manifest_check:
@@ -1263,10 +1278,10 @@
if not os.path.isfile(manifest_path):
raise ValueError(_("\nManifest '%s' does not exist.\n") %
manifest_path)
-
+
config.set_service_props(self.name,
{config.PROP_DEFAULT_MANIFEST: manifest_name})
-
+
def get_default_manifest(self):
'''Return the name of the default for this service'''
props = config.get_service_props(self.name)
@@ -1339,13 +1354,13 @@
def get_a_free_tcp_port(hostname):
''' get next free tcp port
-
+
Looks for next free tcp port number, starting from 46501
-
+
Input: hostname
Returns: next free tcp port number if one found or
None if no free port found
-
+
'''
# determine ports in use by other install services
existing_ports = set()
@@ -1353,9 +1368,9 @@
for svcname in allprops:
port = config.get_service_port(svcname)
existing_ports.add(int(port))
-
+
logging.debug("get_a_free_tcp_port, existing_ports=%s", existing_ports)
-
+
mysock = None
for port in xrange(STARTING_PORT, ENDING_PORT):
try:
@@ -1373,7 +1388,7 @@
else:
logging.debug("no available tcp port found")
return None
-
+
return port
@@ -1389,7 +1404,7 @@
def setup_dhcp_server(service, ip_start, ip_count, bootserver):
'''Set-up DHCP server for given AI service and IP address range'''
-
+
_incomplete_msg = cw(_("\nThe install service has been created but the "
"DHCP configuration has not been completed. Please "
"see dhcpd(8) for further information.\n"))
@@ -1427,7 +1442,7 @@
print >> sys.stderr, cw(_("\nUnable to add IP range: %s\n" % err))
print >> sys.stderr, _incomplete_msg
return
-
+
# Regardless of whether the IP arguments are passed or not, now check the
# current DHCP configuration for default service configuration. If we're
# creating a new default alias for this architecture, set this service's