def prepare_create( self, daemon_spec: CephadmDaemonDeploySpec) -> CephadmDaemonDeploySpec: """ Create a new monitor on the given host. """ assert self.TYPE == daemon_spec.daemon_type name, _, network = daemon_spec.daemon_id, daemon_spec.host, daemon_spec.network # get mon. key ret, keyring, err = self.mgr.check_mon_command({ 'prefix': 'auth get', 'entity': self.get_auth_entity(name), }) extra_config = '[mon.%s]\n' % name if network: # infer whether this is a CIDR network, addrvec, or plain IP if '/' in network: extra_config += 'public network = %s\n' % network elif network.startswith('[v') and network.endswith(']'): extra_config += 'public addrv = %s\n' % network elif is_ipv6(network): extra_config += 'public addr = %s\n' % unwrap_ipv6(network) elif ':' not in network: extra_config += 'public addr = %s\n' % network else: raise OrchestratorError( 'Must specify a CIDR network, ceph addrvec, or plain IP: \'%s\'' % network) else: # try to get the public_network from the config ret, network, err = self.mgr.check_mon_command({ 'prefix': 'config get', 'who': 'mon', 'key': 'public_network', }) network = network.strip() if network else network if not network: raise OrchestratorError( 'Must set public_network config option or specify a CIDR network, ceph addrvec, or plain IP' ) if '/' not in network: raise OrchestratorError( 'public_network is set but does not look like a CIDR network: \'%s\'' % network) extra_config += 'public network = %s\n' % network daemon_spec.ceph_conf = extra_config daemon_spec.keyring = keyring daemon_spec.final_config, daemon_spec.deps = self.generate_config( daemon_spec) return daemon_spec
def parse(cls, host, require_network=True): # type: (str, bool) -> HostPlacementSpec """ Split host into host, network, and (optional) daemon name parts. The network part can be an IP, CIDR, or ceph addrvec like '[v2:1.2.3.4:3300,v1:1.2.3.4:6789]'. e.g., "myhost" "myhost=name" "myhost:1.2.3.4" "myhost:1.2.3.4=name" "myhost:1.2.3.0/24" "myhost:1.2.3.0/24=name" "myhost:[v2:1.2.3.4:3000]=name" "myhost:[v2:1.2.3.4:3000,v1:1.2.3.4:6789]=name" """ # Matches from start to : or = or until end of string host_re = r'^(.*?)(:|=|$)' # Matches from : to = or until end of string ip_re = r':(.*?)(=|$)' # Matches from = to end of string name_re = r'=(.*?)$' # assign defaults host_spec = cls('', '', '') match_host = re.search(host_re, host) if match_host: host_spec = host_spec._replace(hostname=match_host.group(1)) name_match = re.search(name_re, host) if name_match: host_spec = host_spec._replace(name=name_match.group(1)) ip_match = re.search(ip_re, host) if ip_match: host_spec = host_spec._replace(network=ip_match.group(1)) if not require_network: return host_spec networks = list() # type: List[str] network = host_spec.network # in case we have [v2:1.2.3.4:3000,v1:1.2.3.4:6478] if ',' in network: networks = [x for x in network.split(',')] else: if network != '': networks.append(network) for network in networks: # only if we have versioned network configs if network.startswith('v') or network.startswith('[v'): # if this is ipv6 we can't just simply split on ':' so do # a split once and rsplit once to leave us with just ipv6 addr network = network.split(':', 1)[1] network = network.rsplit(':', 1)[0] try: # if subnets are defined, also verify the validity if '/' in network: ip_network(network) else: ip_address(unwrap_ipv6(network)) except ValueError as e: # logging? raise e host_spec.validate() return host_spec
def unwrap_test(address, expected): assert unwrap_ipv6(address) == expected