Example #1
0
    def remove_eula_from_device(self):
        params = dict(command='run', utilCmdArgs='/LICENSE.F5')
        uri = "https://{0}:{1}/mgmt/tm/util/bash".format(
            self.client.provider['server'],
            self.client.provider['server_port'])
        resp = self.client.api.post(uri, json=params)

        try:
            response = resp.json()
        except ValueError as ex:
            raise F5ModuleError(str(ex))

        if 'code' in response and response['code'] in [400, 403]:
            if 'message' in response:
                raise F5ModuleError(response['message'])
            else:
                raise F5ModuleError(resp.content)

        if 'commandResult' in response:
            if 'No such file or directory' in response['commandResult']:
                return True
            else:
                raise F5ModuleError(response['commandResult'])
        return True
    def _get_cert_references(self):
        result = dict()
        uri = "https://{0}:{1}/mgmt/cm/adc-core/working-config/sys/file/ssl-cert/".format(
            self.client.provider['server'],
            self.client.provider['server_port'])

        resp = self.client.api.get(uri)
        try:
            response = resp.json()
        except ValueError as ex:
            raise F5ModuleError(str(ex))
        for cert in response['items']:
            key = fq_name(cert['partition'], cert['name'])
            result[key] = cert['selfLink']
        return result
    def destination(self):
        if self.want.ip is None and self.want.port is None:
            return None
        if self.want.port is None:
            self.want.update({'port': self.have.port})
        if self.want.ip is None:
            self.want.update({'ip': self.have.ip})

        if self.want.port in [None, '*'] and self.want.ip != '*':
            raise F5ModuleError(
                "Specifying an IP address requires that a port number be specified"
            )

        if self.want.destination != self.have.destination:
            return self.want.destination
    def exists(self):
        uri = "https://{0}:{1}/mgmt/tm/vcmp/guest/{2}".format(
            self.client.provider['server'],
            self.client.provider['server_port'],
            self.want.name
        )
        resp = self.client.api.get(uri)
        try:
            response = resp.json()
        except ValueError as ex:
            raise F5ModuleError(str(ex))

        if resp.status == 404 or 'code' in response and response['code'] == 404:
            return False
        if resp.status in [200, 201] or 'code' in response and response['code'] in [200, 201]:
            return True

        errors = [401, 403, 409, 500, 501, 502, 503, 504]

        if resp.status in errors or 'code' in response and response['code'] in errors:
            if 'message' in response:
                raise F5ModuleError(response['message'])
            else:
                raise F5ModuleError(resp.content)
Example #5
0
    def monitors(self):
        if self._values['monitors'] is None:
            return None
        if len(self._values['monitors']) == 1 and self._values['monitors'][0] == '':
            return 'default'
        monitors = [fq_name(self.partition, x) for x in self.monitors_list]
        if self.availability_requirement_type == 'at_least':
            if self.at_least > len(self.monitors_list):
                raise F5ModuleError(
                    "The 'at_least' value must not exceed the number of 'monitors'."
                )
            monitors = ' '.join(monitors)
            result = 'min {0} of {{ {1} }}'.format(self.at_least, monitors)
        elif self.availability_requirement_type == 'require':
            monitors = ' '.join(monitors)
            if self.number_of_probes > self.number_of_probers:
                raise F5ModuleError(
                    "The 'number_of_probes' must not exceed the 'number_of_probers'."
                )
            result = 'require {0} from {1} {{ {2} }}'.format(self.number_of_probes, self.number_of_probers, monitors)
        else:
            result = ' and '.join(monitors).strip()

        return result
 def mgmt_tuple(self):
     Destination = namedtuple('Destination', ['ip', 'subnet'])
     try:
         parts = self._values['mgmt_address'].split('/')
         if len(parts) == 2:
             result = Destination(ip=parts[0], subnet=parts[1])
         elif len(parts) < 2:
             result = Destination(ip=parts[0], subnet=None)
         else:
             raise F5ModuleError(
                 "The provided mgmt_address is malformed."
             )
     except ValueError:
         result = Destination(ip=None, subnet=None)
     return result
Example #7
0
    def create_on_device(self):
        params = self.want.api_params()
        payload = dict(name=self.want.name,
                       partition=self.want.partition,
                       **params)
        uri = "https://{0}:{1}/mgmt/tm/ltm/policy/".format(
            self.client.provider['server'],
            self.client.provider['server_port'],
        )
        resp = self.client.api.post(uri, json=payload)
        try:
            response = resp.json()
        except ValueError as ex:
            raise F5ModuleError(str(ex))

        if 'code' in response and response['code'] in [400, 403]:
            if 'message' in response:
                raise F5ModuleError(response['message'])
            else:
                raise F5ModuleError(resp.content)

        self._upsert_policy_rules_on_device()

        return True
Example #8
0
    def device_reference(self):
        if not self.managed:
            return None
        if self.device_is_address:
            # This range lookup is how you do lookups for single IP addresses. Weird.
            filter = "address+eq+'{0}...{0}'".format(self.device)
        elif self.device_is_name:
            filter = "hostname+eq+'{0}'".format(self.device)
        elif self.device_is_id:
            filter = "uuid+eq+'{0}'".format(self.device)
        else:
            raise F5ModuleError("Unknown device format '{0}'".format(
                self.device))

        uri = "https://{0}:{1}/mgmt/shared/resolver/device-groups/cm-bigip-allBigIpDevices/devices/" \
              "?$filter={2}&$top=1".format(self.client.provider['server'],
                                           self.client.provider['server_port'], filter)
        resp = self.client.api.get(uri)
        try:
            response = resp.json()
        except ValueError as ex:
            raise F5ModuleError(str(ex))
        if resp.status == 200 and response['totalItems'] == 0:
            raise F5ModuleError(
                "No device with the specified address was found.")
        elif 'code' in response and response['code'] == 400:
            if 'message' in response:
                raise F5ModuleError(response['message'])
            else:
                raise F5ModuleError(resp._content)
        id = response['items'][0]['uuid']
        result = dict(
            link=
            'https://localhost/mgmt/shared/resolver/device-groups/cm-bigip-allBigIpDevices/devices/{0}'
            .format(id))
        return result
 def addresses(self):
     if self._values['addresses'] is None:
         return None
     result = []
     for x in self._values['addresses']:
         if is_valid_ip(x):
             result.append(str(ip_address(u'{0}'.format(x))))
         elif is_valid_ip_interface(x):
             result.append(str(ip_interface(u'{0}'.format(x))))
         else:
             raise F5ModuleError(
                 "Address {0} must be either an IPv4 or IPv6 address or network."
                 .format(x))
     result = sorted(result)
     return result
    def inline_import(self):
        params = self.changes.api_params()
        uri = "https://{0}:{1}/mgmt/tm/asm/tasks/import-policy/".format(
            self.client.provider['server'],
            self.client.provider['server_port'],
        )

        if self.want.force:
            params.update(dict(policyReference={'link': self._get_policy_link()}))
            params.pop('name')

        resp = self.client.api.post(uri, json=params)

        try:
            response = resp.json()
        except ValueError as ex:
            raise F5ModuleError(str(ex))

        if 'code' in response and response['code'] in [400, 403]:
            if 'message' in response:
                raise F5ModuleError(response['message'])
            else:
                raise F5ModuleError(resp.content)
        return response['id']
Example #11
0
 def _policy_exists(self):
     uri = 'https://{0}:{1}/mgmt/tm/asm/policies/'.format(
         self.client.provider['server'],
         self.client.provider['server_port'],
     )
     query = "?$filter=contains(name,'{0}')+and+contains(partition,'{1}')&$select=name,partition".format(
         self.want.name, self.want.partition)
     resp = self.client.api.get(uri + query)
     try:
         response = resp.json()
     except ValueError as ex:
         raise F5ModuleError(str(ex))
     if 'items' in response and response['items'] != []:
         return True
     return False
 def pools(self):
     result = []
     if self._values['pools'] is None:
         return None
     for item in self._values['pools']:
         pool = dict()
         if 'name' not in item:
             raise F5ModuleError(
                 "'name' is a required key for items in the list of pools."
             )
         if 'ratio' in item:
             pool['ratio'] = item['ratio']
         pool['name'] = fq_name(self.partition, item['name'])
         result.append(pool)
     return result
Example #13
0
    def _handle_forward_action(self, action, item):
        """Handle the nuances of the forwarding type

        Right now there is only a single type of forwarding that can be done. As that
        functionality expands, so-to will the behavior of this, and other, methods.
        Therefore, do not be surprised that the logic here is so rigid. It's deliberate.

        :param action:
        :param item:
        :return:
        """
        action['type'] = 'forward'
        if 'pool' not in item:
            raise F5ModuleError(
                "A 'pool' must be specified when the 'forward' type is used.")
        action['pool'] = self._fqdn_name(item['pool'])
    def _discovery_constraints(self):
        if self.want.virtual_server_discovery is None:
            virtual_server_discovery = self.have.virtual_server_discovery
        else:
            virtual_server_discovery = self.want.virtual_server_discovery

        if self.want.link_discovery is None:
            link_discovery = self.have.link_discovery
        else:
            link_discovery = self.want.link_discovery

        if link_discovery in ['enabled', 'enabled-no-delete'
                              ] and virtual_server_discovery == 'disabled':
            raise F5ModuleError(
                "Virtual server discovery must be enabled if link discovery is enabled"
            )
Example #15
0
    def _handle_redirect_action(self, action, item):
        """Handle the nuances of the redirect type

        :param action:
        :param item:
        :return:
        """
        action['type'] = 'redirect'
        if 'location' not in item:
            raise F5ModuleError(
                "A 'location' must be specified when the 'redirect' type is used."
            )
        action.update(
            location=item['location'],
            httpReply=True,
        )
 def route_domain(self):
     if self._values['route_domain'] is None:
         return None
     try:
         return int(self._values['route_domain'])
     except ValueError:
         try:
             rd = self.client.api.tm.net.route_domains.route_domain.load(
                 name=self._values['route_domain'],
                 partition=self.partition
             )
             return int(rd.id)
         except iControlUnexpectedHTTPError:
             raise F5ModuleError(
                 "The specified 'route_domain' was not found."
             )
Example #17
0
 def log_publisher(self):
     if self.want.log_publisher is None:
         return None
     if self.want.log_publisher == '' and self.have.log_publisher in [
             None, 'none'
     ]:
         return None
     if self.want.log_publisher == '':
         if self.want.log_profile is None and self.have.log_profile not in [
                 None, 'none'
         ]:
             raise F5ModuleError(
                 "The log_publisher cannot be removed if log_profile is defined on device."
             )
     if self.want.log_publisher != self.have.log_publisher:
         return self.want.log_publisher
Example #18
0
    def __enter__(self):
        uri = "https://{0}:{1}/mgmt/tm/transaction/".format(
            self.client.provider['server'],
            self.client.provider['server_port'])
        resp = self.client.api.post(uri, json={})
        if resp.status not in [200]:
            raise Exception
        try:
            response = resp.json()
        except ValueError as ex:
            raise F5ModuleError(str(ex))

        self.transid = response['transId']
        self.client.api.request.headers[
            'X-F5-REST-Coordination-Id'] = self.transid
        return self.client
Example #19
0
    def exists(self):
        uri = "https://{0}:{1}/mgmt/tm/asm/policies/".format(
            self.client.provider['server'],
            self.client.provider['server_port'],
        )
        resp = self.client.api.get(uri)

        try:
            response = resp.json()
        except ValueError as ex:
            raise F5ModuleError(str(ex))
        if any(p['name'] == self.want.name
               and p['partition'] == self.want.partition
               for p in response['items']):
            return True
        return False
Example #20
0
    def create_on_device(self):
        remote_path = "/var/local/ucs"
        tpath_name = '/var/config/rest/downloads'

        upload = self.client.api.shared.file_transfer.uploads

        try:
            upload.upload_file(self.want.ucs)
        except IOError as ex:
            raise F5ModuleError(str(ex))

        self.client.api.tm.util.unix_mv.exec_cmd(
            'run',
            utilCmdArgs='{0}/{2} {1}/{2}'.format(tpath_name, remote_path,
                                                 self.want.basename))
        return True
Example #21
0
    def create_on_device(self):
        remote_path = "/var/config/rest/downloads/{0}".format(self.want.name)
        load_command = 'tmsh load sys application template {0}'.format(
            remote_path)

        template = StringIO(self.want.content)

        upload = self.client.api.shared.file_transfer.uploads
        upload.upload_stringio(template, self.want.name)
        output = self.client.api.tm.util.bash.exec_cmd(
            'run', utilCmdArgs='-c "{0}"'.format(load_command))

        if hasattr(output, 'commandResult'):
            result = output.commandResult
            if 'Syntax Error' in result:
                raise F5ModuleError(output.commandResult)
Example #22
0
    def _handle_enable_action(self, action, item):
        """Handle the nuances of the enable type

        :param action:
        :param item:
        :return:
        """
        action['type'] = 'enable'
        if 'asm_policy' not in item:
            raise F5ModuleError(
                "An 'asm_policy' must be specified when the 'enable' type is used."
            )
        action.update(dict(
            policy=fq_name(self.partition, item['asm_policy']),
            asm=True
        ))
Example #23
0
    def remove(self):
        if self.module.check_mode:
            return True
        self.remove_from_device()
        self._wait_for_module_provisioning()

        # For vCMP, because it has to reboot, we also wait for mcpd to become available
        # before "moving on", or else the REST API would not be available and subsequent
        # Tasks would fail.
        if self.want.module == 'vcmp':
            self._wait_for_reboot()
            self._wait_for_module_provisioning()

        if self.exists():
            raise F5ModuleError("Failed to de-provision the module")
        return True
 def ssl_protocols(self):
     if self._values['ssl_protocols'] is None:
         return None
     if isinstance(self._values['ssl_protocols'], string_types):
         protocols = self._values['ssl_protocols'].strip()
     else:
         protocols = self._values['ssl_protocols']
     if not protocols:
         raise F5ModuleError("ssl_protocols may not be set to 'none'")
     if protocols == 'default':
         protocols = ' '.join(Parameters._protocols.split(' '))
     elif isinstance(protocols, string_types):
         protocols = ' '.join(protocols.split(' '))
     else:
         protocols = ' '.join(protocols)
     return protocols
 def ssl_cipher_suite(self):
     if self._values['ssl_cipher_suite'] is None:
         return None
     if isinstance(self._values['ssl_cipher_suite'], string_types):
         ciphers = self._values['ssl_cipher_suite'].strip()
     else:
         ciphers = self._values['ssl_cipher_suite']
     if not ciphers:
         raise F5ModuleError("ssl_cipher_suite may not be set to 'none'")
     if ciphers == 'default':
         ciphers = ':'.join(Parameters._ciphers.split(':'))
     elif isinstance(self._values['ssl_cipher_suite'], string_types):
         ciphers = ':'.join(ciphers.split(':'))
     else:
         ciphers = ':'.join(ciphers)
     return ciphers
Example #26
0
    def exec_module(self):
        if not self.gtm_provisioned():
            raise F5ModuleError("GTM must be provisioned to use this module.")

        if 'all' in self.want.include:
            names = ['pool', 'wide_ip', 'server']
        else:
            names = self.want.include
        managers = [self.get_manager(name) for name in names]
        result = self.execute_managers(managers)
        if result:
            result['changed'] = True
        else:
            result['changed'] = False
        self._announce_deprecations()
        return result
    def exec_module(self):
        if not module_provisioned(self.client, 'asm'):
            raise F5ModuleError(
                "ASM must be provisioned to use this module."
            )

        result = dict()

        changed = self.policy_import()

        reportable = ReportableChanges(params=self.changes.to_return())
        changes = reportable.to_return()
        result.update(**changes)
        result.update(dict(changed=changed))
        self._announce_deprecations(result)
        return result
Example #28
0
    def remove_virtual_disk_from_device(self):
        check = '{0}'.format(self.have.virtual_disk)
        response = self.get_virtual_disks_on_device()
        for resource in response['items']:
            if resource['name'].startswith(check):
                uri = "https://{0}:{1}/mgmt/tm/vcmp/virtual-disk/{2}".format(
                    self.client.provider['server'],
                    self.client.provider['server_port'],
                    resource['name'].replace('/', '~'))
                response = self.client.api.delete(uri)

                if response.status == 200:
                    continue
                else:
                    raise F5ModuleError(response.content)

        return True
Example #29
0
 def destination(self):
     if self._values['destination'] is None:
         return None
     if self._values['destination'].startswith('default'):
         self._values['destination'] = '0.0.0.0/0'
     if self._values['destination'].startswith('default-inet6'):
         self._values['destination'] = '::/0'
     try:
         ip = ip_network(u'%s' % str(self.destination_ip))
         if self.route_domain:
             return '{0}%{1}/{2}'.format(str(ip.network_address),
                                         self.route_domain, ip.prefixlen)
         else:
             return '{0}/{1}'.format(str(ip.network_address), ip.prefixlen)
     except ValueError:
         raise F5ModuleError(
             "The provided destination is not an IP address")
Example #30
0
    def create(self):
        self._set_changed_options()
        if self.changes.version is None:
            raise F5ModuleError(
                "The 'version' parameter is required when creating a new IKE peer."
            )
        if self.changes.phase1_auth_method is None:
            self.changes.update({'phase1_auth_method': 'rsa-signature'})
            if self.changes.phase1_cert is None:
                self.changes.update({'phase1_cert': 'default.crt'})
            if self.changes.phase1_key is None:
                self.changes.update({'phase1_key': 'default.key'})

        if self.module.check_mode:
            return True
        self.create_on_device()
        return True