def push_certificate(self, pkey, cert): icifc = IcontrolInterface( device=self.options.device, address=self.address, username=self.options.admin_username, password=self.options.admin_password, port=self.options.ssl_port, debug=self.options.verbose, ) ic = icifc.open() key_pem = crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey) cert_pem = crypto.dump_certificate(crypto.FILETYPE_PEM, cert) try: ic.Management.KeyCertificate.certificate_delete(mode="MANAGEMENT_MODE_WEBSERVER", cert_ids=["server"]) ic.Management.KeyCertificate.key_delete(mode="MANAGEMENT_MODE_WEBSERVER", key_ids=["server"]) except: LOG.warning("Exception occurred while deleting cert/key") ic.Management.KeyCertificate.certificate_import_from_pem( mode="MANAGEMENT_MODE_WEBSERVER", cert_ids=["server"], pem_data=[cert_pem], overwrite=1 ) ic.Management.KeyCertificate.key_import_from_pem( mode="MANAGEMENT_MODE_WEBSERVER", key_ids=["server"], pem_data=[key_pem], overwrite=1 ) icifc.close() # XXX: Unfortunately we can't reinit httpd through iControl. It's a KI # http://devcentral.f5.com/Default.aspx?tabid=53&forumid=1&postid=1170498&view=topic # # action = pc.System.Services.typefactory.\ # create('System.Services.ServiceAction').\ # SERVICE_ACTION_REINIT # service = pc.System.Services.typefactory.\ # create('System.Services.ServiceType').\ # SERVICE_HTTPD # pc.System.Services.set_service(services = [service], \ # service_action = action) # pc.System.Services.get_service_status([service]) with SSHInterface( device=self.options.device, address=self.address, username=self.options.root_username, password=self.options.root_password, port=self.options.ssh_port, ) as sshifc: version = SCMD.ssh.get_version(ifc=sshifc) if version >= "bigiq 4.4": sshifc.api.run("bigstart reinit webd") elif version >= "bigiq 4.3" and version < "bigiq 4.4": sshifc.api.run("bigstart reinit nginx") else: sshifc.api.run("bigstart reinit httpd") return True
def push_certificate(self, pkey, cert): icifc = IcontrolInterface(device=self.options.device, address=self.address, username=self.options.admin_username, password=self.options.admin_password, port=self.options.ssl_port, debug=self.options.verbose) ic = icifc.open() key_pem = crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey) cert_pem = crypto.dump_certificate(crypto.FILETYPE_PEM, cert) try: ic.Management.KeyCertificate.certificate_delete( mode='MANAGEMENT_MODE_WEBSERVER', cert_ids=['server']) ic.Management.KeyCertificate.key_delete( mode='MANAGEMENT_MODE_WEBSERVER', key_ids=['server']) except: LOG.warning('Exception occurred while deleting cert/key') ic.Management.KeyCertificate.certificate_import_from_pem( mode='MANAGEMENT_MODE_WEBSERVER', cert_ids=['server'], pem_data=[cert_pem], overwrite=1) ic.Management.KeyCertificate.key_import_from_pem( mode='MANAGEMENT_MODE_WEBSERVER', key_ids=['server'], pem_data=[key_pem], overwrite=1) icifc.close() # XXX: Unfortunately we can't reinit httpd through iControl. It's a KI # http://devcentral.f5.com/Default.aspx?tabid=53&forumid=1&postid=1170498&view=topic # # action = pc.System.Services.typefactory.\ # create('System.Services.ServiceAction').\ # SERVICE_ACTION_REINIT # service = pc.System.Services.typefactory.\ # create('System.Services.ServiceType').\ # SERVICE_HTTPD # pc.System.Services.set_service(services = [service], \ # service_action = action) # pc.System.Services.get_service_status([service]) with SSHInterface(device=self.options.device, address=self.address, username=self.options.root_username, password=self.options.root_password, port=self.options.ssh_port) as sshifc: version = SCMD.ssh.get_version(ifc=sshifc) if version >= 'bigiq 4.4' or version < 'bigiq 4.0' or \ version >= 'iworkflow 2.0': sshifc.api.run('bigstart reinit webd') elif version >= 'bigiq 4.3' and version < 'bigiq 4.4': sshifc.api.run('bigstart reinit nginx') else: # all BPs if version < 'bigip 11.5.0': x = sshifc.api.run('bigstart reinit httpd') LOG.debug("pushcert (res: bigstart reinit httpd): {0}".format(x)) else: # See BZ553787 (Matt Davey: restjavad must be restarted after pushing a cert) # was for > 12.0 only but the "fix" made it to all new HFs LOG.debug("pushcert (res: bigstart restart)...(because of issue with restajavad and/or httpd on certain platforms)") # sshifc.api.run('bigstart restart') sshifc.api.run('bigstart restart httpd') self.wait_for_available(version) return True
def by_icontrol(self, filename, hfiso=None): iso_version = cm.version_from_metadata(filename) timeout = self.options.timeout if hfiso: hfiso_version = cm.version_from_metadata(hfiso) else: hfiso_version = None LOG.debug('iso: %s', iso_version) icifc = IcontrolInterface(address=self.address, username=self.options.admin_username, password=self.options.admin_password, port=self.options.ssl_port) ic = icifc.open() running_volume = ICMD.software.get_active_volume(ifc=icifc) assert running_volume != self.options.volume, \ "Can't install on the active volume" version = ICMD.system.get_version(ifc=icifc) base = os.path.basename(filename) LOG.debug('running: %s', version) essential = self.options.essential_config if not essential and abs(iso_version) < abs(version): LOG.warning('Enforcing --esential-config') essential = True LOG.info('Setting the global DB vars...') ic.Management.Partition.set_active_partition(active_partition='Common') ic.Management.DBVariable.modify(variables=[ {'name': 'LiveInstall.MoveConfig', 'value': essential and 'disable' or 'enable'}, {'name': 'LiveInstall.SaveConfig', 'value': essential and 'disable' or 'enable'} ]) # ======================================================================= # Copy the ISO over to the device in /shared/images if it's not already # in the software repository. # ======================================================================= images = ICMD.software.get_software_image(ifc=icifc) haz_it = any(filter(lambda x: x['verified'] and x['product'] == iso_version.product.to_tmos and x['version'] == iso_version.version and x['build'] == iso_version.build, images)) volume = self.options.volume or ICMD.software.get_inactive_volume(ifc=icifc) LOG.info('Preparing volume %s...', volume) ICMD.software.clear_volume(volume=volume, ifc=icifc) def is_available(items): all_count = len(items) return sum(bool(x['verified']) for x in items) == all_count is_clustered = ic.System.Cluster.is_clustered_environment() LOG.info('Timeout: %d', timeout) if essential: with SSHInterface(address=self.address, username=self.options.root_username, password=self.options.root_password, timeout=timeout, port=self.options.ssh_port) as sshifc: ssh = sshifc.api lines = ssh.run('ls ' + SHARED_IMAGES).stdout.split() images = [x for x in lines if '.iso' in x] hfbase = os.path.basename(hfiso) if hfiso else None for image in images: if base != image and hfbase != image: # If the image is a hotfix image if 'hotfix' in image.lower(): LOG.info('Deleting hotfix image: %s' % image) ICMD.software.delete_software_image(image, is_hf=True, ifc=icifc) # Otherwise assume it is a base image else: LOG.info('Deleting base image: %s' % image) ICMD.software.delete_software_image(image, ifc=icifc) if not haz_it: LOG.info('Importing base iso %s', base) SCMD.ssh.scp_put(address=self.address, username=self.options.root_username, password=self.options.root_password, port=self.options.ssh_port, source=filename, nokex=False, timeout=timeout) LOG.info('Wait for image to be imported %s', base) ICMD.software.GetSoftwareImage(filename=base, ifc=icifc) \ .run_wait(is_available, timeout=timeout, timeout_message="Timeout ({0}s) while waiting for the software image to be imported.") if hfiso: images = ICMD.software.get_software_image(ifc=icifc, is_hf=True) haz_it = any(filter(lambda x: x['verified'] and x['product'] == hfiso_version.product.to_tmos and x['version'] == hfiso_version.version and x['build'] == hfiso_version.build, images)) if not haz_it: hfbase = os.path.basename(hfiso) LOG.info('Importing hotfix iso %s', hfiso) SCMD.ssh.scp_put(address=self.address, username=self.options.root_username, password=self.options.root_password, port=self.options.ssh_port, source=hfiso, nokex=False) LOG.info('Wait for image to be imported %s', hfbase) ICMD.software.GetSoftwareImage(filename=hfbase, ifc=icifc, is_hf=True) \ .run_wait(is_available, timeout_message="Timeout ({0}s) while waiting for the hotfix image to be imported.") def is_still_removing(items): return not any(filter(lambda x: x['status'].startswith('removing'), items)) def is_still_installing(items): return not any(filter(lambda x: x['status'].startswith('installing') or x['status'].startswith('waiting') or x['status'].startswith('testing') or x['status'] in ('audited', 'auditing', 'upgrade needed'), items)) volumes = ICMD.software.get_software_status(ifc=icifc) assert is_still_installing(volumes), "An install is already in " \ "progress on another slot: %s" % volumes ICMD.software.GetSoftwareStatus(volume=volume, ifc=icifc) \ .run_wait(is_still_removing, # CAVEAT: tracks progress only for the first blade progress_cb=lambda x: x[0]['status'], timeout=timeout) LOG.info('Installing %s...', iso_version) ICMD.software.install_software(hfiso_version or iso_version, volume=volume, ifc=icifc) ret = ICMD.software.GetSoftwareStatus(volume=volume, ifc=icifc) \ .run_wait(is_still_installing, # CAVEAT: tracks progress only for the first blade progress_cb=lambda x: x[0]['status'], timeout=timeout, timeout_message="Timeout ({0}s) while waiting software install to finish.", stabilize=10) LOG.info('Resetting the global DB vars...') ic.Management.DBVariable.modify(variables=[ {'name': 'LiveInstall.MoveConfig', 'value': essential and 'enable' or 'disable'}, {'name': 'LiveInstall.SaveConfig', 'value': essential and 'enable' or 'disable'} ]) if sum(x['status'] == 'complete' for x in ret) != len(ret): raise InstallFailed('Install did not succeed: %s' % ret) LOG.info('Setting the active boot location %s.', volume) if is_clustered: # =================================================================== # Apparently on chassis systems the device is rebooted automatically # upon setting the active location, just like `b software desired # HD1.N active enable`. # =================================================================== uptime = ic.System.SystemInfo.get_uptime() ic.System.SoftwareManagement.set_cluster_boot_location(location=volume) time.sleep(60) else: ic.System.SoftwareManagement.set_boot_location(location=volume) LOG.info('Rebooting...') uptime = ICMD.system.reboot(ifc=icifc) # Grab a new iControl handle that uses the default admin credentials. if essential: icifc.close() icifc = IcontrolInterface(address=self.address, port=self.options.ssl_port) icifc.open() if uptime: ICMD.system.HasRebooted(uptime, ifc=icifc).run_wait(timeout=timeout) LOG.info('Device is rebooting...') LOG.info('Wait for box to be ready...') ICMD.system.IsServiceUp('MCPD', ifc=icifc).\ run_wait(timeout=timeout, timeout_message="Timeout ({0}s) while waiting for MCPD to come up") ICMD.system.IsServiceUp('TMM', ifc=icifc).\ run_wait(timeout_message="Timeout ({0}s) while waiting for TMM to come up") ICMD.management.GetDbvar('Configsync.LocalConfigTime', ifc=icifc).\ run_wait(lambda x: int(x) > 0, progress_cb=lambda x: 'waiting configsync...', timeout=timeout) ICMD.system.FileExists('/var/run/mprov.pid', ifc=icifc).\ run_wait(lambda x: x is False, progress_cb=lambda x: 'mprov still running...', timeout=timeout) ICMD.system.FileExists('/var/run/grub.conf.lock', ifc=icifc).\ run_wait(lambda x: x is False, progress_cb=lambda x: 'grub.lock still present...', timeout=timeout) current_version = ICMD.system.get_version(ifc=icifc) expected_version = hfiso_version or iso_version try: if expected_version != current_version: raise InstallFailed('Version expected: %s but found %s' % (expected_version, current_version)) finally: icifc.close() # Will use SSH! if essential: self._initialize_big3d() if essential and current_version.product.is_em: self._initialize_em() self.has_essential_config = essential
class VcmpPlacer(ConfigPlacer): SystemConfig = SystemConfig vCMPConfig = vCMPConfig def __init__(self, guests, *args, **kwargs): super(VcmpPlacer, self).__init__(*args, **kwargs) # Case when there is no vCMP guests to setup. if not guests: guests = [] self.guests = [] for guest in guests: if isinstance(guest, DeviceAccess): item = guest else: if len(guest.split(':')) > 2: address, gw, name = guest.split(':') elif len(guest.split(':')) > 1: address, gw = guest.split(':') name = None else: address, gw, name = guest, None, None item = O() item.specs = O() spec = item.specs spec.address = IPNetwork(address) spec.gw = IPAddress(gw) if gw else None spec.cores = self.options.get('cores') spec.name = name self.guests.append(item) if isinstance(self.device, DeviceAccess): self.options.admin_username = self.device.get_admin_creds( ).username or ADMIN_USERNAME self.options.admin_password = self.device.get_admin_creds( ).password or ADMIN_PASSWORD self.options.setifnone('admin_username', ADMIN_USERNAME) self.options.setifnone('admin_password', ADMIN_PASSWORD) # Assumed we are using vcmp provisioning here if we are not reverting # BIG-IP back to whatever provision. if not self.options.revert: self.options.provision = 'vcmp' def prep(self): super(VcmpPlacer, self).prep() self.icifc = IcontrolInterface(address=self.address, username=self.options.admin_username, password=self.options.admin_password, port=self.options.ssl_port) def get_provider(self, address, csv): provider = O() if not self.options.no_irack and not csv: LOG.info("Using data from iRack") provider = self.irack_provider( address=self.options.irack_address, username=self.options.irack_username, apikey=self.options.irack_apikey, mgmtip=address, timeout=self.options.timeout) elif csv: LOG.info("Using data from CSV: %s" % csv) provider = self.csv_provider(mgmtip=address, csv_rpath=csv) return provider def wait_reboot(self, icifc, timeout=None): timeout = timeout or self.options.timeout ICMD.system.IsServiceUp('MCPD', ifc=icifc).\ run_wait(timeout=timeout, timeout_message="Timeout ({0}s) while waiting for MCPD " "to come up") ICMD.system.IsServiceUp('TMM', ifc=icifc).\ run_wait(timeout_message="Timeout ({0}s) while waiting for TMM " "to come up") ICMD.management.GetDbvar('Configsync.LocalConfigTime', ifc=icifc).\ run_wait(lambda x: int(x) > 0, progress_cb=lambda x: 'waiting configsync...', timeout=timeout) ICMD.system.FileExists('/var/run/mprov.pid', ifc=self.icifc).\ run_wait(lambda x: x is False, progress_cb=lambda x: 'mprov still running...', timeout=timeout) ICMD.system.FileExists('/var/run/grub.conf.lock', ifc=self.icifc).\ run_wait(lambda x: x is False, progress_cb=lambda x: 'grub.lock still present...', timeout=timeout) def clean_vdisk(self): images = SCMD.tmsh.list('vcmp virtual-disk', ifc=self.sshifc) for image in images: LOG.info("Cleaning old Virtual Disk Image: %s" % image.split()[-1]) SCMD.tmsh.run(image, command='delete', ifc=self.sshifc) def delete_guests(self): guests = SCMD.tmsh.list('vcmp guest', ifc=self.sshifc) for guest, items in guests.iteritems(): if 'state' in items and items['state'] in VCMP_ONLINE_STATES: LOG.info("Disabling %s..." % guest.split()[-1]) SCMD.tmsh.run(guest + ' state configured', command='modify', ifc=self.sshifc) LOG.info("Deleting %s..." % guest.split()[-1]) SCMD.tmsh.run(guest, command='delete', ifc=self.sshifc) def setup(self): ctx = self.make_context() if self.options.revert: LOG.info("Reverting by provisioning to %s" % self.options.provision) if self.options.clean_only and 'vcmp' in ctx.provision.keys(): # Disable any running vCMP Guests then delete them self.delete_guests() self.clean_vdisk() return if not self.guests and not self.revert: LOG.warning("No vCMP Guests to setup. Just use the normal " "configurator if you only need to do vcmp " "provisioning only...") return provider = self.get_provider(self.address, self.options.csv) reboot = True # TODO: We will need to add more logic here to check if the current # running guests are the same as our config. If so, leave it, otherwise # clean it out. if 'vcmp' in ctx.provision.keys(): # Disable any running vCMP Guests then delete them self.delete_guests() self.clean_vdisk() if self.options.provision in ctx.provision.keys(): LOG.info("No need for reboot...") reboot = False # System o = O() o.hostname = self.options.hostname or provider.get('hostname') self.set_networking(o) self.set_provisioning(o) if provider.mgmtip and (o.mgmtip.ip != provider.mgmtip.ip or o.mgmtip.cidr != provider.mgmtip.cidr): LOG.warning('Management address mismatch. iRack/CSV has {0} but ' 'found {1}. iRack/CSV will take ' 'precedence.'.format(provider.mgmtip, o.mgmtip)) o.mgmtip = provider.mgmtip if provider.gateway and o.gateway != provider.gateway: LOG.warning('Default gateway address mismatch. iRack/CSV has ' '{0} but found {1}. iRack/CSV will take ' 'precedence.'.format(provider.gateway, o.gateway)) o.gateway = provider.gateway tree = self.SystemConfig(self.context, partitions=0, **o).run() # Skip this if we are reverting back to another provision if not self.options.revert: # vCMP Guests LOG.info("Generating vCMP Guests...") # Look for image and hotfix with the same version as BIG-IP Host. target_version = ctx.version.version images = SCMD.ssh.generic('ls /shared/images', ifc=self.sshifc).stdout hotfix = base = None for image in images.split(): if target_version in image and 'Hotfix' in image: hotfix = image elif target_version in image: base = image if hotfix and image: break for i, guest in enumerate(self.guests): csv = self.device.specs.csv if isinstance( self.device, DeviceAccess) else self.options.csv # Just IP, no netmask info like x.x.x.x/yy ip = guest.specs.address.ip if isinstance( guest.specs.address, IPNetwork) else guest.address provider = self.get_provider(ip, csv) management_ip = provider.mgmtip or IPNetwork( guest.specs.address) management_gw = provider.gateway or guest.specs.gw if str(management_ip.netmask) == '255.255.255.255': LOG.warning( "Mgmt netmask probably was not set! Defaulting to " "/24 prefix.") management_ip.prefixlen = DEFAULT_NETMASK_PREFIX if not management_gw: LOG.warning("Gateway not set!!") default_gw = management_ip.broadcast - 1 management_gw = default_gw LOG.warning("Defaulting to %s" % default_gw) guest_name = guest.specs.name or GUEST_NAME % (i) o = O(tree=tree, name=guest_name, management_ip=management_ip, management_gw=management_gw, initial_image=base, initial_hotfix=hotfix) if guest.specs.get('cores'): o.cores_per_slot = guest.specs.get('cores') tree = self.vCMPConfig(self.context, **o).run() if self.options.stdout: self.dump(tree, ctx) return self.load(tree, ctx) # If BIG-IP isn't already provisioned, a reboot will happen. timeout = self.options.timeout if reboot: ic = self.icifc.open() uptime = ic.System.SystemInfo.get_uptime() LOG.info("Pausing 30 seconds to wait until reboot has happened...") time.sleep(30) if uptime: ICMD.system.HasRebooted(uptime, ifc=self.icifc).\ run_wait(timeout=timeout) LOG.info('Device is rebooting...') LOG.info('Wait for box to be ready...') self.wait_reboot(self.icifc) self.reset_trust() self.ready_wait() # Skip this if we are reverting back to another provision if not self.options.revert: # There shouldn't be any virtual disks so clean out any remaining ones # from previous runs self.clean_vdisk() # Deploy vCMP Guests. guests = SCMD.tmsh.list('vcmp guest', ifc=self.sshifc) for guest, items in guests.iteritems(): if 'state' not in items or items['state'] != 'deployed': LOG.info("Deploying %s..." % guest.split()[-1]) SCMD.tmsh.run(guest + ' state deployed', command='modify', ifc=self.sshifc) # Wait until vCMP guests are running timeout = VCMP_TIMEOUT * ( len(self.guests) / 6 + 1 ) # Only 6 vCMP Guests can start in parallel for guest in self.guests: try: ip = guest.specs.address.ip if isinstance( guest.specs.address, IPNetwork) else guest.address icifc = IcontrolInterface(address=ip, username=ADMIN_USERNAME, password=ADMIN_PASSWORD, port=self.options.ssl_port) LOG.info('Wait for %s to be ready...' % ip) self.wait_reboot(icifc, timeout=timeout) finally: icifc.close() self.save(ctx) self.ssh_key_exchange() def cleanup(self): super(VcmpPlacer, self).cleanup() self.icifc.close()
def push_certificate(self, pkey, cert): icifc = IcontrolInterface(device=self.options.device, address=self.address, username=self.options.admin_username, password=self.options.admin_password, port=self.options.ssl_port, debug=self.options.verbose) ic = icifc.open() key_pem = crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey) cert_pem = crypto.dump_certificate(crypto.FILETYPE_PEM, cert) try: ic.Management.KeyCertificate.certificate_delete( mode='MANAGEMENT_MODE_WEBSERVER', cert_ids=['server']) ic.Management.KeyCertificate.key_delete( mode='MANAGEMENT_MODE_WEBSERVER', key_ids=['server']) except: LOG.warning('Exception occurred while deleting cert/key') ic.Management.KeyCertificate.certificate_import_from_pem( mode='MANAGEMENT_MODE_WEBSERVER', cert_ids=['server'], pem_data=[cert_pem], overwrite=1) ic.Management.KeyCertificate.key_import_from_pem( mode='MANAGEMENT_MODE_WEBSERVER', key_ids=['server'], pem_data=[key_pem], overwrite=1) icifc.close() # XXX: Unfortunately we can't reinit httpd through iControl. It's a KI # http://devcentral.f5.com/Default.aspx?tabid=53&forumid=1&postid=1170498&view=topic # # action = pc.System.Services.typefactory.\ # create('System.Services.ServiceAction').\ # SERVICE_ACTION_REINIT # service = pc.System.Services.typefactory.\ # create('System.Services.ServiceType').\ # SERVICE_HTTPD # pc.System.Services.set_service(services = [service], \ # service_action = action) # pc.System.Services.get_service_status([service]) with SSHInterface(device=self.options.device, address=self.address, username=self.options.root_username, password=self.options.root_password, port=self.options.ssh_port) as sshifc: version = SCMD.ssh.get_version(ifc=sshifc) if version >= 'bigiq 4.4': sshifc.api.run('bigstart reinit webd') elif version >= 'bigiq 4.3' and version < 'bigiq 4.4': sshifc.api.run('bigstart reinit nginx') else: sshifc.api.run('bigstart reinit httpd') return True