Пример #1
0
def vmaction():
    """
    start/stop/delete/create vm
    """
    config = Kconfig()
    k = config.k
    if 'name' in request.form:
        name = request.form['name']
        action = request.form['action']
        if action == 'start':
            result = k.start(name)
        elif action == 'stop':
            result = k.stop(name)
        elif action == 'delete':
            result = k.delete(name)
        elif action == 'create' and 'profile' in request.form:
            profile = request.form['profile']
            result = config.create_vm(name, profile)
        else:
            result = "Nothing to do"
        print(result)
        response = jsonify(result)
        print(response)
        response.status_code = 200
        return response
    else:
        failure = {'result': 'failure', 'reason': "Invalid Data"}
        response = jsonify(failure)
        response.status_code = 400
        return jsonify(failure)
Пример #2
0
def process_vm(name, namespace, spec, operation='create', timeout=60):
    config = Kconfig(quiet=True)
    exists = config.k.exists(name)
    if operation == "delete" and exists:
        print("Deleting vm %s" % name)
        return config.k.delete(name)
    if operation == "create":
        if not exists:
            profile = spec.get("profile")
            if profile is None:
                if 'image' in spec:
                    profile = spec['image']
                else:
                    profile = name
            print("Creating vm %s" % name)
            if profile is not None:
                result = config.create_vm(name, profile, overrides=spec)
                if result['result'] != 'success':
                    return result
        info = config.k.info(name)
        image = info.get('image')
        if image is not None and 'ip' not in info:
            raise kopf.TemporaryError("Waiting to populate ip", delay=10)
        newspec = {'spec': {'info': info}}
        return update_vm_cr(name, namespace, newspec)
Пример #3
0
def main():
    """

    """
    argument_spec = {
        "state": {
            "default": "present",
            "choices": ['present', 'absent'],
            "type": 'str'
        },
        "name": {"required": True, "type": "str"},
        "client": {"required": False, "type": "str"},
        "image": {"required": False, "type": "str"},
        "profile": {"required": False, "type": "str"},
        "parameters": {"required": False, "type": "dict"},
    }
    module = AnsibleModule(argument_spec=argument_spec)
    client = module.params['client']
    config = Kconfig(client=client, quiet=True)
    k = config.k
    name = module.params['name']
    exists = k.exists(name)
    state = module.params['state']
    if state == 'present':
        if exists:
            changed = False
            skipped = True
            meta = {'result': 'skipped'}
        else:
            image = module.params['image']
            profile = module.params['profile']
            if image is not None:
                profile = image
            elif profile is None:
                # module.fail_json(msg='profile or image needs to be specified', changed=False)
                profile = 'kvirt'
                config.profiles[profile] = {}
            overrides = module.params['parameters'] if module.params['parameters'] is not None else {}
            meta = config.create_vm(name, profile, overrides=overrides)
            changed = True
            skipped = False
    else:
        if exists:
            meta = k.delete(name)
            changed = True
            skipped = False
        else:
            changed = False
            skipped = True
            meta = {'result': 'skipped'}
    module.exit_json(changed=changed, skipped=skipped, meta=meta)
Пример #4
0
def vmaction():
    """
    start/stop/delete/create vm
    """
    config = Kconfig()
    k = config.k
    if 'name' in request.form:
        name = request.form['name']
        action = request.form['action']
        if action not in ['start', 'stop', 'delete', 'create']:
            result = {'result': 'failure', 'reason': "Invalid Action"}
            response = jsonify(result)
            response.status_code = 400
        else:
            if action == 'start':
                result = k.start(name)
            elif action == 'stop':
                result = k.stop(name)
            elif action == 'delete':
                result = k.delete(name)
            elif action == 'create' and 'profile' in request.form:
                profile = request.form['profile']
                parameters = {}
                for p in request.form:
                    if p.startswith('parameters'):
                        value = request.form[p]
                        key = p.replace('parameters[', '').replace(']', '')
                        parameters[key] = value
                parameters['nets'] = parameters['nets'].split(',')
                parameters['disks'] = [
                    int(disk) for disk in parameters['disks'].split(',')
                ]
                if name == '':
                    name = nameutils.get_random_name()
                result = config.create_vm(name, profile, overrides=parameters)
            response = jsonify(result)
            response.status_code = 200
    else:
        result = {'result': 'failure', 'reason': "Invalid Data"}
        response = jsonify(result)
        response.status_code = 400
    return jsonify(result)
Пример #5
0
 def create_vm(self, request, context):
     print("Handling create_vm call for:\n%s" % request)
     config = Kconfig()
     overrides = ast.literal_eval(
         request.overrides) if request.overrides != '' else {}
     profile = request.profile
     customprofile = ast.literal_eval(
         request.customprofile) if request.customprofile != '' else {}
     name = request.name
     if name == '':
         name = nameutils.get_random_name()
         if config.type in ['gcp', 'kubevirt']:
             name = name.replace('_', '-')
         if config.type != 'aws':
             common.pprint("Using %s as name of the vm" % name)
     if request.image != '':
         if request.image in config.profiles:
             common.pprint("Using %s as profile" % request.image)
         profile = request.image
     elif profile is not None:
         if profile.endswith('.yml'):
             profilefile = profile
             profile = None
             if not os.path.exists(profilefile):
                 common.pprint("Missing profile file %s" % profilefile,
                               color='red')
                 result = {
                     'result': 'failure',
                     'reason': "Missing profile file %s" % profilefile
                 }
                 response = kcli_pb2.result(**result)
                 return response
             else:
                 with open(profilefile, 'r') as entries:
                     entries = yaml.safe_load(entries)
                     entrieskeys = list(entries.keys())
                     if len(entrieskeys) == 1:
                         profile = entrieskeys[0]
                         customprofile = entries[profile]
                         common.pprint("Using data from %s as profile" %
                                       profilefile,
                                       color='blue')
                     else:
                         common.pprint("Cant' parse %s as profile file" %
                                       profilefile,
                                       color='red')
                         result = {
                             'result': 'failure',
                             'reason':
                             "Missing profile file %s" % profilefile
                         }
                         response = kcli_pb2.result(**result)
                         return response
     elif overrides:
         profile = 'kvirt'
         config.profiles[profile] = {}
     else:
         common.pprint(
             "You need to either provide a profile, an image or some parameters",
             color='red')
         result = {
             'result':
             'failure',
             'reason':
             "You need to either provide a profile, an image or some parameters"
         }
         response = kcli_pb2.result(**result)
         response = kcli_pb2.result(**result)
         return response
     if request.vmfiles:
         for _fil in request.vmfiles:
             origin = _fil.origin
             content = _fil.content
             with open(origin, 'w') as f:
                 f.write(content)
     if request.ignitionfile != '':
         with open("%s.ign" % name, 'w') as f:
             f.write(request.ignitionfile)
     result = config.create_vm(name,
                               profile,
                               overrides=overrides,
                               customprofile=customprofile)
     result['vm'] = name
     response = kcli_pb2.result(**result)
     return response
Пример #6
0
def create(args):
    paramfile = args.paramfile if not os.path.exists(
        '/i_am_a_container') else '/workdir/%s' % args.paramfile
    config = Kconfig()
    k = config.k
    client = config.client
    platform = config.type
    pprint("Deploying on client %s" % client, color='blue')
    envname = paramfile if paramfile is not None else 'testk'
    if not os.path.exists(paramfile):
        pprint("Specified parameter file %s doesn't exist.Leaving..." %
               real_path(paramfile),
               color='red')
        sys.exit(1)
    with open(paramfile) as entries:
        paramdata = yaml.safe_load(entries)
    data = {
        'cluster': envname,
        'helper_image': 'CentOS-7-x86_64-GenericCloud.qcow2',
        'domain': 'karmalabs.com',
        'network': 'default',
        'masters': 1,
        'workers': 0,
        'tag': 'cnvlab',
        'pub_key': '%s/.ssh/id_rsa.pub' % os.environ['HOME'],
        'pull_secret': 'openshift_pull.json',
        'version': 'nightly',
        'macosx': False,
        'baremetal': False,
        'network_type': 'OpenShiftSDN'
    }
    data.update(paramdata)
    version = data.get('version')
    if version not in ['ci', 'nightly', 'upstream']:
        pprint("Using stable version", color='blue')
    else:
        pprint("Using %s version" % version, color='blue')
    cluster = data.get('cluster')
    helper_image = data.get('helper_image')
    image = data.get('image')
    api_ip = data.get('api_ip')
    public_api_ip = data.get('public_api_ip')
    bootstrap_api_ip = data.get('bootstrap_api_ip')
    domain = data.get('domain')
    network = data.get('network')
    masters = data.get('masters')
    workers = data.get('workers')
    tag = data.get('tag')
    pub_key = data.get('pub_key')
    pull_secret = pwd_path(
        data.get('pull_secret')) if version != 'upstream' else pwd_path(
            'fake_pull.json')
    macosx = data.get('macosx')
    baremetal = data.get('baremetal')
    if macosx and not os.path.exists('/i_am_a_container'):
        macosx = False
    if platform == 'openstack' and (api_ip is None or public_api_ip is None):
        pprint(
            "You need to define both api_ip and public_api_ip in your parameters file",
            color='red')
        os._exit(1)
    if not os.path.exists(pull_secret):
        pprint("Missing pull secret file %s" % pull_secret, color='red')
        sys.exit(1)
    if not os.path.exists(pub_key):
        if os.path.exists('/%s/.kcli/id_rsa.pub' % os.environ['HOME']):
            pub_key = '%s/.kcli/id_rsa.pub' % os.environ['HOME']
        else:
            pprint("Missing public key file %s" % pub_key, color='red')
            sys.exit(1)
    clusterdir = pwd_path("clusters/%s" % cluster)
    if os.path.exists(clusterdir):
        pprint("Please Remove existing %s first..." % clusterdir, color='red')
        sys.exit(1)
    os.environ['KUBECONFIG'] = "%s/auth/kubeconfig" % clusterdir
    if find_executable('oc') is None:
        SYSTEM = 'macosx' if os.path.exists('/Users') else 'linux'
        pprint("Downloading oc in current directory", color='blue')
        occmd = "curl -s https://mirror.openshift.com/pub/openshift-v4/clients/oc/latest/%s/oc.tar.gz" % SYSTEM
        occmd += "| tar zxf - oc"
        occmd += "; chmod 700 oc"
        call(occmd, shell=True)
        if os.path.exists('/i_am_a_container'):
            if macosx:
                occmd = "curl -s https://mirror.openshift.com/pub/openshift-v4/clients/oc/latest/maxosx/oc.tar.gz"
                occmd += "| tar zxf -C /workdir - oc"
                occmd += "; chmod 700 /workdir/oc"
                call(occmd, shell=True)
            else:
                move('oc', '/workdir/oc')
    if find_executable('openshift-install') is None:
        if version == 'ci':
            get_ci_installer(pull_secret, tag=tag, baremetal=baremetal)
        elif version == 'nightly':
            get_installer(nightly=True)
        elif version == 'upstream':
            get_upstream_installer()
        else:
            get_installer()
        if not macosx and os.path.exists('/i_am_a_container'):
            move('openshift-install', '/workdir')
    INSTALLER_VERSION = os.popen(
        'openshift-install version').readlines()[0].split(" ")[1].strip()
    pprint("Using installer version %s" % INSTALLER_VERSION, color='blue')
    if version == 'upstream':
        COS_VERSION = "latest"
        COS_TYPE = "fcos"
    else:
        COS_TYPE = "rhcos"
        version_match = re.match("v([0-9]*).([0-9]*).*", INSTALLER_VERSION)
        if version_match is not None:
            COS_VERSION = "%s%s" % (version_match.group(1),
                                    version_match.group(2))
        else:
            COS_VERSION = "rhcos44"
    if image is None:
        images = [v for v in k.volumes() if COS_TYPE in v and COS_VERSION in v]
        if images:
            image = os.path.basename(images[0])
        else:
            pprint("Downloading %s image" % COS_TYPE, color='blue')
            result = config.handle_host(pool=config.pool,
                                        image="%s%s" % (COS_TYPE, COS_VERSION),
                                        download=True,
                                        update_profile=False)
            if result['result'] != 'success':
                os._exit(1)
            images = [
                v for v in k.volumes()
                if image.startswith("%s-%s" % (COS_TYPE, COS_VERSION))
            ]
            image = images[0]
        pprint("Using image %s" % image, color='blue')
    else:
        pprint("Checking if image %s is available" % image, color='blue')
        images = [v for v in k.volumes() if image in v]
        if not images:
            pprint(
                "Missing %s. Indicate correct image in your parameters file..."
                % image,
                color='red')
            os._exit(1)
    paramdata['image'] = image
    if not os.path.exists(clusterdir):
        os.makedirs(clusterdir)
    data['pub_key'] = open(pub_key).read().strip()
    data['pull_secret'] = re.sub(r"\s", "", open(pull_secret).read())
    installconfig = config.process_inputfile(cluster,
                                             "install-config.yaml",
                                             overrides=data)
    with open("%s/install-config.yaml" % clusterdir, 'w') as f:
        f.write(installconfig)
    call('openshift-install --dir=%s create manifests' % clusterdir,
         shell=True)
    for f in [f for f in glob("customisation/*.yaml")]:
        if '99-ingress-controller.yaml' in f:
            ingressrole = 'master' if workers == 0 else 'worker'
            replicas = masters if workers == 0 else workers
            installconfig = config.process_inputfile(cluster,
                                                     f,
                                                     overrides={
                                                         'replicas': replicas,
                                                         'role': ingressrole
                                                     })
            with open("%s/openshift/99-ingress-controller.yaml" % clusterdir,
                      'w') as f:
                f.write(installconfig)
        else:
            copy2(f, "%s/openshift" % clusterdir)
    if baremetal:
        metal3config = config.process_inputfile(cluster,
                                                "metal3-config.yaml",
                                                overrides=data)
        pprint("Rendering metal3 config map", color='blue')
        with open("%s/openshift/metal3-config.yaml" % clusterdir, 'w') as f:
            f.write(metal3config)
    call('openshift-install --dir=%s create ignition-configs' % clusterdir,
         shell=True)
    staticdata = gather_dhcp(data, platform)
    if staticdata:
        pprint("Deploying helper dhcp node" % image, color='green')
        staticdata.update({
            'network': network,
            'dhcp_image': helper_image,
            'prefix': cluster,
            domain: '%s.%s' % (cluster, domain)
        })
        config.plan(cluster, inputfile='dhcp.yml', overrides=staticdata)
    if platform in virtplatforms:
        if api_ip is None:
            pprint("You need to define api_ip in your parameters file",
                   color='red')
            os._exit(1)
        host_ip = api_ip if platform != "openstack" else public_api_ip
        pprint("Using %s for api vip...." % host_ip, color='blue')
        if not os.path.exists("/i_am_a_container"):
            hosts = open("/etc/hosts").readlines()
            wronglines = [
                e for e in hosts if not e.startswith('#') and "api.%s.%s" %
                (cluster, domain) in e and host_ip not in e
            ]
            for wrong in wronglines:
                pprint(
                    "Cleaning duplicate entries for api.%s.%s in /etc/hosts" %
                    (cluster, domain),
                    color='blue')
                call("sudo sed -i '/api.%s.%s/d' /etc/hosts" %
                     (cluster, domain),
                     shell=True)
            hosts = open("/etc/hosts").readlines()
            correct = [
                e for e in hosts if not e.startswith('#') and "api.%s.%s" %
                (cluster, domain) in e and host_ip in e
            ]
            if not correct:
                entries = [
                    "%s.%s.%s" % (x, cluster, domain) for x in [
                        'api', 'console-openshift-console.apps',
                        'oauth-openshift.apps',
                        'prometheus-k8s-openshift-monitoring.apps'
                    ]
                ]
                entries = ' '.join(entries)
                call("sudo sh -c 'echo %s %s >> /etc/hosts'" %
                     (host_ip, entries),
                     shell=True)
            if os.path.exists('/Users'):
                if not os.path.exists('/etc/resolver'):
                    os.mkdir('/etc/resolver')
                if not os.path.exists('/etc/resolver/%s.%s' %
                                      (cluster, domain)):
                    pprint("Adding wildcard for apps.%s.%s in /etc/resolver" %
                           (cluster, domain),
                           color='blue')
                    call(
                        "sudo sh -c 'echo nameserver %s > /etc/resolver/%s.%s'"
                        % (api_ip, cluster, domain),
                        shell=True)
                else:
                    resolverlines = open("/etc/resolver/%s.%s" %
                                         (cluster, domain)).readlines()
                    correct = [e for e in resolverlines if api_ip not in e]
                    if not correct:
                        pprint(
                            "Adding wildcard for apps.%s.%s in /etc/resolver" %
                            (cluster, domain),
                            color='blue')
                        call(
                            "sudo sh -c 'echo nameserver %s > /etc/resolver/%s.%s'"
                            % (api_ip, cluster, domain),
                            shell=True)
            elif not os.path.exists(
                    "/etc/NetworkManager/dnsmasq.d/%s.%s.conf" %
                (cluster, domain)):
                pprint("Adding wildcard for apps.%s.%s in /etc/resolver" %
                       (cluster, domain),
                       color='blue')
                nm = "sudo sh -c '"
                nm += "echo server=/apps.%s.%s/%s > /etc/NetworkManager/dnsmasq.d/%s.%s.conf'" % (
                    cluster, domain, api_ip, cluster, domain)
                nm += ";sudo systemctl reload NetworkManager"
                call(nm, shell=True)
            else:
                nmfile = open("/etc/NetworkManager/dnsmasq.d/%s.%s.conf" %
                              (cluster, domain)).readlines()
                correct = [e for e in nmfile if host_ip in e]
                if not correct:
                    pprint("Adding wildcard for apps.%s.%s in /etc/resolver" %
                           (cluster, domain),
                           color='blue')
                    nm = "sudo sh -c '"
                    nm += "echo server=/apps.%s.%s/%s > /etc/NetworkManager/dnsmasq.d/%s.%s.conf'" % (
                        cluster, domain, api_ip, cluster, domain)
                    nm += ";sudo systemctl reload NetworkManager"
                    call(nm, shell=True)
        else:
            entries = [
                "%s.%s.%s" % (x, cluster, domain) for x in [
                    'api', 'console-openshift-console.apps',
                    'oauth-openshift.apps',
                    'prometheus-k8s-openshift-monitoring.apps'
                ]
            ]
            entries = ' '.join(entries)
            call("sh -c 'echo %s %s >> /etc/hosts'" % (host_ip, entries),
                 shell=True)
            if os.path.exists('/etcdir/hosts'):
                call("sh -c 'echo %s %s >> /etcdir/hosts'" %
                     (host_ip, entries),
                     shell=True)
        if platform in ['kubevirt', 'openstack', 'vsphere']:
            # bootstrap ignition is too big for kubevirt/openstack/vsphere so we deploy a temporary web server
            overrides = {}
            if platform == 'kubevirt':
                overrides[
                    'helper_image'] = "kubevirt/fedora-cloud-container-disk-demo"
                iptype = "ip"
            else:
                if helper_image is None:
                    images = [
                        v for v in k.volumes()
                        if 'centos' in v.lower() or 'fedora' in v.lower()
                    ]
                    if images:
                        image = os.path.basename(images[0])
                    else:
                        helper_image = "CentOS-7-x86_64-GenericCloud.qcow2"
                        pprint("Downloading centos helper image", color='blue')
                        result = config.handle_host(pool=config.pool,
                                                    image="centos7",
                                                    download=True,
                                                    update_profile=False)
                    pprint("Using helper image %s" % helper_image,
                           color='blue')
                else:
                    images = [v for v in k.volumes() if helper_image in v]
                    if not images:
                        pprint(
                            "Missing image %s. Indicate correct helper image in your parameters file"
                            % helper_image,
                            color='red')
                        os._exit(1)
                iptype = 'ip'
                if platform == 'openstack':
                    overrides['flavor'] = "m1.medium"
                    iptype = "privateip"
            overrides['nets'] = [network]
            overrides['plan'] = cluster
            bootstrap_helper_name = "%s-bootstrap-helper" % cluster
            config.create_vm("%s-bootstrap-helper" % cluster,
                             helper_image,
                             overrides=overrides)
            while bootstrap_api_ip is None:
                bootstrap_api_ip = k.info(bootstrap_helper_name).get(iptype)
                pprint("Waiting 5s for bootstrap helper node to be running...",
                       color='blue')
                sleep(5)
            sleep(5)
            cmd = "iptables -F ; yum -y install httpd ; systemctl start httpd"
            sshcmd = k.ssh(bootstrap_helper_name,
                           user='******',
                           tunnel=config.tunnel,
                           insecure=True,
                           cmd=cmd)
            os.system(sshcmd)
            source, destination = "%s/bootstrap.ign" % clusterdir, "/var/www/html/bootstrap"
            scpcmd = k.scp(bootstrap_helper_name,
                           user='******',
                           source=source,
                           destination=destination,
                           tunnel=config.tunnel,
                           download=False,
                           insecure=True)
            os.system(scpcmd)
            sedcmd = 'sed "s@https://api-int.%s.%s:22623/config/master@http://%s/bootstrap@" ' % (
                cluster, domain, bootstrap_api_ip)
            sedcmd += '%s/master.ign' % clusterdir
            sedcmd += ' > %s/bootstrap.ign' % clusterdir
            call(sedcmd, shell=True)
        sedcmd = 'sed -i "s@https://api-int.%s.%s:22623/config@http://%s:8080@"' % (
            cluster, domain, api_ip)
        sedcmd += ' %s/master.ign %s/worker.ign' % (clusterdir, clusterdir)
        call(sedcmd, shell=True)
    if platform in cloudplatforms:
        bootstrap_helper_name = "%s-bootstrap-helper" % cluster
        overrides = {
            'reservedns': True,
            'domain': '%s.%s' % (cluster, domain),
            'tags': [tag],
            'plan': cluster,
            'nets': [network]
        }
        config.create_vm("%s-bootstrap-helper" % cluster,
                         helper_image,
                         overrides=overrides)
        status = ""
        while status != "running":
            status = k.info(bootstrap_helper_name).get('status')
            pprint("Waiting 5s for bootstrap helper node to be running...",
                   color='blue')
            sleep(5)
        sleep(5)
        cmd = "iptables -F ; yum -y install httpd ; systemctl start httpd"
        sshcmd = k.ssh(bootstrap_helper_name,
                       user='******',
                       tunnel=config.tunnel,
                       insecure=True,
                       cmd=cmd)
        os.system(sshcmd)
        source, destination = "%s/bootstrap.ign" % clusterdir, "/var/www/html/bootstrap"
        scpcmd = k.scp(bootstrap_helper_name,
                       user='******',
                       source=source,
                       destination=destination,
                       tunnel=config.tunnel,
                       download=False,
                       insecure=True)
        os.system(scpcmd)
        sedcmd = 'sed "s@https://api-int.%s.%s:22623/config/master@' % (
            cluster, domain)
        sedcmd += 'http://%s-bootstrap-helper.%s.%s/bootstrap@ "' % (cluster,
                                                                     domain)
        sedcmd += '%s/master.ign' % clusterdir
        sedcmd += ' > %s/bootstrap.ign' % clusterdir
        call(sedcmd, shell=True)
    if platform in virtplatforms:
        config.plan(cluster, inputfile='ocp.yml', overrides=paramdata)
        call('openshift-install --dir=%s wait-for bootstrap-complete || exit 1'
             % clusterdir,
             shell=True)
        todelete = ["%s-bootstrap" % cluster]
        if platform in ['kubevirt', 'openstack', 'vsphere']:
            todelete.append("%s-bootstrap-helper" % cluster)
        for vm in todelete:
            pprint("Deleting %s" % vm)
            k.delete(vm)
    else:
        config.plan(cluster, inputfile='ocp_cloud.yml', overrides=paramdata)
        call('openshift-install --dir=%s wait-for bootstrap-complete || exit 1'
             % clusterdir,
             shell=True)
        todelete = ["%s-bootstrap" % cluster, "%s-bootstrap-helper" % cluster]
        for vm in todelete:
            pprint("Deleting %s" % vm)
            k.delete(vm)
    if workers == 0:
        call(
            "oc adm taint nodes -l node-role.kubernetes.io/master node-role.kubernetes.io/master:NoSchedule-",
            shell=True)
    pprint("Deploying certs autoapprover cronjob", color='blue')
    call("oc create -f autoapprovercron.yml", shell=True)
    installcommand = 'openshift-install --dir=%s wait-for install-complete' % clusterdir
    installcommand = "%s | %s" % (installcommand, installcommand)
    pprint(
        "Launching install-complete step. Note it will be retried one extra time in case of timeouts",
        color='blue')
    call(installcommand, shell=True)
    if platform in virtplatforms:
        copy2("%s/worker.ign" % clusterdir, "%s/worker.ign.ori" % clusterdir)
        with open("%s/worker.ign" % clusterdir, 'w') as w:
            workerdata = insecure_fetch(
                "https://api.%s.%s:22623/config/worker" % (cluster, domain))
            w.write(str(workerdata))
    extrasdir = pwd_path("extras")
    if os.path.exists(extrasdir):
        pprint("Deploying extras", color='blue')
        os.chdir(extrasdir)
        for entry in sorted(os.listdir('.')):
            if os.path.isfile(entry) and entry.endswith('sh'):
                call("bash %s" % entry, shell=True)