I'm new to Openstack and I'm trying to create a tool so that I can launch any number of instances in an Openstack cloud. This was easily done using the nova-client module of openstacksdk.
Now the problem is that I want to make the instances execute a bash script as they are created by adding it as a userdata file, but it doesn't execute. This is confusing because I don't any error or warning message. Does anyone know what could it be?
Important parts of the code
The most important parts of the Python program are the function which gets the cloud info, the one that creates the instances and the main function, . I'll post them here as #Corey told.
"""
Function that allow us to log at cloud with all the credentials needed.
Username and password are not read from env.
"""
def get_nova_credentials_v2():
d = {}
user = ""
password = ""
print("Logging in...")
user = input("Username: ")
password = getpass.getpass(prompt="Password: ", stream=None)
while (user == "" or password == ""):
print("User or password field is empty")
user = input("Username: ")
password = getpass.getpass(prompt="Password: ", stream=None)
d['version'] = '2.65'
d['username'] = user
d['password'] = password
d['project_id'] = os.environ['OS_PROJECT_ID']
d['auth_url'] = os.environ['OS_AUTH_URL']
d['user_domain_name'] = os.environ['OS_USER_DOMAIN_NAME']
return d
Then we have the create_server function:
"""
This function creates a server using the info we got from JSON file
"""
def create_server(server):
s = {}
print("Creating "+server['compulsory']['name']+"...")
s['name'] = server['compulsory']['name']
s['image'] = server['compulsory']['os']
s['flavor'] = server['compulsory']['flavor']
s['min_count'] = server['compulsory']['copyNumber']
s['max_count'] = server['compulsory']['copyNumber']
s['userdata'] = server['file']
s['key_name'] = server['compulsory']['keyName']
s['availability_zone'] = server['compulsory']['availabilityZone']
s['nics'] = server['compulsory']['network']
print(s['userdata'])
if(exists("instalacion_k8s_docker.sh")):
print("Exists")
s['userdata'] = server['file']
nova.servers.create(**s)
And now the main function:
"""
Main process: First we create a connection to Openstack using our credentials.
Once connected we cal get_serverdata function to get all instance objects we want to be created.
We check that it is not empty and that we are not trying to create more instances than we are allowed.
Lastly we create the instances and the program finishes.
"""
credentials = get_nova_credentials_v2()
nova = client.Client(**credentials)
instances = get_serverdata()
current_instances = len(nova.servers.list())
if not instances:
print("No instance was writen. Check instances.json file.")
exit(3)
num = 0
for i in instances:
create_server(i)
exit(0)
For the rest of the code you can access to this public repo on github.
Thanks a lot!
Problem solved
The problem was the content of the server['file'] as #Corey said. It cannot be the Path to the file where you wrote the data but the content of it or a file type object. In the case of OpenstackSDK it must be base64 encoded but it is not the case in Novaclient.
Thanks a lot to #Corey for all the help! :)
I have this block of code that basically translates text from one language to another using the cloud translate API. The problem is that this code always throws the error: "Caller's project doesn't match parent project". What could be the problem?
translation_separator = "translated_text: "
language_separator = "detected_language_code: "
translate_client = translate.TranslationServiceClient()
# parent = translate_client.location_path(
# self.translate_project_id, self.translate_location
# )
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = (
os.getcwd()
+ "/translator_credentials.json"
)
# Text can also be a sequence of strings, in which case this method
# will return a sequence of results for each text.
try:
result = str(
translate_client.translate_text(
request={
"contents": [text],
"target_language_code": self.target_language_code,
"parent": f'projects/{self.translate_project_id}/'
f'locations/{self.translate_location}',
"model": self.translate_model
}
)
)
print(result)
except Exception as e:
print("error here>>>>>", e)
Your issue seems to be related to the authentication method that you are using on your application, please follow the guide for authention methods with the translate API. If you are trying to pass the credentials using code, you can explicitly point to your service account file in code with:
def explicit():
from google.cloud import storage
# Explicitly use service account credentials by specifying the private key
# file.
storage_client = storage.Client.from_service_account_json(
'service_account.json')
Also, there is a codelab for getting started with the translation API with Python, this is a great step by step getting started guide for running the translate API with Python.
If the issue persists, you can try creating a Public Issue Tracker for Google Support
I've written a basic code which is in Azure CLI wrapped in Python. This runs well on Linux machine and deploys a VM. We just have to provide the Resource Group Name. It fetches the VNET from that RG and then deploys the VM.
I wanted to fetch the credentials which is present in KeyVault and then pass it to the Azure VM password. But VM gets created successfully and I've to reset the password to make it work as I'm unable to login the VM.
Below is the code
import subprocess
import json
#one vnet and one subnet in the resourcegroup.
def get_vnet_name(rscgroup_name):
get_vnet_command=["az","network","vnet","list","--resource-group",rscgroup_name]
get_vnet=subprocess.run(get_vnet_command, stdout=subprocess.PIPE, stderr = subprocess.PIPE)
a=get_vnet.stdout.decode('utf-8')
d=json.loads(a)
for item in d:
vname=item["name"]
subnets=item["subnets"]
for i in subnets:
subnetname=i["name"]
return vname,subnetname
def fetch_secret(vault_name,secret_name):
fetch_secret_command=["az","keyvault","secret","show","--vault-name",vault_name,"--name",secret_name,"--query","value", "-o", "tsv"]
fetch_secret=subprocess.run(fetch_secret_command, stdout=subprocess.PIPE, stderr = subprocess.PIPE)
secretkubectl=fetch_secret.stdout
return secretkubectl
def fetch_secret_password(vault_name,secret_pass_name):
fetch_password_command=["az","keyvault","secret","show","--vault-name",vault_name,"--name",secret_pass_name,"--query","value", "-o", "tsv"]
fetch_password=subprocess.run(fetch_password_command, stdout=subprocess.PIPE, stderr = subprocess.PIPE)
print(fetch_password.stdout)
secretpass=fetch_password.stdout
print(secretpass)
return secretpass
def create_vm(vm_resourcegroup,vm_name, vm_image,vm_username, secretpass,vm_vnet,vm_subnet, vm_size, secretkubectl):
create_vm_command=["az","vm","create","--resource-group",vm_resourcegroup,"--name",vm_name,"--image",vm_image,"--admin-username", vm_username,"--admin-password",secretpass,"--vnet-name",vm_vnet,"--subnet",vm_subnet,"--size", vm_size, "--custom-data", secretkubectl]
create_vm=subprocess.run(create_vm_command, stdout=subprocess.PIPE, stderr = subprocess.PIPE)
return
if __name__=="__main__":
rscgroup_name="vm-test-group"
avm_name="testvm1245"
avm_image="Win2019Datacenter"
avm_username="azureuser"
avm_size="Standard_D2_V3"
vault_name = "keyvaultname"
secret_name = "storgacctn"
secret_pass_name = "password"
avm_vnet,avm_subnet=get_vnet_name(rscgroup_name)
secretkubectl =fetch_secret(vault_name,secret_name)
secretpass =fetch_secret_password(vault_name,secret_pass_name)
create_vm(rscgroup_name,avm_name,avm_image,avm_username,secretpass,avm_vnet,avm_subnet,avm_size,secretkubectl)
I can see the password fine, i removed the "-o", "tsv" flag and i see below snap with password in double quotes. Still i cannot login with the credentials present as secret in KeyVault.
I know it's very easy when i use JSON but i wanted to achieve it using python and cli
The issue in your code is that the output of the subprocess is a Bytecode, not a real string. You can see the output start with the b, it means the Bytecode. So you need to convert the output into a string and remove the line break. Change the function like below:
def fetch_secret_password(vault_name,secret_pass_name):
fetch_password_command=["az","keyvault","secret","show","--vault-name",vault_name,"--name",secret_pass_name,"--query","value", "-o", "tsv"]
fetch_password=subprocess.run(fetch_password_command, stdout=subprocess.PIPE, stderr = subprocess.PIPE)
print(fetch_password.stdout)
secretpass=fetch_password.stdout.decode('UTF-8').strip()
print(secretpass)
return secretpass
Then you get a string as you store in the secret for your VM password.
I would like to query Windows using a file extension as a parameter (e.g. ".jpg") and be returned the path of whatever app windows has configured as the default application for this file type.
Ideally the solution would look something like this:
from stackoverflow import get_default_windows_app
default_app = get_default_windows_app(".jpg")
print(default_app)
"c:\path\to\default\application\application.exe"
I have been investigating the winreg builtin library which holds the registry infomation for windows but I'm having trouble understanding its structure and the documentation is quite complex.
I'm running Windows 10 and Python 3.6.
Does anyone have any ideas to help?
The registry isn't a simple well-structured database. The Windows
shell executor has some pretty complex logic to it. But for the simple cases, this should do the trick:
import shlex
import winreg
def get_default_windows_app(suffix):
class_root = winreg.QueryValue(winreg.HKEY_CLASSES_ROOT, suffix)
with winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, r'{}\shell\open\command'.format(class_root)) as key:
command = winreg.QueryValueEx(key, '')[0]
return shlex.split(command)[0]
>>> get_default_windows_app('.pptx')
'C:\\Program Files\\Microsoft Office 15\\Root\\Office15\\POWERPNT.EXE'
Though some error handling should definitely be added too.
Added some improvements to the nice code by Hetzroni, in order to handle more cases:
import os
import shlex
import winreg
def get_default_windows_app(ext):
try: # UserChoice\ProgId lookup initial
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\{}\UserChoice'.format(ext)) as key:
progid = winreg.QueryValueEx(key, 'ProgId')[0]
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'SOFTWARE\Classes\{}\shell\open\command'.format(progid)) as key:
path = winreg.QueryValueEx(key, '')[0]
except: # UserChoice\ProgId not found
try:
class_root = winreg.QueryValue(winreg.HKEY_CLASSES_ROOT, ext)
if not class_root: # No reference from ext
class_root = ext # Try direct lookup from ext
with winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, r'{}\shell\open\command'.format(class_root)) as key:
path = winreg.QueryValueEx(key, '')[0]
except: # Ext not found
path = None
# Path clean up, if any
if path: # Path found
path = os.path.expandvars(path) # Expand env vars, e.g. %SystemRoot% for ext .txt
path = shlex.split(path, posix=False)[0] # posix False for Windows operation
path = path.strip('"') # Strip quotes
# Return
return path
I'm trying to write a Python script to talk to my instance of Jenkins. I am using the newest version of the jenkinsapi module and querying Jenkins 1.509.3.
I can get a job list like follows:
l=j.get_jobs_list()
where j is an instance of jenkinsapi.Jenkins (I used the requester from jenkinsapi.utils.requester to skip ssl verification)
However, when I try to get more information on an individual job with
j.get_job(l[0])
it fails with this error: Inappropriate content found at [some_address] and what is returned is a bunch of HTML (that looks like the starting page for my instance, the one you see when you log in) instead of anything that should look like the response. Pasting [some_address] into the browser gives me what I expect as a response.
While I can get some information on the Jenkins instance, what I am really interested in is info on individual jobs. Any ideas how to fix it and get the job info?
Using python 3.6, python-jenkins 1.0.1 and Jenkins 2.121.1, following works nicely:
import pprint
import jenkins
IP = 'localhost'
USERNAME = 'my_username'
PW = 'my_password'
def get_version(server):
user = server.get_whoami()
version = server.get_version()
print('Hello %s from Jenkins %s' % (user['fullName'], version))
def get_jobs(server):
jobs = server.get_jobs() # List[dict]
print("Here are top 5 jobs")
pprint(jobs[:5])
return jobs
def get_job(server, job_name):
job_config = server.get_job_config(job_name) # XML
job_info = server.get_job_info(job_name) # dict
print("\n --- JOB CONFIG --- ")
print(job_config)
print("\n --- JOB INFO --- ")
pprint(job_info)
if __name__ == "__main__":
_server = jenkins.Jenkins(IP, username=USERNAME, password=PW)
get_version(_server)
_jobs = get_jobs(_server)
get_job(_server, _jobs[0]['name'])
Jenkins API I was using is documented here: https://python-jenkins.readthedocs.io/en/latest/index.html