Exemple #1
0
    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
Exemple #2
0
    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')
Exemple #3
0
    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)
Exemple #4
0
    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)
Exemple #5
0
    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
Exemple #6
0
    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
Exemple #7
0
    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)
Exemple #8
0
    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
Exemple #9
0
    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...'
            )
Exemple #10
0
    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
Exemple #11
0
    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
Exemple #12
0
    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()
Exemple #13
0
    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
Exemple #14
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)
Exemple #15
0
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)
Exemple #16
0
    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
Exemple #17
0
    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()
Exemple #18
0
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()
Exemple #19
0
 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)
Exemple #20
0
    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