def __init__(self, options, address=None, address_iq=None, *args, **kwargs): self.context = O() self.options = O(options) self.options.setifnone('timeout', DEFAULT_TIMEOUT) self.options.setifnone('skip_ping', False) if self.options.device: self.device = ConfigInterface().get_device(options.device) self.address = self.device.address else: self.device = None self.address = address self.options.setifnone('username', DEFAULT_ROOT_USERNAME) self.options.setifnone('password', DEFAULT_ROOT_PASSWORD) self.options.setifnone('admin_username', DEFAULT_ADMIN_USERNAME) self.options.setifnone('admin_password', DEFAULT_ADMIN_PASSWORD) if self.options.device_biq: self.device_biq = ConfigInterface().get_device(options.device_biq) self.address_biq = self.device_biq.address else: self.device_biq = None self.address_biq = address_iq self.options.setifnone('username_iq', DEFAULT_ROOT_USERNAME) self.options.setifnone('password_iq', DEFAULT_ROOT_PASSWORD) super(ScaleCheck, self).__init__(*args, **kwargs)
def __init__(self, options, address=None, *args, **kwargs): self.context = O() self.options = O(options) self.options.setifnone('node_count', DEFAULT_NODES) self.options.setifnone('pool_count', DEFAULT_POOLS) self.options.setifnone('pool_members', DEFAULT_MEMBERS) self.options.setifnone('vip_count', DEFAULT_VIPS) self.options.setifnone('node_start', DEFAULT_NODE_START) self.options.setifnone('partitions', DEFAULT_PARTITIONS) self.options.setifnone('timeout', DEFAULT_TIMEOUT) if self.options.device: self.device = ConfigInterface().get_device(options.device) self.address = self.device.address else: self.device = None self.address = address self.options.setifnone('username', DEFAULT_ROOT_USERNAME) self.options.setifnone('password', DEFAULT_ROOT_PASSWORD) # can.* shortcuts to check for certain features based on the version self.can = O() def can_tmsh(v): return (v.product.is_bigip and v >= 'bigip 11.0.0' or v.product.is_em and v >= 'em 2.0.0' or v.product.is_bigiq) self.can.tmsh = can_tmsh def can_provision(v): return (v.product.is_bigip and v >= 'bigip 10.0.1' or v.product.is_em and v >= 'em 2.0.0' or v.product.is_bigiq) self.can.provision = can_provision def can_lvm(sshifc): return not sshifc('/usr/lib/install/lvmtest').status self.can.lvm = can_lvm self.has = O() def has_asm(s): return bool(SCMD.tmsh.get_provision(ifc=s).asm) self.has.asm = has_asm def has_lvm(s): return not s('/usr/lib/install/lvmtest').status self.has.lvm = has_lvm super(ConfigPlacer, self).__init__(*args, **kwargs)
def ssl_signedcert_install(self, hostname): # BUG: Sometimes user 'a' role gets downgraded to 'guest' at this point. # It's still unclear why this happens. if self.context.version >= 'bigip 11.6' or self.context.version >= 'bigiq 4.6': SCMD.ssh.generic('tmsh modify auth user %s partition-access modify {all-partitions {role admin}}' % OUR_ADMIN_USERNAME, ifc=self.sshifc) else: SCMD.ssh.generic('tmsh modify auth user %s role admin' % OUR_ADMIN_USERNAME, ifc=self.sshifc) o = O() o.admin_username = OUR_ADMIN_USERNAME o.root_username = self.options.username o.ssh_port = self.options.ssh_port o.ssl_port = self.options.ssl_port o.verbose = self.options.verbose o.timeout = self.options.timeout LOG.info('Pushing the key/certificate pair') # The special a:a admin user is used here. It should be included in the # remote_config yaml config in the users.administrator section. o.admin_password = OUR_ADMIN_PASSWORD o.root_password = self.options.password if hostname: o.alias = [hostname] cs = WebCert(o, address=self.address) cs.run()
def irack_provider(self, address, username, apikey, mgmtip, timeout=120): """Get the static data for a device with a given mgmtip from iRack.""" data = O() with IrackInterface(address=address, timeout=timeout, username=username, password=apikey, proto='http') as irack: params = dict(address_set__address__in=mgmtip, address_set__type=4) # Locate the static bag for the F5Asset with mgmtip ret = irack.api.staticbag.filter(asset__type=1, **params) if ret.data.meta.total_count == 0: LOG.warning("No devices with mgmtip=%s found in iRack." % mgmtip) return data if ret.data.meta.total_count > 1: raise ValueError("More than one device with mgmtip=%s found in iRack." % mgmtip) bag = ret.data.objects[0] bagid = bag['id'] # Get the hostname ret = irack.api.staticsystem.filter(bag=bagid) assert ret.data.meta.total_count == 1, "No StaticSystem entries for bagid=%s" % bagid data.hostname = ret.data.objects[0].hostname # Get all reg_keys ret = irack.api.staticlicense.filter(bag=bagid) assert ret.data.meta.total_count >= 1, "No StaticLicense entries for bagid=%s" % bagid data.licenses = {} data.licenses.reg_key = [x.reg_key for x in ret.data.objects] # Get all VLAN -> self IPs pairs ret = irack.api.staticaddress.filter(bag=bagid, type=1) data.selfip = {} for o in ret.data.objects: vlan = o.vlan.split('/')[-1] # TODO: IPv6 support...someday? if IPAddress(o.address).version == 4 \ and not int(o.floating): data.selfip[vlan] = IPNetwork("{0.address}/{0.netmask}".format(o)) # Get all mgmt ips ret = irack.api.staticaddress.filter(bag=bagid, type=0) assert ret.data.meta.total_count >= 1, "No StaticAddress entries for bagid=%s" % bagid data.mgmtip = {} for o in ret.data.objects: if IPAddress(o.address).version == 4: data.mgmtip = IPNetwork("{0.address}/{0.netmask}".format(o)) # GW ret = irack.api.staticaddress.filter(bag=bagid, type=3) assert ret.data.meta.total_count >= 1, "No StaticAddress entries for bagid=%s" % bagid for o in ret.data.objects: if IPAddress(o.address).version == 4: data.gateway = IPAddress(o.address) LOG.debug(data) return data
def ssh_key_exchange(self): if self.options.get('no_sshkey'): return o = O() o.device = self.device o.username = self.options.username o.password = self.options.password o.port = self.options.ssh_port cs = KeySwap(o, address=self.address) cs.run()
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 bigiq_special_selfip_handling(self, tree, ctx): "Because the use of tmsh has become frown upon starting with 4.2" v = ctx.version if v.product.is_bigiq and v >= 'bigiq 4.2.0': # XXX: Because sometimes user 'a' set via tmsh is not picked up. self.call('bigstart restart restjavad') with EmapiInterface(username=OUR_ADMIN_USERNAME, password=OUR_ADMIN_PASSWORD, port=self.options.ssl_port, address=self.address) as rstifc: payload = O(selfIpAddresses=[]) for self_ip in enumerate_stamps(tree, SelfIP, include_common=False): # XXX: BIGIQ 4.2 API only supports untagged. for iface in self_ip.vlan.untagged: payload.selfIpAddresses.append(O(address=str(self_ip.address), vlan=self_ip.vlan.name, iface=iface)) LOG.debug('EasySetup payload: %s', payload) wait_args(rstifc.api.patch, func_args=(EasySetup.URI, payload), timeout=180, interval=5, timeout_message="Can't patch selfIPs ready after {0}s")
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 parse_vlan_options(kind): specs = O(tagged=[], untagged=[]) if kind == 'internal': tags = self.options.vlan_internal if not tags: specs.untagged.append(eth1) if kind == 'external': tags = self.options.vlan_external if not tags: specs.untagged.append(eth2) if tags: for tag in re.split('\s+', tags): key, value = tag.split('=') if key == 'tag': specs.tag = value else: specs[key].append(value) return specs
def csv_provider(self, mgmtip): """ Get the static data for a device with a given mgmtip from a CSV file. """ venv_path = os.environ['VIRTUAL_ENV'] csv_location = venv_path + self.options.csv data = O() with open(csv_location, 'rb') as csvfile: reader = csv.DictReader(csvfile) device_row = None for row in reader: # Clean up whitespaces row = {x.strip(): y.strip() for x, y in row.iteritems()} if IPAddress(mgmtip) == IPNetwork(row['mgmtip']).ip: device_row = row break if device_row: if 'hostname' in device_row and device_row['hostname']: data.hostname = device_row['hostname'] data.licenses = {} if 'reg_key' in device_row and device_row['reg_key']: data.licenses.reg_key = [device_row['reg_key']] data.selfip = {} if 'internal' in device_row and device_row['internal']: data.selfip.internal = IPNetwork(device_row['internal']) if 'external' in device_row and device_row['external']: data.selfip.external = IPNetwork(device_row['external']) if 'gateway' in device_row and device_row['gateway']: data.gateway = IPAddress(device_row['gateway']) data.mgmtip = IPNetwork(device_row['mgmtip']) else: LOG.warning("No devices with mgmtip=%s found in CSV." % mgmtip) LOG.debug(data) return data
''' Created on Apr 9, 2013 @author: jono ''' import logging from f5test.macros.tmosconf.placer import ConfigPlacer if __name__ == '__main__': from f5test.base import AttrDict as O from f5test.utils.version import Version from f5test.macros.tmosconf.base import (SystemConfig, NetworkConfig, LTMConfig, AFMConfig, APMConfig) logging.basicConfig(level=logging.INFO) context = O(version=Version('bigip 12.1.0'), provision=O(afm='nominal', ltm='nominal', apm='nominal')) o = O() o.partitions = 1 o.mgmtip = '10.1.2.3/24' o.gateway = '10.1.2.254' o.nameservers = ['172.27.1.1'] o.ntpservers = ['ntp'] o.provision = {} o.provision.ltm = 'nominal' o.users = {} o.users.g = 'guest' o.users.a = 'admin' o.users.o = 'operator' #o.users.ra = O(password='******', role='guest') o.smtpserver = 'mail.aaaa.bb'
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 setup(self): provider = O() if not self.options.no_irack and not self.options.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=self.address, timeout=self.options.timeout) elif self.options.csv: LOG.info("Using data from CSV: %s" % self.options.csv) provider = self.csv_provider(mgmtip=self.address) ctx = self.make_context() # System o = O() o.partitions = self.options.partitions o.nameservers = DNS_SERVERS if self.options.dns_servers is None else \ self.options.dns_servers o.suffixes = DNS_SUFFIXES if self.options.dns_suffixes is None else \ self.options.dns_suffixes o.ntpservers = NTP_SERVERS if self.options.ntp_servers is None else \ self.options.ntp_servers o.smtpserver = 'mail.f5net.com' o.hostname = self.options.hostname or provider.get('hostname') o.timezone = self.options.timezone self.set_networking(o) self.set_provisioning(o) self.set_users(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 mgmtip = o.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, **o).run() if self.options.clean: self.load_default_config() if not self.options.stdout: self.load(tree, ctx, func=lambda x: not isinstance(x, Partition)) if not self.options.stdout: # XXX: Add any given DNS before attempting to relicense. # Licensing may need to resolve the license server hostname. if self.can.tmsh(ctx.version): self.call('tmsh modify sys dns name-servers add { %s }' % ' '.join(o.nameservers)) self.license(ctx, self.options.license or provider and provider.licenses.reg_key[0]) if self.options.clean: self.reset_trust() return # Network o = O() o.tree = tree self.set_vlans(o) o.selfips = {} selfip_internal = self.options.selfip_internal or provider and provider.selfip.internal selfip_external = self.options.selfip_external or provider and provider.selfip.external if selfip_internal: o.selfips.internal = [O(address=selfip_internal)] # o.selfips.internal.append(O(address=ip4to6(selfip_internal), name='int_6')) o.selfips.internal.append(O(address=ip4to6(selfip_internal))) if selfip_external: o.selfips.external = [O(address=selfip_external)] # o.selfips.external.append(O(address=ip4to6(selfip_external), name='ext_6')) o.selfips.external.append(O(address=ip4to6(selfip_external))) tree = self.NetworkConfig(self.context, **o).run() # LTM o = O() o.tree = tree o.nodes = self.options.node_count o.pools = self.options.pool_count o.members = self.options.pool_members o.vips = self.options.vip_count o.node1 = self.options.node_start o.vip1 = self.calculate_vip_start(self.options.vip_start, mgmtip, selfip_external) o.with_monitors = not self.options.no_mon tree = self.LTMConfig(self.context, **o).run() if self.options.stdout: self.dump(tree, ctx) return self.load(tree, ctx) self.reset_trust() self.ready_wait() self.save(ctx) self.ssh_key_exchange() self.ssl_signedcert_install(o.hostname) self.bigiq_special_selfip_handling(tree, ctx)
def set_vlans(self, o): ctx = self.context lacp = self.options.trunks_lacp if ctx.platform.startswith('A'): o.trunks = {} eth1 = 'internal' # Trunk names eth2 = 'external' elif ctx.platform.startswith('Z'): # VEs can may have a variable number of TMM interfaces. # Adjusting accordingly. ret = SCMD.tmsh.list('net interface', ifc=self.sshifc) interfaces = sorted([x.split()[2] for x in ret.keys() if x.split()[2] != 'mgmt']) eth1, eth2 = (interfaces + [None, None])[:2] else: eth1 = '1.1' eth2 = '1.2' o.vlans = {} if ctx.is_vcmp: # No trunks. They will be automatically generated on VCMP guests. eth1 = eth2 = None ret = SCMD.tmsh.list('net vlan', ifc=self.sshifc) for key, obj in ret.items(): s = Mirror(key, obj) o.vlans[s.name] = s if ctx.platform == 'A100': o.trunks.internal = O(interfaces=['1/2.1', '2/2.1', '3/2.1', '4/2.1'], lacp=lacp) o.trunks.external = O(interfaces=['1/2.2', '2/2.2', '3/2.2', '4/2.2'], lacp=lacp) elif ctx.platform in ('A107', 'A109', 'A111'): o.trunks.internal = O(interfaces=['1/1.1', '2/1.1', '3/1.1', '4/1.1'], lacp=lacp) o.trunks.external = O(interfaces=['1/1.2', '2/1.2', '3/1.2', '4/1.2'], lacp=lacp) elif ctx.platform == 'A108': o.trunks.internal = O(interfaces=['1/1.1', '2/1.1', '3/1.1', '4/1.1', '5/1.1', '6/1.1', '7/1.1', '8/1.1'], lacp=lacp) o.trunks.external = O(interfaces=['1/1.2', '2/1.2', '3/1.2', '4/1.2', '5/1.2', '6/1.2', '7/1.2', '8/1.2'], lacp=lacp) def parse_vlan_options(kind): specs = O(tagged=[], untagged=[]) if kind == 'internal': tags = self.options.vlan_internal if not tags: specs.untagged.append(eth1) if kind == 'external': tags = self.options.vlan_external if not tags: specs.untagged.append(eth2) if tags: for tag in re.split('\s+', tags): key, value = tag.split('=') if key == 'tag': specs.tag = value else: specs[key].append(value) return specs if eth1: o.vlans.internal = O(**parse_vlan_options('internal')) if eth2: o.vlans.external = O(**parse_vlan_options('external'))