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 do_BZ364939(self): devices = self.cas + self.peers devices.reverse() for device in devices: cred = device.get_admin_creds() with IcontrolInterface(address=device.address, username=cred.username, password=cred.password, port=device.ports['https']) as icifc: v = icifc.version if v.product.is_bigip and v >= 'bigip 11.2.0' or \ v.product.is_em and v >= 'em 3.0.0' or \ v.product.is_bigiq: continue # if icifc.version.product.is_bigip and icifc.version < 'bigip 11.2': ic = icifc.api LOG.info('Working around BZ364939 on %s...', device.alias) ic.System.Services.set_service( services=['SERVICE_TMM'], service_action='SERVICE_ACTION_RESTART') wait(ic.System.Failover.get_failover_state, lambda x: x != 'FAILOVER_STATE_OFFLINE')
def do_config_sync(self): groups = list(self.groups.keys()) self.do_wait_valid_state() # If so_config_all() is called, use cas[0] device, otherwise sync using # first active device. if self.sync_device: first_active_device = self.sync_device else: # Wait for at least one Active device. active_devices = wait(self.do_get_active, timeout=30, interval=2) # Will initiate config sync only from the first Active device. first_active_device = active_devices[0] LOG.info("Doing Config Sync to group %s...", groups) cred = first_active_device[0].get_admin_creds() with IcontrolInterface( address=first_active_device[0].address, username=cred.username, password=cred.password, port=first_active_device[0].ports['https']) as icifc: ic = icifc.api # This device group appears starting in 11.6.0. Sync this as well. dgs = ic.Management.DeviceGroup.get_list() if ASM_DG in dgs: LOG.info("This appears to be BIGIP11.6.0+ because of %s...", ASM_DG) groups.append(ASM_DG) for dg in groups: ic.System.ConfigSync.synchronize_to_group(group=dg)
def do_set_active(self): if isinstance(self.options.set_active, DeviceAccess): with EmapiInterface(device=self.options.set_active) as rstifc: name = rstifc.api.get(MgmtIp.URI)['items'][0]['name'] ip = IPNetworkRd(name) desired_active = str(ip.ip) else: desired_active = self.options.set_active LOG.info('Trying to set device with mgmt address %s to Active', desired_active) active_devices = wait(self.do_get_active, timeout=30, interval=1, stabilize=CMI_STABILIZE_TIME) device_map = {} LOG.info('Active devices: %s', active_devices) for device in active_devices: if not device[0]: LOG.warning('No configuration found for device %s', device[2]) continue cred = device[0].get_admin_creds() with IcontrolInterface(address=device[0].address, username=cred.username, password=cred.password, port=device[0].ports['https']) as icifc: v = icifc.version if v.product.is_bigip and v < 'bigip 11.2.0' or \ v.product.is_em and v < 'em 3.0.0': LOG.warning( 'Set active not supported on this version (%s).', v) ic = icifc.api devices = ic.Management.Device.get_list() if desired_active in devices: LOG.info("Current Active device is %s.", device[2]) LOG.info("Setting %s to Active...", desired_active) ic.System.Failover.set_standby_to_device( device=desired_active) def _is_desired_device_active(devices): return [ x for x in devices if x[1] == 'HA_STATE_ACTIVE' and x[2] == device_map[desired_active] ] if device_map.get(desired_active): LOG.info("Waiting for Active status...") wait(self.do_get_active, _is_desired_device_active, timeout=10, interval=1)
def setup(self): # Set the admin and root usernames and passwords self.set_defaults() if self.options.image: title = 'Installing custom base image on %s' % self.address else: title = 'Installing %s %s on %s' % (self.options.product, self.options.pversion, self.address) LOG.info(title) filename, hfiso = self._find_iso() iso_version = cm.version_from_metadata(filename) if self.options.copy_only: self.copy_only(filename, hfiso) return #LOG.info('Disabling the 14.0+ password policy...') #RCMD.system.DisablePasswordPolicy(address=self.address, # port=self.options.ssl_port).run_wait(timeout=self.options.timeout) if self.options.format_partitions or self.options.format_volumes: with SSHInterface(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) else: with IcontrolInterface(address=self.address, username=self.options.admin_username, password=self.options.admin_password, port=self.options.ssl_port) as icifc: version = ICMD.system.get_version(ifc=icifc) if (iso_version.product.is_bigip and iso_version >= 'bigip 10.0.0' or iso_version.product.is_em and iso_version >= 'em 2.0.0' or iso_version.product.is_bigiq or iso_version.product.is_iworkflow): if self.options.format_partitions or self.options.format_volumes or \ (version.product.is_bigip and version < 'bigip 10.0.0' or version.product.is_em and version < 'em 2.0.0'): ret = self.by_image2disk(filename, hfiso) else: ret = self.by_icontrol(filename, hfiso) elif (iso_version.product.is_bigip and iso_version < 'bigip 9.6.0' or iso_version.product.is_em and iso_version < 'em 2.0.0'): assert self.options.em_address, "--em-address is needed for legacy installations." ret = self.by_em_api(filename, hfiso) else: raise VersionNotSupported('%s is not supported' % iso_version) LOG.debug('done') return ret
def setup(self): with IcontrolInterface(**self.icparams) as icifc: if self.options.session: icifc.set_session(self.options.session) ic = icifc.api method = re.sub(r'[\./:]{1,2}', r'.', self.method) limited_globals = dict(__builtins__={ 'True': True, 'False': False, 'None': None }) params = [] for param in self.params: param = param.decode('utf-8') name, value = param.split('=', 1) # Convert the command-line arguments to Python objects. try: obj = eval(value, limited_globals) params.append("%s=%r" % (name, obj)) except (NameError, SyntaxError) as e: LOG.debug(e) if value.startswith('[') or value.startswith('{'): LOG.warning("Did you forget quotes around %s?", value) params.append("%s=%s" % (name, repr(value))) LOG.debug(u"Calling: {0}({1})".format(method, ', '.join(params))) x = eval(u"ic.{0}({1})".format(method, ','.join(params)), limited_globals, {'ic': ic}) # print "--- RETURN ---" if self.options.yaml: import yaml result = yaml.safe_dump(x, default_flow_style=False, indent=4, allow_unicode=True) elif self.options.json: import json result = json.dumps(x, sort_keys=True, indent=4, ensure_ascii=False) elif self.options.raw: result = x else: import pprint result = pprint.pformat(x) return result
def do_set_active(self): if isinstance(self.options.set_active, DeviceAccess): desired_active = self.options.set_active.address else: desired_active = self.options.set_active active_devices = wait(self.do_get_active, timeout=30, interval=2) device_map = {} for device in active_devices: if not device[0]: LOG.warning('No configuration found for device %s', device[2]) continue cred = device[0].get_admin_creds() with IcontrolInterface(address=device[0].address, username=cred.username, password=cred.password, port=device[0].ports['https']) as icifc: v = icifc.version if v.product.is_bigip and v < 'bigip 11.2.0' or \ v.product.is_em and v < 'em 3.0.0': LOG.warning( 'Set active not supported on this version (%s).', v) ic = icifc.api devices = ic.Management.Device.get_list() mgmtaddrs = ic.Management.Device.get_management_address( devices=devices) device_map = dict(zip(mgmtaddrs, devices)) if device_map.get(desired_active): LOG.info("Current Active device is %s.", device[2]) LOG.info("Setting %s to Active...", device_map[desired_active]) ic.System.Failover.set_standby_to_device( device=device_map[desired_active]) def _is_desired_device_active(devices): return [ x for x in devices if x[1] == 'HA_STATE_ACTIVE' and x[2] == device_map[desired_active] ] if device_map.get(desired_active): LOG.info("Waiting for Active status...") wait(self.do_get_active, _is_desired_device_active, timeout=10, interval=1)
def do_reset_all(self): devices = self.cas + self.peers groups = list(self.groups.keys()) for device in devices: cred = device.get_admin_creds() with IcontrolInterface(address=device.address, username=cred.username, password=cred.password, port=device.ports['https']) as icifc: ic = icifc.api v = ICMD.system.get_version(ifc=icifc) if v.product.is_bigip and v < 'bigip 11.0': raise NotImplemented('Not working for < 11.0') # In 11.2.0 the device cannot be renamed while it's in the Trust v = icifc.version if v.product.is_bigip and v >= 'bigip 11.2.0' or \ v.product.is_em and v >= 'em 3.0.0' or \ v.product.is_bigiq: device_name = ic.Management.Device.get_local_device() else: device_name = uuid.uuid4().hex LOG.info('Resetting trust on %s...', device.alias) ic.Management.Trust.reset_all(device_object_name=device_name, keep_current_authority='false', authority_cert='', authority_key='') dgs = ic.Management.DeviceGroup.get_list() for dg in groups + [ASM_DG]: if dg in dgs or '/Common/%s' % dg in dgs: LOG.info('Removing %s from %s...', dg, device.alias) ic.Management.DeviceGroup.remove_all_devices( device_groups=[dg]) ic.Management.DeviceGroup.delete_device_group( device_groups=[dg]) try: if self.options.floatingip: icifc.api.Networking.SelfIPV2.delete_self_ip( self_ips=[SELFIP_NAME]) except IControlFault as e: if 'was not found' not in e.faultstring: raise
def do_wait_valid_state(self): LOG.info('Waiting until BIG-IPs are out of Disconnected state...') def get_sync_statuses(): ret = [] for device in self.cas + self.peers: device_cred = device.get_admin_creds() with EmapiInterface(username=device_cred.username, password=device_cred.password, port=device.ports['https'], address=device.address) as rstifc: api = rstifc.api entries = api.get(SyncStatus.URI)['entries'] x = [ entries[entry].nestedStats.entries.status.description for entry in entries ] ret.extend(x) return ret # Verify all BIG-IPs are at least 11.5.0 valid_bigips = True for device in self.cas + self.peers: device_cred = device.get_admin_creds() with IcontrolInterface(address=device.address, username=device_cred.username, password=device_cred.password, port=device.ports['https']) as icifc: v = icifc.version if v.product.is_bigip and v < 'bigip 11.5.0': valid_bigips = False if valid_bigips: wait(get_sync_statuses, condition=lambda ret: 'Disconnected' not in ret, progress_cb=lambda ret: "Device sync-status: {0}".format(ret), timeout=10) else: LOG.info( 'There are BIG-IPs that are older than 11.5.0. Skipping wait...' )
def do_get_active(self): device_accesses = self.cas + self.peers devices_map = dict([(x.alias, x) for x in device_accesses]) cred = device_accesses[0].get_admin_creds() with IcontrolInterface( address=device_accesses[0].address, username=cred.username, password=cred.password, port=device_accesses[0].ports['https']) as icifc: ic = icifc.api devices = ic.Management.Device.get_list() fostates = ic.Management.Device.get_failover_state(devices=devices) mgmtaddrs = ic.Management.Device.get_management_address( devices=devices) trios = [(devices_map.get(x[0].rsplit('/', 1)[-1]), x[1], x[0]) for x in zip(devices, fostates, mgmtaddrs)] LOG.debug(trios) active_devices = list([x for x in trios if x[1] == 'HA_STATE_ACTIVE']) return active_devices
def do_get_active(self): device_accesses = self.cas + self.peers devices_map = dict(map(lambda x: (x.address, x), device_accesses)) cred = device_accesses[0].get_admin_creds() with IcontrolInterface( address=device_accesses[0].address, username=cred.username, password=cred.password, port=device_accesses[0].ports['https']) as icifc: ic = icifc.api devices = ic.Management.Device.get_list() fostates = ic.Management.Device.get_failover_state(devices=devices) mgmtaddrs = ic.Management.Device.get_management_address( devices=devices) trios = map(lambda x: (devices_map.get(x[2]), x[1], x[0]), zip(devices, fostates, mgmtaddrs)) LOG.debug(trios) active_devices = list( filter(lambda x: x[1] == 'HA_STATE_ACTIVE', trios)) return active_devices
def do_config_all(self): peers = self.peers groups = self.groups ipv6 = self.options.ipv6 cas = self.cas if not cas: LOG.warning('No CAs specified, NOOP!') return ca_cred = cas[0].get_admin_creds() # There is a chance where the first cas device can come up as STANDBY. This # ensures the sync will use the first cas device (cas[0]) to sync to group. self.sync_device = [cas[0]] with IcontrolInterface(address=cas[0].address, username=ca_cred.username, password=ca_cred.password, port=cas[0].ports['https']) as caicifc: ca_api = caicifc.api v = ICMD.system.get_version(ifc=caicifc) if v.product.is_bigip and v < 'bigip 11.0': raise NotImplementedError('Not working for < 11.0: %s' % caicifc.address) self.do_prep_dgs(caicifc, cas[0], groups) self.do_prep_cmi(caicifc, cas[0], ipv6) for peer in cas[1:]: cred = peer.get_admin_creds() with IcontrolInterface(address=peer.address, username=cred.username, password=cred.password, port=peer.ports['https']) as peericifc: v = ICMD.system.get_version(ifc=peericifc) if v.product.is_bigip and v < 'bigip 11.0': raise NotImplemented('Not working for < 11.0') self.do_prep_cmi(peericifc, peer, ipv6) peer_address = peericifc.api.Networking.AdminIP.get_list( )[0] LOG.info('Adding CA device %s to trust...', peer) ca_api.Management.Trust.add_authority_device( address=peer_address, username=cred.username, password=cred.password, device_object_name=peer.alias, browser_cert_serial_number='', browser_cert_signature='', browser_cert_sha1_fingerprint='', browser_cert_md5_fingerprint='') for peer in peers: cred = peer.get_admin_creds() with IcontrolInterface(address=peer.address, username=cred.username, password=cred.password, port=peer.ports['https']) as peericifc: v = ICMD.system.get_version(ifc=peericifc) if v.product.is_bigip and v < 'bigip 11.0': raise NotImplemented('Not working for < 11.0') self.do_prep_cmi(peericifc, peer, ipv6) ret = peericifc.api.Networking.AdminIP.get_list() if ret: peer_address = ret[0] else: # VCMP case ret = peericifc.api.Networking.AdminIP.get_cluster_list( cluster_names=['default']) if ret[0]: peer_address = ret[0][0] LOG.info('Adding non-CA device %s to trust...', peer) ca_api.Management.Trust.add_non_authority_device( address=peer_address, username=cred.username, password=cred.password, device_object_name=peer.alias, browser_cert_serial_number='', browser_cert_signature='', browser_cert_sha1_fingerprint='', browser_cert_md5_fingerprint='') dgs = ca_api.Management.DeviceGroup.get_list() if ASM_DG in dgs: LOG.info('Found %s. Forcing it to use auto sync...', ASM_DG) ca_api.Management.DeviceGroup.set_full_load_on_sync_state( device_groups=[ASM_DG], states=['STATE_DISABLED']) ca_api.Management.DeviceGroup.set_autosync_enabled_state( device_groups=[ASM_DG], states=['STATE_ENABLED']) group_2_devices = {} for device in cas + peers: #for group in device.groups: for group in self.groups_specs: group_2_devices.setdefault(group, []) group_2_devices[group].append(device.alias) device_groups, devices = list(zip(*list(group_2_devices.items()))) LOG.info('Adding devices %s to %s...', devices, device_groups) ca_api.Management.DeviceGroup.add_device( device_groups=device_groups, devices=devices) if self.options.floatingip: LOG.info('Adding floating ip to %s...', DEFAULT_TG) ip = IPNetworkRd(self.options.floatingip) if ip.prefixlen == 32: raise ValueError("Did you forget the /16 prefix?") selfips = ca_api.Networking.SelfIPV2.get_list() if SELFIP_NAME not in selfips: ca_api.Networking.SelfIPV2.create( self_ips=[SELFIP_NAME], vlan_names=[self.options.ha_vlan], addresses=[str(ip.ip)], netmasks=[str(ip.netmask)], traffic_groups=[DEFAULT_TG], floating_states=['STATE_ENABLED']) # Change Port Lockdown to Allow Default. ca_api.Networking.SelfIPV2.add_allow_access_list( self_ips=[SELFIP_NAME], access_lists=[ dict(mode='ALLOW_MODE_DEFAULTS', protocol_ports=[]) ]) # BUG: BZ364939 (workaround restart tmm on all peers) # 01/22: Appears to work sometimes in 11.2 955.0 self.do_BZ364939()
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 do_inject(self): LOG.info('* Cloning mode *') bulk_sql = [] ip_offset = self.options.ip_offset with EMInterface(**self.emicparams) as emicifc: LOG.info('Disable auto-refresh on EM...') EMAPI.device.set_config(auto_refresh=False, ifc=emicifc) with SSHInterface(**self.emparams) as emsshifc: version = SCMD.ssh.get_version(ifc=emsshifc) has_groups = version < 'em 2.3.0' rows = SQL.query('SELECT MAX(device.uid) AS device, MAX(device_slot.uid) AS slot FROM device, device_slot;', ifc=emsshifc) max_device_uid = int(rows[0].device) max_slot_uid = int(rows[0].slot) bpmgmt = self.bigipparams.address template = self.do_get_template(bpmgmt, emsshifc) assert template.access_address != template.mgmt_address, \ "Template device must be discovered by its self IP." device_uid = int(template.uid) LOG.info('Template: %s', template.host_name) start_ip = IPAddress(START_IP) LOG.info('Inserting device rows...') for i in range(1, self.options.clones + 1, 1): template.uid = max_device_uid + UIDOFFSET + i template.access_address = str(start_ip + ip_offset + i) template.system_id = None template.last_refresh = None query = "INSERT INTO `device` %s" % self.do_prep_insert(template) bulk_sql.append(query) if has_groups: bulk_sql.append("INSERT INTO device_2_device_group VALUES (NULL,%d,1)" % template.uid) while bulk_sql: SQL.query(";".join(bulk_sql[:MAXSQL]), ifc=emsshifc) bulk_sql[:MAXSQL] = [] # Prepare device slot rows = SQL.query("SELECT * FROM device_slot WHERE device_id=%d;" % device_uid, ifc=emsshifc) last_device_slot_uid = max_slot_uid + UIDOFFSET LOG.info('Inserting device_slot rows...') for row in rows: last_device_uid = max_device_uid + UIDOFFSET for i in range(1, self.options.clones + 1, 1): last_device_slot_uid += 1 last_device_uid += 1 row.uid = last_device_slot_uid row.device_id = last_device_uid query = "INSERT INTO `device_slot` %s" % self.do_prep_insert(row) bulk_sql.append(query) while bulk_sql: SQL.query(";".join(bulk_sql[:MAXSQL]), ifc=emsshifc) bulk_sql[:MAXSQL] = [] LOG.info('Creating SelfIPs on %s...', bpmgmt) self_ips = [str(start_ip + ip_offset + x) for x in range(1, self.options.clones + 1, 1)] vlan_names = ['internal'] * self.options.clones netmasks = ['255.255.0.0'] * self.options.clones unit_ids = [0] * self.options.clones floating_states = ['STATE_DISABLED'] * self.options.clones with IcontrolInterface(**self.bigipparams) as bigipicifc: ic = bigipicifc.api ic.Networking.SelfIP.create(self_ips=self_ips, vlan_names=vlan_names, netmasks=netmasks, unit_ids=unit_ids, floating_states=floating_states) access_lists = [dict(self_ip=x, mode='ALLOW_MODE_ALL', protocol_ports=[]) for x in self_ips] ic.Networking.SelfIPPortLockdown.add_allow_access_list(access_lists=access_lists)
class DeviceCloner(Macro): def __init__(self, options, emaddress=None, bigipaddress=None): self.options = Options(options) self.emparams = Options(device=self.options.emdevice, address=emaddress, timeout=self.options.timeout, username=self.options.em_root_username, password=self.options.em_root_password) self.emicparams = Options(device=self.options.emdevice, address=emaddress, timeout=self.options.timeout, username=self.options.em_admin_username, password=self.options.em_admin_password) self.bigipparams = Options(device=self.options.bigipdevice, address=bigipaddress, timeout=self.options.timeout, username=self.options.bigip_admin_username, password=self.options.bigip_admin_password) super(DeviceCloner, self).__init__() def do_prep_insert(self, row): names = ['NULL' if x is None else unicode(x) for x in row.keys()] values = [] for x in row.values(): if x is None: values.append('NULL') else: values.append("'%s'" % unicode(x)) return "(`%s`) VALUES(%s)" % ("`,`".join(names), ",".join(values)) def do_get_template(self, mgmtip, ifc): # Select template row rows = SQL.query("SELECT * FROM device WHERE mgmt_address='%s';" % mgmtip, ifc=ifc) if not rows: raise ClonerFailed('Device with mgmtip %s not found.' % mgmtip) return rows[0] def do_inject(self): LOG.info('* Cloning mode *') bulk_sql = [] ip_offset = self.options.ip_offset with EMInterface(**self.emicparams) as emicifc: LOG.info('Disable auto-refresh on EM...') EMAPI.device.set_config(auto_refresh=False, ifc=emicifc) with SSHInterface(**self.emparams) as emsshifc: version = SCMD.ssh.get_version(ifc=emsshifc) has_groups = version < 'em 2.3.0' rows = SQL.query('SELECT MAX(device.uid) AS device, MAX(device_slot.uid) AS slot FROM device, device_slot;', ifc=emsshifc) max_device_uid = int(rows[0].device) max_slot_uid = int(rows[0].slot) bpmgmt = self.bigipparams.address template = self.do_get_template(bpmgmt, emsshifc) assert template.access_address != template.mgmt_address, \ "Template device must be discovered by its self IP." device_uid = int(template.uid) LOG.info('Template: %s', template.host_name) start_ip = IPAddress(START_IP) LOG.info('Inserting device rows...') for i in range(1, self.options.clones + 1, 1): template.uid = max_device_uid + UIDOFFSET + i template.access_address = str(start_ip + ip_offset + i) template.system_id = None template.last_refresh = None query = "INSERT INTO `device` %s" % self.do_prep_insert(template) bulk_sql.append(query) if has_groups: bulk_sql.append("INSERT INTO device_2_device_group VALUES (NULL,%d,1)" % template.uid) while bulk_sql: SQL.query(";".join(bulk_sql[:MAXSQL]), ifc=emsshifc) bulk_sql[:MAXSQL] = [] # Prepare device slot rows = SQL.query("SELECT * FROM device_slot WHERE device_id=%d;" % device_uid, ifc=emsshifc) last_device_slot_uid = max_slot_uid + UIDOFFSET LOG.info('Inserting device_slot rows...') for row in rows: last_device_uid = max_device_uid + UIDOFFSET for i in range(1, self.options.clones + 1, 1): last_device_slot_uid += 1 last_device_uid += 1 row.uid = last_device_slot_uid row.device_id = last_device_uid query = "INSERT INTO `device_slot` %s" % self.do_prep_insert(row) bulk_sql.append(query) while bulk_sql: SQL.query(";".join(bulk_sql[:MAXSQL]), ifc=emsshifc) bulk_sql[:MAXSQL] = [] LOG.info('Creating SelfIPs on %s...', bpmgmt) self_ips = [str(start_ip + ip_offset + x) for x in range(1, self.options.clones + 1, 1)] vlan_names = ['internal'] * self.options.clones netmasks = ['255.255.0.0'] * self.options.clones unit_ids = [0] * self.options.clones floating_states = ['STATE_DISABLED'] * self.options.clones with IcontrolInterface(**self.bigipparams) as bigipicifc: ic = bigipicifc.api ic.Networking.SelfIP.create(self_ips=self_ips, vlan_names=vlan_names, netmasks=netmasks, unit_ids=unit_ids, floating_states=floating_states) access_lists = [dict(self_ip=x, mode='ALLOW_MODE_ALL', protocol_ports=[]) for x in self_ips] ic.Networking.SelfIPPortLockdown.add_allow_access_list(access_lists=access_lists) def do_delete(self): LOG.info('* Delete mode *') with SSHInterface(**self.emparams) as emsshifc: bpmgmt = self.bigipparams.address devices = SQL.query("SELECT uid,access_address FROM device WHERE mgmt_address='%s';" % bpmgmt, ifc=emsshifc) clones = devices[1:] uids = [x.uid for x in clones] with EMInterface(**self.emicparams) as emicifc: emapi = emicifc.api LOG.info('Deleting devices...') try: emapi.device.delete_device(deviceIds=uids) #LOG.info('Enabling auto-refresh on EM...') #EMAPI.device.set_config(auto_refresh=True, ifc=emicifc) except ParsingError, e: LOG.warning(e) if clones: LOG.info('Deleting SelfIPs on %s...', bpmgmt) self_ips = [x.access_address for x in clones] with IcontrolInterface(**self.bigipparams) as bigipicifc: ic = bigipicifc.api try: ic.Networking.SelfIP.delete_self_ip(self_ips=self_ips) except IControlFault, e: LOG.warning(e)
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 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()
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 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 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